diff --git a/make/devkit/Sysroot.gmk b/make/devkit/Sysroot.gmk index 13395172074..a0576ed571b 100644 --- a/make/devkit/Sysroot.gmk +++ b/make/devkit/Sysroot.gmk @@ -88,8 +88,7 @@ SRCDIR := $(OUTPUT_ROOT)/src DOWNLOAD_RPMS_MARKER := $(BUILDDIR)/download-rpms.marker RPMS_UNPACKED_MARKER := $(BUILDDIR)/rpms_unpacked.marker -UNPATCHED_SYSROOT_MARKER := $(BUILDDIR)/sysroot_unpatched.marker -PATCHED_SYSROOT_MARKER := $(BUILDDIR)/sysroot_patched.marker +SYSROOT_MARKER := $(BUILDDIR)/sysroot.marker ################################################################################ # Download RPMs @@ -101,10 +100,6 @@ else endif RPM_ARCHS := $(RPM_ARCH) noarch -ifeq ($(ARCH), x86_64) - # Enable mixed mode. - RPM_ARCHS += i386 i686 -endif EMPTY := SPACE := $(EMPTY) $(EMPTY) @@ -166,43 +161,12 @@ $(RPMS_UNPACKED_MARKER): $(DOWNLOAD_RPMS_MARKER) ################################################################################ -$(UNPATCHED_SYSROOT_MARKER): $(RPMS_UNPACKED_MARKER) +$(SYSROOT_MARKER): $(RPMS_UNPACKED_MARKER) touch $@ -################################################################################ -# Patch sysroot - -# Note: MUST create a /usr/lib even if not really needed. -# gcc will use a path relative to it to resolve lib64. (x86_64). -# we're creating multi-lib compiler with 32bit libc as well, so we should -# have it anyway, but just to make sure... -# Patch GNU ld scripts to force linking against libraries in the sysroot -# and not the ones installed on the build machine. - -LD_SCRIPT_PATCHES := \ - -e 's|/usr/lib64/||g' \ - -e 's|/usr/lib/||g' \ - -e 's|/lib64/||g' \ - -e 's|/lib/||g' \ - # - -$(PATCHED_SYSROOT_MARKER): $(UNPATCHED_SYSROOT_MARKER) - @echo Patching GNU ld scripts - @( \ - for f in $$(find $(SYSROOT) -name "*.so" -type f 2>/dev/null); do \ - if grep -Iq 'GNU ld script' "$$f"; then \ - sed $(LD_SCRIPT_PATCHES) "$$f" > "$$f.tmp" && \ - mv "$$f.tmp" "$$f"; \ - fi; \ - done \ - ) - @mkdir -p $(SYSROOT)/usr/lib - @touch $@ - ################################################################################ download-rpms: $(DOWNLOAD_RPMS_MARKER) -unpatched-sysroot: $(UNPATCHED_SYSROOT_MARKER) -sysroot: $(PATCHED_SYSROOT_MARKER) +sysroot: $(SYSROOT_MARKER) -.PHONY: download-rpms unpatched-sysroot sysroot +.PHONY: download-rpms sysroot diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 835ada3a082..7d973313cea 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -103,16 +103,6 @@ ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),) endif ################################################################################ -# Define common directories and files - -# Ensure we have 32-bit libs also for x64. We enable mixed-mode. -ifeq (x86_64,$(ARCH)) - LIBDIRS := lib64 lib - CFLAGS_lib := -m32 -else - LIBDIRS := lib -endif - # Define directories DOWNLOAD := $(OUTPUT_ROOT)/download SRCDIR := $(OUTPUT_ROOT)/src @@ -200,23 +190,19 @@ TOOLS ?= $(call declare_tools,_FOR_TARGET,$(TARGET)-) ################################################################################ -# Create a TARGET bfd + libiberty only. -# Configure one or two times depending on mulitlib arch. -# If multilib, the second should be 32-bit, and we resolve -# CFLAG_ to most likely -m32. -define mk_bfd - $$(info Libs for $(1)) - $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile: \ - CFLAGS += $$(CFLAGS_$(1)) - $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile: \ - LIBDIRS = --libdir=$(TARGETDIR)/$(1) +ifeq (x86_64,$(ARCH)) + LIBDIR := lib64 +else + LIBDIR := lib +endif - BFDLIB += $$(TARGETDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1)).done - BFDMAKES += $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile -endef +$(BUILDDIR)/$(BINUTILS_VER)-$(LIBDIR)/Makefile: + CFLAGS += CFLAGS_$(LIBDIR) +$(BUILDDIR)/$(BINUTILS_VER)-$(LIBDIR)/Makefile: + LIBDIR = --libdir=$(TARGETDIR)/$(LIBDIR) -# Create one set of bfds etc for each multilib arch -$(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l)))) +BFDLIB += $(TARGETDIR)/$(BINUTILS_VER)-$(LIBDIR).done +BFDMAKES += $(BUILDDIR)/$(BINUTILS_VER)-$(LIBDIR)/Makefile # Only build these two libs. $(BFDLIB): MAKECMD = all-libiberty all-bfd @@ -228,7 +214,7 @@ $(BFDMAKES): CONFIG = --target=$(TARGET) \ --host=$(TARGET) --build=$(BUILD) \ --prefix=$(TARGETDIR) \ --with-sysroot=$(SYSROOT) \ - $(LIBDIRS) + $(LIBDIR) $(BFDMAKES): TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-) @@ -243,11 +229,8 @@ $(GCC) \ $(CCACHE): ENVS += $(TOOLS) # libdir to work around hateful bfd stuff installing into wrong dirs... -# ensure we have 64 bit bfd support in the HOST library. I.e our -# compiler on i686 will know 64 bit symbols, BUT later -# we build just the libs again for TARGET, then with whatever the arch -# wants. -$(BUILDDIR)/$(BINUTILS_VER)/Makefile: CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS)) +# ensure we have 64 bit bfd support in the HOST library. +$(BUILDDIR)/$(BINUTILS_VER)/Makefile: CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(LIBDIR) ifeq ($(filter $(ARCH), s390x riscv64 ppc64le), ) # gold compiles but cannot link properly on s390x @ gcc 13.2 and Fedore 41 @@ -256,10 +239,6 @@ ifeq ($(filter $(ARCH), s390x riscv64 ppc64le), ) LINKER_CONFIG_ENABLE_GOLD := --enable-gold=default endif -ifeq ($(filter riscv64 ppc64le s390x armhfp, $(ARCH)), ) - ENABLE_MULTILIB := --enable-multilib -endif - # Makefile creation. Simply run configure in build dir. # Setting CFLAGS to -O2 generates a much faster ld. $(BFDMAKES) \ @@ -275,7 +254,6 @@ $(BUILDDIR)/$(BINUTILS_VER)/Makefile: $(BINUTILS_CFG) --with-sysroot=$(SYSROOT) \ --disable-nls \ --program-prefix=$(TARGET)- \ - $(ENABLE_MULTILIB) \ --enable-threads \ --enable-plugins \ ) > $(@D)/log.config 2>&1 @@ -340,15 +318,12 @@ ifeq ($(ARCH), riscv64) $(BUILDDIR)/$(GCC_VER)/Makefile: CONFIG += --disable-libsanitizer endif -ifneq ($(filter riscv64 ppc64le s390x armhfp, $(ARCH)), ) - # We only support 64-bit on these platforms anyway - CONFIG += --disable-multilib -endif +# We don't need to support multilib +CONFIG += --disable-multilib # Want: # c,c++ # shared libs -# multilib (-m32/-m64 on x64) # skip native language. # and link and assemble with the binutils we created # earlier, so --with-gnu* @@ -438,14 +413,12 @@ ifeq ($(HOST),$(TARGET)) # "Solve" this by create links from the target libdirs to where they are. $(LINK_LIBS_MARKER): $(GCC) @echo -n 'Creating library symlinks...' - @for l in $(LIBDIRS); do \ - for f in `cd $(PREFIX)/$$l && ls`; do \ - if [ ! -e $(TARGETDIR)/$$l/$$f ]; then \ - mkdir -p $(TARGETDIR)/$$l && \ - cd $(TARGETDIR)/$$l/ && \ - ln -fs ../../$$l/$$f $$f; \ - fi \ - done \ + @for f in `cd $(PREFIX)/$(LIBDIR) && ls`; do \ + if [ ! -e $(TARGETDIR)/$(LIBDIR)/$$f ]; then \ + mkdir -p $(TARGETDIR)/$(LIBDIR) && \ + cd $(TARGETDIR)/$(LIBDIR)/ && \ + ln -fs ../../$(LIBDIR)/$$f $$f; \ + fi \ done @touch $@ @echo 'done' diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index f31514e666c..49f3419dfb6 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -8294,6 +8294,34 @@ instruct castII_checked(iRegI dst, rFlagsReg cr) ins_pipe(pipe_slow); %} +// The unchecked and checked variants for CastII below both use iRegINoSp for src and dst +// as some consumers of CastII node like ConvHF2F forbid the stack pointer as an input +// (please see convHF2F_reg_reg rule which requires input to be in an iRegINoSp register). +instruct castII_nosp(iRegINoSp dst) +%{ + predicate(VerifyConstraintCasts == 0); + match(Set dst (CastII dst)); + + size(0); + format %{ "# castII of $dst" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + +instruct castII_checked_nosp(iRegINoSp dst, rFlagsReg cr) +%{ + predicate(VerifyConstraintCasts > 0); + match(Set dst (CastII dst)); + effect(KILL cr); + + format %{ "# castII_checked of $dst" %} + ins_encode %{ + __ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register, rscratch1); + %} + ins_pipe(pipe_slow); +%} + instruct castLL(iRegL dst) %{ predicate(VerifyConstraintCasts == 0); diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index a53efd43d5d..febd084d78a 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -241,9 +241,9 @@ source %{ return false; } break; - // At the time of writing this, the Vector API has no half-float (FP16) species. - // Consequently, AddReductionVHF and MulReductionVHF are only produced by the - // auto-vectorizer, which requires strictly ordered semantics for FP reductions. + // AddReductionVHF and MulReductionVHF are currently only produced by the + // auto-vectorizer (the Vector API does not yet intrinsify Float16 reductions), + // which requires strictly ordered semantics for FP reductions. // // There is no direct Neon instruction that performs strictly ordered floating // point add reduction. Hence, on Neon only machines, the add reduction operation @@ -354,9 +354,9 @@ source %{ opcode = Op_StoreVectorScatterMasked; break; // Currently, the masked versions of the following 8 Float16 operations are disabled. - // When the support for Float16 vector classes is added in VectorAPI and the masked - // Float16 IR can be generated, these masked operations will be enabled and relevant - // backend support added. + // The Vector API does not yet emit predicated Float16 IR. When such masked IR can be + // generated, these masked operations will be enabled and the relevant backend support + // added. case Op_AddVHF: case Op_SubVHF: case Op_MulVHF: diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 7731290c801..c590b6699c0 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -976,12 +976,9 @@ void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) { if (c_rarg0 == _obj) { __ lea(c_rarg1, _addr); } else if (c_rarg1 == _obj) { - // Set up arguments in reverse, and then flip them - __ lea(c_rarg0, _addr); - // flip them - __ mov(_tmp1, c_rarg0); - __ mov(c_rarg0, c_rarg1); - __ mov(c_rarg1, _tmp1); + __ mov(_tmp1, c_rarg1); + __ lea(c_rarg1, _addr); + __ mov(c_rarg0, _tmp1); } else { assert_different_registers(c_rarg1, _obj); __ lea(c_rarg1, _addr); diff --git a/src/hotspot/cpu/arm/frame_arm.hpp b/src/hotspot/cpu/arm/frame_arm.hpp index 6d4ac042831..026bd993981 100644 --- a/src/hotspot/cpu/arm/frame_arm.hpp +++ b/src/hotspot/cpu/arm/frame_arm.hpp @@ -61,6 +61,7 @@ // between a callee frame and its stack arguments, where it is part // of the caller/callee overlap metadata_words_at_top = 0, + // in bytes frame_alignment = 16, // size, in words, of maximum shift in frame position due to alignment align_wiggle = 1 diff --git a/src/hotspot/cpu/ppc/frame_ppc.hpp b/src/hotspot/cpu/ppc/frame_ppc.hpp index ebe5d24c072..14743c7d75a 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.hpp +++ b/src/hotspot/cpu/ppc/frame_ppc.hpp @@ -402,8 +402,7 @@ // between a callee frame and its stack arguments, where it is part // of the caller/callee overlap metadata_words_at_top = sizeof(java_abi) >> LogBytesPerWord, - // size, in words, of frame metadata at the frame top that needs - // to be reserved for callee functions in the runtime + // in bytes frame_alignment = 16, frame_alignment_in_words = frame_alignment >> LogBytesPerWord, // size, in words, of maximum shift in frame position due to alignment diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 823ff175379..582327282fd 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -1210,12 +1210,9 @@ void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) { if (c_rarg0 == _obj) { __ addi(c_rarg1, _addr.base(), _addr.disp()); } else if (c_rarg1 == _obj) { - // Set up arguments in reverse, and then flip them - __ addi(c_rarg0, _addr.base(), _addr.disp()); - // flip them - __ mr(_tmp1, c_rarg0); - __ mr(c_rarg0, c_rarg1); - __ mr(c_rarg1, _tmp1); + __ mr(_tmp1, c_rarg1); + __ addi(c_rarg1, _addr.base(), _addr.disp()); + __ mr(c_rarg0, _tmp1); } else { assert_different_registers(c_rarg1, _obj); __ addi(c_rarg1, _addr.base(), _addr.disp()); diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp index d30592d68f1..eec5f9a5165 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp @@ -912,12 +912,9 @@ void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) { if (c_rarg0 == _obj) { __ la(c_rarg1, _addr); } else if (c_rarg1 == _obj) { - // Set up arguments in reverse, and then flip them - __ la(c_rarg0, _addr); - // flip them - __ mv(_tmp1, c_rarg0); - __ mv(c_rarg0, c_rarg1); - __ mv(c_rarg1, _tmp1); + __ mv(_tmp1, c_rarg1); + __ la(c_rarg1, _addr); + __ mv(c_rarg0, _tmp1); } else { assert_different_registers(c_rarg1, _obj); __ la(c_rarg1, _addr); diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index 18ca120bdfa..f05b9ff7791 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -120,10 +120,10 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZvbb, false, EXPERIMENTAL, "Use Zvbb instructions") \ product(bool, UseZvbc, false, EXPERIMENTAL, "Use Zvbc instructions") \ product(bool, UseZvfh, false, DIAGNOSTIC, "Use Zvfh instructions") \ - product(bool, UseZvkn, false, EXPERIMENTAL, \ + product(bool, UseZvkg, false, DIAGNOSTIC, "Use Zvkg instructions") \ + product(bool, UseZvkn, false, DIAGNOSTIC, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ product(bool, UseCtxFencei, false, EXPERIMENTAL, \ - "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") \ - product(bool, UseZvkg, false, EXPERIMENTAL, "Use Zvkg instructions") + "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") #endif // CPU_RISCV_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/x86/frame_x86.hpp b/src/hotspot/cpu/x86/frame_x86.hpp index 2d382c7e5e5..546c40fffe4 100644 --- a/src/hotspot/cpu/x86/frame_x86.hpp +++ b/src/hotspot/cpu/x86/frame_x86.hpp @@ -101,8 +101,7 @@ // between a callee frame and its stack arguments, where it is part // of the caller/callee overlap metadata_words_at_top = 0, - // size, in words, of frame metadata at the frame top that needs - // to be reserved for callee functions in the runtime + // in bytes frame_alignment = 16, // size, in words, of maximum shift in frame position due to alignment align_wiggle = 1 diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 0ac0a8243d4..80dd7ccfbca 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -10106,10 +10106,6 @@ void MacroAssembler::load_aotrc_address(Register reg, address a) { } void MacroAssembler::setcc(Assembler::Condition comparison, Register dst) { - if (VM_Version::supports_apx_f()) { - esetzucc(comparison, dst); - } else { - setb(comparison, dst); - movzbl(dst, dst); - } + setb(comparison, dst); + movzbl(dst, dst); } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index b3dd1a0812b..370437edee2 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -7287,13 +7287,8 @@ instruct loadNKlassCompactHeaders(rRegN dst, memory mem, rFlagsReg cr) "shrl $dst, markWord::klass_shift_at_offset" %} ins_encode %{ - if (UseAPX) { - __ eshrl($dst$$Register, $mem$$Address, markWord::klass_shift_at_offset, false); - } - else { - __ movl($dst$$Register, $mem$$Address); - __ shrl($dst$$Register, markWord::klass_shift_at_offset); - } + __ movl($dst$$Register, $mem$$Address); + __ shrl($dst$$Register, markWord::klass_shift_at_offset); %} ins_pipe(ialu_reg_mem); %} @@ -9269,7 +9264,6 @@ instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) // Conditional move instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{ - predicate(!UseAPX); match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); ins_cost(250); // XXX @@ -9280,24 +9274,9 @@ instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{ ins_pipe(pipe_cmov_mem); %} -// Conditional move -instruct cmovI_rReg_rReg_mem_ndd(rRegI dst, cmpOp cop, rFlagsReg cr, rRegI src1, memory src2) -%{ - predicate(UseAPX); - match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2)))); - - ins_cost(250); - format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %} - ins_encode %{ - __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address); - %} - ins_pipe(pipe_cmov_mem); -%} - // Conditional move instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src) %{ - predicate(!UseAPX); match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); ins_cost(250); // XXX @@ -9317,27 +9296,13 @@ instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{ %} %} -instruct cmovI_rReg_rReg_memU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, memory src2) -%{ - predicate(UseAPX); - match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2)))); +instruct cmovI_memUCFE(cmpOpUCFE cop, rFlagsRegUCFE cr, rRegI dst, memory src) %{ + match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); - ins_cost(250); - format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %} + ins_cost(250); // XXX + format %{ "cmovl$cop $dst, $src\t# unsigned, int" %} ins_encode %{ - __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address); - %} - ins_pipe(pipe_cmov_mem); -%} - -instruct cmovI_rReg_rReg_memUCFE_ndd(rRegI dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegI src1, memory src2) -%{ - match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2)))); - - ins_cost(250); - format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, unsigned, int ndd" %} - ins_encode %{ - __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address); + __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address); %} ins_pipe(pipe_cmov_mem); %} @@ -9596,7 +9561,6 @@ instruct cmovL_reg_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, rRegL src instruct cmovL_mem(cmpOp cop, rFlagsReg cr, rRegL dst, memory src) %{ - predicate(!UseAPX); match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); ins_cost(200); // XXX @@ -9607,19 +9571,6 @@ instruct cmovL_mem(cmpOp cop, rFlagsReg cr, rRegL dst, memory src) ins_pipe(pipe_cmov_mem); // XXX %} -instruct cmovL_rReg_rReg_mem_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, memory src2) -%{ - predicate(UseAPX); - match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2)))); - - ins_cost(200); - format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %} - ins_encode %{ - __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address); - %} - ins_pipe(pipe_cmov_mem); -%} - instruct cmovL_imm_01U(rRegL dst, immL1 src, rFlagsRegU cr, cmpOpU cop) %{ predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0); @@ -9741,7 +9692,6 @@ instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src) %{ - predicate(!UseAPX); match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); ins_cost(200); // XXX @@ -9761,29 +9711,15 @@ instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{ %} %} -instruct cmovL_rReg_rReg_memU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, memory src2) -%{ - predicate(UseAPX); - match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2)))); +instruct cmovL_memUCFE(cmpOpUCFE cop, rFlagsRegUCFE cr, rRegL dst, memory src) %{ + match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); - ins_cost(200); - format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %} + ins_cost(200); // XXX + format %{ "cmovq$cop $dst, $src\t# unsigned, long" %} ins_encode %{ - __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address); + __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address); %} - ins_pipe(pipe_cmov_mem); -%} - -instruct cmovL_rReg_rReg_memUCFE_ndd(rRegL dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegL src1, memory src2) -%{ - match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2)))); - - ins_cost(200); - format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, unsigned, long ndd" %} - ins_encode %{ - __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address); - %} - ins_pipe(pipe_cmov_mem); + ins_pipe(pipe_cmov_mem); // XXX %} instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src) @@ -9970,23 +9906,8 @@ instruct addI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr) ins_pipe( ialu_reg ); %} -instruct addI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AddI (LoadI src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); - - format %{ "eaddl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eaddl($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe( ialu_reg ); -%} - instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (AddI dst (LoadI src))); effect(KILL cr); flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); @@ -9999,21 +9920,6 @@ instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct addI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AddI src1 (LoadI src2))); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "eaddl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eaddl($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - instruct addI_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ match(Set dst (StoreI dst (AddI (LoadI dst) src))); @@ -10070,19 +9976,6 @@ instruct incI_rReg_ndd(rRegI dst, rRegI src, immI_1 val, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct incI_rReg_mem_ndd(rRegI dst, memory src, immI_1 val, rFlagsReg cr) -%{ - predicate(UseAPX && UseIncDec); - match(Set dst (AddI (LoadI src) val)); - effect(KILL cr); - - format %{ "eincl $dst, $src\t# int ndd" %} - ins_encode %{ - __ eincl($dst$$Register, $src$$Address, false); - %} - ins_pipe(ialu_reg); -%} - instruct incI_mem(memory dst, immI_1 src, rFlagsReg cr) %{ predicate(UseIncDec); @@ -10125,19 +10018,6 @@ instruct decI_rReg_ndd(rRegI dst, rRegI src, immI_M1 val, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct decI_rReg_mem_ndd(rRegI dst, memory src, immI_M1 val, rFlagsReg cr) -%{ - predicate(UseAPX && UseIncDec); - match(Set dst (AddI (LoadI src) val)); - effect(KILL cr); - - format %{ "edecl $dst, $src\t# int ndd" %} - ins_encode %{ - __ edecl($dst$$Register, $src$$Address, false); - %} - ins_pipe(ialu_reg); -%} - // XXX why does that use AddI instruct decI_mem(memory dst, immI_M1 src, rFlagsReg cr) %{ @@ -10260,23 +10140,8 @@ instruct addL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr ins_pipe( ialu_reg ); %} -instruct addL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AddL (LoadL src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); - - format %{ "eaddq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ eaddq($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe( ialu_reg ); -%} - instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (AddL dst (LoadL src))); effect(KILL cr); flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); @@ -10289,21 +10154,6 @@ instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct addL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AddL src1 (LoadL src2))); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "eaddq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ eaddq($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - instruct addL_mem_rReg(memory dst, rRegL src, rFlagsReg cr) %{ match(Set dst (StoreL dst (AddL (LoadL dst) src))); @@ -10359,19 +10209,6 @@ instruct incL_rReg_ndd(rRegL dst, rRegI src, immL1 val, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct incL_rReg_mem_ndd(rRegL dst, memory src, immL1 val, rFlagsReg cr) -%{ - predicate(UseAPX && UseIncDec); - match(Set dst (AddL (LoadL src) val)); - effect(KILL cr); - - format %{ "eincq $dst, $src\t# long ndd" %} - ins_encode %{ - __ eincq($dst$$Register, $src$$Address, false); - %} - ins_pipe(ialu_reg); -%} - instruct incL_mem(memory dst, immL1 src, rFlagsReg cr) %{ predicate(UseIncDec); @@ -10414,19 +10251,6 @@ instruct decL_rReg_ndd(rRegL dst, rRegL src, immL_M1 val, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct decL_rReg_mem_ndd(rRegL dst, memory src, immL_M1 val, rFlagsReg cr) -%{ - predicate(UseAPX && UseIncDec); - match(Set dst (AddL (LoadL src) val)); - effect(KILL cr); - - format %{ "edecq $dst, $src\t# long ndd" %} - ins_encode %{ - __ edecq($dst$$Register, $src$$Address, false); - %} - ins_pipe(ialu_reg); -%} - // XXX why does that use AddL instruct decL_mem(memory dst, immL_M1 src, rFlagsReg cr) %{ @@ -11147,23 +10971,8 @@ instruct subI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr) ins_pipe(ialu_reg_reg); %} -instruct subI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (SubI (LoadI src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); - - format %{ "esubl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ esubl($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg_reg); -%} - instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (SubI dst (LoadI src))); effect(KILL cr); flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); @@ -11176,36 +10985,6 @@ instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct subI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (SubI src1 (LoadI src2))); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag, PD::Flag_ndd_demotable_opr1); - - ins_cost(150); - format %{ "esubl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ esubl($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - -instruct subI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (SubI (LoadI src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); - - ins_cost(150); - format %{ "esubl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ esubl($dst$$Register, $src1$$Address, $src2$$Register, false); - %} - ins_pipe(ialu_reg_mem); -%} - instruct subI_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ match(Set dst (StoreI dst (SubI (LoadI dst) src))); @@ -11262,23 +11041,8 @@ instruct subL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr ins_pipe(ialu_reg_reg); %} -instruct subL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (SubL (LoadL src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); - - format %{ "esubq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ esubq($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg_reg); -%} - instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (SubL dst (LoadL src))); effect(KILL cr); flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); @@ -11291,36 +11055,6 @@ instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct subL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (SubL src1 (LoadL src2))); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag, PD::Flag_ndd_demotable_opr1); - - ins_cost(150); - format %{ "esubq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ esubq($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - -instruct subL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (SubL (LoadL src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag); - - ins_cost(150); - format %{ "esubq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ esubq($dst$$Register, $src1$$Address, $src2$$Register, false); - %} - ins_pipe(ialu_reg_mem); -%} - instruct subL_mem_rReg(memory dst, rRegL src, rFlagsReg cr) %{ match(Set dst (StoreL dst (SubL (LoadL dst) src))); @@ -11535,7 +11269,6 @@ instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr) instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (MulI dst (LoadI src))); effect(KILL cr); @@ -11547,21 +11280,6 @@ instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem_alu0); %} -instruct mulI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (MulI src1 (LoadI src2))); - effect(KILL cr); - flag(PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(350); - format %{ "eimull $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eimull($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem_alu0); -%} - instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr) %{ match(Set dst (MulI (LoadI src) imm)); @@ -11629,7 +11347,6 @@ instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr) instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (MulL dst (LoadL src))); effect(KILL cr); @@ -11641,20 +11358,6 @@ instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem_alu0); %} -instruct mulL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (MulL src1 (LoadL src2))); - effect(KILL cr); - flag(PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(350); - format %{ "eimulq $dst, $src1, $src2 \t# long" %} - ins_encode %{ - __ eimulq($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem_alu0); -%} instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr) %{ @@ -11959,19 +11662,6 @@ instruct salI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct salI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (LShiftI (LoadI src) shift)); - effect(KILL cr); - - format %{ "esall $dst, $src, $shift\t# int (ndd)" %} - ins_encode %{ - __ esall($dst$$Register, $src$$Address, $shift$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Shift Left by 8-bit immediate instruct salI_mem_imm(memory dst, immI8 shift, rFlagsReg cr) %{ @@ -12066,19 +11756,6 @@ instruct sarI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr) ins_pipe(ialu_mem_imm); %} -instruct sarI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (RShiftI (LoadI src) shift)); - effect(KILL cr); - - format %{ "esarl $dst, $src, $shift\t# int (ndd)" %} - ins_encode %{ - __ esarl($dst$$Register, $src$$Address, $shift$$constant, false); - %} - ins_pipe(ialu_mem_imm); -%} - // Arithmetic Shift Right by 8-bit immediate instruct sarI_mem_imm(memory dst, immI8 shift, rFlagsReg cr) %{ @@ -12173,19 +11850,6 @@ instruct shrI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct shrI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (URShiftI (LoadI src) shift)); - effect(KILL cr); - - format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %} - ins_encode %{ - __ eshrl($dst$$Register, $src$$Address, $shift$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Logical Shift Right by 8-bit immediate instruct shrI_mem_imm(memory dst, immI8 shift, rFlagsReg cr) %{ @@ -12310,19 +11974,6 @@ instruct salL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct salL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (LShiftL (LoadL src) shift)); - effect(KILL cr); - - format %{ "esalq $dst, $src, $shift\t# long (ndd)" %} - ins_encode %{ - __ esalq($dst$$Register, $src$$Address, $shift$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Shift Left by 8-bit immediate instruct salL_mem_imm(memory dst, immI8 shift, rFlagsReg cr) %{ @@ -12417,19 +12068,6 @@ instruct sarL_rReg_imm_ndd(rRegL dst, rRegL src, immI shift, rFlagsReg cr) ins_pipe(ialu_mem_imm); %} -instruct sarL_rReg_mem_imm_ndd(rRegL dst, memory src, immI shift, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (RShiftL (LoadL src) shift)); - effect(KILL cr); - - format %{ "esarq $dst, $src, $shift\t# long (ndd)" %} - ins_encode %{ - __ esarq($dst$$Register, $src$$Address, (unsigned char)($shift$$constant & 0x3F), false); - %} - ins_pipe(ialu_mem_imm); -%} - // Arithmetic Shift Right by 8-bit immediate instruct sarL_mem_imm(memory dst, immI shift, rFlagsReg cr) %{ @@ -12524,19 +12162,6 @@ instruct shrL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct shrL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (URShiftL (LoadL src) shift)); - effect(KILL cr); - - format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %} - ins_encode %{ - __ eshrq($dst$$Register, $src$$Address, $shift$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Logical Shift Right by 8-bit immediate instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr) %{ @@ -13064,24 +12689,9 @@ instruct andI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct andI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AndI (LoadI src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); - - format %{ "eandl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eandl($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // And Register with Memory instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (AndI dst (LoadI src))); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -13094,21 +12704,6 @@ instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct andI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AndI src1 (LoadI src2))); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "eandl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eandl($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - // And Memory with Register instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ @@ -13351,24 +12946,9 @@ instruct orI_rReg_imm_rReg_ndd(rRegI dst, immI src1, rRegI src2, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct orI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (OrI (LoadI src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); - - format %{ "eorl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eorl($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Or Register with Memory instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (OrI dst (LoadI src))); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -13381,21 +12961,6 @@ instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct orI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (OrI src1 (LoadI src2))); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "eorl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ eorl($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - // Or Memory with Register instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ @@ -13528,26 +13093,9 @@ instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr) ins_pipe(ialu_reg); %} -// Xor Memory with Immediate -instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (XorI (LoadI src1) src2)); - effect(KILL cr); - ins_cost(150); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); - - format %{ "exorl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ exorl($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Xor Register with Memory instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (XorI dst (LoadI src))); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -13560,21 +13108,6 @@ instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct xorI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (XorI src1 (LoadI src2))); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "exorl $dst, $src1, $src2\t# int ndd" %} - ins_encode %{ - __ exorl($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - // Xor Memory with Register instruct xorB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ @@ -13709,24 +13242,9 @@ instruct andL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr ins_pipe(ialu_reg); %} -instruct andL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AndL (LoadL src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); - - format %{ "eandq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ eandq($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // And Register with Memory instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (AndL dst (LoadL src))); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -13739,21 +13257,6 @@ instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct andL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (AndL src1 (LoadL src2))); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "eandq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ eandq($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - // And Memory with Register instruct andL_mem_rReg(memory dst, rRegL src, rFlagsReg cr) %{ @@ -14027,25 +13530,9 @@ instruct orL_rReg_imm_rReg_ndd(rRegL dst, immL32 src1, rRegL src2, rFlagsReg cr) ins_pipe(ialu_reg); %} -// Or Memory with Immediate -instruct orL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (OrL (LoadL src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); - - format %{ "eorq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ eorq($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Or Register with Memory instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (OrL dst (LoadL src))); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -14058,21 +13545,6 @@ instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct orL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (OrL src1 (LoadL src2))); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "eorq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ eorq($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - // Or Memory with Register instruct orL_mem_rReg(memory dst, rRegL src, rFlagsReg cr) %{ @@ -14208,26 +13680,9 @@ instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr) ins_pipe(ialu_reg); %} -// Xor Memory with Immediate -instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (XorL (LoadL src1) src2)); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); - ins_cost(150); - - format %{ "exorq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ exorq($dst$$Register, $src1$$Address, $src2$$constant, false); - %} - ins_pipe(ialu_reg); -%} - // Xor Register with Memory instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) %{ - predicate(!UseAPX); match(Set dst (XorL dst (LoadL src))); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -14240,21 +13695,6 @@ instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct xorL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr) -%{ - predicate(UseAPX); - match(Set dst (XorL src1 (LoadL src2))); - effect(KILL cr); - flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag, PD::Flag_ndd_demotable_opr1, PD::Flag_ndd_demotable_opr2); - - ins_cost(150); - format %{ "exorq $dst, $src1, $src2\t# long ndd" %} - ins_encode %{ - __ exorq($dst$$Register, $src1$$Register, $src2$$Address, false); - %} - ins_pipe(ialu_reg_mem); -%} - // Xor Memory with Register instruct xorL_mem_rReg(memory dst, rRegL src, rFlagsReg cr) %{ diff --git a/src/hotspot/cpu/zero/frame_zero.hpp b/src/hotspot/cpu/zero/frame_zero.hpp index af9abe22cbe..19096615594 100644 --- a/src/hotspot/cpu/zero/frame_zero.hpp +++ b/src/hotspot/cpu/zero/frame_zero.hpp @@ -39,6 +39,7 @@ // between a callee frame and its stack arguments, where it is part // of the caller/callee overlap metadata_words_at_top = 0, + // in bytes frame_alignment = 16, // size, in words, of maximum shift in frame position due to alignment align_wiggle = 1 diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 253f460dca3..a3bd1bfa870 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -249,7 +249,6 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { VM_Version::ext_Zvfh.enable_feature(); } -#ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNED) && is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNHB) && is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKB) && @@ -259,7 +258,6 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKG)) { VM_Version::ext_Zvkg.enable_feature(); } -#endif // ====== non-extensions ====== // diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.cpp b/src/hotspot/share/gc/parallel/psMemoryPool.cpp index 40170f62f06..13304ca18ad 100644 --- a/src/hotspot/share/gc/parallel/psMemoryPool.cpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.cpp @@ -32,7 +32,7 @@ PSOldGenerationPool::PSOldGenerationPool(PSOldGen* old_gen, } MemoryUsage PSOldGenerationPool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); size_t used = used_in_bytes(); size_t committed = _old_gen->capacity_in_bytes(); @@ -59,7 +59,7 @@ PSEdenSpacePool::PSEdenSpacePool(PSYoungGen* young_gen, } MemoryUsage PSEdenSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); size_t used = used_in_bytes(); size_t committed = _space->capacity_in_bytes(); @@ -80,7 +80,7 @@ PSSurvivorSpacePool::PSSurvivorSpacePool(PSYoungGen* young_gen, } MemoryUsage PSSurvivorSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); size_t used = used_in_bytes(); size_t committed = committed_in_bytes(); return MemoryUsage(initial_size(), used, committed, maxSize); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index a4a2bfe72c2..ff757f205a2 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1268,8 +1268,7 @@ void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) { #endif } -template -void PSParallelCompact::adjust_in_space_helper(SpaceId id, Atomic* claim_counter, Func&& on_stripe) { +void PSParallelCompact::adjust_in_space_helper(SpaceId id, Atomic* claim_counter) { MutableSpace* sp = PSParallelCompact::space(id); HeapWord* const bottom = sp->bottom(); HeapWord* const top = sp->top(); @@ -1288,53 +1287,46 @@ void PSParallelCompact::adjust_in_space_helper(SpaceId id, Atomic* claim_c break; } HeapWord* stripe_end = MIN2(cur_stripe + stripe_size, top); - on_stripe(cur_stripe, stripe_end); + adjust_in_stripe(cur_stripe, stripe_end); + } +} + +size_t PSParallelCompact::adjust_in_obj_with_limit(HeapWord* obj_start, HeapWord* left, HeapWord* right) { + precond(mark_bitmap()->is_marked(obj_start)); + oop obj = cast_to_oop(obj_start); + return obj->oop_iterate_size(&pc_adjust_pointer_closure, MemRegion(left, right)); +} + +void PSParallelCompact::adjust_in_stripe(HeapWord* stripe_start, HeapWord* stripe_end) { + precond(_summary_data.is_region_aligned(stripe_start)); + + RegionData* cur_region = _summary_data.addr_to_region_ptr(stripe_start); + HeapWord* obj_start; + if (cur_region->partial_obj_size() != 0) { + obj_start = cur_region->partial_obj_addr(); + obj_start += adjust_in_obj_with_limit(obj_start, stripe_start, stripe_end); + } else { + obj_start = stripe_start; + } + + while (obj_start < stripe_end) { + obj_start = mark_bitmap()->find_obj_beg(obj_start, stripe_end); + if (obj_start >= stripe_end) { + break; + } + obj_start += adjust_in_obj_with_limit(obj_start, stripe_start, stripe_end); } } void PSParallelCompact::adjust_in_old_space(Atomic* claim_counter) { // Regions in old-space shouldn't be split. - assert(!_space_info[old_space_id].split_info().is_valid(), "inv"); + precond(!_space_info[old_space_id].split_info().is_valid()); - auto scan_obj_with_limit = [&] (HeapWord* obj_start, HeapWord* left, HeapWord* right) { - assert(mark_bitmap()->is_marked(obj_start), "inv"); - oop obj = cast_to_oop(obj_start); - return obj->oop_iterate_size(&pc_adjust_pointer_closure, MemRegion(left, right)); - }; - - adjust_in_space_helper(old_space_id, claim_counter, [&] (HeapWord* stripe_start, HeapWord* stripe_end) { - assert(_summary_data.is_region_aligned(stripe_start), "inv"); - RegionData* cur_region = _summary_data.addr_to_region_ptr(stripe_start); - HeapWord* obj_start; - if (cur_region->partial_obj_size() != 0) { - obj_start = cur_region->partial_obj_addr(); - obj_start += scan_obj_with_limit(obj_start, stripe_start, stripe_end); - } else { - obj_start = stripe_start; - } - - while (obj_start < stripe_end) { - obj_start = mark_bitmap()->find_obj_beg(obj_start, stripe_end); - if (obj_start >= stripe_end) { - break; - } - obj_start += scan_obj_with_limit(obj_start, stripe_start, stripe_end); - } - }); + adjust_in_space_helper(old_space_id, claim_counter); } void PSParallelCompact::adjust_in_young_space(SpaceId id, Atomic* claim_counter) { - adjust_in_space_helper(id, claim_counter, [](HeapWord* stripe_start, HeapWord* stripe_end) { - HeapWord* obj_start = stripe_start; - while (obj_start < stripe_end) { - obj_start = mark_bitmap()->find_obj_beg(obj_start, stripe_end); - if (obj_start >= stripe_end) { - break; - } - oop obj = cast_to_oop(obj_start); - obj_start += obj->oop_iterate_size(&pc_adjust_pointer_closure); - } - }); + adjust_in_space_helper(id, claim_counter); } void PSParallelCompact::adjust_pointers_in_spaces(uint worker_id, Atomic* claim_counters) { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 25f4f66de6f..909005f5360 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -760,8 +760,11 @@ public: // should_do_max_compaction controls whether all spaces for dead objs should be reclaimed. static bool invoke(bool clear_all_soft_refs, bool should_do_max_compaction); - template - static void adjust_in_space_helper(SpaceId id, Atomic* claim_counter, Func&& on_stripe); + static void adjust_in_space_helper(SpaceId id, Atomic* claim_counter); + + static size_t adjust_in_obj_with_limit(HeapWord* obj_start, HeapWord* left, HeapWord* right); + + static void adjust_in_stripe(HeapWord* stripe_start, HeapWord* stripe_end); static void adjust_in_old_space(Atomic* claim_counter); diff --git a/src/hotspot/share/gc/serial/serialMemoryPools.cpp b/src/hotspot/share/gc/serial/serialMemoryPools.cpp index 723b53a3e2b..8b0230264ef 100644 --- a/src/hotspot/share/gc/serial/serialMemoryPools.cpp +++ b/src/hotspot/share/gc/serial/serialMemoryPools.cpp @@ -40,7 +40,7 @@ size_t ContiguousSpacePool::used_in_bytes() { } MemoryUsage ContiguousSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); size_t used = used_in_bytes(); size_t committed = _space->capacity(); @@ -64,7 +64,7 @@ size_t SurvivorContiguousSpacePool::committed_in_bytes() { } MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); size_t used = used_in_bytes(); size_t committed = committed_in_bytes(); @@ -85,7 +85,7 @@ size_t TenuredGenerationPool::used_in_bytes() { MemoryUsage TenuredGenerationPool::get_memory_usage() { size_t used = used_in_bytes(); size_t committed = _gen->capacity(); - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); return MemoryUsage(initial_size(), used, committed, maxSize); } diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index e6e3fdf3d82..dcf13ab48e9 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -194,6 +194,7 @@ void CardTable::resize_covered_region(MemRegion new_region) { // Note that these versions are precise! The scanning code has to handle the // fact that the write barrier may be either precise or imprecise. void CardTable::dirty_MemRegion(MemRegion mr) { + assert(!mr.is_empty(), "precondition"); assert(align_down(mr.start(), HeapWordSize) == mr.start(), "Unaligned start"); assert(align_up (mr.end(), HeapWordSize) == mr.end(), "Unaligned end" ); assert(_covered[0].contains(mr) || _covered[1].contains(mr), "precondition"); @@ -203,6 +204,7 @@ void CardTable::dirty_MemRegion(MemRegion mr) { } void CardTable::clear_MemRegion(MemRegion mr) { + assert(!mr.is_empty(), "precondition"); // Be conservative: only clean cards entirely contained within the // region. CardValue* cur; diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp index f60a7f47a19..5c10a1618a5 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp @@ -130,7 +130,10 @@ oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, // pointer delta is scaled to number of elements (length field in // objArrayOop) which we assume is 32 bit. assert(pd == (size_t)(int)pd, "length field overflow"); - bs->write_ref_array((HeapWord*)dst_raw, pd); + if (pd > 0) { + // Copied at least one element; call the barrier. + bs->write_ref_array((HeapWord*)dst_raw, pd); + } return OopCopyResult::failed_check_class_cast; } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.hpp index ff0a425e260..4d75c5d6794 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.hpp @@ -174,7 +174,7 @@ private: void take_sample(jlong now, jlong elapsed, size_t unsampled); double upper_bound_no_lock(const double standard_deviations) const { - assert(_sample_lock.is_locked(), "Caller must hold lock"); + assert(_sample_lock.owned_by_self(), "Caller must hold lock"); return _baseline.weighted_average() + standard_deviations * _baseline.weighted_sd(); } }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.inline.hpp index eedda19b86e..4872b288a5b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAllocRate.inline.hpp @@ -114,7 +114,7 @@ void ShenandoahAllocRate::force_update() { template void ShenandoahAllocRate::take_sample(jlong now, jlong elapsed, size_t unsampled) { - assert(_sample_lock.is_locked(), "Caller must hold lock"); + assert(_sample_lock.owned_by_self(), "Caller must hold lock"); _last_sample_time = now; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index f2447db8210..3fefae58ef8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -221,22 +221,22 @@ void ShenandoahControlThread::run_service() { // Wait before performing the next action. If allocation happened during this wait, // we exit sooner, to let heuristics re-evaluate new conditions. If we are at idle, // back off exponentially. - const double before_sleep = most_recent_wake_time; if (heap->has_changed()) { sleep = ShenandoahControlIntervalMin; - } else if ((before_sleep - last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ + } else if ((most_recent_wake_time - last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ sleep = MIN2(ShenandoahControlIntervalMax, MAX2(1, sleep * 2)); - last_sleep_adjust_time = before_sleep; + last_sleep_adjust_time = most_recent_wake_time; } MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + const double before_sleep_time = os::elapsedTime(); ml.wait(sleep); + most_recent_wake_time = os::elapsedTime(); // Record a conservative estimate of the longest anticipated sleep duration until we sample again. double planned_sleep_interval = MIN2(ShenandoahControlIntervalMax, MAX2(1, sleep * 2)) / 1000.0; - most_recent_wake_time = os::elapsedTime(); heuristics->update_should_start_query_times(most_recent_wake_time, planned_sleep_interval); if (LogTarget(Debug, gc, thread)::is_enabled()) { - double elapsed = most_recent_wake_time - before_sleep; - double hiccup = elapsed - double(sleep); + double elapsed = most_recent_wake_time - before_sleep_time; + double hiccup = elapsed - double(sleep) / 1000.0; if (hiccup > 0.001) { log_debug(gc, thread)("Control Thread hiccup time: %.3fs", hiccup); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 4c474f2f86c..6563ffb6359 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -1745,8 +1745,8 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req, bo for (idx_t i = beg; i <= end; i++) { ShenandoahHeapRegion* r = _heap->get_region(i); assert(i == beg || _heap->get_region(i - 1)->index() + 1 == r->index(), "Should be contiguous"); - assert(r->is_empty(), "Should be empty"); r->try_recycle_under_lock(); + assert(r->is_empty(), "Should be empty"); r->set_affiliation(req.affiliation()); r->make_regular_allocation(req.affiliation()); if ((i == end) && (used_words_in_last_region > 0)) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp index 28094a1d57d..8823e7e4af7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp @@ -116,23 +116,21 @@ void ShenandoahRegulatorThread::regulator_sleep() { // Wait before performing the next action. If allocation happened during this wait, // we exit sooner, to let heuristics re-evaluate new conditions. If we are at idle, // back off exponentially. - double before_sleep_time = _most_recent_wake_time; if (ShenandoahHeap::heap()->has_changed()) { _sleep = ShenandoahControlIntervalMin; - } else if ((before_sleep_time - _last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ + } else if ((_most_recent_wake_time - _last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ _sleep = MIN2(ShenandoahControlIntervalMax, MAX2(1u, _sleep * 2)); - _last_sleep_adjust_time = before_sleep_time; + _last_sleep_adjust_time = _most_recent_wake_time; } SuspendibleThreadSetLeaver leaver; + const double before_sleep_time = os::elapsedTime(); os::naked_short_sleep(_sleep); - double wake_time = os::elapsedTime(); - _most_recent_period = wake_time - _most_recent_wake_time; - _most_recent_wake_time = wake_time; + _most_recent_wake_time = os::elapsedTime(); _young_heuristics->update_should_start_query_times(_most_recent_wake_time, double(_sleep) / 1000.0); if (LogTarget(Debug, gc, thread)::is_enabled()) { double elapsed = _most_recent_wake_time - before_sleep_time; - double hiccup = elapsed - double(_sleep); + double hiccup = elapsed - double(_sleep) / 1000.0; if (hiccup > 0.001) { log_debug(gc, thread)("Regulator hiccup time: %.3fs", hiccup); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp index cc41bc2c65b..62a5dcce9df 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp @@ -82,7 +82,6 @@ class ShenandoahRegulatorThread: public ConcurrentGCThread { // duration of planned regulator sleep period, in ms uint _sleep; double _most_recent_wake_time; - double _most_recent_period; double _last_sleep_adjust_time; }; diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 014f41f82cc..39d5f0be90c 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1921,6 +1921,31 @@ bool BoolNode::is_counted_loop_exit_test() { return false; } +template +static const IntegerType* integral_abs_value(const IntegerType* t) { + typedef typename IntegerType::NativeUType NativeUType; + + // Find the absolute value of a type, resulting in a range that fits inside the unsigned range [0, signed_max+1]. + // The possible values of a TypeInteger is described with the following range in the signed domain: + // smin----------lo=======uhi--------0--------ulo===========hi----------smax + + // To find the absolute value of the range, we find the closer (min) value of uhi and ulo to 0, and the further (max) + // value of lo and hi from 0. In the unsigned domain, the resulting range looks like this: + // 0-----------min(|ulo|,|uhi|)================max(|lo|,|hi|)-----------umax + + // When the input range's hi and lo are both positive or negative, lo == ulo and hi == uhi: + // smin------------------------------0-------lo===========hi------------smax (Positive) + // smin--------lo===========hi-------0----------------------------------smax (Negative) + + // For these ranges, the result in the unsigned domain is simply [min(|lo|, |hi|), max(|lo|, |hi|)]: + // 0-----------min(|lo|,|hi|)==================max(|lo|,|hi|)-----------umax + + NativeUType umin = MIN2(g_uabs(t->_ulo), g_uabs(t->_uhi)); + NativeUType umax = MAX2(g_uabs(t->_lo), g_uabs(t->_hi)); + + return IntegerType::make_unsigned(umin, umax, t->_widen); +} + //============================================================================= //------------------------------Value------------------------------------------ const Type* AbsNode::Value(PhaseGVN* phase) const { @@ -1930,17 +1955,13 @@ const Type* AbsNode::Value(PhaseGVN* phase) const { switch (t1->base()) { case Type::Int: { const TypeInt* ti = t1->is_int(); - if (ti->is_con()) { - return TypeInt::make(g_uabs(ti->get_con())); - } - break; + + return integral_abs_value(ti); } case Type::Long: { const TypeLong* tl = t1->is_long(); - if (tl->is_con()) { - return TypeLong::make(g_uabs(tl->get_con())); - } - break; + + return integral_abs_value(tl); } case Type::FloatCon: return TypeF::make(abs(t1->getf())); diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index fcdf9b09fc3..a1e213319b7 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1801,6 +1801,12 @@ const TypeInt* TypeInt::make(jint lo, jint hi, int widen) { return make_or_top(TypeIntPrototype{{lo, hi}, {0, max_juint}, {0, 0}}, widen)->is_int(); } +const TypeInt* TypeInt::make_unsigned(juint ulo, juint uhi, int widen) { + assert(ulo <= uhi, "must be legal bounds"); + // By creating the TypeInt with the full signed range and the given unsigned range, the signed bounds are inferred from the unsigned bounds. + return make_or_top(TypeIntPrototype{{min_jint, max_jint}, {ulo, uhi}, {0, 0}}, widen)->is_int(); +} + const Type* TypeInt::make_or_top(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen, false); } @@ -1936,6 +1942,12 @@ const TypeLong* TypeLong::make(jlong lo, jlong hi, int widen) { return make_or_top(TypeIntPrototype{{lo, hi}, {0, max_julong}, {0, 0}}, widen)->is_long(); } +const TypeLong* TypeLong::make_unsigned(julong ulo, julong uhi, int widen) { + assert(ulo <= uhi, "must be legal bounds"); + // By creating the TypeLong with the full signed range and the given unsigned range, the signed bounds are inferred from the unsigned bounds. + return make_or_top(TypeIntPrototype{{min_jlong, max_jlong}, {ulo, uhi}, {0, 0}}, widen)->is_long(); +} + const Type* TypeLong::make_or_top(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen, false); } diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 6eaa497e86d..06201113311 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -782,6 +782,7 @@ protected: public: typedef jint NativeType; + typedef juint NativeUType; virtual bool eq(const Type* t) const; virtual uint hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton @@ -795,6 +796,7 @@ public: static const TypeInt* make(jint con); // must always specify w static const TypeInt* make(jint lo, jint hi, int widen); + static const TypeInt* make_unsigned(juint ulo, juint uhi, int widen); static const Type* make_or_top(const TypeIntPrototype& t, int widen); static const TypeInt* make(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen)->is_int(); } static const TypeInt* make(const TypeIntMirror& t, int widen) { @@ -871,6 +873,7 @@ protected: virtual const Type* filter_helper(const Type* kills, bool include_speculative) const; public: typedef jlong NativeType; + typedef julong NativeUType; virtual bool eq( const Type *t ) const; virtual uint hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton @@ -885,6 +888,7 @@ public: static const TypeLong* make(jlong con); // must always specify w static const TypeLong* make(jlong lo, jlong hi, int widen); + static const TypeLong* make_unsigned(julong ulo, julong uhi, int widen); static const Type* make_or_top(const TypeIntPrototype& t, int widen); static const TypeLong* make(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen)->is_long(); } static const TypeLong* make(const TypeIntMirror& t, int widen) { diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index f5162c4bb2f..96b717fe56c 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -298,7 +298,7 @@ static bool is_klass_initialized(const TypeInstPtr* vec_klass) { } static bool is_primitive_lane_type(VectorSupport::LaneType laneType) { - return laneType >= VectorSupport::LT_FLOAT && laneType <= VectorSupport::LT_LONG; + return laneType >= VectorSupport::LT_FLOAT && laneType <= VectorSupport::LT_FLOAT16; } static BasicType get_vector_primitive_lane_type(VectorSupport::LaneType lanetype) { @@ -310,10 +310,15 @@ static BasicType get_vector_primitive_lane_type(VectorSupport::LaneType lanetype case VectorSupport::LaneType::LT_INT: return T_INT; case VectorSupport::LaneType::LT_SHORT: return T_SHORT; case VectorSupport::LaneType::LT_BYTE: return T_BYTE; + case VectorSupport::LaneType::LT_FLOAT16: return T_SHORT; } return T_ILLEGAL; } +static bool is_supported_lane_type(VectorSupport::LaneType laneType) { + return laneType >= VectorSupport::LT_FLOAT && laneType <= VectorSupport::LT_LONG; +} + // // , // M extends VectorMask, @@ -557,6 +562,11 @@ bool LibraryCallKit::inline_vector_call(int arity) { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); @@ -651,6 +661,11 @@ bool LibraryCallKit::inline_vector_mask_operation() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + int num_elem = vlen->get_con(); BasicType elem_bt = get_vector_primitive_lane_type(vltype); int mopc = VectorSupport::vop2ideal(oper->get_con(), vltype); @@ -721,6 +736,12 @@ bool LibraryCallKit::inline_vector_frombits_coerced() { return false; } + int bcast_mode = mode->get_con(); + if (!is_supported_lane_type(vltype) && bcast_mode != VectorSupport::MODE_BROADCAST) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; // should be primitive type + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -732,7 +753,6 @@ bool LibraryCallKit::inline_vector_frombits_coerced() { const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass); bool is_mask = is_vector_mask(vbox_klass); - int bcast_mode = mode->get_con(); VectorMaskUseType checkFlags = (VectorMaskUseType)(is_mask ? VecMaskUseAll : VecMaskNotUsed); int opc = bcast_mode == VectorSupport::MODE_BITS_COERCED_LONG_TO_MASK ? Op_VectorLongToMask : Op_Replicate; @@ -1296,6 +1316,11 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + BasicType elem_bt = get_vector_primitive_lane_type(vltype); int num_elem = vlen->get_con(); int idx_num_elem = idx_vlen->get_con(); @@ -1479,6 +1504,10 @@ bool LibraryCallKit::inline_vector_reduction() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } BasicType elem_bt = get_vector_primitive_lane_type(vltype); const Type* vmask_type = gvn().type(argument(6)); bool is_masked_op = vmask_type != TypePtr::NULL_PTR; @@ -1624,6 +1653,11 @@ bool LibraryCallKit::inline_vector_test() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -1773,6 +1807,11 @@ bool LibraryCallKit::inline_vector_compare() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass) || !is_klass_initialized(mask_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -1893,6 +1932,10 @@ bool LibraryCallKit::inline_vector_rearrange() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } BasicType elem_bt = get_vector_primitive_lane_type(vltype); BasicType shuffle_bt = elem_bt; if (shuffle_bt == T_FLOAT) { @@ -2029,6 +2072,10 @@ bool LibraryCallKit::inline_vector_select_from() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } int num_elem = vlen->get_con(); BasicType elem_bt = get_vector_primitive_lane_type(vltype); if (!is_power_of_2(num_elem)) { @@ -2193,6 +2240,11 @@ bool LibraryCallKit::inline_vector_broadcast_int() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + const Type* vmask_type = gvn().type(argument(7)); bool is_masked_op = vmask_type != TypePtr::NULL_PTR; if (is_masked_op) { @@ -2369,6 +2421,16 @@ bool LibraryCallKit::inline_vector_convert() { log_if_needed(" ** not a primitive to lt=%s", VectorSupport::lanetype2name(vltype_to)); return false; // should be primitive type } + + if (!is_supported_lane_type(vltype_from)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype_from)); + return false; + } + + if (!is_supported_lane_type(vltype_to)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype_to)); + return false; + } BasicType elem_bt_from = get_vector_primitive_lane_type(vltype_from); BasicType elem_bt_to = get_vector_primitive_lane_type(vltype_to); @@ -2550,6 +2612,11 @@ bool LibraryCallKit::inline_vector_insert() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -2638,6 +2705,11 @@ bool LibraryCallKit::inline_vector_extract() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -2822,6 +2894,11 @@ bool LibraryCallKit::inline_vector_select_from_two_vectors() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -2960,6 +3037,11 @@ bool LibraryCallKit::inline_vector_compress_expand() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + int num_elem = vlen->get_con(); BasicType elem_bt = get_vector_primitive_lane_type(vltype); int opc = VectorSupport::vop2ideal(opr->get_con(), vltype); @@ -3035,6 +3117,11 @@ bool LibraryCallKit::inline_index_vector() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(vector_klass)) { log_if_needed(" ** klass argument not initialized"); return false; @@ -3170,6 +3257,11 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { return false; } + if (!is_supported_lane_type(vltype)) { + log_if_needed(" ** unsupported lane type =%s", VectorSupport::lanetype2name(vltype)); + return false; + } + if (!is_klass_initialized(mask_klass)) { log_if_needed(" ** klass argument not initialized"); return false; diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index 5c6010acdf1..badfb8e9b82 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -206,9 +206,10 @@ const char* VectorSupport::lanetype2name(LaneType lane_type) { "byte", "short", "int", - "long" + "long", + "float16", }; - if (lane_type >= LT_FLOAT && lane_type <= LT_LONG) { + if (lane_type >= LT_FLOAT && lane_type <= LT_FLOAT16) { return lanetype2name[lane_type]; } assert(false, "unknown lane type: %d", (int)lane_type); @@ -224,6 +225,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: return Op_AddI; case LT_LONG: return Op_AddL; + case LT_FLOAT16: return Op_AddHF; case LT_FLOAT: return Op_AddF; case LT_DOUBLE: return Op_AddD; default: return 0; @@ -236,6 +238,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: return Op_SubI; case LT_LONG: return Op_SubL; + case LT_FLOAT16: return Op_SubHF; case LT_FLOAT: return Op_SubF; case LT_DOUBLE: return Op_SubD; default: return 0; @@ -248,6 +251,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: return Op_MulI; case LT_LONG: return Op_MulL; + case LT_FLOAT16: return Op_MulHF; case LT_FLOAT: return Op_MulF; case LT_DOUBLE: return Op_MulD; default: return 0; @@ -260,6 +264,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: return Op_DivI; case LT_LONG: return Op_DivL; + case LT_FLOAT16: return Op_DivHF; case LT_FLOAT: return Op_DivF; case LT_DOUBLE: return Op_DivD; default: return 0; @@ -272,6 +277,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: case LT_INT: return Op_MinI; case LT_LONG: return Op_MinL; + case LT_FLOAT16: return Op_MinHF; case LT_FLOAT: return Op_MinF; case LT_DOUBLE: return Op_MinD; default: return 0; @@ -284,6 +290,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: case LT_INT: return Op_MaxI; case LT_LONG: return Op_MaxL; + case LT_FLOAT16: return Op_MaxHF; case LT_FLOAT: return Op_MaxF; case LT_DOUBLE: return Op_MaxD; default: return 0; @@ -316,6 +323,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: return Op_AbsI; case LT_LONG: return Op_AbsL; + case LT_FLOAT16: return 0; case LT_FLOAT: return Op_AbsF; case LT_DOUBLE: return Op_AbsD; default: return 0; @@ -328,6 +336,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: return Op_NegI; case LT_LONG: return Op_NegL; + case LT_FLOAT16: return 0; case LT_FLOAT: return Op_NegF; case LT_DOUBLE: return Op_NegD; default: return 0; @@ -366,6 +375,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { } case VECTOR_OP_SQRT: { switch (lt) { + case LT_FLOAT16: return Op_SqrtHF; case LT_FLOAT: return Op_SqrtF; case LT_DOUBLE: return Op_SqrtD; default: return 0; @@ -374,6 +384,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { } case VECTOR_OP_FMA: { switch (lt) { + case LT_FLOAT16: return Op_FmaHF; case LT_FLOAT: return Op_FmaF; case LT_DOUBLE: return Op_FmaD; default: return 0; @@ -436,6 +447,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_VectorMaskLastTrue; default: return 0; @@ -448,6 +460,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_VectorMaskFirstTrue; default: return 0; @@ -460,6 +473,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_VectorMaskTrueCount; default: return 0; @@ -472,6 +486,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_VectorMaskToLong; default: return 0; @@ -484,6 +499,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_ExpandV; default: return 0; @@ -496,6 +512,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_CompressV; default: return 0; @@ -508,6 +525,7 @@ int VectorSupport::vop2ideal(jint id, LaneType lt) { case LT_SHORT: // fall-through case LT_INT: // fall-through case LT_LONG: // fall-through + case LT_FLOAT16: // fall-through case LT_FLOAT: // fall-through case LT_DOUBLE: return Op_CompressM; default: return 0; diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp index da3736b4711..f33c56a9b84 100644 --- a/src/hotspot/share/prims/vectorSupport.hpp +++ b/src/hotspot/share/prims/vectorSupport.hpp @@ -144,7 +144,8 @@ class VectorSupport : AllStatic { LT_BYTE = 2, LT_SHORT = 3, LT_INT = 4, - LT_LONG = 5 + LT_LONG = 5, + LT_FLOAT16 = 6 }; enum { diff --git a/src/hotspot/share/services/memoryPool.cpp b/src/hotspot/share/services/memoryPool.cpp index 41362181c6b..8361913862c 100644 --- a/src/hotspot/share/services/memoryPool.cpp +++ b/src/hotspot/share/services/memoryPool.cpp @@ -51,7 +51,6 @@ MemoryPool::MemoryPool(const char* name, _type(type), _initial_size(init_size), _max_size(max_size), - _available_for_allocation(true), _managers(), _num_managers(0), _peak_usage(), @@ -188,7 +187,7 @@ MemoryUsage CodeHeapPool::get_memory_usage() { size_t used = used_in_bytes(); OrderAccess::acquire(); // ensure possible cache expansion in CodeCache::allocate is seen size_t committed = _codeHeap->capacity(); - size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t maxSize = max_size(); return MemoryUsage(initial_size(), used, committed, maxSize); } diff --git a/src/hotspot/share/services/memoryPool.hpp b/src/hotspot/share/services/memoryPool.hpp index a55c593ebed..f0a4ba21659 100644 --- a/src/hotspot/share/services/memoryPool.hpp +++ b/src/hotspot/share/services/memoryPool.hpp @@ -61,7 +61,6 @@ class MemoryPool : public CHeapObj { PoolType _type; size_t _initial_size; size_t _max_size; - bool _available_for_allocation; // Default is true MemoryManager* _managers[max_num_managers]; int _num_managers; MemoryUsage _peak_usage; // Peak memory usage @@ -98,13 +97,6 @@ class MemoryPool : public CHeapObj { bool is_pool(instanceHandle pool) const; - bool available_for_allocation() { return _available_for_allocation; } - bool set_available_for_allocation(bool value) { - bool prev = _available_for_allocation; - _available_for_allocation = value; - return prev; - } - MemoryManager* get_memory_manager(int index) { assert(index >= 0 && index < _num_managers, "Invalid index"); return _managers[index]; diff --git a/src/java.base/share/classes/java/security/BinaryEncodable.java b/src/java.base/share/classes/java/security/BinaryEncodable.java index bd5d05ee4ec..a1713c413ba 100644 --- a/src/java.base/share/classes/java/security/BinaryEncodable.java +++ b/src/java.base/share/classes/java/security/BinaryEncodable.java @@ -32,15 +32,35 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import jdk.internal.javac.PreviewFeature; +import sun.security.internal.InternalBinaryEncodable; + /** - * This interface is implemented by security API classes that contain - * binary-encodable cryptographic material. + * This interface identifies the cryptographic objects that can be converted + * to and from binary data, and thereby encoded and decoded as PEM text. * - *

This sealed interface may evolve. When using {@code switch}, always include a - * {@code default} case rather than relying on the classes specified in the - * {@code permits} clause to remain fixed. An exhaustive {@code switch} may - * result in a {@link MatchException}. + *

The APIs for cryptographic objects such as public keys, private keys, + * certificates, and certificate revocation lists all provide the means to + * convert their instances to and from standardized binary representations. + * Other kinds of cryptographic objects, such as certificate requests, have + * no corresponding API but can still be expressed as standardized binary + * representations. The {@code BinaryEncodable} interface allows the + * {@link PEMEncoder} and {@link PEMDecoder} classes to operate uniformly on + * binary representations of key or certificate material. + * + *

The permitted subtype {@code PEM} is notable for supporting the encoding + * and decoding of PEM text that represents cryptographic objects for which no + * API exists. In future releases, other permitted subtypes may be added to + * support the encoding and decoding of such cryptographic objects. + * + *

The list of permitted subtypes shown after {@code permits} is not + * exhaustive. This means if application code switches over a + * {@code BinaryEncodable} value, the {@code switch} cannot be made exhaustive + * simply by providing a {@code case} label for every permitted subtype shown + * in the list; there also must be a {@code default} or + * {@code case BinaryEncodable} label to handle additional subtypes. This + * allows the list of permitted subtypes to change over time without causing + * pre-existing switches to fail because of an unrecognized subtype. * * @see AsymmetricKey * @see KeyPair @@ -57,5 +77,5 @@ import jdk.internal.javac.PreviewFeature; @PreviewFeature(feature = PreviewFeature.Feature.PEM_API) public sealed interface BinaryEncodable permits AsymmetricKey, KeyPair, PKCS8EncodedKeySpec, X509EncodedKeySpec, EncryptedPrivateKeyInfo, - X509Certificate, X509CRL, PEM { + X509Certificate, X509CRL, PEM, InternalBinaryEncodable { } diff --git a/src/java.base/share/classes/java/security/PEMDecoder.java b/src/java.base/share/classes/java/security/PEMDecoder.java index f5a6a70d0f5..8ebc83f93d1 100644 --- a/src/java.base/share/classes/java/security/PEMDecoder.java +++ b/src/java.base/share/classes/java/security/PEMDecoder.java @@ -48,10 +48,10 @@ import java.util.Objects; * PEM is a textual encoding used to store and transfer cryptographic * objects, such as asymmetric keys, certificates, and certificate revocation * lists (CRLs). It is defined in RFC 1421 and RFC 7468. PEM consists of - * Base64-encoded content enclosed by a type-identifying header - * and footer. + * Base64-encoded content enclosed by a header and footer that identify the + * type of the content. * - *

The {@link #decode(String)} and {@link #decode(InputStream)} methods + *

The {@link #decode(String)} and {@link #decode(InputStream)} methods * return an instance of a class that matches the PEM type and implements * {@link BinaryEncodable}, as follows: *

    @@ -70,11 +70,18 @@ import java.util.Objects; *
* *

If the PEM type has no corresponding class, {@code decode(String)} and - * {@code decode(InputStream)} will return a {@code PEM} object. + * {@code decode(InputStream)} return a {@code PEM} object. + * + *

If application code switches over the {@code BinaryEncodable} result of + * {@link #decode(String)} or {@link #decode(InputStream)}, the {@code switch} cannot + * be made exhaustive simply by providing a {@code case} label for every permitted + * subtype listed for {@code BinaryEncodable}; there also must be a {@code default} + * or {@code case BinaryEncodable} label to handle additional subtypes that + * might be added in the future. * *

The {@link #decode(String, Class)} and {@link #decode(InputStream, Class)} - * methods accept a class parameter specifying the desired {@code BinaryEncodable} - * type. These methods avoid the need for casting and are useful when multiple + * methods accept a parameter specifying the desired {@code BinaryEncodable} + * result. These methods avoid the need for casting and are useful when multiple * representations are possible. For example, if the PEM contains both public and * private keys, specifying {@code PrivateKey.class} returns only the private key. * If {@code X509EncodedKeySpec.class} is provided, the public key encoding is @@ -109,11 +116,6 @@ import java.util.Objects; * for decryption, an {@link EncryptedPrivateKeyInfo} is returned. * A {@code PEMDecoder} configured for decryption can also decode unencrypted PEM. * - *

The {@code BinaryEncodable} interface may evolve. When using a decode method - * with {@code switch}, always include a {@code default} case rather than - * relying on the classes specified in the permits clause to remain fixed. - * An exhaustive {@code switch} may result in a {@link MatchException}. - * *

This class is immutable and thread-safe. * *

Example: decode a private key: @@ -136,6 +138,7 @@ import java.util.Objects; * @see PEMEncoder * @see PEM * @see EncryptedPrivateKeyInfo + * @see BinaryEncodable * * @spec https://www.rfc-editor.org/info/rfc1421 * RFC 1421: Privacy Enhancement for Internet Electronic Mail diff --git a/src/java.base/share/classes/java/text/ListFormat.java b/src/java.base/share/classes/java/text/ListFormat.java index 29e58ea717c..c610ace64d6 100644 --- a/src/java.base/share/classes/java/text/ListFormat.java +++ b/src/java.base/share/classes/java/text/ListFormat.java @@ -498,15 +498,18 @@ public final class ListFormat extends Format { midIndex += mbLength; } } - parsed = new MessageFormat(createMessageFormatString(count), locale).parseObject(source, parsePos); + parsed = new MessageFormat(listToMessageFormatPattern(createMessageFormatString(count)), + locale).parseObject(source, parsePos); } } if (parsed == null) { // now try exact number patterns - parsed = new MessageFormat(patterns[TWO], locale).parseObject(source, parsePos); + parsed = new MessageFormat(listToMessageFormatPattern(patterns[TWO]), + locale).parseObject(source, parsePos); if (parsed == null) { - parsed = new MessageFormat(patterns[THREE], locale).parseObject(source, parsePos); + parsed = new MessageFormat(listToMessageFormatPattern(patterns[THREE]), + locale).parseObject(source, parsePos); } } @@ -584,9 +587,9 @@ public final class ListFormat extends Format { var len = input.length; return switch (len) { case 0 -> throw new IllegalArgumentException("There should at least be one input string"); - case 1 -> new MessageFormat("{0}", locale); - case 2, 3 -> new MessageFormat(patterns[len + 1], locale); - default -> new MessageFormat(createMessageFormatString(len), locale); + case 1 -> new MessageFormat(listToMessageFormatPattern("{0}"), locale); + case 2, 3 -> new MessageFormat(listToMessageFormatPattern(patterns[len + 1]), locale); + default -> new MessageFormat(listToMessageFormatPattern(createMessageFormatString(len)), locale); }; } @@ -742,4 +745,18 @@ public final class ListFormat extends Format { return prefixPos < suffixPos ? new int[] {prefixPos, suffixPos + suffix.length()} : null; } + + /** + * {@return the MessageFormat pattern corresponding to the passed ListFormat pattern} + * + * Single quotes must be escaped so they are interpreted as literal text + * as opposed to escaping delimiters when passed to MessageFormat. Everything + * else remains the same; ListFormat already handles other validation on its own. + * + * @param pattern list pattern to use + */ + private static String listToMessageFormatPattern(String pattern) { + return pattern.indexOf('\'') < 0 ? pattern : + pattern.replace("'", "''"); + } } diff --git a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java index 23a787971c0..07da636e781 100644 --- a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java @@ -156,7 +156,8 @@ public class VectorSupport { LT_BYTE = 2, LT_SHORT = 3, LT_INT = 4, - LT_LONG = 5; + LT_LONG = 5, + LT_FLOAT16 = 6; /* ============================================================================ */ diff --git a/src/java.base/share/classes/sun/security/internal/InternalBinaryEncodable.java b/src/java.base/share/classes/sun/security/internal/InternalBinaryEncodable.java new file mode 100644 index 00000000000..72d0008a505 --- /dev/null +++ b/src/java.base/share/classes/sun/security/internal/InternalBinaryEncodable.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.internal; + +import java.security.BinaryEncodable; + +/** + * This class is a non-public subtype of BinaryEncodable. This type + * allows the BinaryEncodable list of permitted subtypes to change + * over time without causing pre-existing switches to fail because of an + * unrecognized subtype. + */ + +public final class InternalBinaryEncodable implements BinaryEncodable { + private InternalBinaryEncodable() {} +} diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java index af0b8909d30..45882a79fd7 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.locks.ReentrantLock; -import java.util.zip.Adler32; +import java.util.zip.CRC32C; import javax.crypto.KDF; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; @@ -610,9 +610,9 @@ final class SSLSessionImpl extends ExtendedSSLSession { } private static int getChecksum(byte[] input) { - Adler32 adler32 = new Adler32(); - adler32.update(input); - return (int) adler32.getValue(); + CRC32C crc32c = new CRC32C(); + crc32c.update(input); + return (int) crc32c.getValue(); } void setMasterSecret(SecretKey secret) { diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c index 2f163cf27f1..bc2ed500d60 100644 --- a/src/java.base/unix/native/libjava/TimeZone_md.c +++ b/src/java.base/unix/native/libjava/TimeZone_md.c @@ -352,33 +352,15 @@ getPlatformTimeZoneID() } static char * -mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { +getJavaTimezoneFromPlatform(const char *tz_buf, size_t tz_len, const char *mapfilename) { FILE *tzmapf; - char mapfilename[PATH_MAX + 1]; char line[256]; int linecount = 0; - char *tz_buf = NULL; - char *temp_tz = NULL; char *javatz = NULL; - size_t tz_len = 0; - /* On AIX, the TZ environment variable may end with a comma - * followed by modifier fields until early AIX6.1. - * This restriction has been removed from AIX7. */ - - tz_buf = strdup(tz); - tz_len = strlen(tz_buf); - - /* Open tzmappings file, with buffer overrun check */ - if ((strlen(java_home_dir) + 15) > PATH_MAX) { - jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); - goto tzerr; - } - strcpy(mapfilename, java_home_dir); - strcat(mapfilename, "/lib/tzmappings"); if ((tzmapf = fopen(mapfilename, "r")) == NULL) { jio_fprintf(stderr, "can't open %s\n", mapfilename); - goto tzerr; + return NULL; } while (fgets(line, sizeof(line), tzmapf) != NULL) { @@ -431,10 +413,58 @@ mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { break; } } + (void) fclose(tzmapf); + return javatz; +} + +static char * +mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { + char mapfilename[PATH_MAX + 1]; + char *tz_buf = NULL; + char *javatz = NULL; + char *temp_tz = NULL; + size_t tz_len = 0; + + /* On AIX, the TZ environment variable may end with a comma + * followed by modifier fields until early AIX6.1. + * This restriction has been removed from AIX7. */ + + tz_buf = strdup(tz); + if (tz_buf == NULL) { + jio_fprintf(stderr, "Failed to allocate timezone buffer\n"); + goto tzerr; + } + tz_len = strlen(tz_buf); + + /* Open tzmappings file, with buffer overrun check */ + if ((strlen(java_home_dir) + 15) > PATH_MAX) { + jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); + goto tzerr; + } + strcpy(mapfilename, java_home_dir); + strcat(mapfilename, "/lib/tzmappings"); + + // First attempt to find the Java timezone for the full tz string + javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); + + // If no match was found, check for timezone with truncated value + if (javatz == NULL) { + temp_tz = strchr(tz, ','); + tz_len = (temp_tz == NULL) ? strlen(tz) : temp_tz - tz; + free((void *) tz_buf); + tz_buf = (char *)malloc(tz_len + 1); + if (tz_buf == NULL) { + jio_fprintf(stderr, "Failed to allocate timezone buffer\n"); + goto tzerr; + } + memcpy(tz_buf, tz, tz_len); + tz_buf[tz_len] = '\0'; + javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); + } tzerr: - if (tz_buf != NULL ) { + if (tz_buf != NULL) { free((void *) tz_buf); } diff --git a/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java b/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java index 4c284bf29ba..6bec617b5ae 100644 --- a/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java +++ b/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,13 +32,13 @@ package java.awt.event; *

* Mouse motion events occur when a mouse is moved or dragged. * (Many such events will be generated in a normal program. - * To track clicks and other mouse events, use the MouseAdapter.) + * To track clicks and other mouse events, use the {@link MouseAdapter}.) *

* Extend this class to create a {@code MouseEvent} listener * and override the methods for the events of interest. (If you implement the * {@code MouseMotionListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them - * all, so you can only have to define methods for events you care about.) + * all, so you have to define only methods for events you care about.) *

* Create a listener object using the extended class and then register it with * a component using the component's {@code addMouseMotionListener} @@ -61,17 +61,14 @@ public abstract class MouseMotionAdapter implements MouseMotionListener { protected MouseMotionAdapter() {} /** - * Invoked when a mouse button is pressed on a component and then - * dragged. Mouse drag events will continue to be delivered to - * the component where the first originated until the mouse button is - * released (regardless of whether the mouse position is within the - * bounds of the component). + * {@inheritDoc} */ + @Override public void mouseDragged(MouseEvent e) {} /** - * Invoked when the mouse button has been moved on a component - * (with no buttons no down). + * {@inheritDoc} */ + @Override public void mouseMoved(MouseEvent e) {} } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java index 9ac90c08c27..9fac32da26d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractMask.java @@ -36,7 +36,9 @@ abstract sealed class AbstractMask extends VectorMask FloatVector64.FloatMask64, FloatVector128.FloatMask128, FloatVector256.FloatMask256, FloatVector512.FloatMask512, FloatVectorMax.FloatMaskMax, IntVector64.IntMask64, IntVector128.IntMask128, IntVector256.IntMask256, IntVector512.IntMask512, IntVectorMax.IntMaskMax, LongVector64.LongMask64, LongVector128.LongMask128, LongVector256.LongMask256, LongVector512.LongMask512, LongVectorMax.LongMaskMax, - ShortVector64.ShortMask64, ShortVector128.ShortMask128, ShortVector256.ShortMask256, ShortVector512.ShortMask512, ShortVectorMax.ShortMaskMax { + ShortVector64.ShortMask64, ShortVector128.ShortMask128, ShortVector256.ShortMask256, ShortVector512.ShortMask512, ShortVectorMax.ShortMaskMax, + Float16Vector64.Float16Mask64, Float16Vector128.Float16Mask128, Float16Vector256.Float16Mask256, Float16Vector512.Float16Mask512, + Float16VectorMax.Float16MaskMax { AbstractMask(boolean[] bits) { super(bits); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java index bea495f74fc..8c22329a833 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractShuffle.java @@ -35,7 +35,8 @@ abstract sealed class AbstractShuffle extends VectorShuffle FloatVector64.FloatShuffle64, FloatVector128.FloatShuffle128, FloatVector256.FloatShuffle256, FloatVector512.FloatShuffle512, FloatVectorMax.FloatShuffleMax, IntVector64.IntShuffle64, IntVector128.IntShuffle128, IntVector256.IntShuffle256, IntVector512.IntShuffle512, IntVectorMax.IntShuffleMax, LongVector64.LongShuffle64, LongVector128.LongShuffle128, LongVector256.LongShuffle256, LongVector512.LongShuffle512, LongVectorMax.LongShuffleMax, - ShortVector64.ShortShuffle64, ShortVector128.ShortShuffle128, ShortVector256.ShortShuffle256, ShortVector512.ShortShuffle512, ShortVectorMax.ShortShuffleMax { + ShortVector64.ShortShuffle64, ShortVector128.ShortShuffle128, ShortVector256.ShortShuffle256, ShortVector512.ShortShuffle512, ShortVectorMax.ShortShuffleMax, + Float16Vector64.Float16Shuffle64, Float16Vector128.Float16Shuffle128, Float16Vector256.Float16Shuffle256, Float16Vector512.Float16Shuffle512, Float16VectorMax.Float16ShuffleMax { static final IntUnaryOperator IDENTITY = i -> i; // Internal representation allows for a maximum index of E.MAX_VALUE - 1 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java index 3fd2be34346..fa338f27975 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractSpecies.java @@ -37,7 +37,7 @@ import jdk.internal.vm.annotation.TrustFinalFields; abstract sealed class AbstractSpecies extends jdk.internal.vm.vector.VectorSupport.VectorSpecies implements VectorSpecies permits ByteVector.ByteSpecies, DoubleVector.DoubleSpecies, FloatVector.FloatSpecies, - IntVector.IntSpecies, LongVector.LongSpecies, ShortVector.ShortSpecies { + IntVector.IntSpecies, LongVector.LongSpecies, ShortVector.ShortSpecies, Float16Vector.Float16Species { final VectorShape vectorShape; final LaneType laneType; final int laneCount; @@ -424,14 +424,21 @@ abstract sealed class AbstractSpecies extends jdk.internal.vm.vector.VectorSu Object ia = Array.newInstance(carrierType(), laneCount); assert(ia.getClass() == laneType.arrayType); checkValue(laneCount-1); // worst case - for (int i = 0; i < laneCount; i++) { - if ((byte)i == i) - Array.setByte(ia, i, (byte)i); - else if ((short)i == i) - Array.setShort(ia, i, (short)i); - else - Array.setInt(ia, i, i); - assert(Array.getDouble(ia, i) == i); + if (elementType() == Float16.class) { + for (int i = 0; i < laneCount; i++) { + Array.setShort(ia, i, Float.floatToFloat16((float)i)); + assert(Float16.shortBitsToFloat16(Array.getShort(ia, i)).intValue() == i); + } + } else { + for (int i = 0; i < laneCount; i++) { + if ((byte)i == i) + Array.setByte(ia, i, (byte)i); + else if ((short)i == i) + Array.setShort(ia, i, (short)i); + else + Array.setInt(ia, i, i); + assert(Array.getDouble(ia, i) == i); + } } return ia; } @@ -629,6 +636,8 @@ abstract sealed class AbstractSpecies extends jdk.internal.vm.vector.VectorSu s = IntVector.species(shape); break; case LaneType.SK_LONG: s = LongVector.species(shape); break; + case LaneType.SK_FLOAT16: + s = Float16Vector.species(shape); break; } if (s == null) { // NOTE: The result of this method is guaranteed to be diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java index 4efd0d24af9..cf6602573a8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java @@ -35,7 +35,7 @@ import static jdk.incubator.vector.VectorOperators.*; @SuppressWarnings("cast") abstract sealed class AbstractVector extends Vector - permits ByteVector, DoubleVector, FloatVector, IntVector, LongVector, ShortVector { + permits ByteVector, DoubleVector, FloatVector, IntVector, LongVector, ShortVector, Float16Vector { /** * The order of vector bytes when stored in natural, * array elements of the same lane type. @@ -331,6 +331,15 @@ abstract sealed class AbstractVector extends Vector return (DoubleVector) asVectorRaw(LaneType.DOUBLE); } + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public Float16Vector reinterpretAsFloat16s() { + return (Float16Vector) asVectorRaw(LaneType.FLOAT16); + } + /** * {@inheritDoc} */ @@ -682,6 +691,8 @@ abstract sealed class AbstractVector extends Vector return FloatVector.fromMemorySegment(rsp.check(float.class), ms, 0, bo, m.check(float.class)).check0(rsp); case LaneType.SK_DOUBLE: return DoubleVector.fromMemorySegment(rsp.check(double.class), ms, 0, bo, m.check(double.class)).check0(rsp); + case LaneType.SK_FLOAT16: + return Float16Vector.fromMemorySegment(rsp.check(Float16.class), ms, 0, bo, m.check(Float16.class)).check0(rsp); default: throw new AssertionError(rsp.toString()); } @@ -744,6 +755,13 @@ abstract sealed class AbstractVector extends Vector } return DoubleVector.fromArray(dsp.check(double.class), a, 0).check0(dsp); } + case LaneType.SK_FLOAT16: { + short[] a = new short[rlength]; + for (int i = 0; i < limit; i++) { + a[i] = Float16.float16ToRawShortBits(Float16.valueOf((float) lanes[i])); + } + return Float16Vector.fromArray(dsp.check(Float16.class), a, 0).check0(dsp); + } default: break; } } else { @@ -794,6 +812,13 @@ abstract sealed class AbstractVector extends Vector } return DoubleVector.fromArray(dsp.check(double.class), a, 0).check0(dsp); } + case LaneType.SK_FLOAT16: { + short[] a = new short[rlength]; + for (int i = 0; i < limit; i++) { + a[i] = Float16.float16ToRawShortBits(Float16.valueOf((float) lanes[i])); + } + return Float16Vector.fromArray(dsp.check(Float16.class), a, 0).check0(dsp); + } default: break; } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java new file mode 100644 index 00000000000..cf7eae5dd6a --- /dev/null +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector.java @@ -0,0 +1,4085 @@ +/* + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.vector; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Function; + +import jdk.internal.foreign.AbstractMemorySegmentImpl; +import jdk.internal.misc.ScopedMemoryAccess; +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.vector.VectorSupport; + +import static jdk.internal.vm.vector.VectorSupport.*; +import static jdk.incubator.vector.VectorIntrinsics.*; + +import static jdk.incubator.vector.VectorOperators.*; +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import static java.lang.Float.*; + +// -- This file was mechanically generated: Do not edit! -- // + +/** + * A specialized {@link Vector} representing an ordered immutable sequence of + * 16-bit data values in the IEEE 754 binary16 format. + *

+ * The scalar {@linkplain Float16Vector#elementType() element type} of {@code Float16Vector} + * is the class {@link Float16}, a value-based + * class holding 16-bit data in IEEE 754 binary16 format. However, the {@code Float16} + * class is not used by vector operations that accept scalar element values, or + * arrays of scalar element values. Instead, the primitive type {@code short} is + * used to explicitly hold 16-bit data in IEEE 754 binary16 format. For such operations + * it may be necessary to explicitly convert between floating-point values of {@code Float16} + * or {@code float} and values of {@code short} using the appropriate conversion + * methods on {@code Float16} or {@code Float}. + * + *

+ * The specifications for operations on elements of this class are written as if + * {@code Float16} is a primitive floating-point type. An operation referencing a + * Java operator is mapped to a method on {@code Float16} that specifies that + * operator's semantics. For example, the semantics of the {@code +} operator, + * as referenced by {@link Vector#add(Vector)} and {@link VectorOperators#ADD}, + * is mapped to the method {@link Float16#add(Float16, Float16)}. + * An operation referencing a method on {@link Math} is mapped to a method of the + * same name on {@code Float16}, if it exists. For example, {@link Math#fma} is + * mapped to {@link Float16#fma}, as referenced by {@link Float16Vector#fma(short, short)} + * and {@link VectorOperators#FMA}. + * Otherwise, if there is no equivalent method on {@code Float16}, the expression that is + * an invocation of a method on {@code Math} is mapped to an expression that converts + * the {@code Float16} arguments to {@code double} values or {@code float} values as + * required by the method's parameter types, invokes the method on {@code Math} with + * the converted values, and converts the resulting {@code double} or {@code float} value + * to a {@code Float16} value. For example, {@link Math#sin} is mapped to the expression + * {@code Float16.valueOf(Math.sin(a.doubleValue()))}, where {@code a} is the + * {@code Float16} lane value, as referenced by {@link VectorOperators#SIN}. + * + * @apiNote + * {@code Float16} is currently a value-based class and therefore cannot be optimally + * used as the scalar element type of vector operations until it becomes a value class + * that behaves similarly to the primitive type {@code short} and to arrays of {@code short}. + * For example, accessing {@code Float16} vectors using arrays requires those arrays be + * {@code short[]} arrays. Accessing vectors using memory segments requires, naturally, + * that consecutive 16-bits of memory hold 16-bit data values in the IEEE 754 binary16 + * format. + * @see Float16 + * @see Float16#float16ToRawShortBits(Float16) + * @see Float16#shortBitsToFloat16(short) + * @see Float#floatToFloat16(float) + * @see Float#float16ToFloat(short) + */ +@SuppressWarnings("cast") // warning: redundant cast +public abstract sealed class Float16Vector extends AbstractVector + permits Float16Vector64, Float16Vector128, Float16Vector256, Float16Vector512, Float16VectorMax { + + Float16Vector(short[] vec) { + super(vec); + } + + static final int FORBID_OPCODE_KIND = VO_NOFP; + + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); + + static final int LANE_TYPE_ORDINAL = LT_FLOAT16; + + static final int LANEBITS_TYPE_ORDINAL = LT_SHORT; + + @ForceInline + static int opCode(Operator op) { + return VectorOperators.opCode(op, VO_OPCODE_VALID, FORBID_OPCODE_KIND); + } + @ForceInline + static int opCode(Operator op, int requireKind) { + requireKind |= VO_OPCODE_VALID; + return VectorOperators.opCode(op, requireKind, FORBID_OPCODE_KIND); + } + @ForceInline + static boolean opKind(Operator op, int bit) { + return VectorOperators.opKind(op, bit); + } + + // Virtualized factories and operators, + // coded with portable definitions. + // These are all @ForceInline in case + // they need to be used performantly. + // The various shape-specific subclasses + // also specialize them by wrapping + // them in a call like this: + // return (ByteVector128) + // super.bOp((ByteVector128) o); + // The purpose of that is to forcibly inline + // the generic definition from this file + // into a sharply-typed and size-specific + // wrapper in the subclass file, so that + // the JIT can specialize the code. + // The code is only inlined and expanded + // if it gets hot. Think of it as a cheap + // and lazy version of C++ templates. + + // Virtualized getter + + /*package-private*/ + abstract short[] vec(); + + // Virtualized constructors + + /** + * Build a vector directly using my own constructor. + * It is an error if the array is aliased elsewhere. + */ + /*package-private*/ + abstract Float16Vector vectorFactory(short[] vec); + + /** + * Build a mask directly using my species. + * It is an error if the array is aliased elsewhere. + */ + /*package-private*/ + @ForceInline + final + AbstractMask maskFactory(boolean[] bits) { + return vspecies().maskFactory(bits); + } + + // Constant loader (takes dummy as vector arg) + interface FVOp { + short apply(int i); + } + + /*package-private*/ + @ForceInline + final + Float16Vector vOp(FVOp f) { + short[] res = new short[length()]; + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i); + } + return vectorFactory(res); + } + + @ForceInline + final + Float16Vector vOp(VectorMask m, FVOp f) { + short[] res = new short[length()]; + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + if (mbits[i]) { + res[i] = f.apply(i); + } + } + return vectorFactory(res); + } + + // Unary operator + + /*package-private*/ + interface FUnOp { + float apply(int i, float a); + } + + /*package-private*/ + abstract + Float16Vector uOp(FUnOp f); + @ForceInline + final + Float16Vector uOpTemplate(FUnOp f) { + short[] vec = vec(); + short[] res = new short[length()]; + for (int i = 0; i < res.length; i++) { + res[i] = floatToFloat16(f.apply(i, float16ToFloat(vec[i]))); + } + return vectorFactory(res); + } + + /*package-private*/ + abstract + Float16Vector uOp(VectorMask m, + FUnOp f); + @ForceInline + final + Float16Vector uOpTemplate(VectorMask m, + FUnOp f) { + if (m == null) { + return uOpTemplate(f); + } + short[] vec = vec(); + short[] res = new short[length()]; + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = mbits[i] ? floatToFloat16(f.apply(i, float16ToFloat(vec[i]))) : vec[i]; + } + return vectorFactory(res); + } + + /*package-private*/ + interface FUnRawOp { + short apply(int i, short a); + } + + /*package-private*/ + abstract + Float16Vector uRawOp(FUnRawOp f); + @ForceInline + final + Float16Vector uRawOpTemplate(FUnRawOp f) { + short[] vec = vec(); + short[] res = new short[length()]; + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, vec[i]); + } + return vectorFactory(res); + } + + /*package-private*/ + abstract + Float16Vector uRawOp(VectorMask m, + FUnRawOp f); + @ForceInline + final + Float16Vector uRawOpTemplate(VectorMask m, + FUnRawOp f) { + if (m == null) { + return uRawOpTemplate(f); + } + short[] vec = vec(); + short[] res = new short[length()]; + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i]; + } + return vectorFactory(res); + } + // Binary operator + + /*package-private*/ + interface FBinOp { + float apply(int i, float a, float b); + } + + /*package-private*/ + abstract + Float16Vector bOp(Vector o, + FBinOp f); + @ForceInline + final + Float16Vector bOpTemplate(Vector o, + FBinOp f) { + short[] res = new short[length()]; + short[] vec1 = this.vec(); + short[] vec2 = ((Float16Vector)o).vec(); + for (int i = 0; i < res.length; i++) { + res[i] = floatToFloat16(f.apply(i, float16ToFloat(vec1[i]), float16ToFloat(vec2[i]))); + } + return vectorFactory(res); + } + + /*package-private*/ + abstract + Float16Vector bOp(Vector o, + VectorMask m, + FBinOp f); + @ForceInline + final + Float16Vector bOpTemplate(Vector o, + VectorMask m, + FBinOp f) { + if (m == null) { + return bOpTemplate(o, f); + } + short[] res = new short[length()]; + short[] vec1 = this.vec(); + short[] vec2 = ((Float16Vector)o).vec(); + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = mbits[i] ? floatToFloat16(f.apply(i, float16ToFloat(vec1[i]), float16ToFloat(vec2[i]))) : vec1[i]; + } + return vectorFactory(res); + } + + // Ternary operator + + /*package-private*/ + interface FTriOp { + short apply(int i, short a, short b, short c); + } + + /*package-private*/ + abstract + Float16Vector tOp(Vector o1, + Vector o2, + FTriOp f); + @ForceInline + final + Float16Vector tOpTemplate(Vector o1, + Vector o2, + FTriOp f) { + short[] res = new short[length()]; + short[] vec1 = this.vec(); + short[] vec2 = ((Float16Vector)o1).vec(); + short[] vec3 = ((Float16Vector)o2).vec(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, vec1[i], vec2[i], vec3[i]); + } + return vectorFactory(res); + } + + /*package-private*/ + abstract + Float16Vector tOp(Vector o1, + Vector o2, + VectorMask m, + FTriOp f); + @ForceInline + final + Float16Vector tOpTemplate(Vector o1, + Vector o2, + VectorMask m, + FTriOp f) { + if (m == null) { + return tOpTemplate(o1, o2, f); + } + short[] res = new short[length()]; + short[] vec1 = this.vec(); + short[] vec2 = ((Float16Vector)o1).vec(); + short[] vec3 = ((Float16Vector)o2).vec(); + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i], vec3[i]) : vec1[i]; + } + return vectorFactory(res); + } + + // Reduction operator + + /*package-private*/ + abstract + short rOp(short v, VectorMask m, FBinOp f); + + @ForceInline + final + short rOpTemplate(short v, VectorMask m, FBinOp f) { + if (m == null) { + return rOpTemplate(v, f); + } + short[] vec = vec(); + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < vec.length; i++) { + v = mbits[i] ? floatToFloat16(f.apply(i, float16ToFloat(v), float16ToFloat(vec[i]))) : v; + } + return v; + } + + @ForceInline + final + short rOpTemplate(short v, FBinOp f) { + short[] vec = vec(); + for (int i = 0; i < vec.length; i++) { + v = floatToFloat16(f.apply(i, float16ToFloat(v), float16ToFloat(vec[i]))); + } + return v; + } + + // Memory reference + + /*package-private*/ + interface FLdOp { + short apply(M memory, int offset, int i); + } + + /*package-private*/ + @ForceInline + final + Float16Vector ldOp(M memory, int offset, + FLdOp f) { + //dummy; no vec = vec(); + short[] res = new short[length()]; + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(memory, offset, i); + } + return vectorFactory(res); + } + + /*package-private*/ + @ForceInline + final + Float16Vector ldOp(M memory, int offset, + VectorMask m, + FLdOp f) { + //short[] vec = vec(); + short[] res = new short[length()]; + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + if (mbits[i]) { + res[i] = f.apply(memory, offset, i); + } + } + return vectorFactory(res); + } + + /*package-private*/ + interface FLdLongOp { + short apply(MemorySegment memory, long offset, int i); + } + + /*package-private*/ + @ForceInline + final + Float16Vector ldLongOp(MemorySegment memory, long offset, + FLdLongOp f) { + //dummy; no vec = vec(); + short[] res = new short[length()]; + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(memory, offset, i); + } + return vectorFactory(res); + } + + /*package-private*/ + @ForceInline + final + Float16Vector ldLongOp(MemorySegment memory, long offset, + VectorMask m, + FLdLongOp f) { + //short[] vec = vec(); + short[] res = new short[length()]; + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + if (mbits[i]) { + res[i] = f.apply(memory, offset, i); + } + } + return vectorFactory(res); + } + + static short memorySegmentGet(MemorySegment ms, long o, int i) { + return ms.get(ELEMENT_LAYOUT, o + i * 2L); + } + + interface FStOp { + void apply(M memory, int offset, int i, short a); + } + + /*package-private*/ + @ForceInline + final + void stOp(M memory, int offset, + FStOp f) { + short[] vec = vec(); + for (int i = 0; i < vec.length; i++) { + f.apply(memory, offset, i, vec[i]); + } + } + + /*package-private*/ + @ForceInline + final + void stOp(M memory, int offset, + VectorMask m, + FStOp f) { + short[] vec = vec(); + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < vec.length; i++) { + if (mbits[i]) { + f.apply(memory, offset, i, vec[i]); + } + } + } + + interface FStLongOp { + void apply(MemorySegment memory, long offset, int i, short a); + } + + /*package-private*/ + @ForceInline + final + void stLongOp(MemorySegment memory, long offset, + FStLongOp f) { + short[] vec = vec(); + for (int i = 0; i < vec.length; i++) { + f.apply(memory, offset, i, vec[i]); + } + } + + /*package-private*/ + @ForceInline + final + void stLongOp(MemorySegment memory, long offset, + VectorMask m, + FStLongOp f) { + short[] vec = vec(); + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < vec.length; i++) { + if (mbits[i]) { + f.apply(memory, offset, i, vec[i]); + } + } + } + + static void memorySegmentSet(MemorySegment ms, long o, int i, short e) { + ms.set(ELEMENT_LAYOUT, o + i * 2L, e); + } + + // Binary test + + /*package-private*/ + interface FBinTest { + boolean apply(int cond, int i, short a, short b); + } + + /*package-private*/ + @ForceInline + final + AbstractMask bTest(int cond, + Vector o, + FBinTest f) { + short[] vec1 = vec(); + short[] vec2 = ((Float16Vector)o).vec(); + boolean[] bits = new boolean[length()]; + for (int i = 0; i < length(); i++){ + bits[i] = f.apply(cond, i, vec1[i], vec2[i]); + } + return maskFactory(bits); + } + + + /*package-private*/ + @Override + abstract Float16Species vspecies(); + + /*package-private*/ + @ForceInline + static long toBits(short e) { + return e; + } + + /*package-private*/ + @ForceInline + static short fromBits(long bits) { + return (short)bits; + } + + static Float16Vector expandHelper(Vector v, VectorMask m) { + VectorSpecies vsp = m.vectorSpecies(); + Float16Vector r = (Float16Vector) vsp.zero(); + Float16Vector vi = (Float16Vector) v; + if (m.allTrue()) { + return vi; + } + for (int i = 0, j = 0; i < vsp.length(); i++) { + if (m.laneIsSet(i)) { + r = r.withLane(i, vi.lane(j++)); + } + } + return r; + } + + static Float16Vector compressHelper(Vector v, VectorMask m) { + VectorSpecies vsp = m.vectorSpecies(); + Float16Vector r = (Float16Vector) vsp.zero(); + Float16Vector vi = (Float16Vector) v; + if (m.allTrue()) { + return vi; + } + for (int i = 0, j = 0; i < vsp.length(); i++) { + if (m.laneIsSet(i)) { + r = r.withLane(j++, vi.lane(i)); + } + } + return r; + } + + static Float16Vector selectFromTwoVectorHelper(Vector indexes, Vector src1, Vector src2) { + int vlen = indexes.length(); + short[] res = new short[vlen]; + short[] vecPayload1 = ((Float16Vector)indexes).vec(); + short[] vecPayload2 = ((Float16Vector)src1).vec(); + short[] vecPayload3 = ((Float16Vector)src2).vec(); + for (int i = 0; i < vlen; i++) { + int index = shortBitsToFloat16(vecPayload1[i]).intValue(); + int wrapped_index = VectorIntrinsics.wrapToRange(index, 2 * vlen); + res[i] = wrapped_index >= vlen ? vecPayload3[wrapped_index - vlen] : vecPayload2[wrapped_index]; + } + return ((Float16Vector)src1).vectorFactory(res); + } + + // Static factories (other than memory operations) + + // Note: A surprising behavior in javadoc + // sometimes makes a lone /** {@inheritDoc} */ + // comment drop the method altogether, + // apparently if the method mentions a + // parameter or return type of Vector + // instead of Vector as originally specified. + // Adding an empty HTML fragment appears to + // nudge javadoc into providing the desired + // inherited documentation. We use the HTML + // comment for this. + + /** + * Returns a vector of the given species + * where all lane elements are set to + * zero, the default primitive value. + * + * @param species species of the desired zero vector + * @return a zero vector + */ + @ForceInline + public static Float16Vector zero(VectorSpecies species) { + Float16Species vsp = (Float16Species) species; + return VectorSupport.fromBitsCoerced(vsp.vectorType(), LANE_TYPE_ORDINAL, species.length(), + toBits((short) 0), MODE_BROADCAST, vsp, + ((bits_, s_) -> s_.rvOp(i -> bits_))); + } + + /** + * Returns a vector of the same species as this one + * where all lane elements are set to + * the primitive value {@code e}. + * + * The contents of the current vector are discarded; + * only the species is relevant to this operation. + * + *

This method returns the value of this expression: + * {@code Float16Vector.broadcast(this.species(), e)}. + * + * @apiNote + * Unlike the similar method named {@code broadcast()} + * in the supertype {@code Vector}, this method does not + * need to validate its argument, and cannot throw + * {@code IllegalArgumentException}. This method is + * therefore preferable to the supertype method. + * + * @param e the value to broadcast + * @return a vector where all lane elements are set to + * the primitive value {@code e} + * @see #broadcast(VectorSpecies,long) + * @see Vector#broadcast(long) + * @see VectorSpecies#broadcast(long) + */ + public abstract Float16Vector broadcast(short e); + + /** + * Returns a vector of the given species + * where all lane elements are set to + * the primitive value {@code e}. + * + * @param species species of the desired vector + * @param e the value to broadcast + * @return a vector where all lane elements are set to + * the primitive value {@code e} + * @see #broadcast(long) + * @see Vector#broadcast(long) + * @see VectorSpecies#broadcast(long) + */ + @ForceInline + public static Float16Vector broadcast(VectorSpecies species, short e) { + Float16Species vsp = (Float16Species) species; + return vsp.broadcast(e); + } + + /*package-private*/ + @ForceInline + final Float16Vector broadcastTemplate(short e) { + Float16Species vsp = vspecies(); + return vsp.broadcast(e); + } + + /** + * {@inheritDoc} + * @apiNote + * When working with vector subtypes like {@code Float16Vector}, + * {@linkplain #broadcast(short) the more strongly typed method} + * is typically selected. It can be explicitly selected + * using a cast: {@code v.broadcast((short)e)}. + * The two expressions will produce numerically identical results. + */ + @Override + public abstract Float16Vector broadcast(long e); + + /** + * Returns a vector of the given species + * where all lane elements are set to + * the primitive value {@code e}. + * + * The {@code long} value must be accurately representable + * by the {@code ETYPE} of the vector species, so that + * {@code e==(long)(ETYPE)e}. + * + * @param species species of the desired vector + * @param e the value to broadcast + * @return a vector where all lane elements are set to + * the primitive value {@code e} + * @throws IllegalArgumentException + * if the given {@code long} value cannot + * be represented by the vector's {@code ETYPE} + * @see #broadcast(VectorSpecies,short) + * @see VectorSpecies#checkValue(long) + */ + @ForceInline + public static Float16Vector broadcast(VectorSpecies species, long e) { + Float16Species vsp = (Float16Species) species; + return vsp.broadcast(e); + } + + /*package-private*/ + @ForceInline + final Float16Vector broadcastTemplate(long e) { + return vspecies().broadcast(e); + } + + // Unary lanewise support + + /** + * {@inheritDoc} + */ + public abstract + Float16Vector lanewise(VectorOperators.Unary op); + + @ForceInline + final + Float16Vector lanewiseTemplate(VectorOperators.Unary op) { + if (opKind(op, VO_SPECIAL)) { + if (op == ZOMO) { + return blend(broadcast(-1), compare(NE, 0)); + } + else if (opKind(op, VO_MATHLIB)) { + return unaryMathOp(op); + } + } + int opc = opCode(op); + return VectorSupport.unaryOp( + opc, getClass(), null, laneTypeOrdinal(), length(), + this, null, + UN_IMPL.find(op, opc, Float16Vector::unaryOperations)); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector lanewise(VectorOperators.Unary op, + VectorMask m); + @ForceInline + final + Float16Vector lanewiseTemplate(VectorOperators.Unary op, + Class> maskClass, + VectorMask m) { + m.check(maskClass, this); + if (opKind(op, VO_SPECIAL)) { + if (op == ZOMO) { + return blend(broadcast(-1), compare(NE, 0, m)); + } + else if (opKind(op, VO_MATHLIB)) { + return blend(unaryMathOp(op), m); + } + } + int opc = opCode(op); + return VectorSupport.unaryOp( + opc, getClass(), maskClass, laneTypeOrdinal(), length(), + this, m, + UN_IMPL.find(op, opc, Float16Vector::unaryOperations)); + } + + @ForceInline + final + Float16Vector unaryMathOp(VectorOperators.Unary op) { + return VectorMathLibrary.unaryMathOp(op, opCode(op), vspecies(), Float16Vector::unaryOperations, + this); + } + + private static final + ImplCache>> + UN_IMPL = new ImplCache<>(Unary.class, Float16Vector.class); + + private static UnaryOperation> unaryOperations(int opc_) { + switch (opc_) { + case VECTOR_OP_NEG: return (v0, m) -> + v0.uOp(m, (i, a) -> Float16.negate(Float16.valueOf(a)).floatValue()); + case VECTOR_OP_ABS: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.abs(a)); + case VECTOR_OP_SIN: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.sin(a)); + case VECTOR_OP_COS: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.cos(a)); + case VECTOR_OP_TAN: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.tan(a)); + case VECTOR_OP_ASIN: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.asin(a)); + case VECTOR_OP_ACOS: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.acos(a)); + case VECTOR_OP_ATAN: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.atan(a)); + case VECTOR_OP_EXP: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.exp(a)); + case VECTOR_OP_LOG: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.log(a)); + case VECTOR_OP_LOG10: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.log10(a)); + case VECTOR_OP_SQRT: return (v0, m) -> + v0.uOp(m, (i, a) -> Float16.sqrt(Float16.valueOf(a)).floatValue()); + case VECTOR_OP_CBRT: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.cbrt(a)); + case VECTOR_OP_SINH: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.sinh(a)); + case VECTOR_OP_COSH: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.cosh(a)); + case VECTOR_OP_TANH: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.tanh(a)); + case VECTOR_OP_EXPM1: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.expm1(a)); + case VECTOR_OP_LOG1P: return (v0, m) -> + v0.uOp(m, (i, a) -> (float) Math.log1p(a)); + default: return null; + } + } + + // Binary lanewise support + + /** + * {@inheritDoc} + * @see #lanewise(VectorOperators.Binary,short) + * @see #lanewise(VectorOperators.Binary,short,VectorMask) + */ + @Override + public abstract + Float16Vector lanewise(VectorOperators.Binary op, + Vector v); + @ForceInline + final + Float16Vector lanewiseTemplate(VectorOperators.Binary op, + Vector v) { + Float16Vector that = (Float16Vector) v; + that.check(this); + + if (opKind(op, VO_SPECIAL )) { + if (op == FIRST_NONZERO) { + VectorMask mask + = this.viewAsIntegralLanes().compare(EQ, (short) 0); + return this.blend(that, mask.cast(vspecies())); + } + else if (opKind(op, VO_MATHLIB)) { + return binaryMathOp(op, that); + } + } + + int opc = opCode(op); + return VectorSupport.binaryOp( + opc, getClass(), null, laneTypeOrdinal(), length(), + this, that, null, + BIN_IMPL.find(op, opc, Float16Vector::binaryOperations)); + } + + /** + * {@inheritDoc} + * @see #lanewise(VectorOperators.Binary,short,VectorMask) + */ + @Override + public abstract + Float16Vector lanewise(VectorOperators.Binary op, + Vector v, + VectorMask m); + @ForceInline + final + Float16Vector lanewiseTemplate(VectorOperators.Binary op, + Class> maskClass, + Vector v, VectorMask m) { + Float16Vector that = (Float16Vector) v; + that.check(this); + m.check(maskClass, this); + + if (opKind(op, VO_SPECIAL )) { + if (op == FIRST_NONZERO) { + ShortVector bits = this.viewAsIntegralLanes(); + VectorMask mask + = bits.compare(EQ, (short) 0, m.cast(bits.vspecies())); + return this.blend(that, mask.cast(vspecies())); + } + else if (opKind(op, VO_MATHLIB)) { + return this.blend(binaryMathOp(op, that), m); + } + + } + + int opc = opCode(op); + return VectorSupport.binaryOp( + opc, getClass(), maskClass, laneTypeOrdinal(), length(), + this, that, m, + BIN_IMPL.find(op, opc, Float16Vector::binaryOperations)); + } + + @ForceInline + final + Float16Vector binaryMathOp(VectorOperators.Binary op, Float16Vector that) { + return VectorMathLibrary.binaryMathOp(op, opCode(op), vspecies(), Float16Vector::binaryOperations, + this, that); + } + + private static final + ImplCache>> + BIN_IMPL = new ImplCache<>(Binary.class, Float16Vector.class); + + private static BinaryOperation> binaryOperations(int opc_) { + switch (opc_) { + case VECTOR_OP_ADD: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float)(a + b)); + case VECTOR_OP_SUB: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float)(a - b)); + case VECTOR_OP_MUL: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float)(a * b)); + case VECTOR_OP_DIV: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float)(a / b)); + case VECTOR_OP_MAX: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float)Math.max(a, b)); + case VECTOR_OP_MIN: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float)Math.min(a, b)); + case VECTOR_OP_OR: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> FloatVector.fromBits(FloatVector.toBits(a) | FloatVector.toBits(b))); + case VECTOR_OP_ATAN2: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float) Math.atan2(a, b)); + case VECTOR_OP_POW: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float) Math.pow(a, b)); + case VECTOR_OP_HYPOT: return (v0, v1, vm) -> + v0.bOp(v1, vm, (i, a, b) -> (float) Math.hypot(a, b)); + default: return null; + } + } + + // FIXME: Maybe all of the public final methods in this file (the + // simple ones that just call lanewise) should be pushed down to + // the X-VectorBits template. They can't optimize properly at + // this level, and must rely on inlining. Does it work? + // (If it works, of course keep the code here.) + + /** + * Combines the lane values of this vector + * with the value of a broadcast scalar. + * + * This is a lane-wise binary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, this.broadcast(e))}. + * + * @param op the operation used to process lane values + * @param e the input scalar + * @return the result of applying the operation lane-wise + * to the two input vectors + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short,VectorMask) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Binary op, + short e) { + return lanewise(op, broadcast(e)); + } + + /** + * Combines the lane values of this vector + * with the value of a broadcast scalar, + * with selection of lane elements controlled by a mask. + * + * This is a masked lane-wise binary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, this.broadcast(e), m)}. + * + * @param op the operation used to process lane values + * @param e the input scalar + * @param m the mask controlling lane selection + * @return the result of applying the operation lane-wise + * to the input vector and the scalar + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Binary op, + short e, + VectorMask m) { + return lanewise(op, broadcast(e), m); + } + + /** + * {@inheritDoc} + * @apiNote + * When working with vector subtypes like {@code Float16Vector}, + * {@linkplain #lanewise(VectorOperators.Binary,short) + * the more strongly typed method} + * is typically selected. It can be explicitly selected + * using a cast: {@code v.lanewise(op,(short)e)}. + * The two expressions will produce numerically identical results. + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Binary op, + long e) { + short e1 = float16ToRawShortBits(Float16.valueOf(e)); + if (shortBitsToFloat16(e1).longValue() != e) { + vspecies().checkValue(e); // for exception + } + return lanewise(op, e1); + } + + /** + * {@inheritDoc} + * @apiNote + * When working with vector subtypes like {@code Float16Vector}, + * {@linkplain #lanewise(VectorOperators.Binary,short,VectorMask) + * the more strongly typed method} + * is typically selected. It can be explicitly selected + * using a cast: {@code v.lanewise(op,(short)e,m)}. + * The two expressions will produce numerically identical results. + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Binary op, + long e, VectorMask m) { + short e1 = float16ToRawShortBits(Float16.valueOf(e)); + if (shortBitsToFloat16(e1).longValue() != e) { + vspecies().checkValue(e); // for exception + } + return lanewise(op, e1, m); + } + + + // Ternary lanewise support + + // Ternary operators come in eight variations: + // lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2]) + // lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2], mask) + + // It is annoying to support all of these variations of masking + // and broadcast, but it would be more surprising not to continue + // the obvious pattern started by unary and binary. + + /** + * {@inheritDoc} + * @see #lanewise(VectorOperators.Ternary,short,short,VectorMask) + * @see #lanewise(VectorOperators.Ternary,Vector,short,VectorMask) + * @see #lanewise(VectorOperators.Ternary,short,Vector,VectorMask) + * @see #lanewise(VectorOperators.Ternary,short,short) + * @see #lanewise(VectorOperators.Ternary,Vector,short) + * @see #lanewise(VectorOperators.Ternary,short,Vector) + */ + @Override + public abstract + Float16Vector lanewise(VectorOperators.Ternary op, + Vector v1, + Vector v2); + @ForceInline + final + Float16Vector lanewiseTemplate(VectorOperators.Ternary op, + Vector v1, + Vector v2) { + Float16Vector that = (Float16Vector) v1; + Float16Vector tother = (Float16Vector) v2; + // It's a word: https://www.dictionary.com/browse/tother + // See also Chapter 11 of Dickens, Our Mutual Friend: + // "Totherest Governor," replied Mr Riderhood... + that.check(this); + tother.check(this); + int opc = opCode(op); + return VectorSupport.ternaryOp( + opc, getClass(), null, laneTypeOrdinal(), length(), + this, that, tother, null, + TERN_IMPL.find(op, opc, Float16Vector::ternaryOperations)); + } + + /** + * {@inheritDoc} + * @see #lanewise(VectorOperators.Ternary,short,short,VectorMask) + * @see #lanewise(VectorOperators.Ternary,Vector,short,VectorMask) + * @see #lanewise(VectorOperators.Ternary,short,Vector,VectorMask) + */ + @Override + public abstract + Float16Vector lanewise(VectorOperators.Ternary op, + Vector v1, + Vector v2, + VectorMask m); + @ForceInline + final + Float16Vector lanewiseTemplate(VectorOperators.Ternary op, + Class> maskClass, + Vector v1, + Vector v2, + VectorMask m) { + Float16Vector that = (Float16Vector) v1; + Float16Vector tother = (Float16Vector) v2; + // It's a word: https://www.dictionary.com/browse/tother + // See also Chapter 11 of Dickens, Our Mutual Friend: + // "Totherest Governor," replied Mr Riderhood... + that.check(this); + tother.check(this); + m.check(maskClass, this); + + int opc = opCode(op); + return VectorSupport.ternaryOp( + opc, getClass(), maskClass, laneTypeOrdinal(), length(), + this, that, tother, m, + TERN_IMPL.find(op, opc, Float16Vector::ternaryOperations)); + } + + private static final + ImplCache>> + TERN_IMPL = new ImplCache<>(Ternary.class, Float16Vector.class); + + private static TernaryOperation> ternaryOperations(int opc_) { + switch (opc_) { + case VECTOR_OP_FMA: return (v0, v1_, v2_, m) -> + v0.tOp(v1_, v2_, m, (i, a, b, c) -> float16ToRawShortBits(Float16.fma(shortBitsToFloat16(a), shortBitsToFloat16(b), shortBitsToFloat16(c)))); + default: return null; + } + } + + /** + * Combines the lane values of this vector + * with the values of two broadcast scalars. + * + * This is a lane-wise ternary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2))}. + * + * @param op the operation used to combine lane values + * @param e1 the first input scalar + * @param e2 the second input scalar + * @return the result of applying the operation lane-wise + * to the input vector and the scalars + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Ternary,Vector,Vector) + * @see #lanewise(VectorOperators.Ternary,short,short,VectorMask) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Ternary op, //(op,e1,e2) + short e1, + short e2) { + return lanewise(op, broadcast(e1), broadcast(e2)); + } + + /** + * Combines the lane values of this vector + * with the values of two broadcast scalars, + * with selection of lane elements controlled by a mask. + * + * This is a masked lane-wise ternary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2), m)}. + * + * @param op the operation used to combine lane values + * @param e1 the first input scalar + * @param e2 the second input scalar + * @param m the mask controlling lane selection + * @return the result of applying the operation lane-wise + * to the input vector and the scalars + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask) + * @see #lanewise(VectorOperators.Ternary,short,short) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Ternary op, //(op,e1,e2,m) + short e1, + short e2, + VectorMask m) { + return lanewise(op, broadcast(e1), broadcast(e2), m); + } + + /** + * Combines the lane values of this vector + * with the values of another vector and a broadcast scalar. + * + * This is a lane-wise ternary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, v1, this.broadcast(e2))}. + * + * @param op the operation used to combine lane values + * @param v1 the other input vector + * @param e2 the input scalar + * @return the result of applying the operation lane-wise + * to the input vectors and the scalar + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Ternary,short,short) + * @see #lanewise(VectorOperators.Ternary,Vector,short,VectorMask) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Ternary op, //(op,v1,e2) + Vector v1, + short e2) { + return lanewise(op, v1, broadcast(e2)); + } + + /** + * Combines the lane values of this vector + * with the values of another vector and a broadcast scalar, + * with selection of lane elements controlled by a mask. + * + * This is a masked lane-wise ternary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, v1, this.broadcast(e2), m)}. + * + * @param op the operation used to combine lane values + * @param v1 the other input vector + * @param e2 the input scalar + * @param m the mask controlling lane selection + * @return the result of applying the operation lane-wise + * to the input vectors and the scalar + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Ternary,Vector,Vector) + * @see #lanewise(VectorOperators.Ternary,short,short,VectorMask) + * @see #lanewise(VectorOperators.Ternary,Vector,short) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Ternary op, //(op,v1,e2,m) + Vector v1, + short e2, + VectorMask m) { + return lanewise(op, v1, broadcast(e2), m); + } + + /** + * Combines the lane values of this vector + * with the values of another vector and a broadcast scalar. + * + * This is a lane-wise ternary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, this.broadcast(e1), v2)}. + * + * @param op the operation used to combine lane values + * @param e1 the input scalar + * @param v2 the other input vector + * @return the result of applying the operation lane-wise + * to the input vectors and the scalar + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Ternary,Vector,Vector) + * @see #lanewise(VectorOperators.Ternary,short,Vector,VectorMask) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Ternary op, //(op,e1,v2) + short e1, + Vector v2) { + return lanewise(op, broadcast(e1), v2); + } + + /** + * Combines the lane values of this vector + * with the values of another vector and a broadcast scalar, + * with selection of lane elements controlled by a mask. + * + * This is a masked lane-wise ternary operation which applies + * the selected operation to each lane. + * The return value will be equal to this expression: + * {@code this.lanewise(op, this.broadcast(e1), v2, m)}. + * + * @param op the operation used to combine lane values + * @param e1 the input scalar + * @param v2 the other input vector + * @param m the mask controlling lane selection + * @return the result of applying the operation lane-wise + * to the input vectors and the scalar + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask) + * @see #lanewise(VectorOperators.Ternary,short,Vector) + */ + @ForceInline + public final + Float16Vector lanewise(VectorOperators.Ternary op, //(op,e1,v2,m) + short e1, + Vector v2, + VectorMask m) { + return lanewise(op, broadcast(e1), v2, m); + } + + // (Thus endeth the Great and Mighty Ternary Ogdoad.) + // https://en.wikipedia.org/wiki/Ogdoad + + /// FULL-SERVICE BINARY METHODS: ADD, SUB, MUL, DIV + // + // These include masked and non-masked versions. + // This subclass adds broadcast (masked or not). + + /** + * {@inheritDoc} + * @see #add(short) + */ + @Override + @ForceInline + public final Float16Vector add(Vector v) { + return lanewise(ADD, v); + } + + /** + * Adds this vector to the broadcast of an input scalar. + * + * This is a lane-wise binary operation which applies + * the primitive addition operation ({@code +}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short) + * lanewise}{@code (}{@link VectorOperators#ADD + * ADD}{@code , e)}. + * + * @param e the input scalar + * @return the result of adding each lane of this vector to the scalar + * @see #add(Vector) + * @see #broadcast(short) + * @see #add(short,VectorMask) + * @see VectorOperators#ADD + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final + Float16Vector add(short e) { + return lanewise(ADD, e); + } + + /** + * {@inheritDoc} + * @see #add(short,VectorMask) + */ + @Override + @ForceInline + public final Float16Vector add(Vector v, + VectorMask m) { + return lanewise(ADD, v, m); + } + + /** + * Adds this vector to the broadcast of an input scalar, + * selecting lane elements controlled by a mask. + * + * This is a masked lane-wise binary operation which applies + * the primitive addition operation ({@code +}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short,VectorMask) + * lanewise}{@code (}{@link VectorOperators#ADD + * ADD}{@code , s, m)}. + * + * @param e the input scalar + * @param m the mask controlling lane selection + * @return the result of adding each lane of this vector to the scalar + * @see #add(Vector,VectorMask) + * @see #broadcast(short) + * @see #add(short) + * @see VectorOperators#ADD + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector add(short e, + VectorMask m) { + return lanewise(ADD, e, m); + } + + /** + * {@inheritDoc} + * @see #sub(short) + */ + @Override + @ForceInline + public final Float16Vector sub(Vector v) { + return lanewise(SUB, v); + } + + /** + * Subtracts an input scalar from this vector. + * + * This is a masked lane-wise binary operation which applies + * the primitive subtraction operation ({@code -}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short) + * lanewise}{@code (}{@link VectorOperators#SUB + * SUB}{@code , e)}. + * + * @param e the input scalar + * @return the result of subtracting the scalar from each lane of this vector + * @see #sub(Vector) + * @see #broadcast(short) + * @see #sub(short,VectorMask) + * @see VectorOperators#SUB + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector sub(short e) { + return lanewise(SUB, e); + } + + /** + * {@inheritDoc} + * @see #sub(short,VectorMask) + */ + @Override + @ForceInline + public final Float16Vector sub(Vector v, + VectorMask m) { + return lanewise(SUB, v, m); + } + + /** + * Subtracts an input scalar from this vector + * under the control of a mask. + * + * This is a masked lane-wise binary operation which applies + * the primitive subtraction operation ({@code -}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short,VectorMask) + * lanewise}{@code (}{@link VectorOperators#SUB + * SUB}{@code , s, m)}. + * + * @param e the input scalar + * @param m the mask controlling lane selection + * @return the result of subtracting the scalar from each lane of this vector + * @see #sub(Vector,VectorMask) + * @see #broadcast(short) + * @see #sub(short) + * @see VectorOperators#SUB + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector sub(short e, + VectorMask m) { + return lanewise(SUB, e, m); + } + + /** + * {@inheritDoc} + * @see #mul(short) + */ + @Override + @ForceInline + public final Float16Vector mul(Vector v) { + return lanewise(MUL, v); + } + + /** + * Multiplies this vector by the broadcast of an input scalar. + * + * This is a lane-wise binary operation which applies + * the primitive multiplication operation ({@code *}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short) + * lanewise}{@code (}{@link VectorOperators#MUL + * MUL}{@code , e)}. + * + * @param e the input scalar + * @return the result of multiplying this vector by the given scalar + * @see #mul(Vector) + * @see #broadcast(short) + * @see #mul(short,VectorMask) + * @see VectorOperators#MUL + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector mul(short e) { + return lanewise(MUL, e); + } + + /** + * {@inheritDoc} + * @see #mul(short,VectorMask) + */ + @Override + @ForceInline + public final Float16Vector mul(Vector v, + VectorMask m) { + return lanewise(MUL, v, m); + } + + /** + * Multiplies this vector by the broadcast of an input scalar, + * selecting lane elements controlled by a mask. + * + * This is a masked lane-wise binary operation which applies + * the primitive multiplication operation ({@code *}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short,VectorMask) + * lanewise}{@code (}{@link VectorOperators#MUL + * MUL}{@code , s, m)}. + * + * @param e the input scalar + * @param m the mask controlling lane selection + * @return the result of muling each lane of this vector to the scalar + * @see #mul(Vector,VectorMask) + * @see #broadcast(short) + * @see #mul(short) + * @see VectorOperators#MUL + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector mul(short e, + VectorMask m) { + return lanewise(MUL, e, m); + } + + /** + * {@inheritDoc} + * @apiNote Because the underlying scalar operator is an IEEE + * floating point number, division by zero in fact will + * not throw an exception, but will yield a signed + * infinity or NaN. + */ + @Override + @ForceInline + public final Float16Vector div(Vector v) { + return lanewise(DIV, v); + } + + /** + * Divides this vector by the broadcast of an input scalar. + * + * This is a lane-wise binary operation which applies + * the primitive division operation ({@code /}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short) + * lanewise}{@code (}{@link VectorOperators#DIV + * DIV}{@code , e)}. + * + * @apiNote Because the underlying scalar operator is an IEEE + * floating point number, division by zero in fact will + * not throw an exception, but will yield a signed + * infinity or NaN. + * + * @param e the input scalar + * @return the result of dividing each lane of this vector by the scalar + * @see #div(Vector) + * @see #broadcast(short) + * @see #div(short,VectorMask) + * @see VectorOperators#DIV + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector div(short e) { + return lanewise(DIV, e); + } + + /** + * {@inheritDoc} + * @see #div(short,VectorMask) + * @apiNote Because the underlying scalar operator is an IEEE + * floating point number, division by zero in fact will + * not throw an exception, but will yield a signed + * infinity or NaN. + */ + @Override + @ForceInline + public final Float16Vector div(Vector v, + VectorMask m) { + return lanewise(DIV, v, m); + } + + /** + * Divides this vector by the broadcast of an input scalar, + * selecting lane elements controlled by a mask. + * + * This is a masked lane-wise binary operation which applies + * the primitive division operation ({@code /}) to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short,VectorMask) + * lanewise}{@code (}{@link VectorOperators#DIV + * DIV}{@code , s, m)}. + * + * @apiNote Because the underlying scalar operator is an IEEE + * floating point number, division by zero in fact will + * not throw an exception, but will yield a signed + * infinity or NaN. + * + * @param e the input scalar + * @param m the mask controlling lane selection + * @return the result of dividing each lane of this vector by the scalar + * @see #div(Vector,VectorMask) + * @see #broadcast(short) + * @see #div(short) + * @see VectorOperators#DIV + * @see #lanewise(VectorOperators.Binary,Vector) + * @see #lanewise(VectorOperators.Binary,short) + */ + @ForceInline + public final Float16Vector div(short e, + VectorMask m) { + return lanewise(DIV, e, m); + } + + /// END OF FULL-SERVICE BINARY METHODS + + /// SECOND-TIER BINARY METHODS + // + // There are no masked versions. + + /** + * {@inheritDoc} + * @apiNote + * For this method, floating point negative + * zero {@code -0.0} is treated as a value distinct from, and less + * than the default value (positive zero). + */ + @Override + @ForceInline + public final Float16Vector min(Vector v) { + return lanewise(MIN, v); + } + + // FIXME: "broadcast of an input scalar" is really wordy. Reduce? + /** + * Computes the smaller of this vector and the broadcast of an input scalar. + * + * This is a lane-wise binary operation which applies the + * operation {@code Math.min()} to each pair of + * corresponding lane values. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short) + * lanewise}{@code (}{@link VectorOperators#MIN + * MIN}{@code , e)}. + * + * @param e the input scalar + * @return the result of multiplying this vector by the given scalar + * @see #min(Vector) + * @see #broadcast(short) + * @see VectorOperators#MIN + * @see #lanewise(VectorOperators.Binary,short,VectorMask) + * @apiNote + * For this method, floating point negative + * zero {@code -0.0} is treated as a value distinct from, and less + * than the default value (positive zero). + */ + @ForceInline + public final Float16Vector min(short e) { + return lanewise(MIN, e); + } + + /** + * {@inheritDoc} + * @apiNote + * For this method, floating point negative + * zero {@code -0.0} is treated as a value distinct from, and less + * than the default value (positive zero). + */ + @Override + @ForceInline + public final Float16Vector max(Vector v) { + return lanewise(MAX, v); + } + + /** + * Computes the larger of this vector and the broadcast of an input scalar. + * + * This is a lane-wise binary operation which applies the + * operation {@code Math.max()} to each pair of + * corresponding lane values. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,short) + * lanewise}{@code (}{@link VectorOperators#MAX + * MAX}{@code , e)}. + * + * @param e the input scalar + * @return the result of multiplying this vector by the given scalar + * @see #max(Vector) + * @see #broadcast(short) + * @see VectorOperators#MAX + * @see #lanewise(VectorOperators.Binary,short,VectorMask) + * @apiNote + * For this method, floating point negative + * zero {@code -0.0} is treated as a value distinct from, and less + * than the default value (positive zero). + */ + @ForceInline + public final Float16Vector max(short e) { + return lanewise(MAX, e); + } + + + // common FP operator: pow + /** + * Raises this vector to the power of a second input vector. + * + * This is a lane-wise binary operation which applies an operation + * conforming to the specification of + * {@link Math#pow Math.pow(a,b)} + * to each pair of corresponding lane values. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,Vector) + * lanewise}{@code (}{@link VectorOperators#POW + * POW}{@code , b)}. + * + *

+ * This is not a full-service named operation like + * {@link #add(Vector) add}. A masked version of + * this operation is not directly available + * but may be obtained via the masked version of + * {@code lanewise}. + * + * @param b a vector exponent by which to raise this vector + * @return the {@code b}-th power of this vector + * @see #pow(short) + * @see VectorOperators#POW + * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) + */ + @ForceInline + public final Float16Vector pow(Vector b) { + return lanewise(POW, b); + } + + /** + * Raises this vector to a scalar power. + * + * This is a lane-wise binary operation which applies an operation + * conforming to the specification of + * {@link Math#pow Math.pow(a,b)} + * to each pair of corresponding lane values. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Binary,Vector) + * lanewise}{@code (}{@link VectorOperators#POW + * POW}{@code , b)}. + * + * @param b a scalar exponent by which to raise this vector + * @return the {@code b}-th power of this vector + * @see #pow(Vector) + * @see VectorOperators#POW + * @see #lanewise(VectorOperators.Binary,short,VectorMask) + */ + @ForceInline + public final Float16Vector pow(short b) { + return lanewise(POW, b); + } + + /// UNARY METHODS + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + Float16Vector neg() { + return lanewise(NEG); + } + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + Float16Vector abs() { + return lanewise(ABS); + } + + + + // sqrt + /** + * Computes the square root of this vector. + * + * This is a lane-wise unary operation which applies an operation + * conforming to the specification of + * {@link Math#sqrt Math.sqrt(a)} + * to each lane value. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Unary) + * lanewise}{@code (}{@link VectorOperators#SQRT + * SQRT}{@code )}. + * + * @return the square root of this vector + * @see VectorOperators#SQRT + * @see #lanewise(VectorOperators.Unary,VectorMask) + */ + @ForceInline + public final Float16Vector sqrt() { + return lanewise(SQRT); + } + + /// COMPARISONS + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + VectorMask eq(Vector v) { + return compare(EQ, v); + } + + /** + * Tests if this vector is equal to an input scalar. + * + * This is a lane-wise binary test operation which applies + * the primitive equals operation ({@code ==}) to each lane. + * The result is the same as {@code compare(VectorOperators.Comparison.EQ, e)}. + * + * @param e the input scalar + * @return the result mask of testing if this vector + * is equal to {@code e} + * @see #compare(VectorOperators.Comparison,short) + */ + @ForceInline + public final + VectorMask eq(short e) { + return compare(EQ, e); + } + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + VectorMask lt(Vector v) { + return compare(LT, v); + } + + /** + * Tests if this vector is less than an input scalar. + * + * This is a lane-wise binary test operation which applies + * the primitive less than operation ({@code <}) to each lane. + * The result is the same as {@code compare(VectorOperators.LT, e)}. + * + * @param e the input scalar + * @return the mask result of testing if this vector + * is less than the input scalar + * @see #compare(VectorOperators.Comparison,short) + */ + @ForceInline + public final + VectorMask lt(short e) { + return compare(LT, e); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + VectorMask test(VectorOperators.Test op); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op) { + Float16Species vsp = vspecies(); + if (opKind(op, VO_SPECIAL)) { + ShortVector bits = this.viewAsIntegralLanes(); + VectorMask m; + if (op == IS_DEFAULT) { + m = bits.compare(EQ, (short) 0); + } else if (op == IS_NEGATIVE) { + m = bits.compare(LT, (short) 0); + } + else if (op == IS_FINITE || + op == IS_NAN || + op == IS_INFINITE) { + // first kill the sign: + bits = bits.and(Short.MAX_VALUE); + // next find the bit pattern for infinity: + short infbits = (short) toBits(float16ToRawShortBits(Float16.POSITIVE_INFINITY)); + // now compare: + if (op == IS_FINITE) { + m = bits.compare(LT, infbits); + } else if (op == IS_NAN) { + m = bits.compare(GT, infbits); + } else { + m = bits.compare(EQ, infbits); + } + } + else { + throw new AssertionError(op); + } + return maskType.cast(m.cast(vsp)); + } + int opc = opCode(op); + throw new AssertionError(op); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + VectorMask test(VectorOperators.Test op, + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + Float16Species vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + ShortVector bits = this.viewAsIntegralLanes(); + VectorMask m = mask.cast(ShortVector.species(shape())); + if (op == IS_DEFAULT) { + m = bits.compare(EQ, (short) 0, m); + } else if (op == IS_NEGATIVE) { + m = bits.compare(LT, (short) 0, m); + } + else if (op == IS_FINITE || + op == IS_NAN || + op == IS_INFINITE) { + // first kill the sign: + bits = bits.and(Short.MAX_VALUE); + // next find the bit pattern for infinity: + short infbits = (short) toBits(float16ToRawShortBits(Float16.POSITIVE_INFINITY)); + // now compare: + if (op == IS_FINITE) { + m = bits.compare(LT, infbits, m); + } else if (op == IS_NAN) { + m = bits.compare(GT, infbits, m); + } else { + m = bits.compare(EQ, infbits, m); + } + } + else { + throw new AssertionError(op); + } + return maskType.cast(m.cast(vsp)); + } + int opc = opCode(op); + throw new AssertionError(op); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + VectorMask compare(VectorOperators.Comparison op, Vector v); + + /*package-private*/ + @ForceInline + final + > + M compareTemplate(Class maskType, Comparison op, Vector v) { + Float16Vector that = (Float16Vector) v; + that.check(this); + int opc = opCode(op); + return VectorSupport.compare( + opc, getClass(), maskType, laneTypeOrdinal(), length(), + this, that, null, + (cond, v0, v1, m1) -> { + AbstractMask m + = v0.bTest(cond, v1, (cond_, i, a, b) + -> compareWithOp(cond, a, b)); + @SuppressWarnings("unchecked") + M m2 = (M) m; + return m2; + }); + } + + /*package-private*/ + @ForceInline + final + > + M compareTemplate(Class maskType, Comparison op, Vector v, M m) { + Float16Vector that = (Float16Vector) v; + that.check(this); + m.check(maskType, this); + int opc = opCode(op); + return VectorSupport.compare( + opc, getClass(), maskType, laneTypeOrdinal(), length(), + this, that, m, + (cond, v0, v1, m1) -> { + AbstractMask cmpM + = v0.bTest(cond, v1, (cond_, i, a, b) + -> compareWithOp(cond, a, b)); + @SuppressWarnings("unchecked") + M m2 = (M) cmpM.and(m1); + return m2; + }); + } + + @ForceInline + private static boolean compareWithOp(int cond, short a, short b) { + return switch (cond) { + case BT_eq -> Float.float16ToFloat(a) == Float.float16ToFloat(b); + case BT_ne -> Float.float16ToFloat(a) != Float.float16ToFloat(b); + case BT_lt -> Float.float16ToFloat(a) < Float.float16ToFloat(b); + case BT_le -> Float.float16ToFloat(a) <= Float.float16ToFloat(b); + case BT_gt -> Float.float16ToFloat(a) > Float.float16ToFloat(b); + case BT_ge -> Float.float16ToFloat(a) >= Float.float16ToFloat(b); + default -> throw new AssertionError(); + }; + } + + /** + * Tests this vector by comparing it with an input scalar, + * according to the given comparison operation. + * + * This is a lane-wise binary test operation which applies + * the comparison operation to each lane. + *

+ * The result is the same as + * {@code compare(op, broadcast(species(), e))}. + * That is, the scalar may be regarded as broadcast to + * a vector of the same species, and then compared + * against the original vector, using the selected + * comparison operation. + * + * @param op the operation used to compare lane values + * @param e the input scalar + * @return the mask result of testing lane-wise if this vector + * compares to the input, according to the selected + * comparison operator + * @see Float16Vector#compare(VectorOperators.Comparison,Vector) + * @see #eq(short) + * @see #lt(short) + */ + public abstract + VectorMask compare(Comparison op, short e); + + /*package-private*/ + @ForceInline + final + > + M compareTemplate(Class maskType, Comparison op, short e) { + return compareTemplate(maskType, op, broadcast(e)); + } + + /** + * Tests this vector by comparing it with an input scalar, + * according to the given comparison operation, + * in lanes selected by a mask. + * + * This is a masked lane-wise binary test operation which applies + * to each pair of corresponding lane values. + * + * The returned result is equal to the expression + * {@code compare(op,s).and(m)}. + * + * @param op the operation used to compare lane values + * @param e the input scalar + * @param m the mask controlling lane selection + * @return the mask result of testing lane-wise if this vector + * compares to the input, according to the selected + * comparison operator, + * and only in the lanes selected by the mask + * @see Float16Vector#compare(VectorOperators.Comparison,Vector,VectorMask) + */ + @ForceInline + public final VectorMask compare(VectorOperators.Comparison op, + short e, + VectorMask m) { + return compare(op, broadcast(e), m); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + VectorMask compare(Comparison op, long e); + + /*package-private*/ + @ForceInline + final + > + M compareTemplate(Class maskType, Comparison op, long e) { + return compareTemplate(maskType, op, broadcast(e)); + } + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + VectorMask compare(Comparison op, long e, VectorMask m) { + return compare(op, broadcast(e), m); + } + + + + /** + * {@inheritDoc} + */ + @Override public abstract + Float16Vector blend(Vector v, VectorMask m); + + /*package-private*/ + @ForceInline + final + > + Float16Vector + blendTemplate(Class maskType, Float16Vector v, M m) { + v.check(this); + return VectorSupport.blend( + getClass(), maskType, laneTypeOrdinal(), length(), + this, v, m, + (v0, v1, m_) -> v0.bOp(v1, m_, (i, a, b) -> b)); + } + + /** + * {@inheritDoc} + */ + @Override public abstract Float16Vector addIndex(int scale); + + /*package-private*/ + @ForceInline + final Float16Vector addIndexTemplate(int scale) { + Float16Species vsp = vspecies(); + // make sure VLENGTH*scale doesn't overflow: + vsp.checkScale(scale); + return VectorSupport.indexVector( + getClass(), laneTypeOrdinal(), length(), + this, scale, vsp, + (v, scale_, s) + -> { + // If the platform doesn't support an INDEX + // instruction directly, load IOTA from memory + // and multiply. + Float16Vector iota = s.iota(); + short sc = (short) scale_; + return v.add(sc == 1 ? iota : iota.mul(float16ToRawShortBits(Float16.valueOf(sc)))); + }); + } + + /** + * Replaces selected lanes of this vector with + * a scalar value + * under the control of a mask. + * + * This is a masked lane-wise binary operation which + * selects each lane value from one or the other input. + * + * The returned result is equal to the expression + * {@code blend(broadcast(e),m)}. + * + * @param e the input scalar, containing the replacement lane value + * @param m the mask controlling lane selection of the scalar + * @return the result of blending the lane elements of this vector with + * the scalar value + */ + @ForceInline + public final Float16Vector blend(short e, + VectorMask m) { + return blend(broadcast(e), m); + } + + /** + * Replaces selected lanes of this vector with + * a scalar value + * under the control of a mask. + * + * This is a masked lane-wise binary operation which + * selects each lane value from one or the other input. + * + * The returned result is equal to the expression + * {@code blend(broadcast(e),m)}. + * + * @param e the input scalar, containing the replacement lane value + * @param m the mask controlling lane selection of the scalar + * @return the result of blending the lane elements of this vector with + * the scalar value + */ + @ForceInline + public final Float16Vector blend(long e, + VectorMask m) { + return blend(broadcast(e), m); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector slice(int origin, Vector v1); + + /*package-private*/ + final + @ForceInline + Float16Vector sliceTemplate(int origin, Vector v1) { + Float16Vector that = (Float16Vector) v1; + that.check(this); + Objects.checkIndex(origin, length() + 1); + ShortVector iotaVector = (ShortVector) iotaShuffle().toBitsVector(); + ShortVector filter = ShortVector.broadcast((ShortVector.ShortSpecies) vspecies().asIntegral(), (short)(length() - origin)); + VectorMask blendMask = iotaVector.compare(VectorOperators.LT, filter).cast(vspecies()); + AbstractShuffle iota = iotaShuffle(origin, 1, true); + return that.rearrange(iota).blend(this.rearrange(iota), blendMask); + } + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + Float16Vector slice(int origin, + Vector w, + VectorMask m) { + return broadcast(0).blend(slice(origin, w), m); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector slice(int origin); + + /*package-private*/ + final + @ForceInline + Float16Vector sliceTemplate(int origin) { + Objects.checkIndex(origin, length() + 1); + ShortVector iotaVector = (ShortVector) iotaShuffle().toBitsVector(); + ShortVector filter = ShortVector.broadcast((ShortVector.ShortSpecies) vspecies().asIntegral(), (short)(length() - origin)); + VectorMask blendMask = iotaVector.compare(VectorOperators.LT, filter).cast(vspecies()); + AbstractShuffle iota = iotaShuffle(origin, 1, true); + return vspecies().zero().blend(this.rearrange(iota), blendMask); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector unslice(int origin, Vector w, int part); + + /*package-private*/ + final + @ForceInline + Float16Vector + unsliceTemplate(int origin, Vector w, int part) { + Float16Vector that = (Float16Vector) w; + that.check(this); + Objects.checkIndex(origin, length() + 1); + if ((-2 & part) != 0) { + throw wrongPartForSlice(part); + } + ShortVector iotaVector = (ShortVector) iotaShuffle().toBitsVector(); + ShortVector filter = ShortVector.broadcast((ShortVector.ShortSpecies) vspecies().asIntegral(), (short)origin); + VectorMask blendMask = iotaVector.compare((part == 0) ? VectorOperators.GE : VectorOperators.LT, filter).cast(vspecies()); + AbstractShuffle iota = iotaShuffle(-origin, 1, true); + return that.blend(this.rearrange(iota), blendMask); + } + + /*package-private*/ + final + @ForceInline + > + Float16Vector + unsliceTemplate(Class maskType, int origin, Vector w, int part, M m) { + Float16Vector that = (Float16Vector) w; + that.check(this); + Float16Vector slice = that.sliceTemplate(origin, that); + slice = slice.blendTemplate(maskType, this, m); + return slice.unsliceTemplate(origin, w, part); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector unslice(int origin, Vector w, int part, VectorMask m); + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector unslice(int origin); + + /*package-private*/ + final + @ForceInline + Float16Vector + unsliceTemplate(int origin) { + Objects.checkIndex(origin, length() + 1); + ShortVector iotaVector = (ShortVector) iotaShuffle().toBitsVector(); + ShortVector filter = ShortVector.broadcast((ShortVector.ShortSpecies) vspecies().asIntegral(), (short)origin); + VectorMask blendMask = iotaVector.compare(VectorOperators.GE, filter).cast(vspecies()); + AbstractShuffle iota = iotaShuffle(-origin, 1, true); + return vspecies().zero().blend(this.rearrange(iota), blendMask); + } + + private ArrayIndexOutOfBoundsException + wrongPartForSlice(int part) { + String msg = String.format("bad part number %d for slice operation", + part); + return new ArrayIndexOutOfBoundsException(msg); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector rearrange(VectorShuffle shuffle); + + /*package-private*/ + @ForceInline + final + > + Float16Vector rearrangeTemplate(Class shuffletype, S shuffle) { + Objects.requireNonNull(shuffle); + return VectorSupport.rearrangeOp( + getClass(), shuffletype, null, laneTypeOrdinal(), length(), + this, shuffle, null, + (v1, s_, m_) -> v1.uRawOp((i, a) -> { + int ei = Integer.remainderUnsigned(s_.laneSource(i), v1.length()); + return v1.lane(ei); + })); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector rearrange(VectorShuffle s, + VectorMask m); + + /*package-private*/ + @ForceInline + final + , M extends VectorMask> + Float16Vector rearrangeTemplate(Class shuffletype, + Class masktype, + S shuffle, + M m) { + Objects.requireNonNull(shuffle); + m.check(masktype, this); + return VectorSupport.rearrangeOp( + getClass(), shuffletype, masktype, laneTypeOrdinal(), length(), + this, shuffle, m, + (v1, s_, m_) -> v1.uRawOp((i, a) -> { + int ei = Integer.remainderUnsigned(s_.laneSource(i), v1.length()); + return !m_.laneIsSet(i) ? 0 : v1.lane(ei); + })); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector rearrange(VectorShuffle s, + Vector v); + + /*package-private*/ + @ForceInline + final + > + Float16Vector rearrangeTemplate(Class shuffletype, + S shuffle, + Float16Vector v) { + VectorMask valid = shuffle.laneIsValid(); + Float16Vector r0 = + VectorSupport.rearrangeOp( + getClass(), shuffletype, null, laneTypeOrdinal(), length(), + this, shuffle, null, + (v0, s_, m_) -> v0.uRawOp((i, a) -> { + int ei = Integer.remainderUnsigned(s_.laneSource(i), v0.length()); + return v0.lane(ei); + })); + Float16Vector r1 = + VectorSupport.rearrangeOp( + getClass(), shuffletype, null, laneTypeOrdinal(), length(), + v, shuffle, null, + (v1, s_, m_) -> v1.uRawOp((i, a) -> { + int ei = Integer.remainderUnsigned(s_.laneSource(i), v1.length()); + return v1.lane(ei); + })); + return r1.blend(r0, valid); + } + + @Override + @ForceInline + final VectorShuffle bitsToShuffle0(AbstractSpecies dsp) { + throw new AssertionError(); + } + + @ForceInline + final + VectorShuffle toShuffle(AbstractSpecies dsp, boolean wrap) { + assert(dsp.elementSize() == vspecies().elementSize()); + ShortVector idx = convert(VectorOperators.H2S, 0).reinterpretAsShorts(); + ShortVector wrapped = idx.lanewise(VectorOperators.AND, length() - 1); + if (!wrap) { + ShortVector wrappedEx = wrapped.lanewise(VectorOperators.SUB, length()); + VectorMask inBound = wrapped.compare(VectorOperators.EQ, idx); + wrapped = wrappedEx.blend(wrapped, inBound); + } + return wrapped.bitsToShuffle(dsp); + } + + /** + * {@inheritDoc} + * @since 27 + */ + @Override + public abstract + Float16Vector compress(VectorMask m); + + /*package-private*/ + @ForceInline + final + > + Float16Vector compressTemplate(Class masktype, M m) { + m.check(masktype, this); + return (Float16Vector) VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_COMPRESS, getClass(), masktype, + laneTypeOrdinal(), length(), this, m, + (v1, m1) -> compressHelper(v1, m1)); + } + + /** + * {@inheritDoc} + * @since 27 + */ + @Override + public abstract + Float16Vector expand(VectorMask m); + + /*package-private*/ + @ForceInline + final + > + Float16Vector expandTemplate(Class masktype, M m) { + m.check(masktype, this); + return (Float16Vector) VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_EXPAND, getClass(), masktype, + laneTypeOrdinal(), length(), this, m, + (v1, m1) -> expandHelper(v1, m1)); + } + + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector selectFrom(Vector v); + + /*package-private*/ + @ForceInline + final Float16Vector selectFromTemplate(Float16Vector v) { + return (Float16Vector)VectorSupport.selectFromOp(getClass(), null, laneTypeOrdinal(), + length(), this, v, null, + (v1, v2, _m) -> + v2.rearrange(v1.toShuffle())); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector selectFrom(Vector s, VectorMask m); + + /*package-private*/ + @ForceInline + final + > + Float16Vector selectFromTemplate(Float16Vector v, + Class masktype, M m) { + m.check(masktype, this); + return (Float16Vector)VectorSupport.selectFromOp(getClass(), masktype, laneTypeOrdinal(), + length(), this, v, m, + (v1, v2, _m) -> + v2.rearrange(v1.toShuffle(), _m)); + } + + + /** + * {@inheritDoc} + */ + @Override + public abstract + Float16Vector selectFrom(Vector v1, Vector v2); + + + /*package-private*/ + @ForceInline + final Float16Vector selectFromTemplate(Float16Vector v1, Float16Vector v2) { + return VectorSupport.selectFromTwoVectorOp(getClass(), laneTypeOrdinal(), length(), this, v1, v2, + (vec1, vec2, vec3) -> selectFromTwoVectorHelper(vec1, vec2, vec3)); + } + + /// Ternary operations + + + /** + * Multiplies this vector by a second input vector, and sums + * the result with a third. + * + * Extended precision is used for the intermediate result, + * avoiding possible loss of precision from rounding once + * for each of the two operations. + * The result is numerically close to {@code this.mul(b).add(c)}, + * and is typically closer to the true mathematical result. + * + * This is a lane-wise ternary operation which applies an operation + * conforming to the specification of + * {@link Math#fma(float,float,float) Math.fma(a,b,c)} + * to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Ternary,Vector,Vector) + * lanewise}{@code (}{@link VectorOperators#FMA + * FMA}{@code , b, c)}. + * + * @param b the second input vector, supplying multiplier values + * @param c the third input vector, supplying addend values + * @return the product of this vector and the second input vector + * summed with the third input vector, using extended precision + * for the intermediate result + * @see #fma(short,short) + * @see VectorOperators#FMA + * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask) + */ + @ForceInline + public final + Float16Vector fma(Vector b, Vector c) { + return lanewise(FMA, b, c); + } + + /** + * Multiplies this vector by a scalar multiplier, and sums + * the result with a scalar addend. + * + * Extended precision is used for the intermediate result, + * avoiding possible loss of precision from rounding once + * for each of the two operations. + * The result is numerically close to {@code this.mul(b).add(c)}, + * and is typically closer to the true mathematical result. + * + * This is a lane-wise ternary operation which applies an operation + * conforming to the specification of + * {@link Math#fma(float,float,float) Math.fma(a,b,c)} + * to each lane. + * + * This method is also equivalent to the expression + * {@link #lanewise(VectorOperators.Ternary,Vector,Vector) + * lanewise}{@code (}{@link VectorOperators#FMA + * FMA}{@code , b, c)}. + * + * @param b the scalar multiplier + * @param c the scalar addend + * @return the product of this vector and the scalar multiplier + * summed with scalar addend, using extended precision + * for the intermediate result + * @see #fma(Vector,Vector) + * @see VectorOperators#FMA + * @see #lanewise(VectorOperators.Ternary,short,short,VectorMask) + */ + @ForceInline + public final + Float16Vector fma(short b, short c) { + return lanewise(FMA, b, c); + } + + // Don't bother with (Vector,short) and (short,Vector) overloadings. + + // Type specific horizontal reductions + + /** + * Returns a value accumulated from all the lanes of this vector. + * + * This is an associative cross-lane reduction operation which + * applies the specified operation to all the lane elements. + *

+ * A few reduction operations do not support arbitrary reordering + * of their operands, yet are included here because of their + * usefulness. + *

    + *
  • + * In the case of {@code FIRST_NONZERO}, the reduction returns + * the value from the lowest-numbered non-zero lane. + * (As with {@code MAX} and {@code MIN}, floating point negative + * zero {@code -0.0} is treated as a value distinct from + * the default value, positive zero. So a first-nonzero lane reduction + * might return {@code -0.0} even in the presence of non-zero + * lane values.) + *
  • + * In the case of {@code ADD} and {@code MUL}, the + * precise result will reflect the choice of an arbitrary order + * of operations, which may even vary over time. + * For further details see the section + * Operations on floating point vectors. + *
  • + * All other reduction operations are fully commutative and + * associative. The implementation can choose any order of + * processing, yet it will always produce the same result. + *
+ * + * @param op the operation used to combine lane values + * @return the accumulated result + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #reduceLanes(VectorOperators.Associative,VectorMask) + * @see #add(Vector) + * @see #mul(Vector) + * @see #min(Vector) + * @see #max(Vector) + * @see VectorOperators#FIRST_NONZERO + */ + public abstract short reduceLanes(VectorOperators.Associative op); + + /** + * Returns a value accumulated from selected lanes of this vector, + * controlled by a mask. + * + * This is an associative cross-lane reduction operation which + * applies the specified operation to the selected lane elements. + *

+ * If no elements are selected, an operation-specific identity + * value is returned. + *

    + *
  • + * If the operation is + * {@code ADD} + * or {@code FIRST_NONZERO}, + * then the identity value is positive zero, the default {@code short} value. + *
  • + * If the operation is {@code MUL}, + * then the identity value is one. + *
  • + * If the operation is {@code MAX}, + * then the identity value is {@code Float16.NEGATIVE_INFINITY}. + *
  • + * If the operation is {@code MIN}, + * then the identity value is {@code Float16.POSITIVE_INFINITY}. + *
+ *

+ * A few reduction operations do not support arbitrary reordering + * of their operands, yet are included here because of their + * usefulness. + *

    + *
  • + * In the case of {@code FIRST_NONZERO}, the reduction returns + * the value from the lowest-numbered non-zero lane. + * (As with {@code MAX} and {@code MIN}, floating point negative + * zero {@code -0.0} is treated as a value distinct from + * the default value, positive zero. So a first-nonzero lane reduction + * might return {@code -0.0} even in the presence of non-zero + * lane values.) + *
  • + * In the case of {@code ADD} and {@code MUL}, the + * precise result will reflect the choice of an arbitrary order + * of operations, which may even vary over time. + * For further details see the section + * Operations on floating point vectors. + *
  • + * All other reduction operations are fully commutative and + * associative. The implementation can choose any order of + * processing, yet it will always produce the same result. + *
+ * + * @param op the operation used to combine lane values + * @param m the mask controlling lane selection + * @return the reduced result accumulated from the selected lane values + * @throws UnsupportedOperationException if this vector does + * not support the requested operation + * @see #reduceLanes(VectorOperators.Associative) + */ + public abstract short reduceLanes(VectorOperators.Associative op, + VectorMask m); + + /*package-private*/ + @ForceInline + final + short reduceLanesTemplate(VectorOperators.Associative op, + Class> maskClass, + VectorMask m) { + m.check(maskClass, this); + if (op == FIRST_NONZERO) { + // FIXME: The JIT should handle this. + Float16Vector v = broadcast((short) 0).blend(this, m); + return v.reduceLanesTemplate(op); + } + int opc = opCode(op); + return fromBits(VectorSupport.reductionCoerced( + opc, getClass(), maskClass, laneTypeOrdinal(), length(), + this, m, + REDUCE_IMPL.find(op, opc, Float16Vector::reductionOperations))); + } + + /*package-private*/ + @ForceInline + final + short reduceLanesTemplate(VectorOperators.Associative op) { + if (op == FIRST_NONZERO) { + // FIXME: The JIT should handle this. + VectorMask thisNZ + = this.viewAsIntegralLanes().compare(NE, (short) 0); + int ft = thisNZ.firstTrue(); + return ft < length() ? this.lane(ft) : (short) 0; + } + int opc = opCode(op); + return fromBits(VectorSupport.reductionCoerced( + opc, getClass(), null, laneTypeOrdinal(), length(), + this, null, + REDUCE_IMPL.find(op, opc, Float16Vector::reductionOperations))); + } + + private static final + ImplCache>> + REDUCE_IMPL = new ImplCache<>(Associative.class, Float16Vector.class); + + private static ReductionOperation> reductionOperations(int opc_) { + switch (opc_) { + case VECTOR_OP_ADD: return (v, m) -> + toBits(v.rOp((short)0, m, (i, a, b) -> (float)(a + b))); + case VECTOR_OP_MUL: return (v, m) -> + toBits(v.rOp((short)floatToFloat16(1.0f), m, (i, a, b) -> (float)(a * b))); + case VECTOR_OP_MIN: return (v, m) -> + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (float) Math.min(a, b))); + case VECTOR_OP_MAX: return (v, m) -> + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (float) Math.max(a, b))); + default: return null; + } + } + + private static final short MIN_OR_INF = float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + private static final short MAX_OR_INF = float16ToRawShortBits(Float16.POSITIVE_INFINITY); + + public @Override abstract long reduceLanesToLong(VectorOperators.Associative op); + public @Override abstract long reduceLanesToLong(VectorOperators.Associative op, + VectorMask m); + + // Type specific accessors + + /** + * Gets the lane element at lane index {@code i} + * + * @param i the lane index + * @return the lane element at lane index {@code i} + * @throws IllegalArgumentException if the index is out of range + * ({@code < 0 || >= length()}) + */ + public abstract short lane(int i); + + /** + * Replaces the lane element of this vector at lane index {@code i} with + * value {@code e}. + * + * This is a cross-lane operation and behaves as if it returns the result + * of blending this vector with an input vector that is the result of + * broadcasting {@code e} and a mask that has only one lane set at lane + * index {@code i}. + * + * @param i the lane index of the lane element to be replaced + * @param e the value to be placed + * @return the result of replacing the lane element of this vector at lane + * index {@code i} with value {@code e}. + * @throws IllegalArgumentException if the index is out of range + * ({@code < 0 || >= length()}) + */ + public abstract Float16Vector withLane(int i, short e); + + // Memory load operations + + /** + * Returns an array of type {@code short[]} + * containing all the lane values. + * The array length is the same as the vector length. + * The array elements are stored in lane order. + *

+ * This method behaves as if it stores + * this vector into an allocated array + * (using {@link #intoArray(short[], int) intoArray}) + * and returns the array as follows: + *

{@code
+     *   short[] a = new short[this.length()];
+     *   this.intoArray(a, 0);
+     *   return a;
+     * }
+ * + * @return an array containing the lane values of this vector + */ + @ForceInline + @Override + public final short[] toArray() { + short[] a = new short[vspecies().laneCount()]; + intoArray(a, 0); + return a; + } + + /** {@inheritDoc} + */ + @ForceInline + @Override + public final int[] toIntArray() { + short[] a = toArray(); + int[] res = new int[a.length]; + for (int i = 0; i < a.length; i++) { + short e = a[i]; + res[i] = (int) Float16Species.toIntegralChecked(e, true); + } + return res; + } + + /** {@inheritDoc} + */ + @ForceInline + @Override + public final long[] toLongArray() { + short[] a = toArray(); + long[] res = new long[a.length]; + for (int i = 0; i < a.length; i++) { + short e = a[i]; + res[i] = Float16Species.toIntegralChecked(e, false); + } + return res; + } + + /** {@inheritDoc} + * @implNote + * When this method is used on vectors + * of type {@code Float16Vector}, + * there will be no loss of precision. + */ + @ForceInline + @Override + public final double[] toDoubleArray() { + short[] a = toArray(); + double[] res = new double[a.length]; + for (int i = 0; i < a.length; i++) { + res[i] = (double) shortBitsToFloat16(a[i]).doubleValue(); + } + return res; + } + + /** + * Loads a vector from an array of type {@code short[]} holding IEEE 754 binary16 values + * starting at an offset. + * For each vector lane, where {@code N} is the vector lane index, the + * array element at index {@code offset + N} is placed into the + * resulting vector at lane index {@code N}. + * + * @param species species of desired vector + * @param a the array + * @param offset the offset into the array + * @return the vector loaded from an array + * @throws IndexOutOfBoundsException + * if {@code offset+N < 0} or {@code offset+N >= a.length} + * for any lane {@code N} in the vector + */ + @ForceInline + public static + Float16Vector fromArray(VectorSpecies species, + short[] a, int offset) { + offset = checkFromIndexSize(offset, species.length(), a.length); + Float16Species vsp = (Float16Species) species; + return vsp.dummyVector().fromArray0(a, offset); + } + + /** + * Loads a vector from an array of type {@code short[]} holding IEEE 754 binary16 values + * starting at an offset and using a mask. + * Lanes where the mask is unset are filled with the default + * value of {@code short} (positive zero). + * For each vector lane, where {@code N} is the vector lane index, + * if the mask lane at index {@code N} is set then the array element at + * index {@code offset + N} is placed into the resulting vector at lane index + * {@code N}, otherwise the default element value is placed into the + * resulting vector at lane index {@code N}. + * + * @param species species of desired vector + * @param a the array + * @param offset the offset into the array + * @param m the mask controlling lane selection + * @return the vector loaded from an array + * @throws IndexOutOfBoundsException + * if {@code offset+N < 0} or {@code offset+N >= a.length} + * for any lane {@code N} in the vector + * where the mask is set + */ + @ForceInline + public static + Float16Vector fromArray(VectorSpecies species, + short[] a, int offset, + VectorMask m) { + Float16Species vsp = (Float16Species) species; + if (VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { + return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); + } + + ((AbstractMask)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); + return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); + } + + /** + * Gathers a new vector composed of elements from an array of type + * {@code short[]} holding IEEE 754 binary16 values, + * using indexes obtained by adding a fixed {@code offset} to a + * series of secondary offsets from an index map. + * The index map is a contiguous sequence of {@code VLENGTH} + * elements in a second array of {@code int}s, starting at a given + * {@code mapOffset}. + *

+ * For each vector lane, where {@code N} is the vector lane index, + * the lane is loaded from the array + * element {@code a[f(N)]}, where {@code f(N)} is the + * index mapping expression + * {@code offset + indexMap[mapOffset + N]]}. + * + * @param species species of desired vector + * @param a the array + * @param offset the offset into the array, may be negative if relative + * indexes in the index map compensate to produce a value within the + * array bounds + * @param indexMap the index map + * @param mapOffset the offset into the index map + * @return the vector loaded from the indexed elements of the array + * @throws IndexOutOfBoundsException + * if {@code mapOffset+N < 0} + * or if {@code mapOffset+N >= indexMap.length}, + * or if {@code f(N)=offset+indexMap[mapOffset+N]} + * is an invalid index into {@code a}, + * for any lane {@code N} in the vector + * @see Float16Vector#toIntArray() + */ + @ForceInline + public static + Float16Vector fromArray(VectorSpecies species, + short[] a, int offset, + int[] indexMap, int mapOffset) { + Float16Species vsp = (Float16Species) species; + IntVector.IntSpecies isp = IntVector.species(vsp.indexShape()); + Objects.requireNonNull(a); + Objects.requireNonNull(indexMap); + Class vectorType = vsp.vectorType(); + + + // Constant folding should sweep out following conditonal logic. + VectorSpecies lsp; + if (isp.length() > IntVector.SPECIES_PREFERRED.length()) { + lsp = IntVector.SPECIES_PREFERRED; + } else { + lsp = isp; + } + + // Check indices are within array bounds. + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); + } + + return VectorSupport.loadWithMap( + vectorType, null, LANE_TYPE_ORDINAL, vsp.laneCount(), + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, null, null, null, + a, offset, indexMap, mapOffset, vsp, + (c, idx, iMap, idy, s, vm) -> + s.vOp(n -> c[idx + iMap[idy+n]])); + } + + /** + * Gathers a new vector composed of elements from an array of type + * {@code short[]} holding IEEE 754 binary16 values, + * under the control of a mask, and + * using indexes obtained by adding a fixed {@code offset} to a + * series of secondary offsets from an index map. + * The index map is a contiguous sequence of {@code VLENGTH} + * elements in a second array of {@code int}s, starting at a given + * {@code mapOffset}. + *

+ * For each vector lane, where {@code N} is the vector lane index, + * if the lane is set in the mask, + * the lane is loaded from the array + * element {@code a[f(N)]}, where {@code f(N)} is the + * index mapping expression + * {@code offset + indexMap[mapOffset + N]]}. + * Unset lanes in the resulting vector are set to zero. + * + * @param species species of desired vector + * @param a the array + * @param offset the offset into the array, may be negative if relative + * indexes in the index map compensate to produce a value within the + * array bounds + * @param indexMap the index map + * @param mapOffset the offset into the index map + * @param m the mask controlling lane selection + * @return the vector loaded from the indexed elements of the array + * @throws IndexOutOfBoundsException + * if {@code mapOffset+N < 0} + * or if {@code mapOffset+N >= indexMap.length}, + * or if {@code f(N)=offset+indexMap[mapOffset+N]} + * is an invalid index into {@code a}, + * for any lane {@code N} in the vector + * where the mask is set + * @see Float16Vector#toIntArray() + */ + @ForceInline + public static + Float16Vector fromArray(VectorSpecies species, + short[] a, int offset, + int[] indexMap, int mapOffset, + VectorMask m) { + if (m.allTrue()) { + return fromArray(species, a, offset, indexMap, mapOffset); + } + else { + Float16Species vsp = (Float16Species) species; + return vsp.dummyVector().fromArray0(a, offset, indexMap, mapOffset, m); + } + } + + + + /** + * Loads a vector from a {@linkplain MemorySegment memory segment} + * starting at an offset into the memory segment. + * Bytes are composed into primitive lane elements according + * to the specified byte order. + * The vector is arranged into lanes according to + * memory ordering. + *

+ * This method behaves as if it returns the result of calling + * {@link #fromMemorySegment(VectorSpecies,MemorySegment,long,ByteOrder,VectorMask) + * fromMemorySegment()} as follows: + *

{@code
+     * var m = species.maskAll(true);
+     * return fromMemorySegment(species, ms, offset, bo, m);
+     * }
+ * + * @param species species of desired vector + * @param ms the memory segment + * @param offset the offset into the memory segment + * @param bo the intended byte order + * @return a vector loaded from the memory segment + * @throws IndexOutOfBoundsException + * if {@code offset+N*2 < 0} + * or {@code offset+N*2 >= ms.byteSize()} + * for any lane {@code N} in the vector + * @throws IllegalStateException if the memory segment's session is not alive, + * or if access occurs from a thread other than the thread owning the session. + * @since 27 + */ + @ForceInline + public static + Float16Vector fromMemorySegment(VectorSpecies species, + MemorySegment ms, long offset, + ByteOrder bo) { + offset = checkFromIndexSize(offset, species.vectorByteSize(), ms.byteSize()); + Float16Species vsp = (Float16Species) species; + return vsp.dummyVector().fromMemorySegment0(ms, offset).maybeSwap(bo); + } + + /** + * Loads a vector from a {@linkplain MemorySegment memory segment} + * starting at an offset into the memory segment + * and using a mask. + * Lanes where the mask is unset are filled with the default + * value of {@code short} (positive zero). + * Bytes are composed into primitive lane elements according + * to the specified byte order. + * The vector is arranged into lanes according to + * memory ordering. + *

+ * The following pseudocode illustrates the behavior: + *

{@code
+     * var slice = ms.asSlice(offset);
+     * short[] ar = new short[species.length()];
+     * for (int n = 0; n < ar.length; n++) {
+     *     if (m.laneIsSet(n)) {
+     *         ar[n] = slice.getAtIndex(ValuaLayout.JAVA_SHORT.withByteAlignment(1), n);
+     *     }
+     * }
+     * Float16Vector r = Float16Vector.fromArray(species, ar, 0);
+     * }
+ * @implNote + * This operation is likely to be more efficient if + * the specified byte order is the same as + * {@linkplain ByteOrder#nativeOrder() + * the platform native order}, + * since this method will not need to reorder + * the bytes of lane values. + * + * @param species species of desired vector + * @param ms the memory segment + * @param offset the offset into the memory segment + * @param bo the intended byte order + * @param m the mask controlling lane selection + * @return a vector loaded from the memory segment + * @throws IndexOutOfBoundsException + * if {@code offset+N*2 < 0} + * or {@code offset+N*2 >= ms.byteSize()} + * for any lane {@code N} in the vector + * where the mask is set + * @throws IllegalStateException if the memory segment's session is not alive, + * or if access occurs from a thread other than the thread owning the session. + * @since 27 + */ + @ForceInline + public static + Float16Vector fromMemorySegment(VectorSpecies species, + MemorySegment ms, long offset, + ByteOrder bo, + VectorMask m) { + Float16Species vsp = (Float16Species) species; + if (VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { + return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); + } + + ((AbstractMask)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 2); + return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); + } + + // Memory store operations + + /** + * Stores this vector into an array of type {@code short[]} + * starting at an offset. + *

+ * For each vector lane, where {@code N} is the vector lane index, + * the lane element at index {@code N} is stored into the array + * element {@code a[offset+N]}. + * + * @param a the array, of type {@code short[]} + * @param offset the offset into the array + * @throws IndexOutOfBoundsException + * if {@code offset+N < 0} or {@code offset+N >= a.length} + * for any lane {@code N} in the vector + */ + @ForceInline + public final + void intoArray(short[] a, int offset) { + offset = checkFromIndexSize(offset, length(), a.length); + Float16Species vsp = vspecies(); + VectorSupport.store( + vsp.vectorType(), LANE_TYPE_ORDINAL, vsp.laneCount(), + a, arrayAddress(a, offset), false, + this, + a, offset, + (arr, off, v) + -> v.stOp(arr, (int) off, + (arr_, off_, i, e) -> arr_[off_ + i] = e)); + } + + /** + * Stores this vector into an array of type {@code short[]} + * starting at offset and using a mask. + *

+ * For each vector lane, where {@code N} is the vector lane index, + * the lane element at index {@code N} is stored into the array + * element {@code a[offset+N]}. + * If the mask lane at {@code N} is unset then the corresponding + * array element {@code a[offset+N]} is left unchanged. + *

+ * Array range checking is done for lanes where the mask is set. + * Lanes where the mask is unset are not stored and do not need + * to correspond to legitimate elements of {@code a}. + * That is, unset lanes may correspond to array indexes less than + * zero or beyond the end of the array. + * + * @param a the array, of type {@code short[]} + * @param offset the offset into the array + * @param m the mask controlling lane storage + * @throws IndexOutOfBoundsException + * if {@code offset+N < 0} or {@code offset+N >= a.length} + * for any lane {@code N} in the vector + * where the mask is set + */ + @ForceInline + public final + void intoArray(short[] a, int offset, + VectorMask m) { + if (m.allTrue()) { + intoArray(a, offset); + } else { + Float16Species vsp = vspecies(); + if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { + ((AbstractMask)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); + } + intoArray0(a, offset, m); + } + } + + /** + * Scatters this vector into an array of type {@code short[]} + * using indexes obtained by adding a fixed {@code offset} to a + * series of secondary offsets from an index map. + * The index map is a contiguous sequence of {@code VLENGTH} + * elements in a second array of {@code int}s, starting at a given + * {@code mapOffset}. + *

+ * For each vector lane, where {@code N} is the vector lane index, + * the lane element at index {@code N} is stored into the array + * element {@code a[f(N)]}, where {@code f(N)} is the + * index mapping expression + * {@code offset + indexMap[mapOffset + N]]}. + * + * @param a the array + * @param offset an offset to combine with the index map offsets + * @param indexMap the index map + * @param mapOffset the offset into the index map + * @throws IndexOutOfBoundsException + * if {@code mapOffset+N < 0} + * or if {@code mapOffset+N >= indexMap.length}, + * or if {@code f(N)=offset+indexMap[mapOffset+N]} + * is an invalid index into {@code a}, + * for any lane {@code N} in the vector + * @see Float16Vector#toIntArray() + */ + @ForceInline + public final + void intoArray(short[] a, int offset, + int[] indexMap, int mapOffset) { + stOp(a, offset, + (arr, off, i, e) -> { + int j = indexMap[mapOffset + i]; + arr[off + j] = e; + }); + } + + /** + * Scatters this vector into an array of type {@code short[]}, + * under the control of a mask, and + * using indexes obtained by adding a fixed {@code offset} to a + * series of secondary offsets from an index map. + * The index map is a contiguous sequence of {@code VLENGTH} + * elements in a second array of {@code int}s, starting at a given + * {@code mapOffset}. + *

+ * For each vector lane, where {@code N} is the vector lane index, + * if the mask lane at index {@code N} is set then + * the lane element at index {@code N} is stored into the array + * element {@code a[f(N)]}, where {@code f(N)} is the + * index mapping expression + * {@code offset + indexMap[mapOffset + N]]}. + * + * @param a the array + * @param offset an offset to combine with the index map offsets + * @param indexMap the index map + * @param mapOffset the offset into the index map + * @param m the mask + * @throws IndexOutOfBoundsException + * if {@code mapOffset+N < 0} + * or if {@code mapOffset+N >= indexMap.length}, + * or if {@code f(N)=offset+indexMap[mapOffset+N]} + * is an invalid index into {@code a}, + * for any lane {@code N} in the vector + * where the mask is set + * @see Float16Vector#toIntArray() + */ + @ForceInline + public final + void intoArray(short[] a, int offset, + int[] indexMap, int mapOffset, + VectorMask m) { + stOp(a, offset, m, + (arr, off, i, e) -> { + int j = indexMap[mapOffset + i]; + arr[off + j] = e; + }); + } + + + + /** + * {@inheritDoc} + * @since 27 + */ + @Override + @ForceInline + public final + void intoMemorySegment(MemorySegment ms, long offset, + ByteOrder bo) { + if (ms.isReadOnly()) { + throw new UnsupportedOperationException("Attempt to write a read-only segment"); + } + + offset = checkFromIndexSize(offset, byteSize(), ms.byteSize()); + maybeSwap(bo).intoMemorySegment0(ms, offset); + } + + /** + * {@inheritDoc} + * @since 27 + */ + @Override + @ForceInline + public final + void intoMemorySegment(MemorySegment ms, long offset, + ByteOrder bo, + VectorMask m) { + if (m.allTrue()) { + intoMemorySegment(ms, offset, bo); + } else { + if (ms.isReadOnly()) { + throw new UnsupportedOperationException("Attempt to write a read-only segment"); + } + Float16Species vsp = vspecies(); + if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { + ((AbstractMask)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 2); + } + maybeSwap(bo).intoMemorySegment0(ms, offset, m); + } + } + + // ================================================ + + // Low-level memory operations. + // + // Note that all of these operations *must* inline into a context + // where the exact species of the involved vector is a + // compile-time constant. Otherwise, the intrinsic generation + // will fail and performance will suffer. + // + // In many cases this is achieved by re-deriving a version of the + // method in each concrete subclass (per species). The re-derived + // method simply calls one of these generic methods, with exact + // parameters for the controlling metadata, which is either a + // typed vector or constant species instance. + + // Unchecked loading operations in native byte order. + // Caller is responsible for applying index checks, masking, and + // byte swapping. + + /*package-private*/ + abstract + Float16Vector fromArray0(short[] a, int offset); + @ForceInline + final + Float16Vector fromArray0Template(short[] a, int offset) { + Float16Species vsp = vspecies(); + return VectorSupport.load( + vsp.vectorType(), LANE_TYPE_ORDINAL, vsp.laneCount(), + a, arrayAddress(a, offset), false, + a, offset, vsp, + (arr, off, s) -> s.ldOp(arr, (int) off, + (arr_, off_, i) -> arr_[off_ + i])); + } + + /*package-private*/ + abstract + Float16Vector fromArray0(short[] a, int offset, VectorMask m, int offsetInRange); + @ForceInline + final + > + Float16Vector fromArray0Template(Class maskClass, short[] a, int offset, M m, int offsetInRange) { + m.check(species()); + Float16Species vsp = vspecies(); + return VectorSupport.loadMasked( + vsp.vectorType(), maskClass, LANE_TYPE_ORDINAL, vsp.laneCount(), + a, arrayAddress(a, offset), false, m, offsetInRange, + a, offset, vsp, + (arr, off, s, vm) -> s.ldOp(arr, (int) off, vm, + (arr_, off_, i) -> arr_[off_ + i])); + } + + /*package-private*/ + abstract + Float16Vector fromArray0(short[] a, int offset, + int[] indexMap, int mapOffset, + VectorMask m); + @ForceInline + final + > + Float16Vector fromArray0Template(Class maskClass, short[] a, int offset, + int[] indexMap, int mapOffset, M m) { + Float16Species vsp = vspecies(); + IntVector.IntSpecies isp = IntVector.species(vsp.indexShape()); + Objects.requireNonNull(a); + Objects.requireNonNull(indexMap); + m.check(vsp); + Class vectorType = vsp.vectorType(); + + + // Constant folding should sweep out following conditonal logic. + VectorSpecies lsp; + if (isp.length() > IntVector.SPECIES_PREFERRED.length()) { + lsp = IntVector.SPECIES_PREFERRED; + } else { + lsp = isp; + } + + // Check indices are within array bounds. + // FIXME: Check index under mask controlling. + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); + } + + return VectorSupport.loadWithMap( + vectorType, maskClass, LANE_TYPE_ORDINAL, vsp.laneCount(), + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, null, null, m, + a, offset, indexMap, mapOffset, vsp, + (c, idx, iMap, idy, s, vm) -> + s.vOp(vm, n -> c[idx + iMap[idy+n]])); + } + + + + abstract + Float16Vector fromMemorySegment0(MemorySegment bb, long offset); + @ForceInline + final + Float16Vector fromMemorySegment0Template(MemorySegment ms, long offset) { + Float16Species vsp = vspecies(); + return ScopedMemoryAccess.loadFromMemorySegment( + vsp.vectorType(), LANE_TYPE_ORDINAL, vsp.laneCount(), + (AbstractMemorySegmentImpl) ms, offset, vsp, + (msp, off, s) -> { + return s.ldLongOp((MemorySegment) msp, off, Float16Vector::memorySegmentGet); + }); + } + + abstract + Float16Vector fromMemorySegment0(MemorySegment ms, long offset, VectorMask m, int offsetInRange); + @ForceInline + final + > + Float16Vector fromMemorySegment0Template(Class maskClass, MemorySegment ms, long offset, M m, int offsetInRange) { + Float16Species vsp = vspecies(); + m.check(vsp); + return ScopedMemoryAccess.loadFromMemorySegmentMasked( + vsp.vectorType(), maskClass, LANE_TYPE_ORDINAL, vsp.laneCount(), + (AbstractMemorySegmentImpl) ms, offset, m, vsp, offsetInRange, + (msp, off, s, vm) -> { + return s.ldLongOp((MemorySegment) msp, off, vm, Float16Vector::memorySegmentGet); + }); + } + + // Unchecked storing operations in native byte order. + // Caller is responsible for applying index checks, masking, and + // byte swapping. + + abstract + void intoArray0(short[] a, int offset); + @ForceInline + final + void intoArray0Template(short[] a, int offset) { + Float16Species vsp = vspecies(); + VectorSupport.store( + vsp.vectorType(), LANE_TYPE_ORDINAL, vsp.laneCount(), + a, arrayAddress(a, offset), false, + this, a, offset, + (arr, off, v) + -> v.stOp(arr, (int) off, + (arr_, off_, i, e) -> arr_[off_+i] = e)); + } + + abstract + void intoArray0(short[] a, int offset, VectorMask m); + @ForceInline + final + > + void intoArray0Template(Class maskClass, short[] a, int offset, M m) { + m.check(species()); + Float16Species vsp = vspecies(); + VectorSupport.storeMasked( + vsp.vectorType(), maskClass, LANE_TYPE_ORDINAL, vsp.laneCount(), + a, arrayAddress(a, offset), false, + this, m, a, offset, + (arr, off, v, vm) + -> v.stOp(arr, (int) off, vm, + (arr_, off_, i, e) -> arr_[off_ + i] = e)); + } + + + + @ForceInline + final + void intoMemorySegment0(MemorySegment ms, long offset) { + Float16Species vsp = vspecies(); + ScopedMemoryAccess.storeIntoMemorySegment( + vsp.vectorType(), LANE_TYPE_ORDINAL, vsp.laneCount(), + this, + (AbstractMemorySegmentImpl) ms, offset, + (msp, off, v) -> { + v.stLongOp((MemorySegment) msp, off, Float16Vector::memorySegmentSet); + }); + } + + abstract + void intoMemorySegment0(MemorySegment bb, long offset, VectorMask m); + @ForceInline + final + > + void intoMemorySegment0Template(Class maskClass, MemorySegment ms, long offset, M m) { + Float16Species vsp = vspecies(); + m.check(vsp); + ScopedMemoryAccess.storeIntoMemorySegmentMasked( + vsp.vectorType(), maskClass, LANE_TYPE_ORDINAL, vsp.laneCount(), + this, m, + (AbstractMemorySegmentImpl) ms, offset, + (msp, off, v, vm) -> { + v.stLongOp((MemorySegment) msp, off, vm, Float16Vector::memorySegmentSet); + }); + } + + + // End of low-level memory operations. + + @ForceInline + private void conditionalStoreNYI(int offset, + Float16Species vsp, + VectorMask m, + int scale, + int limit) { + if (offset < 0 || offset + vsp.laneCount() * scale > limit) { + String msg = + String.format("unimplemented: store @%d in [0..%d), %s in %s", + offset, limit, m, vsp); + throw new AssertionError(msg); + } + } + + /*package-private*/ + @Override + @ForceInline + final + Float16Vector maybeSwap(ByteOrder bo) { + if (bo != NATIVE_ENDIAN) { + return this.reinterpretAsBytes() + .rearrange(swapBytesShuffle()) + .reinterpretAsFloat16s(); + } + return this; + } + + @Override + @ForceInline + final + Float16Vector swapIfNeeded(AbstractSpecies srcSpecies) { + int subLanesPerSrc = subLanesToSwap(srcSpecies); + if (subLanesPerSrc < 0) { + return this; + } + VectorShuffle shuffle = normalizeSubLanesForSpecies(this.vspecies(), subLanesPerSrc); + return (Float16Vector) this.rearrange(shuffle); + } + + static final int ARRAY_SHIFT = + 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_SHORT_INDEX_SCALE); + static final long ARRAY_BASE = + Unsafe.ARRAY_SHORT_BASE_OFFSET; + + @ForceInline + static long arrayAddress(short[] a, int index) { + return ARRAY_BASE + (((long)index) << ARRAY_SHIFT); + } + + + + @ForceInline + static long byteArrayAddress(byte[] a, int index) { + return Unsafe.ARRAY_BYTE_BASE_OFFSET + index; + } + + // ================================================ + + /// Reinterpreting view methods: + // lanewise reinterpret: viewAsXVector() + // keep shape, redraw lanes: reinterpretAsEs() + + /** + * {@inheritDoc} + */ + @ForceInline + @Override + public final ByteVector reinterpretAsBytes() { + // Going to ByteVector, pay close attention to byte order. + assert(REGISTER_ENDIAN == ByteOrder.LITTLE_ENDIAN); + return asByteVectorRaw(); + //return asByteVectorRaw().rearrange(swapBytesShuffle()); + } + + /** + * {@inheritDoc} + */ + @ForceInline + @Override + public final ShortVector viewAsIntegralLanes() { + LaneType ilt = LaneType.SHORT.asIntegral(); + return (ShortVector) asVectorRaw(ilt); + } + + /** + * {@inheritDoc} + */ + @ForceInline + @Override + public final + Float16Vector + viewAsFloatingLanes() { + return this; + } + + // ================================================ + + /// Object methods: toString, equals, hashCode + // + // Object methods are defined as if via Arrays.toString, etc., + // is applied to the array of elements. Two equal vectors + // are required to have equal species and equal lane values. + + /** + * Returns a string representation of this vector, of the form + * {@code "[0,1,2...]"}, reporting the lane values of this vector, + * in lane order. + * + * The string is produced as if by a call to {@link + * java.util.Arrays#toString(short[]) Arrays.toString()}, + * as appropriate to the {@code short} array returned by + * {@link #toArray this.toArray()}. + * + * @return a string of the form {@code "[0,1,2...]"} + * reporting the lane values of this vector + */ + @Override + @ForceInline + public final + String toString() { + // now that toArray is strongly typed, we can define this + return Arrays.toString(toArray()); + } + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + boolean equals(Object obj) { + if (obj instanceof Vector) { + Vector that = (Vector) obj; + if (this.species().equals(that.species())) { + return this.eq(that.check(this.species())).allTrue(); + } + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public final + int hashCode() { + // now that toArray is strongly typed, we can define this + return Objects.hash(species(), Arrays.hashCode(toArray())); + } + + // ================================================ + + // Species + + /** + * Class representing {@link Float16Vector}'s of the same {@link VectorShape VectorShape}. + */ + /*package-private*/ + static final class Float16Species extends AbstractSpecies { + private Float16Species(VectorShape shape, + Class vectorType, + Class> maskType, + Class> shuffleType, + Function vectorFactory) { + super(shape, LaneType.of(Float16.class), + vectorType, maskType, shuffleType, + vectorFactory); + assert(this.elementSize() == Float16.SIZE); + } + + // Specializing overrides: + + @Override + @ForceInline + public final Class elementType() { + return Float16.class; + } + + @Override + @ForceInline + final Class genericElementType() { + return Float16.class; + } + + @SuppressWarnings("unchecked") + @Override + @ForceInline + public final Class vectorType() { + return (Class) vectorType; + } + + @Override + @ForceInline + public final long checkValue(long e) { + longToElementBits(e); // only for exception + return e; + } + + /*package-private*/ + @Override + @ForceInline + final Float16Vector broadcastBits(long bits) { + return (Float16Vector) + VectorSupport.fromBitsCoerced( + vectorType, laneTypeOrdinal(), laneCount, + bits, MODE_BROADCAST, this, + (bits_, s_) -> s_.rvOp(i -> bits_)); + } + + /*package-private*/ + @ForceInline + final Float16Vector broadcast(short e) { + return broadcastBits(toBits(e)); + } + + @Override + @ForceInline + public final Float16Vector broadcast(long e) { + return broadcastBits(longToElementBits(e)); + } + + /*package-private*/ + final @Override + @ForceInline + long longToElementBits(long value) { + // Do the conversion, and then test it for failure. + short e = float16ToRawShortBits(Float16.valueOf(value)); + if (shortBitsToFloat16(e).longValue() != value) { + throw badElementBits(value, e); + } + return toBits(e); + } + + /*package-private*/ + @ForceInline + static long toIntegralChecked(short e, boolean convertToInt) { + float ef = shortBitsToFloat16(e).floatValue(); + long value = convertToInt ? (int) ef : (long) ef; + if ((float) value != ef) { + throw badArrayBits(e, convertToInt, value); + } + return value; + } + + /* this non-public one is for internal conversions */ + @Override + @ForceInline + final Float16Vector fromIntValues(int[] values) { + VectorIntrinsics.requireLength(values.length, laneCount); + short[] va = new short[laneCount()]; + for (int i = 0; i < va.length; i++) { + int lv = values[i]; + short v = float16ToRawShortBits(Float16.valueOf(lv)); + va[i] = v; + if (Float16.valueOf(lv).intValue() != lv) { + throw badElementBits(lv, v); + } + } + return dummyVector().fromArray0(va, 0); + } + + // Virtual constructors + + @ForceInline + @Override final + public Float16Vector fromArray(Object a, int offset) { + // User entry point + // Defer only to the equivalent method on the vector class, using the same inputs + return Float16Vector + .fromArray(this, (short[]) a, offset); + } + + @ForceInline + @Override final + public Float16Vector fromMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { + // User entry point + // Defer only to the equivalent method on the vector class, using the same inputs + return Float16Vector + .fromMemorySegment(this, ms, offset, bo); + } + + @ForceInline + @Override final + Float16Vector dummyVector() { + return (Float16Vector) super.dummyVector(); + } + + /*package-private*/ + final @Override + @ForceInline + Float16Vector rvOp(RVOp f) { + short[] res = new short[laneCount()]; + for (int i = 0; i < res.length; i++) { + short bits = (short) f.apply(i); + res[i] = fromBits(bits); + } + return dummyVector().vectorFactory(res); + } + + Float16Vector vOp(FVOp f) { + short[] res = new short[laneCount()]; + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i); + } + return dummyVector().vectorFactory(res); + } + + Float16Vector vOp(VectorMask m, FVOp f) { + short[] res = new short[laneCount()]; + boolean[] mbits = ((AbstractMask)m).getBits(); + for (int i = 0; i < res.length; i++) { + if (mbits[i]) { + res[i] = f.apply(i); + } + } + return dummyVector().vectorFactory(res); + } + + /*package-private*/ + @ForceInline + Float16Vector ldOp(M memory, int offset, + FLdOp f) { + return dummyVector().ldOp(memory, offset, f); + } + + /*package-private*/ + @ForceInline + Float16Vector ldOp(M memory, int offset, + VectorMask m, + FLdOp f) { + return dummyVector().ldOp(memory, offset, m, f); + } + + /*package-private*/ + @ForceInline + Float16Vector ldLongOp(MemorySegment memory, long offset, + FLdLongOp f) { + return dummyVector().ldLongOp(memory, offset, f); + } + + /*package-private*/ + @ForceInline + Float16Vector ldLongOp(MemorySegment memory, long offset, + VectorMask m, + FLdLongOp f) { + return dummyVector().ldLongOp(memory, offset, m, f); + } + + /*package-private*/ + @ForceInline + void stOp(M memory, int offset, FStOp f) { + dummyVector().stOp(memory, offset, f); + } + + /*package-private*/ + @ForceInline + void stOp(M memory, int offset, + AbstractMask m, + FStOp f) { + dummyVector().stOp(memory, offset, m, f); + } + + /*package-private*/ + @ForceInline + void stLongOp(MemorySegment memory, long offset, FStLongOp f) { + dummyVector().stLongOp(memory, offset, f); + } + + /*package-private*/ + @ForceInline + void stLongOp(MemorySegment memory, long offset, + AbstractMask m, + FStLongOp f) { + dummyVector().stLongOp(memory, offset, m, f); + } + + // N.B. Make sure these constant vectors and + // masks load up correctly into registers. + // + // Also, see if we can avoid all that switching. + // Could we cache both vectors and both masks in + // this species object? + + // Zero and iota vector access + @Override + @ForceInline + public final Float16Vector zero() { + if ((Class) vectorType() == Float16VectorMax.class) + return Float16VectorMax.ZERO; + switch (vectorBitSize()) { + case 64: return Float16Vector64.ZERO; + case 128: return Float16Vector128.ZERO; + case 256: return Float16Vector256.ZERO; + case 512: return Float16Vector512.ZERO; + } + throw new AssertionError(); + } + + @Override + @ForceInline + public final Float16Vector iota() { + if ((Class) vectorType() == Float16VectorMax.class) + return Float16VectorMax.IOTA; + switch (vectorBitSize()) { + case 64: return Float16Vector64.IOTA; + case 128: return Float16Vector128.IOTA; + case 256: return Float16Vector256.IOTA; + case 512: return Float16Vector512.IOTA; + } + throw new AssertionError(); + } + + // Mask access + @Override + @ForceInline + public final VectorMask maskAll(boolean bit) { + if ((Class) vectorType() == Float16VectorMax.class) + return Float16VectorMax.Float16MaskMax.maskAll(bit); + switch (vectorBitSize()) { + case 64: return Float16Vector64.Float16Mask64.maskAll(bit); + case 128: return Float16Vector128.Float16Mask128.maskAll(bit); + case 256: return Float16Vector256.Float16Mask256.maskAll(bit); + case 512: return Float16Vector512.Float16Mask512.maskAll(bit); + } + throw new AssertionError(); + } + } + + /** + * Finds a species for an element type of {@code Float16} and shape. + * + * @param s the shape + * @return a species for an element type of {@code Float16} and shape + * @throws IllegalArgumentException if no such species exists for the shape + */ + static Float16Species species(VectorShape s) { + Objects.requireNonNull(s); + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (Float16Species) SPECIES_64; + case VectorShape.SK_128_BIT: return (Float16Species) SPECIES_128; + case VectorShape.SK_256_BIT: return (Float16Species) SPECIES_256; + case VectorShape.SK_512_BIT: return (Float16Species) SPECIES_512; + case VectorShape.SK_Max_BIT: return (Float16Species) SPECIES_MAX; + default: throw new IllegalArgumentException("Bad shape: " + s); + } + } + + /** Species representing {@link Float16Vector}s of {@link VectorShape#S_64_BIT VectorShape.S_64_BIT}. */ + public static final VectorSpecies SPECIES_64 + = new Float16Species(VectorShape.S_64_BIT, + Float16Vector64.class, + Float16Vector64.Float16Mask64.class, + Float16Vector64.Float16Shuffle64.class, + Float16Vector64::new); + + /** Species representing {@link Float16Vector}s of {@link VectorShape#S_128_BIT VectorShape.S_128_BIT}. */ + public static final VectorSpecies SPECIES_128 + = new Float16Species(VectorShape.S_128_BIT, + Float16Vector128.class, + Float16Vector128.Float16Mask128.class, + Float16Vector128.Float16Shuffle128.class, + Float16Vector128::new); + + /** Species representing {@link Float16Vector}s of {@link VectorShape#S_256_BIT VectorShape.S_256_BIT}. */ + public static final VectorSpecies SPECIES_256 + = new Float16Species(VectorShape.S_256_BIT, + Float16Vector256.class, + Float16Vector256.Float16Mask256.class, + Float16Vector256.Float16Shuffle256.class, + Float16Vector256::new); + + /** Species representing {@link Float16Vector}s of {@link VectorShape#S_512_BIT VectorShape.S_512_BIT}. */ + public static final VectorSpecies SPECIES_512 + = new Float16Species(VectorShape.S_512_BIT, + Float16Vector512.class, + Float16Vector512.Float16Mask512.class, + Float16Vector512.Float16Shuffle512.class, + Float16Vector512::new); + + /** Species representing {@link Float16Vector}s of {@link VectorShape#S_Max_BIT VectorShape.S_Max_BIT}. */ + public static final VectorSpecies SPECIES_MAX + = new Float16Species(VectorShape.S_Max_BIT, + Float16VectorMax.class, + Float16VectorMax.Float16MaskMax.class, + Float16VectorMax.Float16ShuffleMax.class, + Float16VectorMax::new); + + /** + * Preferred species for {@link Float16Vector}s. + * A preferred species is a species of maximal bit-size for the platform. + */ + public static final VectorSpecies SPECIES_PREFERRED + = (Float16Species) VectorSpecies.ofPreferred(Float16.class); +} + diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector128.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector128.java new file mode 100644 index 00000000000..65e2a2e1ba0 --- /dev/null +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector128.java @@ -0,0 +1,1037 @@ +/* + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.vector; + +import java.lang.foreign.MemorySegment; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.IntUnaryOperator; + +import jdk.internal.ValueBased; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.vector.VectorSupport; + +import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; + +// -- This file was mechanically generated: Do not edit! -- // + +@SuppressWarnings("cast") // warning: redundant cast +@ValueBased +final class Float16Vector128 extends Float16Vector { + static final Float16Species VSPECIES = + (Float16Species) Float16Vector.SPECIES_128; + + static final VectorShape VSHAPE = + VSPECIES.vectorShape(); + + static final Class VCLASS = Float16Vector128.class; + + static final int VSIZE = VSPECIES.vectorBitSize(); + + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // carrier type used by the JVM + + static final Class ETYPE = Float16.class; // used by the JVM + + Float16Vector128(short[] v) { + super(v); + } + + // For compatibility as Float16Vector128::new, + // stored into species.vectorFactory. + Float16Vector128(Object v) { + this((short[]) v); + } + + static final Float16Vector128 ZERO = new Float16Vector128(new short[VLENGTH]); + static final Float16Vector128 IOTA = new Float16Vector128(VSPECIES.iotaArray()); + + static { + // Warm up a few species caches. + // If we do this too much we will + // get NPEs from bootstrap circularity. + VSPECIES.dummyVector(); + VSPECIES.withLanes(LaneType.BYTE); + } + + // Specialized extractors + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractVector, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + @Override + public final Class elementType() { return Float16.class; } + + @ForceInline + final Class carrierType() { return CTYPE; } + + @ForceInline + @Override + public final int elementSize() { return Float16.SIZE; } + + @ForceInline + @Override + public final VectorShape shape() { return VSHAPE; } + + @ForceInline + @Override + public final int length() { return VLENGTH; } + + @ForceInline + @Override + public final int bitSize() { return VSIZE; } + + @ForceInline + @Override + public final int byteSize() { return VSIZE / Byte.SIZE; } + + /*package-private*/ + @ForceInline + final @Override + short[] vec() { + return (short[])getPayload(); + } + + /*package-private*/ + @ForceInline + final @Override + int laneTypeOrdinal() { + return LANE_TYPE_ORDINAL; + } + + // Virtualized constructors + + @Override + @ForceInline + public final Float16Vector128 broadcast(short e) { + return (Float16Vector128) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + public final Float16Vector128 broadcast(long e) { + return (Float16Vector128) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + Float16Mask128 maskFromArray(boolean[] bits) { + return new Float16Mask128(bits); + } + + @Override + @ForceInline + Float16Shuffle128 iotaShuffle() { return Float16Shuffle128.IOTA; } + + @Override + @ForceInline + Float16Shuffle128 iotaShuffle(int start, int step, boolean wrap) { + return (Float16Shuffle128) iotaShuffleTemplate((short) start, (short) step, wrap); + } + + @Override + @ForceInline + Float16Shuffle128 shuffleFromArray(int[] indices, int i) { return new Float16Shuffle128(indices, i); } + + @Override + @ForceInline + Float16Shuffle128 shuffleFromOp(IntUnaryOperator fn) { return new Float16Shuffle128(fn); } + + // Make a vector of the same species but the given elements: + @ForceInline + final @Override + Float16Vector128 vectorFactory(short[] vec) { + return new Float16Vector128(vec); + } + + @ForceInline + final @Override + ByteVector128 asByteVectorRaw() { + return (ByteVector128) super.asByteVectorRawTemplate(); // specialize + } + + @ForceInline + final @Override + AbstractVector asVectorRaw(LaneType laneType) { + return super.asVectorRawTemplate(laneType); // specialize + } + + // Unary operator + + @ForceInline + final @Override + Float16Vector128 uOp(FUnOp f) { + return (Float16Vector128) super.uOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector128 uOp(VectorMask m, FUnOp f) { + return (Float16Vector128) + super.uOpTemplate((Float16Mask128)m, f); // specialize + } + + @ForceInline + final @Override + Float16Vector128 uRawOp(FUnRawOp f) { + return (Float16Vector128) super.uRawOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector128 uRawOp(VectorMask m, FUnRawOp f) { + return (Float16Vector128) + super.uRawOpTemplate((Float16Mask128)m, f); // specialize + } + // Binary operator + + @ForceInline + final @Override + Float16Vector128 bOp(Vector v, FBinOp f) { + return (Float16Vector128) super.bOpTemplate((Float16Vector128)v, f); // specialize + } + + @ForceInline + final @Override + Float16Vector128 bOp(Vector v, + VectorMask m, FBinOp f) { + return (Float16Vector128) + super.bOpTemplate((Float16Vector128)v, (Float16Mask128)m, + f); // specialize + } + + // Ternary operator + + @ForceInline + final @Override + Float16Vector128 tOp(Vector v1, Vector v2, FTriOp f) { + return (Float16Vector128) + super.tOpTemplate((Float16Vector128)v1, (Float16Vector128)v2, + f); // specialize + } + + @ForceInline + final @Override + Float16Vector128 tOp(Vector v1, Vector v2, + VectorMask m, FTriOp f) { + return (Float16Vector128) + super.tOpTemplate((Float16Vector128)v1, (Float16Vector128)v2, + (Float16Mask128)m, f); // specialize + } + + @ForceInline + final @Override + short rOp(short v, VectorMask m, FBinOp f) { + return super.rOpTemplate(v, m, f); // specialize + } + + @Override + @ForceInline + public final + Vector convertShape(VectorOperators.Conversion conv, + VectorSpecies rsp, int part) { + return super.convertShapeTemplate(conv, rsp, part); // specialize + } + + @Override + @ForceInline + public final + Vector reinterpretShape(VectorSpecies toSpecies, int part) { + return super.reinterpretShapeTemplate(toSpecies, part); // specialize + } + + // Specialized algebraic operations: + + // The following definition forces a specialized version of this + // crucial method into the v-table of this class. A call to add() + // will inline to a call to lanewise(ADD,), at which point the JIT + // intrinsic will have the opcode of ADD, plus all the metadata + // for this particular class, enabling it to generate precise + // code. + // + // There is probably no benefit to the JIT to specialize the + // masked or broadcast versions of the lanewise method. + + @Override + @ForceInline + public Float16Vector128 lanewise(Unary op) { + return (Float16Vector128) super.lanewiseTemplate(op); // specialize + } + + @Override + @ForceInline + public Float16Vector128 lanewise(Unary op, VectorMask m) { + return (Float16Vector128) super.lanewiseTemplate(op, Float16Mask128.class, (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 lanewise(Binary op, Vector v) { + return (Float16Vector128) super.lanewiseTemplate(op, v); // specialize + } + + @Override + @ForceInline + public Float16Vector128 lanewise(Binary op, Vector v, VectorMask m) { + return (Float16Vector128) super.lanewiseTemplate(op, Float16Mask128.class, v, (Float16Mask128) m); // specialize + } + + + /*package-private*/ + @Override + @ForceInline + public final + Float16Vector128 + lanewise(Ternary op, Vector v1, Vector v2) { + return (Float16Vector128) super.lanewiseTemplate(op, v1, v2); // specialize + } + + @Override + @ForceInline + public final + Float16Vector128 + lanewise(Ternary op, Vector v1, Vector v2, VectorMask m) { + return (Float16Vector128) super.lanewiseTemplate(op, Float16Mask128.class, v1, v2, (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public final + Float16Vector128 addIndex(int scale) { + return (Float16Vector128) super.addIndexTemplate(scale); // specialize + } + + // Type specific horizontal reductions + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op) { + return super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op, + VectorMask m) { + return super.reduceLanesTemplate(op, Float16Mask128.class, (Float16Mask128) m); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op) { + return (long) super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op, + VectorMask m) { + return (long) super.reduceLanesTemplate(op, Float16Mask128.class, (Float16Mask128) m); // specialized + } + + @Override + @ForceInline + final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { + throw new AssertionError(); + } + + @Override + @ForceInline + public final Float16Shuffle128 toShuffle() { + return (Float16Shuffle128) toShuffle(VSPECIES, false); + } + + // Specialized unary testing + + @Override + @ForceInline + public final Float16Mask128 test(Test op) { + return super.testTemplate(Float16Mask128.class, op); // specialize + } + + @Override + @ForceInline + public final Float16Mask128 test(Test op, VectorMask m) { + return super.testTemplate(Float16Mask128.class, op, (Float16Mask128) m); // specialize + } + + // Specialized comparisons + + @Override + @ForceInline + public final Float16Mask128 compare(Comparison op, Vector v) { + return super.compareTemplate(Float16Mask128.class, op, v); // specialize + } + + @Override + @ForceInline + public final Float16Mask128 compare(Comparison op, short s) { + return super.compareTemplate(Float16Mask128.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask128 compare(Comparison op, long s) { + return super.compareTemplate(Float16Mask128.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask128 compare(Comparison op, Vector v, VectorMask m) { + return super.compareTemplate(Float16Mask128.class, op, v, (Float16Mask128) m); + } + + + @Override + @ForceInline + public Float16Vector128 blend(Vector v, VectorMask m) { + return (Float16Vector128) + super.blendTemplate(Float16Mask128.class, + (Float16Vector128) v, + (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 slice(int origin, Vector v) { + return (Float16Vector128) super.sliceTemplate(origin, v); // specialize + } + + @Override + @ForceInline + public Float16Vector128 slice(int origin) { + return (Float16Vector128) super.sliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector128 unslice(int origin, Vector w, int part) { + return (Float16Vector128) super.unsliceTemplate(origin, w, part); // specialize + } + + @Override + @ForceInline + public Float16Vector128 unslice(int origin, Vector w, int part, VectorMask m) { + return (Float16Vector128) + super.unsliceTemplate(Float16Mask128.class, + origin, w, part, + (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 unslice(int origin) { + return (Float16Vector128) super.unsliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector128 rearrange(VectorShuffle s) { + return (Float16Vector128) + super.rearrangeTemplate(Float16Shuffle128.class, + (Float16Shuffle128) s); // specialize + } + + @Override + @ForceInline + public Float16Vector128 rearrange(VectorShuffle shuffle, + VectorMask m) { + return (Float16Vector128) + super.rearrangeTemplate(Float16Shuffle128.class, + Float16Mask128.class, + (Float16Shuffle128) shuffle, + (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 rearrange(VectorShuffle s, + Vector v) { + return (Float16Vector128) + super.rearrangeTemplate(Float16Shuffle128.class, + (Float16Shuffle128) s, + (Float16Vector128) v); // specialize + } + + @Override + @ForceInline + public Float16Vector128 compress(VectorMask m) { + return (Float16Vector128) + super.compressTemplate(Float16Mask128.class, + (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 expand(VectorMask m) { + return (Float16Vector128) + super.expandTemplate(Float16Mask128.class, + (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 selectFrom(Vector v) { + return (Float16Vector128) + super.selectFromTemplate((Float16Vector128) v); // specialize + } + + @Override + @ForceInline + public Float16Vector128 selectFrom(Vector v, + VectorMask m) { + return (Float16Vector128) + super.selectFromTemplate((Float16Vector128) v, + Float16Mask128.class, (Float16Mask128) m); // specialize + } + + @Override + @ForceInline + public Float16Vector128 selectFrom(Vector v1, + Vector v2) { + return (Float16Vector128) + super.selectFromTemplate((Float16Vector128) v1, (Float16Vector128) v2); // specialize + } + + @ForceInline + @Override + public short lane(int i) { + short bits; + switch(i) { + case 0: bits = laneHelper(0); break; + case 1: bits = laneHelper(1); break; + case 2: bits = laneHelper(2); break; + case 3: bits = laneHelper(3); break; + case 4: bits = laneHelper(4); break; + case 5: bits = laneHelper(5); break; + case 6: bits = laneHelper(6); break; + case 7: bits = laneHelper(7); break; + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + return bits; + } + + @ForceInline + public short laneHelper(int i) { + return (short) VectorSupport.extract( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, + (vec, ix) -> { + short[] vecarr = vec.vec(); + return vecarr[ix]; + }); + } + + @ForceInline + @Override + public Float16Vector128 withLane(int i, short e) { + switch(i) { + case 0: return withLaneHelper(0, e); + case 1: return withLaneHelper(1, e); + case 2: return withLaneHelper(2, e); + case 3: return withLaneHelper(3, e); + case 4: return withLaneHelper(4, e); + case 5: return withLaneHelper(5, e); + case 6: return withLaneHelper(6, e); + case 7: return withLaneHelper(7, e); + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + } + + @ForceInline + public Float16Vector128 withLaneHelper(int i, short e) { + return VectorSupport.insert( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (long)e, + (v, ix, bits) -> { + short[] res = v.vec().clone(); + res[ix] = (short)bits; + return v.vectorFactory(res); + }); + } + + // Mask + @ValueBased + static final class Float16Mask128 extends AbstractMask { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Mask128(boolean[] bits) { + this(bits, 0); + } + + Float16Mask128(boolean[] bits, int offset) { + super(prepare(bits, offset)); + } + + Float16Mask128(boolean val) { + super(prepare(val)); + } + + private static boolean[] prepare(boolean[] bits, int offset) { + boolean[] newBits = new boolean[VSPECIES.laneCount()]; + for (int i = 0; i < newBits.length; i++) { + newBits[i] = bits[offset + i]; + } + return newBits; + } + + private static boolean[] prepare(boolean val) { + boolean[] bits = new boolean[VSPECIES.laneCount()]; + Arrays.fill(bits, val); + return bits; + } + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractMask, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + boolean[] getBits() { + return (boolean[])getPayload(); + } + + @Override + Float16Mask128 uOp(MUnOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i]); + } + return new Float16Mask128(res); + } + + @Override + Float16Mask128 bOp(VectorMask m, MBinOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + boolean[] mbits = ((Float16Mask128)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i], mbits[i]); + } + return new Float16Mask128(res); + } + + @ForceInline + @Override + public final + Float16Vector128 toVector() { + return (Float16Vector128) super.toVectorTemplate(); // specialize + } + + /** + * Helper function for lane-wise mask conversions. + * This function kicks in after intrinsic failure. + */ + @ForceInline + private final + VectorMask defaultMaskCast(AbstractSpecies dsp) { + if (length() != dsp.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + boolean[] maskArray = toArray(); + return dsp.maskFactory(maskArray).check(dsp); + } + + @Override + @ForceInline + public VectorMask cast(VectorSpecies dsp) { + AbstractSpecies species = (AbstractSpecies) dsp; + if (length() != species.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + + return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST, + this.getClass(), LANE_TYPE_ORDINAL, VLENGTH, + species.maskType(), species.laneTypeOrdinal(), VLENGTH, + this, species, + (m, s) -> s.maskFactory(m.toArray()).check(s)); + } + + @Override + @ForceInline + /*package-private*/ + Float16Mask128 indexPartiallyInUpperRange(long offset, long limit) { + return (Float16Mask128) VectorSupport.indexPartiallyInUpperRange( + Float16Mask128.class, LANE_TYPE_ORDINAL, VLENGTH, offset, limit, + (o, l) -> (Float16Mask128) TRUE_MASK.indexPartiallyInRange(o, l)); + } + + // Unary operations + + @Override + @ForceInline + public Float16Mask128 not() { + return xor(maskAll(true)); + } + + @Override + @ForceInline + public Float16Mask128 compress() { + return (Float16Mask128)VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_MASK_COMPRESS, + Float16Vector128.class, Float16Mask128.class, LANE_TYPE_ORDINAL, VLENGTH, null, this, + (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, Float16.float16ToRawShortBits(Float16.valueOf(m1.trueCount())))); + } + + + // Binary operations + + @Override + @ForceInline + public Float16Mask128 and(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask128 m = (Float16Mask128)mask; + return VectorSupport.binaryOp(VECTOR_OP_AND, Float16Mask128.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a & b)); + } + + @Override + @ForceInline + public Float16Mask128 or(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask128 m = (Float16Mask128)mask; + return VectorSupport.binaryOp(VECTOR_OP_OR, Float16Mask128.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a | b)); + } + + @Override + @ForceInline + public Float16Mask128 xor(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask128 m = (Float16Mask128)mask; + return VectorSupport.binaryOp(VECTOR_OP_XOR, Float16Mask128.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a ^ b)); + } + + // Mask Query operations + + @Override + @ForceInline + public int trueCount() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TRUECOUNT, Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> trueCountHelper(m.getBits())); + } + + @Override + @ForceInline + public int firstTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_FIRSTTRUE, Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> firstTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public int lastTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_LASTTRUE, Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> lastTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public long toLong() { + if (length() > Long.SIZE) { + throw new UnsupportedOperationException("too many lanes for one long"); + } + return VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TOLONG, Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> toLongHelper(m.getBits())); + } + + // laneIsSet + + @Override + @ForceInline + public boolean laneIsSet(int i) { + Objects.checkIndex(i, length()); + return VectorSupport.extract(Float16Mask128.class, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (m, idx) -> (m.getBits()[idx] ? 1L : 0L)) == 1L; + } + + // Reductions + + @Override + @ForceInline + public boolean anyTrue() { + return VectorSupport.test(BT_ne, Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((Float16Mask128)m).getBits())); + } + + @Override + @ForceInline + public boolean allTrue() { + return VectorSupport.test(BT_overflow, Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((Float16Mask128)m).getBits())); + } + + @ForceInline + /*package-private*/ + static Float16Mask128 maskAll(boolean bit) { + return VectorSupport.fromBitsCoerced(Float16Mask128.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + } + private static final Float16Mask128 TRUE_MASK = new Float16Mask128(true); + private static final Float16Mask128 FALSE_MASK = new Float16Mask128(false); + + } + + // Shuffle + @ValueBased + static final class Float16Shuffle128 extends AbstractShuffle { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Shuffle128(short[] indices) { + super(indices); + assert(VLENGTH == indices.length); + assert(indicesInRange(indices)); + } + + Float16Shuffle128(int[] indices, int i) { + this(prepare(indices, i)); + } + + Float16Shuffle128(IntUnaryOperator fn) { + this(prepare(fn)); + } + + short[] indices() { + return (short[])getPayload(); + } + + @Override + @ForceInline + public Float16Species vspecies() { + return VSPECIES; + } + + static { + // There must be enough bits in the shuffle lanes to encode + // VLENGTH valid indexes and VLENGTH exceptional ones. + assert(VLENGTH < Short.MAX_VALUE); + assert(Short.MIN_VALUE <= -VLENGTH); + } + static final Float16Shuffle128 IOTA = new Float16Shuffle128(IDENTITY); + + @Override + @ForceInline + public Float16Vector128 toVector() { + return (Float16Vector128) toBitsVector().castShape(VSPECIES, 0); + } + + @Override + @ForceInline + ShortVector128 toBitsVector() { + return (ShortVector128) super.toBitsVectorTemplate(); + } + + @Override + ShortVector128 toBitsVector0() { + return ((ShortVector128) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); + } + + @Override + @ForceInline + public int laneSource(int i) { + return (int)toBitsVector().lane(i); + } + + @Override + @ForceInline + public void intoArray(int[] a, int offset) { + VectorSpecies species = IntVector.SPECIES_128; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoArray(a, offset); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoArray(a, offset + species.length()); + } + + @Override + @ForceInline + public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { + VectorSpecies species = IntVector.SPECIES_128; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoMemorySegment(ms, offset, bo); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoMemorySegment(ms, offset + species.vectorByteSize(), bo); + } + + @Override + @ForceInline + public final Float16Mask128 laneIsValid() { + return (Float16Mask128) toBitsVector().compare(VectorOperators.GE, 0) + .cast(VSPECIES); + } + + @ForceInline + @Override + public final Float16Shuffle128 rearrange(VectorShuffle shuffle) { + Float16Shuffle128 concreteShuffle = (Float16Shuffle128) shuffle; + return (Float16Shuffle128) toBitsVector().rearrange(concreteShuffle.cast(ShortVector.SPECIES_128)) + .toShuffle(VSPECIES, false); + } + + @ForceInline + @Override + public final Float16Shuffle128 wrapIndexes() { + ShortVector128 v = toBitsVector(); + if ((length() & (length() - 1)) == 0) { + v = (ShortVector128) v.lanewise(VectorOperators.AND, length() - 1); + } else { + v = (ShortVector128) v.blend(v.lanewise(VectorOperators.ADD, length()), + v.compare(VectorOperators.LT, 0)); + } + return (Float16Shuffle128) v.toShuffle(VSPECIES, false); + } + + private static short[] prepare(int[] indices, int offset) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = indices[offset + i]; + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static short[] prepare(IntUnaryOperator f) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = f.applyAsInt(i); + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static boolean indicesInRange(short[] indices) { + int length = indices.length; + for (short si : indices) { + if (si >= (short)length || si < (short)(-length)) { + String msg = ("index "+si+"out of range ["+length+"] in "+ + java.util.Arrays.toString(indices)); + throw new AssertionError(msg); + } + } + return true; + } + } + + // ================================================ + + // Specialized low-level memory operations. + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset) { + return super.fromArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, VectorMask m, int offsetInRange) { + return super.fromArray0Template(Float16Mask128.class, a, offset, (Float16Mask128) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, int[] indexMap, int mapOffset, VectorMask m) { + return super.fromArray0Template(Float16Mask128.class, a, offset, indexMap, mapOffset, (Float16Mask128) m); + } + + + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset) { + return super.fromMemorySegment0Template(ms, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset, VectorMask m, int offsetInRange) { + return super.fromMemorySegment0Template(Float16Mask128.class, ms, offset, (Float16Mask128) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset) { + super.intoArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset, VectorMask m) { + super.intoArray0Template(Float16Mask128.class, a, offset, (Float16Mask128) m); + } + + + + @ForceInline + @Override + final + void intoMemorySegment0(MemorySegment ms, long offset, VectorMask m) { + super.intoMemorySegment0Template(Float16Mask128.class, ms, offset, (Float16Mask128) m); + } + + + // End of specialized low-level memory operations. + + // ================================================ + +} + diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector256.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector256.java new file mode 100644 index 00000000000..0ec038c5077 --- /dev/null +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector256.java @@ -0,0 +1,1053 @@ +/* + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.vector; + +import java.lang.foreign.MemorySegment; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.IntUnaryOperator; + +import jdk.internal.ValueBased; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.vector.VectorSupport; + +import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; + +// -- This file was mechanically generated: Do not edit! -- // + +@SuppressWarnings("cast") // warning: redundant cast +@ValueBased +final class Float16Vector256 extends Float16Vector { + static final Float16Species VSPECIES = + (Float16Species) Float16Vector.SPECIES_256; + + static final VectorShape VSHAPE = + VSPECIES.vectorShape(); + + static final Class VCLASS = Float16Vector256.class; + + static final int VSIZE = VSPECIES.vectorBitSize(); + + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // carrier type used by the JVM + + static final Class ETYPE = Float16.class; // used by the JVM + + Float16Vector256(short[] v) { + super(v); + } + + // For compatibility as Float16Vector256::new, + // stored into species.vectorFactory. + Float16Vector256(Object v) { + this((short[]) v); + } + + static final Float16Vector256 ZERO = new Float16Vector256(new short[VLENGTH]); + static final Float16Vector256 IOTA = new Float16Vector256(VSPECIES.iotaArray()); + + static { + // Warm up a few species caches. + // If we do this too much we will + // get NPEs from bootstrap circularity. + VSPECIES.dummyVector(); + VSPECIES.withLanes(LaneType.BYTE); + } + + // Specialized extractors + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractVector, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + @Override + public final Class elementType() { return Float16.class; } + + @ForceInline + final Class carrierType() { return CTYPE; } + + @ForceInline + @Override + public final int elementSize() { return Float16.SIZE; } + + @ForceInline + @Override + public final VectorShape shape() { return VSHAPE; } + + @ForceInline + @Override + public final int length() { return VLENGTH; } + + @ForceInline + @Override + public final int bitSize() { return VSIZE; } + + @ForceInline + @Override + public final int byteSize() { return VSIZE / Byte.SIZE; } + + /*package-private*/ + @ForceInline + final @Override + short[] vec() { + return (short[])getPayload(); + } + + /*package-private*/ + @ForceInline + final @Override + int laneTypeOrdinal() { + return LANE_TYPE_ORDINAL; + } + + // Virtualized constructors + + @Override + @ForceInline + public final Float16Vector256 broadcast(short e) { + return (Float16Vector256) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + public final Float16Vector256 broadcast(long e) { + return (Float16Vector256) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + Float16Mask256 maskFromArray(boolean[] bits) { + return new Float16Mask256(bits); + } + + @Override + @ForceInline + Float16Shuffle256 iotaShuffle() { return Float16Shuffle256.IOTA; } + + @Override + @ForceInline + Float16Shuffle256 iotaShuffle(int start, int step, boolean wrap) { + return (Float16Shuffle256) iotaShuffleTemplate((short) start, (short) step, wrap); + } + + @Override + @ForceInline + Float16Shuffle256 shuffleFromArray(int[] indices, int i) { return new Float16Shuffle256(indices, i); } + + @Override + @ForceInline + Float16Shuffle256 shuffleFromOp(IntUnaryOperator fn) { return new Float16Shuffle256(fn); } + + // Make a vector of the same species but the given elements: + @ForceInline + final @Override + Float16Vector256 vectorFactory(short[] vec) { + return new Float16Vector256(vec); + } + + @ForceInline + final @Override + ByteVector256 asByteVectorRaw() { + return (ByteVector256) super.asByteVectorRawTemplate(); // specialize + } + + @ForceInline + final @Override + AbstractVector asVectorRaw(LaneType laneType) { + return super.asVectorRawTemplate(laneType); // specialize + } + + // Unary operator + + @ForceInline + final @Override + Float16Vector256 uOp(FUnOp f) { + return (Float16Vector256) super.uOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector256 uOp(VectorMask m, FUnOp f) { + return (Float16Vector256) + super.uOpTemplate((Float16Mask256)m, f); // specialize + } + + @ForceInline + final @Override + Float16Vector256 uRawOp(FUnRawOp f) { + return (Float16Vector256) super.uRawOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector256 uRawOp(VectorMask m, FUnRawOp f) { + return (Float16Vector256) + super.uRawOpTemplate((Float16Mask256)m, f); // specialize + } + // Binary operator + + @ForceInline + final @Override + Float16Vector256 bOp(Vector v, FBinOp f) { + return (Float16Vector256) super.bOpTemplate((Float16Vector256)v, f); // specialize + } + + @ForceInline + final @Override + Float16Vector256 bOp(Vector v, + VectorMask m, FBinOp f) { + return (Float16Vector256) + super.bOpTemplate((Float16Vector256)v, (Float16Mask256)m, + f); // specialize + } + + // Ternary operator + + @ForceInline + final @Override + Float16Vector256 tOp(Vector v1, Vector v2, FTriOp f) { + return (Float16Vector256) + super.tOpTemplate((Float16Vector256)v1, (Float16Vector256)v2, + f); // specialize + } + + @ForceInline + final @Override + Float16Vector256 tOp(Vector v1, Vector v2, + VectorMask m, FTriOp f) { + return (Float16Vector256) + super.tOpTemplate((Float16Vector256)v1, (Float16Vector256)v2, + (Float16Mask256)m, f); // specialize + } + + @ForceInline + final @Override + short rOp(short v, VectorMask m, FBinOp f) { + return super.rOpTemplate(v, m, f); // specialize + } + + @Override + @ForceInline + public final + Vector convertShape(VectorOperators.Conversion conv, + VectorSpecies rsp, int part) { + return super.convertShapeTemplate(conv, rsp, part); // specialize + } + + @Override + @ForceInline + public final + Vector reinterpretShape(VectorSpecies toSpecies, int part) { + return super.reinterpretShapeTemplate(toSpecies, part); // specialize + } + + // Specialized algebraic operations: + + // The following definition forces a specialized version of this + // crucial method into the v-table of this class. A call to add() + // will inline to a call to lanewise(ADD,), at which point the JIT + // intrinsic will have the opcode of ADD, plus all the metadata + // for this particular class, enabling it to generate precise + // code. + // + // There is probably no benefit to the JIT to specialize the + // masked or broadcast versions of the lanewise method. + + @Override + @ForceInline + public Float16Vector256 lanewise(Unary op) { + return (Float16Vector256) super.lanewiseTemplate(op); // specialize + } + + @Override + @ForceInline + public Float16Vector256 lanewise(Unary op, VectorMask m) { + return (Float16Vector256) super.lanewiseTemplate(op, Float16Mask256.class, (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 lanewise(Binary op, Vector v) { + return (Float16Vector256) super.lanewiseTemplate(op, v); // specialize + } + + @Override + @ForceInline + public Float16Vector256 lanewise(Binary op, Vector v, VectorMask m) { + return (Float16Vector256) super.lanewiseTemplate(op, Float16Mask256.class, v, (Float16Mask256) m); // specialize + } + + + /*package-private*/ + @Override + @ForceInline + public final + Float16Vector256 + lanewise(Ternary op, Vector v1, Vector v2) { + return (Float16Vector256) super.lanewiseTemplate(op, v1, v2); // specialize + } + + @Override + @ForceInline + public final + Float16Vector256 + lanewise(Ternary op, Vector v1, Vector v2, VectorMask m) { + return (Float16Vector256) super.lanewiseTemplate(op, Float16Mask256.class, v1, v2, (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public final + Float16Vector256 addIndex(int scale) { + return (Float16Vector256) super.addIndexTemplate(scale); // specialize + } + + // Type specific horizontal reductions + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op) { + return super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op, + VectorMask m) { + return super.reduceLanesTemplate(op, Float16Mask256.class, (Float16Mask256) m); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op) { + return (long) super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op, + VectorMask m) { + return (long) super.reduceLanesTemplate(op, Float16Mask256.class, (Float16Mask256) m); // specialized + } + + @Override + @ForceInline + final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { + throw new AssertionError(); + } + + @Override + @ForceInline + public final Float16Shuffle256 toShuffle() { + return (Float16Shuffle256) toShuffle(VSPECIES, false); + } + + // Specialized unary testing + + @Override + @ForceInline + public final Float16Mask256 test(Test op) { + return super.testTemplate(Float16Mask256.class, op); // specialize + } + + @Override + @ForceInline + public final Float16Mask256 test(Test op, VectorMask m) { + return super.testTemplate(Float16Mask256.class, op, (Float16Mask256) m); // specialize + } + + // Specialized comparisons + + @Override + @ForceInline + public final Float16Mask256 compare(Comparison op, Vector v) { + return super.compareTemplate(Float16Mask256.class, op, v); // specialize + } + + @Override + @ForceInline + public final Float16Mask256 compare(Comparison op, short s) { + return super.compareTemplate(Float16Mask256.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask256 compare(Comparison op, long s) { + return super.compareTemplate(Float16Mask256.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask256 compare(Comparison op, Vector v, VectorMask m) { + return super.compareTemplate(Float16Mask256.class, op, v, (Float16Mask256) m); + } + + + @Override + @ForceInline + public Float16Vector256 blend(Vector v, VectorMask m) { + return (Float16Vector256) + super.blendTemplate(Float16Mask256.class, + (Float16Vector256) v, + (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 slice(int origin, Vector v) { + return (Float16Vector256) super.sliceTemplate(origin, v); // specialize + } + + @Override + @ForceInline + public Float16Vector256 slice(int origin) { + return (Float16Vector256) super.sliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector256 unslice(int origin, Vector w, int part) { + return (Float16Vector256) super.unsliceTemplate(origin, w, part); // specialize + } + + @Override + @ForceInline + public Float16Vector256 unslice(int origin, Vector w, int part, VectorMask m) { + return (Float16Vector256) + super.unsliceTemplate(Float16Mask256.class, + origin, w, part, + (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 unslice(int origin) { + return (Float16Vector256) super.unsliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector256 rearrange(VectorShuffle s) { + return (Float16Vector256) + super.rearrangeTemplate(Float16Shuffle256.class, + (Float16Shuffle256) s); // specialize + } + + @Override + @ForceInline + public Float16Vector256 rearrange(VectorShuffle shuffle, + VectorMask m) { + return (Float16Vector256) + super.rearrangeTemplate(Float16Shuffle256.class, + Float16Mask256.class, + (Float16Shuffle256) shuffle, + (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 rearrange(VectorShuffle s, + Vector v) { + return (Float16Vector256) + super.rearrangeTemplate(Float16Shuffle256.class, + (Float16Shuffle256) s, + (Float16Vector256) v); // specialize + } + + @Override + @ForceInline + public Float16Vector256 compress(VectorMask m) { + return (Float16Vector256) + super.compressTemplate(Float16Mask256.class, + (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 expand(VectorMask m) { + return (Float16Vector256) + super.expandTemplate(Float16Mask256.class, + (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 selectFrom(Vector v) { + return (Float16Vector256) + super.selectFromTemplate((Float16Vector256) v); // specialize + } + + @Override + @ForceInline + public Float16Vector256 selectFrom(Vector v, + VectorMask m) { + return (Float16Vector256) + super.selectFromTemplate((Float16Vector256) v, + Float16Mask256.class, (Float16Mask256) m); // specialize + } + + @Override + @ForceInline + public Float16Vector256 selectFrom(Vector v1, + Vector v2) { + return (Float16Vector256) + super.selectFromTemplate((Float16Vector256) v1, (Float16Vector256) v2); // specialize + } + + @ForceInline + @Override + public short lane(int i) { + short bits; + switch(i) { + case 0: bits = laneHelper(0); break; + case 1: bits = laneHelper(1); break; + case 2: bits = laneHelper(2); break; + case 3: bits = laneHelper(3); break; + case 4: bits = laneHelper(4); break; + case 5: bits = laneHelper(5); break; + case 6: bits = laneHelper(6); break; + case 7: bits = laneHelper(7); break; + case 8: bits = laneHelper(8); break; + case 9: bits = laneHelper(9); break; + case 10: bits = laneHelper(10); break; + case 11: bits = laneHelper(11); break; + case 12: bits = laneHelper(12); break; + case 13: bits = laneHelper(13); break; + case 14: bits = laneHelper(14); break; + case 15: bits = laneHelper(15); break; + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + return bits; + } + + @ForceInline + public short laneHelper(int i) { + return (short) VectorSupport.extract( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, + (vec, ix) -> { + short[] vecarr = vec.vec(); + return vecarr[ix]; + }); + } + + @ForceInline + @Override + public Float16Vector256 withLane(int i, short e) { + switch(i) { + case 0: return withLaneHelper(0, e); + case 1: return withLaneHelper(1, e); + case 2: return withLaneHelper(2, e); + case 3: return withLaneHelper(3, e); + case 4: return withLaneHelper(4, e); + case 5: return withLaneHelper(5, e); + case 6: return withLaneHelper(6, e); + case 7: return withLaneHelper(7, e); + case 8: return withLaneHelper(8, e); + case 9: return withLaneHelper(9, e); + case 10: return withLaneHelper(10, e); + case 11: return withLaneHelper(11, e); + case 12: return withLaneHelper(12, e); + case 13: return withLaneHelper(13, e); + case 14: return withLaneHelper(14, e); + case 15: return withLaneHelper(15, e); + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + } + + @ForceInline + public Float16Vector256 withLaneHelper(int i, short e) { + return VectorSupport.insert( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (long)e, + (v, ix, bits) -> { + short[] res = v.vec().clone(); + res[ix] = (short)bits; + return v.vectorFactory(res); + }); + } + + // Mask + @ValueBased + static final class Float16Mask256 extends AbstractMask { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Mask256(boolean[] bits) { + this(bits, 0); + } + + Float16Mask256(boolean[] bits, int offset) { + super(prepare(bits, offset)); + } + + Float16Mask256(boolean val) { + super(prepare(val)); + } + + private static boolean[] prepare(boolean[] bits, int offset) { + boolean[] newBits = new boolean[VSPECIES.laneCount()]; + for (int i = 0; i < newBits.length; i++) { + newBits[i] = bits[offset + i]; + } + return newBits; + } + + private static boolean[] prepare(boolean val) { + boolean[] bits = new boolean[VSPECIES.laneCount()]; + Arrays.fill(bits, val); + return bits; + } + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractMask, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + boolean[] getBits() { + return (boolean[])getPayload(); + } + + @Override + Float16Mask256 uOp(MUnOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i]); + } + return new Float16Mask256(res); + } + + @Override + Float16Mask256 bOp(VectorMask m, MBinOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + boolean[] mbits = ((Float16Mask256)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i], mbits[i]); + } + return new Float16Mask256(res); + } + + @ForceInline + @Override + public final + Float16Vector256 toVector() { + return (Float16Vector256) super.toVectorTemplate(); // specialize + } + + /** + * Helper function for lane-wise mask conversions. + * This function kicks in after intrinsic failure. + */ + @ForceInline + private final + VectorMask defaultMaskCast(AbstractSpecies dsp) { + if (length() != dsp.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + boolean[] maskArray = toArray(); + return dsp.maskFactory(maskArray).check(dsp); + } + + @Override + @ForceInline + public VectorMask cast(VectorSpecies dsp) { + AbstractSpecies species = (AbstractSpecies) dsp; + if (length() != species.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + + return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST, + this.getClass(), LANE_TYPE_ORDINAL, VLENGTH, + species.maskType(), species.laneTypeOrdinal(), VLENGTH, + this, species, + (m, s) -> s.maskFactory(m.toArray()).check(s)); + } + + @Override + @ForceInline + /*package-private*/ + Float16Mask256 indexPartiallyInUpperRange(long offset, long limit) { + return (Float16Mask256) VectorSupport.indexPartiallyInUpperRange( + Float16Mask256.class, LANE_TYPE_ORDINAL, VLENGTH, offset, limit, + (o, l) -> (Float16Mask256) TRUE_MASK.indexPartiallyInRange(o, l)); + } + + // Unary operations + + @Override + @ForceInline + public Float16Mask256 not() { + return xor(maskAll(true)); + } + + @Override + @ForceInline + public Float16Mask256 compress() { + return (Float16Mask256)VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_MASK_COMPRESS, + Float16Vector256.class, Float16Mask256.class, LANE_TYPE_ORDINAL, VLENGTH, null, this, + (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, Float16.float16ToRawShortBits(Float16.valueOf(m1.trueCount())))); + } + + + // Binary operations + + @Override + @ForceInline + public Float16Mask256 and(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask256 m = (Float16Mask256)mask; + return VectorSupport.binaryOp(VECTOR_OP_AND, Float16Mask256.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a & b)); + } + + @Override + @ForceInline + public Float16Mask256 or(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask256 m = (Float16Mask256)mask; + return VectorSupport.binaryOp(VECTOR_OP_OR, Float16Mask256.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a | b)); + } + + @Override + @ForceInline + public Float16Mask256 xor(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask256 m = (Float16Mask256)mask; + return VectorSupport.binaryOp(VECTOR_OP_XOR, Float16Mask256.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a ^ b)); + } + + // Mask Query operations + + @Override + @ForceInline + public int trueCount() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TRUECOUNT, Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> trueCountHelper(m.getBits())); + } + + @Override + @ForceInline + public int firstTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_FIRSTTRUE, Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> firstTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public int lastTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_LASTTRUE, Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> lastTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public long toLong() { + if (length() > Long.SIZE) { + throw new UnsupportedOperationException("too many lanes for one long"); + } + return VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TOLONG, Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> toLongHelper(m.getBits())); + } + + // laneIsSet + + @Override + @ForceInline + public boolean laneIsSet(int i) { + Objects.checkIndex(i, length()); + return VectorSupport.extract(Float16Mask256.class, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (m, idx) -> (m.getBits()[idx] ? 1L : 0L)) == 1L; + } + + // Reductions + + @Override + @ForceInline + public boolean anyTrue() { + return VectorSupport.test(BT_ne, Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((Float16Mask256)m).getBits())); + } + + @Override + @ForceInline + public boolean allTrue() { + return VectorSupport.test(BT_overflow, Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((Float16Mask256)m).getBits())); + } + + @ForceInline + /*package-private*/ + static Float16Mask256 maskAll(boolean bit) { + return VectorSupport.fromBitsCoerced(Float16Mask256.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + } + private static final Float16Mask256 TRUE_MASK = new Float16Mask256(true); + private static final Float16Mask256 FALSE_MASK = new Float16Mask256(false); + + } + + // Shuffle + @ValueBased + static final class Float16Shuffle256 extends AbstractShuffle { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Shuffle256(short[] indices) { + super(indices); + assert(VLENGTH == indices.length); + assert(indicesInRange(indices)); + } + + Float16Shuffle256(int[] indices, int i) { + this(prepare(indices, i)); + } + + Float16Shuffle256(IntUnaryOperator fn) { + this(prepare(fn)); + } + + short[] indices() { + return (short[])getPayload(); + } + + @Override + @ForceInline + public Float16Species vspecies() { + return VSPECIES; + } + + static { + // There must be enough bits in the shuffle lanes to encode + // VLENGTH valid indexes and VLENGTH exceptional ones. + assert(VLENGTH < Short.MAX_VALUE); + assert(Short.MIN_VALUE <= -VLENGTH); + } + static final Float16Shuffle256 IOTA = new Float16Shuffle256(IDENTITY); + + @Override + @ForceInline + public Float16Vector256 toVector() { + return (Float16Vector256) toBitsVector().castShape(VSPECIES, 0); + } + + @Override + @ForceInline + ShortVector256 toBitsVector() { + return (ShortVector256) super.toBitsVectorTemplate(); + } + + @Override + ShortVector256 toBitsVector0() { + return ((ShortVector256) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); + } + + @Override + @ForceInline + public int laneSource(int i) { + return (int)toBitsVector().lane(i); + } + + @Override + @ForceInline + public void intoArray(int[] a, int offset) { + VectorSpecies species = IntVector.SPECIES_256; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoArray(a, offset); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoArray(a, offset + species.length()); + } + + @Override + @ForceInline + public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { + VectorSpecies species = IntVector.SPECIES_256; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoMemorySegment(ms, offset, bo); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoMemorySegment(ms, offset + species.vectorByteSize(), bo); + } + + @Override + @ForceInline + public final Float16Mask256 laneIsValid() { + return (Float16Mask256) toBitsVector().compare(VectorOperators.GE, 0) + .cast(VSPECIES); + } + + @ForceInline + @Override + public final Float16Shuffle256 rearrange(VectorShuffle shuffle) { + Float16Shuffle256 concreteShuffle = (Float16Shuffle256) shuffle; + return (Float16Shuffle256) toBitsVector().rearrange(concreteShuffle.cast(ShortVector.SPECIES_256)) + .toShuffle(VSPECIES, false); + } + + @ForceInline + @Override + public final Float16Shuffle256 wrapIndexes() { + ShortVector256 v = toBitsVector(); + if ((length() & (length() - 1)) == 0) { + v = (ShortVector256) v.lanewise(VectorOperators.AND, length() - 1); + } else { + v = (ShortVector256) v.blend(v.lanewise(VectorOperators.ADD, length()), + v.compare(VectorOperators.LT, 0)); + } + return (Float16Shuffle256) v.toShuffle(VSPECIES, false); + } + + private static short[] prepare(int[] indices, int offset) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = indices[offset + i]; + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static short[] prepare(IntUnaryOperator f) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = f.applyAsInt(i); + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static boolean indicesInRange(short[] indices) { + int length = indices.length; + for (short si : indices) { + if (si >= (short)length || si < (short)(-length)) { + String msg = ("index "+si+"out of range ["+length+"] in "+ + java.util.Arrays.toString(indices)); + throw new AssertionError(msg); + } + } + return true; + } + } + + // ================================================ + + // Specialized low-level memory operations. + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset) { + return super.fromArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, VectorMask m, int offsetInRange) { + return super.fromArray0Template(Float16Mask256.class, a, offset, (Float16Mask256) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, int[] indexMap, int mapOffset, VectorMask m) { + return super.fromArray0Template(Float16Mask256.class, a, offset, indexMap, mapOffset, (Float16Mask256) m); + } + + + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset) { + return super.fromMemorySegment0Template(ms, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset, VectorMask m, int offsetInRange) { + return super.fromMemorySegment0Template(Float16Mask256.class, ms, offset, (Float16Mask256) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset) { + super.intoArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset, VectorMask m) { + super.intoArray0Template(Float16Mask256.class, a, offset, (Float16Mask256) m); + } + + + + @ForceInline + @Override + final + void intoMemorySegment0(MemorySegment ms, long offset, VectorMask m) { + super.intoMemorySegment0Template(Float16Mask256.class, ms, offset, (Float16Mask256) m); + } + + + // End of specialized low-level memory operations. + + // ================================================ + +} + diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector512.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector512.java new file mode 100644 index 00000000000..9ec1eaad8ad --- /dev/null +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector512.java @@ -0,0 +1,1085 @@ +/* + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.vector; + +import java.lang.foreign.MemorySegment; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.IntUnaryOperator; + +import jdk.internal.ValueBased; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.vector.VectorSupport; + +import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; + +// -- This file was mechanically generated: Do not edit! -- // + +@SuppressWarnings("cast") // warning: redundant cast +@ValueBased +final class Float16Vector512 extends Float16Vector { + static final Float16Species VSPECIES = + (Float16Species) Float16Vector.SPECIES_512; + + static final VectorShape VSHAPE = + VSPECIES.vectorShape(); + + static final Class VCLASS = Float16Vector512.class; + + static final int VSIZE = VSPECIES.vectorBitSize(); + + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // carrier type used by the JVM + + static final Class ETYPE = Float16.class; // used by the JVM + + Float16Vector512(short[] v) { + super(v); + } + + // For compatibility as Float16Vector512::new, + // stored into species.vectorFactory. + Float16Vector512(Object v) { + this((short[]) v); + } + + static final Float16Vector512 ZERO = new Float16Vector512(new short[VLENGTH]); + static final Float16Vector512 IOTA = new Float16Vector512(VSPECIES.iotaArray()); + + static { + // Warm up a few species caches. + // If we do this too much we will + // get NPEs from bootstrap circularity. + VSPECIES.dummyVector(); + VSPECIES.withLanes(LaneType.BYTE); + } + + // Specialized extractors + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractVector, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + @Override + public final Class elementType() { return Float16.class; } + + @ForceInline + final Class carrierType() { return CTYPE; } + + @ForceInline + @Override + public final int elementSize() { return Float16.SIZE; } + + @ForceInline + @Override + public final VectorShape shape() { return VSHAPE; } + + @ForceInline + @Override + public final int length() { return VLENGTH; } + + @ForceInline + @Override + public final int bitSize() { return VSIZE; } + + @ForceInline + @Override + public final int byteSize() { return VSIZE / Byte.SIZE; } + + /*package-private*/ + @ForceInline + final @Override + short[] vec() { + return (short[])getPayload(); + } + + /*package-private*/ + @ForceInline + final @Override + int laneTypeOrdinal() { + return LANE_TYPE_ORDINAL; + } + + // Virtualized constructors + + @Override + @ForceInline + public final Float16Vector512 broadcast(short e) { + return (Float16Vector512) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + public final Float16Vector512 broadcast(long e) { + return (Float16Vector512) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + Float16Mask512 maskFromArray(boolean[] bits) { + return new Float16Mask512(bits); + } + + @Override + @ForceInline + Float16Shuffle512 iotaShuffle() { return Float16Shuffle512.IOTA; } + + @Override + @ForceInline + Float16Shuffle512 iotaShuffle(int start, int step, boolean wrap) { + return (Float16Shuffle512) iotaShuffleTemplate((short) start, (short) step, wrap); + } + + @Override + @ForceInline + Float16Shuffle512 shuffleFromArray(int[] indices, int i) { return new Float16Shuffle512(indices, i); } + + @Override + @ForceInline + Float16Shuffle512 shuffleFromOp(IntUnaryOperator fn) { return new Float16Shuffle512(fn); } + + // Make a vector of the same species but the given elements: + @ForceInline + final @Override + Float16Vector512 vectorFactory(short[] vec) { + return new Float16Vector512(vec); + } + + @ForceInline + final @Override + ByteVector512 asByteVectorRaw() { + return (ByteVector512) super.asByteVectorRawTemplate(); // specialize + } + + @ForceInline + final @Override + AbstractVector asVectorRaw(LaneType laneType) { + return super.asVectorRawTemplate(laneType); // specialize + } + + // Unary operator + + @ForceInline + final @Override + Float16Vector512 uOp(FUnOp f) { + return (Float16Vector512) super.uOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector512 uOp(VectorMask m, FUnOp f) { + return (Float16Vector512) + super.uOpTemplate((Float16Mask512)m, f); // specialize + } + + @ForceInline + final @Override + Float16Vector512 uRawOp(FUnRawOp f) { + return (Float16Vector512) super.uRawOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector512 uRawOp(VectorMask m, FUnRawOp f) { + return (Float16Vector512) + super.uRawOpTemplate((Float16Mask512)m, f); // specialize + } + // Binary operator + + @ForceInline + final @Override + Float16Vector512 bOp(Vector v, FBinOp f) { + return (Float16Vector512) super.bOpTemplate((Float16Vector512)v, f); // specialize + } + + @ForceInline + final @Override + Float16Vector512 bOp(Vector v, + VectorMask m, FBinOp f) { + return (Float16Vector512) + super.bOpTemplate((Float16Vector512)v, (Float16Mask512)m, + f); // specialize + } + + // Ternary operator + + @ForceInline + final @Override + Float16Vector512 tOp(Vector v1, Vector v2, FTriOp f) { + return (Float16Vector512) + super.tOpTemplate((Float16Vector512)v1, (Float16Vector512)v2, + f); // specialize + } + + @ForceInline + final @Override + Float16Vector512 tOp(Vector v1, Vector v2, + VectorMask m, FTriOp f) { + return (Float16Vector512) + super.tOpTemplate((Float16Vector512)v1, (Float16Vector512)v2, + (Float16Mask512)m, f); // specialize + } + + @ForceInline + final @Override + short rOp(short v, VectorMask m, FBinOp f) { + return super.rOpTemplate(v, m, f); // specialize + } + + @Override + @ForceInline + public final + Vector convertShape(VectorOperators.Conversion conv, + VectorSpecies rsp, int part) { + return super.convertShapeTemplate(conv, rsp, part); // specialize + } + + @Override + @ForceInline + public final + Vector reinterpretShape(VectorSpecies toSpecies, int part) { + return super.reinterpretShapeTemplate(toSpecies, part); // specialize + } + + // Specialized algebraic operations: + + // The following definition forces a specialized version of this + // crucial method into the v-table of this class. A call to add() + // will inline to a call to lanewise(ADD,), at which point the JIT + // intrinsic will have the opcode of ADD, plus all the metadata + // for this particular class, enabling it to generate precise + // code. + // + // There is probably no benefit to the JIT to specialize the + // masked or broadcast versions of the lanewise method. + + @Override + @ForceInline + public Float16Vector512 lanewise(Unary op) { + return (Float16Vector512) super.lanewiseTemplate(op); // specialize + } + + @Override + @ForceInline + public Float16Vector512 lanewise(Unary op, VectorMask m) { + return (Float16Vector512) super.lanewiseTemplate(op, Float16Mask512.class, (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 lanewise(Binary op, Vector v) { + return (Float16Vector512) super.lanewiseTemplate(op, v); // specialize + } + + @Override + @ForceInline + public Float16Vector512 lanewise(Binary op, Vector v, VectorMask m) { + return (Float16Vector512) super.lanewiseTemplate(op, Float16Mask512.class, v, (Float16Mask512) m); // specialize + } + + + /*package-private*/ + @Override + @ForceInline + public final + Float16Vector512 + lanewise(Ternary op, Vector v1, Vector v2) { + return (Float16Vector512) super.lanewiseTemplate(op, v1, v2); // specialize + } + + @Override + @ForceInline + public final + Float16Vector512 + lanewise(Ternary op, Vector v1, Vector v2, VectorMask m) { + return (Float16Vector512) super.lanewiseTemplate(op, Float16Mask512.class, v1, v2, (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public final + Float16Vector512 addIndex(int scale) { + return (Float16Vector512) super.addIndexTemplate(scale); // specialize + } + + // Type specific horizontal reductions + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op) { + return super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op, + VectorMask m) { + return super.reduceLanesTemplate(op, Float16Mask512.class, (Float16Mask512) m); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op) { + return (long) super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op, + VectorMask m) { + return (long) super.reduceLanesTemplate(op, Float16Mask512.class, (Float16Mask512) m); // specialized + } + + @Override + @ForceInline + final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { + throw new AssertionError(); + } + + @Override + @ForceInline + public final Float16Shuffle512 toShuffle() { + return (Float16Shuffle512) toShuffle(VSPECIES, false); + } + + // Specialized unary testing + + @Override + @ForceInline + public final Float16Mask512 test(Test op) { + return super.testTemplate(Float16Mask512.class, op); // specialize + } + + @Override + @ForceInline + public final Float16Mask512 test(Test op, VectorMask m) { + return super.testTemplate(Float16Mask512.class, op, (Float16Mask512) m); // specialize + } + + // Specialized comparisons + + @Override + @ForceInline + public final Float16Mask512 compare(Comparison op, Vector v) { + return super.compareTemplate(Float16Mask512.class, op, v); // specialize + } + + @Override + @ForceInline + public final Float16Mask512 compare(Comparison op, short s) { + return super.compareTemplate(Float16Mask512.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask512 compare(Comparison op, long s) { + return super.compareTemplate(Float16Mask512.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask512 compare(Comparison op, Vector v, VectorMask m) { + return super.compareTemplate(Float16Mask512.class, op, v, (Float16Mask512) m); + } + + + @Override + @ForceInline + public Float16Vector512 blend(Vector v, VectorMask m) { + return (Float16Vector512) + super.blendTemplate(Float16Mask512.class, + (Float16Vector512) v, + (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 slice(int origin, Vector v) { + return (Float16Vector512) super.sliceTemplate(origin, v); // specialize + } + + @Override + @ForceInline + public Float16Vector512 slice(int origin) { + return (Float16Vector512) super.sliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector512 unslice(int origin, Vector w, int part) { + return (Float16Vector512) super.unsliceTemplate(origin, w, part); // specialize + } + + @Override + @ForceInline + public Float16Vector512 unslice(int origin, Vector w, int part, VectorMask m) { + return (Float16Vector512) + super.unsliceTemplate(Float16Mask512.class, + origin, w, part, + (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 unslice(int origin) { + return (Float16Vector512) super.unsliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector512 rearrange(VectorShuffle s) { + return (Float16Vector512) + super.rearrangeTemplate(Float16Shuffle512.class, + (Float16Shuffle512) s); // specialize + } + + @Override + @ForceInline + public Float16Vector512 rearrange(VectorShuffle shuffle, + VectorMask m) { + return (Float16Vector512) + super.rearrangeTemplate(Float16Shuffle512.class, + Float16Mask512.class, + (Float16Shuffle512) shuffle, + (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 rearrange(VectorShuffle s, + Vector v) { + return (Float16Vector512) + super.rearrangeTemplate(Float16Shuffle512.class, + (Float16Shuffle512) s, + (Float16Vector512) v); // specialize + } + + @Override + @ForceInline + public Float16Vector512 compress(VectorMask m) { + return (Float16Vector512) + super.compressTemplate(Float16Mask512.class, + (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 expand(VectorMask m) { + return (Float16Vector512) + super.expandTemplate(Float16Mask512.class, + (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 selectFrom(Vector v) { + return (Float16Vector512) + super.selectFromTemplate((Float16Vector512) v); // specialize + } + + @Override + @ForceInline + public Float16Vector512 selectFrom(Vector v, + VectorMask m) { + return (Float16Vector512) + super.selectFromTemplate((Float16Vector512) v, + Float16Mask512.class, (Float16Mask512) m); // specialize + } + + @Override + @ForceInline + public Float16Vector512 selectFrom(Vector v1, + Vector v2) { + return (Float16Vector512) + super.selectFromTemplate((Float16Vector512) v1, (Float16Vector512) v2); // specialize + } + + @ForceInline + @Override + public short lane(int i) { + short bits; + switch(i) { + case 0: bits = laneHelper(0); break; + case 1: bits = laneHelper(1); break; + case 2: bits = laneHelper(2); break; + case 3: bits = laneHelper(3); break; + case 4: bits = laneHelper(4); break; + case 5: bits = laneHelper(5); break; + case 6: bits = laneHelper(6); break; + case 7: bits = laneHelper(7); break; + case 8: bits = laneHelper(8); break; + case 9: bits = laneHelper(9); break; + case 10: bits = laneHelper(10); break; + case 11: bits = laneHelper(11); break; + case 12: bits = laneHelper(12); break; + case 13: bits = laneHelper(13); break; + case 14: bits = laneHelper(14); break; + case 15: bits = laneHelper(15); break; + case 16: bits = laneHelper(16); break; + case 17: bits = laneHelper(17); break; + case 18: bits = laneHelper(18); break; + case 19: bits = laneHelper(19); break; + case 20: bits = laneHelper(20); break; + case 21: bits = laneHelper(21); break; + case 22: bits = laneHelper(22); break; + case 23: bits = laneHelper(23); break; + case 24: bits = laneHelper(24); break; + case 25: bits = laneHelper(25); break; + case 26: bits = laneHelper(26); break; + case 27: bits = laneHelper(27); break; + case 28: bits = laneHelper(28); break; + case 29: bits = laneHelper(29); break; + case 30: bits = laneHelper(30); break; + case 31: bits = laneHelper(31); break; + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + return bits; + } + + @ForceInline + public short laneHelper(int i) { + return (short) VectorSupport.extract( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, + (vec, ix) -> { + short[] vecarr = vec.vec(); + return vecarr[ix]; + }); + } + + @ForceInline + @Override + public Float16Vector512 withLane(int i, short e) { + switch(i) { + case 0: return withLaneHelper(0, e); + case 1: return withLaneHelper(1, e); + case 2: return withLaneHelper(2, e); + case 3: return withLaneHelper(3, e); + case 4: return withLaneHelper(4, e); + case 5: return withLaneHelper(5, e); + case 6: return withLaneHelper(6, e); + case 7: return withLaneHelper(7, e); + case 8: return withLaneHelper(8, e); + case 9: return withLaneHelper(9, e); + case 10: return withLaneHelper(10, e); + case 11: return withLaneHelper(11, e); + case 12: return withLaneHelper(12, e); + case 13: return withLaneHelper(13, e); + case 14: return withLaneHelper(14, e); + case 15: return withLaneHelper(15, e); + case 16: return withLaneHelper(16, e); + case 17: return withLaneHelper(17, e); + case 18: return withLaneHelper(18, e); + case 19: return withLaneHelper(19, e); + case 20: return withLaneHelper(20, e); + case 21: return withLaneHelper(21, e); + case 22: return withLaneHelper(22, e); + case 23: return withLaneHelper(23, e); + case 24: return withLaneHelper(24, e); + case 25: return withLaneHelper(25, e); + case 26: return withLaneHelper(26, e); + case 27: return withLaneHelper(27, e); + case 28: return withLaneHelper(28, e); + case 29: return withLaneHelper(29, e); + case 30: return withLaneHelper(30, e); + case 31: return withLaneHelper(31, e); + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + } + + @ForceInline + public Float16Vector512 withLaneHelper(int i, short e) { + return VectorSupport.insert( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (long)e, + (v, ix, bits) -> { + short[] res = v.vec().clone(); + res[ix] = (short)bits; + return v.vectorFactory(res); + }); + } + + // Mask + @ValueBased + static final class Float16Mask512 extends AbstractMask { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Mask512(boolean[] bits) { + this(bits, 0); + } + + Float16Mask512(boolean[] bits, int offset) { + super(prepare(bits, offset)); + } + + Float16Mask512(boolean val) { + super(prepare(val)); + } + + private static boolean[] prepare(boolean[] bits, int offset) { + boolean[] newBits = new boolean[VSPECIES.laneCount()]; + for (int i = 0; i < newBits.length; i++) { + newBits[i] = bits[offset + i]; + } + return newBits; + } + + private static boolean[] prepare(boolean val) { + boolean[] bits = new boolean[VSPECIES.laneCount()]; + Arrays.fill(bits, val); + return bits; + } + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractMask, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + boolean[] getBits() { + return (boolean[])getPayload(); + } + + @Override + Float16Mask512 uOp(MUnOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i]); + } + return new Float16Mask512(res); + } + + @Override + Float16Mask512 bOp(VectorMask m, MBinOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + boolean[] mbits = ((Float16Mask512)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i], mbits[i]); + } + return new Float16Mask512(res); + } + + @ForceInline + @Override + public final + Float16Vector512 toVector() { + return (Float16Vector512) super.toVectorTemplate(); // specialize + } + + /** + * Helper function for lane-wise mask conversions. + * This function kicks in after intrinsic failure. + */ + @ForceInline + private final + VectorMask defaultMaskCast(AbstractSpecies dsp) { + if (length() != dsp.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + boolean[] maskArray = toArray(); + return dsp.maskFactory(maskArray).check(dsp); + } + + @Override + @ForceInline + public VectorMask cast(VectorSpecies dsp) { + AbstractSpecies species = (AbstractSpecies) dsp; + if (length() != species.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + + return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST, + this.getClass(), LANE_TYPE_ORDINAL, VLENGTH, + species.maskType(), species.laneTypeOrdinal(), VLENGTH, + this, species, + (m, s) -> s.maskFactory(m.toArray()).check(s)); + } + + @Override + @ForceInline + /*package-private*/ + Float16Mask512 indexPartiallyInUpperRange(long offset, long limit) { + return (Float16Mask512) VectorSupport.indexPartiallyInUpperRange( + Float16Mask512.class, LANE_TYPE_ORDINAL, VLENGTH, offset, limit, + (o, l) -> (Float16Mask512) TRUE_MASK.indexPartiallyInRange(o, l)); + } + + // Unary operations + + @Override + @ForceInline + public Float16Mask512 not() { + return xor(maskAll(true)); + } + + @Override + @ForceInline + public Float16Mask512 compress() { + return (Float16Mask512)VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_MASK_COMPRESS, + Float16Vector512.class, Float16Mask512.class, LANE_TYPE_ORDINAL, VLENGTH, null, this, + (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, Float16.float16ToRawShortBits(Float16.valueOf(m1.trueCount())))); + } + + + // Binary operations + + @Override + @ForceInline + public Float16Mask512 and(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask512 m = (Float16Mask512)mask; + return VectorSupport.binaryOp(VECTOR_OP_AND, Float16Mask512.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a & b)); + } + + @Override + @ForceInline + public Float16Mask512 or(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask512 m = (Float16Mask512)mask; + return VectorSupport.binaryOp(VECTOR_OP_OR, Float16Mask512.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a | b)); + } + + @Override + @ForceInline + public Float16Mask512 xor(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask512 m = (Float16Mask512)mask; + return VectorSupport.binaryOp(VECTOR_OP_XOR, Float16Mask512.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a ^ b)); + } + + // Mask Query operations + + @Override + @ForceInline + public int trueCount() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TRUECOUNT, Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> trueCountHelper(m.getBits())); + } + + @Override + @ForceInline + public int firstTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_FIRSTTRUE, Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> firstTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public int lastTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_LASTTRUE, Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> lastTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public long toLong() { + if (length() > Long.SIZE) { + throw new UnsupportedOperationException("too many lanes for one long"); + } + return VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TOLONG, Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> toLongHelper(m.getBits())); + } + + // laneIsSet + + @Override + @ForceInline + public boolean laneIsSet(int i) { + Objects.checkIndex(i, length()); + return VectorSupport.extract(Float16Mask512.class, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (m, idx) -> (m.getBits()[idx] ? 1L : 0L)) == 1L; + } + + // Reductions + + @Override + @ForceInline + public boolean anyTrue() { + return VectorSupport.test(BT_ne, Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((Float16Mask512)m).getBits())); + } + + @Override + @ForceInline + public boolean allTrue() { + return VectorSupport.test(BT_overflow, Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((Float16Mask512)m).getBits())); + } + + @ForceInline + /*package-private*/ + static Float16Mask512 maskAll(boolean bit) { + return VectorSupport.fromBitsCoerced(Float16Mask512.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + } + private static final Float16Mask512 TRUE_MASK = new Float16Mask512(true); + private static final Float16Mask512 FALSE_MASK = new Float16Mask512(false); + + } + + // Shuffle + @ValueBased + static final class Float16Shuffle512 extends AbstractShuffle { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Shuffle512(short[] indices) { + super(indices); + assert(VLENGTH == indices.length); + assert(indicesInRange(indices)); + } + + Float16Shuffle512(int[] indices, int i) { + this(prepare(indices, i)); + } + + Float16Shuffle512(IntUnaryOperator fn) { + this(prepare(fn)); + } + + short[] indices() { + return (short[])getPayload(); + } + + @Override + @ForceInline + public Float16Species vspecies() { + return VSPECIES; + } + + static { + // There must be enough bits in the shuffle lanes to encode + // VLENGTH valid indexes and VLENGTH exceptional ones. + assert(VLENGTH < Short.MAX_VALUE); + assert(Short.MIN_VALUE <= -VLENGTH); + } + static final Float16Shuffle512 IOTA = new Float16Shuffle512(IDENTITY); + + @Override + @ForceInline + public Float16Vector512 toVector() { + return (Float16Vector512) toBitsVector().castShape(VSPECIES, 0); + } + + @Override + @ForceInline + ShortVector512 toBitsVector() { + return (ShortVector512) super.toBitsVectorTemplate(); + } + + @Override + ShortVector512 toBitsVector0() { + return ((ShortVector512) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); + } + + @Override + @ForceInline + public int laneSource(int i) { + return (int)toBitsVector().lane(i); + } + + @Override + @ForceInline + public void intoArray(int[] a, int offset) { + VectorSpecies species = IntVector.SPECIES_512; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoArray(a, offset); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoArray(a, offset + species.length()); + } + + @Override + @ForceInline + public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { + VectorSpecies species = IntVector.SPECIES_512; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoMemorySegment(ms, offset, bo); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoMemorySegment(ms, offset + species.vectorByteSize(), bo); + } + + @Override + @ForceInline + public final Float16Mask512 laneIsValid() { + return (Float16Mask512) toBitsVector().compare(VectorOperators.GE, 0) + .cast(VSPECIES); + } + + @ForceInline + @Override + public final Float16Shuffle512 rearrange(VectorShuffle shuffle) { + Float16Shuffle512 concreteShuffle = (Float16Shuffle512) shuffle; + return (Float16Shuffle512) toBitsVector().rearrange(concreteShuffle.cast(ShortVector.SPECIES_512)) + .toShuffle(VSPECIES, false); + } + + @ForceInline + @Override + public final Float16Shuffle512 wrapIndexes() { + ShortVector512 v = toBitsVector(); + if ((length() & (length() - 1)) == 0) { + v = (ShortVector512) v.lanewise(VectorOperators.AND, length() - 1); + } else { + v = (ShortVector512) v.blend(v.lanewise(VectorOperators.ADD, length()), + v.compare(VectorOperators.LT, 0)); + } + return (Float16Shuffle512) v.toShuffle(VSPECIES, false); + } + + private static short[] prepare(int[] indices, int offset) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = indices[offset + i]; + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static short[] prepare(IntUnaryOperator f) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = f.applyAsInt(i); + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static boolean indicesInRange(short[] indices) { + int length = indices.length; + for (short si : indices) { + if (si >= (short)length || si < (short)(-length)) { + String msg = ("index "+si+"out of range ["+length+"] in "+ + java.util.Arrays.toString(indices)); + throw new AssertionError(msg); + } + } + return true; + } + } + + // ================================================ + + // Specialized low-level memory operations. + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset) { + return super.fromArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, VectorMask m, int offsetInRange) { + return super.fromArray0Template(Float16Mask512.class, a, offset, (Float16Mask512) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, int[] indexMap, int mapOffset, VectorMask m) { + return super.fromArray0Template(Float16Mask512.class, a, offset, indexMap, mapOffset, (Float16Mask512) m); + } + + + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset) { + return super.fromMemorySegment0Template(ms, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset, VectorMask m, int offsetInRange) { + return super.fromMemorySegment0Template(Float16Mask512.class, ms, offset, (Float16Mask512) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset) { + super.intoArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset, VectorMask m) { + super.intoArray0Template(Float16Mask512.class, a, offset, (Float16Mask512) m); + } + + + + @ForceInline + @Override + final + void intoMemorySegment0(MemorySegment ms, long offset, VectorMask m) { + super.intoMemorySegment0Template(Float16Mask512.class, ms, offset, (Float16Mask512) m); + } + + + // End of specialized low-level memory operations. + + // ================================================ + +} + diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector64.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector64.java new file mode 100644 index 00000000000..973e5261618 --- /dev/null +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16Vector64.java @@ -0,0 +1,1029 @@ +/* + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.vector; + +import java.lang.foreign.MemorySegment; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.IntUnaryOperator; + +import jdk.internal.ValueBased; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.vector.VectorSupport; + +import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; + +// -- This file was mechanically generated: Do not edit! -- // + +@SuppressWarnings("cast") // warning: redundant cast +@ValueBased +final class Float16Vector64 extends Float16Vector { + static final Float16Species VSPECIES = + (Float16Species) Float16Vector.SPECIES_64; + + static final VectorShape VSHAPE = + VSPECIES.vectorShape(); + + static final Class VCLASS = Float16Vector64.class; + + static final int VSIZE = VSPECIES.vectorBitSize(); + + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // carrier type used by the JVM + + static final Class ETYPE = Float16.class; // used by the JVM + + Float16Vector64(short[] v) { + super(v); + } + + // For compatibility as Float16Vector64::new, + // stored into species.vectorFactory. + Float16Vector64(Object v) { + this((short[]) v); + } + + static final Float16Vector64 ZERO = new Float16Vector64(new short[VLENGTH]); + static final Float16Vector64 IOTA = new Float16Vector64(VSPECIES.iotaArray()); + + static { + // Warm up a few species caches. + // If we do this too much we will + // get NPEs from bootstrap circularity. + VSPECIES.dummyVector(); + VSPECIES.withLanes(LaneType.BYTE); + } + + // Specialized extractors + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractVector, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + @Override + public final Class elementType() { return Float16.class; } + + @ForceInline + final Class carrierType() { return CTYPE; } + + @ForceInline + @Override + public final int elementSize() { return Float16.SIZE; } + + @ForceInline + @Override + public final VectorShape shape() { return VSHAPE; } + + @ForceInline + @Override + public final int length() { return VLENGTH; } + + @ForceInline + @Override + public final int bitSize() { return VSIZE; } + + @ForceInline + @Override + public final int byteSize() { return VSIZE / Byte.SIZE; } + + /*package-private*/ + @ForceInline + final @Override + short[] vec() { + return (short[])getPayload(); + } + + /*package-private*/ + @ForceInline + final @Override + int laneTypeOrdinal() { + return LANE_TYPE_ORDINAL; + } + + // Virtualized constructors + + @Override + @ForceInline + public final Float16Vector64 broadcast(short e) { + return (Float16Vector64) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + public final Float16Vector64 broadcast(long e) { + return (Float16Vector64) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + Float16Mask64 maskFromArray(boolean[] bits) { + return new Float16Mask64(bits); + } + + @Override + @ForceInline + Float16Shuffle64 iotaShuffle() { return Float16Shuffle64.IOTA; } + + @Override + @ForceInline + Float16Shuffle64 iotaShuffle(int start, int step, boolean wrap) { + return (Float16Shuffle64) iotaShuffleTemplate((short) start, (short) step, wrap); + } + + @Override + @ForceInline + Float16Shuffle64 shuffleFromArray(int[] indices, int i) { return new Float16Shuffle64(indices, i); } + + @Override + @ForceInline + Float16Shuffle64 shuffleFromOp(IntUnaryOperator fn) { return new Float16Shuffle64(fn); } + + // Make a vector of the same species but the given elements: + @ForceInline + final @Override + Float16Vector64 vectorFactory(short[] vec) { + return new Float16Vector64(vec); + } + + @ForceInline + final @Override + ByteVector64 asByteVectorRaw() { + return (ByteVector64) super.asByteVectorRawTemplate(); // specialize + } + + @ForceInline + final @Override + AbstractVector asVectorRaw(LaneType laneType) { + return super.asVectorRawTemplate(laneType); // specialize + } + + // Unary operator + + @ForceInline + final @Override + Float16Vector64 uOp(FUnOp f) { + return (Float16Vector64) super.uOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector64 uOp(VectorMask m, FUnOp f) { + return (Float16Vector64) + super.uOpTemplate((Float16Mask64)m, f); // specialize + } + + @ForceInline + final @Override + Float16Vector64 uRawOp(FUnRawOp f) { + return (Float16Vector64) super.uRawOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16Vector64 uRawOp(VectorMask m, FUnRawOp f) { + return (Float16Vector64) + super.uRawOpTemplate((Float16Mask64)m, f); // specialize + } + // Binary operator + + @ForceInline + final @Override + Float16Vector64 bOp(Vector v, FBinOp f) { + return (Float16Vector64) super.bOpTemplate((Float16Vector64)v, f); // specialize + } + + @ForceInline + final @Override + Float16Vector64 bOp(Vector v, + VectorMask m, FBinOp f) { + return (Float16Vector64) + super.bOpTemplate((Float16Vector64)v, (Float16Mask64)m, + f); // specialize + } + + // Ternary operator + + @ForceInline + final @Override + Float16Vector64 tOp(Vector v1, Vector v2, FTriOp f) { + return (Float16Vector64) + super.tOpTemplate((Float16Vector64)v1, (Float16Vector64)v2, + f); // specialize + } + + @ForceInline + final @Override + Float16Vector64 tOp(Vector v1, Vector v2, + VectorMask m, FTriOp f) { + return (Float16Vector64) + super.tOpTemplate((Float16Vector64)v1, (Float16Vector64)v2, + (Float16Mask64)m, f); // specialize + } + + @ForceInline + final @Override + short rOp(short v, VectorMask m, FBinOp f) { + return super.rOpTemplate(v, m, f); // specialize + } + + @Override + @ForceInline + public final + Vector convertShape(VectorOperators.Conversion conv, + VectorSpecies rsp, int part) { + return super.convertShapeTemplate(conv, rsp, part); // specialize + } + + @Override + @ForceInline + public final + Vector reinterpretShape(VectorSpecies toSpecies, int part) { + return super.reinterpretShapeTemplate(toSpecies, part); // specialize + } + + // Specialized algebraic operations: + + // The following definition forces a specialized version of this + // crucial method into the v-table of this class. A call to add() + // will inline to a call to lanewise(ADD,), at which point the JIT + // intrinsic will have the opcode of ADD, plus all the metadata + // for this particular class, enabling it to generate precise + // code. + // + // There is probably no benefit to the JIT to specialize the + // masked or broadcast versions of the lanewise method. + + @Override + @ForceInline + public Float16Vector64 lanewise(Unary op) { + return (Float16Vector64) super.lanewiseTemplate(op); // specialize + } + + @Override + @ForceInline + public Float16Vector64 lanewise(Unary op, VectorMask m) { + return (Float16Vector64) super.lanewiseTemplate(op, Float16Mask64.class, (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 lanewise(Binary op, Vector v) { + return (Float16Vector64) super.lanewiseTemplate(op, v); // specialize + } + + @Override + @ForceInline + public Float16Vector64 lanewise(Binary op, Vector v, VectorMask m) { + return (Float16Vector64) super.lanewiseTemplate(op, Float16Mask64.class, v, (Float16Mask64) m); // specialize + } + + + /*package-private*/ + @Override + @ForceInline + public final + Float16Vector64 + lanewise(Ternary op, Vector v1, Vector v2) { + return (Float16Vector64) super.lanewiseTemplate(op, v1, v2); // specialize + } + + @Override + @ForceInline + public final + Float16Vector64 + lanewise(Ternary op, Vector v1, Vector v2, VectorMask m) { + return (Float16Vector64) super.lanewiseTemplate(op, Float16Mask64.class, v1, v2, (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public final + Float16Vector64 addIndex(int scale) { + return (Float16Vector64) super.addIndexTemplate(scale); // specialize + } + + // Type specific horizontal reductions + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op) { + return super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op, + VectorMask m) { + return super.reduceLanesTemplate(op, Float16Mask64.class, (Float16Mask64) m); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op) { + return (long) super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op, + VectorMask m) { + return (long) super.reduceLanesTemplate(op, Float16Mask64.class, (Float16Mask64) m); // specialized + } + + @Override + @ForceInline + final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { + throw new AssertionError(); + } + + @Override + @ForceInline + public final Float16Shuffle64 toShuffle() { + return (Float16Shuffle64) toShuffle(VSPECIES, false); + } + + // Specialized unary testing + + @Override + @ForceInline + public final Float16Mask64 test(Test op) { + return super.testTemplate(Float16Mask64.class, op); // specialize + } + + @Override + @ForceInline + public final Float16Mask64 test(Test op, VectorMask m) { + return super.testTemplate(Float16Mask64.class, op, (Float16Mask64) m); // specialize + } + + // Specialized comparisons + + @Override + @ForceInline + public final Float16Mask64 compare(Comparison op, Vector v) { + return super.compareTemplate(Float16Mask64.class, op, v); // specialize + } + + @Override + @ForceInline + public final Float16Mask64 compare(Comparison op, short s) { + return super.compareTemplate(Float16Mask64.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask64 compare(Comparison op, long s) { + return super.compareTemplate(Float16Mask64.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16Mask64 compare(Comparison op, Vector v, VectorMask m) { + return super.compareTemplate(Float16Mask64.class, op, v, (Float16Mask64) m); + } + + + @Override + @ForceInline + public Float16Vector64 blend(Vector v, VectorMask m) { + return (Float16Vector64) + super.blendTemplate(Float16Mask64.class, + (Float16Vector64) v, + (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 slice(int origin, Vector v) { + return (Float16Vector64) super.sliceTemplate(origin, v); // specialize + } + + @Override + @ForceInline + public Float16Vector64 slice(int origin) { + return (Float16Vector64) super.sliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector64 unslice(int origin, Vector w, int part) { + return (Float16Vector64) super.unsliceTemplate(origin, w, part); // specialize + } + + @Override + @ForceInline + public Float16Vector64 unslice(int origin, Vector w, int part, VectorMask m) { + return (Float16Vector64) + super.unsliceTemplate(Float16Mask64.class, + origin, w, part, + (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 unslice(int origin) { + return (Float16Vector64) super.unsliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16Vector64 rearrange(VectorShuffle s) { + return (Float16Vector64) + super.rearrangeTemplate(Float16Shuffle64.class, + (Float16Shuffle64) s); // specialize + } + + @Override + @ForceInline + public Float16Vector64 rearrange(VectorShuffle shuffle, + VectorMask m) { + return (Float16Vector64) + super.rearrangeTemplate(Float16Shuffle64.class, + Float16Mask64.class, + (Float16Shuffle64) shuffle, + (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 rearrange(VectorShuffle s, + Vector v) { + return (Float16Vector64) + super.rearrangeTemplate(Float16Shuffle64.class, + (Float16Shuffle64) s, + (Float16Vector64) v); // specialize + } + + @Override + @ForceInline + public Float16Vector64 compress(VectorMask m) { + return (Float16Vector64) + super.compressTemplate(Float16Mask64.class, + (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 expand(VectorMask m) { + return (Float16Vector64) + super.expandTemplate(Float16Mask64.class, + (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 selectFrom(Vector v) { + return (Float16Vector64) + super.selectFromTemplate((Float16Vector64) v); // specialize + } + + @Override + @ForceInline + public Float16Vector64 selectFrom(Vector v, + VectorMask m) { + return (Float16Vector64) + super.selectFromTemplate((Float16Vector64) v, + Float16Mask64.class, (Float16Mask64) m); // specialize + } + + @Override + @ForceInline + public Float16Vector64 selectFrom(Vector v1, + Vector v2) { + return (Float16Vector64) + super.selectFromTemplate((Float16Vector64) v1, (Float16Vector64) v2); // specialize + } + + @ForceInline + @Override + public short lane(int i) { + short bits; + switch(i) { + case 0: bits = laneHelper(0); break; + case 1: bits = laneHelper(1); break; + case 2: bits = laneHelper(2); break; + case 3: bits = laneHelper(3); break; + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + return bits; + } + + @ForceInline + public short laneHelper(int i) { + return (short) VectorSupport.extract( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, + (vec, ix) -> { + short[] vecarr = vec.vec(); + return vecarr[ix]; + }); + } + + @ForceInline + @Override + public Float16Vector64 withLane(int i, short e) { + switch(i) { + case 0: return withLaneHelper(0, e); + case 1: return withLaneHelper(1, e); + case 2: return withLaneHelper(2, e); + case 3: return withLaneHelper(3, e); + default: throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + } + + @ForceInline + public Float16Vector64 withLaneHelper(int i, short e) { + return VectorSupport.insert( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (long)e, + (v, ix, bits) -> { + short[] res = v.vec().clone(); + res[ix] = (short)bits; + return v.vectorFactory(res); + }); + } + + // Mask + @ValueBased + static final class Float16Mask64 extends AbstractMask { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Mask64(boolean[] bits) { + this(bits, 0); + } + + Float16Mask64(boolean[] bits, int offset) { + super(prepare(bits, offset)); + } + + Float16Mask64(boolean val) { + super(prepare(val)); + } + + private static boolean[] prepare(boolean[] bits, int offset) { + boolean[] newBits = new boolean[VSPECIES.laneCount()]; + for (int i = 0; i < newBits.length; i++) { + newBits[i] = bits[offset + i]; + } + return newBits; + } + + private static boolean[] prepare(boolean val) { + boolean[] bits = new boolean[VSPECIES.laneCount()]; + Arrays.fill(bits, val); + return bits; + } + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractMask, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + boolean[] getBits() { + return (boolean[])getPayload(); + } + + @Override + Float16Mask64 uOp(MUnOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i]); + } + return new Float16Mask64(res); + } + + @Override + Float16Mask64 bOp(VectorMask m, MBinOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + boolean[] mbits = ((Float16Mask64)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i], mbits[i]); + } + return new Float16Mask64(res); + } + + @ForceInline + @Override + public final + Float16Vector64 toVector() { + return (Float16Vector64) super.toVectorTemplate(); // specialize + } + + /** + * Helper function for lane-wise mask conversions. + * This function kicks in after intrinsic failure. + */ + @ForceInline + private final + VectorMask defaultMaskCast(AbstractSpecies dsp) { + if (length() != dsp.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + boolean[] maskArray = toArray(); + return dsp.maskFactory(maskArray).check(dsp); + } + + @Override + @ForceInline + public VectorMask cast(VectorSpecies dsp) { + AbstractSpecies species = (AbstractSpecies) dsp; + if (length() != species.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + + return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST, + this.getClass(), LANE_TYPE_ORDINAL, VLENGTH, + species.maskType(), species.laneTypeOrdinal(), VLENGTH, + this, species, + (m, s) -> s.maskFactory(m.toArray()).check(s)); + } + + @Override + @ForceInline + /*package-private*/ + Float16Mask64 indexPartiallyInUpperRange(long offset, long limit) { + return (Float16Mask64) VectorSupport.indexPartiallyInUpperRange( + Float16Mask64.class, LANE_TYPE_ORDINAL, VLENGTH, offset, limit, + (o, l) -> (Float16Mask64) TRUE_MASK.indexPartiallyInRange(o, l)); + } + + // Unary operations + + @Override + @ForceInline + public Float16Mask64 not() { + return xor(maskAll(true)); + } + + @Override + @ForceInline + public Float16Mask64 compress() { + return (Float16Mask64)VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_MASK_COMPRESS, + Float16Vector64.class, Float16Mask64.class, LANE_TYPE_ORDINAL, VLENGTH, null, this, + (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, Float16.float16ToRawShortBits(Float16.valueOf(m1.trueCount())))); + } + + + // Binary operations + + @Override + @ForceInline + public Float16Mask64 and(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask64 m = (Float16Mask64)mask; + return VectorSupport.binaryOp(VECTOR_OP_AND, Float16Mask64.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a & b)); + } + + @Override + @ForceInline + public Float16Mask64 or(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask64 m = (Float16Mask64)mask; + return VectorSupport.binaryOp(VECTOR_OP_OR, Float16Mask64.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a | b)); + } + + @Override + @ForceInline + public Float16Mask64 xor(VectorMask mask) { + Objects.requireNonNull(mask); + Float16Mask64 m = (Float16Mask64)mask; + return VectorSupport.binaryOp(VECTOR_OP_XOR, Float16Mask64.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a ^ b)); + } + + // Mask Query operations + + @Override + @ForceInline + public int trueCount() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TRUECOUNT, Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> trueCountHelper(m.getBits())); + } + + @Override + @ForceInline + public int firstTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_FIRSTTRUE, Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> firstTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public int lastTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_LASTTRUE, Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> lastTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public long toLong() { + if (length() > Long.SIZE) { + throw new UnsupportedOperationException("too many lanes for one long"); + } + return VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TOLONG, Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> toLongHelper(m.getBits())); + } + + // laneIsSet + + @Override + @ForceInline + public boolean laneIsSet(int i) { + Objects.checkIndex(i, length()); + return VectorSupport.extract(Float16Mask64.class, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (m, idx) -> (m.getBits()[idx] ? 1L : 0L)) == 1L; + } + + // Reductions + + @Override + @ForceInline + public boolean anyTrue() { + return VectorSupport.test(BT_ne, Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((Float16Mask64)m).getBits())); + } + + @Override + @ForceInline + public boolean allTrue() { + return VectorSupport.test(BT_overflow, Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((Float16Mask64)m).getBits())); + } + + @ForceInline + /*package-private*/ + static Float16Mask64 maskAll(boolean bit) { + return VectorSupport.fromBitsCoerced(Float16Mask64.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + } + private static final Float16Mask64 TRUE_MASK = new Float16Mask64(true); + private static final Float16Mask64 FALSE_MASK = new Float16Mask64(false); + + } + + // Shuffle + @ValueBased + static final class Float16Shuffle64 extends AbstractShuffle { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16Shuffle64(short[] indices) { + super(indices); + assert(VLENGTH == indices.length); + assert(indicesInRange(indices)); + } + + Float16Shuffle64(int[] indices, int i) { + this(prepare(indices, i)); + } + + Float16Shuffle64(IntUnaryOperator fn) { + this(prepare(fn)); + } + + short[] indices() { + return (short[])getPayload(); + } + + @Override + @ForceInline + public Float16Species vspecies() { + return VSPECIES; + } + + static { + // There must be enough bits in the shuffle lanes to encode + // VLENGTH valid indexes and VLENGTH exceptional ones. + assert(VLENGTH < Short.MAX_VALUE); + assert(Short.MIN_VALUE <= -VLENGTH); + } + static final Float16Shuffle64 IOTA = new Float16Shuffle64(IDENTITY); + + @Override + @ForceInline + public Float16Vector64 toVector() { + return (Float16Vector64) toBitsVector().castShape(VSPECIES, 0); + } + + @Override + @ForceInline + ShortVector64 toBitsVector() { + return (ShortVector64) super.toBitsVectorTemplate(); + } + + @Override + ShortVector64 toBitsVector0() { + return ((ShortVector64) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); + } + + @Override + @ForceInline + public int laneSource(int i) { + return (int)toBitsVector().lane(i); + } + + @Override + @ForceInline + public void intoArray(int[] a, int offset) { + VectorSpecies species = IntVector.SPECIES_64; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoArray(a, offset); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoArray(a, offset + species.length()); + } + + @Override + @ForceInline + public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { + VectorSpecies species = IntVector.SPECIES_64; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoMemorySegment(ms, offset, bo); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoMemorySegment(ms, offset + species.vectorByteSize(), bo); + } + + @Override + @ForceInline + public final Float16Mask64 laneIsValid() { + return (Float16Mask64) toBitsVector().compare(VectorOperators.GE, 0) + .cast(VSPECIES); + } + + @ForceInline + @Override + public final Float16Shuffle64 rearrange(VectorShuffle shuffle) { + Float16Shuffle64 concreteShuffle = (Float16Shuffle64) shuffle; + return (Float16Shuffle64) toBitsVector().rearrange(concreteShuffle.cast(ShortVector.SPECIES_64)) + .toShuffle(VSPECIES, false); + } + + @ForceInline + @Override + public final Float16Shuffle64 wrapIndexes() { + ShortVector64 v = toBitsVector(); + if ((length() & (length() - 1)) == 0) { + v = (ShortVector64) v.lanewise(VectorOperators.AND, length() - 1); + } else { + v = (ShortVector64) v.blend(v.lanewise(VectorOperators.ADD, length()), + v.compare(VectorOperators.LT, 0)); + } + return (Float16Shuffle64) v.toShuffle(VSPECIES, false); + } + + private static short[] prepare(int[] indices, int offset) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = indices[offset + i]; + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static short[] prepare(IntUnaryOperator f) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = f.applyAsInt(i); + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static boolean indicesInRange(short[] indices) { + int length = indices.length; + for (short si : indices) { + if (si >= (short)length || si < (short)(-length)) { + String msg = ("index "+si+"out of range ["+length+"] in "+ + java.util.Arrays.toString(indices)); + throw new AssertionError(msg); + } + } + return true; + } + } + + // ================================================ + + // Specialized low-level memory operations. + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset) { + return super.fromArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, VectorMask m, int offsetInRange) { + return super.fromArray0Template(Float16Mask64.class, a, offset, (Float16Mask64) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, int[] indexMap, int mapOffset, VectorMask m) { + return super.fromArray0Template(Float16Mask64.class, a, offset, indexMap, mapOffset, (Float16Mask64) m); + } + + + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset) { + return super.fromMemorySegment0Template(ms, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset, VectorMask m, int offsetInRange) { + return super.fromMemorySegment0Template(Float16Mask64.class, ms, offset, (Float16Mask64) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset) { + super.intoArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset, VectorMask m) { + super.intoArray0Template(Float16Mask64.class, a, offset, (Float16Mask64) m); + } + + + + @ForceInline + @Override + final + void intoMemorySegment0(MemorySegment ms, long offset, VectorMask m) { + super.intoMemorySegment0Template(Float16Mask64.class, ms, offset, (Float16Mask64) m); + } + + + // End of specialized low-level memory operations. + + // ================================================ + +} + diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16VectorMax.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16VectorMax.java new file mode 100644 index 00000000000..3de14504f86 --- /dev/null +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16VectorMax.java @@ -0,0 +1,1022 @@ +/* + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.vector; + +import java.lang.foreign.MemorySegment; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.IntUnaryOperator; + +import jdk.internal.ValueBased; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.vector.VectorSupport; + +import static jdk.incubator.vector.VectorOperators.*; +import static jdk.internal.vm.vector.VectorSupport.*; + +// -- This file was mechanically generated: Do not edit! -- // + +@SuppressWarnings("cast") // warning: redundant cast +@ValueBased +final class Float16VectorMax extends Float16Vector { + static final Float16Species VSPECIES = + (Float16Species) Float16Vector.SPECIES_MAX; + + static final VectorShape VSHAPE = + VSPECIES.vectorShape(); + + static final Class VCLASS = Float16VectorMax.class; + + static final int VSIZE = VSPECIES.vectorBitSize(); + + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // carrier type used by the JVM + + static final Class ETYPE = Float16.class; // used by the JVM + + Float16VectorMax(short[] v) { + super(v); + } + + // For compatibility as Float16VectorMax::new, + // stored into species.vectorFactory. + Float16VectorMax(Object v) { + this((short[]) v); + } + + static final Float16VectorMax ZERO = new Float16VectorMax(new short[VLENGTH]); + static final Float16VectorMax IOTA = new Float16VectorMax(VSPECIES.iotaArray()); + + static { + // Warm up a few species caches. + // If we do this too much we will + // get NPEs from bootstrap circularity. + VSPECIES.dummyVector(); + VSPECIES.withLanes(LaneType.BYTE); + } + + // Specialized extractors + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractVector, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + @Override + public final Class elementType() { return Float16.class; } + + @ForceInline + final Class carrierType() { return CTYPE; } + + @ForceInline + @Override + public final int elementSize() { return Float16.SIZE; } + + @ForceInline + @Override + public final VectorShape shape() { return VSHAPE; } + + @ForceInline + @Override + public final int length() { return VLENGTH; } + + @ForceInline + @Override + public final int bitSize() { return VSIZE; } + + @ForceInline + @Override + public final int byteSize() { return VSIZE / Byte.SIZE; } + + /*package-private*/ + @ForceInline + final @Override + short[] vec() { + return (short[])getPayload(); + } + + /*package-private*/ + @ForceInline + final @Override + int laneTypeOrdinal() { + return LANE_TYPE_ORDINAL; + } + + // Virtualized constructors + + @Override + @ForceInline + public final Float16VectorMax broadcast(short e) { + return (Float16VectorMax) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + public final Float16VectorMax broadcast(long e) { + return (Float16VectorMax) super.broadcastTemplate(e); // specialize + } + + @Override + @ForceInline + Float16MaskMax maskFromArray(boolean[] bits) { + return new Float16MaskMax(bits); + } + + @Override + @ForceInline + Float16ShuffleMax iotaShuffle() { return Float16ShuffleMax.IOTA; } + + @Override + @ForceInline + Float16ShuffleMax iotaShuffle(int start, int step, boolean wrap) { + return (Float16ShuffleMax) iotaShuffleTemplate((short) start, (short) step, wrap); + } + + @Override + @ForceInline + Float16ShuffleMax shuffleFromArray(int[] indices, int i) { return new Float16ShuffleMax(indices, i); } + + @Override + @ForceInline + Float16ShuffleMax shuffleFromOp(IntUnaryOperator fn) { return new Float16ShuffleMax(fn); } + + // Make a vector of the same species but the given elements: + @ForceInline + final @Override + Float16VectorMax vectorFactory(short[] vec) { + return new Float16VectorMax(vec); + } + + @ForceInline + final @Override + ByteVectorMax asByteVectorRaw() { + return (ByteVectorMax) super.asByteVectorRawTemplate(); // specialize + } + + @ForceInline + final @Override + AbstractVector asVectorRaw(LaneType laneType) { + return super.asVectorRawTemplate(laneType); // specialize + } + + // Unary operator + + @ForceInline + final @Override + Float16VectorMax uOp(FUnOp f) { + return (Float16VectorMax) super.uOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16VectorMax uOp(VectorMask m, FUnOp f) { + return (Float16VectorMax) + super.uOpTemplate((Float16MaskMax)m, f); // specialize + } + + @ForceInline + final @Override + Float16VectorMax uRawOp(FUnRawOp f) { + return (Float16VectorMax) super.uRawOpTemplate(f); // specialize + } + + @ForceInline + final @Override + Float16VectorMax uRawOp(VectorMask m, FUnRawOp f) { + return (Float16VectorMax) + super.uRawOpTemplate((Float16MaskMax)m, f); // specialize + } + // Binary operator + + @ForceInline + final @Override + Float16VectorMax bOp(Vector v, FBinOp f) { + return (Float16VectorMax) super.bOpTemplate((Float16VectorMax)v, f); // specialize + } + + @ForceInline + final @Override + Float16VectorMax bOp(Vector v, + VectorMask m, FBinOp f) { + return (Float16VectorMax) + super.bOpTemplate((Float16VectorMax)v, (Float16MaskMax)m, + f); // specialize + } + + // Ternary operator + + @ForceInline + final @Override + Float16VectorMax tOp(Vector v1, Vector v2, FTriOp f) { + return (Float16VectorMax) + super.tOpTemplate((Float16VectorMax)v1, (Float16VectorMax)v2, + f); // specialize + } + + @ForceInline + final @Override + Float16VectorMax tOp(Vector v1, Vector v2, + VectorMask m, FTriOp f) { + return (Float16VectorMax) + super.tOpTemplate((Float16VectorMax)v1, (Float16VectorMax)v2, + (Float16MaskMax)m, f); // specialize + } + + @ForceInline + final @Override + short rOp(short v, VectorMask m, FBinOp f) { + return super.rOpTemplate(v, m, f); // specialize + } + + @Override + @ForceInline + public final + Vector convertShape(VectorOperators.Conversion conv, + VectorSpecies rsp, int part) { + return super.convertShapeTemplate(conv, rsp, part); // specialize + } + + @Override + @ForceInline + public final + Vector reinterpretShape(VectorSpecies toSpecies, int part) { + return super.reinterpretShapeTemplate(toSpecies, part); // specialize + } + + // Specialized algebraic operations: + + // The following definition forces a specialized version of this + // crucial method into the v-table of this class. A call to add() + // will inline to a call to lanewise(ADD,), at which point the JIT + // intrinsic will have the opcode of ADD, plus all the metadata + // for this particular class, enabling it to generate precise + // code. + // + // There is probably no benefit to the JIT to specialize the + // masked or broadcast versions of the lanewise method. + + @Override + @ForceInline + public Float16VectorMax lanewise(Unary op) { + return (Float16VectorMax) super.lanewiseTemplate(op); // specialize + } + + @Override + @ForceInline + public Float16VectorMax lanewise(Unary op, VectorMask m) { + return (Float16VectorMax) super.lanewiseTemplate(op, Float16MaskMax.class, (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax lanewise(Binary op, Vector v) { + return (Float16VectorMax) super.lanewiseTemplate(op, v); // specialize + } + + @Override + @ForceInline + public Float16VectorMax lanewise(Binary op, Vector v, VectorMask m) { + return (Float16VectorMax) super.lanewiseTemplate(op, Float16MaskMax.class, v, (Float16MaskMax) m); // specialize + } + + + /*package-private*/ + @Override + @ForceInline + public final + Float16VectorMax + lanewise(Ternary op, Vector v1, Vector v2) { + return (Float16VectorMax) super.lanewiseTemplate(op, v1, v2); // specialize + } + + @Override + @ForceInline + public final + Float16VectorMax + lanewise(Ternary op, Vector v1, Vector v2, VectorMask m) { + return (Float16VectorMax) super.lanewiseTemplate(op, Float16MaskMax.class, v1, v2, (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public final + Float16VectorMax addIndex(int scale) { + return (Float16VectorMax) super.addIndexTemplate(scale); // specialize + } + + // Type specific horizontal reductions + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op) { + return super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final short reduceLanes(VectorOperators.Associative op, + VectorMask m) { + return super.reduceLanesTemplate(op, Float16MaskMax.class, (Float16MaskMax) m); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op) { + return (long) super.reduceLanesTemplate(op); // specialized + } + + @Override + @ForceInline + public final long reduceLanesToLong(VectorOperators.Associative op, + VectorMask m) { + return (long) super.reduceLanesTemplate(op, Float16MaskMax.class, (Float16MaskMax) m); // specialized + } + + @Override + @ForceInline + final VectorShuffle bitsToShuffle(AbstractSpecies dsp) { + throw new AssertionError(); + } + + @Override + @ForceInline + public final Float16ShuffleMax toShuffle() { + return (Float16ShuffleMax) toShuffle(VSPECIES, false); + } + + // Specialized unary testing + + @Override + @ForceInline + public final Float16MaskMax test(Test op) { + return super.testTemplate(Float16MaskMax.class, op); // specialize + } + + @Override + @ForceInline + public final Float16MaskMax test(Test op, VectorMask m) { + return super.testTemplate(Float16MaskMax.class, op, (Float16MaskMax) m); // specialize + } + + // Specialized comparisons + + @Override + @ForceInline + public final Float16MaskMax compare(Comparison op, Vector v) { + return super.compareTemplate(Float16MaskMax.class, op, v); // specialize + } + + @Override + @ForceInline + public final Float16MaskMax compare(Comparison op, short s) { + return super.compareTemplate(Float16MaskMax.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16MaskMax compare(Comparison op, long s) { + return super.compareTemplate(Float16MaskMax.class, op, s); // specialize + } + + @Override + @ForceInline + public final Float16MaskMax compare(Comparison op, Vector v, VectorMask m) { + return super.compareTemplate(Float16MaskMax.class, op, v, (Float16MaskMax) m); + } + + + @Override + @ForceInline + public Float16VectorMax blend(Vector v, VectorMask m) { + return (Float16VectorMax) + super.blendTemplate(Float16MaskMax.class, + (Float16VectorMax) v, + (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax slice(int origin, Vector v) { + return (Float16VectorMax) super.sliceTemplate(origin, v); // specialize + } + + @Override + @ForceInline + public Float16VectorMax slice(int origin) { + return (Float16VectorMax) super.sliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16VectorMax unslice(int origin, Vector w, int part) { + return (Float16VectorMax) super.unsliceTemplate(origin, w, part); // specialize + } + + @Override + @ForceInline + public Float16VectorMax unslice(int origin, Vector w, int part, VectorMask m) { + return (Float16VectorMax) + super.unsliceTemplate(Float16MaskMax.class, + origin, w, part, + (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax unslice(int origin) { + return (Float16VectorMax) super.unsliceTemplate(origin); // specialize + } + + @Override + @ForceInline + public Float16VectorMax rearrange(VectorShuffle s) { + return (Float16VectorMax) + super.rearrangeTemplate(Float16ShuffleMax.class, + (Float16ShuffleMax) s); // specialize + } + + @Override + @ForceInline + public Float16VectorMax rearrange(VectorShuffle shuffle, + VectorMask m) { + return (Float16VectorMax) + super.rearrangeTemplate(Float16ShuffleMax.class, + Float16MaskMax.class, + (Float16ShuffleMax) shuffle, + (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax rearrange(VectorShuffle s, + Vector v) { + return (Float16VectorMax) + super.rearrangeTemplate(Float16ShuffleMax.class, + (Float16ShuffleMax) s, + (Float16VectorMax) v); // specialize + } + + @Override + @ForceInline + public Float16VectorMax compress(VectorMask m) { + return (Float16VectorMax) + super.compressTemplate(Float16MaskMax.class, + (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax expand(VectorMask m) { + return (Float16VectorMax) + super.expandTemplate(Float16MaskMax.class, + (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax selectFrom(Vector v) { + return (Float16VectorMax) + super.selectFromTemplate((Float16VectorMax) v); // specialize + } + + @Override + @ForceInline + public Float16VectorMax selectFrom(Vector v, + VectorMask m) { + return (Float16VectorMax) + super.selectFromTemplate((Float16VectorMax) v, + Float16MaskMax.class, (Float16MaskMax) m); // specialize + } + + @Override + @ForceInline + public Float16VectorMax selectFrom(Vector v1, + Vector v2) { + return (Float16VectorMax) + super.selectFromTemplate((Float16VectorMax) v1, (Float16VectorMax) v2); // specialize + } + + @ForceInline + @Override + public short lane(int i) { + if (i < 0 || i >= VLENGTH) { + throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + short bits = laneHelper(i); + return bits; + } + + @ForceInline + public short laneHelper(int i) { + return (short) VectorSupport.extract( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, + (vec, ix) -> { + short[] vecarr = vec.vec(); + return vecarr[ix]; + }); + } + + @ForceInline + @Override + public Float16VectorMax withLane(int i, short e) { + if (i < 0 || i >= VLENGTH) { + throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + VLENGTH); + } + return withLaneHelper(i, e); + } + + @ForceInline + public Float16VectorMax withLaneHelper(int i, short e) { + return VectorSupport.insert( + VCLASS, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (long)e, + (v, ix, bits) -> { + short[] res = v.vec().clone(); + res[ix] = (short)bits; + return v.vectorFactory(res); + }); + } + + // Mask + @ValueBased + static final class Float16MaskMax extends AbstractMask { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16MaskMax(boolean[] bits) { + this(bits, 0); + } + + Float16MaskMax(boolean[] bits, int offset) { + super(prepare(bits, offset)); + } + + Float16MaskMax(boolean val) { + super(prepare(val)); + } + + private static boolean[] prepare(boolean[] bits, int offset) { + boolean[] newBits = new boolean[VSPECIES.laneCount()]; + for (int i = 0; i < newBits.length; i++) { + newBits[i] = bits[offset + i]; + } + return newBits; + } + + private static boolean[] prepare(boolean val) { + boolean[] bits = new boolean[VSPECIES.laneCount()]; + Arrays.fill(bits, val); + return bits; + } + + @ForceInline + final @Override + public Float16Species vspecies() { + // ISSUE: This should probably be a @Stable + // field inside AbstractMask, rather than + // a megamorphic method. + return VSPECIES; + } + + @ForceInline + boolean[] getBits() { + return (boolean[])getPayload(); + } + + @Override + Float16MaskMax uOp(MUnOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i]); + } + return new Float16MaskMax(res); + } + + @Override + Float16MaskMax bOp(VectorMask m, MBinOp f) { + boolean[] res = new boolean[VSPECIES.laneCount()]; + boolean[] bits = getBits(); + boolean[] mbits = ((Float16MaskMax)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, bits[i], mbits[i]); + } + return new Float16MaskMax(res); + } + + @ForceInline + @Override + public final + Float16VectorMax toVector() { + return (Float16VectorMax) super.toVectorTemplate(); // specialize + } + + /** + * Helper function for lane-wise mask conversions. + * This function kicks in after intrinsic failure. + */ + @ForceInline + private final + VectorMask defaultMaskCast(AbstractSpecies dsp) { + if (length() != dsp.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + boolean[] maskArray = toArray(); + return dsp.maskFactory(maskArray).check(dsp); + } + + @Override + @ForceInline + public VectorMask cast(VectorSpecies dsp) { + AbstractSpecies species = (AbstractSpecies) dsp; + if (length() != species.laneCount()) + throw new IllegalArgumentException("VectorMask length and species length differ"); + + return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST, + this.getClass(), LANE_TYPE_ORDINAL, VLENGTH, + species.maskType(), species.laneTypeOrdinal(), VLENGTH, + this, species, + (m, s) -> s.maskFactory(m.toArray()).check(s)); + } + + @Override + @ForceInline + /*package-private*/ + Float16MaskMax indexPartiallyInUpperRange(long offset, long limit) { + return (Float16MaskMax) VectorSupport.indexPartiallyInUpperRange( + Float16MaskMax.class, LANE_TYPE_ORDINAL, VLENGTH, offset, limit, + (o, l) -> (Float16MaskMax) TRUE_MASK.indexPartiallyInRange(o, l)); + } + + // Unary operations + + @Override + @ForceInline + public Float16MaskMax not() { + return xor(maskAll(true)); + } + + @Override + @ForceInline + public Float16MaskMax compress() { + return (Float16MaskMax)VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_MASK_COMPRESS, + Float16VectorMax.class, Float16MaskMax.class, LANE_TYPE_ORDINAL, VLENGTH, null, this, + (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, Float16.float16ToRawShortBits(Float16.valueOf(m1.trueCount())))); + } + + + // Binary operations + + @Override + @ForceInline + public Float16MaskMax and(VectorMask mask) { + Objects.requireNonNull(mask); + Float16MaskMax m = (Float16MaskMax)mask; + return VectorSupport.binaryOp(VECTOR_OP_AND, Float16MaskMax.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a & b)); + } + + @Override + @ForceInline + public Float16MaskMax or(VectorMask mask) { + Objects.requireNonNull(mask); + Float16MaskMax m = (Float16MaskMax)mask; + return VectorSupport.binaryOp(VECTOR_OP_OR, Float16MaskMax.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a | b)); + } + + @Override + @ForceInline + public Float16MaskMax xor(VectorMask mask) { + Objects.requireNonNull(mask); + Float16MaskMax m = (Float16MaskMax)mask; + return VectorSupport.binaryOp(VECTOR_OP_XOR, Float16MaskMax.class, null, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, m, null, + (m1, m2, vm) -> m1.bOp(m2, (i, a, b) -> a ^ b)); + } + + // Mask Query operations + + @Override + @ForceInline + public int trueCount() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TRUECOUNT, Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> trueCountHelper(m.getBits())); + } + + @Override + @ForceInline + public int firstTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_FIRSTTRUE, Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> firstTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public int lastTrue() { + return (int) VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_LASTTRUE, Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> lastTrueHelper(m.getBits())); + } + + @Override + @ForceInline + public long toLong() { + if (length() > Long.SIZE) { + throw new UnsupportedOperationException("too many lanes for one long"); + } + return VectorSupport.maskReductionCoerced(VECTOR_OP_MASK_TOLONG, Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, this, + (m) -> toLongHelper(m.getBits())); + } + + // laneIsSet + + @Override + @ForceInline + public boolean laneIsSet(int i) { + Objects.checkIndex(i, length()); + return VectorSupport.extract(Float16MaskMax.class, LANE_TYPE_ORDINAL, VLENGTH, + this, i, (m, idx) -> (m.getBits()[idx] ? 1L : 0L)) == 1L; + } + + // Reductions + + @Override + @ForceInline + public boolean anyTrue() { + return VectorSupport.test(BT_ne, Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> anyTrueHelper(((Float16MaskMax)m).getBits())); + } + + @Override + @ForceInline + public boolean allTrue() { + return VectorSupport.test(BT_overflow, Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + this, VSPECIES.maskAll(true), + (m, _) -> allTrueHelper(((Float16MaskMax)m).getBits())); + } + + @ForceInline + /*package-private*/ + static Float16MaskMax maskAll(boolean bit) { + return VectorSupport.fromBitsCoerced(Float16MaskMax.class, LANEBITS_TYPE_ORDINAL, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, _) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + } + private static final Float16MaskMax TRUE_MASK = new Float16MaskMax(true); + private static final Float16MaskMax FALSE_MASK = new Float16MaskMax(false); + + } + + // Shuffle + @ValueBased + static final class Float16ShuffleMax extends AbstractShuffle { + static final int VLENGTH = VSPECIES.laneCount(); // used by the JVM + + static final Class CTYPE = short.class; // used by the JVM + + Float16ShuffleMax(short[] indices) { + super(indices); + assert(VLENGTH == indices.length); + assert(indicesInRange(indices)); + } + + Float16ShuffleMax(int[] indices, int i) { + this(prepare(indices, i)); + } + + Float16ShuffleMax(IntUnaryOperator fn) { + this(prepare(fn)); + } + + short[] indices() { + return (short[])getPayload(); + } + + @Override + @ForceInline + public Float16Species vspecies() { + return VSPECIES; + } + + static { + // There must be enough bits in the shuffle lanes to encode + // VLENGTH valid indexes and VLENGTH exceptional ones. + assert(VLENGTH < Short.MAX_VALUE); + assert(Short.MIN_VALUE <= -VLENGTH); + } + static final Float16ShuffleMax IOTA = new Float16ShuffleMax(IDENTITY); + + @Override + @ForceInline + public Float16VectorMax toVector() { + return (Float16VectorMax) toBitsVector().castShape(VSPECIES, 0); + } + + @Override + @ForceInline + ShortVectorMax toBitsVector() { + return (ShortVectorMax) super.toBitsVectorTemplate(); + } + + @Override + ShortVectorMax toBitsVector0() { + return ((ShortVectorMax) VSPECIES.asIntegral().dummyVector()).vectorFactory(indices()); + } + + @Override + @ForceInline + public int laneSource(int i) { + return (int)toBitsVector().lane(i); + } + + @Override + @ForceInline + public void intoArray(int[] a, int offset) { + VectorSpecies species = IntVector.SPECIES_MAX; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoArray(a, offset); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoArray(a, offset + species.length()); + } + + @Override + @ForceInline + public void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo) { + VectorSpecies species = IntVector.SPECIES_MAX; + Vector v = toBitsVector(); + v.convertShape(VectorOperators.S2I, species, 0) + .reinterpretAsInts() + .intoMemorySegment(ms, offset, bo); + v.convertShape(VectorOperators.S2I, species, 1) + .reinterpretAsInts() + .intoMemorySegment(ms, offset + species.vectorByteSize(), bo); + } + + @Override + @ForceInline + public final Float16MaskMax laneIsValid() { + return (Float16MaskMax) toBitsVector().compare(VectorOperators.GE, 0) + .cast(VSPECIES); + } + + @ForceInline + @Override + public final Float16ShuffleMax rearrange(VectorShuffle shuffle) { + Float16ShuffleMax concreteShuffle = (Float16ShuffleMax) shuffle; + return (Float16ShuffleMax) toBitsVector().rearrange(concreteShuffle.cast(ShortVector.SPECIES_MAX)) + .toShuffle(VSPECIES, false); + } + + @ForceInline + @Override + public final Float16ShuffleMax wrapIndexes() { + ShortVectorMax v = toBitsVector(); + if ((length() & (length() - 1)) == 0) { + v = (ShortVectorMax) v.lanewise(VectorOperators.AND, length() - 1); + } else { + v = (ShortVectorMax) v.blend(v.lanewise(VectorOperators.ADD, length()), + v.compare(VectorOperators.LT, 0)); + } + return (Float16ShuffleMax) v.toShuffle(VSPECIES, false); + } + + private static short[] prepare(int[] indices, int offset) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = indices[offset + i]; + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static short[] prepare(IntUnaryOperator f) { + short[] a = new short[VLENGTH]; + for (int i = 0; i < VLENGTH; i++) { + int si = f.applyAsInt(i); + si = partiallyWrapIndex(si, VLENGTH); + a[i] = (short)si; + } + return a; + } + + private static boolean indicesInRange(short[] indices) { + int length = indices.length; + for (short si : indices) { + if (si >= (short)length || si < (short)(-length)) { + String msg = ("index "+si+"out of range ["+length+"] in "+ + java.util.Arrays.toString(indices)); + throw new AssertionError(msg); + } + } + return true; + } + } + + // ================================================ + + // Specialized low-level memory operations. + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset) { + return super.fromArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, VectorMask m, int offsetInRange) { + return super.fromArray0Template(Float16MaskMax.class, a, offset, (Float16MaskMax) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromArray0(short[] a, int offset, int[] indexMap, int mapOffset, VectorMask m) { + return super.fromArray0Template(Float16MaskMax.class, a, offset, indexMap, mapOffset, (Float16MaskMax) m); + } + + + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset) { + return super.fromMemorySegment0Template(ms, offset); // specialize + } + + @ForceInline + @Override + final + Float16Vector fromMemorySegment0(MemorySegment ms, long offset, VectorMask m, int offsetInRange) { + return super.fromMemorySegment0Template(Float16MaskMax.class, ms, offset, (Float16MaskMax) m, offsetInRange); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset) { + super.intoArray0Template(a, offset); // specialize + } + + @ForceInline + @Override + final + void intoArray0(short[] a, int offset, VectorMask m) { + super.intoArray0Template(Float16MaskMax.class, a, offset, (Float16MaskMax) m); + } + + + + @ForceInline + @Override + final + void intoMemorySegment0(MemorySegment ms, long offset, VectorMask m) { + super.intoMemorySegment0Template(Float16MaskMax.class, ms, offset, (Float16MaskMax) m); + } + + + // End of specialized low-level memory operations. + + // ================================================ + +} + diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LaneType.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LaneType.java index c18bbce1f34..69252017827 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LaneType.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LaneType.java @@ -40,7 +40,8 @@ enum LaneType { BYTE(byte.class, Byte.class, byte[].class, 'I', -1, Byte.SIZE, byte.class), SHORT(short.class, Short.class, short[].class, 'I', -1, Short.SIZE, short.class), INT(int.class, Integer.class, int[].class, 'I', -1, Integer.SIZE, int.class), - LONG(long.class, Long.class, long[].class, 'I', -1, Long.SIZE, long.class); + LONG(long.class, Long.class, long[].class, 'I', -1, Long.SIZE, long.class), + FLOAT16(Float16.class, Short.class, short[].class, 'F', 11, Float16.SIZE, short.class); LaneType(Class elementType, Class genericElementType, @@ -66,7 +67,7 @@ enum LaneType { // printName. If we do unsigned or vector or bit lane types, // report that condition also. this.typeChar = genericElementType.getSimpleName().charAt(0); - assert("FDBSIL".indexOf(typeChar) == ordinal()) : this; + assert("FDBSILS".charAt(ordinal()) == typeChar) : this; this.carrierType = carrierType; assert(carrierType.isPrimitive()); @@ -181,7 +182,8 @@ enum LaneType { SK_SHORT = 4, SK_INT = 5, SK_LONG = 6, - SK_LIMIT = 7; + SK_FLOAT16 = 7, + SK_LIMIT = 8; /*package-private*/ @ForceInline @@ -278,5 +280,6 @@ enum LaneType { assert(ofLaneTypeOrdinal(LT_SHORT) == SHORT); assert(ofLaneTypeOrdinal(LT_INT) == INT); assert(ofLaneTypeOrdinal(LT_LONG) == LONG); + assert(ofLaneTypeOrdinal(LT_FLOAT16) == FLOAT16); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index a9184d1faa9..ac381330e31 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -4149,22 +4149,14 @@ public abstract sealed class ShortVector extends AbstractVector /** * {@inheritDoc} - * - * @implNote This method always throws - * {@code UnsupportedOperationException}, because there is no floating - * point type of the same size as {@code short}. The return type - * of this method is arbitrarily designated as - * {@code Vector}. Future versions of this API may change the return - * type if additional floating point types become available. */ @ForceInline @Override public final - Vector + Float16Vector viewAsFloatingLanes() { LaneType flt = LaneType.SHORT.asFloating(); - // asFloating() will throw UnsupportedOperationException for the unsupported type short - throw new AssertionError("Cannot reach here"); + return (Float16Vector) asVectorRaw(flt); } // ================================================ diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java index 4e064e0af37..1bffb8d2238 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java @@ -200,11 +200,11 @@ import java.util.Arrays; * element type (such as access to element values in lanes, logical operations * on values of integral elements types, or transcendental operations on values * of floating point element types). - * There are six abstract subclasses of Vector corresponding to the supported set + * There are seven abstract subclasses of Vector corresponding to the supported set * of element types, {@link ByteVector}, {@link ShortVector}, - * {@link IntVector}, {@link LongVector}, {@link FloatVector}, and - * {@link DoubleVector}. Along with type-specific operations these classes - * support creation of vector values (instances of Vector). + * {@link IntVector}, {@link LongVector}, {@link FloatVector}, + * {@link DoubleVector}, and {@link Float16Vector}. Along with type-specific + * operations these classes support creation of vector values (instances of Vector). * They expose static constants corresponding to the supported species, * and static methods on these types generally take a species as a parameter. * For example, @@ -3826,6 +3826,19 @@ public abstract sealed class Vector extends jdk.internal.vm.vector.VectorSupp */ public abstract LongVector reinterpretAsLongs(); + /** + * Reinterprets this vector as a vector of the same shape + * and contents but a lane type of {@code Float16}, + * where the lanes are assembled from successive bytes + * according to little-endian order. + * It is a convenience method for the expression + * {@code reinterpretShape(species().withLanes(Float16.class))}. + * It may be considered an inverse to {@link Vector#reinterpretAsBytes()}. + * + * @return a {@code Float16Vector} with the same shape and information content + */ + public abstract Float16Vector reinterpretAsFloat16s(); + /** * Reinterprets this vector as a vector of the same shape * and contents but a lane type of {@code float}, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java index cc5a7ccbdef..7c6b6e69086 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java @@ -64,8 +64,9 @@ import static jdk.internal.vm.vector.Utils.isNonCapturingLambda; * *

  • {@code bits(x)} — a function call which produces the * underlying bits of the value {@code x}. If {@code x} is a floating - * point value, this is either {@code doubleToLongBits(x)} or - * {@code floatToIntBits(x)}. Otherwise, the value is just {@code x}. + * point value, this is {@code doubleToLongBits(x)}, + * {@code floatToIntBits(x)}, or {@code float16ToShortBits(x)}. + * Otherwise, the value is just {@code x}. * *
  • {@code ESIZE} — the size in bytes of the operand type * @@ -73,6 +74,26 @@ import static jdk.internal.vm.vector.Utils.isNonCapturingLambda; * *
  • {@code intVal}, {@code byteVal}, etc. — the operand of a * conversion, with the indicated type + * + *
  • Single-letter type codes used in the names of + * {@linkplain Conversion conversion} operator tokens (for example + * {@link #B2D}, {@link #F2H}, {@link #H2F}, {@link #REINTERPRET_F2I}, + * {@link #ZERO_EXTEND_B2L}) abbreviate lane types as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Lane type letter codes
    LetterLane type
    {@code B}{@code byte}
    {@code S}{@code short}
    {@code I}{@code int}
    {@code L}{@code long}
    {@code F}{@code float}
    {@code D}{@code double}
    {@code H}{@link Float16} ("half")
    * * *

    Operations on floating point vectors

    @@ -307,13 +328,13 @@ public final class VectorOperators { */ public sealed interface Conversion extends Operator { /** - * The domain of this conversion, a primitive type. + * The domain of this conversion, a supported lane type. * @return the domain of this conversion */ Class domainType(); /** - * The range of this conversion, a primitive type. + * The range of this conversion, a supported lane type. * @return the range of this conversion */ @Override @@ -657,6 +678,8 @@ public final class VectorOperators { public static final Conversion B2L = convert("B2L", 'C', byte.class, long.class, VO_KIND_CAST, VO_ALL); /** Convert {@code byteVal} to {@code (short)byteVal}. */ public static final Conversion B2S = convert("B2S", 'C', byte.class, short.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code byteVal} to {@code (Float16)byteVal}. */ + public static final Conversion B2H = convert("B2H", 'C', byte.class, Float16.class, VO_KIND_CAST, VO_ALL); /** Convert {@code doubleVal} to {@code (byte)doubleVal}. */ public static final Conversion D2B = convert("D2B", 'C', double.class, byte.class, VO_KIND_CAST, VO_ALL); /** Convert {@code doubleVal} to {@code (float)doubleVal}. */ @@ -667,6 +690,8 @@ public final class VectorOperators { public static final Conversion D2L = convert("D2L", 'C', double.class, long.class, VO_KIND_CAST, VO_ALL); /** Convert {@code doubleVal} to {@code (short)doubleVal}. */ public static final Conversion D2S = convert("D2S", 'C', double.class, short.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code doubleVal} to {@code (Float16)doubleVal}. */ + public static final Conversion D2H = convert("D2H", 'C', double.class, Float16.class, VO_KIND_CAST, VO_ALL); /** Convert {@code floatVal} to {@code (byte)floatVal}. */ public static final Conversion F2B = convert("F2B", 'C', float.class, byte.class, VO_KIND_CAST, VO_ALL); /** Convert {@code floatVal} to {@code (double)floatVal}. */ @@ -677,6 +702,8 @@ public final class VectorOperators { public static final Conversion F2L = convert("F2L", 'C', float.class, long.class, VO_KIND_CAST, VO_ALL); /** Convert {@code floatVal} to {@code (short)floatVal}. */ public static final Conversion F2S = convert("F2S", 'C', float.class, short.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code floatVal} to {@code (Float16)floatVal}. */ + public static final Conversion F2H = convert("F2H", 'C', float.class, Float16.class, VO_KIND_CAST, VO_ALL); /** Convert {@code intVal} to {@code (byte)intVal}. */ public static final Conversion I2B = convert("I2B", 'C', int.class, byte.class, VO_KIND_CAST, VO_ALL); /** Convert {@code intVal} to {@code (double)intVal}. */ @@ -687,6 +714,8 @@ public final class VectorOperators { public static final Conversion I2L = convert("I2L", 'C', int.class, long.class, VO_KIND_CAST, VO_ALL); /** Convert {@code intVal} to {@code (short)intVal}. */ public static final Conversion I2S = convert("I2S", 'C', int.class, short.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code intVal} to {@code (Float16)intVal}. */ + public static final Conversion I2H = convert("I2H", 'C', int.class, Float16.class, VO_KIND_CAST, VO_ALL); /** Convert {@code longVal} to {@code (byte)longVal}. */ public static final Conversion L2B = convert("L2B", 'C', long.class, byte.class, VO_KIND_CAST, VO_ALL); /** Convert {@code longVal} to {@code (double)longVal}. */ @@ -697,6 +726,8 @@ public final class VectorOperators { public static final Conversion L2I = convert("L2I", 'C', long.class, int.class, VO_KIND_CAST, VO_ALL); /** Convert {@code longVal} to {@code (short)longVal}. */ public static final Conversion L2S = convert("L2S", 'C', long.class, short.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code longVal} to {@code (Float16)longVal}. */ + public static final Conversion L2H = convert("L2H", 'C', long.class, Float16.class, VO_KIND_CAST, VO_ALL); /** Convert {@code shortVal} to {@code (byte)shortVal}. */ public static final Conversion S2B = convert("S2B", 'C', short.class, byte.class, VO_KIND_CAST, VO_ALL); /** Convert {@code shortVal} to {@code (double)shortVal}. */ @@ -707,6 +738,21 @@ public final class VectorOperators { public static final Conversion S2I = convert("S2I", 'C', short.class, int.class, VO_KIND_CAST, VO_ALL); /** Convert {@code shortVal} to {@code (long)shortVal}. */ public static final Conversion S2L = convert("S2L", 'C', short.class, long.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code shortVal} to {@code (Float16)shortVal}. */ + public static final Conversion S2H = convert("S2H", 'C', short.class, Float16.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code Float16Val} to {@code (byte)Float16Val}. */ + public static final Conversion H2B = convert("H2B", 'C', Float16.class, byte.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code Float16Val} to {@code (short)Float16Val}. */ + public static final Conversion H2S = convert("H2S", 'C', Float16.class, short.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code Float16Val} to {@code (double)Float16Val}. */ + public static final Conversion H2D = convert("H2D", 'C', Float16.class, double.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code Float16Val} to {@code (float)Float16Val}. */ + public static final Conversion H2F = convert("H2F", 'C', Float16.class, float.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code Float16Val} to {@code (int)Float16Val}. */ + public static final Conversion H2I = convert("H2I", 'C', Float16.class, int.class, VO_KIND_CAST, VO_ALL); + /** Convert {@code Float16Val} to {@code (long)Float16Val}. */ + public static final Conversion H2L = convert("H2L", 'C', Float16.class, long.class, VO_KIND_CAST, VO_ALL); + /** Reinterpret bits of {@code doubleVal} as {@code long}. As if by {@link Double#doubleToRawLongBits(double)} */ public static final Conversion REINTERPRET_D2L = convert("REINTERPRET_D2L", 'R', double.class, long.class, VO_KIND_BITWISE, VO_ALL); /** Reinterpret bits of {@code floatVal} as {@code int}. As if by {@link Float#floatToRawIntBits(float)} */ diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 74d6ce45db0..7c6fb3bcfb2 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -41,12 +41,65 @@ import static jdk.internal.vm.vector.VectorSupport.*; import static jdk.incubator.vector.VectorIntrinsics.*; import static jdk.incubator.vector.VectorOperators.*; +#if[FP16] +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import static java.lang.Float.*; +#end[FP16] #warn This file is preprocessed before being compiled /** * A specialized {@link Vector} representing an ordered immutable sequence of +#if[FP16] + * 16-bit data values in the IEEE 754 binary16 format. + *

    + * The scalar {@linkplain Float16Vector#elementType() element type} of {@code Float16Vector} + * is the class {@link Float16}, a value-based + * class holding 16-bit data in IEEE 754 binary16 format. However, the {@code Float16} + * class is not used by vector operations that accept scalar element values, or + * arrays of scalar element values. Instead, the primitive type {@code short} is + * used to explicitly hold 16-bit data in IEEE 754 binary16 format. For such operations + * it may be necessary to explicitly convert between floating-point values of {@code Float16} + * or {@code float} and values of {@code short} using the appropriate conversion + * methods on {@code Float16} or {@code Float}. + * + *

    + * The specifications for operations on elements of this class are written as if + * {@code Float16} is a primitive floating-point type. An operation referencing a + * Java operator is mapped to a method on {@code Float16} that specifies that + * operator's semantics. For example, the semantics of the {@code +} operator, + * as referenced by {@link Vector#add(Vector)} and {@link VectorOperators#ADD}, + * is mapped to the method {@link Float16#add(Float16, Float16)}. + * An operation referencing a method on {@link Math} is mapped to a method of the + * same name on {@code Float16}, if it exists. For example, {@link Math#fma} is + * mapped to {@link Float16#fma}, as referenced by {@link Float16Vector#fma(short, short)} + * and {@link VectorOperators#FMA}. + * Otherwise, if there is no equivalent method on {@code Float16}, the expression that is + * an invocation of a method on {@code Math} is mapped to an expression that converts + * the {@code Float16} arguments to {@code double} values or {@code float} values as + * required by the method's parameter types, invokes the method on {@code Math} with + * the converted values, and converts the resulting {@code double} or {@code float} value + * to a {@code Float16} value. For example, {@link Math#sin} is mapped to the expression + * {@code Float16.valueOf(Math.sin(a.doubleValue()))}, where {@code a} is the + * {@code Float16} lane value, as referenced by {@link VectorOperators#SIN}. + * + * @apiNote + * {@code Float16} is currently a value-based class and therefore cannot be optimally + * used as the scalar element type of vector operations until it becomes a value class + * that behaves similarly to the primitive type {@code short} and to arrays of {@code short}. + * For example, accessing {@code Float16} vectors using arrays requires those arrays be + * {@code short[]} arrays. Accessing vectors using memory segments requires, naturally, + * that consecutive 16-bits of memory hold 16-bit data values in the IEEE 754 binary16 + * format. + * @see Float16 + * @see Float16#float16ToRawShortBits(Float16) + * @see Float16#shortBitsToFloat16(short) + * @see Float#floatToFloat16(float) + * @see Float#float16ToFloat(short) +#else[FP16] * {@code $type$} values. +#end[FP16] */ @SuppressWarnings("cast") // warning: redundant cast public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtype$> @@ -62,7 +115,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp static final int FORBID_OPCODE_KIND = VO_ONLYFP; #end[FP] - static final ValueLayout.Of$Type$ ELEMENT_LAYOUT = ValueLayout.JAVA_$TYPE$.withByteAlignment(1); + static final ValueLayout.Of$ElemLayout$ ELEMENT_LAYOUT = ValueLayout.JAVA_$TYPE$.withByteAlignment(1); static final int LANE_TYPE_ORDINAL = $laneType$; @@ -158,7 +211,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /*package-private*/ interface FUnOp { - $type$ apply(int i, $type$ a); + $fallbacktype$ apply(int i, $fallbacktype$ a); } /*package-private*/ @@ -170,7 +223,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] vec = vec(); $type$[] res = new $type$[length()]; for (int i = 0; i < res.length; i++) { +#if[FP16] + res[i] = floatToFloat16(f.apply(i, float16ToFloat(vec[i]))); +#else[FP16] res[i] = f.apply(i, vec[i]); +#end[FP16] } return vectorFactory(res); } @@ -190,16 +247,60 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] res = new $type$[length()]; boolean[] mbits = ((AbstractMask<$Boxtype$>)m).getBits(); for (int i = 0; i < res.length; i++) { +#if[FP16] + res[i] = mbits[i] ? floatToFloat16(f.apply(i, float16ToFloat(vec[i]))) : vec[i]; +#else[FP16] res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i]; +#end[FP16] } return vectorFactory(res); } +#if[FP16] + /*package-private*/ + interface FUnRawOp { + $type$ apply(int i, $type$ a); + } + + /*package-private*/ + abstract + $abstractvectortype$ uRawOp(FUnRawOp f); + @ForceInline + final + $abstractvectortype$ uRawOpTemplate(FUnRawOp f) { + $type$[] vec = vec(); + $type$[] res = new $type$[length()]; + for (int i = 0; i < res.length; i++) { + res[i] = f.apply(i, vec[i]); + } + return vectorFactory(res); + } + + /*package-private*/ + abstract + $abstractvectortype$ uRawOp(VectorMask<$Boxtype$> m, + FUnRawOp f); + @ForceInline + final + $abstractvectortype$ uRawOpTemplate(VectorMask<$Boxtype$> m, + FUnRawOp f) { + if (m == null) { + return uRawOpTemplate(f); + } + $type$[] vec = vec(); + $type$[] res = new $type$[length()]; + boolean[] mbits = ((AbstractMask<$Boxtype$>)m).getBits(); + for (int i = 0; i < res.length; i++) { + res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i]; + } + return vectorFactory(res); + } +#end[FP16] // Binary operator /*package-private*/ interface FBinOp { - $type$ apply(int i, $type$ a, $type$ b); + $fallbacktype$ apply(int i, $fallbacktype$ a, $fallbacktype$ b); } /*package-private*/ @@ -214,7 +315,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] vec1 = this.vec(); $type$[] vec2 = (($abstractvectortype$)o).vec(); for (int i = 0; i < res.length; i++) { +#if[FP16] + res[i] = floatToFloat16(f.apply(i, float16ToFloat(vec1[i]), float16ToFloat(vec2[i]))); +#else[FP16] res[i] = f.apply(i, vec1[i], vec2[i]); +#end[FP16] } return vectorFactory(res); } @@ -237,7 +342,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] vec2 = (($abstractvectortype$)o).vec(); boolean[] mbits = ((AbstractMask<$Boxtype$>)m).getBits(); for (int i = 0; i < res.length; i++) { +#if[FP16] + res[i] = mbits[i] ? floatToFloat16(f.apply(i, float16ToFloat(vec1[i]), float16ToFloat(vec2[i]))) : vec1[i]; +#else[FP16] res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i]) : vec1[i]; +#end[FP16] } return vectorFactory(res); } @@ -310,7 +419,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] vec = vec(); boolean[] mbits = ((AbstractMask<$Boxtype$>)m).getBits(); for (int i = 0; i < vec.length; i++) { +#if[FP16] + v = mbits[i] ? floatToFloat16(f.apply(i, float16ToFloat(v), float16ToFloat(vec[i]))) : v; +#else[FP16] v = mbits[i] ? f.apply(i, v, vec[i]) : v; +#end[FP16] } return v; } @@ -320,7 +433,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$ rOpTemplate($type$ v, FBinOp f) { $type$[] vec = vec(); for (int i = 0; i < vec.length; i++) { +#if[FP16] + v = floatToFloat16(f.apply(i, float16ToFloat(v), float16ToFloat(vec[i]))); +#else[FP16] v = f.apply(i, v, vec[i]); +#end[FP16] } return v; } @@ -516,13 +633,21 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /*package-private*/ @ForceInline static long toBits($type$ e) { +#if[FP16] + return e; +#else[FP16] return {#if[FP]? $Type$.$type$ToRaw$Bitstype$Bits(e): e}; +#end[FP16] } /*package-private*/ @ForceInline static $type$ fromBits(long bits) { +#if[FP16] + return (short)bits; +#else[FP16] return {#if[FP]?$Type$.$bitstype$BitsTo$Type$}(($bitstype$)bits); +#end[FP16] } static $abstractvectortype$ expandHelper(Vector<$Boxtype$> v, VectorMask<$Boxtype$> m) { @@ -562,7 +687,12 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] vecPayload2 = (($abstractvectortype$)src1).vec(); $type$[] vecPayload3 = (($abstractvectortype$)src2).vec(); for (int i = 0; i < vlen; i++) { +#if[FP16] + int index = shortBitsToFloat16(vecPayload1[i]).intValue(); + int wrapped_index = VectorIntrinsics.wrapToRange(index, 2 * vlen); +#else[FP16] int wrapped_index = VectorIntrinsics.wrapToRange((int)vecPayload1[i], 2 * vlen); +#end[FP16] res[i] = wrapped_index >= vlen ? vecPayload3[wrapped_index - vlen] : vecPayload2[wrapped_index]; } return (($abstractvectortype$)src1).vectorFactory(res); @@ -594,7 +724,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $Type$Species vsp = ($Type$Species) species; #if[FP] return VectorSupport.fromBitsCoerced(vsp.vectorType(), LANE_TYPE_ORDINAL, species.length(), - toBits(0.0f), MODE_BROADCAST, vsp, + toBits({#if[FP16]?(short) 0:0.0f}), MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); #else[FP] return VectorSupport.fromBitsCoerced(vsp.vectorType(), LANE_TYPE_ORDINAL, species.length(), @@ -784,27 +914,32 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp private static UnaryOperation<$abstractvectortype$, VectorMask<$Boxtype$>> unaryOperations(int opc_) { switch (opc_) { +#if[FP16] case VECTOR_OP_NEG: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) -a); + v0.uOp(m, (i, a) -> Float16.negate(Float16.valueOf(a)).floatValue()); +#else[FP16] + case VECTOR_OP_NEG: return (v0, m) -> + v0.uOp(m, (i, a) -> ($fallbacktype$) -a); +#end[FP16] case VECTOR_OP_ABS: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.abs(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.abs(a)); #if[!FP] #if[intOrLong] case VECTOR_OP_BIT_COUNT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) $Boxtype$.bitCount(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) $Boxtype$.bitCount(a)); case VECTOR_OP_TZ_COUNT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) $Boxtype$.numberOfTrailingZeros(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) $Boxtype$.numberOfTrailingZeros(a)); case VECTOR_OP_LZ_COUNT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) $Boxtype$.numberOfLeadingZeros(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) $Boxtype$.numberOfLeadingZeros(a)); case VECTOR_OP_REVERSE: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) $Boxtype$.reverse(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) $Boxtype$.reverse(a)); #else[intOrLong] case VECTOR_OP_BIT_COUNT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) bitCount(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) bitCount(a)); case VECTOR_OP_TZ_COUNT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) numberOfTrailingZeros(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) numberOfTrailingZeros(a)); case VECTOR_OP_LZ_COUNT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) numberOfLeadingZeros(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) numberOfLeadingZeros(a)); case VECTOR_OP_REVERSE: return (v0, m) -> v0.uOp(m, (i, a) -> reverse(a)); #end[intOrLong] @@ -814,43 +949,47 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp v0.uOp(m, (i, a) -> a); #else[byte] case VECTOR_OP_REVERSE_BYTES: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) $Boxtype$.reverseBytes(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) $Boxtype$.reverseBytes(a)); #end[byte] #end[BITWISE] #end[!FP] #if[FP] case VECTOR_OP_SIN: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.sin(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.sin(a)); case VECTOR_OP_COS: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.cos(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.cos(a)); case VECTOR_OP_TAN: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.tan(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.tan(a)); case VECTOR_OP_ASIN: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.asin(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.asin(a)); case VECTOR_OP_ACOS: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.acos(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.acos(a)); case VECTOR_OP_ATAN: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.atan(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.atan(a)); case VECTOR_OP_EXP: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.exp(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.exp(a)); case VECTOR_OP_LOG: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.log(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.log(a)); case VECTOR_OP_LOG10: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.log10(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.log10(a)); case VECTOR_OP_SQRT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.sqrt(a)); +#if[FP16] + v0.uOp(m, (i, a) -> Float16.sqrt(Float16.valueOf(a)).floatValue()); +#else[FP16] + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.sqrt(a)); +#end[FP16] case VECTOR_OP_CBRT: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.cbrt(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.cbrt(a)); case VECTOR_OP_SINH: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.sinh(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.sinh(a)); case VECTOR_OP_COSH: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.cosh(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.cosh(a)); case VECTOR_OP_TANH: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.tanh(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.tanh(a)); case VECTOR_OP_EXPM1: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.expm1(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.expm1(a)); case VECTOR_OP_LOG1P: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) Math.log1p(a)); + v0.uOp(m, (i, a) -> ($fallbacktype$) Math.log1p(a)); #end[FP] default: return null; } @@ -996,46 +1135,46 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp private static BinaryOperation<$abstractvectortype$, VectorMask<$Boxtype$>> binaryOperations(int opc_) { switch (opc_) { case VECTOR_OP_ADD: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a + b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a + b)); case VECTOR_OP_SUB: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a - b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a - b)); case VECTOR_OP_MUL: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a * b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a * b)); case VECTOR_OP_DIV: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a / b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a / b)); case VECTOR_OP_MAX: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)Math.max(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)Math.max(a, b)); case VECTOR_OP_MIN: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)Math.min(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)Math.min(a, b)); #if[BITWISE] case VECTOR_OP_AND: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a & b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a & b)); case VECTOR_OP_OR: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a | b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a | b)); case VECTOR_OP_XOR: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(a ^ b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(a ^ b)); case VECTOR_OP_LSHIFT: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, n) -> ($type$)(a << n)); + v0.bOp(v1, vm, (i, a, n) -> ($fallbacktype$)(a << n)); case VECTOR_OP_RSHIFT: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, n) -> ($type$)(a >> n)); + v0.bOp(v1, vm, (i, a, n) -> ($fallbacktype$)(a >> n)); case VECTOR_OP_URSHIFT: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, n) -> ($type$)((a & LSHR_SETUP_MASK) >>> n)); + v0.bOp(v1, vm, (i, a, n) -> ($fallbacktype$)((a & LSHR_SETUP_MASK) >>> n)); case VECTOR_OP_LROTATE: return (v0, v1, vm) -> v0.bOp(v1, vm, (i, a, n) -> rotateLeft(a, (int)n)); case VECTOR_OP_RROTATE: return (v0, v1, vm) -> v0.bOp(v1, vm, (i, a, n) -> rotateRight(a, (int)n)); case VECTOR_OP_UMAX: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)VectorMath.maxUnsigned(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)VectorMath.maxUnsigned(a, b)); case VECTOR_OP_UMIN: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)VectorMath.minUnsigned(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)VectorMath.minUnsigned(a, b)); case VECTOR_OP_SADD: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(VectorMath.addSaturating(a, b))); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(VectorMath.addSaturating(a, b))); case VECTOR_OP_SSUB: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(VectorMath.subSaturating(a, b))); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(VectorMath.subSaturating(a, b))); case VECTOR_OP_SUADD: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(VectorMath.addSaturatingUnsigned(a, b))); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(VectorMath.addSaturatingUnsigned(a, b))); case VECTOR_OP_SUSUB: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$)(VectorMath.subSaturatingUnsigned(a, b))); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$)(VectorMath.subSaturatingUnsigned(a, b))); #if[intOrLong] case VECTOR_OP_COMPRESS_BITS: return (v0, v1, vm) -> v0.bOp(v1, vm, (i, a, n) -> $Boxtype$.compress(a, n)); @@ -1045,13 +1184,17 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp #end[BITWISE] #if[FP] case VECTOR_OP_OR: return (v0, v1, vm) -> +#if[FP16] + v0.bOp(v1, vm, (i, a, b) -> FloatVector.fromBits(FloatVector.toBits(a) | FloatVector.toBits(b))); +#else[FP16] v0.bOp(v1, vm, (i, a, b) -> fromBits(toBits(a) | toBits(b))); +#end[FP16] case VECTOR_OP_ATAN2: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$) Math.atan2(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$) Math.atan2(a, b)); case VECTOR_OP_POW: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$) Math.pow(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$) Math.pow(a, b)); case VECTOR_OP_HYPOT: return (v0, v1, vm) -> - v0.bOp(v1, vm, (i, a, b) -> ($type$) Math.hypot(a, b)); + v0.bOp(v1, vm, (i, a, b) -> ($fallbacktype$) Math.hypot(a, b)); #end[FP] default: return null; } @@ -1147,13 +1290,13 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp public final $abstractvectortype$ lanewise(VectorOperators.Binary op, long e) { - $type$ e1 = ($type$) e; + $type$ e1 = {#if[FP16]?float16ToRawShortBits(Float16.valueOf(e)):($type$) e}; #if[BITWISE] if ((long)e1 != e // allow shift ops to clip down their int parameters && !(opKind(op, VO_SHIFT) && (int)e1 == e)) { #else[BITWISE] - if ((long)e1 != e) { + if ({#if[FP16]?shortBitsToFloat16(e1).longValue():(long)e1} != e) { #end[BITWISE] vspecies().checkValue(e); // for exception } @@ -1174,13 +1317,13 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp public final $abstractvectortype$ lanewise(VectorOperators.Binary op, long e, VectorMask<$Boxtype$> m) { - $type$ e1 = ($type$) e; + $type$ e1 = {#if[FP16]?float16ToRawShortBits(Float16.valueOf(e)):($type$) e}; #if[BITWISE] if ((long)e1 != e // allow shift ops to clip down their int parameters && !(opKind(op, VO_SHIFT) && (int)e1 == e)) { #else[BITWISE] - if ((long)e1 != e) { + if ({#if[FP16]?shortBitsToFloat16(e1).longValue():(long)e1} != e) { #end[BITWISE] vspecies().checkValue(e); // for exception } @@ -1255,12 +1398,12 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp // since our lane types are first-class types, not just dressed // up ints. private static final int SHIFT_MASK = ($Boxtype$.SIZE - 1); -#if[byteOrShort] +#if[byteOrStrictShort] // Also simulate >>> on sub-word variables with a mask. private static final int LSHR_SETUP_MASK = ((1 << $Boxtype$.SIZE) - 1); -#else[byteOrShort] +#else[byteOrStrictShort] private static final $type$ LSHR_SETUP_MASK = -1; -#end[byteOrShort] +#end[byteOrStrictShort] #end[BITWISE] // Ternary lanewise support @@ -1363,7 +1506,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp switch (opc_) { #if[FP] case VECTOR_OP_FMA: return (v0, v1_, v2_, m) -> +#if[FP16] + v0.tOp(v1_, v2_, m, (i, a, b, c) -> float16ToRawShortBits(Float16.fma(shortBitsToFloat16(a), shortBitsToFloat16(b), shortBitsToFloat16(c)))); +#else[FP16] v0.tOp(v1_, v2_, m, (i, a, b, c) -> Math.fma(a, b, c)); +#end[FP16] #end[FP] default: return null; } @@ -2392,7 +2539,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp // first kill the sign: bits = bits.and($Boxbitstype$.MAX_VALUE); // next find the bit pattern for infinity: - $bitstype$ infbits = ($bitstype$) toBits($Boxtype$.POSITIVE_INFINITY); + $bitstype$ infbits = ($bitstype$) toBits({#if[FP16]?float16ToRawShortBits($Boxtype$.POSITIVE_INFINITY):$Boxtype$.POSITIVE_INFINITY}); // now compare: if (op == IS_FINITE) { m = bits.compare(LT, infbits); @@ -2446,7 +2593,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp // first kill the sign: bits = bits.and($Boxbitstype$.MAX_VALUE); // next find the bit pattern for infinity: - $bitstype$ infbits = ($bitstype$) toBits($Boxtype$.POSITIVE_INFINITY); + $bitstype$ infbits = ($bitstype$) toBits({#if[FP16]?float16ToRawShortBits($Boxtype$.POSITIVE_INFINITY):$Boxtype$.POSITIVE_INFINITY}); // now compare: if (op == IS_FINITE) { m = bits.compare(LT, infbits, m); @@ -2517,14 +2664,23 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } @ForceInline - private static boolean compareWithOp(int cond, $type$ a, $type$ b) { + private static boolean compareWithOp(int cond, $carriertype$ a, $carriertype$ b) { return switch (cond) { +#if[FP16] + case BT_eq -> Float.float16ToFloat(a) == Float.float16ToFloat(b); + case BT_ne -> Float.float16ToFloat(a) != Float.float16ToFloat(b); + case BT_lt -> Float.float16ToFloat(a) < Float.float16ToFloat(b); + case BT_le -> Float.float16ToFloat(a) <= Float.float16ToFloat(b); + case BT_gt -> Float.float16ToFloat(a) > Float.float16ToFloat(b); + case BT_ge -> Float.float16ToFloat(a) >= Float.float16ToFloat(b); +#else[FP16] case BT_eq -> a == b; case BT_ne -> a != b; case BT_lt -> a < b; case BT_le -> a <= b; case BT_gt -> a > b; case BT_ge -> a >= b; +#end[FP16] #if[!FP] case BT_ult -> $Boxtype$.compareUnsigned(a, b) < 0; case BT_ule -> $Boxtype$.compareUnsigned(a, b) <= 0; @@ -2665,7 +2821,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp // and multiply. $abstractvectortype$ iota = s.iota(); $type$ sc = ($type$) scale_; - return v.add(sc == 1 ? iota : iota.mul(sc)); + return v.add(sc == 1 ? iota : iota.mul({#if[FP16]?float16ToRawShortBits(Float16.valueOf(sc)):sc})); }); } @@ -2875,7 +3031,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp return VectorSupport.rearrangeOp( getClass(), shuffletype, null, laneTypeOrdinal(), length(), this, shuffle, null, - (v1, s_, m_) -> v1.uOp((i, a) -> { + (v1, s_, m_) -> v1.{#if[FP16]?uRawOp:uOp}((i, a) -> { int ei = Integer.remainderUnsigned(s_.laneSource(i), v1.length()); return v1.lane(ei); })); @@ -2902,7 +3058,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp return VectorSupport.rearrangeOp( getClass(), shuffletype, masktype, laneTypeOrdinal(), length(), this, shuffle, m, - (v1, s_, m_) -> v1.uOp((i, a) -> { + (v1, s_, m_) -> v1.{#if[FP16]?uRawOp:uOp}((i, a) -> { int ei = Integer.remainderUnsigned(s_.laneSource(i), v1.length()); return !m_.laneIsSet(i) ? 0 : v1.lane(ei); })); @@ -2928,7 +3084,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp VectorSupport.rearrangeOp( getClass(), shuffletype, null, laneTypeOrdinal(), length(), this, shuffle, null, - (v0, s_, m_) -> v0.uOp((i, a) -> { + (v0, s_, m_) -> v0.{#if[FP16]?uRawOp:uOp}((i, a) -> { int ei = Integer.remainderUnsigned(s_.laneSource(i), v0.length()); return v0.lane(ei); })); @@ -2936,7 +3092,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp VectorSupport.rearrangeOp( getClass(), shuffletype, null, laneTypeOrdinal(), length(), v, shuffle, null, - (v1, s_, m_) -> v1.uOp((i, a) -> { + (v1, s_, m_) -> v1.{#if[FP16]?uRawOp:uOp}((i, a) -> { int ei = Integer.remainderUnsigned(s_.laneSource(i), v1.length()); return v1.lane(ei); })); @@ -2963,6 +3119,9 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp final VectorShuffle toShuffle(AbstractSpecies dsp, boolean wrap) { assert(dsp.elementSize() == vspecies().elementSize()); +#if[FP16] + ShortVector idx = convert(VectorOperators.H2S, 0).reinterpretAsShorts(); +#end[FP16] #if[float] IntVector idx = convert(VectorOperators.F2I, 0).reinterpretAsInts(); #end[float] @@ -2983,7 +3142,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * {@inheritDoc} - * @since 19 + * @since {#if[FP16]?27:19} */ @Override public abstract @@ -3002,7 +3161,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * {@inheritDoc} - * @since 19 + * @since {#if[FP16]?27:19} */ @Override public abstract @@ -3199,7 +3358,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp * * This is a lane-wise ternary operation which applies an operation * conforming to the specification of - * {@link Math#fma($type$,$type$,$type$) Math.fma(a,b,c)} + * {@link Math#fma($fallbacktype$,$fallbacktype$,$fallbacktype$) Math.fma(a,b,c)} * to each lane. #if[intOrFloat] * The operation is adapted to cast the operands and the result, @@ -3240,7 +3399,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp * * This is a lane-wise ternary operation which applies an operation * conforming to the specification of - * {@link Math#fma($type$,$type$,$type$) Math.fma(a,b,c)} + * {@link Math#fma($fallbacktype$,$fallbacktype$,$fallbacktype$) Math.fma(a,b,c)} * to each lane. #if[intOrFloat] * The operation is adapted to cast the operands and the result, @@ -3447,13 +3606,13 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp private static ReductionOperation<$abstractvectortype$, VectorMask<$Boxtype$>> reductionOperations(int opc_) { switch (opc_) { case VECTOR_OP_ADD: return (v, m) -> - toBits(v.rOp(($type$)0, m, (i, a, b) -> ($type$)(a + b))); + toBits(v.rOp(($type$)0, m, (i, a, b) -> ($fallbacktype$)(a + b))); case VECTOR_OP_MUL: return (v, m) -> - toBits(v.rOp(($type$)1, m, (i, a, b) -> ($type$)(a * b))); + toBits(v.rOp(($type$){#if[FP16]?floatToFloat16(1.0f):1}, m, (i, a, b) -> ($fallbacktype$)(a * b))); case VECTOR_OP_MIN: return (v, m) -> - toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> ($type$) Math.min(a, b))); + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> ($fallbacktype$) Math.min(a, b))); case VECTOR_OP_MAX: return (v, m) -> - toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> ($type$) Math.max(a, b))); + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> ($fallbacktype$) Math.max(a, b))); #if[!FP] case VECTOR_OP_UMIN: return (v, m) -> toBits(v.rOp(UMAX_VALUE, m, (i, a, b) -> ($type$) VectorMath.minUnsigned(a, b))); @@ -3475,8 +3634,8 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } #if[FP] - private static final $type$ MIN_OR_INF = $Boxtype$.NEGATIVE_INFINITY; - private static final $type$ MAX_OR_INF = $Boxtype$.POSITIVE_INFINITY; + private static final $type$ MIN_OR_INF = {#if[FP16]?float16ToRawShortBits($Boxtype$.NEGATIVE_INFINITY):$Boxtype$.NEGATIVE_INFINITY}; + private static final $type$ MAX_OR_INF = {#if[FP16]?float16ToRawShortBits($Boxtype$.POSITIVE_INFINITY):$Boxtype$.POSITIVE_INFINITY}; #else[FP] private static final $type$ MIN_OR_INF = $Boxtype$.MIN_VALUE; private static final $type$ MAX_OR_INF = $Boxtype$.MAX_VALUE; @@ -3656,14 +3815,18 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] a = toArray(); double[] res = new double[a.length]; for (int i = 0; i < a.length; i++) { - res[i] = (double) a[i]; + res[i] = (double) {#if[FP16]?shortBitsToFloat16(a[i]).doubleValue():a[i]}; } return res; } #end[double] /** +#if[FP16] + * Loads a vector from an array of type {@code $type$[]} holding IEEE 754 binary16 values +#else[FP16] * Loads a vector from an array of type {@code $type$[]} +#end[FP16] * starting at an offset. * For each vector lane, where {@code N} is the vector lane index, the * array element at index {@code offset + N} is placed into the @@ -3687,7 +3850,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } /** +#if[FP16] + * Loads a vector from an array of type {@code $type$[]} holding IEEE 754 binary16 values +#else[FP16] * Loads a vector from an array of type {@code $type$[]} +#end[FP16] * starting at an offset and using a mask. * Lanes where the mask is unset are filled with the default * value of {@code $type$} ({#if[FP]?positive }zero). @@ -3724,7 +3891,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * Gathers a new vector composed of elements from an array of type +#if[FP16] + * {@code $type$[]} holding IEEE 754 binary16 values, +#else[FP16] * {@code $type$[]}, +#end[FP16] * using indexes obtained by adding a fixed {@code offset} to a * series of secondary offsets from an index map. * The index map is a contiguous sequence of {@code VLENGTH} @@ -3869,7 +4040,11 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * Gathers a new vector composed of elements from an array of type +#if[FP16] + * {@code $type$[]} holding IEEE 754 binary16 values, +#else[FP16] * {@code $type$[]}, +#end[FP16] * under the control of a mask, and * using indexes obtained by adding a fixed {@code offset} to a * series of secondary offsets from an index map. @@ -3918,7 +4093,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } } -#if[short] +#if[strictShort] /** * Loads a vector from an array of type {@code char[]} * starting at an offset. @@ -4069,7 +4244,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $Type$Species vsp = ($Type$Species) species; return vsp.vOp(m, n -> (short) a[offset + indexMap[mapOffset + n]]); } -#end[short] +#end[strictShort] #if[byte] /** @@ -4258,7 +4433,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp * for any lane {@code N} in the vector * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. - * @since 19 + * @since {#if[FP16]?27:19} */ @ForceInline public static @@ -4317,7 +4492,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp * where the mask is set * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. - * @since 19 + * @since {#if[FP16]?27:19} */ @ForceInline public static @@ -4555,7 +4730,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } #end[byteOrShort] -#if[short] +#if[strictShort] /** * Stores this vector into an array of type {@code char[]} * starting at an offset. @@ -4711,7 +4886,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp arr[off + j] = (char) e; }); } -#end[short] +#end[strictShort] #if[byte] /** @@ -4886,7 +5061,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * {@inheritDoc} - * @since 19 + * @since {#if[FP16]?27:19} */ @Override @ForceInline @@ -4903,7 +5078,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * {@inheritDoc} - * @since 19 + * @since {#if[FP16]?27:19} */ @Override @ForceInline @@ -5100,7 +5275,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } #end[byteOrShort] -#if[short] +#if[strictShort] /*package-private*/ abstract $abstractvectortype$ fromCharArray0(char[] a, int offset); @@ -5132,7 +5307,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp (arr, off, s, vm) -> s.ldOp(arr, (int) off, vm, (arr_, off_, i) -> (short) arr_[off_ + i])); } -#end[short] +#end[strictShort] #if[byte] /*package-private*/ @@ -5346,7 +5521,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp }); } -#if[short] +#if[strictShort] /*package-private*/ abstract void intoCharArray0(char[] a, int offset, VectorMask<$Boxtype$> m); @@ -5364,7 +5539,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp -> v.stOp(arr, (int) off, vm, (arr_, off_, i, e) -> arr_[off_ + i] = (char) e)); } -#end[short] +#end[strictShort] // End of low-level memory operations. @@ -5423,7 +5598,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp return ARRAY_BASE + (((long)index) << ARRAY_SHIFT); } -#if[short] +#if[strictShort] static final int ARRAY_CHAR_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_CHAR_INDEX_SCALE); static final long ARRAY_CHAR_BASE = @@ -5433,7 +5608,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp static long charArrayAddress(char[] a, int index) { return ARRAY_CHAR_BASE + (((long)index) << ARRAY_CHAR_SHIFT); } -#end[short] +#end[strictShort] #if[byte] static final int ARRAY_BOOLEAN_SHIFT = @@ -5490,7 +5665,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /** * {@inheritDoc} -#if[byteOrShort] +#if[byte] * * @implNote This method always throws * {@code UnsupportedOperationException}, because there is no floating @@ -5498,23 +5673,27 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp * of this method is arbitrarily designated as * {@code Vector}. Future versions of this API may change the return * type if additional floating point types become available. -#end[byteOrShort] +#end[byte] */ @ForceInline @Override public final - {#if[byteOrShort]?Vector:$Fptype$Vector} +#if[FP16] + $Type$Vector +#else[FP16] + {#if[byte]?Vector:$Fptype$Vector} +#end[FP16] viewAsFloatingLanes() { #if[FP] return this; #else[FP] LaneType flt = LaneType.$TYPE$.asFloating(); -#if[!byteOrShort] +#if[!byte] return ($Fptype$Vector) asVectorRaw(flt); -#else[!byteOrShort] +#else[!byte] // asFloating() will throw UnsupportedOperationException for the unsupported type $type$ throw new AssertionError("Cannot reach here"); -#end[!byteOrShort] +#end[!byte] #end[FP] } @@ -5588,7 +5767,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp Class> maskType, Class> shuffleType, Function vectorFactory) { - super(shape, LaneType.of($type$.class), + super(shape, LaneType.of($elemtype$.class), vectorType, maskType, shuffleType, vectorFactory); assert(this.elementSize() == $Boxtype$.SIZE); @@ -5599,7 +5778,7 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp @Override @ForceInline public final Class<$Boxtype$> elementType() { - return $type$.class; + return $elemtype$.class; } @Override @@ -5656,8 +5835,8 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp return value; #else[long] // Do the conversion, and then test it for failure. - $type$ e = ($type$) value; - if ((long) e != value) { + $type$ e = {#if[FP16]?float16ToRawShortBits(Float16.valueOf(value)):($type$) value}; + if ({#if[FP16]?shortBitsToFloat16(e).longValue():(long) e} != value) { throw badElementBits(value, e); } return toBits(e); @@ -5667,10 +5846,18 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp /*package-private*/ @ForceInline static long toIntegralChecked($type$ e, boolean convertToInt) { +#if[FP16] + float ef = shortBitsToFloat16(e).floatValue(); + long value = convertToInt ? (int) ef : (long) ef; + if ((float) value != ef) { + throw badArrayBits(e, convertToInt, value); + } +#else[FP16] long value = convertToInt ? (int) e : (long) e; if (($type$) value != e) { throw badArrayBits(e, convertToInt, value); } +#end[FP16] return value; } @@ -5682,11 +5869,19 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp $type$[] va = new $type$[laneCount()]; for (int i = 0; i < va.length; i++) { int lv = values[i]; +#if[FP16] + $type$ v = float16ToRawShortBits(Float16.valueOf(lv)); + va[i] = v; + if (Float16.valueOf(lv).intValue() != lv) { + throw badElementBits(lv, v); + } +#else[FP16] $type$ v = ($type$) lv; va[i] = v; if ((int)v != lv) { throw badElementBits(lv, v); } +#end[FP16] } return dummyVector().fromArray0(va, 0); } @@ -5859,10 +6054,17 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp } /** +#if[FP16] + * Finds a species for an element type of {@code $elemtype$} and shape. + * + * @param s the shape + * @return a species for an element type of {@code $elemtype$} and shape +#else[FP16] * Finds a species for an element type of {@code $type$} and shape. * * @param s the shape * @return a species for an element type of {@code $type$} and shape +#end[FP16] * @throws IllegalArgumentException if no such species exists for the shape */ static $Type$Species species(VectorShape s) { @@ -5922,6 +6124,6 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp * A preferred species is a species of maximal bit-size for the platform. */ public static final VectorSpecies<$Boxtype$> SPECIES_PREFERRED - = ($Type$Species) VectorSpecies.ofPreferred($type$.class); + = ($Type$Species) VectorSpecies.ofPreferred($elemtype$.class); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template index d66d22cab19..f8ac090a7f7 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template @@ -59,7 +59,7 @@ final class $vectortype$ extends $abstractvectortype$ { static final Class<$Carriertype$> CTYPE = $carriertype$.class; // carrier type used by the JVM - static final Class<$Boxtype$> ETYPE = $type$.class; // used by the JVM + static final Class<$Boxtype$> ETYPE = $elemtype$.class; // used by the JVM $vectortype$($type$[] v) { super(v); @@ -95,7 +95,7 @@ final class $vectortype$ extends $abstractvectortype$ { @ForceInline @Override - public final Class<$Boxtype$> elementType() { return $type$.class; } + public final Class<$Boxtype$> elementType() { return $elemtype$.class; } @ForceInline final Class<$Carriertype$> carrierType() { return CTYPE; } @@ -216,6 +216,20 @@ final class $vectortype$ extends $abstractvectortype$ { super.uOpTemplate(($masktype$)m, f); // specialize } +#if[FP16] + @ForceInline + final @Override + $vectortype$ uRawOp(FUnRawOp f) { + return ($vectortype$) super.uRawOpTemplate(f); // specialize + } + + @ForceInline + final @Override + $vectortype$ uRawOp(VectorMask<$Boxtype$> m, FUnRawOp f) { + return ($vectortype$) + super.uRawOpTemplate(($masktype$)m, f); // specialize + } +#end[FP16] // Binary operator @ForceInline @@ -574,6 +588,24 @@ final class $vectortype$ extends $abstractvectortype$ { case 13: bits = laneHelper(13); break; case 14: bits = laneHelper(14); break; case 15: bits = laneHelper(15); break; +#if[!16L] + case 16: bits = laneHelper(16); break; + case 17: bits = laneHelper(17); break; + case 18: bits = laneHelper(18); break; + case 19: bits = laneHelper(19); break; + case 20: bits = laneHelper(20); break; + case 21: bits = laneHelper(21); break; + case 22: bits = laneHelper(22); break; + case 23: bits = laneHelper(23); break; + case 24: bits = laneHelper(24); break; + case 25: bits = laneHelper(25); break; + case 26: bits = laneHelper(26); break; + case 27: bits = laneHelper(27); break; + case 28: bits = laneHelper(28); break; + case 29: bits = laneHelper(29); break; + case 30: bits = laneHelper(30); break; + case 31: bits = laneHelper(31); break; +#end[!16L] #end[!8L] #end[!4L] #end[!2L] @@ -586,7 +618,7 @@ final class $vectortype$ extends $abstractvectortype$ { } $bitstype$ bits = laneHelper(i); #end[!Max] - return $Type$.$bitstype$BitsTo$Fptype$(bits); + return {#if[FP16]?bits:$Type$.$bitstype$BitsTo$Fptype$(bits)}; } @ForceInline @@ -596,7 +628,7 @@ final class $vectortype$ extends $abstractvectortype$ { this, i, (vec, ix) -> { $type$[] vecarr = vec.vec(); - return (long)$Type$.$type$ToRaw$Bitstype$Bits(vecarr[ix]); + return {#if[FP16]?vecarr[ix]:(long)$Type$.$type$ToRaw$Bitstype$Bits(vecarr[ix])}; }); } @@ -625,6 +657,24 @@ final class $vectortype$ extends $abstractvectortype$ { case 13: return withLaneHelper(13, e); case 14: return withLaneHelper(14, e); case 15: return withLaneHelper(15, e); +#if[!16L] + case 16: return withLaneHelper(16, e); + case 17: return withLaneHelper(17, e); + case 18: return withLaneHelper(18, e); + case 19: return withLaneHelper(19, e); + case 20: return withLaneHelper(20, e); + case 21: return withLaneHelper(21, e); + case 22: return withLaneHelper(22, e); + case 23: return withLaneHelper(23, e); + case 24: return withLaneHelper(24, e); + case 25: return withLaneHelper(25, e); + case 26: return withLaneHelper(26, e); + case 27: return withLaneHelper(27, e); + case 28: return withLaneHelper(28, e); + case 29: return withLaneHelper(29, e); + case 30: return withLaneHelper(30, e); + case 31: return withLaneHelper(31, e); +#end[!16L] #end[!8L] #end[!4L] #end[!2L] @@ -643,10 +693,10 @@ final class $vectortype$ extends $abstractvectortype$ { public $vectortype$ withLaneHelper(int i, $type$ e) { return VectorSupport.insert( VCLASS, LANE_TYPE_ORDINAL, VLENGTH, - this, i, (long)$Type$.$type$ToRaw$Bitstype$Bits(e), + this, i, (long){#if[FP16]?e:$Type$.$type$ToRaw$Bitstype$Bits(e)}, (v, ix, bits) -> { $type$[] res = v.vec().clone(); - res[ix] = $Type$.$bitstype$BitsTo$Type$(($bitstype$)bits); + res[ix] = {#if[FP16]?($bitstype$)bits:$Type$.$bitstype$BitsTo$Type$(($bitstype$)bits)}; return v.vectorFactory(res); }); } @@ -981,7 +1031,7 @@ final class $vectortype$ extends $abstractvectortype$ { public $masktype$ compress() { return ($masktype$)VectorSupport.compressExpandOp(VectorSupport.VECTOR_OP_MASK_COMPRESS, $vectortype$.class, $masktype$.class, LANE_TYPE_ORDINAL, VLENGTH, null, this, - (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, m1.trueCount())); + (v1, m1) -> VSPECIES.iota().compare(VectorOperators.LT, {#if[FP16]?Float16.float16ToRawShortBits(Float16.valueOf(m1.trueCount())):m1.trueCount()})); } @@ -1389,7 +1439,7 @@ final class $vectortype$ extends $abstractvectortype$ { return super.fromArray0Template($masktype$.class, a, offset, indexMap, mapOffset, ($masktype$) m); } -#if[short] +#if[strictShort] @ForceInline @Override final @@ -1403,7 +1453,7 @@ final class $vectortype$ extends $abstractvectortype$ { $abstractvectortype$ fromCharArray0(char[] a, int offset, VectorMask<$Boxtype$> m, int offsetInRange) { return super.fromCharArray0Template($masktype$.class, a, offset, ($masktype$) m, offsetInRange); // specialize } -#end[short] +#end[strictShort] #if[byte] @ForceInline @@ -1474,14 +1524,14 @@ final class $vectortype$ extends $abstractvectortype$ { super.intoMemorySegment0Template($masktype$.class, ms, offset, ($masktype$) m); } -#if[short] +#if[strictShort] @ForceInline @Override final void intoCharArray0(char[] a, int offset, VectorMask<$Boxtype$> m) { super.intoCharArray0Template($masktype$.class, a, offset, ($masktype$) m); } -#end[short] +#end[strictShort] // End of specialized low-level memory operations. diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/gen-src.sh b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/gen-src.sh index a8a7ea83625..7735085a16b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/gen-src.sh +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/gen-src.sh @@ -53,19 +53,29 @@ typeprefix= globalArgs="" #globalArgs="$globalArgs -KextraOverrides" -for type in byte short int long float double +for type in byte short int long float double float16 do Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${type})" + + case $type in + float16) + type=short + TYPE=SHORT + ;; + esac + args=$globalArgs args="$args -K$type -Dtype=$type -DType=$Type -DTYPE=$TYPE" Boxtype=$Type Wideboxtype=$Boxtype + ElemLayout=$Type kind=BITWISE bitstype=$type + maskbitstype=$type Bitstype=$Type Boxbitstype=$Boxtype @@ -74,23 +84,28 @@ do Boxfptype=$Boxtype carriertype=$type Carriertype=$Type + elemtype=$type + fallbacktype=$type - case $type in - byte) + case $Type in + Byte) Wideboxtype=Integer sizeInBytes=1 laneType=LT_BYTE lanebitsType=LT_BYTE - args="$args -KbyteOrShort" + args="$args -KbyteOrShort -KbyteOrStrictShort" ;; - short) + Short) + fptype=Float16 + Fptype=Float16 + Boxfptype=Float16 Wideboxtype=Integer sizeInBytes=2 laneType=LT_SHORT lanebitsType=LT_SHORT - args="$args -KbyteOrShort" + args="$args -KbyteOrShort -KbyteOrStrictShort -KstrictShort" ;; - int) + Int) Boxtype=Integer Carriertype=Integer Wideboxtype=Integer @@ -103,7 +118,7 @@ do lanebitsType=LT_INT args="$args -KintOrLong -KintOrFP -KintOrFloat" ;; - long) + Long) fptype=double Fptype=Double Boxfptype=Double @@ -112,33 +127,53 @@ do lanebitsType=LT_LONG args="$args -KintOrLong -KlongOrDouble" ;; - float) + Float) kind=FP bitstype=int + maskbitstype=int Bitstype=Int Boxbitstype=Integer sizeInBytes=4 laneType=LT_FLOAT lanebitsType=LT_INT - args="$args -KintOrFP -KintOrFloat" + args="$args -KFP32 -KintOrFP -KintOrFloat" ;; - double) + Double) kind=FP bitstype=long + maskbitstype=long Bitstype=Long Boxbitstype=Long sizeInBytes=8 laneType=LT_DOUBLE lanebitsType=LT_LONG - args="$args -KintOrFP -KlongOrDouble" + args="$args -KFP64 -KintOrFP -KlongOrDouble" + ;; + Float16) + kind=FP + bitstype=short + maskbitstype=short + Bitstype=Short + Boxbitstype=Short + sizeInBytes=2 + carriertype=short + Carriertype=Short + Boxtype=Float16 + elemtype=Float16 + ElemLayout=Short + laneType=LT_FLOAT16 + lanebitsType=LT_SHORT + fallbacktype=float + args="$args -KFP16 -KbyteOrShort" ;; esac - args="$args -K$kind -DlaneType=$laneType -DlanebitsType=$lanebitsType -DBoxtype=$Boxtype -DWideboxtype=$Wideboxtype" - args="$args -Dbitstype=$bitstype -DBitstype=$Bitstype -DBoxbitstype=$Boxbitstype" + + args="$args -K$kind -DlaneType=$laneType -DlanebitsType=$lanebitsType -Dfallbacktype=$fallbacktype -DBoxtype=$Boxtype -DWideboxtype=$Wideboxtype" + args="$args -DElemLayout=$ElemLayout -Dbitstype=$bitstype -Dmaskbitstype=$maskbitstype -DBitstype=$Bitstype -DBoxbitstype=$Boxbitstype" args="$args -Dfptype=$fptype -DFptype=$Fptype -DBoxfptype=$Boxfptype" args="$args -DsizeInBytes=$sizeInBytes" - args="$args -Dcarriertype=$carriertype -DCarriertype=$Carriertype" + args="$args -Dcarriertype=$carriertype -Delemtype=$elemtype -DCarriertype=$Carriertype" abstractvectortype=${typeprefix}${Type}Vector abstractbitsvectortype=${typeprefix}Vector${Bitstype} diff --git a/src/jdk.management.agent/share/conf/jmxremote.password.template b/src/jdk.management.agent/share/conf/jmxremote.password.template index c98a0ad253a..0b0607497de 100644 --- a/src/jdk.management.agent/share/conf/jmxremote.password.template +++ b/src/jdk.management.agent/share/conf/jmxremote.password.template @@ -55,8 +55,6 @@ # * com.sun.management.jmxremote.password.toHashes property is set to true in # management.properties file # * the password file is writable -# * the system security policy allows writing into the password file, if a -# security manager is configured # # In order to change the password for a role, replace the hashed password entry # with a new clear text password or a new hashed password. If the new password @@ -110,6 +108,6 @@ # below entries with clear passwords overwritten by their respective # SHA3-512 hash # -# monitorRole trilby APzBTt34rV2l+OMbuvbnOQ4si8UZmfRCVbIY1+fAofV5CkQzXS/FDMGteQQk/R3q1wtt104qImzJEA7gCwl6dw== 4EeTdSJ7X6Imu0Mb+dWqIns7a7QPIBoM3NB/XlpMQSPSicE7PnlALVWn2pBY3Q3pGDHyAb32Hd8GUToQbUhAjA== SHA3-512 +# monitorRole APzBTt34rV2l+OMbuvbnOQ4si8UZmfRCVbIY1+fAofV5CkQzXS/FDMGteQQk/R3q1wtt104qImzJEA7gCwl6dw== 4EeTdSJ7X6Imu0Mb+dWqIns7a7QPIBoM3NB/XlpMQSPSicE7PnlALVWn2pBY3Q3pGDHyAb32Hd8GUToQbUhAjA== SHA3-512 # controlRole roHEJSbRqSSTII4Z4+NOCV2OJaZVQ/dw153Fy2u4ILDP9XiZ426GwzCzc3RtpoqNMwqYIcfdd74xWXSMrWtGaA== w9qDsekgKn0WOVJycDyU0kLBa081zbStcCjUAVEqlfon5Sgx7XHtaodbmzpLegA1jT7Ag36T0zHaEWRHJe2fdA== SHA3-512 -# \ No newline at end of file +# diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java index a40c9eab12f..3dff0172143 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,18 +25,50 @@ package compiler.c2.irTests; import jdk.test.lib.Asserts; +import compiler.lib.generators.*; import compiler.lib.ir_framework.*; /* * @test - * @bug 8276673 8280089 + * @bug 8276673 8280089 8349563 * @summary Test abs nodes optimization in C2. - * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" + * @key randomness * @library /test/lib / * @run driver compiler.c2.irTests.TestIRAbs */ public class TestIRAbs { + private static final RestrictableGenerator INTS = Generators.G.ints(); + private static final RestrictableGenerator LONGS = Generators.G.longs(); + + private static final IntRange INT_RANGE = IntRange.generate(INTS); + private static final IntRange INT_FULL_RANGE = new IntRange(Integer.MIN_VALUE, Integer.MAX_VALUE); + private static final IntRange INT_UNSIGNED_MAX = new IntRange(-1, Integer.MAX_VALUE); + private static final IntRange INT_POSITIVE = new IntRange(0, Integer.MAX_VALUE); + private static final IntRange INT_NEGATIVE = new IntRange(Integer.MIN_VALUE, 0); + private static final LongRange LONG_RANGE = LongRange.generate(LONGS); + private static final LongRange LONG_FULL_RANGE = new LongRange(Long.MIN_VALUE, Long.MAX_VALUE); + private static final LongRange LONG_UNSIGNED_MAX = new LongRange(-1, Long.MAX_VALUE); + private static final LongRange LONG_POSITIVE = new LongRange(0, Long.MAX_VALUE); + private static final LongRange LONG_NEGATIVE = new LongRange(Long.MIN_VALUE, 0); + + private static final int INT_1 = INTS.next(); + private static final int INT_2 = INTS.next(); + private static final int INT_3 = INTS.next(); + private static final int INT_4 = INTS.next(); + private static final int INT_5 = INTS.next(); + private static final int INT_6 = INTS.next(); + private static final int INT_7 = INTS.next(); + private static final int INT_8 = INTS.next(); + + private static final long LONG_1 = LONGS.next(); + private static final long LONG_2 = LONGS.next(); + private static final long LONG_3 = LONGS.next(); + private static final long LONG_4 = LONGS.next(); + private static final long LONG_5 = LONGS.next(); + private static final long LONG_6 = LONGS.next(); + private static final long LONG_7 = LONGS.next(); + private static final long LONG_8 = LONGS.next(); public static char [] cspecial = { 0, 42, 128, 256, 1024, 4096, 65535 @@ -103,7 +136,7 @@ public class TestIRAbs { } @Test - @IR(failOn = {IRNode.ABS_I, IRNode.ABS_L, IRNode.ABS_F, IRNode.ABS_D}) + @IR(failOn = {IRNode.ABS_I, IRNode.ABS_L, IRNode.ABS_F, IRNode.ABS_D}, applyIfPlatform = { "64-bit", "true" }) public void testAbsConstant() { // Test abs(constant) optimization for int Asserts.assertEquals(Integer.MAX_VALUE, Math.abs(Integer.MAX_VALUE)); @@ -160,14 +193,14 @@ public class TestIRAbs { } @Test - @IR(counts = {IRNode.ABS_L, "1"}) + @IR(counts = {IRNode.ABS_L, "1"}, applyIfPlatform = { "64-bit", "true" }) public long testLong0(long x) { return Math.abs(Math.abs(x)); // transformed to Math.abs(x) } @Test - @IR(failOn = {IRNode.SUB_L}) - @IR(counts = {IRNode.ABS_L, "1"}) + @IR(failOn = {IRNode.SUB_L}, applyIfPlatform = { "64-bit", "true" }) + @IR(counts = {IRNode.ABS_L, "1"}, applyIfPlatform = { "64-bit", "true" }) public long testLong1(long x) { return Math.abs(0 - x); // transformed to Math.abs(x) } @@ -229,4 +262,524 @@ public class TestIRAbs { Asserts.assertEquals(cspecial[i], (char) Math.abs(cspecial[i])); } } - } + + @Run(test = {"testIntRange1", "testIntRange2", "testIntRange3", "testIntRange4", + "testIntRangeFolding", "testIntFullRangeFolding", "testIntUnsignedMaxFolding", + "testIntPositiveRangeFolding", "testIntNegativeRangeFolding"}) + public void checkIntRanges(RunInfo info) { + for (int i : ispecial) { + checkIntRange(i); + } + + for (int j = 0; j < 20; j++) { + int i = INTS.next(); + checkIntRange(i); + } + } + + @DontCompile + public void checkIntRange(int i) { + Asserts.assertEquals(Math.abs((i & 7) - 4) > 4, testIntRange1(i)); + Asserts.assertEquals(Math.abs((i & 7) - 4) < 0, testIntRange2(i)); + Asserts.assertEquals(Math.abs(-((i & 7) + 2)) < 2, testIntRange3(i)); + Asserts.assertEquals(Math.abs(-((i & 7) + 2)) > 9, testIntRange4(i)); + Asserts.assertEquals(testIntRangeFoldingInterpreter(i), testIntRangeFolding(i)); + Asserts.assertEquals(testIntFullRangeFoldingInterpreter(i), testIntFullRangeFolding(i)); + Asserts.assertEquals(testIntUnsignedMaxFoldingInterpreter(i), testIntUnsignedMaxFolding(i)); + Asserts.assertEquals(testIntPositiveRangeFoldingInterpreter(i), testIntPositiveRangeFolding(i)); + Asserts.assertEquals(testIntNegativeRangeFoldingInterpreter(i), testIntNegativeRangeFolding(i)); + } + + @Run(test = {"testLongRange1", "testLongRange2", "testLongRange3", "testLongRange4", + "testLongRangeFolding", "testLongFullRangeFolding", "testLongUnsignedMaxFolding", + "testLongPositiveRangeFolding", "testLongNegativeRangeFolding"}) + public void checkLongRanges(RunInfo info) { + for (long l : lspecial) { + checkLongRange(l); + } + + for (int j = 0; j < 20; j++) { + long l = LONGS.next(); + checkLongRange(l); + } + } + + @DontCompile + public void checkLongRange(long l) { + Asserts.assertEquals(Math.abs((l & 7) - 4) > 4, testLongRange1(l)); + Asserts.assertEquals(Math.abs((l & 7) - 4) < 0, testLongRange2(l)); + Asserts.assertEquals(Math.abs(-((l & 7) + 2)) < 2, testLongRange3(l)); + Asserts.assertEquals(Math.abs(-((l & 7) + 2)) > 9, testLongRange4(l)); + Asserts.assertEquals(testLongRangeFoldingInterpreter(l), testLongRangeFolding(l)); + Asserts.assertEquals(testLongFullRangeFoldingInterpreter(l), testLongFullRangeFolding(l)); + Asserts.assertEquals(testLongUnsignedMaxFoldingInterpreter(l), testLongUnsignedMaxFolding(l)); + Asserts.assertEquals(testLongPositiveRangeFoldingInterpreter(l), testLongPositiveRangeFolding(l)); + Asserts.assertEquals(testLongNegativeRangeFoldingInterpreter(l), testLongNegativeRangeFolding(l)); + } + + // Int ranges + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange1(int in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) > 4; + } + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange2(int in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) < 0; + } + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange3(int in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) < 2; + } + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange4(int in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) > 9; + } + + @Test + public int testIntRangeFolding(int in) { + int c = INT_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntRangeFoldingInterpreter(int in) { + int c = INT_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntFullRangeFolding(int in) { + int c = INT_FULL_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntFullRangeFoldingInterpreter(int in) { + int c = INT_FULL_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntUnsignedMaxFolding(int in) { + int c = INT_UNSIGNED_MAX.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntUnsignedMaxFoldingInterpreter(int in) { + int c = INT_UNSIGNED_MAX.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntPositiveRangeFolding(int in) { + int c = INT_POSITIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntPositiveRangeFoldingInterpreter(int in) { + int c = INT_POSITIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntNegativeRangeFolding(int in) { + int c = INT_NEGATIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntNegativeRangeFoldingInterpreter(int in) { + int c = INT_NEGATIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + // Long ranges + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange1(long in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) > 4; + } + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange2(long in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) < 0; + } + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange3(long in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) < 2; + } + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange4(long in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) > 9; + } + + @Test + public int testLongRangeFolding(long in) { + long c = LONG_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongRangeFoldingInterpreter(long in) { + long c = LONG_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongFullRangeFolding(long in) { + long c = LONG_FULL_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongFullRangeFoldingInterpreter(long in) { + long c = LONG_FULL_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongUnsignedMaxFolding(long in) { + long c = LONG_UNSIGNED_MAX.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongUnsignedMaxFoldingInterpreter(long in) { + long c = LONG_UNSIGNED_MAX.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongPositiveRangeFolding(long in) { + long c = LONG_POSITIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongPositiveRangeFoldingInterpreter(long in) { + long c = LONG_POSITIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongNegativeRangeFolding(long in) { + long c = LONG_NEGATIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongNegativeRangeFoldingInterpreter(long in) { + long c = LONG_NEGATIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + record IntRange(int lo, int hi) { + IntRange { + if (lo > hi) { + throw new IllegalArgumentException("lo > hi"); + } + } + + int clamp(int v) { + return Math.min(hi, Math.max(v, lo)); + } + + static IntRange generate(Generator g) { + var a = g.next(); + var b = g.next(); + if (a > b) { + var tmp = a; + a = b; + b = tmp; + } + return new IntRange(a, b); + } + } + + record LongRange(long lo, long hi) { + LongRange { + if (lo > hi) { + throw new IllegalArgumentException("lo > hi"); + } + } + + long clamp(long v) { + return Math.min(hi, Math.max(v, lo)); + } + + static LongRange generate(Generator g) { + var a = g.next(); + var b = g.next(); + if (a > b) { + var tmp = a; + a = b; + b = tmp; + } + return new LongRange(a, b); + } + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestCastIIToConvHF2FNoSp.java b/test/hotspot/jtreg/compiler/vectorapi/TestCastIIToConvHF2FNoSp.java new file mode 100644 index 00000000000..0c8aa58f586 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestCastIIToConvHF2FNoSp.java @@ -0,0 +1,113 @@ +/* + * Copyright 2025 Arm Limited and/or its affiliates. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** +* @test +* @bug 8370691 8373574 +* @summary Verify correct execution of CastII -> ConvHF2F IR sequence on AArch64 +* @modules jdk.incubator.vector +* @library /test/lib / +* @compile TestCastIIToConvHF2FNoSp.java +* @run driver/timeout=480 compiler.vectorapi.TestCastIIToConvHF2FNoSp +*/ + +package compiler.vectorapi; +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.*; +import static jdk.incubator.vector.Float16.*; +import static java.lang.Float.*; +import java.util.Arrays; +import jdk.test.lib.*; +import compiler.lib.generators.Generator; +import static compiler.lib.generators.Generators.G; + +public class TestCastIIToConvHF2FNoSp { + short[] input1; + short[] output; + static final int LEN = 527; + + static final Float16 FP16_CONST = Float16.valueOf(1023.0f); + static final VectorSpecies SPECIES = Float16Vector.SPECIES_PREFERRED; + + public static void main(String args[]) { + // Test with default MaxVectorSize + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + + // Test with different values of MaxVectorSize + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=8"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=16"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=32"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=64"); + } + + static void assertResults(int arity, short ... values) { + assert values.length == (arity + 2); + Float16 expected_fp16 = shortBitsToFloat16(values[arity]); + Float16 actual_fp16 = shortBitsToFloat16(values[arity + 1]); + if(!expected_fp16.equals(actual_fp16)) { + String inputs = Arrays.toString(Arrays.copyOfRange(values, 0, arity - 1)); + throw new AssertionError("Result Mismatch!, input = " + inputs + " actual = " + actual_fp16 + " expected = " + expected_fp16); + } + } + + public TestCastIIToConvHF2FNoSp() { + input1 = new short[LEN]; + output = new short[LEN]; + + Generator gen = G.float16s(); + for (int i = 0; i < LEN; ++i) { + input1[i] = gen.next(); + } + } + + @Test + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeature = {"sve", "true"}) + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true", "sve", "false"}) + void vectorMinConstantInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.MIN, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.MIN, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMinConstantInputFloat16") + void checkResultMinConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.min(FP16_CONST.floatValue(), float16ToFloat(input1[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input1[i], expected, output[i]); + } + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestFloat16VectorOperations.java b/test/hotspot/jtreg/compiler/vectorapi/TestFloat16VectorOperations.java new file mode 100644 index 00000000000..30d066d1b15 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestFloat16VectorOperations.java @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** +* @test +* @bug 8370691 +* @summary Test intrinsification of Float16Vector operations +* @modules jdk.incubator.vector +* @library /test/lib / +* @compile TestFloat16VectorOperations.java +* @run driver/timeout=480 compiler.vectorapi.TestFloat16VectorOperations +*/ + +package compiler.vectorapi; +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.*; +import static jdk.incubator.vector.Float16.*; +import static java.lang.Float.*; +import java.util.Arrays; +import jdk.test.lib.*; +import compiler.lib.generators.Generator; +import static compiler.lib.generators.Generators.G; + +public class TestFloat16VectorOperations { + short[] input1; + short[] input2; + short[] input3; + short[] output; + static final int LEN = 527; + static short FP16_SCALAR = (short)0x7777; + + static final Float16 FP16_CONST = Float16.valueOf(1023.0f); + static final VectorSpecies SPECIES = Float16Vector.SPECIES_PREFERRED; + + public static void main(String args[]) { + // Test with default MaxVectorSize + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + + // Test with different values of MaxVectorSize + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=8"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=16"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=32"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=64"); + } + + static void assertResults(int arity, short ... values) { + assert values.length == (arity + 2); + Float16 expected_fp16 = shortBitsToFloat16(values[arity]); + Float16 actual_fp16 = shortBitsToFloat16(values[arity + 1]); + if(!expected_fp16.equals(actual_fp16)) { + String inputs = Arrays.toString(Arrays.copyOfRange(values, 0, arity - 1)); + throw new AssertionError("Result Mismatch!, input = " + inputs + " actual = " + actual_fp16 + " expected = " + expected_fp16); + } + } + + public TestFloat16VectorOperations() { + input1 = new short[LEN]; + input2 = new short[LEN]; + input3 = new short[LEN]; + output = new short[LEN]; + + Generator gen = G.float16s(); + for (int i = 0; i < LEN; ++i) { + input1[i] = gen.next(); + input2[i] = gen.next(); + input3[i] = gen.next(); + } + } + + @Test + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorAddFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.ADD, + Float16Vector.fromArray(SPECIES, input2, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.ADD, + Float16Vector.fromArray(SPECIES, input2, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorAddFloat16") + void checkResultAdd() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) + float16ToFloat(input2[i])); + assertResults(2, input1[i], input2[i], expected, output[i]); + } + } + + + @Test + @IR(counts = {IRNode.SUB_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.SUB_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorSubFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.SUB, + Float16Vector.fromArray(SPECIES, input2, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.SUB, + Float16Vector.fromArray(SPECIES, input2, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorSubFloat16") + void checkResultSub() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) - float16ToFloat(input2[i])); + assertResults(2, input1[i], input2[i], expected, output[i]); + } + } + + + @Test + @IR(counts = {IRNode.MUL_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.MUL_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorMulFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.MUL, + Float16Vector.fromArray(SPECIES, input2, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.MUL, + Float16Vector.fromArray(SPECIES, input2, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMulFloat16") + void checkResultMul() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) * float16ToFloat(input2[i])); + assertResults(2, input1[i], input2[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.DIV_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.DIV_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorDivFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.DIV, + Float16Vector.fromArray(SPECIES, input2, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.DIV, + Float16Vector.fromArray(SPECIES, input2, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorDivFloat16") + void checkResultDiv() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) / float16ToFloat(input2[i])); + assertResults(2, input1[i], input2[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorMinFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.MIN, + Float16Vector.fromArray(SPECIES, input2, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.MIN, + Float16Vector.fromArray(SPECIES, input2, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMinFloat16") + void checkResultMin() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.min(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); + assertResults(2, input1[i], input2[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.MAX_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.MAX_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorMaxFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.MAX, + Float16Vector.fromArray(SPECIES, input2, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.MAX, + Float16Vector.fromArray(SPECIES, input2, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMaxFloat16") + void checkResultMax() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.max(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); + assertResults(2, input1[i], input2[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.SQRT_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.SQRT_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorSqrtFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.SQRT) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.SQRT) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorSqrtFloat16") + void checkResultSqrt() { + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(sqrt(shortBitsToFloat16(input1[i]))); + assertResults(1, input1[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorFmaFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(SPECIES, input2, i), + Float16Vector.fromArray(SPECIES, input3, i)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(SPECIES, input2, i, mask), + Float16Vector.fromArray(SPECIES, input3, i, mask)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorFmaFloat16") + void checkResultFma() { + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), + shortBitsToFloat16(input3[i]))); + assertResults(3, input1[i], input2[i], input3[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorFmaFloat16ScalarMixedConstants() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.FMA, + FP16_SCALAR, + floatToFloat16(3.0f)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.FMA, + FP16_SCALAR, + floatToFloat16(3.0f)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorFmaFloat16ScalarMixedConstants") + void checkResultFmaScalarMixedConstants() { + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(FP16_SCALAR), + shortBitsToFloat16(floatToFloat16(3.0f)))); + assertResults(2, input1[i], FP16_SCALAR, expected, output[i]); + } + } + + + @Test + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorFmaFloat16MixedConstants() { + short input3 = floatToFloat16(3.0f); + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(SPECIES, input2, i), + input3) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(SPECIES, input2, i, mask), + input3) + .intoArray(output, i, mask); + } + } + + + @Check(test="vectorFmaFloat16MixedConstants") + void checkResultFmaMixedConstants() { + short input3 = floatToFloat16(3.0f); + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3))); + assertResults(3, input1[i], input2[i], input3, expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.FMA_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorFmaFloat16AllConstants() { + short input1 = floatToFloat16(1.0f); + short input2 = floatToFloat16(2.0f); + short input3 = floatToFloat16(3.0f); + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, input1) + .lanewise(VectorOperators.FMA, + input2, + input3) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.broadcast(SPECIES, input1) + .lanewise(VectorOperators.FMA, + input2, + input3) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorFmaFloat16AllConstants") + void checkResultFmaAllConstants() { + short input1 = floatToFloat16(1.0f); + short input2 = floatToFloat16(2.0f); + short input3 = floatToFloat16(3.0f); + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1), shortBitsToFloat16(input2), shortBitsToFloat16(input3))); + assertResults(3, input1, input2, input3, expected, output[i]); + } + } + + + @Test + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorAddConstInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.ADD, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.ADD, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorAddConstInputFloat16") + void checkResultAddConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) + FP16_CONST.floatValue()); + assertResults(2, input1[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.SUB_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "sve", "true"}) + @IR(counts = {IRNode.SUB_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorSubConstInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input1, i) + .lanewise(VectorOperators.SUB, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input1, i, mask) + .lanewise(VectorOperators.SUB, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorSubConstInputFloat16") + void checkResultSubConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) - FP16_CONST.floatValue()); + assertResults(2, input1[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.MUL_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "sve", "true"}) + @IR(counts = {IRNode.MUL_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorMulConstantInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input2, i) + .lanewise(VectorOperators.MUL, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input2, i, mask) + .lanewise(VectorOperators.MUL, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMulConstantInputFloat16") + void checkResultMulConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(FP16_CONST.floatValue() * float16ToFloat(input2[i])); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.DIV_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "sve", "true"}) + @IR(counts = {IRNode.DIV_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorDivConstantInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input2, i) + .lanewise(VectorOperators.DIV, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input2, i, mask) + .lanewise(VectorOperators.DIV, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorDivConstantInputFloat16") + void checkResultDivConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input2[i]) / FP16_CONST.floatValue()); + assertResults(2, input2[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.MAX_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "sve", "true"}) + @IR(counts = {IRNode.MAX_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorMaxConstantInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input2, i) + .lanewise(VectorOperators.MAX, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input2, i, mask) + .lanewise(VectorOperators.MAX, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMaxConstantInputFloat16") + void checkResultMaxConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.max(FP16_CONST.floatValue(), float16ToFloat(input2[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "sve", "true"}) + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + void vectorMinConstantInputFloat16() { + int i = 0; + for (; i < SPECIES.loopBound(LEN); i += SPECIES.length()) { + Float16Vector.fromArray(SPECIES, input2, i) + .lanewise(VectorOperators.MIN, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i); + } + if (i < LEN) { + VectorMask mask = SPECIES.indexInRange(i, LEN); + Float16Vector.fromArray(SPECIES, input2, i, mask) + .lanewise(VectorOperators.MIN, + float16ToRawShortBits(FP16_CONST)) + .intoArray(output, i, mask); + } + } + + @Check(test="vectorMinConstantInputFloat16") + void checkResultMinConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.min(FP16_CONST.floatValue(), float16ToFloat(input2[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } +} diff --git a/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java b/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java index 9e3ae8de832..f58a287a895 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java +++ b/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ public class PreviewVersion { pb = ProcessTools.createLimitedTestJavaProcessBuilder("--enable-preview", "-Xlog:class+preview", "-cp", "." + File.pathSeparator + System.getProperty("test.classes"), "PVTest"); oa = new OutputAnalyzer(pb.start()); - oa.shouldContain("[info][class,preview] Loading class PVTest that depends on preview features"); + oa.shouldMatch("\\[info *\\]\\[class,preview *\\] Loading class PVTest that depends on preview features"); oa.shouldHaveExitValue(0); // Subtract 1 from class's major version. The class should fail to load diff --git a/test/hotspot/jtreg/runtime/NMT/MallocLimitTest.java b/test/hotspot/jtreg/runtime/NMT/MallocLimitTest.java index 8b711304a99..14832e833e1 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocLimitTest.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocLimitTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022 SAP SE. All rights reserved. - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,7 +106,7 @@ public class MallocLimitTest { ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=1m"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); - output.shouldContain("[nmt] MallocLimit: total limit: 1024K (fatal)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: total limit: 1024K \\(fatal\\)"); output.shouldMatch("# fatal error: MallocLimit: reached global limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1024K\\)"); } @@ -114,8 +114,8 @@ public class MallocLimitTest { ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=1m:oom"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); - output.shouldContain("[nmt] MallocLimit: total limit: 1024K (oom)"); - output.shouldMatch(".*\\[warning\\]\\[nmt\\] MallocLimit: reached global limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1024K\\)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: total limit: 1024K \\(oom\\)"); + output.shouldMatch("\\[warning\\]\\[nmt *\\] MallocLimit: reached global limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1024K\\)"); // The rest is fuzzy. We may get SIGSEGV or a native OOM message, depending on how the failing allocation was handled. } @@ -123,7 +123,7 @@ public class MallocLimitTest { ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=compiler:1234k", "-Xcomp"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); - output.shouldContain("[nmt] MallocLimit: category \"mtCompiler\" limit: 1234K (fatal)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: category \"mtCompiler\" limit: 1234K \\(fatal\\)"); output.shouldMatch("# fatal error: MallocLimit: reached category \"mtCompiler\" limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1234K\\)"); } @@ -131,8 +131,8 @@ public class MallocLimitTest { ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=compiler:1234k:oom", "-Xcomp"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); - output.shouldContain("[nmt] MallocLimit: category \"mtCompiler\" limit: 1234K (oom)"); - output.shouldMatch(".*\\[warning\\]\\[nmt\\] MallocLimit: reached category \"mtCompiler\" limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1234K\\)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: category \"mtCompiler\" limit: 1234K \\(oom\\)"); + output.shouldMatch("\\[warning\\]\\[nmt *\\] MallocLimit: reached category \"mtCompiler\" limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1234K\\)"); // The rest is fuzzy. We may get SIGSEGV or a native OOM message, depending on how the failing allocation was handled. } @@ -140,9 +140,9 @@ public class MallocLimitTest { ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=other:2g,compiler:1g:oom,internal:1k"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); - output.shouldContain("[nmt] MallocLimit: category \"mtCompiler\" limit: 1024M (oom)"); - output.shouldContain("[nmt] MallocLimit: category \"mtInternal\" limit: 1024B (fatal)"); - output.shouldContain("[nmt] MallocLimit: category \"mtOther\" limit: 2048M (fatal)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: category \"mtCompiler\" limit: 1024M \\(oom\\)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: category \"mtInternal\" limit: 1024B \\(fatal\\)"); + output.shouldMatch("\\[nmt *\\] MallocLimit: category \"mtOther\" limit: 2048M \\(fatal\\)"); output.shouldMatch("# fatal error: MallocLimit: reached category \"mtInternal\" limit \\(triggering allocation size: \\d+[BKM], allocated so far: \\d+[BKM], limit: 1024B\\)"); } diff --git a/test/hotspot/jtreg/runtime/StackGuardPages/TestStackGuardPagesNative.java b/test/hotspot/jtreg/runtime/StackGuardPages/TestStackGuardPagesNative.java index d3a132f4b62..7d3aae549e1 100644 --- a/test/hotspot/jtreg/runtime/StackGuardPages/TestStackGuardPagesNative.java +++ b/test/hotspot/jtreg/runtime/StackGuardPages/TestStackGuardPagesNative.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @modules java.base/jdk.internal.misc * @library /test/lib * @requires os.family == "linux" + * @requires !jdk.static * @compile DoOverflow.java * @run main/native TestStackGuardPagesNative */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaProxyClasslist.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaProxyClasslist.java index adafa0d9c69..db431b180eb 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaProxyClasslist.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaProxyClasslist.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ public class LambdaProxyClasslist { out = TestCommon.dump(appJar, TestCommon.list("LambHello", "@lambda-proxy LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()Z")); - out.shouldContain("[warning][cds] No invoke dynamic constant pool entry can be found for class LambHello. The classlist is probably out-of-date.") + out.shouldMatch("\\[warning\\]\\[cds *\\] No invoke dynamic constant pool entry can be found for class LambHello\\. The classlist is probably out-of-date\\.") .shouldHaveExitValue(0); // 4. More blank spaces in between items should be fine. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java index d7ce22e3cf1..796437c0474 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,7 @@ public class LambdaWithOldClass { .setUseVersion(false) .addSuffix(mainClass); OutputAnalyzer output = CDSTestUtils.runWithArchive(runOpts); - output.shouldContain("[class,load] LambdaWithOldClassApp source: shared objects file") + output.shouldMatch("\\[class,load *\\] LambdaWithOldClassApp source: shared objects file") .shouldHaveExitValue(0); if (!CDSTestUtils.isAOTClassLinkingEnabled()) { // With AOTClassLinking, we don't archive any lambda with old classes in the method diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java b/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java index ea69d2db3cd..be5175e6d6a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public class ProhibitedPackage { TestCommon.list("java/lang/Prohibited", "ProhibitedHelper"), "-Xlog:class+load") .shouldContain("Dumping") - .shouldNotContain("[info][class,load] java.lang.Prohibited source: ") + .shouldNotMatch("\\[info *\\]\\[class,load *\\] java.lang.Prohibited source: ") .shouldHaveExitValue(0); // Try loading the class in a prohibited package with various -Xshare diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java index 4cc6ef81c45..864ce88cd11 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ public class AOTLoggingTag { "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "train"); - out.shouldContain("[aot] Writing binary AOTConfiguration file:"); + out.shouldMatch("\\[aot *\\] Writing binary AOTConfiguration file:"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -70,7 +70,7 @@ public class AOTLoggingTag { "-Xlog:aot", "-cp", appJar); out = CDSTestUtils.executeAndLog(pb, "asm"); - out.shouldContain("[aot] Opened AOT configuration file hello.aotconfig"); + out.shouldMatch("\\[aot *\\] Opened AOT configuration file hello\\.aotconfig"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -80,7 +80,7 @@ public class AOTLoggingTag { "-Xlog:aot", "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldContain("[aot] Opened AOT cache hello.aot"); + out.shouldMatch("\\[aot *\\] Opened AOT cache hello\\.aot"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -90,7 +90,7 @@ public class AOTLoggingTag { "-XX:AOTMode=on", "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldContain("[aot] An error has occurred while processing the AOT cache. Run with -Xlog:aot for details."); + out.shouldMatch("\\[aot *\\] An error has occurred while processing the AOT cache\\. Run with -Xlog:aot for details\\."); out.shouldNotHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java index f7e15f8fae0..694e653676e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java @@ -67,7 +67,7 @@ public class AddOpens { {{"-Xlog:cds", "-Xlog:cds"}, {"--add-opens", addOpensArg}}; private static String expectedOutput[] = - { "[class,load] com.simple.Main source: shared objects file", + { "\\[class,load *\\] com\\.simple\\.Main source: shared objects file", "method.setAccessible succeeded!"}; public static void buildTestModule() throws Exception { @@ -103,7 +103,7 @@ public class AddOpens { out.shouldContain("Full module graph = enabled"); }) .setProductionChecker((OutputAnalyzer out) -> { - out.shouldContain(expectedOutput[0]); + out.shouldMatch(expectedOutput[0]); out.shouldContain(expectedOutput[1]); }) .runStaticWorkflow() @@ -154,7 +154,7 @@ public class AddOpens { @Override public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { if (runMode == RunMode.PRODUCTION) { - out.shouldContain(expectedOutput[0]); + out.shouldMatch(expectedOutput[0]); out.shouldContain(expectedOutput[1]); } else if (runMode == RunMode.ASSEMBLY) { out.shouldMatch("(full module graph: enabled)|(Full module graph = enabled)"); @@ -197,7 +197,7 @@ public class AddOpens { @Override public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { if (runMode == RunMode.PRODUCTION) { - out.shouldContain(expectedOutput[0]); + out.shouldMatch(expectedOutput[0]); out.shouldContain(expectedOutput[1]); } else if (runMode == RunMode.ASSEMBLY) { out.shouldMatch("(full module graph: enabled)|(Full module graph = enabled)"); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/OldClassAndInf.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/OldClassAndInf.java index ea5acef8551..eb7f1dbf11f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/OldClassAndInf.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/OldClassAndInf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,7 +92,7 @@ public class OldClassAndInf { TestCommon.checkExec(output); for (String loadee : loadees) { - output.shouldContain("[class,load] " + loadee + " source: shared objects file"); + output.shouldMatch("\\[class,load *\\] " + loadee + " source: shared objects file"); } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchivedSuperIf.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchivedSuperIf.java index b46b48efb62..28d8043cde0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchivedSuperIf.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchivedSuperIf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ public class ArchivedSuperIf extends DynamicArchiveTestBase { .assertNormalExit(output -> { // The interface Bar will be loaded from the archive. // The class (Baz) which implements Bar will be loaded from jar. - output.shouldContain("[class,load] pkg.Bar source: shared objects file (top)") + output.shouldMatch("\\[class,load *\\] pkg\\.Bar source: shared objects file \\(top\\)") .shouldMatch(".class.load. pkg.Baz source:.*archived_super_if.jar") .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JFRDynamicCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JFRDynamicCDS.java index 7abfd11b914..c6c30c164a1 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JFRDynamicCDS.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JFRDynamicCDS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ public class JFRDynamicCDS extends DynamicArchiveTestBase { .assertNormalExit(output -> { output.shouldHaveExitValue(0) .shouldMatch(".class.load. jdk.jfr.events.*source:.*jrt:/jdk.jfr") - .shouldContain("[class,load] JFRDynamicCDSApp source: shared objects file (top)"); + .shouldMatch("\\[class,load *\\] JFRDynamicCDSApp source: shared objects file \\(top\\)"); }); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaContainsOldInf.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaContainsOldInf.java index 9845fd9549b..5ff65f85493 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaContainsOldInf.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaContainsOldInf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,7 +76,7 @@ public class LambdaContainsOldInf extends DynamicArchiveTestBase { "-Xlog:class+load=debug", "-cp", appJar, mainClass, mainArg) .assertNormalExit(output -> { - output.shouldContain("[class,load] LambdaContainsOldInfApp source: shared objects file (top)") + output.shouldMatch("\\[class,load *\\] LambdaContainsOldInfApp source: shared objects file \\(top\\)") .shouldMatch(".class.load. OldProvider.source:.*lambda_contains_old_inf.jar") .shouldMatch(".class.load. LambdaContainsOldInfApp[$][$]Lambda.*/0x.*source:.*LambdaContainsOldInf") .shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java index a43888c81cd..8f001209892 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java @@ -117,7 +117,7 @@ public class MainModuleOnly extends DynamicArchiveTestBase { "--module-path", moduleDir.toString(), "-m", TEST_MODULE1) .assertNormalExit(output -> { - output.shouldContain("[class,load] com.simple.Main source: shared objects file") + output.shouldMatch("\\[class,load *\\] com\\.simple\\.Main source: shared objects file") .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/classpathtests/BootAppendTests.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/classpathtests/BootAppendTests.java index a77c38c21b9..8bb84424676 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/classpathtests/BootAppendTests.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/classpathtests/BootAppendTests.java @@ -205,7 +205,7 @@ public class BootAppendTests { "Test #6", BOOT_APPEND_CLASS, "true", "BOOT"); TestCommon.checkExec(output); if (!TestCommon.isUnableToMap(output)) - output.shouldContain("[class,load] sun.nio.cs.ext1.MyClass source: shared objects file"); + output.shouldMatch("\\[class,load *\\] sun\\.nio\\.cs\\.ext1\\.MyClass source: shared objects file"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/AddModules.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/AddModules.java index bd569732ed5..9c2039e538b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/AddModules.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/AddModules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,8 +118,8 @@ public class AddModules { moduleDir.toString(), // --module-path MAIN_MODULE1) // -m .assertNormalExit(out -> { - out.shouldContain("[class,load] com.greetings.Main source: shared objects file") - .shouldContain("[class,load] org.astro.World source: shared objects file"); + out.shouldMatch("\\[class,load *\\] com\\.greetings\\.Main source: shared objects file") + .shouldMatch("\\[class,load *\\] org\\.astro\\.World source: shared objects file"); }); // run the com.hello module with the archive with the --module-path @@ -130,8 +130,8 @@ public class AddModules { moduleDir.toString(), // --module-path MAIN_MODULE2) // -m .assertNormalExit(out -> { - out.shouldContain("[class,load] com.hello.Main source: shared objects file") - .shouldContain("[class,load] org.astro.World source: shared objects file"); + out.shouldMatch("\\[class,load *\\] com\\.hello\\.Main source: shared objects file") + .shouldMatch("\\[class,load *\\] org\\.astro\\.World source: shared objects file"); }); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java index 6c44ad587e3..9985215f773 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,8 +115,8 @@ public class ModulePathAndCP { moduleDir.toString(), // --module-path MAIN_MODULE) // -m .assertNormalExit(out -> { - out.shouldContain("[class,load] com.greetings.Main source: shared objects file") - .shouldContain("[class,load] org.astro.World source: shared objects file"); + out.shouldMatch("\\[class,load *\\] com\\.greetings\\.Main source: shared objects file") + .shouldMatch("\\[class,load *\\] org\\.astro\\.World source: shared objects file"); }); // run with the archive with the --module-path different from the one during @@ -181,7 +181,7 @@ public class ModulePathAndCP { jars, // --module-path MAIN_MODULE) // -m .assertNormalExit(out -> { - out.shouldContain("[class,load] com.greetings.Main source: shared objects file") + out.shouldMatch("\\[class,load *\\] com\\.greetings\\.Main source: shared objects file") .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); }); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java index 26bccdf764e..b55e6cfbd8b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,8 +71,8 @@ public class OldClassAndRedefineClass { "-Xlog:cds,class+load", agentCmdArg, "OldClassAndRedefineClassApp"); - out.shouldContain("[class,load] OldSuper source: shared objects file") - .shouldContain("[class,load] ChildOldSuper source: shared objects file") - .shouldContain("[class,load] Hello source: __VM_RedefineClasses__"); + out.shouldMatch("\\[class,load *\\] OldSuper source: shared objects file") + .shouldMatch("\\[class,load *\\] ChildOldSuper source: shared objects file") + .shouldMatch("\\[class,load *\\] Hello source: __VM_RedefineClasses__"); } } diff --git a/test/hotspot/jtreg/runtime/jni/mutateFinals/MutateFinalsTest.java b/test/hotspot/jtreg/runtime/jni/mutateFinals/MutateFinalsTest.java index 0ae4ae231b9..69786e3b368 100644 --- a/test/hotspot/jtreg/runtime/jni/mutateFinals/MutateFinalsTest.java +++ b/test/hotspot/jtreg/runtime/jni/mutateFinals/MutateFinalsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,7 +134,7 @@ class MutateFinalsTest { void testMutateInstanceFinalWithLogging(String methodName) throws Exception { String type = methodName.contains("Object") ? "Object" : ""; test(methodName, "-Xlog:jni=debug") - .shouldContain("[debug][jni] Set" + type + "Field mutated final instance field") + .shouldMatch("\\[debug *\\]\\[jni *\\] Set" + type + "Field mutated final instance field") .shouldHaveExitValue(0); } @@ -147,7 +147,7 @@ class MutateFinalsTest { void testMutateStaticFinalWithLogging(String methodName) throws Exception { String type = methodName.contains("Object") ? "Object" : ""; test(methodName, "-Xlog:jni=debug") - .shouldContain("[debug][jni] SetStatic" + type + "Field mutated final static field") + .shouldMatch("\\[debug *\\]\\[jni *\\] SetStatic" + type + "Field mutated final static field") .shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java b/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java index 34249e5fec8..ab076826723 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ public class ClassInitializationTest { "BadMap50"); out = new OutputAnalyzer(pb.start()); out.shouldNotHaveExitValue(0); - out.shouldNotContain("[class,init]"); + out.shouldNotMatch("\\[class,init *\\]"); out.shouldNotContain("Fail over class verification to old verifier for: BadMap50"); } diff --git a/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java b/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java index c62402c918b..9e75d52496f 100644 --- a/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java +++ b/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,27 +44,27 @@ public class CondyIndyTest { "CondyIndy"); OutputAnalyzer o = new OutputAnalyzer(pb.start()); o.shouldHaveExitValue(0); - o.shouldContain("[info][methodhandles"); - o.shouldNotContain("[debug][methodhandles,indy"); - o.shouldNotContain("[debug][methodhandles,condy"); + o.shouldMatch("\\[info *\\]\\[methodhandles"); + o.shouldNotMatch("\\[debug *\\]\\[methodhandles,indy"); + o.shouldNotMatch("\\[debug *\\]\\[methodhandles,condy"); // (2) methodhandles+condy=debug only pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:methodhandles+condy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); o.shouldHaveExitValue(0); - o.shouldNotContain("[info ][methodhandles"); - o.shouldNotContain("[debug][methodhandles,indy"); - o.shouldContain("[debug][methodhandles,condy"); + o.shouldNotMatch("\\[info *\\]\\[methodhandles"); + o.shouldNotMatch("\\[debug *\\]\\[methodhandles,indy"); + o.shouldMatch("\\[debug *\\]\\[methodhandles,condy"); // (3) methodhandles+indy=debug only pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:methodhandles+indy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); o.shouldHaveExitValue(0); - o.shouldNotContain("[info ][methodhandles"); - o.shouldContain("[debug][methodhandles,indy"); - o.shouldNotContain("[debug][methodhandles,condy"); + o.shouldNotMatch("\\[info *\\]\\[methodhandles"); + o.shouldMatch("\\[debug *\\]\\[methodhandles,indy"); + o.shouldNotMatch("\\[debug *\\]\\[methodhandles,condy"); // (4) methodhandles, condy, indy all on pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:methodhandles=info", @@ -73,8 +73,8 @@ public class CondyIndyTest { "CondyIndy"); o = new OutputAnalyzer(pb.start()); o.shouldHaveExitValue(0); - o.shouldContain("[info ][methodhandles"); - o.shouldContain("[debug][methodhandles,indy"); - o.shouldContain("[debug][methodhandles,condy"); + o.shouldMatch("\\[info *\\]\\[methodhandles"); + o.shouldMatch("\\[debug *\\]\\[methodhandles,indy"); + o.shouldMatch("\\[debug *\\]\\[methodhandles,condy"); }; } diff --git a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java index c2c966cb047..3bbec57b158 100644 --- a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java +++ b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ public class ExceptionsTest { static void analyzeOutputOff(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("[exceptions]"); + output.shouldNotMatch("\\[exceptions *\\]"); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/logging/GenerateOopMapTest.java b/test/hotspot/jtreg/runtime/logging/GenerateOopMapTest.java index 6e114ff6b1d..c16102ff448 100644 --- a/test/hotspot/jtreg/runtime/logging/GenerateOopMapTest.java +++ b/test/hotspot/jtreg/runtime/logging/GenerateOopMapTest.java @@ -43,7 +43,7 @@ public class GenerateOopMapTest { static String infoPattern = "[generateoopmap]"; static String debugPattern = "[generateoopmap] Basicblock#0 begins at:"; - static String tracePattern = "[trace][generateoopmap] 5 vars = 'r' stack = 'v' monitors = '' \tifne"; + static String tracePattern = "\\[trace *\\]\\[generateoopmap\\] 5 vars = 'r' stack = 'v' monitors = '' \tifne"; static String traceDetailPattern = "[generateoopmap] 0 vars = ( r |slot0) invokestatic()V"; static void test() throws Exception { @@ -63,7 +63,7 @@ public class GenerateOopMapTest { pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:generateoopmap=trace", "GenerateOopMapTest", "test"); o = new OutputAnalyzer(pb.start()); - o.shouldContain(tracePattern).shouldHaveExitValue(0); + o.shouldMatch(tracePattern).shouldHaveExitValue(0); // Prints extra stuff with detailed. Not sure how useful this is but keep it for now. if (Platform.isDebugBuild()) { diff --git a/test/hotspot/jtreg/runtime/logging/StackWalkTest.java b/test/hotspot/jtreg/runtime/logging/StackWalkTest.java index 226dac6f466..1cf90c1088d 100644 --- a/test/hotspot/jtreg/runtime/logging/StackWalkTest.java +++ b/test/hotspot/jtreg/runtime/logging/StackWalkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ public class StackWalkTest { static void analyzeOutputOff(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("[stackwalk]"); + output.shouldNotMatch("\\[stackwalk *\\]"); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/logging/StartupTimeTest.java b/test/hotspot/jtreg/runtime/logging/StartupTimeTest.java index 88ec76efd12..a1715509243 100644 --- a/test/hotspot/jtreg/runtime/logging/StartupTimeTest.java +++ b/test/hotspot/jtreg/runtime/logging/StartupTimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ public class StartupTimeTest { static void analyzeOutputOff(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("[startuptime]"); + output.shouldNotMatch("\\[startuptime *\\]"); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/logging/VerificationTest.java b/test/hotspot/jtreg/runtime/logging/VerificationTest.java index a6a0ee66acc..b2315f585c8 100644 --- a/test/hotspot/jtreg/runtime/logging/VerificationTest.java +++ b/test/hotspot/jtreg/runtime/logging/VerificationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,26 +39,26 @@ public class VerificationTest { static void analyzeOutputOn(ProcessBuilder pb, boolean isLogLevelInfo) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("[verification]"); + output.shouldMatch("\\[verification *\\]"); output.shouldContain("Verifying class VerificationTest$InternalClass with new format"); output.shouldContain("Verifying method VerificationTest$InternalClass.()V"); output.shouldContain("End class verification for: VerificationTest$InternalClass"); if (isLogLevelInfo) { // logging level 'info' should not output stack map and opcode data. - output.shouldNotContain("[verification] StackMapTable: frame_count"); - output.shouldNotContain("[verification] offset = 0, opcode ="); + output.shouldNotMatch("\\[verification *\\] StackMapTable: frame_count"); + output.shouldNotMatch("\\[verification *\\] offset = 0, opcode ="); } else { // log level debug - output.shouldContain("[debug][verification] StackMapTable: frame_count"); - output.shouldContain("[debug][verification] offset = 0, opcode ="); + output.shouldMatch("\\[debug *\\]\\[verification *\\] StackMapTable: frame_count"); + output.shouldMatch("\\[debug *\\]\\[verification *\\] offset = 0, opcode ="); } output.shouldHaveExitValue(0); } static void analyzeOutputOff(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("[verification]"); + output.shouldNotMatch("\\[verification *\\]"); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleTraceCL.java b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleTraceCL.java index 4750e95c828..0c57b4f2076 100644 --- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleTraceCL.java +++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleTraceCL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,11 +60,11 @@ public class PatchModuleTraceCL { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); // "modules" jimage case. - output.shouldContain("[class,load] java.lang.Thread source: jrt:/java.base"); + output.shouldMatch("\\[class,load *\\] java\\.lang\\.Thread source: jrt:/java.base"); // --patch-module case. - output.shouldContain("[class,load] javax.naming.spi.NamingManager source: mods/java.naming"); + output.shouldMatch("\\[class,load *\\] javax\\.naming\\.spi\\.NamingManager source: mods/java.naming"); // -cp case. - output.shouldContain("[class,load] PatchModuleMain source: file"); + output.shouldMatch("\\[class,load *\\] PatchModuleMain source: file"); // Test -Xlog:class+load=info output for -Xbootclasspath/a source = "package PatchModuleTraceCL_pkg; " + @@ -82,7 +82,7 @@ public class PatchModuleTraceCL { "-Xlog:class+load=info", "PatchModuleMain", "PatchModuleTraceCL_pkg.ItIsI"); output = new OutputAnalyzer(pb.start()); // -Xbootclasspath/a case. - output.shouldContain("[class,load] PatchModuleTraceCL_pkg.ItIsI source: xbcp"); + output.shouldMatch("\\[class,load *\\] PatchModuleTraceCL_pkg\\.ItIsI source: xbcp"); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/runtime/os/THPsInThreadStackPreventionTest.java b/test/hotspot/jtreg/runtime/os/THPsInThreadStackPreventionTest.java index 163a665b687..7fa80a5b40b 100644 --- a/test/hotspot/jtreg/runtime/os/THPsInThreadStackPreventionTest.java +++ b/test/hotspot/jtreg/runtime/os/THPsInThreadStackPreventionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -188,7 +188,7 @@ public class THPsInThreadStackPreventionTest { output.shouldHaveExitValue(0); // this line indicates the mitigation is active: - output.shouldContain("[pagesize] JVM will attempt to prevent THPs in thread stacks."); + output.shouldMatch("\\[pagesize *\\] JVM will attempt to prevent THPs in thread stacks\\."); ProcSelfStatus status = ProcSelfStatus.parse(output); if (status.numLifeThreads < numThreads) { @@ -225,7 +225,7 @@ public class THPsInThreadStackPreventionTest { output.shouldHaveExitValue(0); // We deliberately switched off mitigation, VM should tell us: - output.shouldContain("[pagesize] JVM will *not* prevent THPs in thread stacks. This may cause high RSS."); + output.shouldMatch("\\[pagesize *\\] JVM will \\*not\\* prevent THPs in thread stacks\\. This may cause high RSS\\."); // Parse output from self/status ProcSelfStatus status = ProcSelfStatus.parse(output); diff --git a/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java b/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java index 6c5896df058..52e7560a460 100644 --- a/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java +++ b/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java @@ -68,8 +68,8 @@ import java.util.Set; public class TestHugePageDecisionsAtVMStartup { // End user warnings, printing with Xlog:pagesize at warning level, should be unconditional - static final String warningNoTHP = "[warning][pagesize] UseTransparentHugePages disabled, transparent huge pages are not supported by the operating system."; - static final String warningNoLP = "[warning][pagesize] UseLargePages disabled, no large pages configured and available on the system."; + static final String warningNoTHP = "\\[warning\\]\\[pagesize *\\] UseTransparentHugePages disabled, transparent huge pages are not supported by the operating system\\."; + static final String warningNoLP = "\\[warning\\]\\[pagesize *\\] UseLargePages disabled, no large pages configured and available on the system\\."; static final String buildSizeString(long l) { String units[] = { "K", "M", "G" }; @@ -119,27 +119,27 @@ public class TestHugePageDecisionsAtVMStartup { } if (!useLP) { - out.shouldContain("[info][pagesize] Large page support disabled"); + out.shouldMatch("\\[info *\\]\\[pagesize *\\] Large page support disabled"); } else if (useLP && !useTHP && (!configuration.supportsExplicitHugePages() || !haveUsableExplicitHugePages)) { - out.shouldContain(warningNoLP); + out.shouldMatch(warningNoLP); } else if (useLP && useTHP && !configuration.supportsTHP()) { - out.shouldContain(warningNoTHP); + out.shouldMatch(warningNoTHP); } else if (useLP && !useTHP && configuration.supportsExplicitHugePages() && haveUsableExplicitHugePages) { if (configuration.getExplicitAvailableHugePageNumber() == 0) { throw new SkippedException("No usable explicit hugepages configured on the system, skipping test"); } - out.shouldContain("[info][pagesize] Using the default large page size: " + buildSizeString(configuration.getExplicitDefaultHugePageSize())); - out.shouldContain("[info][pagesize] UseLargePages=1, UseTransparentHugePages=0"); - out.shouldContain("[info][pagesize] Large page support enabled"); + out.shouldMatch("\\[info *\\]\\[pagesize *\\] Using the default large page size: " + buildSizeString(configuration.getExplicitDefaultHugePageSize())); + out.shouldMatch("\\[info *\\]\\[pagesize *\\] UseLargePages=1, UseTransparentHugePages=0"); + out.shouldMatch("\\[info *\\]\\[pagesize *\\] Large page support enabled"); } else if (useLP && useTHP && configuration.supportsTHP()) { long thpPageSize = configuration.getThpPageSizeOrFallback(); String thpPageSizeString = buildSizeString(thpPageSize); // We expect to see exactly two "Usable page sizes" : the system page size and the THP page size. The system // page size differs, but its always in KB). - out.shouldContain("[info][pagesize] UseLargePages=1, UseTransparentHugePages=1"); - out.shouldMatch(".*\\[info]\\[pagesize] Large page support enabled. Usable page sizes: \\d+[kK], " + thpPageSizeString + ". Default large page size: " + thpPageSizeString + ".*"); + out.shouldMatch("\\[info *\\]\\[pagesize *\\] UseLargePages=1, UseTransparentHugePages=1"); + out.shouldMatch("\\[info *\\]\\[pagesize *\\] Large page support enabled\\. Usable page sizes: \\d+[kK], " + thpPageSizeString + "\\. Default large page size: " + thpPageSizeString); } } diff --git a/test/hotspot/jtreg/runtime/os/TestTrimNative.java b/test/hotspot/jtreg/runtime/os/TestTrimNative.java index e8645a91479..467891bfe1e 100644 --- a/test/hotspot/jtreg/runtime/os/TestTrimNative.java +++ b/test/hotspot/jtreg/runtime/os/TestTrimNative.java @@ -1,7 +1,7 @@ /* * Copyright (c) 2023 SAP SE. All rights reserved. * Copyright (c) 2023, 2024, Red Hat, Inc. All rights reserved. - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -322,7 +322,7 @@ public class TestTrimNative { checkExpectedLogMessages(output, false, 0); parseOutputAndLookForNegativeTrim(output, 0, 0, strictTesting); // The following output is expected to be printed with warning level, so it should not need -Xlog - output.shouldContain("[warning][trimnative] Native heap trim is not supported on this platform"); + output.shouldMatch("\\[warning\\]\\[trimnative *\\] Native heap trim is not supported on this platform"); } break; case "testOffExplicit": { diff --git a/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpParallelTest.java b/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpParallelTest.java index 0010c5bdd78..f4dcb4dc1b0 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpParallelTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpParallelTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Alibaba Group Holding Limited. All Rights Reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +56,7 @@ public class HeapDumpParallelTest { dcmdOut.shouldHaveExitValue(0); dcmdOut.shouldContain("Heap dump file created"); OutputAnalyzer appOut = new OutputAnalyzer(app.getProcessStdout()); - appOut.shouldContain("[heapdump]"); + appOut.shouldMatch("\\[heapdump *\\]"); String opts = Arrays.asList(Utils.getTestJavaOpts()).toString(); if (opts.contains("-XX:+UseSerialGC") || opts.contains("-XX:+UseEpsilonGC")) { System.out.println("UseSerialGC detected."); @@ -136,4 +137,4 @@ public class HeapDumpParallelTest { PidJcmdExecutor executor = new PidJcmdExecutor("" + lingeredAppPid); return executor.execute("GC.heap_dump " + arg + " " + heapDumpFile.getAbsolutePath()); } -} \ No newline at end of file +} diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 08a476427bb..7048aafc638 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -59,7 +59,7 @@ exclusiveAccess.dirs=java/math/BigInteger/largeMemory \ java/rmi/Naming java/util/prefs sun/management/jmxremote \ sun/tools/jstatd sun/security/mscapi java/util/Arrays/largeMemory \ java/util/BitSet/stream javax/rmi java/net/httpclient/websocket \ -com/sun/net/httpserver/simpleserver sun/tools/jhsdb +com/sun/net/httpserver/simpleserver sun/tools/jhsdb javax/sound # Group definitions groups=TEST.groups diff --git a/test/jdk/java/text/Format/ListFormat/TestListFormat.java b/test/jdk/java/text/Format/ListFormat/TestListFormat.java index 68da9ce5fda..e85e98b6cf6 100644 --- a/test/jdk/java/text/Format/ListFormat/TestListFormat.java +++ b/test/jdk/java/text/Format/ListFormat/TestListFormat.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8041488 8316974 8318569 8306116 8385736 8385834 + * @bug 8041488 8316974 8318569 8306116 8385736 8385834 8386200 * @summary Tests for ListFormat class * @run junit TestListFormat */ @@ -74,6 +74,14 @@ public class TestListFormat { "", "", }; + // Ensures MessageFormat single quotes in custom patterns are treated as literals. + private static final String[] CUSTOM_PATTERNS_SINGLE_QUOTE = { + "' {0} ' {1}", + "{0} '' {1}", + "{0} ''' {1} '''", + "", + "", + }; private static final String[] CUSTOM_PATTERNS_IAE_START = { "{0}", "{0} mid {1}", @@ -142,6 +150,10 @@ public class TestListFormat { arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE2, ". foo | bar ["), arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE3, ". foo * bar | baz ["), arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE4, ". foo * bar + baz | qux ["), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE1, "foo"), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE2, "' foo ''' bar '''"), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE3, "' foo ' bar ''' baz '''"), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE4, "' foo ' bar '' baz ''' qux '''") }; } diff --git a/test/jdk/java/util/TimeZone/AIXTzMappingTest.java b/test/jdk/java/util/TimeZone/AIXTzMappingTest.java new file mode 100644 index 00000000000..6324bb8581a --- /dev/null +++ b/test/jdk/java/util/TimeZone/AIXTzMappingTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8380993 + * @library /test/lib + * @summary Validates AIX timezone mapping behavior where POSIX TZ strings + * with comma-separated DST rules are truncated and mapped through tzmappings + * to the expected IANA timezone IDs. + * @requires os.family == "aix" + * @run main/othervm AIXTzMappingTest + */ + +import java.util.TimeZone; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class AIXTzMappingTest { + + // POSIX TZ strings that should be mapped via tzmappings + private static final String TZ_CET = "CET-1CEST,M3.5.0,M10.5.0"; + private static final String TZ_MEZ = "MEZ-1MESZ,M3.5.0,M10.5.0/3"; + + private static final String ID_PARIS = "Europe/Paris"; + private static final String ID_BERLIN = "Europe/Berlin"; + + public static void main(String[] args) throws Throwable { + if (args.length == 0) { + runWithTZ(TZ_CET, ID_PARIS); + runWithTZ(TZ_MEZ, ID_BERLIN); + } else if (args.length == 1) { + runTZTest(args[0]); + } else { + throw new RuntimeException( + "Expected 0 or 1 arguments, got " + args.length); + } + } + + private static void runWithTZ(String tz, String expectedId) + throws Throwable { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "AIXTzMappingTest", expectedId); + + pb.environment().put("TZ", tz); + + OutputAnalyzer output = ProcessTools.executeProcess(pb); + output.shouldHaveExitValue(0); + } + + /* + * On AIX, POSIX TZ strings such as: + * CET-1CEST,M3.5.0,M10.5.0 + * MEZ-1MESZ,M3.5.0,M10.5.0/3 + * are truncated at the comma and mapped through tzmappings to + * IANA timezone IDs. + * + * This test verifies that the expected IANA timezone ID is selected. + */ + private static void runTZTest(String expectedId) { + String tzStr = System.getenv("TZ"); + + if (tzStr == null) { + throw new RuntimeException( + "Got unexpected timezone information: TZ is null"); + } + + TimeZone tz = TimeZone.getDefault(); + String tzId = tz.getID(); + + if (!expectedId.equals(tzId)) { + throw new RuntimeException( + "Expected timezone ID " + expectedId + + " but got " + tzId + + " for TZ=" + tzStr); + } + + System.out.println( + "AIX timezone mapping test passed: " + + tzId + " for TZ=" + tzStr); + } +} diff --git a/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java b/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java index 5fd48efadcc..9a332202ab3 100644 --- a/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java +++ b/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,10 @@ * @library /test/lib * @summary This test will ensure that daylight savings rules are followed * appropriately when setting a custom timezone ID via the TZ env variable. - * @requires os.family != "windows" + * AIX is excluded because it uses a different timezone mapping mechanism + * through the tzmappings file; see AIXTzMappingTest.java for AIX-specific + * coverage. + * @requires os.family != "windows" & os.family != "aix" * @run main/othervm CustomTzIDCheckDST */ diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorConversionTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorConversionTest.java index 6f0625d7985..854ffd407c8 100644 --- a/test/jdk/jdk/incubator/vector/AbstractVectorConversionTest.java +++ b/test/jdk/jdk/incubator/vector/AbstractVectorConversionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.IntFunction; +import jdk.incubator.vector.Float16; abstract class AbstractVectorConversionTest { @@ -156,6 +157,31 @@ abstract class AbstractVectorConversionTest { return a; } + interface ToFloat16F { + short apply(int i); + } + + static short[] fill_float16(int s, ToFloat16F f) { + return fill_float16(new short[s], f); + } + + static short[] fill_float16(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + if (a.length > 7) { + a[0] = Float16.float16ToRawShortBits(Float16.MAX_VALUE); + a[1] = Float16.float16ToRawShortBits(Float16.MIN_VALUE); + a[2] = Float16.float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + a[3] = Float16.float16ToRawShortBits(Float16.POSITIVE_INFINITY); + a[4] = Float16.float16ToRawShortBits(Float16.NaN); + a[5] = (short)0.0; + a[6] = Short.MIN_VALUE; + } + return a; + } + + static final List> BYTE_GENERATORS = List.of( withToString("byte(i)", (int s) -> fill_byte(s, i -> (byte) (i + 1))) ); @@ -180,6 +206,10 @@ abstract class AbstractVectorConversionTest { withToString("double(i)", (int s) -> fill_double(s, i -> (double) (i * 10 + 0.1))) ); + static final List> FLOAT16_GENERATORS = List.of( + withToString("Float16(i)", (int s) -> fill_float16(s, i -> (short) (i * 100 + 1))) + ); + static List sourceGenerators(Class src) { if (src == byte.class) { return BYTE_GENERATORS; @@ -199,6 +229,9 @@ abstract class AbstractVectorConversionTest { else if (src == double.class) { return DOUBLE_GENERATORS; } + else if (src == Float16.class) { + return FLOAT16_GENERATORS; + } else throw new IllegalStateException(); } @@ -206,11 +239,11 @@ abstract class AbstractVectorConversionTest { static Object[][] fixedShapeXFixedShapeSpeciesArgs(VectorShape shape) { List args = new ArrayList<>(); - for (Class srcE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class)) { + for (Class srcE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class, Float16.class)) { VectorSpecies src = VectorSpecies.of(srcE, shape); List srcGens = sourceGenerators(srcE); - for (Class dstE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class)) { + for (Class dstE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class, Float16.class)) { VectorSpecies dst = VectorSpecies.of(dstE, shape); for (Object srcGen : srcGens) { @@ -225,12 +258,12 @@ abstract class AbstractVectorConversionTest { static Object[][] fixedShapeXShapeSpeciesArgs(VectorShape srcShape) { List args = new ArrayList<>(); - for (Class srcE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class)) { + for (Class srcE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class, Float16.class)) { VectorSpecies src = VectorSpecies.of(srcE, srcShape); List srcGens = sourceGenerators(srcE); for (VectorShape dstShape : VectorShape.values()) { - for (Class dstE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class)) { + for (Class dstE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class, Float16.class)) { VectorSpecies dst = VectorSpecies.of(dstE, dstShape); for (Object srcGen : srcGens) { @@ -245,10 +278,10 @@ abstract class AbstractVectorConversionTest { static Object[][] fixedShapeXSegmentedCastSpeciesArgs(VectorShape srcShape, boolean legal) { List args = new ArrayList<>(); - for (Class srcE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class)) { + for (Class srcE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class, Float16.class)) { VectorSpecies src = VectorSpecies.of(srcE, srcShape); for (VectorShape dstShape : VectorShape.values()) { - for (Class dstE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class)) { + for (Class dstE : List.of(byte.class, short.class, int.class, long.class, float.class, double.class, Float16.class)) { VectorSpecies dst = VectorSpecies.of(dstE, dstShape); if (legal == (dst.length() == src.length())) { args.add(new Object[]{src, dst}); @@ -261,6 +294,22 @@ abstract class AbstractVectorConversionTest { public enum ConvAPI {CONVERT, CONVERTSHAPE, CASTSHAPE, REINTERPRETSHAPE} + static Short float16_conversion_adapter(Number in) { + if (in.getClass() == Short.class) + return Float16.float16ToRawShortBits(Float16.valueOf(in.shortValue())); + else if (in.getClass() == Integer.class) + return Float16.float16ToRawShortBits(Float16.valueOf(in.intValue())); + else if (in.getClass() == Long.class) + return Float16.float16ToRawShortBits(Float16.valueOf(in.longValue())); + else if (in.getClass() == Float.class) + return Float16.float16ToRawShortBits(Float16.valueOf(in.floatValue())); + else if (in.getClass() == Double.class) + return Float16.float16ToRawShortBits(Float16.valueOf(in.doubleValue())); + else if (in.getClass() == Byte.class) + return Float16.float16ToRawShortBits(Float16.valueOf(in.byteValue())); + else + throw new IllegalStateException(); + } static Function convertValueFunction(Class to) { if (to == byte.class) @@ -273,6 +322,8 @@ abstract class AbstractVectorConversionTest { return Number::longValue; else if (to == float.class) return Number::floatValue; + else if (to == Float16.class) + return (N) -> float16_conversion_adapter(N); else if (to == double.class) return Number::doubleValue; else @@ -282,7 +333,7 @@ abstract class AbstractVectorConversionTest { static BiConsumer putBufferValueFunction(Class from) { if (from == byte.class) return (bb, o) -> bb.put((byte) o); - else if (from == short.class) + else if (from == short.class || from == Float16.class) return (bb, o) -> bb.putShort((short) o); else if (from == int.class) return (bb, o) -> bb.putInt((int) o); @@ -299,7 +350,7 @@ abstract class AbstractVectorConversionTest { static Function getBufferValueFunction(Class to) { if (to == byte.class) return ByteBuffer::get; - else if (to == short.class) + else if (to == short.class || to == Float16.class) return ByteBuffer::getShort; else if (to == int.class) return ByteBuffer::getInt; @@ -335,10 +386,23 @@ abstract class AbstractVectorConversionTest { static void copyConversionArray(Object src, int srcPos, Object dest, int destPos, int length, + VectorSpecies srcSpecies, + VectorSpecies dstSpecies, Function c) { + if (srcSpecies.elementType() == dstSpecies.elementType()) { + System.arraycopy(src, srcPos, dest, destPos, length); + return; + } for (int i = 0; i < length; i++) { Number v = (Number) Array.get(src, srcPos + i); - Array.set(dest, destPos + i, c.apply(v)); + if (srcSpecies.elementType() == Float16.class) { + v = (Number) Float16.shortBitsToFloat16(v.shortValue()); + } + v = (Number) c.apply(v); + if (dstSpecies.elementType() == Float16.class) { + v = (Number) v.shortValue(); + } + Array.set(dest, destPos + i, v); } } @@ -420,8 +484,14 @@ abstract class AbstractVectorConversionTest { int[] parts = getPartsArray(m, is_contracting_conv); - Object expected = Array.newInstance(destSpecies.elementType(), out_len); - Object actual = Array.newInstance(destSpecies.elementType(), out_len); + Object expected = null, actual = null; + if (destSpecies.elementType() == Float16.class) { + expected = Array.newInstance(short.class, out_len); + actual = Array.newInstance(short.class, out_len); + } else { + expected = Array.newInstance(destSpecies.elementType(), out_len); + actual = Array.newInstance(destSpecies.elementType(), out_len); + } Function convertValue = convertValueFunction(destSpecies.elementType()); @@ -432,11 +502,12 @@ abstract class AbstractVectorConversionTest { if (is_contracting_conv) { int start_idx = -part * src_species_len; zeroArray(expected, j, dst_species_len); - copyConversionArray(in, i, expected, start_idx + j, src_species_len, convertValue); + copyConversionArray(in, i, expected, start_idx + j, src_species_len, srcSpecies, destSpecies, convertValue); } else { int start_idx = part * dst_species_len; - copyConversionArray(in, start_idx + i, expected, j, dst_species_len, convertValue); + copyConversionArray(in, start_idx + i, expected, j, dst_species_len, srcSpecies, destSpecies, convertValue); } + } for (int ic = 0; ic < INVOC_COUNT; ic++) { @@ -452,7 +523,6 @@ abstract class AbstractVectorConversionTest { System.arraycopy(rv.toArray(), 0, actual, j, dst_species_len); } } - Assert.assertEquals(actual, expected); } @@ -469,8 +539,14 @@ abstract class AbstractVectorConversionTest { int[] parts = getPartsArray(m, is_contracting_conv); - Object expected = Array.newInstance(dstSpecies.elementType(), out_len); - Object actual = Array.newInstance(dstSpecies.elementType(), out_len); + Object expected = null, actual = null; + if (dstSpecies.elementType() == Float16.class) { + expected = Array.newInstance(short.class, out_len); + actual = Array.newInstance(short.class, out_len); + } else { + expected = Array.newInstance(dstSpecies.elementType(), out_len); + actual = Array.newInstance(dstSpecies.elementType(), out_len); + } BiConsumer putValue = putBufferValueFunction(srcSpecies.elementType()); Function getValue = getBufferValueFunction(dstSpecies.elementType()); diff --git a/test/jdk/jdk/incubator/vector/Float16Vector128LoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float16Vector128LoadStoreTests.java new file mode 100644 index 00000000000..570be3bde63 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector128LoadStoreTests.java @@ -0,0 +1,1038 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:-TieredCompilation Float16Vector128LoadStoreTests + * + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.Arena; +import java.lang.foreign.ValueLayout; +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.internal.vm.annotation.DontInline; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.nio.ByteOrder; +import java.util.List; +import java.util.function.*; + +@Test +public class Float16Vector128LoadStoreTests extends AbstractVectorLoadStoreTest { + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_128; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); + + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 128); + + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0, "at index #" + i); + } + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("short[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i * 5)); + }), + withToString("short[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1))); + }) + ); + + // Relative to array.length + static final List> INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl + 1", (int l) -> { + return l - SPECIES.length() + 1; + }), + withToString("l + speciesl - 1", (int l) -> { + return l + SPECIES.length() - 1; + }), + withToString("l + speciesl", (int l) -> { + return l + SPECIES.length(); + }), + withToString("l + speciesl + 1", (int l) -> { + return l + SPECIES.length() + 1; + }) + ); + + // Relative to byte[] array.length or MemorySegment.byteSize() + static final List> BYTE_INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl*ebsize + 1", (int l) -> { + return l - SPECIES.vectorByteSize() + 1; + }), + withToString("l + speciesl*ebsize - 1", (int l) -> { + return l + SPECIES.vectorByteSize() - 1; + }), + withToString("l + speciesl*ebsize", (int l) -> { + return l + SPECIES.vectorByteSize(); + }), + withToString("l + speciesl*ebsize + 1", (int l) -> { + return l + SPECIES.vectorByteSize() + 1; + }) + ); + + @DataProvider + public Object[][] shortProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentProvider() { + return FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, bo}; + }))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, fm, bo}; + })))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + static MemorySegment toSegment(short[] a, IntFunction fb) { + MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8); + for (int i = 0; i < a.length; i++) { + ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]); + } + return ms; + } + + static short[] segmentToArray(MemorySegment ms) { + return ms.toArray(ELEMENT_LAYOUT); + } + + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + @DontInline + static VectorShuffle shuffleFromArray(int[] a, int i) { + return SPECIES.shuffleFromArray(a, i); + } + + @DontInline + static void shuffleIntoArray(VectorShuffle s, int[] a, int i) { + s.intoArray(a, i); + } + + @DontInline + static VectorShuffle shuffleFromMemorySegment(MemorySegment mem, int i, ByteOrder bo) { + return VectorShuffle.fromMemorySegment(SPECIES, mem, i, bo); + } + + @DontInline + static void shuffleIntoMemorySegment(VectorShuffle s, MemorySegment mem, int i, ByteOrder bo) { + s.intoMemorySegment(mem, i, bo); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromArray(a, i); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i, VectorMask m) { + return Float16Vector.fromArray(SPECIES, a, i, m); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i) { + v.intoArray(a, i); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i, VectorMask m) { + v.intoArray(a, i, m); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromMemorySegment(a, i, bo); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask m) { + return Float16Vector.fromMemorySegment(SPECIES, a, i, bo, m); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo) { + v.intoMemorySegment(a, i, bo); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo, VectorMask m) { + v.intoMemorySegment(a, i, bo, m); + } + + @Test(dataProvider = "shortProvider") + static void loadStoreArray(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i); + } + } + assertEquals(r, a); + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void loadArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + fromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void storeArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMaskArray(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, vmask); + av.intoArray(r, i); + } + } + assertArraysEquals(r, a, mask); + + + r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, vmask); + } + } + assertArraysEquals(r, a, mask); + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void loadArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i, vmask); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + fromArray(a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void storeArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i, vmask); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMask(IntFunction fa, + IntFunction fm) { + boolean[] mask = fm.apply(SPECIES.length()); + boolean[] r = new boolean[mask.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < mask.length; i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, mask); + } + + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo); + } + } + long m = r.mismatch(a); + Assert.assertEquals(m, -1, "Segments not equal"); + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder()); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentMaskProvider") + static void loadStoreMemorySegmentMask(IntFunction fa, + IntFunction fb, + IntFunction fm, + ByteOrder bo) { + short[] _a = fa.apply(SPECIES.length()); + MemorySegment a = toSegment(_a, fb); + MemorySegment r = fb.apply((int) a.byteSize()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo, vmask); + av.intoMemorySegment(r, i, bo); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + + + r = fb.apply((int) a.byteSize()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo, vmask); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void storeMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreReadonlyMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly(); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true)) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false)) + ); + + VectorMask m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1) + .laneIsValid(); + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m) + ); + } + + + @Test(dataProvider = "maskProvider") + static void loadStoreMask(IntFunction fm) { + boolean[] a = fm.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask vmask = SPECIES.loadMask(a, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, a); + } + + + @Test(dataProvider = "shuffleIntProvider") + static void loadStoreShuffleArray(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = VectorShuffle.fromArray(SPECIES, a, i); + shuffle.intoArray(r, i); + } + } + + for (int i = 0; i < a.length; i++) { + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, a[i]), r[i]); + } + + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void storeShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffleIntoArray(shuffle, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + VectorShuffle shuffle = shuffleFromArray(a, index); + shuffleIntoArray(shuffle, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void loadShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffle.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + shuffleFromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntMemorySegmentProvider") + static void loadStoreShuffleMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; //An integer for every lane is read out. So 4 bytes per lane + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = VectorShuffle.fromMemorySegment(SPECIES, a, i, bo); + shuffle.intoMemorySegment(r, i, bo); + } + } + + for (int i = 0; i < l / 4; i++) { + int ai = a.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + int ri = r.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, ai), ri); + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleLoadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = shuffleFromMemorySegment(a, i, ByteOrder.nativeOrder()); + shuffle.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + shuffleFromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleStoreMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + + + // Gather/Scatter load/store tests + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], a[i + indexMap[j]]); + } + } + } catch (AssertionError e) { + assertEquals(r[j], a[i + indexMap[j]], "at index #" + j); + } + } + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0); + } + } + } catch (AssertionError e) { + assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j); + } + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + if (mask[j % SPECIES.length()]) { + expected[i + indexMap[j]] = a[j]; + } + } + } + + assertEquals(r, expected); + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + expected[i + indexMap[j]] = a[j]; + } + } + + assertEquals(r, expected); + } + + @DataProvider + public Object[][] gatherScatterProvider() { + return INT_INDEX_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] gatherScatterMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm -> + FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm, fs}; + }))). + toArray(Object[][]::new); + } + + + @Test(dataProvider = "gatherScatterProvider") + static void gather(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void gatherMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i, vmask); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b, mask); + } + + @Test(dataProvider = "gatherScatterProvider") + static void scatter(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i); + } + } + + assertScatterArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void scatterMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i, vmask); + } + } + + assertScatterArraysEquals(r, a, b, mask); + } + + + +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector128Tests.java b/test/jdk/jdk/incubator/vector/Float16Vector128Tests.java new file mode 100644 index 00000000000..ad971e9b9bf --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector128Tests.java @@ -0,0 +1,5887 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector + * @run testng/othervm/timeout=300 -ea -esa -Xbatch -XX:-TieredCompilation Float16Vector128Tests + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.Vector; + +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import jdk.incubator.vector.Float16Vector; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.Integer; +import java.util.List; +import java.util.Arrays; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Test +public class Float16Vector128Tests extends AbstractVectorTest { + + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_128; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + static void assertEquals(short actual, short expected, short delta) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta)); + } + static void assertEquals(short actual, short expected, short delta, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta), msg); + } + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + static void assertEquals(long actual, long expected) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected)); + } + static void assertEquals(long actual, long expected, String msg) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected), msg); + } + static void assertEquals(String actual, String expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(Object actual, Object expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + static void assertEquals(boolean actual, boolean expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(boolean actual, boolean expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + + + // Identity values for reduction operations + private static final short ADD_IDENTITY = (short)0; + private static final short FIRST_NONZERO_IDENTITY = (short)0; + private static final short MAX_IDENTITY = float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + private static final short MIN_IDENTITY = float16ToRawShortBits(Float16.POSITIVE_INFINITY); + private static final short MUL_IDENTITY = float16ToRawShortBits(Float16.valueOf(1.0f)); + + // for floating point addition reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_ADD = float16ToRawShortBits(Float16.valueOf(10.0f)); + + // for floating point multiplication reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_MUL = float16ToRawShortBits(Float16.valueOf(50.0f)); + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 128); + + static void assertArraysStrictlyEquals(short[] r, short[] a) { + for (int i = 0; i < a.length; i++) { + short ir = r[i]; + short ia = a[i]; + if (ir != ia) { + Assert.fail(String.format("at index #%d, expected = %016X, actual = %016X", i, ia, ir)); + } + } + } + + interface FUnOp { + short apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]); + } + } + + interface FUnArrayOp { + short[] apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnArrayOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a[i])); + } + } catch (AssertionError e) { + short[] ref = f.apply(a[i]); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i], "at index #" + i + ", input = " + a[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + interface FReductionOp { + short apply(short[] a, int idx); + } + + interface FReductionAllOp { + short apply(short[] a); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa) { + assertReductionArraysEquals(r, rc, a, f, fa, (short)0.0); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa, + short relativeErrorFactor) { + int i = 0; + try { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor)))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor)))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor))), "at index #" + i); + } + } + + interface FReductionMaskedOp { + short apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOp { + short apply(short[] a, boolean[] mask); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa) { + assertReductionArraysEqualsMasked(r, rc, a, mask, f, fa, (short)0.0); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa, + short relativeError) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError))))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError))))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError)))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError)))), "at index #" + i); + } + } + + interface FReductionOpLong { + long apply(short[] a, int idx); + } + + interface FReductionAllOpLong { + long apply(short[] a); + } + + static void assertReductionLongArraysEquals(long[] r, long rc, short[] a, + FReductionOpLong f, FReductionAllOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FReductionMaskedOpLong { + long apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOpLong { + long apply(short[] a, boolean[] mask); + } + + static void assertReductionLongArraysEqualsMasked(long[] r, long rc, short[] a, boolean[] mask, + FReductionMaskedOpLong f, FReductionAllMaskedOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), "at index #" + i); + } + } + + interface FBoolReductionOp { + boolean apply(boolean[] a, int idx); + } + + static void assertReductionBoolArraysEquals(boolean[] r, boolean[] a, FBoolReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FMaskReductionOp { + int apply(boolean[] a, int idx); + } + + static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+order[i+j]]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]); + } + } + + static void assertcompressArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + k], a[i + j]); + k++; + } + } + for (; k < vector_len; k++) { + assertEquals(r[i + k], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + k; + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[idx], a[i + j], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertexpandArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + j], a[i + k]); + k++; + } else { + assertEquals(r[i + j], (short)0); + } + } + } + } catch (AssertionError e) { + int idx = i + j; + if (m[idx % SPECIES.length()]) { + assertEquals(r[idx], a[i + k], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertSelectFromTwoVectorEquals(short[] r, short[] order, short[] a, short[] b, int vector_len) { + int i = 0, j = 0; + boolean is_exceptional_idx = false; + int idx = 0, wrapped_index = 0, oidx = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + idx = i + j; + wrapped_index = Math.floorMod(shortBitsToFloat16(order[idx]).intValue(), 2 * vector_len); + is_exceptional_idx = wrapped_index >= vector_len; + oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index; + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx])); + } + } + } catch (AssertionError e) { + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]), "at index #" + idx + ", order = " + order[idx] + ", a = " + a[i + oidx] + ", b = " + b[i + oidx]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a) { + int i = 0; + for (; i < a.length; i += SPECIES.length()) { + int idx = i; + for (int j = idx; j < (idx + SPECIES.length()); j++) + a[j]=a[idx]; + } + + try { + for (i = 0; i < a.length; i++) { + assertEquals(r[i], a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]); + } + } + + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + interface FBinOp { + short apply(short a, short b); + } + + interface FBinMaskOp { + short apply(short a, short b, boolean m); + + static FBinMaskOp lift(FBinOp f) { + return (a, b, m) -> m ? f.apply(a, b) : a; + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b), "(" + a[i] + ", " + b + ") at index #" + i); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())))); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue()))), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastLongArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertShiftArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", input2 = " + b[j] + ", mask = " + mask[i]); + } + } + + interface FBinConstOp { + short apply(short a); + } + + interface FBinConstMaskOp { + short apply(short a, boolean m); + + static FBinConstMaskOp lift(FBinConstOp f) { + return (a, m) -> m ? f.apply(a) : a; + } + } + + static void assertShiftConstEquals(short[] r, short[] a, FBinConstOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstOp f) { + assertShiftConstEquals(r, a, mask, FBinConstMaskOp.lift(f)); + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", mask = " + mask[i]); + } + } + + interface FTernOp { + short apply(short a, short b, short c); + } + + interface FTernMaskOp { + short apply(short a, short b, short c, boolean m); + + static FTernMaskOp lift(FTernOp f) { + return (a, b, c, m) -> m ? f.apply(a, b, c) : a; + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernOp f) { + assertArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + c[i]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertAltBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + + static boolean isWithin1Ulp(short actual, short expected) { + Float16 act = shortBitsToFloat16(actual); + Float16 exp = shortBitsToFloat16(expected); + if (Float16.isNaN(exp) && !Float16.isNaN(act)) { + return false; + } else if (!Float16.isNaN(exp) && Float16.isNaN(act)) { + return false; + } + + Float16 low = Float16.nextDown(exp); + Float16 high = Float16.nextUp(exp); + + if (Float16.compare(low, exp) > 0) { + return false; + } + + if (Float16.compare(high, exp) < 0) { + return false; + } + + return true; + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, FUnOp mathf, FUnOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i])); + } + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i])); + } + } + + static void assertBroadcastArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, + FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0 || + isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0, + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + Assert.assertTrue(isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])), + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], + b[(i / SPECIES.length()) * SPECIES.length()])); + } + } + + interface FGatherScatterOp { + short[] apply(short[] a, int ix, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, FGatherScatterOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + " at index #" + i); + } + } + + interface FGatherMaskedOp { + short[] apply(short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + interface FScatterMaskedOp { + short[] apply(short[] r, short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FGatherMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FScatterMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(r, a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(r, a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", r: " + + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + interface FLaneOp { + short[] apply(short[] a, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, int origin, FLaneOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + interface FLaneBop { + short[] apply(short[] a, short[] b, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, FLaneBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLaneMaskedBop { + short[] apply(short[] a, short[] b, int origin, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, boolean[] mask, FLaneMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLanePartBop { + short[] apply(short[] a, short[] b, int origin, int part, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, FLanePartBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + interface FLanePartMaskedBop { + short[] apply(short[] a, short[] b, int origin, int part, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, boolean[] mask, FLanePartMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + + static short convToFloat16(int i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convIntToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504); + case 1: + return convToFloat16(-65504); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> INT_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[intCornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convIntToFloat16CornerCases(i)); + }) + ); + + static void assertArraysEquals(int[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (int)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + + static short convToFloat16(long i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convLongToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504L); + case 1: + return convToFloat16(-65504L); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> LONG_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convLongToFloat16CornerCases(i)); + }) + ); + + + static void assertArraysEquals(long[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (long)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static void assertArraysEquals(double[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (double)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static short bits(short e) { + return e; + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[0.01 + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01f + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (i % 17 == 0) ? cornerCaseValue(i) : Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + // Create combinations of pairs + // @@@ Might be sensitive to order e.g. div by 0 + static final List>> FLOAT16_GENERATOR_PAIRS = + Stream.of(FLOAT16_GENERATORS.get(0)). + flatMap(fa -> FLOAT16_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_GENERATOR_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> FLOAT16_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + static final List> SELECT_FROM_INDEX_GENERATORS = List.of( + withToString("float16[0..VECLEN*2)", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(RAND.nextInt())); + }) + ); + + static final List>> FLOAT16_GENERATOR_SELECT_FROM_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> SELECT_FROM_INDEX_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortBinaryOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortIndexedOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortBinaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpProvider() { + return FLOAT16_GENERATOR_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSelectFromTwoVectorOpProvider() { + return FLOAT16_GENERATOR_SELECT_FROM_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_TRIPLES.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoIntUnaryOpProvider() { + return INT_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoLongUnaryOpProvider() { + return LONG_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleCompareOpProvider() { + return INT_SHUFFLE_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_SHUFFLE_GENERATORS = List.of( + withToStringBi("shuffle[random]", (Integer l, Integer m) -> { + short[] a = new short[l]; + int upper = m; + for (int i = 0; i < 1; i++) { + a[i] = (short)RAND.nextInt(upper); + } + return a; + }) + ); + + @DataProvider + public Object[][] shortUnaryOpSelectFromProvider() { + return FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpSelectFromMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_COMPARE_GENERATORS = List.of( + withToString("float16[i]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)i); + }), + withToString("float16[i - length / 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - (s * BUFFER_REPS / 2))); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i + 1)); + }), + withToString("float16[i - 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - 2)); + }), + withToString("float16[zigZag(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> i%3 == 0 ? (short)i : (i%3 == 1 ? (short)(i + 1) : (short)(i - 2))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + static final List>> FLOAT16_TEST_GENERATOR_ARGS = + FLOAT16_COMPARE_GENERATORS.stream(). + map(fa -> List.of(fa)). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortTestOpProvider() { + return FLOAT16_TEST_GENERATOR_ARGS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTestOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_TEST_GENERATOR_ARGS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_COMPARE_GENERATOR_PAIRS = + FLOAT16_COMPARE_GENERATORS.stream(). + flatMap(fa -> FLOAT16_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortCompareOpProvider() { + return FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortCompareOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + static short cornerCaseValue(int i) { + return switch(i % 8) { + case 0 -> float16ToRawShortBits(Float16.MAX_VALUE); + case 1 -> float16ToRawShortBits(Float16.MIN_VALUE); + case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY); + case 4 -> float16ToRawShortBits(Float16.NaN); + case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA)); + case 6 -> float16ToShortBits(Float16.valueOf(0.0f)); + default -> float16ToShortBits(Float16.valueOf(-0.0f)); + }; + } + + static final IntFunction fr = (vl) -> { + int length = BUFFER_REPS * vl; + return new short[length]; + }; + + static final IntFunction fmr = (vl) -> { + int length = BUFFER_REPS * vl; + return new boolean[length]; + }; + + static final IntFunction lfr = (vl) -> { + int length = BUFFER_REPS * vl; + return new long[length]; + }; + + static boolean eq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() == bt.floatValue(); + } + + static boolean neq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() != bt.floatValue(); + } + + static boolean lt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() < bt.floatValue(); + } + + static boolean le(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() <= bt.floatValue(); + } + + static boolean gt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() > bt.floatValue(); + } + + static boolean ge(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() >= bt.floatValue(); + } + + static short firstNonZero(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 zero = shortBitsToFloat16((short)0); + return Float16.compare(at, zero) != 0 ? a : b; + } + + static short scalar_add(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.add(at, bt)); + } + + static short scalar_sub(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.subtract(at, bt)); + } + + static short scalar_mul(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.multiply(at, bt)); + + } + static short scalar_max(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.max(at, bt)); + } + + static short scalar_min(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.min(at, bt)); + } + + static short scalar_div(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.divide(at, bt)); + } + + static short scalar_fma(short a, short b, short c) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 ct = shortBitsToFloat16(c); + return float16ToRawShortBits(Float16.fma(at, bt, ct)); + } + + static short scalar_abs(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.abs(at)); + } + + static short scalar_neg(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.negate(at)); + } + + static short scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static boolean isNaN(short a) { + return Float16.isNaN(shortBitsToFloat16(a)); + } + static boolean isFinite(short a) { + return Float16.isFinite(shortBitsToFloat16(a)); + } + static boolean isInfinite(short a) { + return Float16.isInfinite(shortBitsToFloat16(a)); + } + + @Test + static void smokeTest1() { + Float16Vector three = Float16Vector.broadcast(SPECIES, float16ToRawShortBits(Float16.valueOf(-3))); + Float16Vector three2 = (Float16Vector) SPECIES.broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three2).allTrue()); + Float16Vector three3 = three2.broadcast(float16ToRawShortBits(Float16.valueOf(1))).broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three3).allTrue()); + int scale = 2; + Class ETYPE = short.class; + if (ETYPE == double.class || ETYPE == long.class) + scale = 1000000; + else if (ETYPE == byte.class && SPECIES.length() >= 64) + scale = 1; + Float16Vector higher = three.addIndex(scale); + VectorMask m = three.compare(VectorOperators.LE, higher); + assert(m.allTrue()); + m = higher.min(float16ToRawShortBits(Float16.valueOf(-1))).test(VectorOperators.IS_NEGATIVE); + assert(m.allTrue()); + m = higher.test(VectorOperators.IS_FINITE); + assert(m.allTrue()); + short max = higher.reduceLanes(VectorOperators.MAX); + assert(max == float16ToRawShortBits(Float16.add(Float16.valueOf(-3), Float16.multiply(Float16.valueOf(scale), Float16.valueOf((SPECIES.length()-1)))))); + } + + private static short[] + bothToArray(Float16Vector a, Float16Vector b) { + short[] r = new short[a.length() + b.length()]; + a.intoArray(r, 0); + b.intoArray(r, a.length()); + return r; + } + + @Test + static void smokeTest2() { + // Do some zipping and shuffling. + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES,0,1,false).toVector(); + assertEquals(io, io2); + Float16Vector a = io.add((short)1); //[1,2] + Float16Vector b = a.neg(); //[-1,-2] + short[] abValues = bothToArray(a,b); //[1,2,-1,-2] + VectorShuffle zip0 = VectorShuffle.makeZip(SPECIES, 0); + VectorShuffle zip1 = VectorShuffle.makeZip(SPECIES, 1); + Float16Vector zab0 = a.rearrange(zip0,b); //[1,-1] + Float16Vector zab1 = a.rearrange(zip1,b); //[2,-2] + short[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2] + // manually zip + short[] manual = new short[zabValues.length]; + for (int i = 0; i < manual.length; i += 2) { + manual[i+0] = abValues[i/2]; + manual[i+1] = abValues[a.length() + i/2]; + } + assertEquals(Arrays.toString(zabValues), Arrays.toString(manual)); + VectorShuffle unz0 = VectorShuffle.makeUnzip(SPECIES, 0); + VectorShuffle unz1 = VectorShuffle.makeUnzip(SPECIES, 1); + Float16Vector uab0 = zab0.rearrange(unz0,zab1); + Float16Vector uab1 = zab0.rearrange(unz1,zab1); + short[] abValues1 = bothToArray(uab0, uab1); + assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1)); + } + + static void iotaShuffle() { + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector(); + assertEquals(io, io2); + } + + @Test + // Test all shuffle related operations. + static void shuffleTest() { + // To test backend instructions, make sure that C2 is used. + for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) { + iotaShuffle(); + } + } + + @Test + void viewAsIntegeralLanesTest() { + Vector asIntegral = SPECIES.zero().viewAsIntegralLanes(); + VectorSpecies asIntegralSpecies = asIntegral.species(); + Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType()); + assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asIntegralSpecies.length(), SPECIES.length()); + assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES); + } + + @Test + void viewAsFloatingLanesTest() { + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + assertEquals(asFloating.species(), SPECIES); + } + + static short ADD(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::ADD); + } + + static short add(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::add); + } + + static short SUB(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void SUBFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::SUB); + } + + static short sub(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void SUBFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::SUB); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::sub); + } + + static short MUL(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MULFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::MUL); + } + + static short mul(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void MULFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::MUL); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::mul); + } + + static short DIV(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void DIVFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::DIV); + } + + static short div(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void DIVFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::DIV); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::div); + } + + static short FIRST_NONZERO(short a, short b) { + return (short)(firstNonZero(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void FIRST_NONZEROFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void FIRST_NONZEROFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector128Tests::add); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector128Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector128Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector128Tests::div); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector128TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue()).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, Float16Vector128Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector128TestsBroadcastMaskedLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector128Tests::ADD); + } + + static Float16Vector bv_MIN = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINFloat16Vector128TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector128Tests::MIN); + } + + static Float16Vector bv_min = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void minFloat16Vector128TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(bv_min).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector128Tests::min); + } + + static Float16Vector bv_MIN_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINFloat16Vector128TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector128Tests::MIN); + } + + static Float16Vector bv_MAX = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXFloat16Vector128TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector128Tests::MAX); + } + + static Float16Vector bv_max = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void maxFloat16Vector128TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(bv_max).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector128Tests::max); + } + + static Float16Vector bv_MAX_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXFloat16Vector128TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector128Tests::MAX); + } + + static short MIN(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MIN, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::MIN); + } + + static short min(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.min(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::min); + } + + static short MAX(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MAX, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::MAX); + } + + static short max(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.max(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::max); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::MIN); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::min); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::MAX); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector128Tests::max); + } + + static short ADDReduce(short[] a, int idx) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAll(short[] a) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector128Tests::ADDReduce, Float16Vector128Tests::ADDReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = ADD_IDENTITY; + + assertEquals((short) (scalar_add(id, id)), id, + "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_add(id, x)), x, + "ADD(ADD_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_add(x, id)), x, + "ADD(" + x + ", ADD_IDENTITY) != " + x); + } + } + + static short ADDReduceMasked(short[] a, int idx, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAllMasked(short[] a, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD, vmask); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector128Tests::ADDReduceMasked, Float16Vector128Tests::ADDReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + static short MULReduce(short[] a, int idx) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAll(short[] a) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector128Tests::MULReduce, Float16Vector128Tests::MULReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MUL_IDENTITY; + + assertEquals((short) (scalar_mul(id, id)), id, + "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_mul(id, x)), x, + "MUL(MUL_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_mul(x, id)), x, + "MUL(" + x + ", MUL_IDENTITY) != " + x); + } + } + + static short MULReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAllMasked(short[] a, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MULReduceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL, vmask); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector128Tests::MULReduceMasked, Float16Vector128Tests::MULReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + static short MINReduce(short[] a, int idx) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAll(short[] a) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector128Tests::MINReduce, Float16Vector128Tests::MINReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MIN_IDENTITY; + + assertEquals(scalar_min(id, id), id, + "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_min(id, x), x, + "MIN(MIN_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_min(x, id), x, + "MIN(" + x + ", MIN_IDENTITY) != " + x); + } + } + + static short MINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAllMasked(short[] a, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINReduceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN, vmask); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector128Tests::MINReduceMasked, Float16Vector128Tests::MINReduceAllMasked); + } + + static short MAXReduce(short[] a, int idx) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAll(short[] a) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector128Tests::MAXReduce, Float16Vector128Tests::MAXReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MAX_IDENTITY; + + assertEquals(scalar_max(id, id), id, + "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_max(id, x), x, + "MAX(MAX_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_max(x, id), x, + "MAX(" + x + ", MAX_IDENTITY) != " + x); + } + } + + static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAllMasked(short[] a, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXReduceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX, vmask); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector128Tests::MAXReduceMasked, Float16Vector128Tests::MAXReduceAllMasked); + } + + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector128Tests::FIRST_NONZEROReduce, Float16Vector128Tests::FIRST_NONZEROReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = FIRST_NONZERO_IDENTITY; + + assertEquals(firstNonZero(id, id), id, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, FIRST_NONZERO_IDENTITY) != FIRST_NONZERO_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(firstNonZero(id, x), x); + assertEquals(firstNonZero(x, id), x); + } + } catch (AssertionError e) { + assertEquals(firstNonZero(id, x), x, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, " + x + ") != " + x); + assertEquals(firstNonZero(x, id), x, + "FIRST_NONZERO(" + x + ", FIRST_NONZERO_IDENTITY) != " + x); + } + } + + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector128Tests::FIRST_NONZEROReduceMasked, Float16Vector128Tests::FIRST_NONZEROReduceAllMasked); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void withFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.withLane(j, b[i + j]).intoArray(r, i); + a[i + j] = b[i + j]; + j = (j + 1) & (SPECIES.length() - 1); + } + } + + + assertArraysStrictlyEquals(r, a); + } + + static boolean testIS_DEFAULT(short a) { + return bits(a)==0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_DEFAULTFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_DEFAULT(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_DEFAULTMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } + } + } + } + + static boolean testIS_NEGATIVE(short a) { + return bits(a)<0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NEGATIVEFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NEGATIVE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NEGATIVEMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } + } + } + } + + static boolean testIS_FINITE(short a) { + return isFinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_FINITEFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_FINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_FINITEMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } + } + } + } + + static boolean testIS_NAN(short a) { + return isNaN(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NANFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NAN(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NANMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } + } + } + } + + static boolean testIS_INFINITE(short a) { + return isInfinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_INFINITEFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_INFINITEMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.lt(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GTFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GTFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.eq(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void NEFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void NEFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LEFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LEFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GEFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GEFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector128TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector128TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector128TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector128TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + static short blend(short a, short b, boolean mask) { + return mask ? b : a; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector128Tests(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.blend(bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector128Tests::blend); + } + + @Test(dataProvider = "shortUnaryOpShuffleProvider") + static void RearrangeFloat16Vector128Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i)).intoArray(r, i); + } + } + + assertRearrangeArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpShuffleMaskProvider") + static void RearrangeFloat16Vector128TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i), vmask).intoArray(r, i); + } + + assertRearrangeArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void compressFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.compress(vmask).intoArray(r, i); + } + } + + assertcompressArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void expandFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.expand(vmask).intoArray(r, i); + } + } + + assertexpandArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void getFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int num_lanes = SPECIES.length(); + // Manually unroll because full unroll happens after intrinsification. + // Unroll is needed because get intrinsic requires for index to be a known constant. + if (num_lanes == 1) { + r[i]=av.lane(0); + } else if (num_lanes == 2) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + } else if (num_lanes == 4) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + } else if (num_lanes == 8) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + } else if (num_lanes == 16) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + } else if (num_lanes == 32) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + } else if (num_lanes == 64) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + r[i+32]=av.lane(32); + r[i+33]=av.lane(33); + r[i+34]=av.lane(34); + r[i+35]=av.lane(35); + r[i+36]=av.lane(36); + r[i+37]=av.lane(37); + r[i+38]=av.lane(38); + r[i+39]=av.lane(39); + r[i+40]=av.lane(40); + r[i+41]=av.lane(41); + r[i+42]=av.lane(42); + r[i+43]=av.lane(43); + r[i+44]=av.lane(44); + r[i+45]=av.lane(45); + r[i+46]=av.lane(46); + r[i+47]=av.lane(47); + r[i+48]=av.lane(48); + r[i+49]=av.lane(49); + r[i+50]=av.lane(50); + r[i+51]=av.lane(51); + r[i+52]=av.lane(52); + r[i+53]=av.lane(53); + r[i+54]=av.lane(54); + r[i+55]=av.lane(55); + r[i+56]=av.lane(56); + r[i+57]=av.lane(57); + r[i+58]=av.lane(58); + r[i+59]=av.lane(59); + r[i+60]=av.lane(60); + r[i+61]=av.lane(61); + r[i+62]=av.lane(62); + r[i+63]=av.lane(63); + } else { + for (int j = 0; j < SPECIES.length(); j++) { + r[i+j]=av.lane(j); + } + } + } + } + + assertArraysStrictlyEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void BroadcastFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, a[i]).intoArray(r, i); + } + } + + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ZeroFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.zero(SPECIES).intoArray(a, i); + } + } + + assertEquals(a, r); + } + + static short[] sliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else + res[i] = (short)0; + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sliceUnaryFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.slice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector128Tests::sliceUnary); + } + + static short[] sliceBinary(short[] a, short[] b, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void sliceBinaryFloat16Vector128TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, Float16Vector128Tests::sliceBinary); + } + + static short[] slice(short[] a, short[] b, int origin, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = mask[i] ? a[idx+i+origin] : (short)0; + else { + res[i] = mask[i] ? b[idx+j] : (short)0; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void sliceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, mask, Float16Vector128Tests::slice); + } + + static short[] unsliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i < origin) + res[i] = (short)0; + else { + res[i] = a[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void unsliceUnaryFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.unslice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector128Tests::unsliceUnary); + } + + static short[] unsliceBinary(short[] a, short[] b, int origin, int part, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (part == 0) { + if (i < origin) + res[i] = b[idx+i]; + else { + res[i] = a[idx+j]; + j++; + } + } else if (part == 1) { + if (i < origin) + res[i] = a[idx+SPECIES.length()-origin+i]; + else { + res[i] = b[idx+origin+j]; + j++; + } + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void unsliceBinaryFloat16Vector128TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, Float16Vector128Tests::unsliceBinary); + } + + static short[] unslice(short[] a, short[] b, int origin, int part, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = b[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + for (int i = 0; i < SPECIES.length(); i++){ + res[i] = mask[i] ? a[idx+i] : res[i]; + } + short[] res1 = new short[SPECIES.length()]; + if (part == 0) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = b[idx+i]; + else { + res1[i] = res[j]; + j++; + } + } + } else if (part == 1) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = res[SPECIES.length()-origin+i]; + else { + res1[i] = b[idx+origin+j]; + j++; + } + } + } + return res1; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void unsliceFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, mask, Float16Vector128Tests::unslice); + } + + static short SIN(short a) { + return (short)(scalar_sin(a)); + } + + static short strictSIN(short a) { + return (short)(strict_scalar_sin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::SIN, Float16Vector128Tests::strictSIN); + } + + static short EXP(short a) { + return (short)(scalar_exp(a)); + } + + static short strictEXP(short a) { + return (short)(strict_scalar_exp(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXP).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::EXP, Float16Vector128Tests::strictEXP); + } + + static short LOG1P(short a) { + return (short)(scalar_log1p(a)); + } + + static short strictLOG1P(short a) { + return (short)(strict_scalar_log1p(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG1PFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG1P).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::LOG1P, Float16Vector128Tests::strictLOG1P); + } + + static short LOG(short a) { + return (short)(scalar_log(a)); + } + + static short strictLOG(short a) { + return (short)(strict_scalar_log(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOGFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::LOG, Float16Vector128Tests::strictLOG); + } + + static short LOG10(short a) { + return (short)(scalar_log10(a)); + } + + static short strictLOG10(short a) { + return (short)(strict_scalar_log10(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG10Float16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG10).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::LOG10, Float16Vector128Tests::strictLOG10); + } + + static short EXPM1(short a) { + return (short)(scalar_expm1(a)); + } + + static short strictEXPM1(short a) { + return (short)(strict_scalar_expm1(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPM1Float16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXPM1).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::EXPM1, Float16Vector128Tests::strictEXPM1); + } + + static short COS(short a) { + return (short)(scalar_cos(a)); + } + + static short strictCOS(short a) { + return (short)(strict_scalar_cos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::COS, Float16Vector128Tests::strictCOS); + } + + static short TAN(short a) { + return (short)(scalar_tan(a)); + } + + static short strictTAN(short a) { + return (short)(strict_scalar_tan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::TAN, Float16Vector128Tests::strictTAN); + } + + static short SINH(short a) { + return (short)(scalar_sinh(a)); + } + + static short strictSINH(short a) { + return (short)(strict_scalar_sinh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINHFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SINH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::SINH, Float16Vector128Tests::strictSINH); + } + + static short COSH(short a) { + return (short)(scalar_cosh(a)); + } + + static short strictCOSH(short a) { + return (short)(strict_scalar_cosh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSHFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COSH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::COSH, Float16Vector128Tests::strictCOSH); + } + + static short TANH(short a) { + return (short)(scalar_tanh(a)); + } + + static short strictTANH(short a) { + return (short)(strict_scalar_tanh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANHFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TANH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::TANH, Float16Vector128Tests::strictTANH); + } + + static short ASIN(short a) { + return (short)(scalar_asin(a)); + } + + static short strictASIN(short a) { + return (short)(strict_scalar_asin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ASINFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ASIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::ASIN, Float16Vector128Tests::strictASIN); + } + + static short ACOS(short a) { + return (short)(scalar_acos(a)); + } + + static short strictACOS(short a) { + return (short)(strict_scalar_acos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ACOSFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ACOS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::ACOS, Float16Vector128Tests::strictACOS); + } + + static short ATAN(short a) { + return (short)(scalar_atan(a)); + } + + static short strictATAN(short a) { + return (short)(strict_scalar_atan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ATANFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ATAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::ATAN, Float16Vector128Tests::strictATAN); + } + + static short CBRT(short a) { + return (short)(scalar_cbrt(a)); + } + + static short strictCBRT(short a) { + return (short)(strict_scalar_cbrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void CBRTFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.CBRT).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector128Tests::CBRT, Float16Vector128Tests::strictCBRT); + } + + static short HYPOT(short a, short b) { + return (short)(scalar_hypot(a, b)); + } + + static short strictHYPOT(short a, short b) { + return (short)(strict_scalar_hypot(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void HYPOTFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.HYPOT, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector128Tests::HYPOT, Float16Vector128Tests::strictHYPOT); + } + + + static short POW(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictPOW(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.POW, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector128Tests::POW, Float16Vector128Tests::strictPOW); + } + + + static short pow(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictpow(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.pow(bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector128Tests::pow, Float16Vector128Tests::strictpow); + } + + + static short ATAN2(short a, short b) { + return (short)(scalar_atan2(a, b)); + } + + static short strictATAN2(short a, short b) { + return (short)(strict_scalar_atan2(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ATAN2Float16Vector128Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ATAN2, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector128Tests::ATAN2, Float16Vector128Tests::strictATAN2); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.POW, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector128Tests::POW, Float16Vector128Tests::strictPOW); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.pow(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector128Tests::pow, Float16Vector128Tests::strictpow); + } + + + static short FMA(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + static short fma(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector128Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector128Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.fma(bv, cv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, c, Float16Vector128Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector128TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, mask, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i]).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a, b, c, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector128TestsAltBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv).intoArray(r, i); + } + assertAltBroadcastArraysEquals(r, a, b, c, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, c, mask, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector128TestsAltBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv, vmask).intoArray(r, i); + } + + assertAltBroadcastArraysEquals(r, a, b, c, mask, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector128TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector128Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector128TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.fma(b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector128Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector128TestsDoubleBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i], vmask).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, Float16Vector128Tests::FMA); + } + + static short NEG(short a) { + return (short)(scalar_neg((short)a)); + } + + static short neg(short a) { + return (short)(scalar_neg((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void NEGFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::NEG); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void negFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.neg().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::neg); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void NEGMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector128Tests::NEG); + } + + static short ABS(short a) { + return (short)(scalar_abs((short)a)); + } + + static short abs(short a) { + return (short)(scalar_abs((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ABSFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::ABS); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void absFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.abs().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::abs); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ABSMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector128Tests::ABS); + } + + static short SQRT(short a) { + return (short)(scalar_sqrt(a)); + } + + static short sqrt(short a) { + return (short)(scalar_sqrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SQRTFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::SQRT); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sqrtFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sqrt().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::sqrt); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void SQRTMaskedFloat16Vector128Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector128Tests::SQRT); + } + + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector128Tests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat16Vector128Tests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector128Tests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat16Vector128Tests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector128TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.lt(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector128TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.eq(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shorttoIntUnaryOpProvider") + static void toIntArrayFloat16Vector128TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int[] r = av.toIntArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void toLongArrayFloat16Vector128TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + long[] r = av.toLongArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toDoubleArrayFloat16Vector128TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + double[] r = av.toDoubleArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toStringFloat16Vector128TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + String str = av.toString(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals(Arrays.toString(subarr)), "at index " + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void hashCodeFloat16Vector128TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int hash = av.hashCode(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + + static long ADDReduceLong(short[] a, int idx) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return (long)res; + } + + static long ADDReduceAllLong(short[] a) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceLongFloat16Vector128Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEquals(r, ra, a, + Float16Vector128Tests::ADDReduceLong, Float16Vector128Tests::ADDReduceAllLong); + } + + static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } + } + + return (long)res; + } + + static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceLongFloat16Vector128TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD, vmask); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEqualsMasked(r, ra, a, mask, + Float16Vector128Tests::ADDReduceLongMasked, Float16Vector128Tests::ADDReduceAllLongMasked); + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void BroadcastLongFloat16Vector128TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, shortBitsToFloat16(a[i]).longValue()).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector128TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.blend(shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + } + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector128Tests::blend); + } + + + @Test(dataProvider = "shortUnaryOpSelectFromProvider") + static void SelectFromFloat16Vector128Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortSelectFromTwoVectorOpProvider") + static void SelectFromTwoVectorFloat16Vector128Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] idx = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < idx.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector idxv = Float16Vector.fromArray(SPECIES, idx, i); + idxv.selectFrom(av, bv).intoArray(r, i); + } + } + assertSelectFromTwoVectorEquals(r, idx, a, b, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpSelectFromMaskProvider") + static void SelectFromFloat16Vector128TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av, vmask).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleMiscellaneousFloat16Vector128TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + int hash = shuffle.hashCode(); + int length = shuffle.length(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + assertEquals(length, SPECIES.length()); + } + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleToStringFloat16Vector128TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + String str = shuffle.toString(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals("Shuffle" + Arrays.toString(subarr)), "at index " + + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shuffleCompareOpProvider") + static void shuffleEqualsFloat16Vector128TestsSmokeTest(BiFunction fa, BiFunction fb) { + int[] a = fa.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + int[] b = fb.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = VectorShuffle.fromArray(SPECIES, a, i); + var bv = VectorShuffle.fromArray(SPECIES, b, i); + boolean eq = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(eq, Arrays.equals(a, i, to, b, i, to)); + } + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat16Vector128Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } + } + } + + @Test(dataProvider = "maskProvider") + static void maskHashCodeFloat16Vector128TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + int hash = vmask.hashCode(); + + boolean subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + static int maskTrueCount(boolean[] a, int idx) { + int trueCount = 0; + for (int i = idx; i < idx + SPECIES.length(); i++) { + trueCount += a[i] ? 1 : 0; + } + return trueCount; + } + + @Test(dataProvider = "maskProvider") + static void maskTrueCountFloat16Vector128TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.trueCount(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector128Tests::maskTrueCount); + } + + static int maskLastTrue(boolean[] a, int idx) { + int i = idx + SPECIES.length() - 1; + for (; i >= idx; i--) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskLastTrueFloat16Vector128TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.lastTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector128Tests::maskLastTrue); + } + + static int maskFirstTrue(boolean[] a, int idx) { + int i = idx; + for (; i < idx + SPECIES.length(); i++) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskFirstTrueFloat16Vector128TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.firstTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector128Tests::maskFirstTrue); + } + + @Test(dataProvider = "maskProvider") + static void maskCompressFloat16Vector128TestsSmokeTest(IntFunction fa) { + int trueCount = 0; + boolean[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + trueCount = vmask.trueCount(); + var rmask = vmask.compress(); + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(rmask.laneIsSet(j), j < trueCount); + } + } + } + } + + @DataProvider + public static Object[][] offsetProvider() { + return new Object[][]{ + {0}, + {-1}, + {+1}, + {+2}, + {-2}, + }; + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeFloat16Vector128TestsSmokeTest(int offset) { + int limit = SPECIES.length() * BUFFER_REPS; + for (int i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + int index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeLongFloat16Vector128TestsSmokeTest(int offset) { + long limit = SPECIES.length() * BUFFER_REPS; + for (long i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + long index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @DataProvider + public static Object[][] lengthProvider() { + return new Object[][]{ + {0}, + {1}, + {32}, + {37}, + {1024}, + {1024+1}, + {1024+5}, + }; + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundFloat16Vector128TestsSmokeTest(int length) { + int actualLoopBound = SPECIES.loopBound(length); + int expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundLongFloat16Vector128TestsSmokeTest(int _length) { + long length = _length; + long actualLoopBound = SPECIES.loopBound(length); + long expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test + static void ElementSizeFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + int elsize = av.elementSize(); + assertEquals(elsize, Float16.SIZE); + } + + @Test + static void VectorShapeFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + assert(vsh.equals(VectorShape.S_128_BIT)); + } + + @Test + static void ShapeWithLanesFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = vsh.withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void ElementTypeFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementType() == Float16.class); + } + + @Test + static void SpeciesElementSizeFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementSize() == Float16.SIZE); + } + + @Test + static void VectorTypeFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().vectorType() == av.getClass()); + } + + @Test + static void WithLanesFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorSpecies species = av.species().withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void WithShapeFloat16Vector128TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = av.species().withShape(vsh); + assert(species.equals(SPECIES)); + } + + @Test + static void MaskAllTrueFloat16Vector128TestsSmokeTest() { + for (int ic = 0; ic < INVOC_COUNT; ic++) { + assertEquals(SPECIES.maskAll(true).toLong(), -1L >>> (64 - SPECIES.length())); + } + } +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector256LoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float16Vector256LoadStoreTests.java new file mode 100644 index 00000000000..dac06d6925f --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector256LoadStoreTests.java @@ -0,0 +1,1038 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:-TieredCompilation Float16Vector256LoadStoreTests + * + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.Arena; +import java.lang.foreign.ValueLayout; +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.internal.vm.annotation.DontInline; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.nio.ByteOrder; +import java.util.List; +import java.util.function.*; + +@Test +public class Float16Vector256LoadStoreTests extends AbstractVectorLoadStoreTest { + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_256; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); + + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 256); + + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0, "at index #" + i); + } + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("short[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i * 5)); + }), + withToString("short[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1))); + }) + ); + + // Relative to array.length + static final List> INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl + 1", (int l) -> { + return l - SPECIES.length() + 1; + }), + withToString("l + speciesl - 1", (int l) -> { + return l + SPECIES.length() - 1; + }), + withToString("l + speciesl", (int l) -> { + return l + SPECIES.length(); + }), + withToString("l + speciesl + 1", (int l) -> { + return l + SPECIES.length() + 1; + }) + ); + + // Relative to byte[] array.length or MemorySegment.byteSize() + static final List> BYTE_INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl*ebsize + 1", (int l) -> { + return l - SPECIES.vectorByteSize() + 1; + }), + withToString("l + speciesl*ebsize - 1", (int l) -> { + return l + SPECIES.vectorByteSize() - 1; + }), + withToString("l + speciesl*ebsize", (int l) -> { + return l + SPECIES.vectorByteSize(); + }), + withToString("l + speciesl*ebsize + 1", (int l) -> { + return l + SPECIES.vectorByteSize() + 1; + }) + ); + + @DataProvider + public Object[][] shortProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentProvider() { + return FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, bo}; + }))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, fm, bo}; + })))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + static MemorySegment toSegment(short[] a, IntFunction fb) { + MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8); + for (int i = 0; i < a.length; i++) { + ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]); + } + return ms; + } + + static short[] segmentToArray(MemorySegment ms) { + return ms.toArray(ELEMENT_LAYOUT); + } + + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + @DontInline + static VectorShuffle shuffleFromArray(int[] a, int i) { + return SPECIES.shuffleFromArray(a, i); + } + + @DontInline + static void shuffleIntoArray(VectorShuffle s, int[] a, int i) { + s.intoArray(a, i); + } + + @DontInline + static VectorShuffle shuffleFromMemorySegment(MemorySegment mem, int i, ByteOrder bo) { + return VectorShuffle.fromMemorySegment(SPECIES, mem, i, bo); + } + + @DontInline + static void shuffleIntoMemorySegment(VectorShuffle s, MemorySegment mem, int i, ByteOrder bo) { + s.intoMemorySegment(mem, i, bo); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromArray(a, i); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i, VectorMask m) { + return Float16Vector.fromArray(SPECIES, a, i, m); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i) { + v.intoArray(a, i); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i, VectorMask m) { + v.intoArray(a, i, m); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromMemorySegment(a, i, bo); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask m) { + return Float16Vector.fromMemorySegment(SPECIES, a, i, bo, m); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo) { + v.intoMemorySegment(a, i, bo); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo, VectorMask m) { + v.intoMemorySegment(a, i, bo, m); + } + + @Test(dataProvider = "shortProvider") + static void loadStoreArray(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i); + } + } + assertEquals(r, a); + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void loadArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + fromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void storeArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMaskArray(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, vmask); + av.intoArray(r, i); + } + } + assertArraysEquals(r, a, mask); + + + r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, vmask); + } + } + assertArraysEquals(r, a, mask); + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void loadArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i, vmask); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + fromArray(a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void storeArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i, vmask); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMask(IntFunction fa, + IntFunction fm) { + boolean[] mask = fm.apply(SPECIES.length()); + boolean[] r = new boolean[mask.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < mask.length; i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, mask); + } + + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo); + } + } + long m = r.mismatch(a); + Assert.assertEquals(m, -1, "Segments not equal"); + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder()); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentMaskProvider") + static void loadStoreMemorySegmentMask(IntFunction fa, + IntFunction fb, + IntFunction fm, + ByteOrder bo) { + short[] _a = fa.apply(SPECIES.length()); + MemorySegment a = toSegment(_a, fb); + MemorySegment r = fb.apply((int) a.byteSize()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo, vmask); + av.intoMemorySegment(r, i, bo); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + + + r = fb.apply((int) a.byteSize()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo, vmask); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void storeMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreReadonlyMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly(); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true)) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false)) + ); + + VectorMask m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1) + .laneIsValid(); + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m) + ); + } + + + @Test(dataProvider = "maskProvider") + static void loadStoreMask(IntFunction fm) { + boolean[] a = fm.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask vmask = SPECIES.loadMask(a, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, a); + } + + + @Test(dataProvider = "shuffleIntProvider") + static void loadStoreShuffleArray(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = VectorShuffle.fromArray(SPECIES, a, i); + shuffle.intoArray(r, i); + } + } + + for (int i = 0; i < a.length; i++) { + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, a[i]), r[i]); + } + + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void storeShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffleIntoArray(shuffle, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + VectorShuffle shuffle = shuffleFromArray(a, index); + shuffleIntoArray(shuffle, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void loadShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffle.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + shuffleFromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntMemorySegmentProvider") + static void loadStoreShuffleMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; //An integer for every lane is read out. So 4 bytes per lane + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = VectorShuffle.fromMemorySegment(SPECIES, a, i, bo); + shuffle.intoMemorySegment(r, i, bo); + } + } + + for (int i = 0; i < l / 4; i++) { + int ai = a.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + int ri = r.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, ai), ri); + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleLoadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = shuffleFromMemorySegment(a, i, ByteOrder.nativeOrder()); + shuffle.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + shuffleFromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleStoreMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + + + // Gather/Scatter load/store tests + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], a[i + indexMap[j]]); + } + } + } catch (AssertionError e) { + assertEquals(r[j], a[i + indexMap[j]], "at index #" + j); + } + } + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0); + } + } + } catch (AssertionError e) { + assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j); + } + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + if (mask[j % SPECIES.length()]) { + expected[i + indexMap[j]] = a[j]; + } + } + } + + assertEquals(r, expected); + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + expected[i + indexMap[j]] = a[j]; + } + } + + assertEquals(r, expected); + } + + @DataProvider + public Object[][] gatherScatterProvider() { + return INT_INDEX_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] gatherScatterMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm -> + FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm, fs}; + }))). + toArray(Object[][]::new); + } + + + @Test(dataProvider = "gatherScatterProvider") + static void gather(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void gatherMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i, vmask); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b, mask); + } + + @Test(dataProvider = "gatherScatterProvider") + static void scatter(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i); + } + } + + assertScatterArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void scatterMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i, vmask); + } + } + + assertScatterArraysEquals(r, a, b, mask); + } + + + +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector256Tests.java b/test/jdk/jdk/incubator/vector/Float16Vector256Tests.java new file mode 100644 index 00000000000..a946e0d8585 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector256Tests.java @@ -0,0 +1,5887 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector + * @run testng/othervm/timeout=300 -ea -esa -Xbatch -XX:-TieredCompilation Float16Vector256Tests + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.Vector; + +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import jdk.incubator.vector.Float16Vector; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.Integer; +import java.util.List; +import java.util.Arrays; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Test +public class Float16Vector256Tests extends AbstractVectorTest { + + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_256; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + static void assertEquals(short actual, short expected, short delta) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta)); + } + static void assertEquals(short actual, short expected, short delta, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta), msg); + } + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + static void assertEquals(long actual, long expected) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected)); + } + static void assertEquals(long actual, long expected, String msg) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected), msg); + } + static void assertEquals(String actual, String expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(Object actual, Object expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + static void assertEquals(boolean actual, boolean expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(boolean actual, boolean expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + + + // Identity values for reduction operations + private static final short ADD_IDENTITY = (short)0; + private static final short FIRST_NONZERO_IDENTITY = (short)0; + private static final short MAX_IDENTITY = float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + private static final short MIN_IDENTITY = float16ToRawShortBits(Float16.POSITIVE_INFINITY); + private static final short MUL_IDENTITY = float16ToRawShortBits(Float16.valueOf(1.0f)); + + // for floating point addition reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_ADD = float16ToRawShortBits(Float16.valueOf(10.0f)); + + // for floating point multiplication reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_MUL = float16ToRawShortBits(Float16.valueOf(50.0f)); + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 256); + + static void assertArraysStrictlyEquals(short[] r, short[] a) { + for (int i = 0; i < a.length; i++) { + short ir = r[i]; + short ia = a[i]; + if (ir != ia) { + Assert.fail(String.format("at index #%d, expected = %016X, actual = %016X", i, ia, ir)); + } + } + } + + interface FUnOp { + short apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]); + } + } + + interface FUnArrayOp { + short[] apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnArrayOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a[i])); + } + } catch (AssertionError e) { + short[] ref = f.apply(a[i]); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i], "at index #" + i + ", input = " + a[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + interface FReductionOp { + short apply(short[] a, int idx); + } + + interface FReductionAllOp { + short apply(short[] a); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa) { + assertReductionArraysEquals(r, rc, a, f, fa, (short)0.0); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa, + short relativeErrorFactor) { + int i = 0; + try { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor)))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor)))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor))), "at index #" + i); + } + } + + interface FReductionMaskedOp { + short apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOp { + short apply(short[] a, boolean[] mask); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa) { + assertReductionArraysEqualsMasked(r, rc, a, mask, f, fa, (short)0.0); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa, + short relativeError) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError))))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError))))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError)))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError)))), "at index #" + i); + } + } + + interface FReductionOpLong { + long apply(short[] a, int idx); + } + + interface FReductionAllOpLong { + long apply(short[] a); + } + + static void assertReductionLongArraysEquals(long[] r, long rc, short[] a, + FReductionOpLong f, FReductionAllOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FReductionMaskedOpLong { + long apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOpLong { + long apply(short[] a, boolean[] mask); + } + + static void assertReductionLongArraysEqualsMasked(long[] r, long rc, short[] a, boolean[] mask, + FReductionMaskedOpLong f, FReductionAllMaskedOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), "at index #" + i); + } + } + + interface FBoolReductionOp { + boolean apply(boolean[] a, int idx); + } + + static void assertReductionBoolArraysEquals(boolean[] r, boolean[] a, FBoolReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FMaskReductionOp { + int apply(boolean[] a, int idx); + } + + static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+order[i+j]]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]); + } + } + + static void assertcompressArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + k], a[i + j]); + k++; + } + } + for (; k < vector_len; k++) { + assertEquals(r[i + k], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + k; + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[idx], a[i + j], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertexpandArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + j], a[i + k]); + k++; + } else { + assertEquals(r[i + j], (short)0); + } + } + } + } catch (AssertionError e) { + int idx = i + j; + if (m[idx % SPECIES.length()]) { + assertEquals(r[idx], a[i + k], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertSelectFromTwoVectorEquals(short[] r, short[] order, short[] a, short[] b, int vector_len) { + int i = 0, j = 0; + boolean is_exceptional_idx = false; + int idx = 0, wrapped_index = 0, oidx = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + idx = i + j; + wrapped_index = Math.floorMod(shortBitsToFloat16(order[idx]).intValue(), 2 * vector_len); + is_exceptional_idx = wrapped_index >= vector_len; + oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index; + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx])); + } + } + } catch (AssertionError e) { + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]), "at index #" + idx + ", order = " + order[idx] + ", a = " + a[i + oidx] + ", b = " + b[i + oidx]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a) { + int i = 0; + for (; i < a.length; i += SPECIES.length()) { + int idx = i; + for (int j = idx; j < (idx + SPECIES.length()); j++) + a[j]=a[idx]; + } + + try { + for (i = 0; i < a.length; i++) { + assertEquals(r[i], a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]); + } + } + + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + interface FBinOp { + short apply(short a, short b); + } + + interface FBinMaskOp { + short apply(short a, short b, boolean m); + + static FBinMaskOp lift(FBinOp f) { + return (a, b, m) -> m ? f.apply(a, b) : a; + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b), "(" + a[i] + ", " + b + ") at index #" + i); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())))); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue()))), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastLongArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertShiftArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", input2 = " + b[j] + ", mask = " + mask[i]); + } + } + + interface FBinConstOp { + short apply(short a); + } + + interface FBinConstMaskOp { + short apply(short a, boolean m); + + static FBinConstMaskOp lift(FBinConstOp f) { + return (a, m) -> m ? f.apply(a) : a; + } + } + + static void assertShiftConstEquals(short[] r, short[] a, FBinConstOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstOp f) { + assertShiftConstEquals(r, a, mask, FBinConstMaskOp.lift(f)); + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", mask = " + mask[i]); + } + } + + interface FTernOp { + short apply(short a, short b, short c); + } + + interface FTernMaskOp { + short apply(short a, short b, short c, boolean m); + + static FTernMaskOp lift(FTernOp f) { + return (a, b, c, m) -> m ? f.apply(a, b, c) : a; + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernOp f) { + assertArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + c[i]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertAltBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + + static boolean isWithin1Ulp(short actual, short expected) { + Float16 act = shortBitsToFloat16(actual); + Float16 exp = shortBitsToFloat16(expected); + if (Float16.isNaN(exp) && !Float16.isNaN(act)) { + return false; + } else if (!Float16.isNaN(exp) && Float16.isNaN(act)) { + return false; + } + + Float16 low = Float16.nextDown(exp); + Float16 high = Float16.nextUp(exp); + + if (Float16.compare(low, exp) > 0) { + return false; + } + + if (Float16.compare(high, exp) < 0) { + return false; + } + + return true; + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, FUnOp mathf, FUnOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i])); + } + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i])); + } + } + + static void assertBroadcastArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, + FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0 || + isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0, + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + Assert.assertTrue(isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])), + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], + b[(i / SPECIES.length()) * SPECIES.length()])); + } + } + + interface FGatherScatterOp { + short[] apply(short[] a, int ix, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, FGatherScatterOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + " at index #" + i); + } + } + + interface FGatherMaskedOp { + short[] apply(short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + interface FScatterMaskedOp { + short[] apply(short[] r, short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FGatherMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FScatterMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(r, a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(r, a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", r: " + + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + interface FLaneOp { + short[] apply(short[] a, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, int origin, FLaneOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + interface FLaneBop { + short[] apply(short[] a, short[] b, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, FLaneBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLaneMaskedBop { + short[] apply(short[] a, short[] b, int origin, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, boolean[] mask, FLaneMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLanePartBop { + short[] apply(short[] a, short[] b, int origin, int part, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, FLanePartBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + interface FLanePartMaskedBop { + short[] apply(short[] a, short[] b, int origin, int part, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, boolean[] mask, FLanePartMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + + static short convToFloat16(int i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convIntToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504); + case 1: + return convToFloat16(-65504); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> INT_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[intCornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convIntToFloat16CornerCases(i)); + }) + ); + + static void assertArraysEquals(int[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (int)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + + static short convToFloat16(long i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convLongToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504L); + case 1: + return convToFloat16(-65504L); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> LONG_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convLongToFloat16CornerCases(i)); + }) + ); + + + static void assertArraysEquals(long[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (long)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static void assertArraysEquals(double[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (double)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static short bits(short e) { + return e; + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[0.01 + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01f + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (i % 17 == 0) ? cornerCaseValue(i) : Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + // Create combinations of pairs + // @@@ Might be sensitive to order e.g. div by 0 + static final List>> FLOAT16_GENERATOR_PAIRS = + Stream.of(FLOAT16_GENERATORS.get(0)). + flatMap(fa -> FLOAT16_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_GENERATOR_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> FLOAT16_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + static final List> SELECT_FROM_INDEX_GENERATORS = List.of( + withToString("float16[0..VECLEN*2)", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(RAND.nextInt())); + }) + ); + + static final List>> FLOAT16_GENERATOR_SELECT_FROM_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> SELECT_FROM_INDEX_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortBinaryOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortIndexedOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortBinaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpProvider() { + return FLOAT16_GENERATOR_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSelectFromTwoVectorOpProvider() { + return FLOAT16_GENERATOR_SELECT_FROM_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_TRIPLES.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoIntUnaryOpProvider() { + return INT_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoLongUnaryOpProvider() { + return LONG_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleCompareOpProvider() { + return INT_SHUFFLE_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_SHUFFLE_GENERATORS = List.of( + withToStringBi("shuffle[random]", (Integer l, Integer m) -> { + short[] a = new short[l]; + int upper = m; + for (int i = 0; i < 1; i++) { + a[i] = (short)RAND.nextInt(upper); + } + return a; + }) + ); + + @DataProvider + public Object[][] shortUnaryOpSelectFromProvider() { + return FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpSelectFromMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_COMPARE_GENERATORS = List.of( + withToString("float16[i]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)i); + }), + withToString("float16[i - length / 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - (s * BUFFER_REPS / 2))); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i + 1)); + }), + withToString("float16[i - 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - 2)); + }), + withToString("float16[zigZag(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> i%3 == 0 ? (short)i : (i%3 == 1 ? (short)(i + 1) : (short)(i - 2))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + static final List>> FLOAT16_TEST_GENERATOR_ARGS = + FLOAT16_COMPARE_GENERATORS.stream(). + map(fa -> List.of(fa)). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortTestOpProvider() { + return FLOAT16_TEST_GENERATOR_ARGS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTestOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_TEST_GENERATOR_ARGS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_COMPARE_GENERATOR_PAIRS = + FLOAT16_COMPARE_GENERATORS.stream(). + flatMap(fa -> FLOAT16_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortCompareOpProvider() { + return FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortCompareOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + static short cornerCaseValue(int i) { + return switch(i % 8) { + case 0 -> float16ToRawShortBits(Float16.MAX_VALUE); + case 1 -> float16ToRawShortBits(Float16.MIN_VALUE); + case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY); + case 4 -> float16ToRawShortBits(Float16.NaN); + case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA)); + case 6 -> float16ToShortBits(Float16.valueOf(0.0f)); + default -> float16ToShortBits(Float16.valueOf(-0.0f)); + }; + } + + static final IntFunction fr = (vl) -> { + int length = BUFFER_REPS * vl; + return new short[length]; + }; + + static final IntFunction fmr = (vl) -> { + int length = BUFFER_REPS * vl; + return new boolean[length]; + }; + + static final IntFunction lfr = (vl) -> { + int length = BUFFER_REPS * vl; + return new long[length]; + }; + + static boolean eq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() == bt.floatValue(); + } + + static boolean neq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() != bt.floatValue(); + } + + static boolean lt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() < bt.floatValue(); + } + + static boolean le(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() <= bt.floatValue(); + } + + static boolean gt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() > bt.floatValue(); + } + + static boolean ge(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() >= bt.floatValue(); + } + + static short firstNonZero(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 zero = shortBitsToFloat16((short)0); + return Float16.compare(at, zero) != 0 ? a : b; + } + + static short scalar_add(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.add(at, bt)); + } + + static short scalar_sub(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.subtract(at, bt)); + } + + static short scalar_mul(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.multiply(at, bt)); + + } + static short scalar_max(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.max(at, bt)); + } + + static short scalar_min(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.min(at, bt)); + } + + static short scalar_div(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.divide(at, bt)); + } + + static short scalar_fma(short a, short b, short c) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 ct = shortBitsToFloat16(c); + return float16ToRawShortBits(Float16.fma(at, bt, ct)); + } + + static short scalar_abs(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.abs(at)); + } + + static short scalar_neg(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.negate(at)); + } + + static short scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static boolean isNaN(short a) { + return Float16.isNaN(shortBitsToFloat16(a)); + } + static boolean isFinite(short a) { + return Float16.isFinite(shortBitsToFloat16(a)); + } + static boolean isInfinite(short a) { + return Float16.isInfinite(shortBitsToFloat16(a)); + } + + @Test + static void smokeTest1() { + Float16Vector three = Float16Vector.broadcast(SPECIES, float16ToRawShortBits(Float16.valueOf(-3))); + Float16Vector three2 = (Float16Vector) SPECIES.broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three2).allTrue()); + Float16Vector three3 = three2.broadcast(float16ToRawShortBits(Float16.valueOf(1))).broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three3).allTrue()); + int scale = 2; + Class ETYPE = short.class; + if (ETYPE == double.class || ETYPE == long.class) + scale = 1000000; + else if (ETYPE == byte.class && SPECIES.length() >= 64) + scale = 1; + Float16Vector higher = three.addIndex(scale); + VectorMask m = three.compare(VectorOperators.LE, higher); + assert(m.allTrue()); + m = higher.min(float16ToRawShortBits(Float16.valueOf(-1))).test(VectorOperators.IS_NEGATIVE); + assert(m.allTrue()); + m = higher.test(VectorOperators.IS_FINITE); + assert(m.allTrue()); + short max = higher.reduceLanes(VectorOperators.MAX); + assert(max == float16ToRawShortBits(Float16.add(Float16.valueOf(-3), Float16.multiply(Float16.valueOf(scale), Float16.valueOf((SPECIES.length()-1)))))); + } + + private static short[] + bothToArray(Float16Vector a, Float16Vector b) { + short[] r = new short[a.length() + b.length()]; + a.intoArray(r, 0); + b.intoArray(r, a.length()); + return r; + } + + @Test + static void smokeTest2() { + // Do some zipping and shuffling. + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES,0,1,false).toVector(); + assertEquals(io, io2); + Float16Vector a = io.add((short)1); //[1,2] + Float16Vector b = a.neg(); //[-1,-2] + short[] abValues = bothToArray(a,b); //[1,2,-1,-2] + VectorShuffle zip0 = VectorShuffle.makeZip(SPECIES, 0); + VectorShuffle zip1 = VectorShuffle.makeZip(SPECIES, 1); + Float16Vector zab0 = a.rearrange(zip0,b); //[1,-1] + Float16Vector zab1 = a.rearrange(zip1,b); //[2,-2] + short[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2] + // manually zip + short[] manual = new short[zabValues.length]; + for (int i = 0; i < manual.length; i += 2) { + manual[i+0] = abValues[i/2]; + manual[i+1] = abValues[a.length() + i/2]; + } + assertEquals(Arrays.toString(zabValues), Arrays.toString(manual)); + VectorShuffle unz0 = VectorShuffle.makeUnzip(SPECIES, 0); + VectorShuffle unz1 = VectorShuffle.makeUnzip(SPECIES, 1); + Float16Vector uab0 = zab0.rearrange(unz0,zab1); + Float16Vector uab1 = zab0.rearrange(unz1,zab1); + short[] abValues1 = bothToArray(uab0, uab1); + assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1)); + } + + static void iotaShuffle() { + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector(); + assertEquals(io, io2); + } + + @Test + // Test all shuffle related operations. + static void shuffleTest() { + // To test backend instructions, make sure that C2 is used. + for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) { + iotaShuffle(); + } + } + + @Test + void viewAsIntegeralLanesTest() { + Vector asIntegral = SPECIES.zero().viewAsIntegralLanes(); + VectorSpecies asIntegralSpecies = asIntegral.species(); + Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType()); + assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asIntegralSpecies.length(), SPECIES.length()); + assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES); + } + + @Test + void viewAsFloatingLanesTest() { + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + assertEquals(asFloating.species(), SPECIES); + } + + static short ADD(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::ADD); + } + + static short add(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::add); + } + + static short SUB(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void SUBFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::SUB); + } + + static short sub(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void SUBFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::SUB); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::sub); + } + + static short MUL(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MULFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::MUL); + } + + static short mul(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void MULFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::MUL); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::mul); + } + + static short DIV(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void DIVFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::DIV); + } + + static short div(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void DIVFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::DIV); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::div); + } + + static short FIRST_NONZERO(short a, short b) { + return (short)(firstNonZero(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void FIRST_NONZEROFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void FIRST_NONZEROFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector256Tests::add); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector256Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector256Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector256Tests::div); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector256TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue()).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, Float16Vector256Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector256TestsBroadcastMaskedLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector256Tests::ADD); + } + + static Float16Vector bv_MIN = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINFloat16Vector256TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector256Tests::MIN); + } + + static Float16Vector bv_min = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void minFloat16Vector256TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(bv_min).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector256Tests::min); + } + + static Float16Vector bv_MIN_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINFloat16Vector256TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector256Tests::MIN); + } + + static Float16Vector bv_MAX = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXFloat16Vector256TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector256Tests::MAX); + } + + static Float16Vector bv_max = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void maxFloat16Vector256TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(bv_max).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector256Tests::max); + } + + static Float16Vector bv_MAX_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXFloat16Vector256TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector256Tests::MAX); + } + + static short MIN(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MIN, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::MIN); + } + + static short min(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.min(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::min); + } + + static short MAX(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MAX, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::MAX); + } + + static short max(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.max(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::max); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::MIN); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::min); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::MAX); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector256Tests::max); + } + + static short ADDReduce(short[] a, int idx) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAll(short[] a) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector256Tests::ADDReduce, Float16Vector256Tests::ADDReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = ADD_IDENTITY; + + assertEquals((short) (scalar_add(id, id)), id, + "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_add(id, x)), x, + "ADD(ADD_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_add(x, id)), x, + "ADD(" + x + ", ADD_IDENTITY) != " + x); + } + } + + static short ADDReduceMasked(short[] a, int idx, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAllMasked(short[] a, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD, vmask); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector256Tests::ADDReduceMasked, Float16Vector256Tests::ADDReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + static short MULReduce(short[] a, int idx) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAll(short[] a) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector256Tests::MULReduce, Float16Vector256Tests::MULReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MUL_IDENTITY; + + assertEquals((short) (scalar_mul(id, id)), id, + "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_mul(id, x)), x, + "MUL(MUL_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_mul(x, id)), x, + "MUL(" + x + ", MUL_IDENTITY) != " + x); + } + } + + static short MULReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAllMasked(short[] a, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MULReduceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL, vmask); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector256Tests::MULReduceMasked, Float16Vector256Tests::MULReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + static short MINReduce(short[] a, int idx) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAll(short[] a) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector256Tests::MINReduce, Float16Vector256Tests::MINReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MIN_IDENTITY; + + assertEquals(scalar_min(id, id), id, + "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_min(id, x), x, + "MIN(MIN_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_min(x, id), x, + "MIN(" + x + ", MIN_IDENTITY) != " + x); + } + } + + static short MINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAllMasked(short[] a, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINReduceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN, vmask); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector256Tests::MINReduceMasked, Float16Vector256Tests::MINReduceAllMasked); + } + + static short MAXReduce(short[] a, int idx) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAll(short[] a) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector256Tests::MAXReduce, Float16Vector256Tests::MAXReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MAX_IDENTITY; + + assertEquals(scalar_max(id, id), id, + "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_max(id, x), x, + "MAX(MAX_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_max(x, id), x, + "MAX(" + x + ", MAX_IDENTITY) != " + x); + } + } + + static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAllMasked(short[] a, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXReduceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX, vmask); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector256Tests::MAXReduceMasked, Float16Vector256Tests::MAXReduceAllMasked); + } + + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector256Tests::FIRST_NONZEROReduce, Float16Vector256Tests::FIRST_NONZEROReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = FIRST_NONZERO_IDENTITY; + + assertEquals(firstNonZero(id, id), id, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, FIRST_NONZERO_IDENTITY) != FIRST_NONZERO_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(firstNonZero(id, x), x); + assertEquals(firstNonZero(x, id), x); + } + } catch (AssertionError e) { + assertEquals(firstNonZero(id, x), x, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, " + x + ") != " + x); + assertEquals(firstNonZero(x, id), x, + "FIRST_NONZERO(" + x + ", FIRST_NONZERO_IDENTITY) != " + x); + } + } + + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector256Tests::FIRST_NONZEROReduceMasked, Float16Vector256Tests::FIRST_NONZEROReduceAllMasked); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void withFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.withLane(j, b[i + j]).intoArray(r, i); + a[i + j] = b[i + j]; + j = (j + 1) & (SPECIES.length() - 1); + } + } + + + assertArraysStrictlyEquals(r, a); + } + + static boolean testIS_DEFAULT(short a) { + return bits(a)==0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_DEFAULTFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_DEFAULT(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_DEFAULTMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } + } + } + } + + static boolean testIS_NEGATIVE(short a) { + return bits(a)<0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NEGATIVEFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NEGATIVE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NEGATIVEMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } + } + } + } + + static boolean testIS_FINITE(short a) { + return isFinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_FINITEFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_FINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_FINITEMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } + } + } + } + + static boolean testIS_NAN(short a) { + return isNaN(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NANFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NAN(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NANMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } + } + } + } + + static boolean testIS_INFINITE(short a) { + return isInfinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_INFINITEFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_INFINITEMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.lt(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GTFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GTFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.eq(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void NEFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void NEFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LEFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LEFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GEFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GEFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector256TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector256TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector256TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector256TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + static short blend(short a, short b, boolean mask) { + return mask ? b : a; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector256Tests(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.blend(bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector256Tests::blend); + } + + @Test(dataProvider = "shortUnaryOpShuffleProvider") + static void RearrangeFloat16Vector256Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i)).intoArray(r, i); + } + } + + assertRearrangeArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpShuffleMaskProvider") + static void RearrangeFloat16Vector256TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i), vmask).intoArray(r, i); + } + + assertRearrangeArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void compressFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.compress(vmask).intoArray(r, i); + } + } + + assertcompressArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void expandFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.expand(vmask).intoArray(r, i); + } + } + + assertexpandArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void getFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int num_lanes = SPECIES.length(); + // Manually unroll because full unroll happens after intrinsification. + // Unroll is needed because get intrinsic requires for index to be a known constant. + if (num_lanes == 1) { + r[i]=av.lane(0); + } else if (num_lanes == 2) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + } else if (num_lanes == 4) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + } else if (num_lanes == 8) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + } else if (num_lanes == 16) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + } else if (num_lanes == 32) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + } else if (num_lanes == 64) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + r[i+32]=av.lane(32); + r[i+33]=av.lane(33); + r[i+34]=av.lane(34); + r[i+35]=av.lane(35); + r[i+36]=av.lane(36); + r[i+37]=av.lane(37); + r[i+38]=av.lane(38); + r[i+39]=av.lane(39); + r[i+40]=av.lane(40); + r[i+41]=av.lane(41); + r[i+42]=av.lane(42); + r[i+43]=av.lane(43); + r[i+44]=av.lane(44); + r[i+45]=av.lane(45); + r[i+46]=av.lane(46); + r[i+47]=av.lane(47); + r[i+48]=av.lane(48); + r[i+49]=av.lane(49); + r[i+50]=av.lane(50); + r[i+51]=av.lane(51); + r[i+52]=av.lane(52); + r[i+53]=av.lane(53); + r[i+54]=av.lane(54); + r[i+55]=av.lane(55); + r[i+56]=av.lane(56); + r[i+57]=av.lane(57); + r[i+58]=av.lane(58); + r[i+59]=av.lane(59); + r[i+60]=av.lane(60); + r[i+61]=av.lane(61); + r[i+62]=av.lane(62); + r[i+63]=av.lane(63); + } else { + for (int j = 0; j < SPECIES.length(); j++) { + r[i+j]=av.lane(j); + } + } + } + } + + assertArraysStrictlyEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void BroadcastFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, a[i]).intoArray(r, i); + } + } + + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ZeroFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.zero(SPECIES).intoArray(a, i); + } + } + + assertEquals(a, r); + } + + static short[] sliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else + res[i] = (short)0; + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sliceUnaryFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.slice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector256Tests::sliceUnary); + } + + static short[] sliceBinary(short[] a, short[] b, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void sliceBinaryFloat16Vector256TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, Float16Vector256Tests::sliceBinary); + } + + static short[] slice(short[] a, short[] b, int origin, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = mask[i] ? a[idx+i+origin] : (short)0; + else { + res[i] = mask[i] ? b[idx+j] : (short)0; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void sliceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, mask, Float16Vector256Tests::slice); + } + + static short[] unsliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i < origin) + res[i] = (short)0; + else { + res[i] = a[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void unsliceUnaryFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.unslice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector256Tests::unsliceUnary); + } + + static short[] unsliceBinary(short[] a, short[] b, int origin, int part, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (part == 0) { + if (i < origin) + res[i] = b[idx+i]; + else { + res[i] = a[idx+j]; + j++; + } + } else if (part == 1) { + if (i < origin) + res[i] = a[idx+SPECIES.length()-origin+i]; + else { + res[i] = b[idx+origin+j]; + j++; + } + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void unsliceBinaryFloat16Vector256TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, Float16Vector256Tests::unsliceBinary); + } + + static short[] unslice(short[] a, short[] b, int origin, int part, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = b[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + for (int i = 0; i < SPECIES.length(); i++){ + res[i] = mask[i] ? a[idx+i] : res[i]; + } + short[] res1 = new short[SPECIES.length()]; + if (part == 0) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = b[idx+i]; + else { + res1[i] = res[j]; + j++; + } + } + } else if (part == 1) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = res[SPECIES.length()-origin+i]; + else { + res1[i] = b[idx+origin+j]; + j++; + } + } + } + return res1; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void unsliceFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, mask, Float16Vector256Tests::unslice); + } + + static short SIN(short a) { + return (short)(scalar_sin(a)); + } + + static short strictSIN(short a) { + return (short)(strict_scalar_sin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::SIN, Float16Vector256Tests::strictSIN); + } + + static short EXP(short a) { + return (short)(scalar_exp(a)); + } + + static short strictEXP(short a) { + return (short)(strict_scalar_exp(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXP).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::EXP, Float16Vector256Tests::strictEXP); + } + + static short LOG1P(short a) { + return (short)(scalar_log1p(a)); + } + + static short strictLOG1P(short a) { + return (short)(strict_scalar_log1p(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG1PFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG1P).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::LOG1P, Float16Vector256Tests::strictLOG1P); + } + + static short LOG(short a) { + return (short)(scalar_log(a)); + } + + static short strictLOG(short a) { + return (short)(strict_scalar_log(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOGFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::LOG, Float16Vector256Tests::strictLOG); + } + + static short LOG10(short a) { + return (short)(scalar_log10(a)); + } + + static short strictLOG10(short a) { + return (short)(strict_scalar_log10(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG10Float16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG10).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::LOG10, Float16Vector256Tests::strictLOG10); + } + + static short EXPM1(short a) { + return (short)(scalar_expm1(a)); + } + + static short strictEXPM1(short a) { + return (short)(strict_scalar_expm1(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPM1Float16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXPM1).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::EXPM1, Float16Vector256Tests::strictEXPM1); + } + + static short COS(short a) { + return (short)(scalar_cos(a)); + } + + static short strictCOS(short a) { + return (short)(strict_scalar_cos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::COS, Float16Vector256Tests::strictCOS); + } + + static short TAN(short a) { + return (short)(scalar_tan(a)); + } + + static short strictTAN(short a) { + return (short)(strict_scalar_tan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::TAN, Float16Vector256Tests::strictTAN); + } + + static short SINH(short a) { + return (short)(scalar_sinh(a)); + } + + static short strictSINH(short a) { + return (short)(strict_scalar_sinh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINHFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SINH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::SINH, Float16Vector256Tests::strictSINH); + } + + static short COSH(short a) { + return (short)(scalar_cosh(a)); + } + + static short strictCOSH(short a) { + return (short)(strict_scalar_cosh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSHFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COSH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::COSH, Float16Vector256Tests::strictCOSH); + } + + static short TANH(short a) { + return (short)(scalar_tanh(a)); + } + + static short strictTANH(short a) { + return (short)(strict_scalar_tanh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANHFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TANH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::TANH, Float16Vector256Tests::strictTANH); + } + + static short ASIN(short a) { + return (short)(scalar_asin(a)); + } + + static short strictASIN(short a) { + return (short)(strict_scalar_asin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ASINFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ASIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::ASIN, Float16Vector256Tests::strictASIN); + } + + static short ACOS(short a) { + return (short)(scalar_acos(a)); + } + + static short strictACOS(short a) { + return (short)(strict_scalar_acos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ACOSFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ACOS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::ACOS, Float16Vector256Tests::strictACOS); + } + + static short ATAN(short a) { + return (short)(scalar_atan(a)); + } + + static short strictATAN(short a) { + return (short)(strict_scalar_atan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ATANFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ATAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::ATAN, Float16Vector256Tests::strictATAN); + } + + static short CBRT(short a) { + return (short)(scalar_cbrt(a)); + } + + static short strictCBRT(short a) { + return (short)(strict_scalar_cbrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void CBRTFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.CBRT).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector256Tests::CBRT, Float16Vector256Tests::strictCBRT); + } + + static short HYPOT(short a, short b) { + return (short)(scalar_hypot(a, b)); + } + + static short strictHYPOT(short a, short b) { + return (short)(strict_scalar_hypot(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void HYPOTFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.HYPOT, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector256Tests::HYPOT, Float16Vector256Tests::strictHYPOT); + } + + + static short POW(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictPOW(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.POW, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector256Tests::POW, Float16Vector256Tests::strictPOW); + } + + + static short pow(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictpow(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.pow(bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector256Tests::pow, Float16Vector256Tests::strictpow); + } + + + static short ATAN2(short a, short b) { + return (short)(scalar_atan2(a, b)); + } + + static short strictATAN2(short a, short b) { + return (short)(strict_scalar_atan2(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ATAN2Float16Vector256Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ATAN2, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector256Tests::ATAN2, Float16Vector256Tests::strictATAN2); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.POW, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector256Tests::POW, Float16Vector256Tests::strictPOW); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.pow(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector256Tests::pow, Float16Vector256Tests::strictpow); + } + + + static short FMA(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + static short fma(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector256Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector256Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.fma(bv, cv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, c, Float16Vector256Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector256TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, mask, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i]).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a, b, c, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector256TestsAltBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv).intoArray(r, i); + } + assertAltBroadcastArraysEquals(r, a, b, c, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, c, mask, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector256TestsAltBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv, vmask).intoArray(r, i); + } + + assertAltBroadcastArraysEquals(r, a, b, c, mask, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector256TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector256Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector256TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.fma(b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector256Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector256TestsDoubleBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i], vmask).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, Float16Vector256Tests::FMA); + } + + static short NEG(short a) { + return (short)(scalar_neg((short)a)); + } + + static short neg(short a) { + return (short)(scalar_neg((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void NEGFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::NEG); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void negFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.neg().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::neg); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void NEGMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector256Tests::NEG); + } + + static short ABS(short a) { + return (short)(scalar_abs((short)a)); + } + + static short abs(short a) { + return (short)(scalar_abs((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ABSFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::ABS); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void absFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.abs().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::abs); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ABSMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector256Tests::ABS); + } + + static short SQRT(short a) { + return (short)(scalar_sqrt(a)); + } + + static short sqrt(short a) { + return (short)(scalar_sqrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SQRTFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::SQRT); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sqrtFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sqrt().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::sqrt); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void SQRTMaskedFloat16Vector256Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector256Tests::SQRT); + } + + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector256Tests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat16Vector256Tests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector256Tests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat16Vector256Tests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector256TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.lt(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector256TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.eq(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shorttoIntUnaryOpProvider") + static void toIntArrayFloat16Vector256TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int[] r = av.toIntArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void toLongArrayFloat16Vector256TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + long[] r = av.toLongArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toDoubleArrayFloat16Vector256TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + double[] r = av.toDoubleArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toStringFloat16Vector256TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + String str = av.toString(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals(Arrays.toString(subarr)), "at index " + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void hashCodeFloat16Vector256TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int hash = av.hashCode(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + + static long ADDReduceLong(short[] a, int idx) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return (long)res; + } + + static long ADDReduceAllLong(short[] a) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceLongFloat16Vector256Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEquals(r, ra, a, + Float16Vector256Tests::ADDReduceLong, Float16Vector256Tests::ADDReduceAllLong); + } + + static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } + } + + return (long)res; + } + + static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceLongFloat16Vector256TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD, vmask); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEqualsMasked(r, ra, a, mask, + Float16Vector256Tests::ADDReduceLongMasked, Float16Vector256Tests::ADDReduceAllLongMasked); + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void BroadcastLongFloat16Vector256TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, shortBitsToFloat16(a[i]).longValue()).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector256TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.blend(shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + } + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector256Tests::blend); + } + + + @Test(dataProvider = "shortUnaryOpSelectFromProvider") + static void SelectFromFloat16Vector256Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortSelectFromTwoVectorOpProvider") + static void SelectFromTwoVectorFloat16Vector256Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] idx = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < idx.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector idxv = Float16Vector.fromArray(SPECIES, idx, i); + idxv.selectFrom(av, bv).intoArray(r, i); + } + } + assertSelectFromTwoVectorEquals(r, idx, a, b, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpSelectFromMaskProvider") + static void SelectFromFloat16Vector256TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av, vmask).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleMiscellaneousFloat16Vector256TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + int hash = shuffle.hashCode(); + int length = shuffle.length(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + assertEquals(length, SPECIES.length()); + } + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleToStringFloat16Vector256TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + String str = shuffle.toString(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals("Shuffle" + Arrays.toString(subarr)), "at index " + + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shuffleCompareOpProvider") + static void shuffleEqualsFloat16Vector256TestsSmokeTest(BiFunction fa, BiFunction fb) { + int[] a = fa.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + int[] b = fb.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = VectorShuffle.fromArray(SPECIES, a, i); + var bv = VectorShuffle.fromArray(SPECIES, b, i); + boolean eq = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(eq, Arrays.equals(a, i, to, b, i, to)); + } + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat16Vector256Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } + } + } + + @Test(dataProvider = "maskProvider") + static void maskHashCodeFloat16Vector256TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + int hash = vmask.hashCode(); + + boolean subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + static int maskTrueCount(boolean[] a, int idx) { + int trueCount = 0; + for (int i = idx; i < idx + SPECIES.length(); i++) { + trueCount += a[i] ? 1 : 0; + } + return trueCount; + } + + @Test(dataProvider = "maskProvider") + static void maskTrueCountFloat16Vector256TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.trueCount(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector256Tests::maskTrueCount); + } + + static int maskLastTrue(boolean[] a, int idx) { + int i = idx + SPECIES.length() - 1; + for (; i >= idx; i--) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskLastTrueFloat16Vector256TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.lastTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector256Tests::maskLastTrue); + } + + static int maskFirstTrue(boolean[] a, int idx) { + int i = idx; + for (; i < idx + SPECIES.length(); i++) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskFirstTrueFloat16Vector256TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.firstTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector256Tests::maskFirstTrue); + } + + @Test(dataProvider = "maskProvider") + static void maskCompressFloat16Vector256TestsSmokeTest(IntFunction fa) { + int trueCount = 0; + boolean[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + trueCount = vmask.trueCount(); + var rmask = vmask.compress(); + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(rmask.laneIsSet(j), j < trueCount); + } + } + } + } + + @DataProvider + public static Object[][] offsetProvider() { + return new Object[][]{ + {0}, + {-1}, + {+1}, + {+2}, + {-2}, + }; + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeFloat16Vector256TestsSmokeTest(int offset) { + int limit = SPECIES.length() * BUFFER_REPS; + for (int i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + int index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeLongFloat16Vector256TestsSmokeTest(int offset) { + long limit = SPECIES.length() * BUFFER_REPS; + for (long i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + long index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @DataProvider + public static Object[][] lengthProvider() { + return new Object[][]{ + {0}, + {1}, + {32}, + {37}, + {1024}, + {1024+1}, + {1024+5}, + }; + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundFloat16Vector256TestsSmokeTest(int length) { + int actualLoopBound = SPECIES.loopBound(length); + int expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundLongFloat16Vector256TestsSmokeTest(int _length) { + long length = _length; + long actualLoopBound = SPECIES.loopBound(length); + long expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test + static void ElementSizeFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + int elsize = av.elementSize(); + assertEquals(elsize, Float16.SIZE); + } + + @Test + static void VectorShapeFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + assert(vsh.equals(VectorShape.S_256_BIT)); + } + + @Test + static void ShapeWithLanesFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = vsh.withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void ElementTypeFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementType() == Float16.class); + } + + @Test + static void SpeciesElementSizeFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementSize() == Float16.SIZE); + } + + @Test + static void VectorTypeFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().vectorType() == av.getClass()); + } + + @Test + static void WithLanesFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorSpecies species = av.species().withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void WithShapeFloat16Vector256TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = av.species().withShape(vsh); + assert(species.equals(SPECIES)); + } + + @Test + static void MaskAllTrueFloat16Vector256TestsSmokeTest() { + for (int ic = 0; ic < INVOC_COUNT; ic++) { + assertEquals(SPECIES.maskAll(true).toLong(), -1L >>> (64 - SPECIES.length())); + } + } +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector512LoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float16Vector512LoadStoreTests.java new file mode 100644 index 00000000000..401baf67361 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector512LoadStoreTests.java @@ -0,0 +1,1038 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:-TieredCompilation Float16Vector512LoadStoreTests + * + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.Arena; +import java.lang.foreign.ValueLayout; +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.internal.vm.annotation.DontInline; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.nio.ByteOrder; +import java.util.List; +import java.util.function.*; + +@Test +public class Float16Vector512LoadStoreTests extends AbstractVectorLoadStoreTest { + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_512; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); + + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 512); + + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0, "at index #" + i); + } + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("short[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i * 5)); + }), + withToString("short[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1))); + }) + ); + + // Relative to array.length + static final List> INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl + 1", (int l) -> { + return l - SPECIES.length() + 1; + }), + withToString("l + speciesl - 1", (int l) -> { + return l + SPECIES.length() - 1; + }), + withToString("l + speciesl", (int l) -> { + return l + SPECIES.length(); + }), + withToString("l + speciesl + 1", (int l) -> { + return l + SPECIES.length() + 1; + }) + ); + + // Relative to byte[] array.length or MemorySegment.byteSize() + static final List> BYTE_INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl*ebsize + 1", (int l) -> { + return l - SPECIES.vectorByteSize() + 1; + }), + withToString("l + speciesl*ebsize - 1", (int l) -> { + return l + SPECIES.vectorByteSize() - 1; + }), + withToString("l + speciesl*ebsize", (int l) -> { + return l + SPECIES.vectorByteSize(); + }), + withToString("l + speciesl*ebsize + 1", (int l) -> { + return l + SPECIES.vectorByteSize() + 1; + }) + ); + + @DataProvider + public Object[][] shortProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentProvider() { + return FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, bo}; + }))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, fm, bo}; + })))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + static MemorySegment toSegment(short[] a, IntFunction fb) { + MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8); + for (int i = 0; i < a.length; i++) { + ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]); + } + return ms; + } + + static short[] segmentToArray(MemorySegment ms) { + return ms.toArray(ELEMENT_LAYOUT); + } + + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + @DontInline + static VectorShuffle shuffleFromArray(int[] a, int i) { + return SPECIES.shuffleFromArray(a, i); + } + + @DontInline + static void shuffleIntoArray(VectorShuffle s, int[] a, int i) { + s.intoArray(a, i); + } + + @DontInline + static VectorShuffle shuffleFromMemorySegment(MemorySegment mem, int i, ByteOrder bo) { + return VectorShuffle.fromMemorySegment(SPECIES, mem, i, bo); + } + + @DontInline + static void shuffleIntoMemorySegment(VectorShuffle s, MemorySegment mem, int i, ByteOrder bo) { + s.intoMemorySegment(mem, i, bo); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromArray(a, i); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i, VectorMask m) { + return Float16Vector.fromArray(SPECIES, a, i, m); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i) { + v.intoArray(a, i); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i, VectorMask m) { + v.intoArray(a, i, m); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromMemorySegment(a, i, bo); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask m) { + return Float16Vector.fromMemorySegment(SPECIES, a, i, bo, m); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo) { + v.intoMemorySegment(a, i, bo); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo, VectorMask m) { + v.intoMemorySegment(a, i, bo, m); + } + + @Test(dataProvider = "shortProvider") + static void loadStoreArray(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i); + } + } + assertEquals(r, a); + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void loadArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + fromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void storeArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMaskArray(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, vmask); + av.intoArray(r, i); + } + } + assertArraysEquals(r, a, mask); + + + r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, vmask); + } + } + assertArraysEquals(r, a, mask); + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void loadArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i, vmask); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + fromArray(a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void storeArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i, vmask); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMask(IntFunction fa, + IntFunction fm) { + boolean[] mask = fm.apply(SPECIES.length()); + boolean[] r = new boolean[mask.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < mask.length; i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, mask); + } + + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo); + } + } + long m = r.mismatch(a); + Assert.assertEquals(m, -1, "Segments not equal"); + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder()); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentMaskProvider") + static void loadStoreMemorySegmentMask(IntFunction fa, + IntFunction fb, + IntFunction fm, + ByteOrder bo) { + short[] _a = fa.apply(SPECIES.length()); + MemorySegment a = toSegment(_a, fb); + MemorySegment r = fb.apply((int) a.byteSize()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo, vmask); + av.intoMemorySegment(r, i, bo); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + + + r = fb.apply((int) a.byteSize()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo, vmask); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void storeMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreReadonlyMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly(); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true)) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false)) + ); + + VectorMask m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1) + .laneIsValid(); + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m) + ); + } + + + @Test(dataProvider = "maskProvider") + static void loadStoreMask(IntFunction fm) { + boolean[] a = fm.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask vmask = SPECIES.loadMask(a, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, a); + } + + + @Test(dataProvider = "shuffleIntProvider") + static void loadStoreShuffleArray(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = VectorShuffle.fromArray(SPECIES, a, i); + shuffle.intoArray(r, i); + } + } + + for (int i = 0; i < a.length; i++) { + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, a[i]), r[i]); + } + + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void storeShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffleIntoArray(shuffle, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + VectorShuffle shuffle = shuffleFromArray(a, index); + shuffleIntoArray(shuffle, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void loadShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffle.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + shuffleFromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntMemorySegmentProvider") + static void loadStoreShuffleMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; //An integer for every lane is read out. So 4 bytes per lane + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = VectorShuffle.fromMemorySegment(SPECIES, a, i, bo); + shuffle.intoMemorySegment(r, i, bo); + } + } + + for (int i = 0; i < l / 4; i++) { + int ai = a.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + int ri = r.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, ai), ri); + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleLoadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = shuffleFromMemorySegment(a, i, ByteOrder.nativeOrder()); + shuffle.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + shuffleFromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleStoreMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + + + // Gather/Scatter load/store tests + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], a[i + indexMap[j]]); + } + } + } catch (AssertionError e) { + assertEquals(r[j], a[i + indexMap[j]], "at index #" + j); + } + } + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0); + } + } + } catch (AssertionError e) { + assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j); + } + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + if (mask[j % SPECIES.length()]) { + expected[i + indexMap[j]] = a[j]; + } + } + } + + assertEquals(r, expected); + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + expected[i + indexMap[j]] = a[j]; + } + } + + assertEquals(r, expected); + } + + @DataProvider + public Object[][] gatherScatterProvider() { + return INT_INDEX_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] gatherScatterMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm -> + FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm, fs}; + }))). + toArray(Object[][]::new); + } + + + @Test(dataProvider = "gatherScatterProvider") + static void gather(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void gatherMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i, vmask); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b, mask); + } + + @Test(dataProvider = "gatherScatterProvider") + static void scatter(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i); + } + } + + assertScatterArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void scatterMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i, vmask); + } + } + + assertScatterArraysEquals(r, a, b, mask); + } + + + +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector512Tests.java b/test/jdk/jdk/incubator/vector/Float16Vector512Tests.java new file mode 100644 index 00000000000..0e70b4c85ec --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector512Tests.java @@ -0,0 +1,5887 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector + * @run testng/othervm/timeout=300 -ea -esa -Xbatch -XX:-TieredCompilation Float16Vector512Tests + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.Vector; + +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import jdk.incubator.vector.Float16Vector; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.Integer; +import java.util.List; +import java.util.Arrays; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Test +public class Float16Vector512Tests extends AbstractVectorTest { + + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_512; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + static void assertEquals(short actual, short expected, short delta) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta)); + } + static void assertEquals(short actual, short expected, short delta, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta), msg); + } + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + static void assertEquals(long actual, long expected) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected)); + } + static void assertEquals(long actual, long expected, String msg) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected), msg); + } + static void assertEquals(String actual, String expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(Object actual, Object expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + static void assertEquals(boolean actual, boolean expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(boolean actual, boolean expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + + + // Identity values for reduction operations + private static final short ADD_IDENTITY = (short)0; + private static final short FIRST_NONZERO_IDENTITY = (short)0; + private static final short MAX_IDENTITY = float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + private static final short MIN_IDENTITY = float16ToRawShortBits(Float16.POSITIVE_INFINITY); + private static final short MUL_IDENTITY = float16ToRawShortBits(Float16.valueOf(1.0f)); + + // for floating point addition reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_ADD = float16ToRawShortBits(Float16.valueOf(10.0f)); + + // for floating point multiplication reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_MUL = float16ToRawShortBits(Float16.valueOf(50.0f)); + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 512); + + static void assertArraysStrictlyEquals(short[] r, short[] a) { + for (int i = 0; i < a.length; i++) { + short ir = r[i]; + short ia = a[i]; + if (ir != ia) { + Assert.fail(String.format("at index #%d, expected = %016X, actual = %016X", i, ia, ir)); + } + } + } + + interface FUnOp { + short apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]); + } + } + + interface FUnArrayOp { + short[] apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnArrayOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a[i])); + } + } catch (AssertionError e) { + short[] ref = f.apply(a[i]); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i], "at index #" + i + ", input = " + a[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + interface FReductionOp { + short apply(short[] a, int idx); + } + + interface FReductionAllOp { + short apply(short[] a); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa) { + assertReductionArraysEquals(r, rc, a, f, fa, (short)0.0); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa, + short relativeErrorFactor) { + int i = 0; + try { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor)))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor)))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor))), "at index #" + i); + } + } + + interface FReductionMaskedOp { + short apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOp { + short apply(short[] a, boolean[] mask); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa) { + assertReductionArraysEqualsMasked(r, rc, a, mask, f, fa, (short)0.0); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa, + short relativeError) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError))))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError))))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError)))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError)))), "at index #" + i); + } + } + + interface FReductionOpLong { + long apply(short[] a, int idx); + } + + interface FReductionAllOpLong { + long apply(short[] a); + } + + static void assertReductionLongArraysEquals(long[] r, long rc, short[] a, + FReductionOpLong f, FReductionAllOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FReductionMaskedOpLong { + long apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOpLong { + long apply(short[] a, boolean[] mask); + } + + static void assertReductionLongArraysEqualsMasked(long[] r, long rc, short[] a, boolean[] mask, + FReductionMaskedOpLong f, FReductionAllMaskedOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), "at index #" + i); + } + } + + interface FBoolReductionOp { + boolean apply(boolean[] a, int idx); + } + + static void assertReductionBoolArraysEquals(boolean[] r, boolean[] a, FBoolReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FMaskReductionOp { + int apply(boolean[] a, int idx); + } + + static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+order[i+j]]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]); + } + } + + static void assertcompressArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + k], a[i + j]); + k++; + } + } + for (; k < vector_len; k++) { + assertEquals(r[i + k], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + k; + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[idx], a[i + j], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertexpandArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + j], a[i + k]); + k++; + } else { + assertEquals(r[i + j], (short)0); + } + } + } + } catch (AssertionError e) { + int idx = i + j; + if (m[idx % SPECIES.length()]) { + assertEquals(r[idx], a[i + k], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertSelectFromTwoVectorEquals(short[] r, short[] order, short[] a, short[] b, int vector_len) { + int i = 0, j = 0; + boolean is_exceptional_idx = false; + int idx = 0, wrapped_index = 0, oidx = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + idx = i + j; + wrapped_index = Math.floorMod(shortBitsToFloat16(order[idx]).intValue(), 2 * vector_len); + is_exceptional_idx = wrapped_index >= vector_len; + oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index; + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx])); + } + } + } catch (AssertionError e) { + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]), "at index #" + idx + ", order = " + order[idx] + ", a = " + a[i + oidx] + ", b = " + b[i + oidx]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a) { + int i = 0; + for (; i < a.length; i += SPECIES.length()) { + int idx = i; + for (int j = idx; j < (idx + SPECIES.length()); j++) + a[j]=a[idx]; + } + + try { + for (i = 0; i < a.length; i++) { + assertEquals(r[i], a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]); + } + } + + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + interface FBinOp { + short apply(short a, short b); + } + + interface FBinMaskOp { + short apply(short a, short b, boolean m); + + static FBinMaskOp lift(FBinOp f) { + return (a, b, m) -> m ? f.apply(a, b) : a; + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b), "(" + a[i] + ", " + b + ") at index #" + i); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())))); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue()))), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastLongArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertShiftArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", input2 = " + b[j] + ", mask = " + mask[i]); + } + } + + interface FBinConstOp { + short apply(short a); + } + + interface FBinConstMaskOp { + short apply(short a, boolean m); + + static FBinConstMaskOp lift(FBinConstOp f) { + return (a, m) -> m ? f.apply(a) : a; + } + } + + static void assertShiftConstEquals(short[] r, short[] a, FBinConstOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstOp f) { + assertShiftConstEquals(r, a, mask, FBinConstMaskOp.lift(f)); + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", mask = " + mask[i]); + } + } + + interface FTernOp { + short apply(short a, short b, short c); + } + + interface FTernMaskOp { + short apply(short a, short b, short c, boolean m); + + static FTernMaskOp lift(FTernOp f) { + return (a, b, c, m) -> m ? f.apply(a, b, c) : a; + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernOp f) { + assertArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + c[i]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertAltBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + + static boolean isWithin1Ulp(short actual, short expected) { + Float16 act = shortBitsToFloat16(actual); + Float16 exp = shortBitsToFloat16(expected); + if (Float16.isNaN(exp) && !Float16.isNaN(act)) { + return false; + } else if (!Float16.isNaN(exp) && Float16.isNaN(act)) { + return false; + } + + Float16 low = Float16.nextDown(exp); + Float16 high = Float16.nextUp(exp); + + if (Float16.compare(low, exp) > 0) { + return false; + } + + if (Float16.compare(high, exp) < 0) { + return false; + } + + return true; + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, FUnOp mathf, FUnOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i])); + } + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i])); + } + } + + static void assertBroadcastArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, + FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0 || + isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0, + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + Assert.assertTrue(isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])), + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], + b[(i / SPECIES.length()) * SPECIES.length()])); + } + } + + interface FGatherScatterOp { + short[] apply(short[] a, int ix, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, FGatherScatterOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + " at index #" + i); + } + } + + interface FGatherMaskedOp { + short[] apply(short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + interface FScatterMaskedOp { + short[] apply(short[] r, short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FGatherMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FScatterMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(r, a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(r, a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", r: " + + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + interface FLaneOp { + short[] apply(short[] a, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, int origin, FLaneOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + interface FLaneBop { + short[] apply(short[] a, short[] b, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, FLaneBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLaneMaskedBop { + short[] apply(short[] a, short[] b, int origin, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, boolean[] mask, FLaneMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLanePartBop { + short[] apply(short[] a, short[] b, int origin, int part, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, FLanePartBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + interface FLanePartMaskedBop { + short[] apply(short[] a, short[] b, int origin, int part, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, boolean[] mask, FLanePartMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + + static short convToFloat16(int i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convIntToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504); + case 1: + return convToFloat16(-65504); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> INT_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[intCornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convIntToFloat16CornerCases(i)); + }) + ); + + static void assertArraysEquals(int[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (int)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + + static short convToFloat16(long i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convLongToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504L); + case 1: + return convToFloat16(-65504L); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> LONG_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convLongToFloat16CornerCases(i)); + }) + ); + + + static void assertArraysEquals(long[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (long)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static void assertArraysEquals(double[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (double)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static short bits(short e) { + return e; + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[0.01 + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01f + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (i % 17 == 0) ? cornerCaseValue(i) : Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + // Create combinations of pairs + // @@@ Might be sensitive to order e.g. div by 0 + static final List>> FLOAT16_GENERATOR_PAIRS = + Stream.of(FLOAT16_GENERATORS.get(0)). + flatMap(fa -> FLOAT16_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_GENERATOR_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> FLOAT16_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + static final List> SELECT_FROM_INDEX_GENERATORS = List.of( + withToString("float16[0..VECLEN*2)", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(RAND.nextInt())); + }) + ); + + static final List>> FLOAT16_GENERATOR_SELECT_FROM_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> SELECT_FROM_INDEX_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortBinaryOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortIndexedOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortBinaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpProvider() { + return FLOAT16_GENERATOR_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSelectFromTwoVectorOpProvider() { + return FLOAT16_GENERATOR_SELECT_FROM_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_TRIPLES.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoIntUnaryOpProvider() { + return INT_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoLongUnaryOpProvider() { + return LONG_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleCompareOpProvider() { + return INT_SHUFFLE_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_SHUFFLE_GENERATORS = List.of( + withToStringBi("shuffle[random]", (Integer l, Integer m) -> { + short[] a = new short[l]; + int upper = m; + for (int i = 0; i < 1; i++) { + a[i] = (short)RAND.nextInt(upper); + } + return a; + }) + ); + + @DataProvider + public Object[][] shortUnaryOpSelectFromProvider() { + return FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpSelectFromMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_COMPARE_GENERATORS = List.of( + withToString("float16[i]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)i); + }), + withToString("float16[i - length / 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - (s * BUFFER_REPS / 2))); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i + 1)); + }), + withToString("float16[i - 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - 2)); + }), + withToString("float16[zigZag(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> i%3 == 0 ? (short)i : (i%3 == 1 ? (short)(i + 1) : (short)(i - 2))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + static final List>> FLOAT16_TEST_GENERATOR_ARGS = + FLOAT16_COMPARE_GENERATORS.stream(). + map(fa -> List.of(fa)). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortTestOpProvider() { + return FLOAT16_TEST_GENERATOR_ARGS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTestOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_TEST_GENERATOR_ARGS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_COMPARE_GENERATOR_PAIRS = + FLOAT16_COMPARE_GENERATORS.stream(). + flatMap(fa -> FLOAT16_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortCompareOpProvider() { + return FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortCompareOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + static short cornerCaseValue(int i) { + return switch(i % 8) { + case 0 -> float16ToRawShortBits(Float16.MAX_VALUE); + case 1 -> float16ToRawShortBits(Float16.MIN_VALUE); + case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY); + case 4 -> float16ToRawShortBits(Float16.NaN); + case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA)); + case 6 -> float16ToShortBits(Float16.valueOf(0.0f)); + default -> float16ToShortBits(Float16.valueOf(-0.0f)); + }; + } + + static final IntFunction fr = (vl) -> { + int length = BUFFER_REPS * vl; + return new short[length]; + }; + + static final IntFunction fmr = (vl) -> { + int length = BUFFER_REPS * vl; + return new boolean[length]; + }; + + static final IntFunction lfr = (vl) -> { + int length = BUFFER_REPS * vl; + return new long[length]; + }; + + static boolean eq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() == bt.floatValue(); + } + + static boolean neq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() != bt.floatValue(); + } + + static boolean lt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() < bt.floatValue(); + } + + static boolean le(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() <= bt.floatValue(); + } + + static boolean gt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() > bt.floatValue(); + } + + static boolean ge(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() >= bt.floatValue(); + } + + static short firstNonZero(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 zero = shortBitsToFloat16((short)0); + return Float16.compare(at, zero) != 0 ? a : b; + } + + static short scalar_add(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.add(at, bt)); + } + + static short scalar_sub(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.subtract(at, bt)); + } + + static short scalar_mul(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.multiply(at, bt)); + + } + static short scalar_max(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.max(at, bt)); + } + + static short scalar_min(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.min(at, bt)); + } + + static short scalar_div(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.divide(at, bt)); + } + + static short scalar_fma(short a, short b, short c) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 ct = shortBitsToFloat16(c); + return float16ToRawShortBits(Float16.fma(at, bt, ct)); + } + + static short scalar_abs(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.abs(at)); + } + + static short scalar_neg(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.negate(at)); + } + + static short scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static boolean isNaN(short a) { + return Float16.isNaN(shortBitsToFloat16(a)); + } + static boolean isFinite(short a) { + return Float16.isFinite(shortBitsToFloat16(a)); + } + static boolean isInfinite(short a) { + return Float16.isInfinite(shortBitsToFloat16(a)); + } + + @Test + static void smokeTest1() { + Float16Vector three = Float16Vector.broadcast(SPECIES, float16ToRawShortBits(Float16.valueOf(-3))); + Float16Vector three2 = (Float16Vector) SPECIES.broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three2).allTrue()); + Float16Vector three3 = three2.broadcast(float16ToRawShortBits(Float16.valueOf(1))).broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three3).allTrue()); + int scale = 2; + Class ETYPE = short.class; + if (ETYPE == double.class || ETYPE == long.class) + scale = 1000000; + else if (ETYPE == byte.class && SPECIES.length() >= 64) + scale = 1; + Float16Vector higher = three.addIndex(scale); + VectorMask m = three.compare(VectorOperators.LE, higher); + assert(m.allTrue()); + m = higher.min(float16ToRawShortBits(Float16.valueOf(-1))).test(VectorOperators.IS_NEGATIVE); + assert(m.allTrue()); + m = higher.test(VectorOperators.IS_FINITE); + assert(m.allTrue()); + short max = higher.reduceLanes(VectorOperators.MAX); + assert(max == float16ToRawShortBits(Float16.add(Float16.valueOf(-3), Float16.multiply(Float16.valueOf(scale), Float16.valueOf((SPECIES.length()-1)))))); + } + + private static short[] + bothToArray(Float16Vector a, Float16Vector b) { + short[] r = new short[a.length() + b.length()]; + a.intoArray(r, 0); + b.intoArray(r, a.length()); + return r; + } + + @Test + static void smokeTest2() { + // Do some zipping and shuffling. + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES,0,1,false).toVector(); + assertEquals(io, io2); + Float16Vector a = io.add((short)1); //[1,2] + Float16Vector b = a.neg(); //[-1,-2] + short[] abValues = bothToArray(a,b); //[1,2,-1,-2] + VectorShuffle zip0 = VectorShuffle.makeZip(SPECIES, 0); + VectorShuffle zip1 = VectorShuffle.makeZip(SPECIES, 1); + Float16Vector zab0 = a.rearrange(zip0,b); //[1,-1] + Float16Vector zab1 = a.rearrange(zip1,b); //[2,-2] + short[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2] + // manually zip + short[] manual = new short[zabValues.length]; + for (int i = 0; i < manual.length; i += 2) { + manual[i+0] = abValues[i/2]; + manual[i+1] = abValues[a.length() + i/2]; + } + assertEquals(Arrays.toString(zabValues), Arrays.toString(manual)); + VectorShuffle unz0 = VectorShuffle.makeUnzip(SPECIES, 0); + VectorShuffle unz1 = VectorShuffle.makeUnzip(SPECIES, 1); + Float16Vector uab0 = zab0.rearrange(unz0,zab1); + Float16Vector uab1 = zab0.rearrange(unz1,zab1); + short[] abValues1 = bothToArray(uab0, uab1); + assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1)); + } + + static void iotaShuffle() { + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector(); + assertEquals(io, io2); + } + + @Test + // Test all shuffle related operations. + static void shuffleTest() { + // To test backend instructions, make sure that C2 is used. + for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) { + iotaShuffle(); + } + } + + @Test + void viewAsIntegeralLanesTest() { + Vector asIntegral = SPECIES.zero().viewAsIntegralLanes(); + VectorSpecies asIntegralSpecies = asIntegral.species(); + Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType()); + assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asIntegralSpecies.length(), SPECIES.length()); + assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES); + } + + @Test + void viewAsFloatingLanesTest() { + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + assertEquals(asFloating.species(), SPECIES); + } + + static short ADD(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::ADD); + } + + static short add(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::add); + } + + static short SUB(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void SUBFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::SUB); + } + + static short sub(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void SUBFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::SUB); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::sub); + } + + static short MUL(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MULFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::MUL); + } + + static short mul(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void MULFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::MUL); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::mul); + } + + static short DIV(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void DIVFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::DIV); + } + + static short div(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void DIVFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::DIV); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::div); + } + + static short FIRST_NONZERO(short a, short b) { + return (short)(firstNonZero(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void FIRST_NONZEROFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void FIRST_NONZEROFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector512Tests::add); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector512Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector512Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector512Tests::div); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector512TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue()).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, Float16Vector512Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector512TestsBroadcastMaskedLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector512Tests::ADD); + } + + static Float16Vector bv_MIN = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINFloat16Vector512TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector512Tests::MIN); + } + + static Float16Vector bv_min = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void minFloat16Vector512TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(bv_min).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector512Tests::min); + } + + static Float16Vector bv_MIN_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINFloat16Vector512TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector512Tests::MIN); + } + + static Float16Vector bv_MAX = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXFloat16Vector512TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector512Tests::MAX); + } + + static Float16Vector bv_max = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void maxFloat16Vector512TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(bv_max).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector512Tests::max); + } + + static Float16Vector bv_MAX_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXFloat16Vector512TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector512Tests::MAX); + } + + static short MIN(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MIN, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::MIN); + } + + static short min(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.min(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::min); + } + + static short MAX(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MAX, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::MAX); + } + + static short max(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.max(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::max); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::MIN); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::min); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::MAX); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector512Tests::max); + } + + static short ADDReduce(short[] a, int idx) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAll(short[] a) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector512Tests::ADDReduce, Float16Vector512Tests::ADDReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = ADD_IDENTITY; + + assertEquals((short) (scalar_add(id, id)), id, + "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_add(id, x)), x, + "ADD(ADD_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_add(x, id)), x, + "ADD(" + x + ", ADD_IDENTITY) != " + x); + } + } + + static short ADDReduceMasked(short[] a, int idx, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAllMasked(short[] a, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD, vmask); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector512Tests::ADDReduceMasked, Float16Vector512Tests::ADDReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + static short MULReduce(short[] a, int idx) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAll(short[] a) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector512Tests::MULReduce, Float16Vector512Tests::MULReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MUL_IDENTITY; + + assertEquals((short) (scalar_mul(id, id)), id, + "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_mul(id, x)), x, + "MUL(MUL_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_mul(x, id)), x, + "MUL(" + x + ", MUL_IDENTITY) != " + x); + } + } + + static short MULReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAllMasked(short[] a, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MULReduceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL, vmask); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector512Tests::MULReduceMasked, Float16Vector512Tests::MULReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + static short MINReduce(short[] a, int idx) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAll(short[] a) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector512Tests::MINReduce, Float16Vector512Tests::MINReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MIN_IDENTITY; + + assertEquals(scalar_min(id, id), id, + "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_min(id, x), x, + "MIN(MIN_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_min(x, id), x, + "MIN(" + x + ", MIN_IDENTITY) != " + x); + } + } + + static short MINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAllMasked(short[] a, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINReduceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN, vmask); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector512Tests::MINReduceMasked, Float16Vector512Tests::MINReduceAllMasked); + } + + static short MAXReduce(short[] a, int idx) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAll(short[] a) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector512Tests::MAXReduce, Float16Vector512Tests::MAXReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MAX_IDENTITY; + + assertEquals(scalar_max(id, id), id, + "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_max(id, x), x, + "MAX(MAX_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_max(x, id), x, + "MAX(" + x + ", MAX_IDENTITY) != " + x); + } + } + + static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAllMasked(short[] a, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXReduceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX, vmask); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector512Tests::MAXReduceMasked, Float16Vector512Tests::MAXReduceAllMasked); + } + + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector512Tests::FIRST_NONZEROReduce, Float16Vector512Tests::FIRST_NONZEROReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = FIRST_NONZERO_IDENTITY; + + assertEquals(firstNonZero(id, id), id, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, FIRST_NONZERO_IDENTITY) != FIRST_NONZERO_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(firstNonZero(id, x), x); + assertEquals(firstNonZero(x, id), x); + } + } catch (AssertionError e) { + assertEquals(firstNonZero(id, x), x, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, " + x + ") != " + x); + assertEquals(firstNonZero(x, id), x, + "FIRST_NONZERO(" + x + ", FIRST_NONZERO_IDENTITY) != " + x); + } + } + + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector512Tests::FIRST_NONZEROReduceMasked, Float16Vector512Tests::FIRST_NONZEROReduceAllMasked); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void withFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.withLane(j, b[i + j]).intoArray(r, i); + a[i + j] = b[i + j]; + j = (j + 1) & (SPECIES.length() - 1); + } + } + + + assertArraysStrictlyEquals(r, a); + } + + static boolean testIS_DEFAULT(short a) { + return bits(a)==0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_DEFAULTFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_DEFAULT(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_DEFAULTMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } + } + } + } + + static boolean testIS_NEGATIVE(short a) { + return bits(a)<0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NEGATIVEFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NEGATIVE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NEGATIVEMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } + } + } + } + + static boolean testIS_FINITE(short a) { + return isFinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_FINITEFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_FINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_FINITEMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } + } + } + } + + static boolean testIS_NAN(short a) { + return isNaN(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NANFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NAN(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NANMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } + } + } + } + + static boolean testIS_INFINITE(short a) { + return isInfinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_INFINITEFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_INFINITEMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.lt(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GTFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GTFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.eq(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void NEFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void NEFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LEFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LEFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GEFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GEFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector512TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector512TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector512TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector512TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + static short blend(short a, short b, boolean mask) { + return mask ? b : a; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector512Tests(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.blend(bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector512Tests::blend); + } + + @Test(dataProvider = "shortUnaryOpShuffleProvider") + static void RearrangeFloat16Vector512Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i)).intoArray(r, i); + } + } + + assertRearrangeArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpShuffleMaskProvider") + static void RearrangeFloat16Vector512TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i), vmask).intoArray(r, i); + } + + assertRearrangeArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void compressFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.compress(vmask).intoArray(r, i); + } + } + + assertcompressArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void expandFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.expand(vmask).intoArray(r, i); + } + } + + assertexpandArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void getFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int num_lanes = SPECIES.length(); + // Manually unroll because full unroll happens after intrinsification. + // Unroll is needed because get intrinsic requires for index to be a known constant. + if (num_lanes == 1) { + r[i]=av.lane(0); + } else if (num_lanes == 2) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + } else if (num_lanes == 4) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + } else if (num_lanes == 8) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + } else if (num_lanes == 16) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + } else if (num_lanes == 32) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + } else if (num_lanes == 64) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + r[i+32]=av.lane(32); + r[i+33]=av.lane(33); + r[i+34]=av.lane(34); + r[i+35]=av.lane(35); + r[i+36]=av.lane(36); + r[i+37]=av.lane(37); + r[i+38]=av.lane(38); + r[i+39]=av.lane(39); + r[i+40]=av.lane(40); + r[i+41]=av.lane(41); + r[i+42]=av.lane(42); + r[i+43]=av.lane(43); + r[i+44]=av.lane(44); + r[i+45]=av.lane(45); + r[i+46]=av.lane(46); + r[i+47]=av.lane(47); + r[i+48]=av.lane(48); + r[i+49]=av.lane(49); + r[i+50]=av.lane(50); + r[i+51]=av.lane(51); + r[i+52]=av.lane(52); + r[i+53]=av.lane(53); + r[i+54]=av.lane(54); + r[i+55]=av.lane(55); + r[i+56]=av.lane(56); + r[i+57]=av.lane(57); + r[i+58]=av.lane(58); + r[i+59]=av.lane(59); + r[i+60]=av.lane(60); + r[i+61]=av.lane(61); + r[i+62]=av.lane(62); + r[i+63]=av.lane(63); + } else { + for (int j = 0; j < SPECIES.length(); j++) { + r[i+j]=av.lane(j); + } + } + } + } + + assertArraysStrictlyEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void BroadcastFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, a[i]).intoArray(r, i); + } + } + + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ZeroFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.zero(SPECIES).intoArray(a, i); + } + } + + assertEquals(a, r); + } + + static short[] sliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else + res[i] = (short)0; + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sliceUnaryFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.slice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector512Tests::sliceUnary); + } + + static short[] sliceBinary(short[] a, short[] b, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void sliceBinaryFloat16Vector512TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, Float16Vector512Tests::sliceBinary); + } + + static short[] slice(short[] a, short[] b, int origin, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = mask[i] ? a[idx+i+origin] : (short)0; + else { + res[i] = mask[i] ? b[idx+j] : (short)0; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void sliceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, mask, Float16Vector512Tests::slice); + } + + static short[] unsliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i < origin) + res[i] = (short)0; + else { + res[i] = a[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void unsliceUnaryFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.unslice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector512Tests::unsliceUnary); + } + + static short[] unsliceBinary(short[] a, short[] b, int origin, int part, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (part == 0) { + if (i < origin) + res[i] = b[idx+i]; + else { + res[i] = a[idx+j]; + j++; + } + } else if (part == 1) { + if (i < origin) + res[i] = a[idx+SPECIES.length()-origin+i]; + else { + res[i] = b[idx+origin+j]; + j++; + } + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void unsliceBinaryFloat16Vector512TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, Float16Vector512Tests::unsliceBinary); + } + + static short[] unslice(short[] a, short[] b, int origin, int part, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = b[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + for (int i = 0; i < SPECIES.length(); i++){ + res[i] = mask[i] ? a[idx+i] : res[i]; + } + short[] res1 = new short[SPECIES.length()]; + if (part == 0) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = b[idx+i]; + else { + res1[i] = res[j]; + j++; + } + } + } else if (part == 1) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = res[SPECIES.length()-origin+i]; + else { + res1[i] = b[idx+origin+j]; + j++; + } + } + } + return res1; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void unsliceFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, mask, Float16Vector512Tests::unslice); + } + + static short SIN(short a) { + return (short)(scalar_sin(a)); + } + + static short strictSIN(short a) { + return (short)(strict_scalar_sin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::SIN, Float16Vector512Tests::strictSIN); + } + + static short EXP(short a) { + return (short)(scalar_exp(a)); + } + + static short strictEXP(short a) { + return (short)(strict_scalar_exp(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXP).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::EXP, Float16Vector512Tests::strictEXP); + } + + static short LOG1P(short a) { + return (short)(scalar_log1p(a)); + } + + static short strictLOG1P(short a) { + return (short)(strict_scalar_log1p(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG1PFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG1P).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::LOG1P, Float16Vector512Tests::strictLOG1P); + } + + static short LOG(short a) { + return (short)(scalar_log(a)); + } + + static short strictLOG(short a) { + return (short)(strict_scalar_log(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOGFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::LOG, Float16Vector512Tests::strictLOG); + } + + static short LOG10(short a) { + return (short)(scalar_log10(a)); + } + + static short strictLOG10(short a) { + return (short)(strict_scalar_log10(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG10Float16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG10).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::LOG10, Float16Vector512Tests::strictLOG10); + } + + static short EXPM1(short a) { + return (short)(scalar_expm1(a)); + } + + static short strictEXPM1(short a) { + return (short)(strict_scalar_expm1(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPM1Float16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXPM1).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::EXPM1, Float16Vector512Tests::strictEXPM1); + } + + static short COS(short a) { + return (short)(scalar_cos(a)); + } + + static short strictCOS(short a) { + return (short)(strict_scalar_cos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::COS, Float16Vector512Tests::strictCOS); + } + + static short TAN(short a) { + return (short)(scalar_tan(a)); + } + + static short strictTAN(short a) { + return (short)(strict_scalar_tan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::TAN, Float16Vector512Tests::strictTAN); + } + + static short SINH(short a) { + return (short)(scalar_sinh(a)); + } + + static short strictSINH(short a) { + return (short)(strict_scalar_sinh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINHFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SINH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::SINH, Float16Vector512Tests::strictSINH); + } + + static short COSH(short a) { + return (short)(scalar_cosh(a)); + } + + static short strictCOSH(short a) { + return (short)(strict_scalar_cosh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSHFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COSH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::COSH, Float16Vector512Tests::strictCOSH); + } + + static short TANH(short a) { + return (short)(scalar_tanh(a)); + } + + static short strictTANH(short a) { + return (short)(strict_scalar_tanh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANHFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TANH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::TANH, Float16Vector512Tests::strictTANH); + } + + static short ASIN(short a) { + return (short)(scalar_asin(a)); + } + + static short strictASIN(short a) { + return (short)(strict_scalar_asin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ASINFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ASIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::ASIN, Float16Vector512Tests::strictASIN); + } + + static short ACOS(short a) { + return (short)(scalar_acos(a)); + } + + static short strictACOS(short a) { + return (short)(strict_scalar_acos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ACOSFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ACOS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::ACOS, Float16Vector512Tests::strictACOS); + } + + static short ATAN(short a) { + return (short)(scalar_atan(a)); + } + + static short strictATAN(short a) { + return (short)(strict_scalar_atan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ATANFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ATAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::ATAN, Float16Vector512Tests::strictATAN); + } + + static short CBRT(short a) { + return (short)(scalar_cbrt(a)); + } + + static short strictCBRT(short a) { + return (short)(strict_scalar_cbrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void CBRTFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.CBRT).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector512Tests::CBRT, Float16Vector512Tests::strictCBRT); + } + + static short HYPOT(short a, short b) { + return (short)(scalar_hypot(a, b)); + } + + static short strictHYPOT(short a, short b) { + return (short)(strict_scalar_hypot(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void HYPOTFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.HYPOT, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector512Tests::HYPOT, Float16Vector512Tests::strictHYPOT); + } + + + static short POW(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictPOW(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.POW, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector512Tests::POW, Float16Vector512Tests::strictPOW); + } + + + static short pow(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictpow(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.pow(bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector512Tests::pow, Float16Vector512Tests::strictpow); + } + + + static short ATAN2(short a, short b) { + return (short)(scalar_atan2(a, b)); + } + + static short strictATAN2(short a, short b) { + return (short)(strict_scalar_atan2(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ATAN2Float16Vector512Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ATAN2, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector512Tests::ATAN2, Float16Vector512Tests::strictATAN2); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.POW, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector512Tests::POW, Float16Vector512Tests::strictPOW); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.pow(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector512Tests::pow, Float16Vector512Tests::strictpow); + } + + + static short FMA(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + static short fma(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector512Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector512Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.fma(bv, cv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, c, Float16Vector512Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector512TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, mask, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i]).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a, b, c, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector512TestsAltBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv).intoArray(r, i); + } + assertAltBroadcastArraysEquals(r, a, b, c, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, c, mask, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector512TestsAltBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv, vmask).intoArray(r, i); + } + + assertAltBroadcastArraysEquals(r, a, b, c, mask, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector512TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector512Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector512TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.fma(b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector512Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector512TestsDoubleBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i], vmask).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, Float16Vector512Tests::FMA); + } + + static short NEG(short a) { + return (short)(scalar_neg((short)a)); + } + + static short neg(short a) { + return (short)(scalar_neg((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void NEGFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::NEG); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void negFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.neg().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::neg); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void NEGMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector512Tests::NEG); + } + + static short ABS(short a) { + return (short)(scalar_abs((short)a)); + } + + static short abs(short a) { + return (short)(scalar_abs((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ABSFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::ABS); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void absFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.abs().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::abs); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ABSMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector512Tests::ABS); + } + + static short SQRT(short a) { + return (short)(scalar_sqrt(a)); + } + + static short sqrt(short a) { + return (short)(scalar_sqrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SQRTFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::SQRT); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sqrtFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sqrt().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::sqrt); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void SQRTMaskedFloat16Vector512Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector512Tests::SQRT); + } + + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector512Tests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat16Vector512Tests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector512Tests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat16Vector512Tests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector512TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.lt(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector512TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.eq(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shorttoIntUnaryOpProvider") + static void toIntArrayFloat16Vector512TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int[] r = av.toIntArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void toLongArrayFloat16Vector512TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + long[] r = av.toLongArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toDoubleArrayFloat16Vector512TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + double[] r = av.toDoubleArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toStringFloat16Vector512TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + String str = av.toString(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals(Arrays.toString(subarr)), "at index " + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void hashCodeFloat16Vector512TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int hash = av.hashCode(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + + static long ADDReduceLong(short[] a, int idx) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return (long)res; + } + + static long ADDReduceAllLong(short[] a) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceLongFloat16Vector512Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEquals(r, ra, a, + Float16Vector512Tests::ADDReduceLong, Float16Vector512Tests::ADDReduceAllLong); + } + + static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } + } + + return (long)res; + } + + static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceLongFloat16Vector512TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD, vmask); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEqualsMasked(r, ra, a, mask, + Float16Vector512Tests::ADDReduceLongMasked, Float16Vector512Tests::ADDReduceAllLongMasked); + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void BroadcastLongFloat16Vector512TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, shortBitsToFloat16(a[i]).longValue()).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector512TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.blend(shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + } + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector512Tests::blend); + } + + + @Test(dataProvider = "shortUnaryOpSelectFromProvider") + static void SelectFromFloat16Vector512Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortSelectFromTwoVectorOpProvider") + static void SelectFromTwoVectorFloat16Vector512Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] idx = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < idx.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector idxv = Float16Vector.fromArray(SPECIES, idx, i); + idxv.selectFrom(av, bv).intoArray(r, i); + } + } + assertSelectFromTwoVectorEquals(r, idx, a, b, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpSelectFromMaskProvider") + static void SelectFromFloat16Vector512TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av, vmask).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleMiscellaneousFloat16Vector512TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + int hash = shuffle.hashCode(); + int length = shuffle.length(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + assertEquals(length, SPECIES.length()); + } + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleToStringFloat16Vector512TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + String str = shuffle.toString(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals("Shuffle" + Arrays.toString(subarr)), "at index " + + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shuffleCompareOpProvider") + static void shuffleEqualsFloat16Vector512TestsSmokeTest(BiFunction fa, BiFunction fb) { + int[] a = fa.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + int[] b = fb.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = VectorShuffle.fromArray(SPECIES, a, i); + var bv = VectorShuffle.fromArray(SPECIES, b, i); + boolean eq = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(eq, Arrays.equals(a, i, to, b, i, to)); + } + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat16Vector512Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } + } + } + + @Test(dataProvider = "maskProvider") + static void maskHashCodeFloat16Vector512TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + int hash = vmask.hashCode(); + + boolean subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + static int maskTrueCount(boolean[] a, int idx) { + int trueCount = 0; + for (int i = idx; i < idx + SPECIES.length(); i++) { + trueCount += a[i] ? 1 : 0; + } + return trueCount; + } + + @Test(dataProvider = "maskProvider") + static void maskTrueCountFloat16Vector512TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.trueCount(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector512Tests::maskTrueCount); + } + + static int maskLastTrue(boolean[] a, int idx) { + int i = idx + SPECIES.length() - 1; + for (; i >= idx; i--) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskLastTrueFloat16Vector512TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.lastTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector512Tests::maskLastTrue); + } + + static int maskFirstTrue(boolean[] a, int idx) { + int i = idx; + for (; i < idx + SPECIES.length(); i++) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskFirstTrueFloat16Vector512TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.firstTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector512Tests::maskFirstTrue); + } + + @Test(dataProvider = "maskProvider") + static void maskCompressFloat16Vector512TestsSmokeTest(IntFunction fa) { + int trueCount = 0; + boolean[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + trueCount = vmask.trueCount(); + var rmask = vmask.compress(); + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(rmask.laneIsSet(j), j < trueCount); + } + } + } + } + + @DataProvider + public static Object[][] offsetProvider() { + return new Object[][]{ + {0}, + {-1}, + {+1}, + {+2}, + {-2}, + }; + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeFloat16Vector512TestsSmokeTest(int offset) { + int limit = SPECIES.length() * BUFFER_REPS; + for (int i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + int index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeLongFloat16Vector512TestsSmokeTest(int offset) { + long limit = SPECIES.length() * BUFFER_REPS; + for (long i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + long index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @DataProvider + public static Object[][] lengthProvider() { + return new Object[][]{ + {0}, + {1}, + {32}, + {37}, + {1024}, + {1024+1}, + {1024+5}, + }; + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundFloat16Vector512TestsSmokeTest(int length) { + int actualLoopBound = SPECIES.loopBound(length); + int expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundLongFloat16Vector512TestsSmokeTest(int _length) { + long length = _length; + long actualLoopBound = SPECIES.loopBound(length); + long expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test + static void ElementSizeFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + int elsize = av.elementSize(); + assertEquals(elsize, Float16.SIZE); + } + + @Test + static void VectorShapeFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + assert(vsh.equals(VectorShape.S_512_BIT)); + } + + @Test + static void ShapeWithLanesFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = vsh.withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void ElementTypeFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementType() == Float16.class); + } + + @Test + static void SpeciesElementSizeFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementSize() == Float16.SIZE); + } + + @Test + static void VectorTypeFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().vectorType() == av.getClass()); + } + + @Test + static void WithLanesFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorSpecies species = av.species().withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void WithShapeFloat16Vector512TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = av.species().withShape(vsh); + assert(species.equals(SPECIES)); + } + + @Test + static void MaskAllTrueFloat16Vector512TestsSmokeTest() { + for (int ic = 0; ic < INVOC_COUNT; ic++) { + assertEquals(SPECIES.maskAll(true).toLong(), -1L >>> (64 - SPECIES.length())); + } + } +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector64LoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float16Vector64LoadStoreTests.java new file mode 100644 index 00000000000..83befc161a5 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector64LoadStoreTests.java @@ -0,0 +1,1038 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:-TieredCompilation Float16Vector64LoadStoreTests + * + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.Arena; +import java.lang.foreign.ValueLayout; +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.internal.vm.annotation.DontInline; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.nio.ByteOrder; +import java.util.List; +import java.util.function.*; + +@Test +public class Float16Vector64LoadStoreTests extends AbstractVectorLoadStoreTest { + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_64; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); + + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 64); + + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0, "at index #" + i); + } + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("short[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i * 5)); + }), + withToString("short[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1))); + }) + ); + + // Relative to array.length + static final List> INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl + 1", (int l) -> { + return l - SPECIES.length() + 1; + }), + withToString("l + speciesl - 1", (int l) -> { + return l + SPECIES.length() - 1; + }), + withToString("l + speciesl", (int l) -> { + return l + SPECIES.length(); + }), + withToString("l + speciesl + 1", (int l) -> { + return l + SPECIES.length() + 1; + }) + ); + + // Relative to byte[] array.length or MemorySegment.byteSize() + static final List> BYTE_INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl*ebsize + 1", (int l) -> { + return l - SPECIES.vectorByteSize() + 1; + }), + withToString("l + speciesl*ebsize - 1", (int l) -> { + return l + SPECIES.vectorByteSize() - 1; + }), + withToString("l + speciesl*ebsize", (int l) -> { + return l + SPECIES.vectorByteSize(); + }), + withToString("l + speciesl*ebsize + 1", (int l) -> { + return l + SPECIES.vectorByteSize() + 1; + }) + ); + + @DataProvider + public Object[][] shortProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentProvider() { + return FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, bo}; + }))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, fm, bo}; + })))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + static MemorySegment toSegment(short[] a, IntFunction fb) { + MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8); + for (int i = 0; i < a.length; i++) { + ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]); + } + return ms; + } + + static short[] segmentToArray(MemorySegment ms) { + return ms.toArray(ELEMENT_LAYOUT); + } + + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + @DontInline + static VectorShuffle shuffleFromArray(int[] a, int i) { + return SPECIES.shuffleFromArray(a, i); + } + + @DontInline + static void shuffleIntoArray(VectorShuffle s, int[] a, int i) { + s.intoArray(a, i); + } + + @DontInline + static VectorShuffle shuffleFromMemorySegment(MemorySegment mem, int i, ByteOrder bo) { + return VectorShuffle.fromMemorySegment(SPECIES, mem, i, bo); + } + + @DontInline + static void shuffleIntoMemorySegment(VectorShuffle s, MemorySegment mem, int i, ByteOrder bo) { + s.intoMemorySegment(mem, i, bo); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromArray(a, i); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i, VectorMask m) { + return Float16Vector.fromArray(SPECIES, a, i, m); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i) { + v.intoArray(a, i); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i, VectorMask m) { + v.intoArray(a, i, m); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromMemorySegment(a, i, bo); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask m) { + return Float16Vector.fromMemorySegment(SPECIES, a, i, bo, m); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo) { + v.intoMemorySegment(a, i, bo); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo, VectorMask m) { + v.intoMemorySegment(a, i, bo, m); + } + + @Test(dataProvider = "shortProvider") + static void loadStoreArray(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i); + } + } + assertEquals(r, a); + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void loadArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + fromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void storeArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMaskArray(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, vmask); + av.intoArray(r, i); + } + } + assertArraysEquals(r, a, mask); + + + r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, vmask); + } + } + assertArraysEquals(r, a, mask); + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void loadArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i, vmask); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + fromArray(a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void storeArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i, vmask); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMask(IntFunction fa, + IntFunction fm) { + boolean[] mask = fm.apply(SPECIES.length()); + boolean[] r = new boolean[mask.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < mask.length; i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, mask); + } + + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo); + } + } + long m = r.mismatch(a); + Assert.assertEquals(m, -1, "Segments not equal"); + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder()); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentMaskProvider") + static void loadStoreMemorySegmentMask(IntFunction fa, + IntFunction fb, + IntFunction fm, + ByteOrder bo) { + short[] _a = fa.apply(SPECIES.length()); + MemorySegment a = toSegment(_a, fb); + MemorySegment r = fb.apply((int) a.byteSize()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo, vmask); + av.intoMemorySegment(r, i, bo); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + + + r = fb.apply((int) a.byteSize()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo, vmask); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void storeMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreReadonlyMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly(); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true)) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false)) + ); + + VectorMask m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1) + .laneIsValid(); + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m) + ); + } + + + @Test(dataProvider = "maskProvider") + static void loadStoreMask(IntFunction fm) { + boolean[] a = fm.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask vmask = SPECIES.loadMask(a, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, a); + } + + + @Test(dataProvider = "shuffleIntProvider") + static void loadStoreShuffleArray(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = VectorShuffle.fromArray(SPECIES, a, i); + shuffle.intoArray(r, i); + } + } + + for (int i = 0; i < a.length; i++) { + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, a[i]), r[i]); + } + + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void storeShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffleIntoArray(shuffle, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + VectorShuffle shuffle = shuffleFromArray(a, index); + shuffleIntoArray(shuffle, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void loadShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffle.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + shuffleFromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntMemorySegmentProvider") + static void loadStoreShuffleMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; //An integer for every lane is read out. So 4 bytes per lane + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = VectorShuffle.fromMemorySegment(SPECIES, a, i, bo); + shuffle.intoMemorySegment(r, i, bo); + } + } + + for (int i = 0; i < l / 4; i++) { + int ai = a.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + int ri = r.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, ai), ri); + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleLoadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = shuffleFromMemorySegment(a, i, ByteOrder.nativeOrder()); + shuffle.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + shuffleFromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleStoreMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + + + // Gather/Scatter load/store tests + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], a[i + indexMap[j]]); + } + } + } catch (AssertionError e) { + assertEquals(r[j], a[i + indexMap[j]], "at index #" + j); + } + } + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0); + } + } + } catch (AssertionError e) { + assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j); + } + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + if (mask[j % SPECIES.length()]) { + expected[i + indexMap[j]] = a[j]; + } + } + } + + assertEquals(r, expected); + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + expected[i + indexMap[j]] = a[j]; + } + } + + assertEquals(r, expected); + } + + @DataProvider + public Object[][] gatherScatterProvider() { + return INT_INDEX_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] gatherScatterMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm -> + FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm, fs}; + }))). + toArray(Object[][]::new); + } + + + @Test(dataProvider = "gatherScatterProvider") + static void gather(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void gatherMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i, vmask); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b, mask); + } + + @Test(dataProvider = "gatherScatterProvider") + static void scatter(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i); + } + } + + assertScatterArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void scatterMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i, vmask); + } + } + + assertScatterArraysEquals(r, a, b, mask); + } + + + +} diff --git a/test/jdk/jdk/incubator/vector/Float16Vector64Tests.java b/test/jdk/jdk/incubator/vector/Float16Vector64Tests.java new file mode 100644 index 00000000000..94017042b7b --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16Vector64Tests.java @@ -0,0 +1,5887 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector + * @run testng/othervm/timeout=300 -ea -esa -Xbatch -XX:-TieredCompilation Float16Vector64Tests + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.Vector; + +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import jdk.incubator.vector.Float16Vector; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.Integer; +import java.util.List; +import java.util.Arrays; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Test +public class Float16Vector64Tests extends AbstractVectorTest { + + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_64; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + static void assertEquals(short actual, short expected, short delta) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta)); + } + static void assertEquals(short actual, short expected, short delta, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta), msg); + } + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + static void assertEquals(long actual, long expected) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected)); + } + static void assertEquals(long actual, long expected, String msg) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected), msg); + } + static void assertEquals(String actual, String expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(Object actual, Object expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + static void assertEquals(boolean actual, boolean expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(boolean actual, boolean expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + + + // Identity values for reduction operations + private static final short ADD_IDENTITY = (short)0; + private static final short FIRST_NONZERO_IDENTITY = (short)0; + private static final short MAX_IDENTITY = float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + private static final short MIN_IDENTITY = float16ToRawShortBits(Float16.POSITIVE_INFINITY); + private static final short MUL_IDENTITY = float16ToRawShortBits(Float16.valueOf(1.0f)); + + // for floating point addition reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_ADD = float16ToRawShortBits(Float16.valueOf(10.0f)); + + // for floating point multiplication reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_MUL = float16ToRawShortBits(Float16.valueOf(50.0f)); + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 64); + + static void assertArraysStrictlyEquals(short[] r, short[] a) { + for (int i = 0; i < a.length; i++) { + short ir = r[i]; + short ia = a[i]; + if (ir != ia) { + Assert.fail(String.format("at index #%d, expected = %016X, actual = %016X", i, ia, ir)); + } + } + } + + interface FUnOp { + short apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]); + } + } + + interface FUnArrayOp { + short[] apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnArrayOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a[i])); + } + } catch (AssertionError e) { + short[] ref = f.apply(a[i]); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i], "at index #" + i + ", input = " + a[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + interface FReductionOp { + short apply(short[] a, int idx); + } + + interface FReductionAllOp { + short apply(short[] a); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa) { + assertReductionArraysEquals(r, rc, a, f, fa, (short)0.0); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa, + short relativeErrorFactor) { + int i = 0; + try { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor)))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor)))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor))), "at index #" + i); + } + } + + interface FReductionMaskedOp { + short apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOp { + short apply(short[] a, boolean[] mask); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa) { + assertReductionArraysEqualsMasked(r, rc, a, mask, f, fa, (short)0.0); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa, + short relativeError) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError))))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError))))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError)))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError)))), "at index #" + i); + } + } + + interface FReductionOpLong { + long apply(short[] a, int idx); + } + + interface FReductionAllOpLong { + long apply(short[] a); + } + + static void assertReductionLongArraysEquals(long[] r, long rc, short[] a, + FReductionOpLong f, FReductionAllOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FReductionMaskedOpLong { + long apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOpLong { + long apply(short[] a, boolean[] mask); + } + + static void assertReductionLongArraysEqualsMasked(long[] r, long rc, short[] a, boolean[] mask, + FReductionMaskedOpLong f, FReductionAllMaskedOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), "at index #" + i); + } + } + + interface FBoolReductionOp { + boolean apply(boolean[] a, int idx); + } + + static void assertReductionBoolArraysEquals(boolean[] r, boolean[] a, FBoolReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FMaskReductionOp { + int apply(boolean[] a, int idx); + } + + static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+order[i+j]]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]); + } + } + + static void assertcompressArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + k], a[i + j]); + k++; + } + } + for (; k < vector_len; k++) { + assertEquals(r[i + k], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + k; + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[idx], a[i + j], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertexpandArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + j], a[i + k]); + k++; + } else { + assertEquals(r[i + j], (short)0); + } + } + } + } catch (AssertionError e) { + int idx = i + j; + if (m[idx % SPECIES.length()]) { + assertEquals(r[idx], a[i + k], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertSelectFromTwoVectorEquals(short[] r, short[] order, short[] a, short[] b, int vector_len) { + int i = 0, j = 0; + boolean is_exceptional_idx = false; + int idx = 0, wrapped_index = 0, oidx = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + idx = i + j; + wrapped_index = Math.floorMod(shortBitsToFloat16(order[idx]).intValue(), 2 * vector_len); + is_exceptional_idx = wrapped_index >= vector_len; + oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index; + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx])); + } + } + } catch (AssertionError e) { + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]), "at index #" + idx + ", order = " + order[idx] + ", a = " + a[i + oidx] + ", b = " + b[i + oidx]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a) { + int i = 0; + for (; i < a.length; i += SPECIES.length()) { + int idx = i; + for (int j = idx; j < (idx + SPECIES.length()); j++) + a[j]=a[idx]; + } + + try { + for (i = 0; i < a.length; i++) { + assertEquals(r[i], a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]); + } + } + + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + interface FBinOp { + short apply(short a, short b); + } + + interface FBinMaskOp { + short apply(short a, short b, boolean m); + + static FBinMaskOp lift(FBinOp f) { + return (a, b, m) -> m ? f.apply(a, b) : a; + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b), "(" + a[i] + ", " + b + ") at index #" + i); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())))); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue()))), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastLongArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertShiftArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", input2 = " + b[j] + ", mask = " + mask[i]); + } + } + + interface FBinConstOp { + short apply(short a); + } + + interface FBinConstMaskOp { + short apply(short a, boolean m); + + static FBinConstMaskOp lift(FBinConstOp f) { + return (a, m) -> m ? f.apply(a) : a; + } + } + + static void assertShiftConstEquals(short[] r, short[] a, FBinConstOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstOp f) { + assertShiftConstEquals(r, a, mask, FBinConstMaskOp.lift(f)); + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", mask = " + mask[i]); + } + } + + interface FTernOp { + short apply(short a, short b, short c); + } + + interface FTernMaskOp { + short apply(short a, short b, short c, boolean m); + + static FTernMaskOp lift(FTernOp f) { + return (a, b, c, m) -> m ? f.apply(a, b, c) : a; + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernOp f) { + assertArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + c[i]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertAltBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + + static boolean isWithin1Ulp(short actual, short expected) { + Float16 act = shortBitsToFloat16(actual); + Float16 exp = shortBitsToFloat16(expected); + if (Float16.isNaN(exp) && !Float16.isNaN(act)) { + return false; + } else if (!Float16.isNaN(exp) && Float16.isNaN(act)) { + return false; + } + + Float16 low = Float16.nextDown(exp); + Float16 high = Float16.nextUp(exp); + + if (Float16.compare(low, exp) > 0) { + return false; + } + + if (Float16.compare(high, exp) < 0) { + return false; + } + + return true; + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, FUnOp mathf, FUnOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i])); + } + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i])); + } + } + + static void assertBroadcastArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, + FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0 || + isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0, + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + Assert.assertTrue(isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])), + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], + b[(i / SPECIES.length()) * SPECIES.length()])); + } + } + + interface FGatherScatterOp { + short[] apply(short[] a, int ix, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, FGatherScatterOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + " at index #" + i); + } + } + + interface FGatherMaskedOp { + short[] apply(short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + interface FScatterMaskedOp { + short[] apply(short[] r, short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FGatherMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FScatterMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(r, a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(r, a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", r: " + + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + interface FLaneOp { + short[] apply(short[] a, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, int origin, FLaneOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + interface FLaneBop { + short[] apply(short[] a, short[] b, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, FLaneBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLaneMaskedBop { + short[] apply(short[] a, short[] b, int origin, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, boolean[] mask, FLaneMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLanePartBop { + short[] apply(short[] a, short[] b, int origin, int part, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, FLanePartBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + interface FLanePartMaskedBop { + short[] apply(short[] a, short[] b, int origin, int part, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, boolean[] mask, FLanePartMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + + static short convToFloat16(int i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convIntToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504); + case 1: + return convToFloat16(-65504); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> INT_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[intCornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convIntToFloat16CornerCases(i)); + }) + ); + + static void assertArraysEquals(int[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (int)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + + static short convToFloat16(long i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convLongToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504L); + case 1: + return convToFloat16(-65504L); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> LONG_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convLongToFloat16CornerCases(i)); + }) + ); + + + static void assertArraysEquals(long[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (long)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static void assertArraysEquals(double[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (double)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static short bits(short e) { + return e; + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[0.01 + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01f + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (i % 17 == 0) ? cornerCaseValue(i) : Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + // Create combinations of pairs + // @@@ Might be sensitive to order e.g. div by 0 + static final List>> FLOAT16_GENERATOR_PAIRS = + Stream.of(FLOAT16_GENERATORS.get(0)). + flatMap(fa -> FLOAT16_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_GENERATOR_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> FLOAT16_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + static final List> SELECT_FROM_INDEX_GENERATORS = List.of( + withToString("float16[0..VECLEN*2)", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(RAND.nextInt())); + }) + ); + + static final List>> FLOAT16_GENERATOR_SELECT_FROM_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> SELECT_FROM_INDEX_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortBinaryOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortIndexedOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortBinaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpProvider() { + return FLOAT16_GENERATOR_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSelectFromTwoVectorOpProvider() { + return FLOAT16_GENERATOR_SELECT_FROM_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_TRIPLES.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoIntUnaryOpProvider() { + return INT_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoLongUnaryOpProvider() { + return LONG_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleCompareOpProvider() { + return INT_SHUFFLE_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_SHUFFLE_GENERATORS = List.of( + withToStringBi("shuffle[random]", (Integer l, Integer m) -> { + short[] a = new short[l]; + int upper = m; + for (int i = 0; i < 1; i++) { + a[i] = (short)RAND.nextInt(upper); + } + return a; + }) + ); + + @DataProvider + public Object[][] shortUnaryOpSelectFromProvider() { + return FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpSelectFromMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_COMPARE_GENERATORS = List.of( + withToString("float16[i]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)i); + }), + withToString("float16[i - length / 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - (s * BUFFER_REPS / 2))); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i + 1)); + }), + withToString("float16[i - 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - 2)); + }), + withToString("float16[zigZag(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> i%3 == 0 ? (short)i : (i%3 == 1 ? (short)(i + 1) : (short)(i - 2))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + static final List>> FLOAT16_TEST_GENERATOR_ARGS = + FLOAT16_COMPARE_GENERATORS.stream(). + map(fa -> List.of(fa)). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortTestOpProvider() { + return FLOAT16_TEST_GENERATOR_ARGS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTestOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_TEST_GENERATOR_ARGS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_COMPARE_GENERATOR_PAIRS = + FLOAT16_COMPARE_GENERATORS.stream(). + flatMap(fa -> FLOAT16_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortCompareOpProvider() { + return FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortCompareOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + static short cornerCaseValue(int i) { + return switch(i % 8) { + case 0 -> float16ToRawShortBits(Float16.MAX_VALUE); + case 1 -> float16ToRawShortBits(Float16.MIN_VALUE); + case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY); + case 4 -> float16ToRawShortBits(Float16.NaN); + case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA)); + case 6 -> float16ToShortBits(Float16.valueOf(0.0f)); + default -> float16ToShortBits(Float16.valueOf(-0.0f)); + }; + } + + static final IntFunction fr = (vl) -> { + int length = BUFFER_REPS * vl; + return new short[length]; + }; + + static final IntFunction fmr = (vl) -> { + int length = BUFFER_REPS * vl; + return new boolean[length]; + }; + + static final IntFunction lfr = (vl) -> { + int length = BUFFER_REPS * vl; + return new long[length]; + }; + + static boolean eq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() == bt.floatValue(); + } + + static boolean neq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() != bt.floatValue(); + } + + static boolean lt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() < bt.floatValue(); + } + + static boolean le(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() <= bt.floatValue(); + } + + static boolean gt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() > bt.floatValue(); + } + + static boolean ge(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() >= bt.floatValue(); + } + + static short firstNonZero(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 zero = shortBitsToFloat16((short)0); + return Float16.compare(at, zero) != 0 ? a : b; + } + + static short scalar_add(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.add(at, bt)); + } + + static short scalar_sub(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.subtract(at, bt)); + } + + static short scalar_mul(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.multiply(at, bt)); + + } + static short scalar_max(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.max(at, bt)); + } + + static short scalar_min(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.min(at, bt)); + } + + static short scalar_div(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.divide(at, bt)); + } + + static short scalar_fma(short a, short b, short c) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 ct = shortBitsToFloat16(c); + return float16ToRawShortBits(Float16.fma(at, bt, ct)); + } + + static short scalar_abs(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.abs(at)); + } + + static short scalar_neg(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.negate(at)); + } + + static short scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static boolean isNaN(short a) { + return Float16.isNaN(shortBitsToFloat16(a)); + } + static boolean isFinite(short a) { + return Float16.isFinite(shortBitsToFloat16(a)); + } + static boolean isInfinite(short a) { + return Float16.isInfinite(shortBitsToFloat16(a)); + } + + @Test + static void smokeTest1() { + Float16Vector three = Float16Vector.broadcast(SPECIES, float16ToRawShortBits(Float16.valueOf(-3))); + Float16Vector three2 = (Float16Vector) SPECIES.broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three2).allTrue()); + Float16Vector three3 = three2.broadcast(float16ToRawShortBits(Float16.valueOf(1))).broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three3).allTrue()); + int scale = 2; + Class ETYPE = short.class; + if (ETYPE == double.class || ETYPE == long.class) + scale = 1000000; + else if (ETYPE == byte.class && SPECIES.length() >= 64) + scale = 1; + Float16Vector higher = three.addIndex(scale); + VectorMask m = three.compare(VectorOperators.LE, higher); + assert(m.allTrue()); + m = higher.min(float16ToRawShortBits(Float16.valueOf(-1))).test(VectorOperators.IS_NEGATIVE); + assert(m.allTrue()); + m = higher.test(VectorOperators.IS_FINITE); + assert(m.allTrue()); + short max = higher.reduceLanes(VectorOperators.MAX); + assert(max == float16ToRawShortBits(Float16.add(Float16.valueOf(-3), Float16.multiply(Float16.valueOf(scale), Float16.valueOf((SPECIES.length()-1)))))); + } + + private static short[] + bothToArray(Float16Vector a, Float16Vector b) { + short[] r = new short[a.length() + b.length()]; + a.intoArray(r, 0); + b.intoArray(r, a.length()); + return r; + } + + @Test + static void smokeTest2() { + // Do some zipping and shuffling. + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES,0,1,false).toVector(); + assertEquals(io, io2); + Float16Vector a = io.add((short)1); //[1,2] + Float16Vector b = a.neg(); //[-1,-2] + short[] abValues = bothToArray(a,b); //[1,2,-1,-2] + VectorShuffle zip0 = VectorShuffle.makeZip(SPECIES, 0); + VectorShuffle zip1 = VectorShuffle.makeZip(SPECIES, 1); + Float16Vector zab0 = a.rearrange(zip0,b); //[1,-1] + Float16Vector zab1 = a.rearrange(zip1,b); //[2,-2] + short[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2] + // manually zip + short[] manual = new short[zabValues.length]; + for (int i = 0; i < manual.length; i += 2) { + manual[i+0] = abValues[i/2]; + manual[i+1] = abValues[a.length() + i/2]; + } + assertEquals(Arrays.toString(zabValues), Arrays.toString(manual)); + VectorShuffle unz0 = VectorShuffle.makeUnzip(SPECIES, 0); + VectorShuffle unz1 = VectorShuffle.makeUnzip(SPECIES, 1); + Float16Vector uab0 = zab0.rearrange(unz0,zab1); + Float16Vector uab1 = zab0.rearrange(unz1,zab1); + short[] abValues1 = bothToArray(uab0, uab1); + assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1)); + } + + static void iotaShuffle() { + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector(); + assertEquals(io, io2); + } + + @Test + // Test all shuffle related operations. + static void shuffleTest() { + // To test backend instructions, make sure that C2 is used. + for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) { + iotaShuffle(); + } + } + + @Test + void viewAsIntegeralLanesTest() { + Vector asIntegral = SPECIES.zero().viewAsIntegralLanes(); + VectorSpecies asIntegralSpecies = asIntegral.species(); + Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType()); + assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asIntegralSpecies.length(), SPECIES.length()); + assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES); + } + + @Test + void viewAsFloatingLanesTest() { + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + assertEquals(asFloating.species(), SPECIES); + } + + static short ADD(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::ADD); + } + + static short add(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::add); + } + + static short SUB(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void SUBFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::SUB); + } + + static short sub(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void SUBFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::SUB); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::sub); + } + + static short MUL(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MULFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::MUL); + } + + static short mul(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void MULFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::MUL); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::mul); + } + + static short DIV(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void DIVFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::DIV); + } + + static short div(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void DIVFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::DIV); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::div); + } + + static short FIRST_NONZERO(short a, short b) { + return (short)(firstNonZero(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void FIRST_NONZEROFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void FIRST_NONZEROFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector64Tests::add); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector64Tests::sub); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector64Tests::mul); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16Vector64Tests::div); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16Vector64TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue()).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, Float16Vector64Tests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16Vector64TestsBroadcastMaskedLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector64Tests::ADD); + } + + static Float16Vector bv_MIN = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINFloat16Vector64TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector64Tests::MIN); + } + + static Float16Vector bv_min = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void minFloat16Vector64TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(bv_min).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector64Tests::min); + } + + static Float16Vector bv_MIN_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINFloat16Vector64TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector64Tests::MIN); + } + + static Float16Vector bv_MAX = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXFloat16Vector64TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector64Tests::MAX); + } + + static Float16Vector bv_max = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void maxFloat16Vector64TestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(bv_max).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16Vector64Tests::max); + } + + static Float16Vector bv_MAX_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXFloat16Vector64TestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16Vector64Tests::MAX); + } + + static short MIN(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MIN, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::MIN); + } + + static short min(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.min(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::min); + } + + static short MAX(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MAX, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::MAX); + } + + static short max(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.max(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::max); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::MIN); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::min); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::MAX); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16Vector64Tests::max); + } + + static short ADDReduce(short[] a, int idx) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAll(short[] a) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector64Tests::ADDReduce, Float16Vector64Tests::ADDReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = ADD_IDENTITY; + + assertEquals((short) (scalar_add(id, id)), id, + "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_add(id, x)), x, + "ADD(ADD_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_add(x, id)), x, + "ADD(" + x + ", ADD_IDENTITY) != " + x); + } + } + + static short ADDReduceMasked(short[] a, int idx, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAllMasked(short[] a, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD, vmask); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector64Tests::ADDReduceMasked, Float16Vector64Tests::ADDReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + static short MULReduce(short[] a, int idx) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAll(short[] a) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector64Tests::MULReduce, Float16Vector64Tests::MULReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MUL_IDENTITY; + + assertEquals((short) (scalar_mul(id, id)), id, + "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_mul(id, x)), x, + "MUL(MUL_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_mul(x, id)), x, + "MUL(" + x + ", MUL_IDENTITY) != " + x); + } + } + + static short MULReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAllMasked(short[] a, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MULReduceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL, vmask); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector64Tests::MULReduceMasked, Float16Vector64Tests::MULReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + static short MINReduce(short[] a, int idx) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAll(short[] a) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector64Tests::MINReduce, Float16Vector64Tests::MINReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MIN_IDENTITY; + + assertEquals(scalar_min(id, id), id, + "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_min(id, x), x, + "MIN(MIN_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_min(x, id), x, + "MIN(" + x + ", MIN_IDENTITY) != " + x); + } + } + + static short MINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAllMasked(short[] a, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINReduceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN, vmask); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector64Tests::MINReduceMasked, Float16Vector64Tests::MINReduceAllMasked); + } + + static short MAXReduce(short[] a, int idx) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAll(short[] a) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector64Tests::MAXReduce, Float16Vector64Tests::MAXReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MAX_IDENTITY; + + assertEquals(scalar_max(id, id), id, + "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_max(id, x), x, + "MAX(MAX_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_max(x, id), x, + "MAX(" + x + ", MAX_IDENTITY) != " + x); + } + } + + static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAllMasked(short[] a, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXReduceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX, vmask); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector64Tests::MAXReduceMasked, Float16Vector64Tests::MAXReduceAllMasked); + } + + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16Vector64Tests::FIRST_NONZEROReduce, Float16Vector64Tests::FIRST_NONZEROReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = FIRST_NONZERO_IDENTITY; + + assertEquals(firstNonZero(id, id), id, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, FIRST_NONZERO_IDENTITY) != FIRST_NONZERO_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(firstNonZero(id, x), x); + assertEquals(firstNonZero(x, id), x); + } + } catch (AssertionError e) { + assertEquals(firstNonZero(id, x), x, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, " + x + ") != " + x); + assertEquals(firstNonZero(x, id), x, + "FIRST_NONZERO(" + x + ", FIRST_NONZERO_IDENTITY) != " + x); + } + } + + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16Vector64Tests::FIRST_NONZEROReduceMasked, Float16Vector64Tests::FIRST_NONZEROReduceAllMasked); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void withFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.withLane(j, b[i + j]).intoArray(r, i); + a[i + j] = b[i + j]; + j = (j + 1) & (SPECIES.length() - 1); + } + } + + + assertArraysStrictlyEquals(r, a); + } + + static boolean testIS_DEFAULT(short a) { + return bits(a)==0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_DEFAULTFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_DEFAULT(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_DEFAULTMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } + } + } + } + + static boolean testIS_NEGATIVE(short a) { + return bits(a)<0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NEGATIVEFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NEGATIVE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NEGATIVEMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } + } + } + } + + static boolean testIS_FINITE(short a) { + return isFinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_FINITEFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_FINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_FINITEMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } + } + } + } + + static boolean testIS_NAN(short a) { + return isNaN(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NANFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NAN(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NANMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } + } + } + } + + static boolean testIS_INFINITE(short a) { + return isInfinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_INFINITEFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_INFINITEMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.lt(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GTFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GTFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.eq(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void NEFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void NEFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LEFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LEFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GEFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GEFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16Vector64TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16Vector64TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16Vector64TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16Vector64TestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + static short blend(short a, short b, boolean mask) { + return mask ? b : a; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector64Tests(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.blend(bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16Vector64Tests::blend); + } + + @Test(dataProvider = "shortUnaryOpShuffleProvider") + static void RearrangeFloat16Vector64Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i)).intoArray(r, i); + } + } + + assertRearrangeArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpShuffleMaskProvider") + static void RearrangeFloat16Vector64TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i), vmask).intoArray(r, i); + } + + assertRearrangeArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void compressFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.compress(vmask).intoArray(r, i); + } + } + + assertcompressArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void expandFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.expand(vmask).intoArray(r, i); + } + } + + assertexpandArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void getFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int num_lanes = SPECIES.length(); + // Manually unroll because full unroll happens after intrinsification. + // Unroll is needed because get intrinsic requires for index to be a known constant. + if (num_lanes == 1) { + r[i]=av.lane(0); + } else if (num_lanes == 2) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + } else if (num_lanes == 4) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + } else if (num_lanes == 8) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + } else if (num_lanes == 16) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + } else if (num_lanes == 32) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + } else if (num_lanes == 64) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + r[i+32]=av.lane(32); + r[i+33]=av.lane(33); + r[i+34]=av.lane(34); + r[i+35]=av.lane(35); + r[i+36]=av.lane(36); + r[i+37]=av.lane(37); + r[i+38]=av.lane(38); + r[i+39]=av.lane(39); + r[i+40]=av.lane(40); + r[i+41]=av.lane(41); + r[i+42]=av.lane(42); + r[i+43]=av.lane(43); + r[i+44]=av.lane(44); + r[i+45]=av.lane(45); + r[i+46]=av.lane(46); + r[i+47]=av.lane(47); + r[i+48]=av.lane(48); + r[i+49]=av.lane(49); + r[i+50]=av.lane(50); + r[i+51]=av.lane(51); + r[i+52]=av.lane(52); + r[i+53]=av.lane(53); + r[i+54]=av.lane(54); + r[i+55]=av.lane(55); + r[i+56]=av.lane(56); + r[i+57]=av.lane(57); + r[i+58]=av.lane(58); + r[i+59]=av.lane(59); + r[i+60]=av.lane(60); + r[i+61]=av.lane(61); + r[i+62]=av.lane(62); + r[i+63]=av.lane(63); + } else { + for (int j = 0; j < SPECIES.length(); j++) { + r[i+j]=av.lane(j); + } + } + } + } + + assertArraysStrictlyEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void BroadcastFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, a[i]).intoArray(r, i); + } + } + + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ZeroFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.zero(SPECIES).intoArray(a, i); + } + } + + assertEquals(a, r); + } + + static short[] sliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else + res[i] = (short)0; + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sliceUnaryFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.slice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector64Tests::sliceUnary); + } + + static short[] sliceBinary(short[] a, short[] b, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void sliceBinaryFloat16Vector64TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, Float16Vector64Tests::sliceBinary); + } + + static short[] slice(short[] a, short[] b, int origin, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = mask[i] ? a[idx+i+origin] : (short)0; + else { + res[i] = mask[i] ? b[idx+j] : (short)0; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void sliceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, mask, Float16Vector64Tests::slice); + } + + static short[] unsliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i < origin) + res[i] = (short)0; + else { + res[i] = a[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void unsliceUnaryFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.unslice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16Vector64Tests::unsliceUnary); + } + + static short[] unsliceBinary(short[] a, short[] b, int origin, int part, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (part == 0) { + if (i < origin) + res[i] = b[idx+i]; + else { + res[i] = a[idx+j]; + j++; + } + } else if (part == 1) { + if (i < origin) + res[i] = a[idx+SPECIES.length()-origin+i]; + else { + res[i] = b[idx+origin+j]; + j++; + } + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void unsliceBinaryFloat16Vector64TestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, Float16Vector64Tests::unsliceBinary); + } + + static short[] unslice(short[] a, short[] b, int origin, int part, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = b[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + for (int i = 0; i < SPECIES.length(); i++){ + res[i] = mask[i] ? a[idx+i] : res[i]; + } + short[] res1 = new short[SPECIES.length()]; + if (part == 0) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = b[idx+i]; + else { + res1[i] = res[j]; + j++; + } + } + } else if (part == 1) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = res[SPECIES.length()-origin+i]; + else { + res1[i] = b[idx+origin+j]; + j++; + } + } + } + return res1; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void unsliceFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, mask, Float16Vector64Tests::unslice); + } + + static short SIN(short a) { + return (short)(scalar_sin(a)); + } + + static short strictSIN(short a) { + return (short)(strict_scalar_sin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::SIN, Float16Vector64Tests::strictSIN); + } + + static short EXP(short a) { + return (short)(scalar_exp(a)); + } + + static short strictEXP(short a) { + return (short)(strict_scalar_exp(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXP).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::EXP, Float16Vector64Tests::strictEXP); + } + + static short LOG1P(short a) { + return (short)(scalar_log1p(a)); + } + + static short strictLOG1P(short a) { + return (short)(strict_scalar_log1p(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG1PFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG1P).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::LOG1P, Float16Vector64Tests::strictLOG1P); + } + + static short LOG(short a) { + return (short)(scalar_log(a)); + } + + static short strictLOG(short a) { + return (short)(strict_scalar_log(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOGFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::LOG, Float16Vector64Tests::strictLOG); + } + + static short LOG10(short a) { + return (short)(scalar_log10(a)); + } + + static short strictLOG10(short a) { + return (short)(strict_scalar_log10(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG10Float16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG10).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::LOG10, Float16Vector64Tests::strictLOG10); + } + + static short EXPM1(short a) { + return (short)(scalar_expm1(a)); + } + + static short strictEXPM1(short a) { + return (short)(strict_scalar_expm1(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPM1Float16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXPM1).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::EXPM1, Float16Vector64Tests::strictEXPM1); + } + + static short COS(short a) { + return (short)(scalar_cos(a)); + } + + static short strictCOS(short a) { + return (short)(strict_scalar_cos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::COS, Float16Vector64Tests::strictCOS); + } + + static short TAN(short a) { + return (short)(scalar_tan(a)); + } + + static short strictTAN(short a) { + return (short)(strict_scalar_tan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::TAN, Float16Vector64Tests::strictTAN); + } + + static short SINH(short a) { + return (short)(scalar_sinh(a)); + } + + static short strictSINH(short a) { + return (short)(strict_scalar_sinh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINHFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SINH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::SINH, Float16Vector64Tests::strictSINH); + } + + static short COSH(short a) { + return (short)(scalar_cosh(a)); + } + + static short strictCOSH(short a) { + return (short)(strict_scalar_cosh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSHFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COSH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::COSH, Float16Vector64Tests::strictCOSH); + } + + static short TANH(short a) { + return (short)(scalar_tanh(a)); + } + + static short strictTANH(short a) { + return (short)(strict_scalar_tanh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANHFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TANH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::TANH, Float16Vector64Tests::strictTANH); + } + + static short ASIN(short a) { + return (short)(scalar_asin(a)); + } + + static short strictASIN(short a) { + return (short)(strict_scalar_asin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ASINFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ASIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::ASIN, Float16Vector64Tests::strictASIN); + } + + static short ACOS(short a) { + return (short)(scalar_acos(a)); + } + + static short strictACOS(short a) { + return (short)(strict_scalar_acos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ACOSFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ACOS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::ACOS, Float16Vector64Tests::strictACOS); + } + + static short ATAN(short a) { + return (short)(scalar_atan(a)); + } + + static short strictATAN(short a) { + return (short)(strict_scalar_atan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ATANFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ATAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::ATAN, Float16Vector64Tests::strictATAN); + } + + static short CBRT(short a) { + return (short)(scalar_cbrt(a)); + } + + static short strictCBRT(short a) { + return (short)(strict_scalar_cbrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void CBRTFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.CBRT).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16Vector64Tests::CBRT, Float16Vector64Tests::strictCBRT); + } + + static short HYPOT(short a, short b) { + return (short)(scalar_hypot(a, b)); + } + + static short strictHYPOT(short a, short b) { + return (short)(strict_scalar_hypot(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void HYPOTFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.HYPOT, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector64Tests::HYPOT, Float16Vector64Tests::strictHYPOT); + } + + + static short POW(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictPOW(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.POW, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector64Tests::POW, Float16Vector64Tests::strictPOW); + } + + + static short pow(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictpow(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.pow(bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector64Tests::pow, Float16Vector64Tests::strictpow); + } + + + static short ATAN2(short a, short b) { + return (short)(scalar_atan2(a, b)); + } + + static short strictATAN2(short a, short b) { + return (short)(strict_scalar_atan2(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ATAN2Float16Vector64Tests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ATAN2, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16Vector64Tests::ATAN2, Float16Vector64Tests::strictATAN2); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.POW, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector64Tests::POW, Float16Vector64Tests::strictPOW); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.pow(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16Vector64Tests::pow, Float16Vector64Tests::strictpow); + } + + + static short FMA(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + static short fma(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector64Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector64Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.fma(bv, cv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, c, Float16Vector64Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector64TestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, mask, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i]).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a, b, c, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector64TestsAltBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv).intoArray(r, i); + } + assertAltBroadcastArraysEquals(r, a, b, c, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, c, mask, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector64TestsAltBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv, vmask).intoArray(r, i); + } + + assertAltBroadcastArraysEquals(r, a, b, c, mask, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16Vector64TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector64Tests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16Vector64TestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.fma(b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16Vector64Tests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16Vector64TestsDoubleBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i], vmask).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, Float16Vector64Tests::FMA); + } + + static short NEG(short a) { + return (short)(scalar_neg((short)a)); + } + + static short neg(short a) { + return (short)(scalar_neg((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void NEGFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::NEG); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void negFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.neg().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::neg); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void NEGMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector64Tests::NEG); + } + + static short ABS(short a) { + return (short)(scalar_abs((short)a)); + } + + static short abs(short a) { + return (short)(scalar_abs((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ABSFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::ABS); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void absFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.abs().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::abs); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ABSMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector64Tests::ABS); + } + + static short SQRT(short a) { + return (short)(scalar_sqrt(a)); + } + + static short sqrt(short a) { + return (short)(scalar_sqrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SQRTFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::SQRT); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sqrtFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sqrt().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::sqrt); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void SQRTMaskedFloat16Vector64Tests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16Vector64Tests::SQRT); + } + + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16Vector64Tests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat16Vector64Tests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16Vector64Tests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat16Vector64Tests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16Vector64TestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.lt(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16Vector64TestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.eq(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shorttoIntUnaryOpProvider") + static void toIntArrayFloat16Vector64TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int[] r = av.toIntArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void toLongArrayFloat16Vector64TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + long[] r = av.toLongArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toDoubleArrayFloat16Vector64TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + double[] r = av.toDoubleArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toStringFloat16Vector64TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + String str = av.toString(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals(Arrays.toString(subarr)), "at index " + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void hashCodeFloat16Vector64TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int hash = av.hashCode(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + + static long ADDReduceLong(short[] a, int idx) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return (long)res; + } + + static long ADDReduceAllLong(short[] a) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceLongFloat16Vector64Tests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEquals(r, ra, a, + Float16Vector64Tests::ADDReduceLong, Float16Vector64Tests::ADDReduceAllLong); + } + + static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } + } + + return (long)res; + } + + static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceLongFloat16Vector64TestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD, vmask); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEqualsMasked(r, ra, a, mask, + Float16Vector64Tests::ADDReduceLongMasked, Float16Vector64Tests::ADDReduceAllLongMasked); + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void BroadcastLongFloat16Vector64TestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, shortBitsToFloat16(a[i]).longValue()).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16Vector64TestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.blend(shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + } + assertBroadcastLongArraysEquals(r, a, b, mask, Float16Vector64Tests::blend); + } + + + @Test(dataProvider = "shortUnaryOpSelectFromProvider") + static void SelectFromFloat16Vector64Tests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortSelectFromTwoVectorOpProvider") + static void SelectFromTwoVectorFloat16Vector64Tests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] idx = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < idx.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector idxv = Float16Vector.fromArray(SPECIES, idx, i); + idxv.selectFrom(av, bv).intoArray(r, i); + } + } + assertSelectFromTwoVectorEquals(r, idx, a, b, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpSelectFromMaskProvider") + static void SelectFromFloat16Vector64TestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av, vmask).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleMiscellaneousFloat16Vector64TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + int hash = shuffle.hashCode(); + int length = shuffle.length(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + assertEquals(length, SPECIES.length()); + } + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleToStringFloat16Vector64TestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + String str = shuffle.toString(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals("Shuffle" + Arrays.toString(subarr)), "at index " + + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shuffleCompareOpProvider") + static void shuffleEqualsFloat16Vector64TestsSmokeTest(BiFunction fa, BiFunction fb) { + int[] a = fa.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + int[] b = fb.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = VectorShuffle.fromArray(SPECIES, a, i); + var bv = VectorShuffle.fromArray(SPECIES, b, i); + boolean eq = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(eq, Arrays.equals(a, i, to, b, i, to)); + } + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat16Vector64Tests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } + } + } + + @Test(dataProvider = "maskProvider") + static void maskHashCodeFloat16Vector64TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + int hash = vmask.hashCode(); + + boolean subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + static int maskTrueCount(boolean[] a, int idx) { + int trueCount = 0; + for (int i = idx; i < idx + SPECIES.length(); i++) { + trueCount += a[i] ? 1 : 0; + } + return trueCount; + } + + @Test(dataProvider = "maskProvider") + static void maskTrueCountFloat16Vector64TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.trueCount(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector64Tests::maskTrueCount); + } + + static int maskLastTrue(boolean[] a, int idx) { + int i = idx + SPECIES.length() - 1; + for (; i >= idx; i--) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskLastTrueFloat16Vector64TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.lastTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector64Tests::maskLastTrue); + } + + static int maskFirstTrue(boolean[] a, int idx) { + int i = idx; + for (; i < idx + SPECIES.length(); i++) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskFirstTrueFloat16Vector64TestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.firstTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16Vector64Tests::maskFirstTrue); + } + + @Test(dataProvider = "maskProvider") + static void maskCompressFloat16Vector64TestsSmokeTest(IntFunction fa) { + int trueCount = 0; + boolean[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + trueCount = vmask.trueCount(); + var rmask = vmask.compress(); + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(rmask.laneIsSet(j), j < trueCount); + } + } + } + } + + @DataProvider + public static Object[][] offsetProvider() { + return new Object[][]{ + {0}, + {-1}, + {+1}, + {+2}, + {-2}, + }; + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeFloat16Vector64TestsSmokeTest(int offset) { + int limit = SPECIES.length() * BUFFER_REPS; + for (int i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + int index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeLongFloat16Vector64TestsSmokeTest(int offset) { + long limit = SPECIES.length() * BUFFER_REPS; + for (long i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + long index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @DataProvider + public static Object[][] lengthProvider() { + return new Object[][]{ + {0}, + {1}, + {32}, + {37}, + {1024}, + {1024+1}, + {1024+5}, + }; + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundFloat16Vector64TestsSmokeTest(int length) { + int actualLoopBound = SPECIES.loopBound(length); + int expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundLongFloat16Vector64TestsSmokeTest(int _length) { + long length = _length; + long actualLoopBound = SPECIES.loopBound(length); + long expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test + static void ElementSizeFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + int elsize = av.elementSize(); + assertEquals(elsize, Float16.SIZE); + } + + @Test + static void VectorShapeFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + assert(vsh.equals(VectorShape.S_64_BIT)); + } + + @Test + static void ShapeWithLanesFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = vsh.withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void ElementTypeFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementType() == Float16.class); + } + + @Test + static void SpeciesElementSizeFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementSize() == Float16.SIZE); + } + + @Test + static void VectorTypeFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().vectorType() == av.getClass()); + } + + @Test + static void WithLanesFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorSpecies species = av.species().withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void WithShapeFloat16Vector64TestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = av.species().withShape(vsh); + assert(species.equals(SPECIES)); + } + + @Test + static void MaskAllTrueFloat16Vector64TestsSmokeTest() { + for (int ic = 0; ic < INVOC_COUNT; ic++) { + assertEquals(SPECIES.maskAll(true).toLong(), -1L >>> (64 - SPECIES.length())); + } + } +} diff --git a/test/jdk/jdk/incubator/vector/Float16VectorMaxLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float16VectorMaxLoadStoreTests.java new file mode 100644 index 00000000000..931e280c87a --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16VectorMaxLoadStoreTests.java @@ -0,0 +1,1045 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation + * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED + * -XX:-TieredCompilation Float16VectorMaxLoadStoreTests + * + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.Arena; +import java.lang.foreign.ValueLayout; +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.Float16Vector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.internal.vm.annotation.DontInline; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.nio.ByteOrder; +import java.util.List; +import java.util.function.*; + +@Test +public class Float16VectorMaxLoadStoreTests extends AbstractVectorLoadStoreTest { + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_MAX; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); + + static VectorShape getMaxBit() { + return VectorShape.S_Max_BIT; + } + + private static final int Max = 256; // juts so we can do N/Max + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / Max); + + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0, "at index #" + i); + } + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("short[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i * 5)); + }), + withToString("short[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1))); + }) + ); + + // Relative to array.length + static final List> INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl + 1", (int l) -> { + return l - SPECIES.length() + 1; + }), + withToString("l + speciesl - 1", (int l) -> { + return l + SPECIES.length() - 1; + }), + withToString("l + speciesl", (int l) -> { + return l + SPECIES.length(); + }), + withToString("l + speciesl + 1", (int l) -> { + return l + SPECIES.length() + 1; + }) + ); + + // Relative to byte[] array.length or MemorySegment.byteSize() + static final List> BYTE_INDEX_GENERATORS = List.of( + withToString("-1", (int l) -> { + return -1; + }), + withToString("l", (int l) -> { + return l; + }), + withToString("l - 1", (int l) -> { + return l - 1; + }), + withToString("l + 1", (int l) -> { + return l + 1; + }), + withToString("l - speciesl*ebsize + 1", (int l) -> { + return l - SPECIES.vectorByteSize() + 1; + }), + withToString("l + speciesl*ebsize - 1", (int l) -> { + return l + SPECIES.vectorByteSize() - 1; + }), + withToString("l + speciesl*ebsize", (int l) -> { + return l + SPECIES.vectorByteSize(); + }), + withToString("l + speciesl*ebsize + 1", (int l) -> { + return l + SPECIES.vectorByteSize() + 1; + }) + ); + + @DataProvider + public Object[][] shortProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentProvider() { + return FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, bo}; + }))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortMemorySegmentMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream(). + flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream(). + flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { + return new Object[]{fa, fb, fm, bo}; + })))). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi}; + }). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortByteMaskProviderForIOOBE() { + var f = FLOAT16_GENERATORS.get(0); + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> { + return new Object[] {f, fi, fm}; + })). + toArray(Object[][]::new); + } + + static MemorySegment toSegment(short[] a, IntFunction fb) { + MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8); + for (int i = 0; i < a.length; i++) { + ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]); + } + return ms; + } + + static short[] segmentToArray(MemorySegment ms) { + return ms.toArray(ELEMENT_LAYOUT); + } + + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + @DontInline + static VectorShuffle shuffleFromArray(int[] a, int i) { + return SPECIES.shuffleFromArray(a, i); + } + + @DontInline + static void shuffleIntoArray(VectorShuffle s, int[] a, int i) { + s.intoArray(a, i); + } + + @DontInline + static VectorShuffle shuffleFromMemorySegment(MemorySegment mem, int i, ByteOrder bo) { + return VectorShuffle.fromMemorySegment(SPECIES, mem, i, bo); + } + + @DontInline + static void shuffleIntoMemorySegment(VectorShuffle s, MemorySegment mem, int i, ByteOrder bo) { + s.intoMemorySegment(mem, i, bo); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromArray(a, i); + } + + @DontInline + static Float16Vector fromArray(short[] a, int i, VectorMask m) { + return Float16Vector.fromArray(SPECIES, a, i, m); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i) { + v.intoArray(a, i); + } + + @DontInline + static void intoArray(Float16Vector v, short[] a, int i, VectorMask m) { + v.intoArray(a, i, m); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) { + // Tests the species method and the equivalent vector method it defers to + return (Float16Vector) SPECIES.fromMemorySegment(a, i, bo); + } + + @DontInline + static Float16Vector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask m) { + return Float16Vector.fromMemorySegment(SPECIES, a, i, bo, m); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo) { + v.intoMemorySegment(a, i, bo); + } + + @DontInline + static void intoMemorySegment(Float16Vector v, MemorySegment a, int i, ByteOrder bo, VectorMask m) { + v.intoMemorySegment(a, i, bo, m); + } + + @Test(dataProvider = "shortProvider") + static void loadStoreArray(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i); + } + } + assertEquals(r, a); + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void loadArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + fromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortProviderForIOOBE") + static void storeArrayIOOBE(IntFunction fa, IntFunction fi) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMaskArray(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, vmask); + av.intoArray(r, i); + } + } + assertArraysEquals(r, a, mask); + + + r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, vmask); + } + } + assertArraysEquals(r, a, mask); + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void loadArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = fromArray(a, i, vmask); + av.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + fromArray(a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMaskProviderForIOOBE") + static void storeArrayMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + intoArray(av, r, i, vmask); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); + try { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, 0); + intoArray(av, a, index, vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + @Test(dataProvider = "shortMaskProvider") + static void loadStoreMask(IntFunction fa, + IntFunction fm) { + boolean[] mask = fm.apply(SPECIES.length()); + boolean[] r = new boolean[mask.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < mask.length; i += SPECIES.length()) { + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, mask); + } + + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo); + } + } + long m = r.mismatch(a); + Assert.assertEquals(m, -1, "Segments not equal"); + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder()); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteProviderForIOOBE") + static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize()); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentMaskProvider") + static void loadStoreMemorySegmentMask(IntFunction fa, + IntFunction fb, + IntFunction fm, + ByteOrder bo) { + short[] _a = fa.apply(SPECIES.length()); + MemorySegment a = toSegment(_a, fb); + MemorySegment r = fb.apply((int) a.byteSize()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo, vmask); + av.intoMemorySegment(r, i, bo); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + + + r = fb.apply((int) a.byteSize()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, bo); + av.intoMemorySegment(r, i, bo, vmask); + } + } + assertArraysEquals(segmentToArray(r), _a, mask); + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask); + av.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortByteMaskProviderForIOOBE") + static void storeMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Float16.SIZE)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Float16.SIZE); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromValues(SPECIES, mask); + + int l = (int) a.byteSize(); + int s = SPECIES.vectorByteSize(); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8); + try { + Float16Vector av = Float16Vector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shortMemorySegmentProvider") + static void loadStoreReadonlyMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly(); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true)) + ); + + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false)) + ); + + VectorMask m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1) + .laneIsValid(); + Assert.assertThrows( + UnsupportedOperationException.class, + () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m) + ); + } + + + @Test(dataProvider = "maskProvider") + static void loadStoreMask(IntFunction fm) { + boolean[] a = fm.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask vmask = SPECIES.loadMask(a, i); + vmask.intoArray(r, i); + } + } + Assert.assertEquals(r, a); + } + + + @Test(dataProvider = "shuffleIntProvider") + static void loadStoreShuffleArray(IntFunction fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = VectorShuffle.fromArray(SPECIES, a, i); + shuffle.intoArray(r, i); + } + } + + for (int i = 0; i < a.length; i++) { + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, a[i]), r[i]); + } + + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void storeShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffleIntoArray(shuffle, r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + VectorShuffle shuffle = shuffleFromArray(a, index); + shuffleIntoArray(shuffle, r, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntProviderForIOOBE") + static void loadShuffleArrayIOOBE(IntFunction fa, IntFunction fi) { + int[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorShuffle shuffle = shuffleFromArray(a, i); + shuffle.intoArray(r, i); + } + } + + int index = fi.apply(a.length); + boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); + try { + shuffleFromArray(a, index); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntMemorySegmentProvider") + static void loadStoreShuffleMemorySegment(IntFunction fa, + IntFunction fb, + ByteOrder bo) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), fb); + MemorySegment r = fb.apply((int) a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; //An integer for every lane is read out. So 4 bytes per lane + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = VectorShuffle.fromMemorySegment(SPECIES, a, i, bo); + shuffle.intoMemorySegment(r, i, bo); + } + } + + for (int i = 0; i < l / 4; i++) { + int ai = a.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + int ri = r.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED.withOrder(bo), i); + Assert.assertEquals(testPartiallyWrapIndex(SPECIES, ai), ri); + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleLoadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = shuffleFromMemorySegment(a, i, ByteOrder.nativeOrder()); + shuffle.intoMemorySegment(r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + shuffleFromMemorySegment(a, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + @Test(dataProvider = "shuffleIntByteProviderForIOOBE") + static void shuffleStoreMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { + MemorySegment a = toShuffleSegment(SPECIES, fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i)); + MemorySegment r = Arena.ofAuto().allocate(a.byteSize()); + + int l = (int) a.byteSize(); + int s = SPECIES.length() * 4; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < l; i += s) { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, i, ByteOrder.nativeOrder()); + } + } + + int index = fi.apply((int) a.byteSize()); + boolean shouldFail = isIndexOutOfBounds(s, index, (int) a.byteSize()); + try { + VectorShuffle shuffle = + VectorShuffle.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder()); + shuffleIntoMemorySegment(shuffle, r, index, ByteOrder.nativeOrder()); + if (shouldFail) { + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } + } catch (IndexOutOfBoundsException e) { + if (!shouldFail) { + Assert.fail("Unexpected IndexOutOfBoundsException"); + } + } + } + + + + + // Gather/Scatter load/store tests + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], a[i + indexMap[j]]); + } + } + } catch (AssertionError e) { + assertEquals(r[j], a[i + indexMap[j]], "at index #" + j); + } + } + + static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + int i = 0; + int j = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + j = i; + for (; j < i + SPECIES.length(); j++) { + assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0); + } + } + } catch (AssertionError e) { + assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j); + } + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + if (mask[j % SPECIES.length()]) { + expected[i + indexMap[j]] = a[j]; + } + } + } + + assertEquals(r, expected); + } + + static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) { + short[] expected = new short[r.length]; + + // Store before checking, since the same location may be stored to more than once + for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int j = i; j < i + SPECIES.length(); j++) { + expected[i + indexMap[j]] = a[j]; + } + } + + assertEquals(r, expected); + } + + @DataProvider + public Object[][] gatherScatterProvider() { + return INT_INDEX_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] gatherScatterMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm -> + FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm, fs}; + }))). + toArray(Object[][]::new); + } + + + @Test(dataProvider = "gatherScatterProvider") + static void gather(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void gatherMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i, b, i, vmask); + av.intoArray(r, i); + } + } + + assertGatherArraysEquals(r, a, b, mask); + } + + @Test(dataProvider = "gatherScatterProvider") + static void scatter(IntFunction fa, BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i); + } + } + + assertScatterArraysEquals(r, a, b); + } + + @Test(dataProvider = "gatherScatterMaskProvider") + static void scatterMask(IntFunction fa, BiFunction fs, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] b = fs.apply(a.length, SPECIES.length()); + short[] r = new short[a.length]; + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.intoArray(r, i, b, i, vmask); + } + } + + assertScatterArraysEquals(r, a, b, mask); + } + + + +} diff --git a/test/jdk/jdk/incubator/vector/Float16VectorMaxTests.java b/test/jdk/jdk/incubator/vector/Float16VectorMaxTests.java new file mode 100644 index 00000000000..d8649c838ee --- /dev/null +++ b/test/jdk/jdk/incubator/vector/Float16VectorMaxTests.java @@ -0,0 +1,5893 @@ +/* + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key randomness + * + * @library /test/lib + * @modules jdk.incubator.vector + * @run testng/othervm/timeout=300 -ea -esa -Xbatch -XX:-TieredCompilation Float16VectorMaxTests + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.incubator.vector.VectorShuffle; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.Vector; + +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import jdk.incubator.vector.Float16Vector; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.Integer; +import java.util.List; +import java.util.Arrays; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Test +public class Float16VectorMaxTests extends AbstractVectorTest { + + static final VectorSpecies SPECIES = + Float16Vector.SPECIES_MAX; + + static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + static void assertEquals(short actual, short expected, short delta) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta)); + } + static void assertEquals(short actual, short expected, short delta, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta), msg); + } + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + static void assertEquals(long actual, long expected) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected)); + } + static void assertEquals(long actual, long expected, String msg) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected), msg); + } + static void assertEquals(String actual, String expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(Object actual, Object expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(double actual, double expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + static void assertEquals(boolean actual, boolean expected) { + Assert.assertEquals(actual, expected); + } + static void assertEquals(boolean actual, boolean expected, String msg) { + Assert.assertEquals(actual, expected, msg); + } + + + static VectorShape getMaxBit() { + return VectorShape.S_Max_BIT; + } + + private static final int Max = 256; // juts so we can do N/Max + + // Identity values for reduction operations + private static final short ADD_IDENTITY = (short)0; + private static final short FIRST_NONZERO_IDENTITY = (short)0; + private static final short MAX_IDENTITY = float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + private static final short MIN_IDENTITY = float16ToRawShortBits(Float16.POSITIVE_INFINITY); + private static final short MUL_IDENTITY = float16ToRawShortBits(Float16.valueOf(1.0f)); + + // for floating point addition reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_ADD = float16ToRawShortBits(Float16.valueOf(10.0f)); + + // for floating point multiplication reduction ops that may introduce rounding errors + private static final short RELATIVE_ROUNDING_ERROR_FACTOR_MUL = float16ToRawShortBits(Float16.valueOf(50.0f)); + + static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / Max); + + static void assertArraysStrictlyEquals(short[] r, short[] a) { + for (int i = 0; i < a.length; i++) { + short ir = r[i]; + short ia = a[i]; + if (ir != ia) { + Assert.fail(String.format("at index #%d, expected = %016X, actual = %016X", i, ia, ir)); + } + } + } + + interface FUnOp { + short apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]); + } + } + + interface FUnArrayOp { + short[] apply(short a); + } + + static void assertArraysEquals(short[] r, short[] a, FUnArrayOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a[i])); + } + } catch (AssertionError e) { + short[] ref = f.apply(a[i]); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, boolean[] mask, FUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i], "at index #" + i + ", input = " + a[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + interface FReductionOp { + short apply(short[] a, int idx); + } + + interface FReductionAllOp { + short apply(short[] a); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa) { + assertReductionArraysEquals(r, rc, a, f, fa, (short)0.0); + } + + static void assertReductionArraysEquals(short[] r, short rc, short[] a, + FReductionOp f, FReductionAllOp fa, + short relativeErrorFactor) { + int i = 0; + try { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor)))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor)))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor))), "at index #" + i); + } + } + + interface FReductionMaskedOp { + short apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOp { + short apply(short[] a, boolean[] mask); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa) { + assertReductionArraysEqualsMasked(r, rc, a, mask, f, fa, (short)0.0); + } + + static void assertReductionArraysEqualsMasked(short[] r, short rc, short[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa, + short relativeError) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError))))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError))))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError)))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError)))), "at index #" + i); + } + } + + interface FReductionOpLong { + long apply(short[] a, int idx); + } + + interface FReductionAllOpLong { + long apply(short[] a); + } + + static void assertReductionLongArraysEquals(long[] r, long rc, short[] a, + FReductionOpLong f, FReductionAllOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FReductionMaskedOpLong { + long apply(short[] a, int idx, boolean[] mask); + } + + interface FReductionAllMaskedOpLong { + long apply(short[] a, boolean[] mask); + } + + static void assertReductionLongArraysEqualsMasked(long[] r, long rc, short[] a, boolean[] mask, + FReductionMaskedOpLong f, FReductionAllMaskedOpLong fa) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask)); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask)); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), "at index #" + i); + } + } + + interface FBoolReductionOp { + boolean apply(boolean[] a, int idx); + } + + static void assertReductionBoolArraysEquals(boolean[] r, boolean[] a, FBoolReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + interface FMaskReductionOp { + int apply(boolean[] a, int idx); + } + + static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReductionOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a, i), "at index #" + i); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+order[i+j]]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]); + } + } + + static void assertcompressArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + k], a[i + j]); + k++; + } + } + for (; k < vector_len; k++) { + assertEquals(r[i + k], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + k; + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[idx], a[i + j], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertexpandArraysEquals(short[] r, short[] a, boolean[] m, int vector_len) { + int i = 0, j = 0, k = 0; + try { + for (; i < a.length; i += vector_len) { + k = 0; + for (j = 0; j < vector_len; j++) { + if (m[(i + j) % SPECIES.length()]) { + assertEquals(r[i + j], a[i + k]); + k++; + } else { + assertEquals(r[i + j], (short)0); + } + } + } + } catch (AssertionError e) { + int idx = i + j; + if (m[idx % SPECIES.length()]) { + assertEquals(r[idx], a[i + k], "at index #" + idx); + } else { + assertEquals(r[idx], (short)0, "at index #" + idx); + } + } + } + + static void assertSelectFromTwoVectorEquals(short[] r, short[] order, short[] a, short[] b, int vector_len) { + int i = 0, j = 0; + boolean is_exceptional_idx = false; + int idx = 0, wrapped_index = 0, oidx = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + idx = i + j; + wrapped_index = Math.floorMod(shortBitsToFloat16(order[idx]).intValue(), 2 * vector_len); + is_exceptional_idx = wrapped_index >= vector_len; + oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index; + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx])); + } + } + } catch (AssertionError e) { + assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]), "at index #" + idx + ", order = " + order[idx] + ", a = " + a[i + oidx] + ", b = " + b[i + oidx]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + } catch (AssertionError e) { + int idx = i + j; + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()]); + } + } + + static void assertRearrangeArraysEquals(short[] r, short[] a, int[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertSelectFromArraysEquals(short[] r, short[] a, short[] order, boolean[] mask, int vector_len) { + int i = 0, j = 0; + try { + for (; i < a.length; i += vector_len) { + for (j = 0; j < vector_len; j++) { + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()]); + else + assertEquals(r[i+j], (short)0); + } + } + } catch (AssertionError e) { + int idx = i + j; + if (mask[j % SPECIES.length()]) + assertEquals(r[i+j], a[i+shortBitsToFloat16(order[i+j]).intValue()], "at index #" + idx + ", input = " + a[i+shortBitsToFloat16(order[i+j]).intValue()] + ", mask = " + mask[j % SPECIES.length()]); + else + assertEquals(r[i+j], (short)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a) { + int i = 0; + for (; i < a.length; i += SPECIES.length()) { + int idx = i; + for (int j = idx; j < (idx + SPECIES.length()); j++) + a[j]=a[idx]; + } + + try { + for (i = 0; i < a.length; i++) { + assertEquals(r[i], a[i]); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]); + } + } + + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + interface FBinOp { + short apply(short a, short b); + } + + interface FBinMaskOp { + short apply(short a, short b, boolean m); + + static FBinMaskOp lift(FBinOp f) { + return (a, b, m) -> m ? f.apply(a, b) : a; + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b)); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b), "(" + a[i] + ", " + b + ") at index #" + i); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())))); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue()))), + "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinOp f) { + assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertBroadcastLongArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertBroadcastLongArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())), + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinOp f) { + assertShiftArraysEquals(r, a, b, mask, FBinMaskOp.lift(f)); + } + + static void assertShiftArraysEquals(short[] r, short[] a, short[] b, boolean[] mask, FBinMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", input2 = " + b[j] + ", mask = " + mask[i]); + } + } + + interface FBinConstOp { + short apply(short a); + } + + interface FBinConstMaskOp { + short apply(short a, boolean m); + + static FBinConstMaskOp lift(FBinConstOp f) { + return (a, m) -> m ? f.apply(a) : a; + } + } + + static void assertShiftConstEquals(short[] r, short[] a, FBinConstOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j])); + } + } + } catch (AssertionError e) { + assertEquals(r[i+j], f.apply(a[i+j]), "at index #" + i + ", " + j); + } + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstOp f) { + assertShiftConstEquals(r, a, mask, FBinConstMaskOp.lift(f)); + } + + static void assertShiftConstEquals(short[] r, short[] a, boolean[] mask, FBinConstMaskOp f) { + int i = 0; + int j = 0; + try { + for (; j < a.length; j += SPECIES.length()) { + for (i = 0; i < SPECIES.length(); i++) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i])); + } + } + } catch (AssertionError err) { + assertEquals(r[i+j], f.apply(a[i+j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", mask = " + mask[i]); + } + } + + interface FTernOp { + short apply(short a, short b, short c); + } + + interface FTernMaskOp { + short apply(short a, short b, short c, boolean m); + + static FTernMaskOp lift(FTernOp f) { + return (a, b, c, m) -> m ? f.apply(a, b, c) : a; + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + } + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernOp f) { + assertArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + c[i]); + } + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[i] + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertAltBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertAltBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i], + mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, FTernOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()])); + } + } catch (AssertionError e) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " + + c[(i / SPECIES.length()) * SPECIES.length()]); + } + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernOp f) { + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f)); + } + + static void assertDoubleBroadcastArraysEquals(short[] r, short[] a, short[] b, short[] c, boolean[] mask, + FTernMaskOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()])); + } + } catch (AssertionError err) { + assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], + c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #" + + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + + mask[i % SPECIES.length()]); + } + } + + + static boolean isWithin1Ulp(short actual, short expected) { + Float16 act = shortBitsToFloat16(actual); + Float16 exp = shortBitsToFloat16(expected); + if (Float16.isNaN(exp) && !Float16.isNaN(act)) { + return false; + } else if (!Float16.isNaN(exp) && Float16.isNaN(act)) { + return false; + } + + Float16 low = Float16.nextDown(exp); + Float16 high = Float16.nextUp(exp); + + if (Float16.compare(low, exp) > 0) { + return false; + } + + if (Float16.compare(high, exp) < 0) { + return false; + } + + return true; + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, FUnOp mathf, FUnOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i]))) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i])); + } + } + + static void assertArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0 || + isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), shortBitsToFloat16(mathf.apply(a[i], b[i]))) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); + Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i])); + } + } + + static void assertBroadcastArraysEqualsWithinOneUlp(short[] r, short[] a, short[] b, + FBinOp mathf, FBinOp strictmathf) { + int i = 0; + try { + // Check that result is within 1 ulp of strict math or equivalent to math implementation. + for (; i < a.length; i++) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0 || + isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))); + } + } catch (AssertionError e) { + Assert.assertTrue(Float16.compare(shortBitsToFloat16(r[i]), + shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))) == 0, + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); + Assert.assertTrue(isWithin1Ulp(r[i], + strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])), + "at index #" + i + ", input1 = " + a[i] + ", input2 = " + + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], + b[(i / SPECIES.length()) * SPECIES.length()])); + } + } + + interface FGatherScatterOp { + short[] apply(short[] a, int ix, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, FGatherScatterOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + " at index #" + i); + } + } + + interface FGatherMaskedOp { + short[] apply(short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + interface FScatterMaskedOp { + short[] apply(short[] r, short[] a, int ix, boolean[] mask, int[] b, int iy); + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FGatherMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + static void assertArraysEquals(short[] r, short[] a, int[] b, boolean[] mask, FScatterMaskedOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(r, a, i, mask, b, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(r, a, i, mask, b, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, + "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: " + + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length())) + + ", b: " + + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length())) + + ", r: " + + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length())) + + ", mask: " + + Arrays.toString(mask) + + " at index #" + i); + } + } + + interface FLaneOp { + short[] apply(short[] a, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, int origin, FLaneOp f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i); + } + } + + interface FLaneBop { + short[] apply(short[] a, short[] b, int origin, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, FLaneBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLaneMaskedBop { + short[] apply(short[] a, short[] b, int origin, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, boolean[] mask, FLaneMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin); + } + } + + interface FLanePartBop { + short[] apply(short[] a, short[] b, int origin, int part, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, FLanePartBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + interface FLanePartMaskedBop { + short[] apply(short[] a, short[] b, int origin, int part, boolean[] mask, int idx); + } + + static void assertArraysEquals(short[] r, short[] a, short[] b, int origin, int part, boolean[] mask, FLanePartMaskedBop f) { + int i = 0; + try { + for (; i < a.length; i += SPECIES.length()) { + assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()), + f.apply(a, b, origin, part, mask, i)); + } + } catch (AssertionError e) { + short[] ref = f.apply(a, b, origin, part, mask, i); + short[] res = Arrays.copyOfRange(r, i, i+SPECIES.length()); + assertEquals(res, ref, "(ref: " + Arrays.toString(ref) + + ", res: " + Arrays.toString(res) + + "), at index #" + i + + ", at origin #" + origin + + ", with part #" + part); + } + } + + + static short convToFloat16(int i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convIntToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504); + case 1: + return convToFloat16(-65504); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> INT_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[intCornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convIntToFloat16CornerCases(i)); + }) + ); + + static void assertArraysEquals(int[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (int)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + + static short convToFloat16(long i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static short convLongToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504L); + case 1: + return convToFloat16(-65504L); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> LONG_FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convLongToFloat16CornerCases(i)); + }) + ); + + + static void assertArraysEquals(long[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (long)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static void assertArraysEquals(double[] r, short[] a, int offs) { + int i = 0; + try { + for (; i < r.length; i++) { + assertEquals(r[i], (double)Float.float16ToFloat(a[i+offs])); + } + } catch (AssertionError e) { + assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); + } + } + + static short bits(short e) { + return e; + } + + static final List> FLOAT16_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (((short)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[0.01 + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01f + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (i % 17 == 0) ? cornerCaseValue(i) : Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + // Create combinations of pairs + // @@@ Might be sensitive to order e.g. div by 0 + static final List>> FLOAT16_GENERATOR_PAIRS = + Stream.of(FLOAT16_GENERATORS.get(0)). + flatMap(fa -> FLOAT16_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_GENERATOR_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> FLOAT16_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + static final List> SELECT_FROM_INDEX_GENERATORS = List.of( + withToString("float16[0..VECLEN*2)", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(RAND.nextInt())); + }) + ); + + static final List>> FLOAT16_GENERATOR_SELECT_FROM_TRIPLES = + FLOAT16_GENERATOR_PAIRS.stream(). + flatMap(pair -> SELECT_FROM_INDEX_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortBinaryOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortIndexedOpProvider() { + return FLOAT16_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortBinaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpProvider() { + return FLOAT16_GENERATOR_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSelectFromTwoVectorOpProvider() { + return FLOAT16_GENERATOR_SELECT_FROM_TRIPLES.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTernaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATOR_TRIPLES.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpProvider() { + return FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fm}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoIntUnaryOpProvider() { + return INT_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shorttoLongUnaryOpProvider() { + return LONG_FLOAT16_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] maskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shuffleCompareOpProvider() { + return INT_SHUFFLE_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleProvider() { + return INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpShuffleMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_SHUFFLE_GENERATORS = List.of( + withToStringBi("shuffle[random]", (Integer l, Integer m) -> { + short[] a = new short[l]; + int upper = m; + for (int i = 0; i < 1; i++) { + a[i] = (short)RAND.nextInt(upper); + } + return a; + }) + ); + + @DataProvider + public Object[][] shortUnaryOpSelectFromProvider() { + return FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs}; + })). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortUnaryOpSelectFromMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_SHUFFLE_GENERATORS.stream(). + flatMap(fs -> FLOAT16_GENERATORS.stream().map(fa -> { + return new Object[] {fa, fs, fm}; + }))). + toArray(Object[][]::new); + } + + static final List> FLOAT16_COMPARE_GENERATORS = List.of( + withToString("float16[i]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)i); + }), + withToString("float16[i - length / 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - (s * BUFFER_REPS / 2))); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i + 1)); + }), + withToString("float16[i - 2]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(i - 2)); + }), + withToString("float16[zigZag(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> i%3 == 0 ? (short)i : (i%3 == 1 ? (short)(i + 1) : (short)(i - 2))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); + + static final List>> FLOAT16_TEST_GENERATOR_ARGS = + FLOAT16_COMPARE_GENERATORS.stream(). + map(fa -> List.of(fa)). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortTestOpProvider() { + return FLOAT16_TEST_GENERATOR_ARGS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortTestOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_TEST_GENERATOR_ARGS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + static final List>> FLOAT16_COMPARE_GENERATOR_PAIRS = + FLOAT16_COMPARE_GENERATORS.stream(). + flatMap(fa -> FLOAT16_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))). + collect(Collectors.toList()); + + @DataProvider + public Object[][] shortCompareOpProvider() { + return FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortCompareOpMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> FLOAT16_COMPARE_GENERATOR_PAIRS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + interface ToFloat16F { + short apply(int i); + } + + static short[] fill(int s , ToFloat16F f) { + return fill(new short[s], f); + } + + static short[] fill(short[] a, ToFloat16F f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + static short cornerCaseValue(int i) { + return switch(i % 8) { + case 0 -> float16ToRawShortBits(Float16.MAX_VALUE); + case 1 -> float16ToRawShortBits(Float16.MIN_VALUE); + case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY); + case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY); + case 4 -> float16ToRawShortBits(Float16.NaN); + case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA)); + case 6 -> float16ToShortBits(Float16.valueOf(0.0f)); + default -> float16ToShortBits(Float16.valueOf(-0.0f)); + }; + } + + static final IntFunction fr = (vl) -> { + int length = BUFFER_REPS * vl; + return new short[length]; + }; + + static final IntFunction fmr = (vl) -> { + int length = BUFFER_REPS * vl; + return new boolean[length]; + }; + + static final IntFunction lfr = (vl) -> { + int length = BUFFER_REPS * vl; + return new long[length]; + }; + + static boolean eq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() == bt.floatValue(); + } + + static boolean neq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() != bt.floatValue(); + } + + static boolean lt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() < bt.floatValue(); + } + + static boolean le(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() <= bt.floatValue(); + } + + static boolean gt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() > bt.floatValue(); + } + + static boolean ge(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() >= bt.floatValue(); + } + + static short firstNonZero(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 zero = shortBitsToFloat16((short)0); + return Float16.compare(at, zero) != 0 ? a : b; + } + + static short scalar_add(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.add(at, bt)); + } + + static short scalar_sub(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.subtract(at, bt)); + } + + static short scalar_mul(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.multiply(at, bt)); + + } + static short scalar_max(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.max(at, bt)); + } + + static short scalar_min(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.min(at, bt)); + } + + static short scalar_div(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.divide(at, bt)); + } + + static short scalar_fma(short a, short b, short c) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 ct = shortBitsToFloat16(c); + return float16ToRawShortBits(Float16.fma(at, bt, ct)); + } + + static short scalar_abs(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.abs(at)); + } + + static short scalar_neg(short a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.negate(at)); + } + + static short scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(Math.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(Math.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_sin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_exp(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log1p(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_log10(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_expm1(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sinh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cosh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_tanh(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_asin(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_acos(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_atan(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_cbrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_sqrt(short a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static short strict_scalar_hypot(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_pow(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static short strict_scalar_atan2(short a, short b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static boolean isNaN(short a) { + return Float16.isNaN(shortBitsToFloat16(a)); + } + static boolean isFinite(short a) { + return Float16.isFinite(shortBitsToFloat16(a)); + } + static boolean isInfinite(short a) { + return Float16.isInfinite(shortBitsToFloat16(a)); + } + + @Test + static void smokeTest1() { + Float16Vector three = Float16Vector.broadcast(SPECIES, float16ToRawShortBits(Float16.valueOf(-3))); + Float16Vector three2 = (Float16Vector) SPECIES.broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three2).allTrue()); + Float16Vector three3 = three2.broadcast(float16ToRawShortBits(Float16.valueOf(1))).broadcast(Float16.valueOf(-3).longValue()); + assert(three.eq(three3).allTrue()); + int scale = 2; + Class ETYPE = short.class; + if (ETYPE == double.class || ETYPE == long.class) + scale = 1000000; + else if (ETYPE == byte.class && SPECIES.length() >= 64) + scale = 1; + Float16Vector higher = three.addIndex(scale); + VectorMask m = three.compare(VectorOperators.LE, higher); + assert(m.allTrue()); + m = higher.min(float16ToRawShortBits(Float16.valueOf(-1))).test(VectorOperators.IS_NEGATIVE); + assert(m.allTrue()); + m = higher.test(VectorOperators.IS_FINITE); + assert(m.allTrue()); + short max = higher.reduceLanes(VectorOperators.MAX); + assert(max == float16ToRawShortBits(Float16.add(Float16.valueOf(-3), Float16.multiply(Float16.valueOf(scale), Float16.valueOf((SPECIES.length()-1)))))); + } + + private static short[] + bothToArray(Float16Vector a, Float16Vector b) { + short[] r = new short[a.length() + b.length()]; + a.intoArray(r, 0); + b.intoArray(r, a.length()); + return r; + } + + @Test + static void smokeTest2() { + // Do some zipping and shuffling. + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES,0,1,false).toVector(); + assertEquals(io, io2); + Float16Vector a = io.add((short)1); //[1,2] + Float16Vector b = a.neg(); //[-1,-2] + short[] abValues = bothToArray(a,b); //[1,2,-1,-2] + VectorShuffle zip0 = VectorShuffle.makeZip(SPECIES, 0); + VectorShuffle zip1 = VectorShuffle.makeZip(SPECIES, 1); + Float16Vector zab0 = a.rearrange(zip0,b); //[1,-1] + Float16Vector zab1 = a.rearrange(zip1,b); //[2,-2] + short[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2] + // manually zip + short[] manual = new short[zabValues.length]; + for (int i = 0; i < manual.length; i += 2) { + manual[i+0] = abValues[i/2]; + manual[i+1] = abValues[a.length() + i/2]; + } + assertEquals(Arrays.toString(zabValues), Arrays.toString(manual)); + VectorShuffle unz0 = VectorShuffle.makeUnzip(SPECIES, 0); + VectorShuffle unz1 = VectorShuffle.makeUnzip(SPECIES, 1); + Float16Vector uab0 = zab0.rearrange(unz0,zab1); + Float16Vector uab1 = zab0.rearrange(unz1,zab1); + short[] abValues1 = bothToArray(uab0, uab1); + assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1)); + } + + static void iotaShuffle() { + Float16Vector io = (Float16Vector) SPECIES.broadcast(0).addIndex(1); + Float16Vector io2 = (Float16Vector) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector(); + assertEquals(io, io2); + } + + @Test + // Test all shuffle related operations. + static void shuffleTest() { + // To test backend instructions, make sure that C2 is used. + for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) { + iotaShuffle(); + } + } + + @Test + void viewAsIntegeralLanesTest() { + Vector asIntegral = SPECIES.zero().viewAsIntegralLanes(); + VectorSpecies asIntegralSpecies = asIntegral.species(); + Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType()); + assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asIntegralSpecies.length(), SPECIES.length()); + assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES); + } + + @Test + void viewAsFloatingLanesTest() { + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + assertEquals(asFloating.species(), SPECIES); + } + + static short ADD(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::ADD); + } + + static short add(short a, short b) { + return (short)(scalar_add(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ADD, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.add(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::add); + } + + static short SUB(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void SUBFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::SUB); + } + + static short sub(short a, short b) { + return (short)(scalar_sub(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void SUBFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.SUB, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::SUB); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.sub(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::sub); + } + + static short MUL(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MULFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::MUL); + } + + static short mul(short a, short b) { + return (short)(scalar_mul(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void MULFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MUL, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::MUL); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.mul(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::mul); + } + + static short DIV(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void DIVFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::DIV); + } + + static short div(short a, short b) { + return (short)(scalar_div(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void DIVFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.DIV, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::DIV); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.div(bv, vmask).intoArray(r, i); + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::div); + } + + static short FIRST_NONZERO(short a, short b) { + return (short)(firstNonZero(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void FIRST_NONZEROFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void FIRST_NONZEROFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FIRST_NONZERO, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::FIRST_NONZERO); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void addFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::add); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void addFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.add(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16VectorMaxTests::add); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void subFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::sub); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void subFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sub(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16VectorMaxTests::sub); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void mulFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::mul); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void mulFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.mul(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16VectorMaxTests::mul); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void divFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::div); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void divFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.div(b[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, mask, Float16VectorMaxTests::div); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ADDFloat16VectorMaxTestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue()).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, Float16VectorMaxTests::ADD); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void ADDFloat16VectorMaxTestsBroadcastMaskedLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ADD, shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + + assertBroadcastLongArraysEquals(r, a, b, mask, Float16VectorMaxTests::ADD); + } + + static Float16Vector bv_MIN = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINFloat16VectorMaxTestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16VectorMaxTests::MIN); + } + + static Float16Vector bv_min = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void minFloat16VectorMaxTestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(bv_min).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16VectorMaxTests::min); + } + + static Float16Vector bv_MIN_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINFloat16VectorMaxTestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, bv_MIN_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16VectorMaxTests::MIN); + } + + static Float16Vector bv_MAX = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXFloat16VectorMaxTestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16VectorMaxTests::MAX); + } + + static Float16Vector bv_max = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpProvider") + static void maxFloat16VectorMaxTestsWithMemOp(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(bv_max).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, Float16VectorMaxTests::max); + } + + static Float16Vector bv_MAX_M = Float16Vector.broadcast(SPECIES, (short)10); + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXFloat16VectorMaxTestsMaskedWithMemOp(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, bv_MAX_M, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, (short)10, mask, Float16VectorMaxTests::MAX); + } + + static short MIN(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MIN, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::MIN); + } + + static short min(short a, short b) { + return (short)(scalar_min(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.min(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::min); + } + + static short MAX(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.MAX, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::MAX); + } + + static short max(short a, short b) { + return (short)(scalar_max(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.max(bv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::max); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MINFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MIN, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::MIN); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void minFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.min(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::min); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void MAXFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.MAX, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::MAX); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void maxFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.max(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, Float16VectorMaxTests::max); + } + + static short ADDReduce(short[] a, int idx) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAll(short[] a) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16VectorMaxTests::ADDReduce, Float16VectorMaxTests::ADDReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = ADD_IDENTITY; + + assertEquals((short) (scalar_add(id, id)), id, + "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_add(id, x)), x, + "ADD(ADD_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_add(x, id)), x, + "ADD(" + x + ", ADD_IDENTITY) != " + x); + } + } + + static short ADDReduceMasked(short[] a, int idx, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_add(res, a[i]); + } + + return res; + } + + static short ADDReduceAllMasked(short[] a, boolean[] mask) { + short res = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_add(res, ADDReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = ADD_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.ADD, vmask); + r[i] = v; + ra = scalar_add(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16VectorMaxTests::ADDReduceMasked, Float16VectorMaxTests::ADDReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_ADD); + } + + static short MULReduce(short[] a, int idx) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAll(short[] a) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16VectorMaxTests::MULReduce, Float16VectorMaxTests::MULReduceAll, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MULReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MUL_IDENTITY; + + assertEquals((short) (scalar_mul(id, id)), id, + "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); + } + } catch (AssertionError e) { + assertEquals((short) (scalar_mul(id, x)), x, + "MUL(MUL_IDENTITY, " + x + ") != " + x); + assertEquals((short) (scalar_mul(x, id)), x, + "MUL(" + x + ", MUL_IDENTITY) != " + x); + } + } + + static short MULReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_mul(res, a[i]); + } + + return res; + } + + static short MULReduceAllMasked(short[] a, boolean[] mask) { + short res = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_mul(res, MULReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MULReduceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MUL_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MUL, vmask); + r[i] = v; + ra = scalar_mul(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16VectorMaxTests::MULReduceMasked, Float16VectorMaxTests::MULReduceAllMasked, RELATIVE_ROUNDING_ERROR_FACTOR_MUL); + } + + static short MINReduce(short[] a, int idx) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAll(short[] a) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16VectorMaxTests::MINReduce, Float16VectorMaxTests::MINReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MINReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MIN_IDENTITY; + + assertEquals(scalar_min(id, id), id, + "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_min(id, x), x, + "MIN(MIN_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_min(x, id), x, + "MIN(" + x + ", MIN_IDENTITY) != " + x); + } + } + + static short MINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_min(res, a[i]); + } + + return res; + } + + static short MINReduceAllMasked(short[] a, boolean[] mask) { + short res = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_min(res, MINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MINReduceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MIN_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MIN, vmask); + r[i] = v; + ra = scalar_min(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16VectorMaxTests::MINReduceMasked, Float16VectorMaxTests::MINReduceAllMasked); + } + + static short MAXReduce(short[] a, int idx) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAll(short[] a) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16VectorMaxTests::MAXReduce, Float16VectorMaxTests::MAXReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void MAXReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = MAX_IDENTITY; + + assertEquals(scalar_max(id, id), id, + "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); + } + } catch (AssertionError e) { + assertEquals(scalar_max(id, x), x, + "MAX(MAX_IDENTITY, " + x + ") != " + x); + assertEquals(scalar_max(x, id), x, + "MAX(" + x + ", MAX_IDENTITY) != " + x); + } + } + + static short MAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = scalar_max(res, a[i]); + } + + return res; + } + + static short MAXReduceAllMasked(short[] a, boolean[] mask) { + short res = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = scalar_max(res, MAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void MAXReduceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = MAX_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.MAX, vmask); + r[i] = v; + ra = scalar_max(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16VectorMaxTests::MAXReduceMasked, Float16VectorMaxTests::MAXReduceAllMasked); + } + + static short FIRST_NONZEROReduce(short[] a, int idx) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAll(short[] a) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEquals(r, ra, a, + Float16VectorMaxTests::FIRST_NONZEROReduce, Float16VectorMaxTests::FIRST_NONZEROReduceAll); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void FIRST_NONZEROReduceIdentityValueTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short id = FIRST_NONZERO_IDENTITY; + + assertEquals(firstNonZero(id, id), id, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, FIRST_NONZERO_IDENTITY) != FIRST_NONZERO_IDENTITY"); + + short x = 0; + try { + for (int i = 0; i < a.length; i++) { + x = a[i]; + assertEquals(firstNonZero(id, x), x); + assertEquals(firstNonZero(x, id), x); + } + } catch (AssertionError e) { + assertEquals(firstNonZero(id, x), x, + "FIRST_NONZERO(FIRST_NONZERO_IDENTITY, " + x + ") != " + x); + assertEquals(firstNonZero(x, id), x, + "FIRST_NONZERO(" + x + ", FIRST_NONZERO_IDENTITY) != " + x); + } + } + + static short FIRST_NONZEROReduceMasked(short[] a, int idx, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = firstNonZero(res, a[i]); + } + + return res; + } + + static short FIRST_NONZEROReduceAllMasked(short[] a, boolean[] mask) { + short res = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = firstNonZero(res, FIRST_NONZEROReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void FIRST_NONZEROReduceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = 0; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = FIRST_NONZERO_IDENTITY; + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + short v = av.reduceLanes(VectorOperators.FIRST_NONZERO, vmask); + r[i] = v; + ra = firstNonZero(ra, v); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Float16VectorMaxTests::FIRST_NONZEROReduceMasked, Float16VectorMaxTests::FIRST_NONZEROReduceAllMasked); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void withFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.withLane(j, b[i + j]).intoArray(r, i); + a[i + j] = b[i + j]; + j = (j + 1) & (SPECIES.length() - 1); + } + } + + + assertArraysStrictlyEquals(r, a); + } + + static boolean testIS_DEFAULT(short a) { + return bits(a)==0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_DEFAULTFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_DEFAULT(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_DEFAULTMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } + } + } + } + + static boolean testIS_NEGATIVE(short a) { + return bits(a)<0; + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NEGATIVEFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NEGATIVE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NEGATIVEMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } + } + } + } + + static boolean testIS_FINITE(short a) { + return isFinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_FINITEFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_FINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_FINITEMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } + } + } + } + + static boolean testIS_NAN(short a) { + return isNaN(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_NANFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_NAN(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_NANMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } + } + } + } + + static boolean testIS_INFINITE(short a) { + return isInfinite(a); + } + + @Test(dataProvider = "shortTestOpProvider") + static void IS_INFINITEFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortTestOpMaskProvider") + static void IS_INFINITEMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.lt(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && lt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GTFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GTFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GT, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && gt(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.eq(bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.EQ, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && eq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void NEFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void NEFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.NE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && neq(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LEFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LEFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.LE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && le(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void GEFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void GEFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + VectorMask mv = av.compare(VectorOperators.GE, bv, vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && ge(a[i + j], b[i + j])); + } + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void LTFloat16VectorMaxTestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void LTFloat16VectorMaxTestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.LT, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, b[i], vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void EQFloat16VectorMaxTestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue()); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())))); + } + } + } + + @Test(dataProvider = "shortCompareOpMaskProvider") + static void EQFloat16VectorMaxTestsBroadcastLongMaskedSmokeTest(IntFunction fa, + IntFunction fb, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.compare(VectorOperators.EQ, shortBitsToFloat16(b[i]).longValue(), vmask); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue()))))); + } + } + } + + static short blend(short a, short b, boolean mask) { + return mask ? b : a; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16VectorMaxTests(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.blend(bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, mask, Float16VectorMaxTests::blend); + } + + @Test(dataProvider = "shortUnaryOpShuffleProvider") + static void RearrangeFloat16VectorMaxTests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i)).intoArray(r, i); + } + } + + assertRearrangeArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpShuffleMaskProvider") + static void RearrangeFloat16VectorMaxTestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + int[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.rearrange(VectorShuffle.fromArray(SPECIES, order, i), vmask).intoArray(r, i); + } + + assertRearrangeArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void compressFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.compress(vmask).intoArray(r, i); + } + } + + assertcompressArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void expandFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.expand(vmask).intoArray(r, i); + } + } + + assertexpandArraysEquals(r, a, mask, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void getFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int num_lanes = SPECIES.length(); + // Manually unroll because full unroll happens after intrinsification. + // Unroll is needed because get intrinsic requires for index to be a known constant. + if (num_lanes == 1) { + r[i]=av.lane(0); + } else if (num_lanes == 2) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + } else if (num_lanes == 4) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + } else if (num_lanes == 8) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + } else if (num_lanes == 16) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + } else if (num_lanes == 32) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + } else if (num_lanes == 64) { + r[i]=av.lane(0); + r[i+1]=av.lane(1); + r[i+2]=av.lane(2); + r[i+3]=av.lane(3); + r[i+4]=av.lane(4); + r[i+5]=av.lane(5); + r[i+6]=av.lane(6); + r[i+7]=av.lane(7); + r[i+8]=av.lane(8); + r[i+9]=av.lane(9); + r[i+10]=av.lane(10); + r[i+11]=av.lane(11); + r[i+12]=av.lane(12); + r[i+13]=av.lane(13); + r[i+14]=av.lane(14); + r[i+15]=av.lane(15); + r[i+16]=av.lane(16); + r[i+17]=av.lane(17); + r[i+18]=av.lane(18); + r[i+19]=av.lane(19); + r[i+20]=av.lane(20); + r[i+21]=av.lane(21); + r[i+22]=av.lane(22); + r[i+23]=av.lane(23); + r[i+24]=av.lane(24); + r[i+25]=av.lane(25); + r[i+26]=av.lane(26); + r[i+27]=av.lane(27); + r[i+28]=av.lane(28); + r[i+29]=av.lane(29); + r[i+30]=av.lane(30); + r[i+31]=av.lane(31); + r[i+32]=av.lane(32); + r[i+33]=av.lane(33); + r[i+34]=av.lane(34); + r[i+35]=av.lane(35); + r[i+36]=av.lane(36); + r[i+37]=av.lane(37); + r[i+38]=av.lane(38); + r[i+39]=av.lane(39); + r[i+40]=av.lane(40); + r[i+41]=av.lane(41); + r[i+42]=av.lane(42); + r[i+43]=av.lane(43); + r[i+44]=av.lane(44); + r[i+45]=av.lane(45); + r[i+46]=av.lane(46); + r[i+47]=av.lane(47); + r[i+48]=av.lane(48); + r[i+49]=av.lane(49); + r[i+50]=av.lane(50); + r[i+51]=av.lane(51); + r[i+52]=av.lane(52); + r[i+53]=av.lane(53); + r[i+54]=av.lane(54); + r[i+55]=av.lane(55); + r[i+56]=av.lane(56); + r[i+57]=av.lane(57); + r[i+58]=av.lane(58); + r[i+59]=av.lane(59); + r[i+60]=av.lane(60); + r[i+61]=av.lane(61); + r[i+62]=av.lane(62); + r[i+63]=av.lane(63); + } else { + for (int j = 0; j < SPECIES.length(); j++) { + r[i+j]=av.lane(j); + } + } + } + } + + assertArraysStrictlyEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void BroadcastFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, a[i]).intoArray(r, i); + } + } + + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ZeroFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.zero(SPECIES).intoArray(a, i); + } + } + + assertEquals(a, r); + } + + static short[] sliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else + res[i] = (short)0; + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sliceUnaryFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.slice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16VectorMaxTests::sliceUnary); + } + + static short[] sliceBinary(short[] a, short[] b, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = a[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void sliceBinaryFloat16VectorMaxTestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, Float16VectorMaxTests::sliceBinary); + } + + static short[] slice(short[] a, short[] b, int origin, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = mask[i] ? a[idx+i+origin] : (short)0; + else { + res[i] = mask[i] ? b[idx+j] : (short)0; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void sliceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.slice(origin, bv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, mask, Float16VectorMaxTests::slice); + } + + static short[] unsliceUnary(short[] a, int origin, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i < origin) + res[i] = (short)0; + else { + res[i] = a[idx+j]; + j++; + } + } + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void unsliceUnaryFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.unslice(origin).intoArray(r, i); + } + } + + assertArraysEquals(r, a, origin, Float16VectorMaxTests::unsliceUnary); + } + + static short[] unsliceBinary(short[] a, short[] b, int origin, int part, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (part == 0) { + if (i < origin) + res[i] = b[idx+i]; + else { + res[i] = a[idx+j]; + j++; + } + } else if (part == 1) { + if (i < origin) + res[i] = a[idx+SPECIES.length()-origin+i]; + else { + res[i] = b[idx+origin+j]; + j++; + } + } + } + return res; + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void unsliceBinaryFloat16VectorMaxTestsBinary(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, Float16VectorMaxTests::unsliceBinary); + } + + static short[] unslice(short[] a, short[] b, int origin, int part, boolean[] mask, int idx) { + short[] res = new short[SPECIES.length()]; + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if(i+origin < SPECIES.length()) + res[i] = b[idx+i+origin]; + else { + res[i] = b[idx+j]; + j++; + } + } + for (int i = 0; i < SPECIES.length(); i++){ + res[i] = mask[i] ? a[idx+i] : res[i]; + } + short[] res1 = new short[SPECIES.length()]; + if (part == 0) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = b[idx+i]; + else { + res1[i] = res[j]; + j++; + } + } + } else if (part == 1) { + for (int i = 0, j = 0; i < SPECIES.length(); i++){ + if (i < origin) + res1[i] = res[SPECIES.length()-origin+i]; + else { + res1[i] = b[idx+origin+j]; + j++; + } + } + } + return res1; + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void unsliceFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + short[] r = new short[a.length]; + int origin = RAND.nextInt(SPECIES.length()); + int part = RAND.nextInt(2); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.unslice(origin, bv, part, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, origin, part, mask, Float16VectorMaxTests::unslice); + } + + static short SIN(short a) { + return (short)(scalar_sin(a)); + } + + static short strictSIN(short a) { + return (short)(strict_scalar_sin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::SIN, Float16VectorMaxTests::strictSIN); + } + + static short EXP(short a) { + return (short)(scalar_exp(a)); + } + + static short strictEXP(short a) { + return (short)(strict_scalar_exp(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXP).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::EXP, Float16VectorMaxTests::strictEXP); + } + + static short LOG1P(short a) { + return (short)(scalar_log1p(a)); + } + + static short strictLOG1P(short a) { + return (short)(strict_scalar_log1p(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG1PFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG1P).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::LOG1P, Float16VectorMaxTests::strictLOG1P); + } + + static short LOG(short a) { + return (short)(scalar_log(a)); + } + + static short strictLOG(short a) { + return (short)(strict_scalar_log(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOGFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::LOG, Float16VectorMaxTests::strictLOG); + } + + static short LOG10(short a) { + return (short)(scalar_log10(a)); + } + + static short strictLOG10(short a) { + return (short)(strict_scalar_log10(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void LOG10Float16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.LOG10).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::LOG10, Float16VectorMaxTests::strictLOG10); + } + + static short EXPM1(short a) { + return (short)(scalar_expm1(a)); + } + + static short strictEXPM1(short a) { + return (short)(strict_scalar_expm1(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void EXPM1Float16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.EXPM1).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::EXPM1, Float16VectorMaxTests::strictEXPM1); + } + + static short COS(short a) { + return (short)(scalar_cos(a)); + } + + static short strictCOS(short a) { + return (short)(strict_scalar_cos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::COS, Float16VectorMaxTests::strictCOS); + } + + static short TAN(short a) { + return (short)(scalar_tan(a)); + } + + static short strictTAN(short a) { + return (short)(strict_scalar_tan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::TAN, Float16VectorMaxTests::strictTAN); + } + + static short SINH(short a) { + return (short)(scalar_sinh(a)); + } + + static short strictSINH(short a) { + return (short)(strict_scalar_sinh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SINHFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SINH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::SINH, Float16VectorMaxTests::strictSINH); + } + + static short COSH(short a) { + return (short)(scalar_cosh(a)); + } + + static short strictCOSH(short a) { + return (short)(strict_scalar_cosh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void COSHFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.COSH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::COSH, Float16VectorMaxTests::strictCOSH); + } + + static short TANH(short a) { + return (short)(scalar_tanh(a)); + } + + static short strictTANH(short a) { + return (short)(strict_scalar_tanh(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void TANHFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.TANH).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::TANH, Float16VectorMaxTests::strictTANH); + } + + static short ASIN(short a) { + return (short)(scalar_asin(a)); + } + + static short strictASIN(short a) { + return (short)(strict_scalar_asin(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ASINFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ASIN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::ASIN, Float16VectorMaxTests::strictASIN); + } + + static short ACOS(short a) { + return (short)(scalar_acos(a)); + } + + static short strictACOS(short a) { + return (short)(strict_scalar_acos(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ACOSFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ACOS).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::ACOS, Float16VectorMaxTests::strictACOS); + } + + static short ATAN(short a) { + return (short)(scalar_atan(a)); + } + + static short strictATAN(short a) { + return (short)(strict_scalar_atan(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ATANFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ATAN).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::ATAN, Float16VectorMaxTests::strictATAN); + } + + static short CBRT(short a) { + return (short)(scalar_cbrt(a)); + } + + static short strictCBRT(short a) { + return (short)(strict_scalar_cbrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void CBRTFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.CBRT).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, Float16VectorMaxTests::CBRT, Float16VectorMaxTests::strictCBRT); + } + + static short HYPOT(short a, short b) { + return (short)(scalar_hypot(a, b)); + } + + static short strictHYPOT(short a, short b) { + return (short)(strict_scalar_hypot(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void HYPOTFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.HYPOT, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16VectorMaxTests::HYPOT, Float16VectorMaxTests::strictHYPOT); + } + + + static short POW(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictPOW(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.POW, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16VectorMaxTests::POW, Float16VectorMaxTests::strictPOW); + } + + + static short pow(short a, short b) { + return (short)(scalar_pow(a, b)); + } + + static short strictpow(short a, short b) { + return (short)(strict_scalar_pow(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.pow(bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16VectorMaxTests::pow, Float16VectorMaxTests::strictpow); + } + + + static short ATAN2(short a, short b) { + return (short)(scalar_atan2(a, b)); + } + + static short strictATAN2(short a, short b) { + return (short)(strict_scalar_atan2(a, b)); + } + + @Test(dataProvider = "shortBinaryOpProvider") + static void ATAN2Float16VectorMaxTests(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.ATAN2, bv).intoArray(r, i); + } + } + + assertArraysEqualsWithinOneUlp(r, a, b, Float16VectorMaxTests::ATAN2, Float16VectorMaxTests::strictATAN2); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void POWFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.POW, b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16VectorMaxTests::POW, Float16VectorMaxTests::strictPOW); + } + + + @Test(dataProvider = "shortBinaryOpProvider") + static void powFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.pow(b[i]).intoArray(r, i); + } + + assertBroadcastArraysEqualsWithinOneUlp(r, a, b, Float16VectorMaxTests::pow, Float16VectorMaxTests::strictpow); + } + + + static short FMA(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + static short fma(short a, short b, short c) { + return (short)(scalar_fma(a, b, c)); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16VectorMaxTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16VectorMaxTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.fma(bv, cv).intoArray(r, i); + } + + assertArraysEquals(r, a, b, c, Float16VectorMaxTests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, bv, cv, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, c, mask, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i]).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a, b, c, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16VectorMaxTestsAltBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv).intoArray(r, i); + } + assertAltBroadcastArraysEquals(r, a, b, c, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + av.lanewise(VectorOperators.FMA, bv, c[i], vmask).intoArray(r, i); + } + + assertBroadcastArraysEquals(r, a, b, c, mask, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16VectorMaxTestsAltBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector cv = Float16Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.FMA, b[i], cv, vmask).intoArray(r, i); + } + + assertAltBroadcastArraysEquals(r, a, b, c, mask, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void FMAFloat16VectorMaxTestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16VectorMaxTests::FMA); + } + + @Test(dataProvider = "shortTernaryOpProvider") + static void fmaFloat16VectorMaxTestsDoubleBroadcastSmokeTest(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.fma(b[i], c[i]).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, Float16VectorMaxTests::fma); + } + + @Test(dataProvider = "shortTernaryOpMaskProvider") + static void FMAFloat16VectorMaxTestsDoubleBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.FMA, b[i], c[i], vmask).intoArray(r, i); + } + + assertDoubleBroadcastArraysEquals(r, a, b, c, mask, Float16VectorMaxTests::FMA); + } + + static short NEG(short a) { + return (short)(scalar_neg((short)a)); + } + + static short neg(short a) { + return (short)(scalar_neg((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void NEGFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::NEG); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void negFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.neg().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::neg); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void NEGMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.NEG, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16VectorMaxTests::NEG); + } + + static short ABS(short a) { + return (short)(scalar_abs((short)a)); + } + + static short abs(short a) { + return (short)(scalar_abs((short)a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ABSFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::ABS); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void absFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.abs().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::abs); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ABSMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.ABS, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16VectorMaxTests::ABS); + } + + static short SQRT(short a) { + return (short)(scalar_sqrt(a)); + } + + static short sqrt(short a) { + return (short)(scalar_sqrt(a)); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void SQRTFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT).intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::SQRT); + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void sqrtFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.sqrt().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::sqrt); + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void SQRTMaskedFloat16VectorMaxTests(IntFunction fa, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.lanewise(VectorOperators.SQRT, vmask).intoArray(r, i); + } + } + + assertArraysEquals(r, a, mask, Float16VectorMaxTests::SQRT); + } + + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float16VectorMaxTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat16VectorMaxTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float16VectorMaxTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat16VectorMaxTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + + @Test(dataProvider = "shortCompareOpProvider") + static void ltFloat16VectorMaxTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.lt(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shortCompareOpProvider") + static void eqFloat16VectorMaxTestsBroadcastMaskedSmokeTest(IntFunction fa, IntFunction fb) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + VectorMask mv = av.eq(b[i]); + + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); + } + } + } + + @Test(dataProvider = "shorttoIntUnaryOpProvider") + static void toIntArrayFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int[] r = av.toIntArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void toLongArrayFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + long[] r = av.toLongArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toDoubleArrayFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + double[] r = av.toDoubleArray(); + assertArraysEquals(r, a, i); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void toStringFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + String str = av.toString(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals(Arrays.toString(subarr)), "at index " + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void hashCodeFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + int hash = av.hashCode(); + + short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + + static long ADDReduceLong(short[] a, int idx) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = scalar_add(res, a[i]); + } + + return (long)res; + } + + static long ADDReduceAllLong(short[] a) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void ADDReduceLongFloat16VectorMaxTests(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEquals(r, ra, a, + Float16VectorMaxTests::ADDReduceLong, Float16VectorMaxTests::ADDReduceAllLong); + } + + static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { + short res = 0; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } + } + + return (long)res; + } + + static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { + long res = 0; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void ADDReduceLongFloat16VectorMaxTestsMasked(IntFunction fa, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + long[] r = lfr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = 0; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanesToLong(VectorOperators.ADD, vmask); + } + + ra = 0; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); + } + + assertReductionLongArraysEqualsMasked(r, ra, a, mask, + Float16VectorMaxTests::ADDReduceLongMasked, Float16VectorMaxTests::ADDReduceAllLongMasked); + } + + @Test(dataProvider = "shorttoLongUnaryOpProvider") + static void BroadcastLongFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = new short[a.length]; + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector.broadcast(SPECIES, shortBitsToFloat16(a[i]).longValue()).intoArray(r, i); + } + assertBroadcastArraysEquals(r, a); + } + + @Test(dataProvider = "shortBinaryOpMaskProvider") + static void blendFloat16VectorMaxTestsBroadcastLongSmokeTest(IntFunction fa, IntFunction fb, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + av.blend(shortBitsToFloat16(b[i]).longValue(), vmask).intoArray(r, i); + } + } + assertBroadcastLongArraysEquals(r, a, b, mask, Float16VectorMaxTests::blend); + } + + + @Test(dataProvider = "shortUnaryOpSelectFromProvider") + static void SelectFromFloat16VectorMaxTests(IntFunction fa, + BiFunction fs) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, SPECIES.length()); + } + + @Test(dataProvider = "shortSelectFromTwoVectorOpProvider") + static void SelectFromTwoVectorFloat16VectorMaxTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] idx = fc.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < idx.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, b, i); + Float16Vector idxv = Float16Vector.fromArray(SPECIES, idx, i); + idxv.selectFrom(av, bv).intoArray(r, i); + } + } + assertSelectFromTwoVectorEquals(r, idx, a, b, SPECIES.length()); + } + + @Test(dataProvider = "shortUnaryOpSelectFromMaskProvider") + static void SelectFromFloat16VectorMaxTestsMaskedSmokeTest(IntFunction fa, + BiFunction fs, + IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] order = fs.apply(a.length, SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + Float16Vector av = Float16Vector.fromArray(SPECIES, a, i); + Float16Vector bv = Float16Vector.fromArray(SPECIES, order, i); + bv.selectFrom(av, vmask).intoArray(r, i); + } + + assertSelectFromArraysEquals(r, a, order, mask, SPECIES.length()); + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleMiscellaneousFloat16VectorMaxTestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + int hash = shuffle.hashCode(); + int length = shuffle.length(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + assertEquals(length, SPECIES.length()); + } + } + + @Test(dataProvider = "shuffleProvider") + static void shuffleToStringFloat16VectorMaxTestsSmokeTest(BiFunction fs) { + int[] a = fs.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var shuffle = VectorShuffle.fromArray(SPECIES, a, i); + String str = shuffle.toString(); + + int subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + Assert.assertTrue(str.equals("Shuffle" + Arrays.toString(subarr)), "at index " + + i + ", string should be = " + Arrays.toString(subarr) + ", but is = " + str); + } + } + + @Test(dataProvider = "shuffleCompareOpProvider") + static void shuffleEqualsFloat16VectorMaxTestsSmokeTest(BiFunction fa, BiFunction fb) { + int[] a = fa.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + int[] b = fb.apply(SPECIES.length() * BUFFER_REPS, SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = VectorShuffle.fromArray(SPECIES, a, i); + var bv = VectorShuffle.fromArray(SPECIES, b, i); + boolean eq = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(eq, Arrays.equals(a, i, to, b, i, to)); + } + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat16VectorMaxTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } + } + } + + @Test(dataProvider = "maskProvider") + static void maskHashCodeFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + int hash = vmask.hashCode(); + + boolean subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length()); + int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr)); + Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash); + } + } + + static int maskTrueCount(boolean[] a, int idx) { + int trueCount = 0; + for (int i = idx; i < idx + SPECIES.length(); i++) { + trueCount += a[i] ? 1 : 0; + } + return trueCount; + } + + @Test(dataProvider = "maskProvider") + static void maskTrueCountFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.trueCount(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16VectorMaxTests::maskTrueCount); + } + + static int maskLastTrue(boolean[] a, int idx) { + int i = idx + SPECIES.length() - 1; + for (; i >= idx; i--) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskLastTrueFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.lastTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16VectorMaxTests::maskLastTrue); + } + + static int maskFirstTrue(boolean[] a, int idx) { + int i = idx; + for (; i < idx + SPECIES.length(); i++) { + if (a[i]) { + break; + } + } + return i - idx; + } + + @Test(dataProvider = "maskProvider") + static void maskFirstTrueFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + int[] r = new int[a.length]; + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + r[i] = vmask.firstTrue(); + } + } + + assertMaskReductionArraysEquals(r, a, Float16VectorMaxTests::maskFirstTrue); + } + + @Test(dataProvider = "maskProvider") + static void maskCompressFloat16VectorMaxTestsSmokeTest(IntFunction fa) { + int trueCount = 0; + boolean[] a = fa.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT * INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var vmask = SPECIES.loadMask(a, i); + trueCount = vmask.trueCount(); + var rmask = vmask.compress(); + for (int j = 0; j < SPECIES.length(); j++) { + assertEquals(rmask.laneIsSet(j), j < trueCount); + } + } + } + } + + @DataProvider + public static Object[][] offsetProvider() { + return new Object[][]{ + {0}, + {-1}, + {+1}, + {+2}, + {-2}, + }; + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeFloat16VectorMaxTestsSmokeTest(int offset) { + int limit = SPECIES.length() * BUFFER_REPS; + for (int i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + int index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @Test(dataProvider = "offsetProvider") + static void indexInRangeLongFloat16VectorMaxTestsSmokeTest(int offset) { + long limit = SPECIES.length() * BUFFER_REPS; + for (long i = 0; i < limit; i += SPECIES.length()) { + var actualMask = SPECIES.indexInRange(i + offset, limit); + var expectedMask = SPECIES.maskAll(true).indexInRange(i + offset, limit); + assert(actualMask.equals(expectedMask)); + for (int j = 0; j < SPECIES.length(); j++) { + long index = i + j + offset; + assertEquals(actualMask.laneIsSet(j), index >= 0 && index < limit); + } + } + } + + @DataProvider + public static Object[][] lengthProvider() { + return new Object[][]{ + {0}, + {1}, + {32}, + {37}, + {1024}, + {1024+1}, + {1024+5}, + }; + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundFloat16VectorMaxTestsSmokeTest(int length) { + int actualLoopBound = SPECIES.loopBound(length); + int expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test(dataProvider = "lengthProvider") + static void loopBoundLongFloat16VectorMaxTestsSmokeTest(int _length) { + long length = _length; + long actualLoopBound = SPECIES.loopBound(length); + long expectedLoopBound = length - Math.floorMod(length, SPECIES.length()); + assertEquals(actualLoopBound, expectedLoopBound); + } + + @Test + static void ElementSizeFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + int elsize = av.elementSize(); + assertEquals(elsize, Float16.SIZE); + } + + @Test + static void VectorShapeFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + assert(vsh.equals(VectorShape.S_Max_BIT)); + } + + @Test + static void ShapeWithLanesFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = vsh.withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void ElementTypeFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementType() == Float16.class); + } + + @Test + static void SpeciesElementSizeFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().elementSize() == Float16.SIZE); + } + + @Test + static void VectorTypeFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + assert(av.species().vectorType() == av.getClass()); + } + + @Test + static void WithLanesFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorSpecies species = av.species().withLanes(Float16.class); + assert(species.equals(SPECIES)); + } + + @Test + static void WithShapeFloat16VectorMaxTestsSmokeTest() { + Float16Vector av = Float16Vector.zero(SPECIES); + VectorShape vsh = av.shape(); + VectorSpecies species = av.species().withShape(vsh); + assert(species.equals(SPECIES)); + } + + @Test + static void MaskAllTrueFloat16VectorMaxTestsSmokeTest() { + for (int ic = 0; ic < INVOC_COUNT; ic++) { + assertEquals(SPECIES.maskAll(true).toLong(), -1L >>> (64 - SPECIES.length())); + } + } +} diff --git a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java index 40de51c90ab..1573748b925 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java @@ -1719,9 +1719,14 @@ public class ShortVector128Tests extends AbstractVectorTest { assertEquals(asIntegral.species(), SPECIES); } - @Test(expectedExceptions = UnsupportedOperationException.class) + @Test void viewAsFloatingLanesTest() { - SPECIES.zero().viewAsFloatingLanes(); + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + VectorSpecies asFloatingSpecies = asFloating.species(); + Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType()); + assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asFloatingSpecies.length(), SPECIES.length()); + assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES); } @Test diff --git a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java index c28dd34c8ef..059388477e8 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java @@ -1719,9 +1719,14 @@ public class ShortVector256Tests extends AbstractVectorTest { assertEquals(asIntegral.species(), SPECIES); } - @Test(expectedExceptions = UnsupportedOperationException.class) + @Test void viewAsFloatingLanesTest() { - SPECIES.zero().viewAsFloatingLanes(); + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + VectorSpecies asFloatingSpecies = asFloating.species(); + Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType()); + assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asFloatingSpecies.length(), SPECIES.length()); + assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES); } @Test diff --git a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java index 703ef7d358b..3e39d1bc32f 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java @@ -1719,9 +1719,14 @@ public class ShortVector512Tests extends AbstractVectorTest { assertEquals(asIntegral.species(), SPECIES); } - @Test(expectedExceptions = UnsupportedOperationException.class) + @Test void viewAsFloatingLanesTest() { - SPECIES.zero().viewAsFloatingLanes(); + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + VectorSpecies asFloatingSpecies = asFloating.species(); + Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType()); + assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asFloatingSpecies.length(), SPECIES.length()); + assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES); } @Test diff --git a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java index ea6846498a3..e78eb2ee283 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java @@ -1719,9 +1719,14 @@ public class ShortVector64Tests extends AbstractVectorTest { assertEquals(asIntegral.species(), SPECIES); } - @Test(expectedExceptions = UnsupportedOperationException.class) + @Test void viewAsFloatingLanesTest() { - SPECIES.zero().viewAsFloatingLanes(); + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + VectorSpecies asFloatingSpecies = asFloating.species(); + Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType()); + assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asFloatingSpecies.length(), SPECIES.length()); + assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES); } @Test diff --git a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java index 6a85da12054..dbcb6912323 100644 --- a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java @@ -1725,9 +1725,14 @@ public class ShortVectorMaxTests extends AbstractVectorTest { assertEquals(asIntegral.species(), SPECIES); } - @Test(expectedExceptions = UnsupportedOperationException.class) + @Test void viewAsFloatingLanesTest() { - SPECIES.zero().viewAsFloatingLanes(); + Vector asFloating = SPECIES.zero().viewAsFloatingLanes(); + VectorSpecies asFloatingSpecies = asFloating.species(); + Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType()); + assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape()); + assertEquals(asFloatingSpecies.length(), SPECIES.length()); + assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES); } @Test diff --git a/test/jdk/jdk/incubator/vector/gen-tests.sh b/test/jdk/jdk/incubator/vector/gen-tests.sh index 8b5c4cac616..6890f4e1cdd 100644 --- a/test/jdk/jdk/incubator/vector/gen-tests.sh +++ b/test/jdk/jdk/incubator/vector/gen-tests.sh @@ -52,11 +52,11 @@ Log false "$compilation\n" Log true "done\n" # For each type -for type in byte short int long float double +for type in byte short int long float double float16 do Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${type})" - args="-K$type -Dtype=$type -DType=$Type -DTYPE=$TYPE" + args="-K$type -DType=$Type -DTYPE=$TYPE" Boxtype=$Type Wideboxtype=$Boxtype @@ -69,6 +69,7 @@ do bitstype=$type Bitstype=$Type Boxbitstype=$Boxtype + testtype=$type fptype=$type Fptype=$Type @@ -118,11 +119,23 @@ do MaxValue=POSITIVE_INFINITY MinValue=NEGATIVE_INFINITY ;; + float16) + kind=FP + fpkind=FP16 + bitstype=short + type=short + Bitstype=Short + Boxbitstype=Short + Wideboxtype=Float16 + MaxValue=POSITIVE_INFINITY + MinValue=NEGATIVE_INFINITY + Type=Float16 + ;; esac - args="$args -K$kind -K$fpkind -K$Type -DBoxtype=$Boxtype -DWideboxtype=$Wideboxtype -DMaxValue=$MaxValue -DMinValue=$MinValue" + args="$args -Dtype=$type -K$kind -K$Type -DBoxtype=$Boxtype -DWideboxtype=$Wideboxtype -DMaxValue=$MaxValue -DMinValue=$MinValue" args="$args -Dbitstype=$bitstype -DBitstype=$Bitstype -DBoxbitstype=$Boxbitstype" - args="$args -Dfptype=$fptype -DFptype=$Fptype -DBoxfptype=$Boxfptype" + args="$args -Dtesttype=$testtype -K$fpkind -Dfptype=$fptype -DFptype=$Fptype -DBoxfptype=$Boxfptype" abstractvectortype=${typeprefix}${Type}Vector abstractvectorteststype=${typeprefix}${Type}VectorTests diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Long-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Long-op.template index a4cea57471a..c48c658cdd8 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Long-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Long-op.template @@ -4,5 +4,5 @@ for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - av.lanewise(VectorOperators.[[TEST]], (long)b[i]).intoArray(r, i); + av.lanewise(VectorOperators.[[TEST]], {#if[FP16]?shortBitsToFloat16(b[i]).longValue():(long)b[i]}).intoArray(r, i); } diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Masked-Long-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Masked-Long-op.template index 16343eeaf40..2531f048300 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Masked-Long-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-Binary-Broadcast-Masked-Long-op.template @@ -6,5 +6,5 @@ for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - av.lanewise(VectorOperators.[[TEST]], (long)b[i], vmask).intoArray(r, i); + av.lanewise(VectorOperators.[[TEST]], {#if[FP16]?shortBitsToFloat16(b[i]).longValue():(long)b[i]}, vmask).intoArray(r, i); } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template b/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template index faae74426e7..b59fd1a793f 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template @@ -43,11 +43,11 @@ for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - VectorMask<$Wideboxtype$> mv = av.compare(VectorOperators.[[TEST]], (long)b[i]); + VectorMask<$Wideboxtype$> mv = av.compare(VectorOperators.[[TEST]], {#if[FP16]?shortBitsToFloat16(b[i]).longValue():(long)b[i]}); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), [[TEST_OP]](a[i + j], ($type$)((long)b[i]))); + assertEquals(mv.laneIsSet(j), [[TEST_OP]](a[i + j], {#if[FP16]?float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())):($type$)((long)b[i])})); } } } @@ -63,11 +63,11 @@ for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - VectorMask<$Wideboxtype$> mv = av.compare(VectorOperators.[[TEST]], (long)b[i], vmask); + VectorMask<$Wideboxtype$> mv = av.compare(VectorOperators.[[TEST]], {#if[FP16]?shortBitsToFloat16(b[i]).longValue():(long)b[i]}, vmask); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && ([[TEST_OP]](a[i + j], ($type$)((long)b[i])))); + assertEquals(mv.laneIsSet(j), mask[j] && ([[TEST_OP]](a[i + j], {#if[FP16]?float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[i]).longValue())):($type$)((long)b[i])}))); } } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template index 5ad7623d2c0..8606b9ba598 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template @@ -210,7 +210,7 @@ $type$[] r = new $type$[a.length]; for (int i = 0; i < a.length; i += SPECIES.length()) { - $abstractvectortype$.broadcast(SPECIES, (long)a[i]).intoArray(r, i); + $abstractvectortype$.broadcast(SPECIES, {#if[FP16]?shortBitsToFloat16(a[i]).longValue():(long)a[i]}).intoArray(r, i); } assertBroadcastArraysEquals(r, a); } @@ -227,7 +227,7 @@ for (int ic = 0; ic < INVOC_COUNT; ic++) { for (int i = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - av.blend((long)b[i], vmask).intoArray(r, i); + av.blend({#if[FP16]?shortBitsToFloat16(b[i]).longValue():(long)b[i]}, vmask).intoArray(r, i); } } assertBroadcastLongArraysEquals(r, a, b, mask, $vectorteststype$::blend); @@ -588,14 +588,14 @@ static void ShapeWithLanes$vectorteststype$SmokeTest() { $abstractvectortype$ av = $abstractvectortype$.zero(SPECIES); VectorShape vsh = av.shape(); - VectorSpecies species = vsh.withLanes($type$.class); + VectorSpecies species = vsh.withLanes({#if[FP16]?Float16.class:$type$.class}); assert(species.equals(SPECIES)); } @Test static void ElementType$vectorteststype$SmokeTest() { $abstractvectortype$ av = $abstractvectortype$.zero(SPECIES); - assert(av.species().elementType() == $type$.class); + assert(av.species().elementType() == {#if[FP16]?Float16.class:$type$.class}); } @Test @@ -613,7 +613,7 @@ @Test static void WithLanes$vectorteststype$SmokeTest() { $abstractvectortype$ av = $abstractvectortype$.zero(SPECIES); - VectorSpecies species = av.species().withLanes($type$.class); + VectorSpecies species = av.species().withLanes({#if[FP16]?Float16.class:$type$.class}); assert(species.equals(SPECIES)); } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index b87012a2181..eac7edbbb3f 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -48,6 +48,11 @@ import jdk.incubator.vector.ByteVector; #if[Float] import jdk.incubator.vector.FloatVector; #end[Float] +#if[FP16] +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import jdk.incubator.vector.Float16Vector; +#end[FP16] #if[Int] import jdk.incubator.vector.IntVector; #end[Int] @@ -86,6 +91,38 @@ public class $vectorteststype$ extends AbstractVectorTest { #end[MaxBit] static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); +#if[FP16] + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + static void assertEquals(short actual, short expected, short delta) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta)); + } + static void assertEquals(short actual, short expected, short delta, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), Float.float16ToFloat(delta), msg); + } + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } + static void assertEquals(long actual, long expected) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected)); + } + static void assertEquals(long actual, long expected, String msg) { + Assert.assertEquals(Float.float16ToFloat((short)actual), Float.float16ToFloat((short)expected), msg); + } +#else[FP16] static void assertEquals($type$ actual, $type$ expected) { Assert.assertEquals(actual, expected); } @@ -112,6 +149,7 @@ public class $vectorteststype$ extends AbstractVectorTest { Assert.assertEquals(actual, expected, msg); } #end[!long] +#end[FP16] static void assertEquals(String actual, String expected) { Assert.assertEquals(actual, expected); } @@ -152,9 +190,9 @@ public class $vectorteststype$ extends AbstractVectorTest { private static final $type$ AND_IDENTITY = ($type$)-1; #end[BITWISE] private static final $type$ FIRST_NONZERO_IDENTITY = ($type$)0; - private static final $type$ MAX_IDENTITY = $Wideboxtype$.$MinValue$; - private static final $type$ MIN_IDENTITY = $Wideboxtype$.$MaxValue$; - private static final $type$ MUL_IDENTITY = ($type$)1; + private static final $type$ MAX_IDENTITY = {#if[FP16]?float16ToRawShortBits($Wideboxtype$.$MinValue$):$Wideboxtype$.$MinValue$}; + private static final $type$ MIN_IDENTITY = {#if[FP16]?float16ToRawShortBits($Wideboxtype$.$MaxValue$):$Wideboxtype$.$MaxValue$}; + private static final $type$ MUL_IDENTITY = {#if[FP16]?float16ToRawShortBits(Float16.valueOf(1.0f)):($type$)1}; #if[BITWISE] private static final $type$ OR_IDENTITY = ($type$)0; private static final $type$ SUADD_IDENTITY = ($type$)0; @@ -165,10 +203,10 @@ public class $vectorteststype$ extends AbstractVectorTest { #if[FP] // for floating point addition reduction ops that may introduce rounding errors - private static final $type$ RELATIVE_ROUNDING_ERROR_FACTOR_ADD = ($type$)10.0; + private static final $type$ RELATIVE_ROUNDING_ERROR_FACTOR_ADD = {#if[FP16]?float16ToRawShortBits(Float16.valueOf(10.0f)):($type$)10.0}; // for floating point multiplication reduction ops that may introduce rounding errors - private static final $type$ RELATIVE_ROUNDING_ERROR_FACTOR_MUL = ($type$)50.0; + private static final $type$ RELATIVE_ROUNDING_ERROR_FACTOR_MUL = {#if[FP16]?float16ToRawShortBits(Float16.valueOf(50.0f)):($type$)50.0}; #end[FP] static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / $bits$); @@ -176,8 +214,8 @@ public class $vectorteststype$ extends AbstractVectorTest { static void assertArraysStrictlyEquals($type$[] r, $type$[] a) { for (int i = 0; i < a.length; i++) { #if[FP] - $bitstype$ ir = $Wideboxtype$.$type$ToRaw$Bitstype$Bits(r[i]); - $bitstype$ ia = $Wideboxtype$.$type$ToRaw$Bitstype$Bits(a[i]); + $bitstype$ ir = {#if[FP16]?r[i]:$Wideboxtype$.$type$ToRaw$Bitstype$Bits(r[i])}; + $bitstype$ ia = {#if[FP16]?a[i]:$Wideboxtype$.$type$ToRaw$Bitstype$Bits(a[i])}; if (ir != ia) { #if[Float] Assert.fail(String.format("at index #%d, expected = %08X, actual = %08X", i, ia, ir)); @@ -265,6 +303,23 @@ public class $vectorteststype$ extends AbstractVectorTest { #end[FP] } #if[FP] +#if[FP16] + + static void assertReductionArraysEquals($type$[] r, $type$ rc, $type$[] a, + FReductionOp f, FReductionAllOp fa, + $type$ relativeErrorFactor) { + int i = 0; + try { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor)))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor)))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(rc)), shortBitsToFloat16(relativeErrorFactor))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i), float16ToRawShortBits(Float16.multiply(Float16.ulp(shortBitsToFloat16(r[i])), shortBitsToFloat16(relativeErrorFactor))), "at index #" + i); + } + } +#else[FP16] static void assertReductionArraysEquals($type$[] r, $type$ rc, $type$[] a, FReductionOp f, FReductionAllOp fa, @@ -280,6 +335,7 @@ public class $vectorteststype$ extends AbstractVectorTest { assertEquals(r[i], f.apply(a, i), Math.ulp(r[i]) * relativeErrorFactor, "at index #" + i); } } +#end[FP16] #end[FP] interface FReductionMaskedOp { @@ -308,6 +364,23 @@ public class $vectorteststype$ extends AbstractVectorTest { #end[FP] } #if[FP] +#if[FP16] + + static void assertReductionArraysEqualsMasked($type$[] r, $type$ rc, $type$[] a, boolean[] mask, + FReductionMaskedOp f, FReductionAllMaskedOp fa, + $type$ relativeError) { + int i = 0; + try { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError))))); + for (; i < a.length; i += SPECIES.length()) { + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError))))); + } + } catch (AssertionError e) { + assertEquals(rc, fa.apply(a, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(rc), shortBitsToFloat16(relativeError)))), "Final result is incorrect!"); + assertEquals(r[i], f.apply(a, i, mask), float16ToRawShortBits(Float16.abs(Float16.multiply(shortBitsToFloat16(r[i]), shortBitsToFloat16(relativeError)))), "at index #" + i); + } + } +#else[FP16] static void assertReductionArraysEqualsMasked($type$[] r, $type$ rc, $type$[] a, boolean[] mask, FReductionMaskedOp f, FReductionAllMaskedOp fa, @@ -324,6 +397,7 @@ relativeError)); assertEquals(r[i], f.apply(a, i, mask), Math.abs(r[i] * relativeError), "at index #" + i); } } +#end[FP16] #end[FP] #if[!Long] @@ -473,7 +547,7 @@ relativeError)); for (; i < a.length; i += vector_len) { for (j = 0; j < vector_len; j++) { idx = i + j; - wrapped_index = Math.floorMod((int)order[idx], 2 * vector_len); + wrapped_index = Math.floorMod({#if[FP16]?shortBitsToFloat16(order[idx]).intValue():(int)order[idx]}, 2 * vector_len); is_exceptional_idx = wrapped_index >= vector_len; oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index; assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx])); @@ -489,12 +563,12 @@ relativeError)); try { for (; i < a.length; i += vector_len) { for (j = 0; j < vector_len; j++) { - assertEquals(r[i+j], a[i+(int)order[i+j]]); + assertEquals(r[i+j], a[i+{#if[FP16]?shortBitsToFloat16(order[i+j]).intValue():(int)order[i+j]}]); } } } catch (AssertionError e) { int idx = i + j; - assertEquals(r[i+j], a[i+(int)order[i+j]], "at index #" + idx + ", input = " + a[i+(int)order[i+j]]); + assertEquals(r[i+j], a[i+{#if[FP16]?shortBitsToFloat16(order[i+j]).intValue():(int)order[i+j]}], "at index #" + idx + ", input = " + a[i+{#if[FP16]?shortBitsToFloat16(order[i+j]).intValue():(int)order[i+j]}]); } } @@ -524,7 +598,7 @@ relativeError)); for (; i < a.length; i += vector_len) { for (j = 0; j < vector_len; j++) { if (mask[j % SPECIES.length()]) - assertEquals(r[i+j], a[i+(int)order[i+j]]); + assertEquals(r[i+j], a[i+{#if[FP16]?shortBitsToFloat16(order[i+j]).intValue():(int)order[i+j]}]); else assertEquals(r[i+j], ($type$)0); } @@ -532,7 +606,7 @@ relativeError)); } catch (AssertionError e) { int idx = i + j; if (mask[j % SPECIES.length()]) - assertEquals(r[i+j], a[i+(int)order[i+j]], "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); + assertEquals(r[i+j], a[i+{#if[FP16]?shortBitsToFloat16(order[i+j]).intValue():(int)order[i+j]}], "at index #" + idx + ", input = " + a[i+{#if[FP16]?shortBitsToFloat16(order[i+j]).intValue():(int)order[i+j]}] + ", mask = " + mask[j % SPECIES.length()]); else assertEquals(r[i+j], ($type$)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]); } @@ -681,10 +755,10 @@ relativeError)); int i = 0; try { for (; i < a.length; i++) { - assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()]))); + assertEquals(r[i], f.apply(a[i], {#if[FP16]?float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())):($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])})); } } catch (AssertionError e) { - assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])), + assertEquals(r[i], f.apply(a[i], {#if[FP16]?float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())):($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])}), "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i); } } @@ -745,10 +819,10 @@ relativeError)); int i = 0; try { for (; i < a.length; i++) { - assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()]), mask[i % SPECIES.length()])); + assertEquals(r[i], f.apply(a[i], {#if[FP16]?float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())):($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])}, mask[i % SPECIES.length()])); } } catch (AssertionError err) { - assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()]), + assertEquals(r[i], f.apply(a[i], {#if[FP16]?float16ToRawShortBits(Float16.valueOf(shortBitsToFloat16(b[(i / SPECIES.length()) * SPECIES.length()]).longValue())):($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])}, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + mask[i % SPECIES.length()]); @@ -978,6 +1052,26 @@ relativeError)); #if[FP] static boolean isWithin1Ulp($type$ actual, $type$ expected) { +#if[FP16] + Float16 act = shortBitsToFloat16(actual); + Float16 exp = shortBitsToFloat16(expected); + if (Float16.isNaN(exp) && !Float16.isNaN(act)) { + return false; + } else if (!Float16.isNaN(exp) && Float16.isNaN(act)) { + return false; + } + + Float16 low = Float16.nextDown(exp); + Float16 high = Float16.nextUp(exp); + + if (Float16.compare(low, exp) > 0) { + return false; + } + + if (Float16.compare(high, exp) < 0) { + return false; + } +#else[FP16] if ($Type$.isNaN(expected) && !$Type$.isNaN(actual)) { return false; } else if (!$Type$.isNaN(expected) && $Type$.isNaN(actual)) { @@ -994,6 +1088,7 @@ relativeError)); if ($Type$.compare(high, expected) < 0) { return false; } +#end[FP16] return true; } @@ -1003,11 +1098,11 @@ relativeError)); try { // Check that result is within 1 ulp of strict math or equivalent to math implementation. for (; i < a.length; i++) { - Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i])) == 0 || + Assert.assertTrue($Wideboxtype$.compare({#if[FP16]?shortBitsToFloat16(r[i]):r[i]}, {#if[FP16]?shortBitsToFloat16(mathf.apply(a[i])):mathf.apply(a[i])}) == 0 || isWithin1Ulp(r[i], strictmathf.apply(a[i]))); } } catch (AssertionError e) { - Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i])) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); + Assert.assertTrue($Wideboxtype$.compare({#if[FP16]?shortBitsToFloat16(r[i]):r[i]}, {#if[FP16]?shortBitsToFloat16(mathf.apply(a[i])):mathf.apply(a[i])}) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i])); Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i])); } } @@ -1017,11 +1112,11 @@ relativeError)); try { // Check that result is within 1 ulp of strict math or equivalent to math implementation. for (; i < a.length; i++) { - Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i], b[i])) == 0 || + Assert.assertTrue($Wideboxtype$.compare({#if[FP16]?shortBitsToFloat16(r[i]):r[i]}, {#if[FP16]?shortBitsToFloat16(mathf.apply(a[i], b[i])):mathf.apply(a[i], b[i])}) == 0 || isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i]))); } } catch (AssertionError e) { - Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i], b[i])) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); + Assert.assertTrue($Wideboxtype$.compare({#if[FP16]?shortBitsToFloat16(r[i]):r[i]}, {#if[FP16]?shortBitsToFloat16(mathf.apply(a[i], b[i])):mathf.apply(a[i], b[i])}) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i])); Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i])); } } @@ -1032,14 +1127,14 @@ relativeError)); try { // Check that result is within 1 ulp of strict math or equivalent to math implementation. for (; i < a.length; i++) { - Assert.assertTrue($Type$.compare(r[i], - mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])) == 0 || + Assert.assertTrue($Wideboxtype$.compare({#if[FP16]?shortBitsToFloat16(r[i]):r[i]}, + {#if[FP16]?shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])):mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])}) == 0 || isWithin1Ulp(r[i], strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]))); } } catch (AssertionError e) { - Assert.assertTrue($Type$.compare(r[i], - mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])) == 0, + Assert.assertTrue($Wideboxtype$.compare({#if[FP16]?shortBitsToFloat16(r[i]):r[i]}, + {#if[FP16]?shortBitsToFloat16(mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])):mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])}) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])); @@ -1236,6 +1331,7 @@ relativeError)); #if[!Int] #if[!byteOrShort] +#if[!FP16] static int intCornerCaseValue(int i) { switch(i % 5) { case 0: @@ -1250,7 +1346,45 @@ relativeError)); return (int)0; } } +#end[!FP16] +#if[FP16] + static $type$ convToFloat16(int i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static $type$ convIntToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504); + case 1: + return convToFloat16(-65504); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> INT_$TYPE$_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> ((($type$)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[intCornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convIntToFloat16CornerCases(i)); + }) + ); +#else[FP16] static final List> INT_$TYPE$_GENERATORS = List.of( withToString("$type$[-i * 5]", (int s) -> { return fill(s * BUFFER_REPS, @@ -1269,6 +1403,7 @@ relativeError)); i -> ($type$)intCornerCaseValue(i)); }) ); +#end[FP16] #end[!byteOrShort] #end[!Int] @@ -1276,7 +1411,11 @@ relativeError)); int i = 0; try { for (; i < r.length; i++) { +#if[FP16] + assertEquals(r[i], (int)Float.float16ToFloat(a[i+offs])); +#else[FP16] assertEquals(r[i], (int)(a[i+offs])); +#end[FP16] } } catch (AssertionError e) { assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); @@ -1285,6 +1424,7 @@ relativeError)); #if[!Long] #if[FP] +#if[!FP16] static long longCornerCaseValue(int i) { switch(i % 5) { case 0: @@ -1299,7 +1439,45 @@ relativeError)); return (long)0; } } +#end[!FP16] +#if[FP16] + static $type$ convToFloat16(long i) { + return float16ToRawShortBits(Float16.valueOf(i)); + } + + static $type$ convLongToFloat16CornerCases(int i) { + switch(i % 4) { + case 0: + return convToFloat16(65504L); + case 1: + return convToFloat16(-65504L); + case 2: + return float16ToRawShortBits(Float16.valueOf(-0.0f)); + default: + return float16ToRawShortBits(Float16.valueOf(0.0f)); + } + } + + static final List> LONG_$TYPE$_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> ((($type$)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convLongToFloat16CornerCases(i)); + }) + ); +#else[FP16] static final List> LONG_$TYPE$_GENERATORS = List.of( withToString("$type$[-i * 5]", (int s) -> { return fill(s * BUFFER_REPS, @@ -1318,6 +1496,7 @@ relativeError)); i -> ($type$)longCornerCaseValue(i)); }) ); +#end[FP16] #end[FP] #end[!Long] @@ -1338,7 +1517,11 @@ relativeError)); int i = 0; try { for (; i < r.length; i++) { +#if[FP16] + assertEquals(r[i], (long)Float.float16ToFloat(a[i+offs])); +#else[FP16] assertEquals(r[i], (long)(a[i+offs])); +#end[FP16] } } catch (AssertionError e) { assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); @@ -1350,7 +1533,11 @@ relativeError)); int i = 0; try { for (; i < r.length; i++) { +#if[FP16] + assertEquals(r[i], (double)Float.float16ToFloat(a[i+offs])); +#else[FP16] assertEquals(r[i], (double)(a[i+offs])); +#end[FP16] } } catch (AssertionError e) { assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]); @@ -1358,8 +1545,40 @@ relativeError)); } #end[!Double] +#if[FP16] static $bitstype$ bits($type$ e) { - return {#if[FP]? $Type$.$type$To$Bitstype$Bits(e): e}; + return e; + } + + static final List> $TYPE$_GENERATORS = List.of( + withToString("float16[-i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(-i * 5)); + }), + withToString("float16[i * 5]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> convToFloat16(i * 5)); + }), + withToString("float16[i + 1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> ((($type$)(i + 1) == 0) ? convToFloat16(1) : convToFloat16(i + 1))); + }), + withToString("float16[0.01 + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01f + (i / (i + 1))]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (i % 17 == 0) ? cornerCaseValue(i) : Float.floatToFloat16((0.01f + ((float)i / (i + 1))))); + }), + withToString("float16[cornerCaseValue(i)]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> cornerCaseValue(i)); + }) + ); +#else[FP16] + static $bitstype$ bits($type$ e) { + return {#if[FP]?$Wideboxtype$.$type$To$Bitstype$Bits(e):e}; } static final List> $TYPE$_GENERATORS = List.of( @@ -1394,6 +1613,7 @@ relativeError)); i -> cornerCaseValue(i)); }) ); +#end[FP16] #if[!FP] static final List> $TYPE$_SATURATING_GENERATORS = List.of( @@ -1472,7 +1692,7 @@ relativeError)); collect(Collectors.toList()); static final List> SELECT_FROM_INDEX_GENERATORS = List.of( - withToString("$type$[0..VECLEN*2)", (int s) -> { + withToString("$testtype$[0..VECLEN*2)", (int s) -> { return fill(s * BUFFER_REPS, i -> ($type$)(RAND.nextInt())); }) @@ -1709,27 +1929,27 @@ relativeError)); #end[!Int] static final List> $TYPE$_COMPARE_GENERATORS = List.of( - withToString("$type$[i]", (int s) -> { + withToString("$testtype$[i]", (int s) -> { return fill(s * BUFFER_REPS, i -> ($type$)i); }), - withToString("$type$[i - length / 2]", (int s) -> { + withToString("$testtype$[i - length / 2]", (int s) -> { return fill(s * BUFFER_REPS, i -> ($type$)(i - (s * BUFFER_REPS / 2))); }), - withToString("$type$[i + 1]", (int s) -> { + withToString("$testtype$[i + 1]", (int s) -> { return fill(s * BUFFER_REPS, i -> ($type$)(i + 1)); }), - withToString("$type$[i - 2]", (int s) -> { + withToString("$testtype$[i - 2]", (int s) -> { return fill(s * BUFFER_REPS, i -> ($type$)(i - 2)); }), - withToString("$type$[zigZag(i)]", (int s) -> { + withToString("$testtype$[zigZag(i)]", (int s) -> { return fill(s * BUFFER_REPS, i -> i%3 == 0 ? ($type$)i : (i%3 == 1 ? ($type$)(i + 1) : ($type$)(i - 2))); }), - withToString("$type$[cornerCaseValue(i)]", (int s) -> { + withToString("$testtype$[cornerCaseValue(i)]", (int s) -> { return fill(s * BUFFER_REPS, i -> cornerCaseValue(i)); }) @@ -1792,6 +2012,18 @@ relativeError)); static $type$ cornerCaseValue(int i) { #if[FP] +#if[FP16] + return switch(i % 8) { + case 0 -> float16ToRawShortBits($Wideboxtype$.MAX_VALUE); + case 1 -> float16ToRawShortBits($Wideboxtype$.MIN_VALUE); + case 2 -> float16ToRawShortBits($Wideboxtype$.NEGATIVE_INFINITY); + case 3 -> float16ToRawShortBits($Wideboxtype$.POSITIVE_INFINITY); + case 4 -> float16ToRawShortBits($Wideboxtype$.NaN); + case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA)); + case 6 -> float16ToShortBits(Float16.valueOf(0.0f)); + default -> float16ToShortBits(Float16.valueOf(-0.0f)); + }; +#else[FP16] return switch(i % 8) { case 0 -> $Wideboxtype$.MAX_VALUE; case 1 -> $Wideboxtype$.MIN_VALUE; @@ -1806,6 +2038,7 @@ relativeError)); case 6 -> ($type$)0.0; default -> ($type$)-0.0; }; +#end[FP16] #else[FP] switch(i % 5) { case 0: @@ -1923,6 +2156,262 @@ relativeError)); #end[intOrLong] } #end[BITWISE] +#if[FP16] + + static boolean eq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() == bt.floatValue(); + } + + static boolean neq(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() != bt.floatValue(); + } + + static boolean lt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() < bt.floatValue(); + } + + static boolean le(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() <= bt.floatValue(); + } + + static boolean gt(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() > bt.floatValue(); + } + + static boolean ge(short a, short b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return at.floatValue() >= bt.floatValue(); + } + + static $type$ firstNonZero($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 zero = shortBitsToFloat16((short)0); + return Float16.compare(at, zero) != 0 ? a : b; + } + + static $type$ scalar_add($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.add(at, bt)); + } + + static $type$ scalar_sub($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.subtract(at, bt)); + } + + static $type$ scalar_mul($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.multiply(at, bt)); + + } + static $type$ scalar_max($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.max(at, bt)); + } + + static $type$ scalar_min($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.min(at, bt)); + } + + static $type$ scalar_div($type$ a, $type$ b) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + return float16ToRawShortBits(Float16.divide(at, bt)); + } + + static $type$ scalar_fma($type$ a, $type$ b, $type$ c) { + Float16 at = shortBitsToFloat16(a); + Float16 bt = shortBitsToFloat16(b); + Float16 ct = shortBitsToFloat16(c); + return float16ToRawShortBits(Float16.fma(at, bt, ct)); + } + + static $type$ scalar_abs($type$ a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.abs(at)); + } + + static $type$ scalar_neg($type$ a) { + Float16 at = shortBitsToFloat16(a); + return float16ToRawShortBits(Float16.negate(at)); + } + + static $type$ scalar_sin($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_exp($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_log1p($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_log($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.log(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_log10($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_expm1($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_cos($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_tan($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_sinh($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_cosh($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_tanh($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_asin($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_acos($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_atan($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_cbrt($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_sqrt($type$ a) { + return float16ToRawShortBits(Float16.valueOf(Math.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ scalar_hypot($type$ a, $type$ b) { + return float16ToRawShortBits(Float16.valueOf(Math.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static $type$ scalar_pow($type$ a, $type$ b) { + return float16ToRawShortBits(Float16.valueOf(Math.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static $type$ scalar_atan2($type$ a, $type$ b) { + return float16ToRawShortBits(Float16.valueOf(Math.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static $type$ strict_scalar_sin($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sin(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_exp($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.exp(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_log1p($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log1p(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_log($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_log10($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.log10(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_expm1($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.expm1(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_cos($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cos(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_tan($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tan(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_sinh($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sinh(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_cosh($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cosh(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_tanh($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.tanh(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_asin($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.asin(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_acos($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.acos(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_atan($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_cbrt($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.cbrt(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_sqrt($type$ a) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.sqrt(shortBitsToFloat16(a).doubleValue()))); + } + + static $type$ strict_scalar_hypot($type$ a, $type$ b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.hypot(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static $type$ strict_scalar_pow($type$ a, $type$ b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.pow(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } + + static $type$ strict_scalar_atan2($type$ a, $type$ b) { + return float16ToRawShortBits(Float16.valueOf(StrictMath.atan2(shortBitsToFloat16(a).doubleValue(), + shortBitsToFloat16(b).doubleValue()))); + } +#else[FP16] static boolean eq($type$ a, $type$ b) { return a == b; @@ -2155,6 +2644,7 @@ relativeError)); return ($type$)StrictMath.atan2((double)a, (double)b); } #end[!BITWISE] +#end[FP16] #if[!FP] static boolean ult($type$ a, $type$ b) { @@ -2175,6 +2665,17 @@ relativeError)); #end[!FP] #if[FP] +#if[FP16] + static boolean isNaN($type$ a) { + return $Wideboxtype$.isNaN(shortBitsToFloat16(a)); + } + static boolean isFinite($type$ a) { + return $Wideboxtype$.isFinite(shortBitsToFloat16(a)); + } + static boolean isInfinite($type$ a) { + return $Wideboxtype$.isInfinite(shortBitsToFloat16(a)); + } +#else[FP16] static boolean isNaN($type$ a) { return $Wideboxtype$.isNaN(a); } @@ -2184,14 +2685,15 @@ relativeError)); static boolean isInfinite($type$ a) { return $Wideboxtype$.isInfinite(a); } +#end[FP16] #end[FP] @Test static void smokeTest1() { - $abstractvectortype$ three = $abstractvectortype$.broadcast(SPECIES, (byte)-3); - $abstractvectortype$ three2 = ($abstractvectortype$) SPECIES.broadcast(-3); + $abstractvectortype$ three = $abstractvectortype$.broadcast(SPECIES, {#if[FP16]?float16ToRawShortBits(Float16.valueOf(-3)):(byte)-3}); + $abstractvectortype$ three2 = ($abstractvectortype$) SPECIES.broadcast({#if[FP16]?Float16.valueOf(-3).longValue():-3}); assert(three.eq(three2).allTrue()); - $abstractvectortype$ three3 = three2.broadcast(1).broadcast(-3); + $abstractvectortype$ three3 = three2.broadcast({#if[FP16]?float16ToRawShortBits(Float16.valueOf(1)):1}).broadcast({#if[FP16]?Float16.valueOf(-3).longValue():-3}); assert(three.eq(three3).allTrue()); int scale = 2; Class ETYPE = $type$.class; @@ -2202,14 +2704,18 @@ relativeError)); $abstractvectortype$ higher = three.addIndex(scale); VectorMask<$Boxtype$> m = three.compare(VectorOperators.LE, higher); assert(m.allTrue()); - m = higher.min(($type$)-1).test(VectorOperators.IS_NEGATIVE); + m = higher.min({#if[FP16]?float16ToRawShortBits(Float16.valueOf(-1)):($type$)-1}).test(VectorOperators.IS_NEGATIVE); assert(m.allTrue()); #if[FP] m = higher.test(VectorOperators.IS_FINITE); assert(m.allTrue()); #end[FP] $type$ max = higher.reduceLanes(VectorOperators.MAX); +#if[FP16] + assert(max == float16ToRawShortBits(Float16.add(Float16.valueOf(-3), Float16.multiply(Float16.valueOf(scale), Float16.valueOf((SPECIES.length()-1)))))); +#else[FP16] assert(max == -3 + scale * (SPECIES.length()-1)); +#end[FP16] } private static $type$[] @@ -2286,13 +2792,13 @@ relativeError)); assertEquals(asFloating.species(), SPECIES); } #else[FP] -#if[byteOrShort] +#if[byte] @Test(expectedExceptions = UnsupportedOperationException.class) void viewAsFloatingLanesTest() { SPECIES.zero().viewAsFloatingLanes(); } -#else[byteOrShort] +#else[byte] @Test void viewAsFloatingLanesTest() { @@ -2303,7 +2809,7 @@ relativeError)); assertEquals(asFloatingSpecies.length(), SPECIES.length()); assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES); } -#end[byteOrShort] +#end[byte] #end[FP] #if[BITWISE] diff --git a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template index 6779c78a490..2168eb95d30 100644 --- a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template +++ b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template @@ -41,6 +41,10 @@ import java.lang.foreign.MemorySegment; import java.lang.foreign.Arena; import java.lang.foreign.ValueLayout; +#if[FP16] +import jdk.incubator.vector.Float16; +import jdk.incubator.vector.Float16Vector; +#end[FP16] import jdk.incubator.vector.$Type$Vector; import jdk.incubator.vector.VectorMask; #if[MaxBit] @@ -69,7 +73,11 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); +#if[FP16] + static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1); +#else[FP16] static final ValueLayout.Of$Type$ ELEMENT_LAYOUT = ValueLayout.JAVA_$TYPE$.withByteAlignment(1); +#end[FP16] #if[MaxBit] static VectorShape getMaxBit() { @@ -81,6 +89,29 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / $bits$); +#if[FP16] + static void assertEquals(short actual, short expected) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected)); + } + + static void assertEquals(short actual, short expected, String msg) { + Assert.assertEquals(Float.float16ToFloat(actual), Float.float16ToFloat(expected), msg); + } + + static void assertEquals(short [] actual, short [] expected) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i])); + } + } + + static void assertEquals(short [] actual, short [] expected, String msg) { + assert actual.length == expected.length; + for (int i = 0; i < actual.length; i++) { + Assert.assertEquals(Float.float16ToFloat(actual[i]), Float.float16ToFloat(expected[i]), msg); + } + } +#else[FP16] static void assertEquals($type$ actual, $type$ expected) { Assert.assertEquals(actual, expected); } @@ -95,6 +126,7 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { static void assertEquals($type$ [] actual, $type$ [] expected, String msg) { Assert.assertEquals(actual, expected, msg); } +#end[FP16] static void assertArraysEquals($type$[] r, $type$[] a, boolean[] mask) { int i = 0; diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java b/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java index 8e0d48682fc..da00274f5a6 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java @@ -41,7 +41,6 @@ import jdk.test.whitebox.WhiteBox; * @test * @requires vm.flagless * @requires vm.hasJFR & vm.gc.Z - * @requires vm.flagless * @library /test/lib /test/jdk * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdChangeLogLevel.java b/test/jdk/jdk/jfr/jcmd/TestJcmdChangeLogLevel.java index c4ef5ecfa74..a6dcd458383 100644 --- a/test/jdk/jdk/jfr/jcmd/TestJcmdChangeLogLevel.java +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdChangeLogLevel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; +import java.util.regex.Pattern; import jdk.test.lib.dcmd.JcmdExecutor; import jdk.test.lib.dcmd.PidJcmdExecutor; @@ -46,7 +47,7 @@ import jdk.test.lib.dcmd.PidJcmdExecutor; public class TestJcmdChangeLogLevel { public static void main(String[] args) throws Exception { final String fileName = "jfr_trace.txt"; - final String findWhat = "[info][jfr] Flight Recorder initialized"; + final Pattern findWhat = Pattern.compile("\\[info *\\]\\[jfr *\\] Flight Recorder initialized"); boolean passed = false; JcmdExecutor je = new PidJcmdExecutor(); @@ -61,7 +62,7 @@ public class TestJcmdChangeLogLevel { throw new Error(e); } for (String l : lines) { - if (l.toString().contains(findWhat)) { + if (findWhat.matcher(l).find()) { passed = true; break; } diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java index f64c99bedbc..8000199558c 100644 --- a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; import jdk.jfr.internal.Repository; import jdk.jfr.internal.Options; @@ -127,7 +128,8 @@ public class TestJcmdConfigure { } private static void testRepository(){ - final String findWhat = "[info][jfr] Same base repository path " + REPOSITORYPATH_1 + " is set"; + final Pattern findWhat = Pattern.compile("\\[info *\\]\\[jfr *\\] Same base repository path " + + Pattern.quote(REPOSITORYPATH_1) + " is set"); try { JcmdHelper.jcmd("JFR.configure", REPOSITORYPATH_SETTING_1); @@ -138,7 +140,7 @@ public class TestJcmdConfigure { Asserts.assertTrue(samePath.equals(initialPath)); List lines = Files.readAllLines(Paths.get(JFR_UNIFIED_LOG_FILE)); - Asserts.assertTrue(lines.stream().anyMatch(l->l.contains(findWhat))); + Asserts.assertTrue(lines.stream().anyMatch(l -> findWhat.matcher(l).find())); JcmdHelper.jcmd("JFR.configure", REPOSITORYPATH_SETTING_2); Path changedPath = Repository.getRepository().getRepositoryPath(); diff --git a/test/jdk/jdk/jfr/startupargs/TestStartupMessage.java b/test/jdk/jdk/jfr/startupargs/TestStartupMessage.java index 4a934ebb36d..28e2891a08c 100644 --- a/test/jdk/jdk/jfr/startupargs/TestStartupMessage.java +++ b/test/jdk/jdk/jfr/startupargs/TestStartupMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,12 +59,12 @@ public class TestStartupMessage { // Can't turn off log with -Xlog:jfr+startup=warning startJfrJvm() - .shouldContain("[info][jfr,startup") + .shouldMatch("\\[info *\\]\\[jfr,startup") .shouldContain("Started recording") .shouldContain("Use jcmd"); startJfrJvm("-Xlog:jfr+startup=info") - .shouldContain("[info][jfr,startup") + .shouldMatch("\\[info *\\]\\[jfr,startup") .shouldContain("Started recording") .shouldContain("Use jcmd"); } diff --git a/test/jdk/sun/security/internal/CheckIBE.java b/test/jdk/sun/security/internal/CheckIBE.java new file mode 100644 index 00000000000..802cd336ebc --- /dev/null +++ b/test/jdk/sun/security/internal/CheckIBE.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8383608 + * @summary check that InternalBinaryEncodable exists + * @enablePreview + * @modules java.base/sun.security.internal + * @run main CheckIBE + */ + +import javax.crypto.EncryptedPrivateKeyInfo; +import java.security.AsymmetricKey; +import java.security.BinaryEncodable; +import java.security.KeyPair; +import java.security.PEM; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import sun.security.internal.InternalBinaryEncodable; + +/* + * This test verifies that BinaryEncodable has the expected set of permitted + * subtypes, including InternalBinaryEncodable. If this switch stops compiling, + * update the cases to match the BinaryEncodable permits list. + */ + +public class CheckIBE { + public static void main(String[] args) { + BinaryEncodable be = new PEM("TEST", "TEST"); + + switch (be) { + case AsymmetricKey ignored -> {} + case KeyPair ignored -> {} + case PKCS8EncodedKeySpec ignored -> {} + case X509EncodedKeySpec ignored -> {} + case EncryptedPrivateKeyInfo ignored -> {} + case X509Certificate ignored -> {} + case X509CRL ignored -> {} + case PEM ignored -> {} + case InternalBinaryEncodable ignored -> {} + } + } +} diff --git a/test/jdk/sun/security/internal/ExhaustiveBE.java b/test/jdk/sun/security/internal/ExhaustiveBE.java new file mode 100644 index 00000000000..37222a0310a --- /dev/null +++ b/test/jdk/sun/security/internal/ExhaustiveBE.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8383608 + * @summary verify switches over BinaryEncodable are not exhaustive + * @enablePreview + * @compile/fail ExhaustiveBE.java + */ + +import javax.crypto.EncryptedPrivateKeyInfo; +import java.security.AsymmetricKey; +import java.security.BinaryEncodable; +import java.security.KeyPair; +import java.security.PEM; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/* + * This test verifies that application code cannot exhaustively switch over + * BinaryEncodable by naming only the public permitted subtypes. Compilation + * must fail because application code needs a default case, or a + * BinaryEncodable case, to cover the internal permitted subtype + * InternalBinaryEncodable. + */ + +public class ExhaustiveBE { + public static void main(String[] args) { + BinaryEncodable be = new PEM("TEST", "TEST"); + + switch (be) { + case AsymmetricKey ignored -> {} + case KeyPair ignored -> {} + case PKCS8EncodedKeySpec ignored -> {} + case X509EncodedKeySpec ignored -> {} + case EncryptedPrivateKeyInfo ignored -> {} + case X509Certificate ignored -> {} + case X509CRL ignored -> {} + case PEM ignored -> {} + } + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16VectorOperationsBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16VectorOperationsBenchmark.java new file mode 100644 index 00000000000..445e57cabf0 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16VectorOperationsBenchmark.java @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import java.util.stream.IntStream; +import java.util.concurrent.TimeUnit; +import jdk.incubator.vector.*; +import org.openjdk.jmh.annotations.*; +import static jdk.incubator.vector.Float16.*; +import static java.lang.Float.*; + +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Fork(jvmArgs = {"--add-modules=jdk.incubator.vector", "-Xbatch", "-XX:-TieredCompilation"}) +public class Float16VectorOperationsBenchmark { + @Param({"1024", "2057"}) + int vectorDim; + + int [] rexp; + short [] vectorRes; + short [] vector1; + short [] vector2; + short [] vector3; + short [] vector4; + short [] vector5; + boolean [] vectorPredicate; + + static final short f16_one = Float.floatToFloat16(1.0f); + static final short f16_two = Float.floatToFloat16(2.0f); + + @Setup(Level.Trial) + public void BmSetup() { + rexp = new int[vectorDim]; + vectorRes = new short[vectorDim]; + vector1 = new short[vectorDim]; + vector2 = new short[vectorDim]; + vector3 = new short[vectorDim]; + vector4 = new short[vectorDim]; + vector5 = new short[vectorDim]; + vectorPredicate = new boolean[vectorDim]; + + IntStream.range(0, vectorDim).forEach(i -> {vector1[i] = Float.floatToFloat16((float)i);}); + IntStream.range(0, vectorDim).forEach(i -> {vector2[i] = Float.floatToFloat16((float)i);}); + IntStream.range(0, vectorDim).forEach(i -> {vector3[i] = Float.floatToFloat16((float)i);}); + IntStream.range(0, vectorDim).forEach(i -> {vector4[i] = ((i & 0x1) == 0) ? + float16ToRawShortBits(Float16.POSITIVE_INFINITY) : + Float.floatToFloat16((float)i);}); + IntStream.range(0, vectorDim).forEach(i -> {vector5[i] = ((i & 0x1) == 0) ? + float16ToRawShortBits(Float16.NaN) : + Float.floatToFloat16((float)i);}); + // Special Values + Float16 [] specialValues = {Float16.NaN, Float16.NEGATIVE_INFINITY, Float16.valueOf(0.0), Float16.valueOf(-0.0), Float16.POSITIVE_INFINITY}; + IntStream.range(0, vectorDim).forEach( + i -> { + if ((i % 64) == 0) { + int idx1 = i % specialValues.length; + int idx2 = (i + 1) % specialValues.length; + int idx3 = (i + 2) % specialValues.length; + vector1[i] = float16ToRawShortBits(specialValues[idx1]); + vector2[i] = float16ToRawShortBits(specialValues[idx2]); + vector3[i] = float16ToRawShortBits(specialValues[idx3]); + } + } + ); + } + + static final VectorSpecies HSPECIES = Float16Vector.SPECIES_PREFERRED; + static final VectorSpecies FSPECIES = FloatVector.SPECIES_PREFERRED; + + @Benchmark + public void addBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.ADD, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.ADD, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public void subBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.SUB, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.SUB, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + } + + @Benchmark + public void mulBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.MUL, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.MUL, + Float16Vector.fromArray(HSPECIES, vector2, i, mask)) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public void divBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.DIV, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.DIV, + Float16Vector.fromArray(HSPECIES, vector2, i, mask)) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public void fmaBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(HSPECIES, vector2, i), + Float16Vector.fromArray(HSPECIES, vector3, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(HSPECIES, vector2, i, mask), + Float16Vector.fromArray(HSPECIES, vector3, i, mask)) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public void maxBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.MAX, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.MAX, + Float16Vector.fromArray(HSPECIES, vector2, i, mask)) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public void minBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.MIN, + Float16Vector.fromArray(HSPECIES, vector2, i)) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.MIN, + Float16Vector.fromArray(HSPECIES, vector2, i, mask)) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public void sqrtBenchmark() { + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.SQRT) + .intoArray(vectorRes, i); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.SQRT) + .intoArray(vectorRes, i, mask); + } + } + + @Benchmark + public short cosineSimilarityDoubleRoundingFP16() { + int i = 0; + Float16Vector macResVec = Float16Vector.broadcast(HSPECIES, (short)0); + Float16Vector vector1SquareVec = Float16Vector.broadcast(HSPECIES, (short)0); + Float16Vector vector2SquareVec = Float16Vector.broadcast(HSPECIES, (short)0); + // cosine distance = (VEC1 . VEC2) / ||VEC1||.||VEC2|| + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + // Explicit add and multiply operation ensures double rounding. + Float16Vector vec1 = Float16Vector.fromArray(HSPECIES, vector1, i); + Float16Vector vec2 = Float16Vector.fromArray(HSPECIES, vector2, i); + macResVec = vec1.lanewise(VectorOperators.MUL, vec2) + .lanewise(VectorOperators.ADD, macResVec); + vector1SquareVec = vec1.lanewise(VectorOperators.MUL, vec1) + .lanewise(VectorOperators.ADD, vector1SquareVec); + vector2SquareVec = vec2.lanewise(VectorOperators.MUL, vec2) + .lanewise(VectorOperators.ADD, vector2SquareVec); + } + + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector vec1 = Float16Vector.fromArray(HSPECIES, vector1, i, mask); + Float16Vector vec2 = Float16Vector.fromArray(HSPECIES, vector2, i, mask); + macResVec = vec1.lanewise(VectorOperators.MUL, vec2) + .lanewise(VectorOperators.ADD, macResVec); + vector1SquareVec = vec1.lanewise(VectorOperators.MUL, vec1) + .lanewise(VectorOperators.ADD, vector1SquareVec); + vector2SquareVec = vec2.lanewise(VectorOperators.MUL, vec2) + .lanewise(VectorOperators.ADD, vector2SquareVec); + return macResVec.lanewise(VectorOperators.DIV, + vector1SquareVec.lanewise(VectorOperators.MUL, + vector2SquareVec)) + .reduceLanes(VectorOperators.ADD, mask); + } else { + return macResVec.lanewise(VectorOperators.DIV, + vector1SquareVec.lanewise(VectorOperators.MUL, + vector2SquareVec)) + .reduceLanes(VectorOperators.ADD); + } + } + + @Benchmark + public short cosineSimilaritySingleRoundingFP16() { + int i = 0; + Float16Vector macResVec = Float16Vector.broadcast(HSPECIES, (short)0); + Float16Vector vector1SquareVec = Float16Vector.broadcast(HSPECIES, (short)0); + Float16Vector vector2SquareVec = Float16Vector.broadcast(HSPECIES, (short)0); + // cosine distance = (VEC1 . VEC2) / ||VEC1||.||VEC2|| + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + // Explicit add and multiply operation ensures double rounding. + Float16Vector vec1 = Float16Vector.fromArray(HSPECIES, vector1, i); + Float16Vector vec2 = Float16Vector.fromArray(HSPECIES, vector2, i); + macResVec = vec1.lanewise(VectorOperators.FMA, vec2, macResVec); + vector1SquareVec = vec1.lanewise(VectorOperators.FMA, vec1, vector1SquareVec); + vector2SquareVec = vec2.lanewise(VectorOperators.FMA, vec2, vector2SquareVec); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector vec1 = Float16Vector.fromArray(HSPECIES, vector1, i, mask); + Float16Vector vec2 = Float16Vector.fromArray(HSPECIES, vector2, i, mask); + macResVec = vec1.lanewise(VectorOperators.FMA, vec2, macResVec); + vector1SquareVec = vec1.lanewise(VectorOperators.FMA, vec1, vector1SquareVec); + vector2SquareVec = vec2.lanewise(VectorOperators.FMA, vec2, vector2SquareVec); + return macResVec.lanewise(VectorOperators.DIV, + vector1SquareVec.lanewise(VectorOperators.MUL, + vector2SquareVec)) + .reduceLanes(VectorOperators.ADD, mask); + } else { + return macResVec.lanewise(VectorOperators.DIV, + vector1SquareVec.lanewise(VectorOperators.MUL, + vector2SquareVec)) + .reduceLanes(VectorOperators.ADD); + } + } + + @Benchmark + public short euclideanDistanceFP16() { + Float16Vector resVec = Float16Vector.broadcast(HSPECIES, (short)0); + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + Float16Vector diffVec = Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.SUB, + Float16Vector.fromArray(HSPECIES, vector2, i)); + resVec = diffVec.lanewise(VectorOperators.FMA, diffVec, resVec); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + Float16Vector diffVec = Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.SUB, + Float16Vector.fromArray(HSPECIES, vector2, i, mask)); + resVec = diffVec.lanewise(VectorOperators.FMA, diffVec, resVec); + return resVec.lanewise(VectorOperators.SQRT) + .reduceLanes(VectorOperators.ADD, mask); + } else { + return resVec.lanewise(VectorOperators.SQRT) + .reduceLanes(VectorOperators.ADD); + } + } + + @Benchmark + public short dotProductFP16() { + Float16Vector distResVec = Float16Vector.broadcast(HSPECIES, (short)0); + int i = 0; + for (; i < HSPECIES.loopBound(vectorDim); i += HSPECIES.length()) { + distResVec = Float16Vector.fromArray(HSPECIES, vector1, i) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(HSPECIES, vector2, i), + distResVec); + } + if (i < vectorDim) { + VectorMask mask = HSPECIES.indexInRange(i, vectorDim); + distResVec = Float16Vector.fromArray(HSPECIES, vector1, i, mask) + .lanewise(VectorOperators.FMA, + Float16Vector.fromArray(HSPECIES, vector2, i, mask), + distResVec); + return distResVec.reduceLanes(VectorOperators.ADD, mask); + } else { + return distResVec.reduceLanes(VectorOperators.ADD); + } + } +}