diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000000..ee91f5d33e22 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,184 @@ +# git blame ignore revs file +# +# The list of revisions below will be ignored by git-blame (1) if this file gets +# passed via the --ignore-revs-file command line option or is configured using +# the blame.ignoreRevsFile key. +# +# Only add commits that obviously do not change semantics, e.g. mechanical refactorings +# or formatting. Always add the commit message as a comment above the revision +# to keep the file readable. + +# 8299973: Replace NULL with nullptr in share/utilities/ +1084fd24eb118d4131538c2a3ead714db7d0357b + +# 8299974: Replace NULL with nullptr in share/adlc/ +62537d200f01d58ff1c236f31f71c5839316db9e + +# 8300081: Replace NULL with nullptr in share/asm/ +9d5bab11f08a992803399f422d75b17f8607df72 + +# 8300086: Replace NULL with nullptr in share/c1/ +90d5041b6a055d6266140ffea2aa9a3b08b32209 + +# 8300087: Replace NULL with nullptr in share/cds/ +eca64795be63c599a637ce2a7f740b2d0a1ec9bc + +# 8300222: Replace NULL with nullptr in share/logging +bd5ca953058704087da4bc5796b3ce28ce2a8f78 + +# 8300240: Replace NULL with nullptr in share/ci/ +f52d35c84b7333809156d201c866793854143888 + +# 8300241: Replace NULL with nullptr in share/classfile/ +49ff52087be8b95cbf369518281312ecc9d83618 + +# 8300242: Replace NULL with nullptr in share/code/ +cfe57466ddecb93b528478d0b053b089dd1ed285 + +# 8300243: Replace NULL with nullptr in share/compiler/ +fcbf9d052efd16821750fb20813f8030ee828472 + +# 8300244: Replace NULL with nullptr in share/interpreter/ +a5d8e12872d9de399fa97b33896635d101b71372 + +# 8300245: Replace NULL with nullptr in share/jfr/ +cc396895e5a1dac49f4e341ce91c04b8c092d0af + +# 8300651: Replace NULL with nullptr in share/runtime/ +71107f4648d8f31a7bcc0aa5202ef46230df583f + +# 8301068: Replace NULL with nullptr in share/jvmci/ +90ec19efeda90f13a918b4481fe6ee552ab2af66 + +# 8301069: Replace NULL with nullptr in share/libadt/ +b0376a5f4421fb58c0feeddfce2c2083314e400c + +# 8301070: Replace NULL with nullptr in share/memory/ +d98a323a8b972c17a066c597a81b164681ad5589 + +# 8301072: Replace NULL with nullptr in share/oops/ +c8ace482edead720c865cf996729a316025d937e + +# 8301074: Replace NULL with nullptr in share/opto/ +5726d31e56530bbe7dee61ae04b126e20cb3611d + +# 8301076: Replace NULL with nullptr in share/prims/ +b76a52f2104b63e84e5d09f47ce01dd0cb3935d7 + +# 8301077: Replace NULL with nullptr in share/services/ +5c1ec82656323872c4628026662fe5b62e7a61e3 + +# 8301178: Replace NULL with nullptr in share/gc/epsilon/ +b77abc6a0daed0e01a9003d42493320376dc98bc + +# 8301179: Replace NULL with nullptr in share/gc/serial/ +107e184d59c0bbed6441a3c1a9bfd4527da3bce5 + +# 8301180: Replace NULL with nullptr in share/gc/parallel/ +3758487fda61b27e7e684413793ed28c0b9e64d3 + +# 8301223: Replace NULL with nullptr in share/gc/g1/ +75a4edca6b9fa6b3e66b564aeb4d7ca8acf02491 + +# 8301225: Replace NULL with nullptr in share/gc/shenandoah/ +0c9658446d111ec944f06b7a8a4e3ae7bf53ee8d + +# 8301477: Replace NULL with nullptr in os/aix +43288bbd684abfcefdf385ed1e0307070399ccbf + +# 8301478: Replace NULL with nullptr in os/bsd +716f1df609e7f0aa7b3b9383d23dde5c71017d02 + +# 8301479: Replace NULL with nullptr in os/linux +ac9e046748a9bb6ee065dc473d82135ce36043b7 + +# 8301480: Replace NULL with nullptr in os/posix +4539899c55c77771b951d005c17550ef9ac94819 + +# 8301481: Replace NULL with nullptr in os/windows +c91cd2814baa8dee2af8af0fecf9185d4a0a44cf + +# 8301493: Replace NULL with nullptr in cpu/aarch64 +948f3b3c24709eca3aa6c3f0db6adb9226d6f9ac + +# 8301494: Replace NULL with nullptr in cpu/arm +c4ffe4bf6369d5b271aa8689b8648f3fe8dcabed + +# 8301495: Replace NULL with nullptr in cpu/ppc +0826ceee65ab83f643a77716f8f12d0060369923 + +# 8301496: Replace NULL with nullptr in cpu/riscv +d2ce04bb101002abfdb7c8adb3fa8ea267903c36 + +# 8301497: Replace NULL with nullptr in cpu/s390 +54f7b6ca34986cc26c5b91c6724b9a1754c94391 + +# 8301498: Replace NULL with nullptr in cpu/x86 +4154a980ca28c1ae56db26e3dce64c07c225de12 + +# 8301499: Replace NULL with nullptr in cpu/zero +4e327db1d127c652ef39e31c164e36ae429a0065 + +# 8301500: Replace NULL with nullptr in os_cpu/aix_ppc +c8307e37fdf4453cade84efc113d93dd14333fd0 + +# 8301501: Replace NULL with nullptr in os_cpu/bsd_aarch64 +218223e4a31d485935655cb3f186a752defd8fa8 + +# 8301502: Replace NULL with nullptr in os_cpu/bsd_x86 +6daff6b26946748360d59a12e9069a08ab5ca06d + +# 8301503: Replace NULL with nullptr in os_cpu/bsd_zero +8cc399b672c6ce08037685b3a3a2db3c53a87b50 + +# 8301504: Replace NULL with nullptr in os_cpu/linux_aarch64 +13fcd602d37eb0095f169255128588b872639571 + +# 8301505: Replace NULL with nullptr in os_cpu/linux_arm +b81f0ff43ac8d1431f2f5dccb7499a3a1503823d + +# 8301506: Replace NULL with nullptr in os_cpu/linux_ppc +b1e96989b693aadea082a01576e25f85ed28ff0d + +# 8301507: Replace NULL with nullptr in os_cpu/linux_riscv +182d1b2fb7034b6e9177dc360cbea43d548c3ff0 + +# 8301508: Replace NULL with nullptr in os_cpu/linux_s390 +d097b5e6285e1a59632211e006592fedf2047c09 + +# 8301509: Replace NULL with nullptr in os_cpu/linux_x86 +5d1f71daf06870810c9ca24e911d6191cc4f3006 + +# 8301511: Replace NULL with nullptr in os_cpu/linux_zero +42a286a15862d9a05ea3477a9eeab46e7b33e599 + +# 8301512: Replace NULL with nullptr in os_cpu/windows_aarch64 +ad79e49141f063a61090eda69d96dc580db88949 + +# 8301513: Replace NULL with nullptr in os_cpu/windows_x86 +c109dae48c61c6fbeacadf59d509d37d2c4d2bb8 + +# 8308092: Replace NULL with nullptr in gc/x +599fa774b875da971d66f79e5e43ede2b5ce18aa + +# 8309044: Replace NULL with nullptr, final sweep of hotspot code +4f16161607edbf69f423ced1d3c24f7af058d46b + +# 8324286: Fix backsliding on use of nullptr instead of NULL +bcb340da091e3287da8d2ecfcd017ebcc6613cae + +# 8324678: Replace NULL with nullptr in HotSpot gtests +c1281e6b45ed167df69d29a6039d81854c145ae6 + +# 8324679: Replace NULL with nullptr in HotSpot .ad files +b3ecd55601d483359819d02e70789bbd412b13da + +# 8324680: Replace NULL with nullptr in JVMTI generated code +267780bf0adf4bfd831fbc04347e297fa8f3bb01 + +# 8324681: Replace NULL with nullptr in HotSpot jtreg test native code files +a6bdee48f39993128d8095d40ab417f0102af0f4 + +# 8324799: Use correct extension for C++ test headers +998d0baab0fd051c38d9fd6021628eb863b80554 + diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 4c1d28350545..20315cda97d2 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1192,8 +1192,8 @@ var getJibProfilesDependencies = function (input, common) { server: "jpg", product: "jcov", version: "3.0", - build_number: "5", - file: "bundles/jcov-3.0+5.zip", + build_number: "6", + file: "bundles/jcov-3.0+6.zip", environment_name: "JCOV_HOME", }, diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index b3fd640c2927..83cfa86cf70a 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -33,7 +33,7 @@ DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2027-03-27 +DEFAULT_VERSION_DATE=2027-03-23 DEFAULT_VERSION_CLASSFILE_MAJOR=72 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 diff --git a/make/devkit/Sysroot.gmk b/make/devkit/Sysroot.gmk index fd3d8c1b891a..13395172074d 100644 --- a/make/devkit/Sysroot.gmk +++ b/make/devkit/Sysroot.gmk @@ -109,7 +109,7 @@ endif EMPTY := SPACE := $(EMPTY) $(EMPTY) COMMA := , -DNF_ARCHS := $(subst $(SPACE),$(COMMA),$(RPM_ARCHS)) +DNF_ARCHS := $(foreach arch,$(RPM_ARCHS),--arch $(arch)) # Specify a dummy installation root, otherwise dnf will run into # problems trying to reconcile with the local/system state @@ -123,7 +123,7 @@ DNF_DOWNLOAD_FLAGS := \ --disablerepo='*' \ $(DNF_REPOS) \ --resolve \ - --archlist $(DNF_ARCHS) \ + $(DNF_ARCHS) \ --forcearch $(RPM_ARCH) \ --installroot $(DNF_DUMMY_INSTALL_ROOT) \ --releasever $(BASE_OS_VERSION) \ diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index f31514e666c5..49f3419dfb63 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 a53efd43d5d2..febd084d78a5 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 7731290c801a..c590b6699c01 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/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index eb658ba4e30e..1c052b67503d 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -2813,7 +2813,7 @@ void MacroAssembler::decrementw(Register reg, int value) { if (value < 0) { incrementw(reg, -value); return; } if (value == 0) { return; } - if (value < (1 << 12)) { subw(reg, reg, value); return; } + if (value < (1 << 24)) { subw(reg, reg, value); return; } /* else */ { guarantee(reg != rscratch2, "invalid dst for register decrement"); movw(rscratch2, (unsigned)value); @@ -2825,7 +2825,7 @@ void MacroAssembler::decrement(Register reg, int value) { if (value < 0) { increment(reg, -value); return; } if (value == 0) { return; } - if (value < (1 << 12)) { sub(reg, reg, value); return; } + if (value < (1 << 24)) { sub(reg, reg, value); return; } /* else */ { assert(reg != rscratch2, "invalid dst for register decrement"); mov(rscratch2, (uint64_t)value); @@ -2837,7 +2837,7 @@ void MacroAssembler::decrementw(Address dst, int value) { assert(!dst.uses(rscratch1), "invalid dst for address decrement"); if (dst.getMode() == Address::literal) { - assert(abs(value) < (1 << 12), "invalid value and address mode combination"); + assert(abs(value) < (1 << 24), "invalid value and address mode combination"); lea(rscratch2, dst); dst = Address(rscratch2); } @@ -2850,7 +2850,7 @@ void MacroAssembler::decrement(Address dst, int value) { assert(!dst.uses(rscratch1), "invalid address for decrement"); if (dst.getMode() == Address::literal) { - assert(abs(value) < (1 << 12), "invalid value and address mode combination"); + assert(abs(value) < (1 << 24), "invalid value and address mode combination"); lea(rscratch2, dst); dst = Address(rscratch2); } @@ -2863,7 +2863,7 @@ void MacroAssembler::incrementw(Register reg, int value) { if (value < 0) { decrementw(reg, -value); return; } if (value == 0) { return; } - if (value < (1 << 12)) { addw(reg, reg, value); return; } + if (value < (1 << 24)) { addw(reg, reg, value); return; } /* else */ { assert(reg != rscratch2, "invalid dst for register increment"); movw(rscratch2, (unsigned)value); @@ -2875,7 +2875,7 @@ void MacroAssembler::increment(Register reg, int value) { if (value < 0) { decrement(reg, -value); return; } if (value == 0) { return; } - if (value < (1 << 12)) { add(reg, reg, value); return; } + if (value < (1 << 24)) { add(reg, reg, value); return; } /* else */ { assert(reg != rscratch2, "invalid dst for register increment"); movw(rscratch2, (unsigned)value); @@ -2883,30 +2883,34 @@ void MacroAssembler::increment(Register reg, int value) } } -void MacroAssembler::incrementw(Address dst, int value) +void MacroAssembler::incrementw(Address dst, int value, Register result) { - assert(!dst.uses(rscratch1), "invalid dst for address increment"); + assert(!dst.uses(result), "invalid dst for address increment"); + assert(result->is_valid(), "must be"); + assert_different_registers(result, rscratch2); if (dst.getMode() == Address::literal) { - assert(abs(value) < (1 << 12), "invalid value and address mode combination"); + assert(abs(value) < (1 << 24), "invalid value and address mode combination"); lea(rscratch2, dst); dst = Address(rscratch2); } - ldrw(rscratch1, dst); - incrementw(rscratch1, value); - strw(rscratch1, dst); + ldrw(result, dst); + incrementw(result, value); + strw(result, dst); } -void MacroAssembler::increment(Address dst, int value) +void MacroAssembler::increment(Address dst, int value, Register result) { - assert(!dst.uses(rscratch1), "invalid dst for address increment"); + assert(!dst.uses(result), "invalid dst for address increment"); + assert(result->is_valid(), "must be"); + assert_different_registers(result, rscratch2); if (dst.getMode() == Address::literal) { - assert(abs(value) < (1 << 12), "invalid value and address mode combination"); + assert(abs(value) < (1 << 24), "invalid value and address mode combination"); lea(rscratch2, dst); dst = Address(rscratch2); } - ldr(rscratch1, dst); - increment(rscratch1, value); - str(rscratch1, dst); + ldr(result, dst); + increment(result, value); + str(result, dst); } // Push lots of registers in the bit set supplied. Don't push sp. diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index b1050b457312..a15b06306109 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -482,6 +482,25 @@ class MacroAssembler: public Assembler { WRAP(smaddl) WRAP(smsubl) WRAP(umaddl) WRAP(umsubl) #undef WRAP + using Assembler::andw, Assembler::andr; + void andw(Register Rd, Register Rn, uint64_t imm) { + if (operand_valid_for_logical_immediate(/*is32*/true, imm)) { + Assembler::andw(Rd, Rn, imm); + } else { + assert(Rd != Rn, "must be"); + movw(Rd, imm); + andw(Rd, Rn, Rd); + } + } + void andr(Register Rd, Register Rn, uint64_t imm) { + if (operand_valid_for_logical_immediate(/*is32*/false, imm)) { + Assembler::andr(Rd, Rn, imm); + } else { + assert(Rd != Rn, "must be"); + mov(Rd, imm); + andr(Rd, Rn, Rd); + } + } // macro assembly operations needed for aarch64 @@ -743,7 +762,7 @@ class MacroAssembler: public Assembler { // n.b. increment/decrement calls with an Address destination will // need to use a scratch register to load the value to be // incremented. increment/decrement calls which add or subtract a - // constant value greater than 2^12 will need to use a 2nd scratch + // constant value greater than 2^24 will need to use a 2nd scratch // register to hold the constant. so, a register increment/decrement // may trash rscratch2 and an address increment/decrement trash // rscratch and rscratch2 @@ -754,11 +773,11 @@ class MacroAssembler: public Assembler { void decrement(Register reg, int value = 1); void decrement(Address dst, int value = 1); - void incrementw(Address dst, int value = 1); + void incrementw(Address dst, int value = 1, Register result = rscratch1); void incrementw(Register reg, int value = 1); void increment(Register reg, int value = 1); - void increment(Address dst, int value = 1); + void increment(Address dst, int value = 1, Register result = rscratch1); // Alignment diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 823ff175379a..582327282fd8 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/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 7360ed604f17..ea1768c6afd3 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -3475,30 +3475,34 @@ frame %{ // 4 what apparently works and saves us some spills. return_addr(STACK 4); - // Location of native (C/C++) and interpreter return values. This - // is specified to be the same as Java. In the 32-bit VM, long - // values are actually returned from native calls in O0:O1 and - // returned to the interpreter in I0:I1. The copying to and from - // the register pairs is done by the appropriate call and epilog - // opcodes. This simplifies the register allocator. - c_return_value %{ - assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || - (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0), - "only return normal values"); - // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL - static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; - static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; - return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); - %} - // Location of compiled Java return values. Same as C return_value %{ assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0), "only return normal values"); - // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL - static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; - static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; + // enum names from opcodes.hpp + static int typeToRegLo[Op_RegL+1] = { + 0, // Op_Node + 0, // Op_Set + R3_num, // Op_RegN + R3_num, // Op_RegI + R3_num, // Op_RegP + F1_num, // Op_RegF + F1_num, // Op_RegD + R3_num, // Op_RegL + }; + + static int typeToRegHi[Op_RegL+1] = { + 0, // Op_Node + 0, // Op_Set + OptoReg::Bad, // Op_RegN + OptoReg::Bad, // Op_RegI + R3_H_num, // Op_RegP + OptoReg::Bad, // Op_RegF + F1_H_num, // Op_RegD + R3_H_num // Op_RegL + }; + return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); %} %} diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp index d30592d68f10..eec5f9a5165c 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 18ca120bdfa7..f05b9ff7791d 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/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 0ac0a8243d4f..80dd7ccfbca7 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/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index b64943fc4de8..afd9c126a213 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4904,6 +4904,11 @@ void StubGenerator::generate_compiler_stubs() { StubRoutines::_intpoly_assign = generate_intpoly_assign(); } + if (UseIntPoly25519Intrinsics) { + StubRoutines::_intpoly_mult_25519 = generate_intpoly_mult_25519(); + StubRoutines::_intpoly_square_25519 = generate_intpoly_square_25519(); + } + if (UseMD5Intrinsics) { StubRoutines::_md5_implCompress = generate_md5_implCompress(StubId::stubgen_md5_implCompress_id); StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubId::stubgen_md5_implCompressMB_id); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 360b0329d953..6e3da334f110 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -496,6 +496,9 @@ class StubGenerator: public StubCodeGenerator { address generate_intpoly_montgomeryMult_P256(); address generate_intpoly_assign(); + address generate_intpoly_mult_25519(); + address generate_intpoly_square_25519(); + // SHA3 stubs void generate_sha3_stubs(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly25519.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly25519.cpp new file mode 100644 index 000000000000..c7395220d49c --- /dev/null +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly25519.cpp @@ -0,0 +1,306 @@ +/* + * 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. + */ + +#include "macroAssembler_x86.hpp" +#include "stubGenerator_x86_64.hpp" + +#define __ _masm-> + +const int32_t term = 19; +const int32_t limbs = 5; +const int32_t bpl = 51; +const int32_t rem = 64 - bpl; +const uint64_t MASK = 0x7FFFFFFFFFFFF; +const uint64_t CARRY_ADD = 0x4000000000000; + +// Multiplication operation for polynomial arithmetic in Curve25519. +// +// This is the same algorithm as used in Java, except we use pseudo-Mersenne +// reduction to reduce register pressure instead of using the full 10 columns +// in Java. +void multiply_25519_scalar(const Register aLimbs, const Register bLimbs, const Register rLimbs, Register c[], Register bArg, Register d, Register b, Register mask, MacroAssembler* _masm) { + + for (int i = 0; i < limbs; i++) { + __ xorq(c[i], c[i]); + } + __ mov64(mask, MASK); + __ movq(bArg, bLimbs); + + // Perform high/low multiplication with signed 5x51 bit limbs + for (int i = 0; i < limbs; i++) { + __ movq(b, Address(bArg, i * 8)); + for (int j = 0; j < limbs; j++) { + __ movq(rax, Address(aLimbs, j * 8)); + __ imulq(b); // rdx:rax = a * b + __ movq(d, rax); + __ andq(d, mask); + __ shrq(rax, bpl); + __ shlq(rdx, rem); + __ orq(rax, rdx); + // Fold in pseudo-Mersenne reduction + if ((i + j + 1) >= limbs) { + __ imulq(rax, rax, term); + } + if ((i + j) >= limbs) { + __ imulq(d, d, term); + } + __ addq(c[(i + j) % limbs], d); + __ addq(c[(i + j + 1) % limbs], rax); + } + } + + // Carry-add with reduction from high limb + Register carry = bArg; + __ mov64(mask, CARRY_ADD); + __ movq(carry, mask); + + // Limb 3 + __ addq(carry, c[3]); + __ sarq(carry, bpl); + __ addq(c[4], carry); + __ shlq(carry, bpl); + __ subq(c[3], carry); + + // Limb 4 + __ movq(carry, mask); + __ addq(carry, c[4]); + __ sarq(carry, bpl); + + // Reduce high order limb and fold back into low order limb + __ mov64(rax, term); + __ imulq(carry); + __ addq(c[0], rax); + + __ shlq(carry, bpl); + __ subq(c[4], carry); + + // Limbs 0 - 3 + for (int i = 0; i < (limbs - 1); i++) { + __ movq(carry, mask); + __ addq(carry, c[i]); + __ sarq(carry, bpl); + __ addq(c[i + 1], carry); + __ shlq(carry, bpl); + __ subq(c[i], carry); + } + + __ pop_ppx(rdx); + + for (int i = 0; i < limbs; i++) { + __ movq(Address(rLimbs, i * 8), c[i]); + } +} + +// Squaring operation for polynomial arithmetic in Curve25519. +// +// This is the same algorithm as used in Java, except we use pseudo-Mersenne +// reduction to reduce register pressure instead of using the full 10 columns +// in Java. +void square_25519_scalar(const Register aLimbs, const Register rLimbs, Register c[], Register aArg, Register d, Register carry, Register mask, MacroAssembler* _masm) { + + for (int i = 0; i < limbs; i++) { + __ xorq(c[i], c[i]); + } + __ mov64(mask, MASK); + + // Perform high/low multiplication with signed 5x51 bit limbs + for (int i = 0; i < limbs; i++) { + __ movq(aArg, Address(aLimbs, i * 8)); + __ movq(rax, aArg); + __ imulq(aArg); // rdx:rax = a[j] * a[i] + __ movq(d, rax); + __ andq(d, mask); + __ shrq(rax, bpl); + __ shlq(rdx, rem); + __ orq(rax, rdx); // rax = dd + if ((i * 2 + 1) >= limbs) { + __ imulq(rax, rax, term); + } + if ((i * 2) >= limbs) { + __ imulq(d, d, term); + } + __ addq(c[(i * 2) % limbs], d); + __ addq(c[(i * 2 + 1) % limbs], rax); + for (int j = i + 1; j < limbs; j++) { + __ movq(rax, Address(aLimbs, j * 8)); + __ imulq(aArg); // rdx:rax = a * a + __ movq(d, rax); + __ andq(d, mask); + __ shlq(d, 1); + __ shrq(rax, bpl); + __ shlq(rdx, rem); + __ orq(rax, rdx); // rax = dd + __ shlq(rax, 1); + if ((j + i + 1) >= limbs) { + __ imulq(rax, rax, term); + } + if ((j + i) >= limbs) { + __ imulq(d, d, term); + } + __ addq(c[(i + j) % limbs], d); + __ addq(c[(i + j + 1) % limbs], rax); + } + } + + // Carry-add with reduction from high limb + // Limb 3 + __ mov64(mask, CARRY_ADD); + __ movq(carry, mask); + __ addq(carry, c[3]); + __ sarq(carry, bpl); + __ addq(c[4], carry); + __ shlq(carry, bpl); + __ subq(c[3], carry); + + // Limb 4 + __ movq(carry, mask); + __ addq(carry, c[4]); + __ sarq(carry, bpl); + + // Reduce high order limb and fold back into low order limb + __ mov64(rax, term); + __ imulq(carry); + __ addq(c[0], rax); + + __ shlq(carry, bpl); + __ subq(c[4], carry); + + // Limbs 0 - 3 + for (int i = 0; i < (limbs - 1); i++) { + __ movq(carry, mask); + __ addq(carry, c[i]); + __ sarq(carry, bpl); + __ addq(c[i + 1], carry); + __ shlq(carry, bpl); + __ subq(c[i], carry); + } + + __ pop_ppx(rdx); + + for (int i = 0; i < limbs; i++) { + __ movq(Address(rLimbs, i * 8), c[i]); + } +} + +address StubGenerator::generate_intpoly_mult_25519() { + StubId stub_id = StubId::stubgen_intpoly_mult_25519_id; + int entry_count = StubInfo::entry_count(stub_id); + assert(entry_count == 1, "sanity check"); + address start = load_archive_data(stub_id); + if (start != nullptr) { + return start; + } + __ align(CodeEntryAlignment); + StubCodeMark mark(this, stub_id); + start = __ pc(); + __ enter(); + + // Register Map + const Register aLimbs = c_rarg0; // rdi | rcx + const Register bLimbs = c_rarg1; // rsi | rdx + const Register rLimbs = c_rarg2; // rdx | r8 + + Register c[] = {r9, r10, r11, r12, r13}; + Register bArg = r14; + Register d = r15; + Register b = rbp; + Register mask = rbx; + + __ push_ppx(rbp); + __ push_ppx(rbx); + __ push_ppx(r12); + __ push_ppx(r13); + __ push_ppx(r14); + __ push_ppx(r15); + __ push_ppx(rdx); + + multiply_25519_scalar(aLimbs, bLimbs, rLimbs, c, bArg, d, b, mask, _masm); + + // __ pop_ppx(rdx); // restored in the helper already + __ pop_ppx(r15); + __ pop_ppx(r14); + __ pop_ppx(r13); + __ pop_ppx(r12); + __ pop_ppx(rbx); + __ pop_ppx(rbp); + + __ leave(); + __ ret(0); + + // Record the stub entry and end + store_archive_data(stub_id, start, __ pc()); + + return start; +} + +address StubGenerator::generate_intpoly_square_25519() { + StubId stub_id = StubId::stubgen_intpoly_square_25519_id; + int entry_count = StubInfo::entry_count(stub_id); + assert(entry_count == 1, "sanity check"); + address start = load_archive_data(stub_id); + if (start != nullptr) { + return start; + } + __ align(CodeEntryAlignment); + StubCodeMark mark(this, stub_id); + start = __ pc(); + __ enter(); + + // Register Map + const Register aLimbs = c_rarg0; // rdi | rcx + const Register rLimbs = c_rarg1; // rsi | rdx + Register c[] = {r9, r10, r11, r12, r13}; + Register aArg = r14; + Register d = r15; + Register carry = rbp; + Register mask = rbx; + + __ push_ppx(rbp); + __ push_ppx(rbx); + __ push_ppx(r12); + __ push_ppx(r13); + __ push_ppx(r14); + __ push_ppx(r15); + __ push_ppx(rdx); + + square_25519_scalar(aLimbs, rLimbs, c, aArg, d, carry, mask, _masm); + + // __ pop_ppx(rdx); // restored in the helper already + __ pop_ppx(r15); + __ pop_ppx(r14); + __ pop_ppx(r13); + __ pop_ppx(r12); + __ pop_ppx(rbx); + __ pop_ppx(rbp); + + __ leave(); + __ ret(0); + + // Record the stub entry and end + store_archive_data(stub_id, start, __ pc()); + + return start; +} +#undef __ diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp index 308a80429938..76b6fa97fa58 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Intel Corporation. All rights reserved. + * Copyright (c) 2024, 2026, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -676,7 +676,7 @@ address StubGenerator::generate_intpoly_assign() { // KNOWN Lengths: // MontgomeryIntPolynP256: 5 = 4 + 1 // IntegerPolynomial1305: 5 = 4 + 1 - // IntegerPolynomial25519: 10 = 8 + 2 + // IntegerPolynomial25519: 5 = 4 + 1 // IntegerPolynomialP256: 10 = 8 + 2 // Curve25519OrderField: 10 = 8 + 2 // Curve25519OrderField: 10 = 8 + 2 diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4cdcb1770bbe..2ca1c1725427 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1407,6 +1407,10 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseIntPolyIntrinsics, false); } + if (FLAG_IS_DEFAULT(UseIntPoly25519Intrinsics)) { + UseIntPoly25519Intrinsics = true; + } + if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index b3dd1a0812b5..370437edee2c 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)))); - - ins_cost(250); - format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %} - 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)))); +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# signed, 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); + __ 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)))); - - ins_cost(200); - format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %} - ins_encode %{ - __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$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)))); +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# signed, 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); + 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/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 8f24c0da3098..8a002054b9af 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2183,6 +2183,10 @@ void os::print_os_info(outputStream* st) { st->cr(); } + if (os::Linux::print_numa_info(st)) { + st->cr(); + } + VM_Version::print_platform_virtualization_info(st); // SapMachine 2019-07-02: 8225345: Provide Cloud IAAS related info on Linux in the hs_err file @@ -2625,6 +2629,97 @@ bool os::Linux::print_container_info(outputStream* st) { return true; } +#define SYS_DEVICES_NODE "/sys/devices/system/node" + +static size_t read_sysfs_file(const char* path, char* buf, size_t sz) { + FILE* f = os::fopen(path, "r"); + if (f == nullptr) return 0; + size_t n = fread(buf, 1, sz - 1, f); + fclose(f); + buf[n] = '\0'; + while (n > 0 && (buf[n-1] == '\n' || buf[n-1] == '\r')) buf[--n] = '\0'; + return n; +} + +static void print_numa_memory_info(outputStream* st, int node) { + char path[256]; + char line[256]; + long long mem_total = -1; + long long mem_free = -1; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/meminfo", node); + FILE* f = os::fopen(path, "r"); + if (f == nullptr) { + return; + } + + while (fgets(line, sizeof(line), f) != nullptr) { + long long mval; + if (sscanf(line, "Node %*d MemTotal: %lld kB", &mval) == 1) mem_total = mval; + if (sscanf(line, "Node %*d MemFree: %lld kB", &mval) == 1) mem_free = mval; + } + fclose(f); + + if (mem_total >= 0) { st->print_cr("mem size: %lld kB", mem_total); } + if (mem_free >= 0) { st->print_cr("mem free: %lld kB", mem_free); } +} + +static void print_numa_cpu_list(outputStream* st, int node) { + char path[256]; + char buf[1024]; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/cpulist", node); + if (read_sysfs_file(path, buf, sizeof(buf)) > 0) { + st->print_cr("cpus: %s", buf); + } else { + st->print_cr("cpus: (unavailable)"); + } +} + +bool os::Linux::print_numa_info(outputStream* st) { + if (!UseNUMA) { + // If NUMA optimizations are not enabled we don't print anything + return false; + } + + char buf[1024]; + if (read_sysfs_file("/sys/devices/system/node/online", buf, sizeof(buf)) > 0) { + st->print_cr("NUMA nodes online: %s", buf); + } else { + return false; + } + + bool first = true; + int node_count = 0; + + if (nindex_to_node() == nullptr) { + return false; + } + + for (int node: *nindex_to_node()) { + char nodepath[256]; + os::snprintf_checked(nodepath, sizeof(nodepath), SYS_DEVICES_NODE "/node%d", node); + DIR* currd = os::opendir(nodepath); + if (currd == nullptr) continue; + if (first) { + st->cr(); + first = false; + } + os::closedir(currd); + + st->print_cr("NUMA node %d", node); + StreamIndentor si(st); + print_numa_cpu_list(st, node); + print_numa_memory_info(st, node); + node_count++; + } + + if (node_count == 0) { + return false; + } + + st->print_cr("Total NUMA node count: %d", node_count); + return true; +} + // SapMachine 2019-07-02: 8225345: Provide Cloud IAAS related info on Linux in the hs_err file static int check_matching_lines_from_file(const char* filename, const char* keywords_to_match[]) { char line[500]; diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index e87638e284a0..a01e0f6dfd39 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -79,6 +79,7 @@ class os::Linux { static void print_proc_sys_info(outputStream* st); static bool print_ld_preload_file(outputStream* st); static void print_uptime_info(outputStream* st); + static bool print_numa_info(outputStream* st); public: struct CPUPerfTicks { diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 9137723fa582..d00babef40f3 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -243,6 +243,16 @@ static LPVOID virtualAllocExNuma(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSiz return result; } +void* os::win32::lookup_kernelbase_symbol(const char* name) { + // Pass a small ebuf so dll_load logs failures, but don't use it here to avoid redundancy. + char ebuf[1024]; + static void* const handle = os::dll_load("KernelBase", ebuf, sizeof(ebuf)); + if (handle == nullptr) { + return nullptr; + } + return os::dll_lookup(handle, name); +} + // Logging wrapper for MapViewOfFileEx static LPVOID mapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) { @@ -3250,9 +3260,9 @@ char* os::map_memory_to_file(char* base, size_t size, int fd) { assert(fd != -1, "File descriptor is not valid"); HANDLE fh = (HANDLE)_get_osfhandle(fd); - HANDLE fileMapping = CreateFileMapping(fh, nullptr, PAGE_READWRITE, + HANDLE file_mapping = CreateFileMapping(fh, nullptr, PAGE_READWRITE, (DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), nullptr); - if (fileMapping == nullptr) { + if (file_mapping == nullptr) { if (GetLastError() == ERROR_DISK_FULL) { vm_exit_during_initialization(err_msg("Could not allocate sufficient disk space for Java heap")); } @@ -3263,9 +3273,9 @@ char* os::map_memory_to_file(char* base, size_t size, int fd) { return nullptr; } - LPVOID addr = mapViewOfFileEx(fileMapping, FILE_MAP_WRITE, 0, 0, size, base); + LPVOID addr = mapViewOfFileEx(file_mapping, FILE_MAP_WRITE, 0, 0, size, base); - CloseHandle(fileMapping); + CloseHandle(file_mapping); return (char*)addr; } @@ -3278,40 +3288,75 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in return map_memory_to_file(base, size, fd); } +// VirtualAlloc2 / MapViewOfFile3 (Windows 1803+). Resolved in os::init_2() via lookup_kernelbase_symbol. +os::win32::VirtualAlloc2Fn os::win32::VirtualAlloc2 = nullptr; + +os::win32::MapViewOfFile3Fn os::win32::MapViewOfFile3 = nullptr; + +static bool is_VirtualAlloc2_supported() { + return os::win32::VirtualAlloc2 != nullptr; +} + +static bool is_MapViewOfFile3_supported() { + return os::win32::MapViewOfFile3 != nullptr; +} + // Multiple threads can race in this code but it's not possible to unmap small sections of // virtual space to get requested alignment, like posix-like os's. // Windows prevents multiple thread from remapping over each other so this loop is thread-safe. -static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { +static char* reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag) { assert(is_aligned(alignment, os::vm_allocation_granularity()), - "Alignment must be a multiple of allocation granularity (page size)"); + "Alignment must be a multiple of allocation granularity"); assert(is_aligned(size, os::vm_allocation_granularity()), - "Size must be a multiple of allocation granularity (page size)"); + "Size must be a multiple of allocation granularity"); size_t extra_size = size + alignment; assert(extra_size >= size, "overflow, size is too large to allow alignment"); char* aligned_base = nullptr; - static const int max_attempts = 20; + constexpr int max_attempts = 20; for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) { - char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, mem_tag) : - os::reserve_memory(extra_size, mem_tag); + char* extra_base = os::reserve_memory(extra_size, mem_tag); if (extra_base == nullptr) { return nullptr; } - // Do manual alignment aligned_base = align_up(extra_base, alignment); + os::release_memory(extra_base, extra_size); - if (file_desc != -1) { - os::unmap_memory(extra_base, extra_size); - } else { - os::release_memory(extra_base, extra_size); + // A racing thread may have taken this region instead of us, which is why we loop and retry. + aligned_base = os::attempt_reserve_memory_at(aligned_base, size, mem_tag); + } + + assert(aligned_base != nullptr, + "Did not manage to reserve after %d attempts (size %zu, alignment %zu)", max_attempts, size, alignment); + + return aligned_base; +} + +// Similar to reserve_memory_aligned, other reservation/mapping requests can race with this function. +static char* map_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { + assert(is_aligned(alignment, os::vm_allocation_granularity()), + "Alignment must be a multiple of allocation granularity"); + assert(is_aligned(size, os::vm_allocation_granularity()), + "Size must be a multiple of allocation granularity"); + + size_t extra_size = size + alignment; + assert(extra_size >= size, "overflow, size is too large to allow alignment"); + + char* aligned_base = nullptr; + constexpr int max_attempts = 20; + + for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) { + char* extra_base = os::map_memory_to_file(extra_size, file_desc, mem_tag); + if (extra_base == nullptr) { + return nullptr; } + aligned_base = align_up(extra_base, alignment); + os::unmap_memory(extra_base, extra_size); - // Attempt to map, into the just vacated space, the slightly smaller aligned area. - // Which may fail, hence the loop. - aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, mem_tag) : - os::attempt_reserve_memory_at(aligned_base, size, mem_tag); + // A racing thread may have taken this region instead of us, which is why we loop and retry. + aligned_base = os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, mem_tag); } assert(aligned_base != nullptr, @@ -3320,6 +3365,84 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi return aligned_base; } +// MapViewOfFile3 supports alignment natively. +static char* map_memory_aligned_va2(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { + assert(file_desc != -1, "File descriptor should not be -1"); + assert(is_aligned(alignment, os::vm_allocation_granularity()), + "Alignment must be a multiple of allocation granularity"); + assert(is_aligned(size, os::vm_allocation_granularity()), + "Size must be a multiple of allocation granularity"); + + MEM_ADDRESS_REQUIREMENTS requirements = {0}; + requirements.Alignment = alignment; + + MEM_EXTENDED_PARAMETER param = {0}; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &requirements; + + char* aligned_base = nullptr; + + // File-backed aligned mapping. + HANDLE fh = (HANDLE)_get_osfhandle(file_desc); + HANDLE file_mapping = CreateFileMapping(fh, nullptr, PAGE_READWRITE,(DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), nullptr); + DWORD err = GetLastError(); + if (file_mapping != nullptr) { + aligned_base = (char*)os::win32::MapViewOfFile3( + file_mapping, + GetCurrentProcess(), + nullptr, // let the system choose an aligned address + 0, // offset + size, + 0, // no special allocation type flags + PAGE_READWRITE, + ¶m, 1); + err = GetLastError(); + CloseHandle(file_mapping); + } + + if (aligned_base != nullptr) { + assert(is_aligned(aligned_base, alignment), "Result must be aligned"); + MemTracker::record_virtual_memory_reserve_and_commit(aligned_base, size, CALLER_PC, mem_tag); + return aligned_base; + } + log_trace(os)("Aligned allocation via MapViewOfFile3 failed, falling back to retry loop. GetLastError->%lu.", err); + return map_memory_aligned(size, alignment, file_desc, mem_tag); +} + +// VirtualAlloc2 supports alignment natively. +static char* reserve_memory_aligned_va2(size_t size, size_t alignment, MemTag mem_tag) { + assert(is_aligned(alignment, os::vm_allocation_granularity()), + "Alignment must be a multiple of allocation granularity"); + assert(is_aligned(size, os::vm_allocation_granularity()), + "Size must be a multiple of allocation granularity"); + + MEM_ADDRESS_REQUIREMENTS requirements = {0}; + requirements.Alignment = alignment; + + MEM_EXTENDED_PARAMETER param = {0}; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &requirements; + + char* aligned_base = nullptr; + + // Anonymous aligned reservation. + aligned_base = (char*)os::win32::VirtualAlloc2( + GetCurrentProcess(), + nullptr, // let the system choose an aligned address + size, + MEM_RESERVE, + PAGE_READWRITE, + ¶m, 1); + + if (aligned_base != nullptr) { + assert(is_aligned(aligned_base, alignment), "Result must be aligned"); + MemTracker::record_virtual_memory_reserve(aligned_base, size, CALLER_PC, mem_tag); + return aligned_base; + } + log_trace(os)("Aligned allocation via VirtualAlloc2 failed, falling back to retry loop. GetLastError->%lu.", GetLastError()); + return reserve_memory_aligned(size, alignment, mem_tag); +} + size_t os::commit_memory_limit() { BOOL is_in_job_object = false; BOOL res = IsProcessInJob(GetCurrentProcess(), nullptr, &is_in_job_object); @@ -3367,11 +3490,17 @@ size_t os::reserve_memory_limit() { char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) { // exec can be ignored - return map_or_reserve_memory_aligned(size, alignment, -1/* file_desc */, mem_tag); + if (is_VirtualAlloc2_supported()) { + return reserve_memory_aligned_va2(size, alignment, mem_tag); + } + return reserve_memory_aligned(size, alignment, mem_tag); } char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag) { - return map_or_reserve_memory_aligned(size, alignment, fd, mem_tag); + if (is_MapViewOfFile3_supported()) { + return map_memory_aligned_va2(size, alignment, fd, mem_tag); + } + return map_memory_aligned(size, alignment, fd, mem_tag); } char* os::pd_reserve_memory(size_t bytes, bool exec) { @@ -4588,21 +4717,21 @@ jint os::init_2(void) { // Lookup SetThreadDescription - the docs state we must use runtime-linking of // kernelbase.dll, so that is what we do. - HINSTANCE _kernelbase = LoadLibrary(TEXT("kernelbase.dll")); - if (_kernelbase != nullptr) { - _SetThreadDescription = - reinterpret_cast( - GetProcAddress(_kernelbase, - "SetThreadDescription")); + _SetThreadDescription = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("SetThreadDescription")); #ifdef ASSERT - _GetThreadDescription = - reinterpret_cast( - GetProcAddress(_kernelbase, - "GetThreadDescription")); + _GetThreadDescription = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("GetThreadDescription")); #endif - } log_info(os, thread)("The SetThreadDescription API is%s available.", _SetThreadDescription == nullptr ? " not" : ""); + // Prepare KernelBase APIs (VirtualAlloc2, MapViewOfFile3) if available (Windows version 1803). + os::win32::VirtualAlloc2 = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("VirtualAlloc2")); + os::win32::MapViewOfFile3 = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("MapViewOfFile3")); + log_debug(os)("VirtualAlloc2 is%s available.", os::win32::VirtualAlloc2 == nullptr ? " not" : ""); + log_debug(os)("MapViewOfFile3 is%s available.", os::win32::MapViewOfFile3 == nullptr ? " not" : ""); return JNI_OK; } diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index d4a7d51c59b9..5ebc80c817b7 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -109,6 +109,19 @@ class os::win32 { // load dll from Windows system directory or Windows directory static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen); + // Resolve a symbol from KernelBase.dll, returns nullptr if not found. + static void* lookup_kernelbase_symbol(const char* name); + + // VirtualAlloc2 (since Windows version 1803) + // Resolved from KernelBase during os::init_2() or nullptr if unavailable. + typedef PVOID (WINAPI *VirtualAlloc2Fn)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG); + static VirtualAlloc2Fn VirtualAlloc2; + + // MapViewOfFile3 (since Windows version 1803) + // Resolved from KernelBase during os::init_2() or nullptr if unavailable. + typedef PVOID (WINAPI *MapViewOfFile3Fn)(HANDLE, HANDLE, PVOID, ULONG64, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG); + static MapViewOfFile3Fn MapViewOfFile3; + private: static void initialize_performance_counter(); diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 253f460dca30..a3bd1bfa8705 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/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp index 0f79e7a5a69b..a0cfe2a9893f 100644 --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -31,7 +31,10 @@ #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/timerTrace.hpp" #include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" #include "utilities/ostream.hpp" #include "utilities/tableStatistics.hpp" @@ -239,10 +242,24 @@ void Dictionary::verify() { } void Dictionary::print_table_statistics(outputStream* st, const char* table_name) { - static TableStatistics ts; + TableStatistics stats; auto sz = [&] (InstanceKlass** val) { return sizeof(**val); }; - ts = _table->statistics_get(Thread::current(), sz, ts); - ts.print(st, table_name); + Thread* thread = Thread::current(); + ConcurrentTable::StatisticsTask sts(_table); + if (!sts.prepare(thread)) { + st->print_cr("Failed to take statistics"); + return; + } + TraceTime timer("GetStatistics", TRACETIME_LOG(Debug, perf)); + while (sts.do_task(thread, sz)) { + sts.pause(thread); + if (thread->is_Java_thread()) { + ThreadBlockInVM tbivm(JavaThread::cast(thread)); + } + sts.cont(thread); + } + stats = sts.done(thread); + stats.print(st, table_name); } diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index cec3586a50b5..4a1b9ead116b 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, 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 @@ -527,6 +527,10 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_intpoly_assign: if (!UseIntPolyIntrinsics) return true; break; + case vmIntrinsics::_intpoly_mult_25519: + case vmIntrinsics::_intpoly_square_25519: + if (!UseIntPoly25519Intrinsics) return true; + break; case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: if (!UseCRC32CIntrinsics) return true; diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index de4eea669a10..8833e4167f65 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -549,6 +549,13 @@ class methodHandle; do_name(intPolyAssign_name, "conditionalAssign") \ do_signature(intPolyAssign_signature, "(I[J[J)V") \ \ + /* support for sun.security.util.math.intpoly.IntegerPolynomial25519 */ \ + do_class(sun_security_util_math_intpoly_IntegerPolynomial25519, "sun/security/util/math/intpoly/IntegerPolynomial25519") \ + do_intrinsic(_intpoly_mult_25519, sun_security_util_math_intpoly_IntegerPolynomial25519, intPolyMult_name, intPolyMult_signature, F_R) \ + do_intrinsic(_intpoly_square_25519, sun_security_util_math_intpoly_IntegerPolynomial25519, intPolySquare_name, intPolySquare_signature, F_R) \ + do_name(intPolySquare_name, "square") \ + do_signature(intPolySquare_signature, "([J[J)V") \ + \ /* support for java.util.Base64.Encoder*/ \ do_class(java_util_Base64_Encoder, "java/util/Base64$Encoder") \ do_intrinsic(_base64_encodeBlock, java_util_Base64_Encoder, encodeBlock_name, encodeBlock_signature, F_R) \ diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 83dda2a043bb..4afc7fa8ff12 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -714,6 +714,11 @@ class G1ClearBitMapTask : public WorkerTask { } HeapWord* region_clear_limit(G1HeapRegion* r) { + // A garbage collection might have made the region unavailable after a yield during + // clearing. Just return bottom as the limit, causing the clearing for this region to end. + if (G1CollectedHeap::heap()->region_at_or_null(r->hrm_index()) == nullptr) { + return r->bottom(); + } // During a Concurrent Undo Mark cycle, the per region top_at_mark_start and // live_words data are current wrt to the _mark_bitmap. We use this information // to only clear ranges of the bitmap that require clearing. @@ -743,7 +748,7 @@ class G1ClearBitMapTask : public WorkerTask { } HeapWord* cur = r->bottom(); - HeapWord* const end = region_clear_limit(r); + HeapWord* end = region_clear_limit(r); size_t const chunk_size_in_words = G1ClearBitMapTask::chunk_size() / HeapWordSize; @@ -761,8 +766,12 @@ class G1ClearBitMapTask : public WorkerTask { assert(!suspendible() || _cm->is_in_reset_for_next_cycle(), "invariant"); // Abort iteration if necessary. - if (has_aborted()) { - return true; + if (suspendible() && _cm->do_yield_check()) { + if (_cm->has_aborted()) { + return true; + } + // Re-read end. The region might have been uncommitted. + end = region_clear_limit(r); } } assert(cur >= end, "Must have completed iteration over the bitmap for region %u.", r->hrm_index()); diff --git a/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp b/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp index e1203229557a..f88736c5642f 100644 --- a/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp +++ b/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, 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 @@ -58,9 +58,9 @@ void G1UncommitRegionTask::enqueue() { G1UncommitRegionTask* uncommit_task = instance(); if (!uncommit_task->is_active()) { - // Change state to active and schedule using UncommitInitialDelayMs. + // Change state to active and schedule. uncommit_task->set_active(true); - G1CollectedHeap::heap()->service_thread()->schedule_task(uncommit_task, UncommitInitialDelayMs); + G1CollectedHeap::heap()->service_thread()->schedule_task(uncommit_task, G1UncommitInitialDelay); } } diff --git a/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp b/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp index 7c9a25f6857d..835217d2a595 100644 --- a/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp +++ b/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, 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 @@ -34,8 +34,6 @@ class G1UncommitRegionTask : public G1ServiceTask { // This limit is small enough to ensure that the duration of each invocation // is short, while still making reasonable progress. static const uint UncommitSizeLimit = 128 * M; - // Initial delay in milliseconds after GC before the regions are uncommitted. - static const uint UncommitInitialDelayMs = 100; // The delay between two uncommit task executions. static const uint UncommitTaskDelayMs = 10; diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 14daac4800b1..8a346c5c78f3 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -184,6 +184,10 @@ "shrink attempt.") \ range(0, 100) \ \ + develop(uint, G1UncommitInitialDelay, 100, \ + "Delay in milliseconds until regions just made eligible for " \ + "uncommit are actually uncommitted.") \ + \ product(uint, G1CPUUsageDeviationPercent, 25, DIAGNOSTIC, \ "The acceptable deviation (in percent) from the target GC CPU " \ "usage (based on GCTimeRatio). Creates a tolerance range " \ diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.cpp b/src/hotspot/share/gc/parallel/psMemoryPool.cpp index 40170f62f065..13304ca18ad2 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 a4a2bfe72c2d..ff757f205a26 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"); - - 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; - } + precond(!_space_info[old_space_id].split_info().is_valid()); - 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 25f4f66de6f4..909005f5360a 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -760,8 +760,11 @@ class PSParallelCompact : AllStatic { // 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/cardTableRS.cpp b/src/hotspot/share/gc/serial/cardTableRS.cpp index a53ab0663873..fe4977a809a1 100644 --- a/src/hotspot/share/gc/serial/cardTableRS.cpp +++ b/src/hotspot/share/gc/serial/cardTableRS.cpp @@ -49,7 +49,14 @@ void CardTableRS::scan_old_to_young_refs(TenuredGeneration* tg, HeapWord* saved_ void CardTableRS::maintain_old_to_young_invariant(TenuredGeneration* old_gen, bool is_young_gen_empty) { if (is_young_gen_empty) { - clear_MemRegion(old_gen->prev_used_region()); + MemRegion prev_used_mr = old_gen->prev_used_region(); + if (!prev_used_mr.is_empty()) { + clear_MemRegion(prev_used_mr); + } + { + MemRegion old_gen_committed{old_gen->space()->bottom(), old_gen->space()->end()}; + verify_region(old_gen_committed, clean_card_val(), true); + } } else { MemRegion used_mr = old_gen->used_region(); MemRegion prev_used_mr = old_gen->prev_used_region(); @@ -59,7 +66,9 @@ void CardTableRS::maintain_old_to_young_invariant(TenuredGeneration* old_gen, } // No idea which card contains old-to-young pointer, so dirtying cards for // the entire used part of old-gen conservatively. - dirty_MemRegion(used_mr); + if (!used_mr.is_empty()) { + dirty_MemRegion(used_mr); + } } } diff --git a/src/hotspot/share/gc/serial/serialMemoryPools.cpp b/src/hotspot/share/gc/serial/serialMemoryPools.cpp index 723b53a3e2b0..8b0230264ef1 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 e6e3fdf3d820..dcf13ab48e95 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 f60a7f47a192..5c10a1618a59 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/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 1ff6fd493a76..14bc320e32c6 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -199,10 +199,9 @@ range(1, (INT_MAX - 1)) \ \ product(size_t, ReferencesPerThread, 1000, EXPERIMENTAL, \ - "Ergonomically start one thread for this amount of " \ - "references for reference processing if " \ - "ParallelRefProcEnabled is true. Specify 0 to disable and " \ - "use all threads.") \ + "Ergonomically start one thread for this amount of references " \ + "for reference processing for parallel stop-the-world garbage " \ + "collectors. Specify 0 to force use of all available threads.") \ \ product(uint, InitiatingHeapOccupancyPercent, 45, \ "The percent occupancy (IHOP) of the current old generation " \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 07eb653bc94f..08032b224d00 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -1203,19 +1203,13 @@ void ShenandoahConcurrentGC::op_final_update_refs() { heap->verifier()->verify_roots_in_to_space(_generation); } - // If we are running in generational mode and this is an aging cycle, this will also age active - // regions that haven't been used for allocation. + // If we are running in generational mode, this will also age active regions that + // haven't been used for allocation. heap->update_heap_region_states(true /*concurrent*/); heap->set_update_refs_in_progress(false); heap->set_has_forwarded_objects(false); - if (heap->mode()->is_generational() && heap->is_concurrent_old_mark_in_progress()) { - // Aging_cycle is only relevant during evacuation cycle for individual objects and during final mark for - // entire regions. Both of these relevant operations occur before final update refs. - ShenandoahGenerationalHeap::heap()->set_aging_cycle(false); - } - if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify); heap->verifier()->verify_after_update_refs(_generation); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 4c474f2f86cf..6563ffb6359b 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/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 94f3409ac41b..f522a33a31ce 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -53,8 +53,7 @@ ShenandoahGenerationalControlThread::ShenandoahGenerationalControlThread() : _requested_generation(nullptr), _gc_mode(none), _degen_point(ShenandoahGC::_degenerated_unset), - _heap(ShenandoahGenerationalHeap::heap()), - _age_period(0) { + _heap(ShenandoahGenerationalHeap::heap()) { shenandoah_assert_generational(); set_name("ShenControl"); create_and_start(); @@ -230,15 +229,6 @@ void ShenandoahGenerationalControlThread::maybe_print_young_region_ages() const } } -void ShenandoahGenerationalControlThread::maybe_set_aging_cycle() { - if (_age_period-- == 0) { - _heap->set_aging_cycle(true); - _age_period = ShenandoahAgingCyclePeriod - 1; - } else { - _heap->set_aging_cycle(false); - } -} - void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest& request) { log_debug(gc, thread)("Starting GC (%s): %s, %s", gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name()); @@ -534,9 +524,6 @@ void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahGen // At this point: // if (generation == YOUNG), this is a normal young cycle or a bootstrap cycle // if (generation == GLOBAL), this is a GLOBAL cycle - // In either case, we want to age old objects if this is an aging cycle - maybe_set_aging_cycle(); - ShenandoahGCSession session(cause, generation); TraceCollectorStats tcs(_heap->monitoring_support()->concurrent_collection_counters()); @@ -615,7 +602,6 @@ bool ShenandoahGenerationalControlThread::check_cancellation_or_degen(Shenandoah void ShenandoahGenerationalControlThread::service_stw_full_cycle(GCCause::Cause cause) { _heap->increment_total_collections(true); ShenandoahGCSession session(cause, _heap->global_generation()); - maybe_set_aging_cycle(); ShenandoahFullGC gc; gc.collect(cause); _degen_point = ShenandoahGC::_degenerated_unset; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index 13e69d252687..5a3ab25eabe8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -80,9 +80,6 @@ class ShenandoahGenerationalControlThread: public ShenandoahController { // A reference to the heap ShenandoahGenerationalHeap* _heap; - // This is used to keep track of whether to age objects during the current cycle. - uint _age_period; - // This is true when the old generation cycle is in an interruptible phase (i.e., marking or // preparing for mark). ShenandoahSharedFlag _allow_old_preemption; @@ -142,9 +139,6 @@ class ShenandoahGenerationalControlThread: public ShenandoahController { void notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation); void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation); - // Configure the heap to age objects and regions if the aging period has elapsed. - void maybe_set_aging_cycle(); - // Take the _control_lock and check for a request to run a gc cycle. If a request is found, // the `prepare` methods are used to configure the heap and update heuristics accordingly. void check_for_request(ShenandoahGCRequest& request); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 1b11c696d189..43dbddda9f7c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -312,11 +312,7 @@ void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) { // After full gc compaction, all regions have age 0. Embed the region's age into the object's age in order to preserve // tenuring progress. - if (_heap->is_aging_cycle()) { - ShenandoahHeap::increase_object_age(p, from_region_age + 1); - } else { - ShenandoahHeap::increase_object_age(p, from_region_age); - } + ShenandoahHeap::increase_object_age(p, from_region_age + 1); if (_young_compact_point + obj_size > _young_to_region->end()) { ShenandoahHeapRegion* new_to_region; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 4af2c9b1e5d8..7170c88cd43c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -347,7 +347,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, uint oop copy_val = cast_to_oop(copy); // Update the age of the evacuated object - if (TO_GENERATION == YOUNG_GENERATION && is_aging_cycle()) { + if (TO_GENERATION == YOUNG_GENERATION) { increase_object_age(copy_val, from_region_age + 1); } @@ -975,7 +975,7 @@ class ShenandoahUpdateRegionAges : public ShenandoahHeapRegionClosure { // There have been allocations in this region since the start of the cycle. // Any objects new to this region must not assimilate elevated age. r->reset_age(); - } else if (ShenandoahGenerationalHeap::heap()->is_aging_cycle()) { + } else { r->increment_age(); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index d6893dc011ec..91e5522de430 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -61,21 +61,10 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { private: // ---------- Evacuations and Promotions - // - // True when regions and objects should be aged during the current cycle - ShenandoahSharedFlag _is_aging_cycle; // Age census used for adapting tenuring threshold ShenandoahAgeCensus* _age_census; public: - void set_aging_cycle(bool cond) { - _is_aging_cycle.set_cond(cond); - } - - inline bool is_aging_cycle() const { - return _is_aging_cycle.is_set(); - } - // Return the age census object for young gen ShenandoahAgeCensus* age_census() const { return _age_census; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index ad8cd2209688..33d5fa6b04f7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -66,7 +66,6 @@ class ShenandoahFreeSet; class ShenandoahConcurrentMark; class ShenandoahFullGC; class ShenandoahMonitoringSupport; -class ShenandoahPacer; class ShenandoahReferenceProcessor; class ShenandoahUncommitThread; class ShenandoahVerifier; @@ -534,7 +533,6 @@ class ShenandoahHeap : public CollectedHeap { ShenandoahCollectorPolicy* _shenandoah_policy; ShenandoahMode* _gc_mode; ShenandoahFreeSet* _free_set; - ShenandoahPacer* _pacer; ShenandoahVerifier* _verifier; ShenandoahPhaseTimings* _phase_timings; @@ -559,7 +557,6 @@ class ShenandoahHeap : public CollectedHeap { ShenandoahCollectorPolicy* shenandoah_policy() const { return _shenandoah_policy; } ShenandoahMode* mode() const { return _gc_mode; } ShenandoahFreeSet* free_set() const { return _free_set; } - ShenandoahPacer* pacer() const { return _pacer; } ShenandoahPhaseTimings* phase_timings() const { return _phase_timings; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index aa6b71a7c50e..3647a8184908 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -529,10 +529,6 @@ "Allow young generation collections to suspend concurrent" \ " marking in the old generation.") \ \ - product(uintx, ShenandoahAgingCyclePeriod, 1, EXPERIMENTAL, \ - "With generational mode, increment the age of objects and" \ - "regions each time this many young-gen GC cycles are completed.") \ - \ develop(bool, ShenandoahEnableCardStats, false, \ "Enable statistics collection related to clean & dirty cards") \ \ diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 2f48fffcaa29..bf434030499d 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -819,6 +819,8 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_poly1305_processBlocks: case vmIntrinsics::_intpoly_montgomeryMult_P256: case vmIntrinsics::_intpoly_assign: + case vmIntrinsics::_intpoly_mult_25519: + case vmIntrinsics::_intpoly_square_25519: case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 49e59c70c470..f561818a99bc 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2272,6 +2272,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "poly1305_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "intpoly_montgomeryMult_P256") == 0 || strcmp(call->as_CallLeaf()->_name, "intpoly_assign") == 0 || + strcmp(call->as_CallLeaf()->_name, "intpoly_mult_25519") == 0 || + strcmp(call->as_CallLeaf()->_name, "intpoly_square_25519") == 0 || strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "chacha20Block") == 0 || strcmp(call->as_CallLeaf()->_name, "kyberNtt") == 0 || diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 7251783d771a..adb8ff2dedbf 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -666,6 +666,10 @@ bool LibraryCallKit::try_to_inline(int predicate) { return inline_intpoly_montgomeryMult_P256(); case vmIntrinsics::_intpoly_assign: return inline_intpoly_assign(); + case vmIntrinsics::_intpoly_mult_25519: + return inline_intpoly_mult_25519(); + case vmIntrinsics::_intpoly_square_25519: + return inline_intpoly_square_25519(); case vmIntrinsics::_encodeISOArray: case vmIntrinsics::_encodeByteISOArray: return inline_encodeISOArray(false); @@ -8373,6 +8377,70 @@ bool LibraryCallKit::inline_intpoly_assign() { return true; } +bool LibraryCallKit::inline_intpoly_mult_25519() { + address stubAddr; + const char *stubName; + assert(UseIntPoly25519Intrinsics, "need intpoly25519 intrinsics support"); + assert(callee()->signature()->size() == 3, "intpoly_mult_25519 has %d parameters", callee()->signature()->size()); + stubAddr = StubRoutines::intpoly_mult_25519(); + stubName = "intpoly_mult_25519"; + + if (!stubAddr) return false; + null_check_receiver(); // null-check receiver + if (stopped()) return true; + + Node* a = argument(1); + Node* b = argument(2); + Node* r = argument(3); + + a = must_be_not_null(a, true); + b = must_be_not_null(b, true); + r = must_be_not_null(r, true); + + Node* a_start = array_element_address(a, intcon(0), T_LONG); + assert(a_start, "a array is null"); + Node* b_start = array_element_address(b, intcon(0), T_LONG); + assert(b_start, "b array is null"); + Node* r_start = array_element_address(r, intcon(0), T_LONG); + assert(r_start, "r array is null"); + + Node* call = make_runtime_call(RC_LEAF | RC_NO_FP, + OptoRuntime::intpoly_mult_25519_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + a_start, b_start, r_start); + return true; +} + +bool LibraryCallKit::inline_intpoly_square_25519() { + address stubAddr; + const char *stubName; + assert(UseIntPoly25519Intrinsics, "need intpoly25519 intrinsics support"); + assert(callee()->signature()->size() == 2, "intpoly_mult_25519 has %d parameters", callee()->signature()->size()); + stubAddr = StubRoutines::intpoly_square_25519(); + stubName = "intpoly_square_25519"; + + if (!stubAddr) return false; + null_check_receiver(); // null-check receiver + if (stopped()) return true; + + Node* a = argument(1); + Node* r = argument(2); + + a = must_be_not_null(a, true); + r = must_be_not_null(r, true); + + Node* a_start = array_element_address(a, intcon(0), T_LONG); + assert(a_start, "a array is null"); + Node* r_start = array_element_address(r, intcon(0), T_LONG); + assert(r_start, "r array is null"); + + Node* call = make_runtime_call(RC_LEAF | RC_NO_FP, + OptoRuntime::intpoly_square_25519_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + a_start, r_start); + return true; +} + //------------------------------inline_digestBase_implCompress----------------------- // // Calculate MD5 for single-block byte[] array. diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 5b46ae832a4b..871a6b0d0721 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -343,6 +343,8 @@ class LibraryCallKit : public GraphKit { bool inline_poly1305_processBlocks(); bool inline_intpoly_montgomeryMult_P256(); bool inline_intpoly_assign(); + bool inline_intpoly_mult_25519(); + bool inline_intpoly_square_25519(); bool inline_digestBase_implCompress(vmIntrinsics::ID id); bool inline_keccak(vmIntrinsics::ID id); bool inline_digestBase_implCompressMB(int predicate); diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 1afffcadd6e7..7f791082b65e 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -237,6 +237,8 @@ const TypeFunc* OptoRuntime::_string_IndexOf_Type = nullptr; const TypeFunc* OptoRuntime::_poly1305_processBlocks_Type = nullptr; const TypeFunc* OptoRuntime::_intpoly_montgomeryMult_P256_Type = nullptr; const TypeFunc* OptoRuntime::_intpoly_assign_Type = nullptr; +const TypeFunc* OptoRuntime::_intpoly_mult_25519_Type = nullptr; +const TypeFunc* OptoRuntime::_intpoly_square_25519_Type = nullptr; const TypeFunc* OptoRuntime::_updateBytesCRC32_Type = nullptr; const TypeFunc* OptoRuntime::_updateBytesCRC32C_Type = nullptr; const TypeFunc* OptoRuntime::_updateBytesAdler32_Type = nullptr; @@ -1786,6 +1788,41 @@ static const TypeFunc* make_intpoly_assign_Type() { return TypeFunc::make(domain, range); } +static const TypeFunc* make_intpoly_mult_25519_Type() { + int argcnt = 3; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // a array + fields[argp++] = TypePtr::NOTNULL; // b array + fields[argp++] = TypePtr::NOTNULL; // r(esult) array + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = nullptr; // void + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + +static const TypeFunc* make_intpoly_square_25519_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // a array + fields[argp++] = TypePtr::NOTNULL; // r(esult) array + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = nullptr; // void + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + //------------- Interpreter state for on stack replacement static const TypeFunc* make_osr_end_Type() { // create input type (domain) @@ -2354,6 +2391,8 @@ void OptoRuntime::initialize_types() { _poly1305_processBlocks_Type = make_poly1305_processBlocks_Type(); _intpoly_montgomeryMult_P256_Type = make_intpoly_montgomeryMult_P256_Type(); _intpoly_assign_Type = make_intpoly_assign_Type(); + _intpoly_mult_25519_Type = make_intpoly_mult_25519_Type(); + _intpoly_square_25519_Type = make_intpoly_square_25519_Type(); _updateBytesCRC32_Type = make_updateBytesCRC32_Type(); _updateBytesCRC32C_Type = make_updateBytesCRC32C_Type(); _updateBytesAdler32_Type = make_updateBytesAdler32_Type(); diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index af8a206e10cf..5802bf59ae56 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -190,6 +190,8 @@ class OptoRuntime : public AllStatic { static const TypeFunc* _poly1305_processBlocks_Type; static const TypeFunc* _intpoly_montgomeryMult_P256_Type; static const TypeFunc* _intpoly_assign_Type; + static const TypeFunc* _intpoly_mult_25519_Type; + static const TypeFunc* _intpoly_square_25519_Type; static const TypeFunc* _updateBytesCRC32_Type; static const TypeFunc* _updateBytesCRC32C_Type; static const TypeFunc* _updateBytesAdler32_Type; @@ -687,6 +689,18 @@ class OptoRuntime : public AllStatic { return _intpoly_assign_Type; } + // IntegerPolynomial25519 multiply function + static inline const TypeFunc* intpoly_mult_25519_Type() { + assert(_intpoly_mult_25519_Type != nullptr, "should be initialized"); + return _intpoly_mult_25519_Type; + } + + // IntegerPolynomial25519 square function + static inline const TypeFunc* intpoly_square_25519_Type() { + assert(_intpoly_square_25519_Type != nullptr, "should be initialized"); + return _intpoly_square_25519_Type; + } + /** * int updateBytesCRC32(int crc, byte* b, int len) */ diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 014f41f82cc1..39d5f0be90cf 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 fcdf9b09fc3d..a1e213319b78 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 6eaa497e86d5..062011133119 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -782,6 +782,7 @@ class TypeInt : public TypeInteger { 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 @@ class TypeInt : public TypeInteger { 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 @@ class TypeLong : public TypeInteger { 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 @@ class TypeLong : public TypeInteger { 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 f5162c4bb2f1..96b717fe56c6 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 5c6010acdf19..badfb8e9b82a 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 da3736b47118..f33c56a9b841 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/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 1b645c4cadaf..d5147728a40b 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -544,25 +544,6 @@ static SpecialFlag const special_jvm_flags[] = { { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(27), JDK_Version::undefined() }, #endif - { "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "MaxRAM", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "NewSizeThreadIncrease", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "NeverActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "AlwaysActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "UseXMMForArrayCopy", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "UseNewLongLShift", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "AggressiveHeap", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - - {"ShenandoahAccelerationSamplePeriod", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahRateAccelerationSampleSize", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahMomentaryAllocationRateSpikeSampleSize", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveSampleFrequencyHz", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveSampleSizeSeconds", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveInitialSpikeThreshold",JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveDecayFactor", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index a1c33f4fda00..b983b4648d4a 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1237,9 +1237,6 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { #ifndef PRODUCT -// Returns true iff the address p is readable and *(intptr_t*)p != errvalue -extern "C" bool dbg_is_safe(const void* p, intptr_t errvalue); - class FrameValuesOopClosure: public OopClosure, public DerivedOopClosure { private: GrowableArray* _oops; @@ -1269,17 +1266,13 @@ class FrameValuesOopClosure: public OopClosure, public DerivedOopClosure { _derived->push(derived_loc); } - bool is_good(oop* p) { - return *p == nullptr || (dbg_is_safe(*p, -1) && dbg_is_safe((*p)->klass_without_asserts(), -1) && oopDesc::is_oop_or_null(*p)); - } void describe(FrameValues& values, int frame_no) { for (int i = 0; i < _oops->length(); i++) { oop* p = _oops->at(i); - values.describe(frame_no, (intptr_t*)p, err_msg("oop%s for #%d", is_good(p) ? "" : " (BAD)", frame_no)); + values.describe(frame_no, (intptr_t*)p, err_msg("oop for #%d", frame_no)); } for (int i = 0; i < _narrow_oops->length(); i++) { narrowOop* p = _narrow_oops->at(i); - // we can't check for bad compressed oops, as decoding them might crash values.describe(frame_no, (intptr_t*)p, err_msg("narrow oop for #%d", frame_no)); } assert(_base->length() == _derived->length(), "should be the same"); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 47ef10167df9..04087e9de064 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -229,9 +229,13 @@ const int ObjectAlignmentInBytes = 8; \ product(bool, UsePoly1305Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for sun.security.util.math.intpoly") \ - product(bool, UseIntPolyIntrinsics, false, DIAGNOSTIC, \ + \ + product(bool, UseIntPolyIntrinsics, false, DIAGNOSTIC, \ "Use intrinsics for sun.security.util.math.intpoly.MontgomeryIntegerPolynomialP256") \ \ + product(bool, UseIntPoly25519Intrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for sun.security.util.math.intpoly.IntegerPolynomial25519") \ + \ product(size_t, LargePageSizeInBytes, 0, \ "Maximum large page size used (0 will use the default large " \ "page size for the environment as the maximum) " \ diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index bef6a0c27f03..5c3567eb0c00 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -801,6 +801,12 @@ intpoly_montgomeryMult_P256, intpoly_montgomeryMult_P256) \ do_stub(compiler, intpoly_assign) \ do_entry(compiler, intpoly_assign, intpoly_assign, intpoly_assign) \ + do_stub(compiler, intpoly_mult_25519) \ + do_entry(compiler, intpoly_mult_25519, \ + intpoly_mult_25519, intpoly_mult_25519) \ + do_stub(compiler, intpoly_square_25519) \ + do_entry(compiler, intpoly_square_25519, \ + intpoly_square_25519, intpoly_square_25519) \ do_stub(compiler, md5_implCompress) \ do_entry(compiler, md5_implCompress, md5_implCompress, \ md5_implCompress) \ diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index 76c45f4d438d..c8e552dc180c 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -674,17 +674,20 @@ class CompilerDirectivesClearDCmd : public DCmd { // VM.systemdictionary -verbose: for dumping the system dictionary table // class VM_DumpHashtable : public VM_Operation { +public: + enum DumpKind { + DumpSymbols, + DumpStrings, + DumpSysDict + }; + private: outputStream* _out; - int _which; + DumpKind _which; bool _verbose; + public: - enum { - DumpSymbols = 1 << 0, - DumpStrings = 1 << 1, - DumpSysDict = 1 << 2 // not implemented yet - }; - VM_DumpHashtable(outputStream* out, int which, bool verbose) { + VM_DumpHashtable(outputStream* out, DumpKind which, bool verbose) { _out = out; _which = which; _verbose = verbose; diff --git a/src/hotspot/share/services/memoryPool.cpp b/src/hotspot/share/services/memoryPool.cpp index 41362181c6b6..8361913862c3 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 a55c593ebed8..f0a4ba216590 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/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index d23178473076..dfba84ca5197 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -534,11 +534,6 @@ class ConcurrentHashTable : public CHeapObj { template void bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f); - // Gets statistics if available, if not return old one. Item sizes are calculated with - // VALUE_SIZE_FUNC. - template - TableStatistics statistics_get(Thread* thread, VALUE_SIZE_FUNC& vs_f, TableStatistics old); - // Moves all nodes from this table to to_cht with new hash code. // Must be done at a safepoint. void rehash_nodes_to(Thread* thread, ConcurrentHashTable* to_cht); diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index d5f6dee336b5..312d118a6479 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -1266,22 +1266,6 @@ inline TableStatistics ConcurrentHashTable:: } } -template -template -inline TableStatistics ConcurrentHashTable:: - statistics_get(Thread* thread, VALUE_SIZE_FUNC& vs_f, TableStatistics old) -{ - if (!try_resize_lock(thread)) { - return old; - } - InternalTable* table = get_table(); - NumberSeq summary; - size_t literal_bytes = 0; - - internal_statistics_range(thread, 0, table->_size, vs_f, summary, literal_bytes); - return internal_statistics_epilog(thread, summary, literal_bytes); -} - template inline void ConcurrentHashTable:: rehash_nodes_to(Thread* thread, ConcurrentHashTable* to_cht) diff --git a/src/java.base/share/classes/java/security/BinaryEncodable.java b/src/java.base/share/classes/java/security/BinaryEncodable.java index bd5d05ee4ecb..a1713c413ba1 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.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. + * + *

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. * - *

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 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 @@ @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 f5a6a70d0f59..8ebc83f93d10 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 @@ * 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 @@ *
* *

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 @@ * 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 @@ * @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 3f320bbcc9be..c610ace64d63 100644 --- a/src/java.base/share/classes/java/text/ListFormat.java +++ b/src/java.base/share/classes/java/text/ListFormat.java @@ -84,9 +84,9 @@ * Note: these examples are from CLDR, there could be different results from other locale providers. *

* Alternatively, Locale, Type, and/or Style independent instances - * can be created with {@link #getInstance(String[])}. The String array to the - * method specifies the delimiting patterns for the start/middle/end portion of - * the formatted string, as well as optional specialized patterns for two or three + * can be created with {@link #getInstance(String[])}. The String array passed to the + * method specifies the delimiting patterns for the {@code start}/{@code middle}/{@code end} + * portion of the formatted string, as well as optional specialized patterns for two or three * elements. Refer to the method description for more detail. *

* On parsing, if some ambiguity is found in the input string, such as delimiting @@ -121,7 +121,8 @@ public final class ListFormat extends Format { /** * The array of five pattern Strings. Each element corresponds to the Unicode LDML's - * `listPatternsPart` type, i.e, start/middle/end/two/three. + * {@code listPatternPart} type, i.e, + * {@code start}/{@code middle}/{@code end}/{@code two}/{@code three}. * @serial */ private final String[] patterns; @@ -153,6 +154,7 @@ private void init() { var pattern = patterns[START]; var placeholderPositions = findPlaceholders(pattern); if (placeholderPositions != null && + placeholderPositions[2] == -1 && placeholderPositions[1] + PLACEHOLDER_LENGTH == pattern.length()) { startBefore = pattern.substring(0, placeholderPositions[0]); startBetween = pattern.substring(placeholderPositions[0] + PLACEHOLDER_LENGTH, @@ -164,6 +166,7 @@ private void init() { pattern = patterns[MIDDLE]; placeholderPositions = findPlaceholders(pattern); if (placeholderPositions != null && + placeholderPositions[2] == -1 && placeholderPositions[0] == 0 && placeholderPositions[1] + PLACEHOLDER_LENGTH == pattern.length()) { middleBetween = pattern.substring(placeholderPositions[0] + PLACEHOLDER_LENGTH, @@ -174,7 +177,9 @@ private void init() { pattern = patterns[END]; placeholderPositions = findPlaceholders(pattern); - if (placeholderPositions != null && placeholderPositions[0] == 0) { + if (placeholderPositions != null && + placeholderPositions[2] == -1 && + placeholderPositions[0] == 0) { endBetween = pattern.substring(placeholderPositions[0] + PLACEHOLDER_LENGTH, placeholderPositions[1]); endAfter = pattern.substring(placeholderPositions[1] + PLACEHOLDER_LENGTH); @@ -185,7 +190,8 @@ private void init() { // Validate two/three patterns, if given. Otherwise, generate them pattern = patterns[TWO]; if (!pattern.isEmpty()) { - if (findPlaceholders(pattern) == null) { + placeholderPositions = findPlaceholders(pattern); + if (placeholderPositions == null || placeholderPositions[2] >= 0) { throw new IllegalArgumentException("pattern for two is incorrect: " + pattern); } } else { @@ -245,36 +251,43 @@ public static ListFormat getInstance(Locale locale, Type type, Style style) { * instead of letting the runtime provide appropriate patterns for the {@code Locale}, * {@code Type}, or {@code Style}. *

- * The patterns array should contain five String patterns, each corresponding to the Unicode LDML's - * {@code listPatternPart}, i.e., "start", "middle", "end", two element, and three element patterns - * in this order. Each pattern contains "{0}" and "{1}" (and "{2}" for the three element pattern) - * placeholders that are substituted with the passed input strings on formatting. - * If the length of the patterns array is not 5, an {@code IllegalArgumentException} - * is thrown. + * The patterns array should contain five String patterns, each corresponding + * to the Unicode LDML's {@code listPatternPart}, i.e., {@code start}, + * {@code middle}, {@code end}, {@code two} element, and {@code three} + * element patterns in this order. Each pattern contains "{0}" and "{1}" + * (and "{2}" for the {@code three} element pattern) placeholders that are + * substituted with the passed input strings on formatting. If the length of + * the patterns array is not 5, an {@code IllegalArgumentException} is thrown. *

* Each pattern string is first parsed as follows. Literals in parentheses, such as * "start_before", are optional: - *

+     * {@snippet :
      * start := (start_before){0}start_between{1}
      * middle := {0}middle_between{1}
      * end := {0}end_between{1}(end_after)
      * two := (two_before){0}two_between{1}(two_after)
      * three := (three_before){0}three_between1{1}three_between2{2}(three_after)
-     * 
- * If two or three pattern string is empty, it falls back to - * {@code "(start_before){0}end_between{1}(end_after)"}, - * {@code "(start_before){0}start_between{1}end_between{2}(end_after)"} respectively. - * If parsing of any pattern string for start, middle, end, two, or three fails, + * } + * If the {@code two} or {@code three} pattern string is empty, it falls back to + * {@snippet : + * (start_before){0}end_between{1}(end_after) + * (start_before){0}start_between{1}end_between{2}(end_after) + * } + * respectively. + * If parsing of any pattern string for {@code start}, {@code middle}, + * {@code end}, {@code two}, or {@code three} fails, including duplicate + * placeholders, "{2}" in patterns other than the {@code three} element + * pattern, or any use of "{" or "}" other than "{0}", "{1}", or "{2}", * it throws an {@code IllegalArgumentException}. *

* On formatting, the input string list with {@code n} elements substitutes above * placeholders based on the number of elements: - *

+     * {@snippet :
      * n = 1: {0}
      * n = 2: parsed pattern for "two"
      * n = 3: parsed pattern for "three"
      * n > 3: (start_before){0}start_between{1}middle_between{2} ... middle_between{m}end_between{n}(end_after)
-     * 
+ * } * As an example, the following table shows a pattern array which is equivalent to * {@code STANDARD} type, {@code FULL} style in US English: * @@ -485,15 +498,18 @@ public Object parseObject(String source, ParsePosition parsePos) { 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); } } @@ -571,9 +587,9 @@ private MessageFormat generateMessageFormat(Object[] input) { 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); }; } @@ -664,15 +680,37 @@ public enum Style { /** * {@return the positions of the "{0}", "{1}", and "{2}" placeholders in the * given pattern string, or null if the pattern is invalid} + * Only "{0}", "{1}", or "{2}" placeholders are allowed. Any other use of + * curly braces is not allowed. * * The returned array contains -1 for "{2}" if that placeholder is absent. * * @param pattern pattern string to parse */ private static int[] findPlaceholders(String pattern) { - var positions = new int[3]; - for (int i = 0; i < positions.length; i++) { - positions[i] = pattern.indexOf("{" + i + "}"); + var positions = new int[] {-1, -1, -1}; + + for (int i = 0; i < pattern.length(); i++) { + var ch = pattern.charAt(i); + if (ch == '{') { + if (i + PLACEHOLDER_LENGTH > pattern.length() || + pattern.charAt(i + 1) < '0' || + pattern.charAt(i + 1) > '2' || + pattern.charAt(i + 2) != '}') { + return null; + } + + // Check for duplicate placeholders + var index = pattern.charAt(i + 1) - '0'; + if (positions[index] != -1) { + return null; + } + + positions[index] = i; + i += PLACEHOLDER_LENGTH - 1; + } else if (ch == '}') { + return null; + } } // Check the existence and order of the placeholders @@ -707,4 +745,18 @@ private static int[] findPattern(String source, int pos, String prefix, String s 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/java/util/concurrent/ForkJoinTask.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index 137cac45ed06..f39d92aeeb40 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -418,19 +418,15 @@ else if (((a = aux) == null || a.ex == null) && for (;;) { if ((s = status) < 0) break; - else if (interrupts < 0) { - s = ABNORMAL; // interrupted and not done - break; - } else if (Thread.interrupted()) { - if (!ForkJoinPool.poolIsStopping(pool)) - interrupts = interruptible ? -1 : 1; - else { - interrupts = 1; // re-assert if cleared + if (ForkJoinPool.poolIsStopping(pool)) { try { cancel(true); - } catch (Throwable ignore) { - } + } catch (Throwable ignore) { } + } + if ((interrupts = interruptible ? -1 : 1) < 0) { + s = ABNORMAL; + break; } } else if (deadline != 0L) { 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 23a787971c09..07da636e7813 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 000000000000..72d0008a5058 --- /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 af0b8909d303..45882a79fd70 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.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 @@ byte[] write() throws Exception { } 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/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java index c8f23da417e9..b7b1ddae0e06 100644 --- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java @@ -26,6 +26,7 @@ package sun.security.util.math.intpoly; import java.math.BigInteger; +import jdk.internal.vm.annotation.IntrinsicCandidate; public final class IntegerPolynomial25519 extends IntegerPolynomial { private static final int BITS_PER_LIMB = 51; @@ -235,6 +236,7 @@ protected void finalCarryReduceLast(long[] limbs) { * @param b [in] the limb operand to multiply. * @param r [out] the product of the limbs operands that is fully reduced. */ + @IntrinsicCandidate protected void mult(long[] a, long[] b, long[] r) { long aa0 = a[0]; long aa1 = a[1]; @@ -414,6 +416,7 @@ protected void mult(long[] a, long[] b, long[] r) { * @param a [in] the limb operand to square. * @param r [out] the resulting square of the limb which is fully reduced. */ + @IntrinsicCandidate protected void square(long[] a, long[] r) { long aa0 = a[0]; long aa1 = a[1]; diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 878e4574e206..529f6d123e1d 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -3001,14 +3001,6 @@ they're used. : Enables the use of Java Flight Recorder (JFR) during the runtime of the application. Since JDK 8u40 this option has not been required to use JFR. -[`-XX:+ParallelRefProcEnabled`]{#-XX__ParallelRefProcEnabled} -: Enables parallel reference processing. By default, collectors employing multiple - threads perform parallel reference processing if the number of parallel threads - to use is larger than one. - The option is available only when the throughput or G1 garbage collector is used - (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple - threads always perform reference processing in parallel. - ## Obsolete Java Options These `java` options are still accepted but ignored, and a warning is issued @@ -3021,6 +3013,18 @@ when they're used. 396](https://openjdk.org/jeps/396) and made obsolete in JDK 17 by [JEP 403](https://openjdk.org/jeps/403). +## Removed Java Options + +These `java` options have been removed in JDK @@VERSION_SPECIFICATION@@ and using them results in an error of: + +> `Unrecognized VM option` *option-name* + +[`-XX:+AggressiveHeap`]{#-XX__AggressiveHeap} +: Enabled Java heap optimization. This set various parameters to be + optimal for long-running jobs with intensive memory allocation, based on + the configuration of the computer (RAM and CPU). By default, the option + was disabled and the heap sizes configured less aggressively. + [`-XX:+NeverActAsServerClassMachine`]{#-XX__NeverActAsServerClassMachine} : Enabled the "Client VM emulation" mode, which used only the C1 JIT compiler, a 32Mb CodeCache, and the Serial GC. The maximum amount of memory that the @@ -3041,18 +3045,18 @@ when they're used. -XX:{+|-}UseJVMCICompiler ``` -[`-XX:+AggressiveHeap`]{#-XX__AggressiveHeap} -: Enabled Java heap optimization. This set various parameters to be - optimal for long-running jobs with intensive memory allocation, based on - the configuration of the computer (RAM and CPU). By default, the option - was disabled and the heap sizes configured less aggressively. - -## Removed Java Options - -No documented java options have been removed in JDK @@VERSION_SPECIFICATION@@. +[`-XX:+ParallelRefProcEnabled`]{#-XX__ParallelRefProcEnabled} +: Enables parallel reference processing. By default, collectors employing multiple + threads perform parallel reference processing if the number of parallel threads + to use is larger than one. + The option is available only when the throughput or G1 garbage collector is used + (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple + threads always perform reference processing in parallel. For the lists and descriptions of options removed in previous releases see the *Removed Java Options* section in: +- [The `java` Command, Release 27](https://docs.oracle.com/en/java/javase/27/docs/specs/man/java.html) + - [The `java` Command, Release 26](https://docs.oracle.com/en/java/javase/26/docs/specs/man/java.html) - [The `java` Command, Release 25](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html) diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c index 2f163cf27f1f..bc2ed500d604 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 4c284bf29bab..6bec617b5ae7 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 @@ *

* 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/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java index 6121a0c16735..c4573317785d 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.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 @@ -351,4 +351,9 @@ SettingsFrame getClientSettings(boolean defaultServerPush) { public boolean stopping() { return stopping; } + + // getConnections() is used only by tests. + Map getConnections() { + return connections; + } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index 94b8505da47b..11022ca5c961 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.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 @@ -52,7 +52,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import java.util.function.Supplier; @@ -1610,16 +1609,37 @@ private List encodeHeaders(OutgoingHeaders> frame) { return frames; } - // Dedicated cache for headers encoding ByteBuffer. + // Dedicated reusable ByteBuffer for headers encoding. // There can be no concurrent access to this buffer as all access to this buffer // and its content happen within a single critical code block section protected - // by the sendLock. / (see sendFrame()) - // private final ByteBufferPool headerEncodingPool = new ByteBufferPool(); + // by the sendlock (see sendFrame()). + private ByteBuffer cachedHeaderBuffer; + + // getCachedHeaderBuffer() is used only by tests and it should not be + // called in source code without also holding `sendlock`. + ByteBuffer getCachedHeaderBuffer() { + return cachedHeaderBuffer; + } private ByteBuffer getHeaderBuffer(int size) { - ByteBuffer buf = ByteBuffer.allocate(size); - buf.limit(size); - return buf; + assert sendlock.isHeldByCurrentThread() : "current thread is not holding sendlock"; + + if (cachedHeaderBuffer == null || cachedHeaderBuffer.capacity() < size) { + cachedHeaderBuffer = ByteBuffer.allocate(size); + return cachedHeaderBuffer; + } + + cachedHeaderBuffer.clear(); + cachedHeaderBuffer.limit(size); + return cachedHeaderBuffer; + } + + private static ByteBuffer copyBuffer(ByteBuffer buffer) { + buffer.flip(); + ByteBuffer copy = ByteBuffer.allocate(buffer.remaining()); + copy.put(buffer); + copy.flip(); + return copy; } /* @@ -1634,8 +1654,8 @@ private ByteBuffer getHeaderBuffer(int size) { * encoding in HTTP/2... */ private List encodeHeadersImpl(int bufferSize, HttpHeaders... headers) { - ByteBuffer buffer = getHeaderBuffer(bufferSize); List buffers = new ArrayList<>(); + ByteBuffer buffer = getHeaderBuffer(bufferSize); for (HttpHeaders header : headers) { for (Map.Entry> e : header.map().entrySet()) { String lKey = e.getKey().toLowerCase(Locale.US); @@ -1644,16 +1664,17 @@ private List encodeHeadersImpl(int bufferSize, HttpHeaders... header hpackOut.header(lKey, value); while (!hpackOut.encode(buffer)) { if (!buffer.hasRemaining()) { - buffer.flip(); - buffers.add(buffer); - buffer = getHeaderBuffer(bufferSize); + ByteBuffer copy = copyBuffer(buffer); + buffers.add(copy); + buffer.clear(); + buffer.limit(bufferSize); } } } } } - buffer.flip(); - buffers.add(buffer); + ByteBuffer copy = copyBuffer(buffer); + buffers.add(copy); return buffers; } @@ -1710,7 +1731,7 @@ private Stream registerNewStream(OutgoingHeaders> oh) { } } - private final Lock sendlock = new ReentrantLock(); + private final ReentrantLock sendlock = new ReentrantLock(); void sendFrame(Http2Frame frame) { try { diff --git a/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java b/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java index 6446473d9d6a..362368cb2c5d 100644 --- a/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java +++ b/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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,8 +58,8 @@ * for example, ships with attach providers that use the package name "sun" * (for historical reasons). The * type typically corresponds to the attach mechanism. For example, an - * implementation that uses the Doors inter-process communication mechanism - * might use the type "doors". The purpose of the name and type is to + * implementation that uses the UNIX Domain Socket inter-process communication mechanism + * might use the type "socket". The purpose of the name and type is to * identify providers in environments where there are multiple providers * installed. * 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 9ac90c08c275..9fac32da26db 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 bea495f74fc9..8c22329a833f 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 3fd2be343467..fa338f279752 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 @@ 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 @@ Object iotaArray() { 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 @@ AbstractSpecies computeSpecies(LaneType laneType, 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 4efd0d24af9b..cf6602573a8f 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 @@ @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 @@ public DoubleVector reinterpretAsDoubles() { return (DoubleVector) asVectorRaw(LaneType.DOUBLE); } + /** + * {@inheritDoc} + */ + @Override + @ForceInline + public Float16Vector reinterpretAsFloat16s() { + return (Float16Vector) asVectorRaw(LaneType.FLOAT16); + } + /** * {@inheritDoc} */ @@ -682,6 +691,8 @@ AbstractVector defaultReinterpret(AbstractSpecies rsp) { 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 @@ AbstractVector defaultCast(AbstractSpecies dsp) { } 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 @@ AbstractVector defaultCast(AbstractSpecies dsp) { } 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 000000000000..cf7eae5dd6a4 --- /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 000000000000..65e2a2e1ba02 --- /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 000000000000..0ec038c5077f --- /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 000000000000..9ec1eaad8ada --- /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 000000000000..973e52616186 --- /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 000000000000..3de14504f863 --- /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 c18bbce1f34c..692520178277 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 @@ RuntimeException badElementType(Class elementType, Object expected) { 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 @@ static LaneType ofLaneTypeOrdinal(int lo) { 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 a9184d1faa9e..ac381330e319 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 final ShortVector viewAsIntegralLanes() { /** * {@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 4e064e0af37a..1bffb8d22389 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 @@ * 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 VectorMask compare(VectorOperators.Comparison op, */ 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 cc5a7ccbdefd..7c6b6e690860 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 @@ * *

  • {@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 @@ * *
  • {@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 sealed interface Comparison extends Operator { */ 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 @@ static boolean opKind(Operator op, int bit) { 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 @@ static boolean opKind(Operator op, int bit) { 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 @@ static boolean opKind(Operator op, int bit) { 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 @@ static boolean opKind(Operator op, int bit) { 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 @@ static boolean opKind(Operator op, int bit) { 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 @@ static boolean opKind(Operator op, int bit) { 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 74d6ce45db0b..7c6fb3bcfb2b 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) -> Float16.negate(Float16.valueOf(a)).floatValue()); +#else[FP16] case VECTOR_OP_NEG: return (v0, m) -> - v0.uOp(m, (i, a) -> ($type$) -a); + 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 d66d22cab19e..f8ac090a7f7b 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 a8a7ea83625d..7735085a16b3 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.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java index 15f55d18cc0f..c1c4dd512d6c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -137,6 +137,26 @@ protected void addInheritedSummaryLink(TypeElement te, Element member, Content t .title(title))); } + /** + * Returns a label for the given element to be used the table of contents sidebar. + * + * @param executableElement method or constructor + * @return the link label + */ + protected Content getTOCLabel(ExecutableElement executableElement) { + var signature = utils.makeSignature(executableElement, typeElement, false, true); + var label = new ContentBuilder(Text.of(utils.getSimpleName(executableElement))); + // Insert line break opportunity before first parameter. + if (signature.length() > 2) { + label.add(Text.of(signature.substring(0, 1))) + .add(HtmlTree.WBR()) + .add(Text.of(signature.substring(1))); + } else { + label.add(signature); + } + return label; + } + /** * Adds the generic type parameters. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java index d8d01a4e6adc..48e269445aef 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java @@ -119,9 +119,7 @@ protected void buildConstructorDoc(Content target) { constructorContent.add(div); memberList.add(getMemberListItem(constructorContent)); writer.tableOfContents.addLink(htmlIds.forMember(currentConstructor).getFirst(), - Text.of(utils.getSimpleName(constructor) - + utils.makeSignature(currentConstructor, typeElement, false, true)), - TableOfContents.Level.SECOND); + getTOCLabel(currentConstructor), TableOfContents.Level.SECOND); } Content constructorDetails = getConstructorDetails(constructorDetailsHeader, memberList); target.add(constructorDetails); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java index 3bc5b7617b0e..5edfd9e174d8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java @@ -118,9 +118,7 @@ protected void buildMethodDoc(Content detailsList) { methodContent.add(div); memberList.add(writer.getMemberListItem(methodContent)); writer.tableOfContents.addLink(htmlIds.forMember(currentMethod).getFirst(), - Text.of(utils.getSimpleName(method) - + utils.makeSignature(currentMethod, typeElement, false, true)), - TableOfContents.Level.SECOND); + getTOCLabel(currentMethod), TableOfContents.Level.SECOND); } Content methodDetails = getMethodDetails(methodDetailsHeader, memberList); detailsList.add(methodDetails); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index fc0fa68f0294..12b441727c67 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -82,6 +82,8 @@ /* Search input colors */ --search-input-background-color: #ffffff; --search-input-text-color: #000000; + --search-border-light-color: #eaeaea; + --search-border-dark-color: #a6a6a6; --search-input-placeholder-color: #757575; --overlay-background: rgba(153, 169, 183, 0.3); /* Highlight color for active search tag target */ @@ -107,23 +109,23 @@ :root[data-theme="theme-dark"] { --body-text-color: #e8e8e8; --block-text-color: #e8e8e8; - --body-background-color: #1f2124; + --body-background-color: #202226; --section-background-color: var(--body-background-color); --detail-background-color: var(--body-background-color); --code-background-color: #303940; --mark-background-color: #313131; --detail-block-color: #31363c; - --navbar-background-color: #395A6F; + --navbar-background-color: #406074; --navbar-text-color: #ffffff; - --subnav-background-color: #3d454d; + --subnav-background-color: #434c54; --subnav-link-color: #d8dcdf; --member-heading-background-color: var(--subnav-background-color); --selected-background-color: #f8981d; --selected-text-color: #253441; --selected-link-color: #4a698a; --table-header-color: #38444d; - --even-row-color: #222528; - --odd-row-color: #2d3135; + --even-row-color: #282c2f; + --odd-row-color: #33383b; --title-color: #fff; --link-color: #94badb; --link-color-active: #e8a351; @@ -138,8 +140,10 @@ --border-color: #444444; --table-border-color: #717171; --tab-border-radius: 2px 2px 0 0; - --search-input-background-color: #303030; + --search-input-background-color: #202224; --search-input-text-color: #d0d0d0; + --search-border-light-color: #505050; + --search-border-dark-color: #000000; --search-input-placeholder-color: #979797; --overlay-background: rgba(0, 0, 0, 0.45); --search-tag-background-color: #c6c61e; @@ -192,7 +196,7 @@ body { width:100%; } main [id] { - scroll-margin-top: calc(var(--nav-height) + 6px); + scroll-margin-top: calc(var(--nav-height) + 14px); } div.main-grid { max-width: var(--max-content-width); @@ -246,6 +250,9 @@ h1, h2, h3, h4, h5, h6, div.member-signature, div.member-signature > span { ul { list-style-type:disc; } +main li { + margin-top: 4px; +} tt { font-family:var(--code-font-family); } @@ -486,12 +493,7 @@ body.class-declaration-page .details h3 { } body.class-declaration-page section.detail:target > h3, body.class-declaration-page section.detail > h3:target { - background-color: var(--navbar-background-color); - color: var(--navbar-text-color); -} -body.class-declaration-page section.detail:target > h3 > a.anchor-link > img, -body.class-declaration-page section.detail > h3:target > a.anchor-link > img { - filter: invert(100%) brightness(160%); + box-shadow: -4px 0 0 rgb(from var(--link-color) r g b / 0.7); } h1 > sup { font-size: small; @@ -522,6 +524,9 @@ section.class-description > div.horizontal-scroll > :is(dl, ol, ul, p, div, bloc section.class-description > div.horizontal-scroll > :last-child > :is(li, dd):last-child { margin-bottom:4px; } +dl.notes { + margin-top: 14.2px; +} dl.notes > dt { font-family: var(--body-font-family); font-size:0.856em; @@ -661,9 +666,12 @@ a.current-selection { } nav.toc a { display: block; - padding: 8px; + padding: 7px 8px; overflow: hidden; text-overflow: ellipsis; + text-wrap: balance; + text-indent: 0.5em hanging; + line-height: 1.35; } nav.toc ol.toc-list ol.toc-list a { padding-left: 24px; @@ -737,11 +745,13 @@ ul.tag-list li { display: inline; } ul.tag-list li:not(:last-child):after, -ul.tag-list-long li:not(:last-child):after -{ +ul.tag-list-long li:not(:last-child):after { content: ", "; white-space: pre-wrap; } +ul.tag-list-long > li { + margin-top: 1px; +} ul.preview-feature-list { list-style: none; margin:0; @@ -940,6 +950,9 @@ div.checkboxes > label > input { .col-first, .col-second, .col-constructor-name { overflow: auto; } +.col-constructor-name, .method-summary .col-second { + text-indent: 0.5em hanging; +} body:not(.class-declaration-page) .col-first a:link, .col-summary-item-name a:link { font-weight:bold; @@ -957,6 +970,12 @@ div.block { font-size:var(--block-font-size); font-family:var(--block-font-family); line-height:var(--block-line-height); + display: block; + margin:0 10px 5px 0; + color:var(--block-text-color); +} +section.detail div.block { + margin-bottom: 14.4px; } .module-signature, .package-signature, @@ -1006,11 +1025,6 @@ div.block { color:var(--source-linenumber-color, green); padding:0 30px 0 0; } -.block { - display:block; - margin:0 10px 5px 0; - color:var(--block-text-color); -} .deprecated-label, .description-from-type-label, .implementation-label, .member-name-link, .package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label, .restricted-label { @@ -1075,15 +1089,16 @@ input[type="text"] { background-image:var(--glass-svg); background-size:13px; background-repeat:no-repeat; - background-position:3px 4px; + background-position:3px 5px; background-color: var(--search-input-background-color); color: var(--search-input-text-color); - border-color: var(--border-color); + border-style:solid; + border-color: var(--search-border-dark-color) var(--search-border-light-color) var(--search-border-light-color) var(--search-border-dark-color); border-radius: 4px; padding-left:20px; padding-right: 18px; font-size: var(--nav-font-size); - height: 19px; + height: 20px; } input#page-search-input { width: calc(180px + 10vw); @@ -1585,8 +1600,7 @@ button.snippet-copy span { table.borderless, table.plain, table.striped { - margin-top: 10px; - margin-bottom: 10px; + margin: 14px 0; } table.borderless > caption, table.plain > caption, @@ -1780,6 +1794,9 @@ table.striped > tbody > tr > th { main { padding: 10px 12px; } + main [id] { + scroll-margin-top: calc(var(--nav-height) + 10px); + } body { -webkit-text-size-adjust: none; } diff --git a/src/jdk.management.agent/share/conf/jmxremote.password.template b/src/jdk.management.agent/share/conf/jmxremote.password.template index c98a0ad253a4..0b0607497def 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/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 26c8fb8cd72e..cc059a931994 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -1200,16 +1200,22 @@ TEST_VM(os, map_unmap_memory) { TEST_VM(os, map_memory_to_file_aligned) { const char* letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const size_t size = strlen(letters) + 1; + const size_t content_size = strlen(letters) + 1; + const size_t granularity = os::vm_allocation_granularity(); + const size_t alignments[] = { granularity, 2 * granularity, 4 * granularity, 16 * granularity, 1 * M }; int fd = os::open("map_memory_to_file.txt", O_RDWR | O_CREAT, 0666); EXPECT_TRUE(fd > 0); - EXPECT_TRUE(os::write(fd, letters, size)); - - char* result = os::map_memory_to_file_aligned(os::vm_allocation_granularity(), os::vm_allocation_granularity(), fd, mtTest); - ASSERT_NOT_NULL(result); - EXPECT_EQ(strcmp(letters, result), 0); - os::unmap_memory(result, os::vm_allocation_granularity()); + ASSERT_TRUE(os::write(fd, letters, content_size)); + + const size_t size = granularity; + for (size_t alignment : alignments) { + char* result = os::map_memory_to_file_aligned(size, alignment, fd, mtTest); + ASSERT_NOT_NULL(result) << "Mapping failed for alignment=" << alignment; + EXPECT_TRUE(is_aligned(result, alignment)) << "Failed to aligned to " << alignment; + EXPECT_EQ(strcmp(letters, result), 0) << "Text mismatch at alignment=" << alignment; + os::unmap_memory(result, size); + } ::close(fd); } @@ -1220,3 +1226,36 @@ TEST_VM(os, dll_load_null_error_buf) { void* lib = os::dll_load("NoSuchLib", nullptr, 0); ASSERT_NULL(lib); } + +TEST_VM(os, reserve_memory_aligned_basic) { + const size_t granularity = os::vm_allocation_granularity(); + const size_t alignments[] = { granularity, 2 * granularity, 4 * granularity, 16 * granularity }; + + for (size_t alignment : alignments) { + const size_t size = alignment; + char* result = os::reserve_memory_aligned(size, alignment, mtTest); + ASSERT_NE(result, (char*)nullptr) << "reserve_memory_aligned failed for alignment=" << alignment; + EXPECT_TRUE(is_aligned(result, alignment)) << "Result " << result << " not aligned to " << alignment; + + ASSERT_TRUE(os::commit_memory(result, size, false)); + memset(result, 0xCD, size); + EXPECT_EQ((unsigned char)result[0], 0xCD); + + os::release_memory(result, size); + } +} + +TEST_VM(os, reserve_memory_aligned_large) { + const size_t alignment = 1 * M; + const size_t size = alignment; + + char* result = os::reserve_memory_aligned(size, alignment, mtTest); + ASSERT_NE(result, (char*)nullptr); + EXPECT_TRUE(is_aligned(result, alignment)); + + ASSERT_TRUE(os::commit_memory(result, size, false)); + memset(result, 0xEF, size); + EXPECT_EQ((unsigned char)result[size - 1], 0xEF); + + os::release_memory(result, size); +} diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index f9a4d5ec2a97..c6b006186179 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -33,8 +33,6 @@ vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java 8265295 lin serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java 8303168 linux-all -serviceability/sa/ClhsdbInspect.java 8283578 windows-x64 - vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java 8308367 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_a/TestDescription.java 8308367 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_b/TestDescription.java 8308367 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 8329026e7a20..bf9c3de95121 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -105,7 +105,6 @@ runtime/os/TestTracePageSizes.java#compiler-options 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#G1 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 -runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x runtime/Thread/TestAlwaysPreTouchStacks.java 8383372 macosx-aarch64 @@ -141,6 +140,8 @@ serviceability/sa/ClhsdbThreadContext.java 8356704 windows-x64 serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 +serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java 8385679 generic-all + ############################################################################# # :hotspot_misc diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java index a40c9eab12f3..3dff01721438 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 static void main(String[] args) { } @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 void checkTestInt(RunInfo info) { } @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 void testChar() { 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/profiling/TestPrintMethodData.java b/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java index 9e14cd6ea4b1..7cc5cda88b6c 100644 --- a/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java +++ b/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java @@ -64,7 +64,7 @@ static class Launcher { private static final Generator GEN_LONG = Generators.G.longs(); private static final int SIZE = 1024; - static void main(String[] args) throws Exception { + public static void main(String[] args) throws Exception { long[] longs = new long[SIZE]; Generators.G.fill(GEN_LONG, longs); diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestCastIIToConvHF2FNoSp.java b/test/hotspot/jtreg/compiler/vectorapi/TestCastIIToConvHF2FNoSp.java new file mode 100644 index 000000000000..0c8aa58f5865 --- /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 000000000000..30d066d1b152 --- /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/compiler/vectorapi/VectorExpressionFuzzer.java b/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java index 12615d839ab6..cb5b95109f57 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java @@ -22,26 +22,17 @@ */ /* - * @test id=AVX2 - * @bug 8369699 + * @test + * @bug 8369699 8381618 * @key randomness * @summary Test the Template Library's expression generation for the Vector API. - * @requires os.family == "linux" & os.simpleArch == "x64" * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc * @library /test/lib / * @compile ../../compiler/lib/verify/Verify.java - * @run driver ${test.main.class} -XX:UseAVX=2 + * @run driver ${test.main.class} */ -// TODO: remove the x64 and linux restriction above. I added that for now so we are not flooded -// with failures in the CI. We should remove these restriction once more bugs are fixed. -// x64 linux is the easiest to debug on for me, that's why I picked it. -// In addition, I put a UseAVX=2 restriction below, to avoid AVX512 bugs for now. -// -// A trick to extend this to other platforms: create a new run block, so you have full -// freedom to restrict it as necessary for platform and vector features. -// // TODO: Some compilation bailouts are to be expected, for example, we've encountered this before: // COMPILE SKIPPED: out of virtual registers in LIR generator (retry at different tier) // Which manifested in: diff --git a/test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java b/test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java new file mode 100644 index 000000000000..f79f4992817f --- /dev/null +++ b/test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java @@ -0,0 +1,133 @@ +/* + * 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 gc.g1; + +/* + * @test TestUncommitDuringConcurrentBitmapClear + * @bug 8385369 + * @requires vm.gc.G1 + * @requires vm.debug + * @requires vm.flagless + * @requires vm.bits == 64 + * @requires os.maxMemory > 8g + * @summary Verify that G1 does not crash while uncommitting a region whose + * bitmap is currently being cleared. + * Options are geared towards uncommitting aggressively. Also use a large + * region size so that corresponding bitmaps get uncommitted always too. + * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xmx8g + * -Xms32m + * -XX:G1HeapRegionSize=16m + * -XX:+UseG1GC + * -XX:ConcGCThreads=1 + * -XX:GCTimeRatio=1 + * -XX:G1CPUUsageShrinkThreshold=1 + * -XX:G1ShrinkByPercentOfAvailable=100 + * -XX:G1UncommitInitialDelay=0 + * -Xlog:gc+marking,gc,gc+ergo+heap=debug + * gc.g1.TestUncommitDuringConcurrentBitmapClear + */ + +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import jdk.test.whitebox.WhiteBox; + +/* + * Repeatedly make the concurrent cycle stop after the cleanup pause, issuing + * young GCs during the Concurrent Cleanup for Next Mark phase. Humongous + * regions allocated and dropped before that should get eager-reclaimed and + * their memory uncommitted while bitmap clearing runs. + */ +public class TestUncommitDuringConcurrentBitmapClear { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static final int NumObjs = 400; // Number of humongous objects to allocate + // per attempt. Sized to fill a fair amount of + // the available memory. + private static final int LargeObjSize = 9 * 1024 * 1024; // Large enough to be a humongous object. + + private static Object[] objects; + + private static void test() throws Exception { + + // This task drops the humongous objects, making them eligible for + // uncommit, and starts the concurrent bitmap clearing. While it is + // running, the caller triggers GCs that may or may not trigger the issue. + FutureTask concurrentClearTask = new FutureTask<>(() -> { + objects = null; + WB.concurrentGCRunTo(WB.G1_BEFORE_CLEANUP_COMPLETED); + return null; + }); + + try { + System.out.println("taking control"); + WB.concurrentGCAcquireControl(); + + // Allocate a new set of humongous objects. Acquire control first to avoid + // unnecessary concurrent cycles due to that allocation. We do not need them. + objects = new Object[NumObjs]; + for (int i = 0; i < objects.length; i++) { + objects[i] = new byte[LargeObjSize]; + } + + WB.concurrentGCRunTo(WB.G1_AFTER_CLEANUP_STARTED); + + new Thread(concurrentClearTask).start(); + + int numYoungGCs = 0; + // Execute at least one young GC, even if the concurrent + // clear bitmap finishes very quickly. + do { + WB.youngGC(); + numYoungGCs++; + // Wait a bit. This should give the concurrent clear task a chance + // to finish execution. + Thread.sleep(1); + } while (!concurrentClearTask.isDone() && numYoungGCs < 200); + + concurrentClearTask.get(30, TimeUnit.SECONDS); // Propagates exceptions, if any. + } finally { + WB.concurrentGCRunToIdle(); + + System.out.println("Releasing control"); + WB.concurrentGCReleaseControl(); + } + } + + public static void main(String[] args) throws Exception { + if (!WB.supportsConcurrentGCBreakpoints()) { + throw new RuntimeException("G1 should support GC breakpoints"); + } + for (int i = 0; i < 20; i++) { + test(); + } + } +} diff --git a/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java b/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java index 9e3ae8de8328..f58a287a895e 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 static void main(String args[]) throws Throwable { 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 8b711304a99f..14832e833e1d 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 @@ private static void testGlobalLimitFatal() throws IOException { 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 @@ private static void testGlobalLimitOOM() throws IOException { 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 @@ private static void testCompilerLimitFatal() throws IOException { 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 @@ private static void testCompilerLimitOOM() throws IOException { 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 @@ private static void testMultiLimit() throws IOException { 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/exeinvoke.c b/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c index abef2ea050a7..4608627688cf 100644 --- a/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c +++ b/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c @@ -56,17 +56,13 @@ static jmp_buf context; static volatile int _last_si_code = -1; static volatile int _failures = 0; static volatile int _rec_count = 0; // Number of allocations to hit stack guard page -static volatile int _kp_rec_count = 0; // Kept record of rec_count, for retrying +static volatile int _previous_rec_count = 0; // Kept record of rec_count, for retrying static int _peek_value = 0; // Used for accessing memory to cause SIGSEGV -pid_t gettid() { - return (pid_t) syscall(SYS_gettid); -} - static void handler(int sig, siginfo_t *si, void *unused) { _last_si_code = si->si_code; printf("Got SIGSEGV(%d) at address: 0x%lx\n",si->si_code, (long) si->si_addr); - longjmp(context, 1); + siglongjmp(context, 1); } static char* altstack = NULL; @@ -159,8 +155,16 @@ void *run_java_overflow (void *p) { void do_overflow(){ volatile int *p = NULL; - if (_kp_rec_count == 0 || _rec_count < _kp_rec_count) { - for(;;) { + if (_previous_rec_count == 0) { + // We need to find the appropriate depth to probe into + for (;;) { + _rec_count++; + p = (int*)alloca(128); + _peek_value = p[0]; // Peek + } + } else { + while (_rec_count < _previous_rec_count) { + // This is our second round, we can do exactly 1 less allocation _rec_count++; p = (int*)alloca(128); _peek_value = p[0]; // Peek @@ -168,19 +172,19 @@ void do_overflow(){ } } -void *run_native_overflow(void *p) { +void *run_native_overflow(void *is_other_thread) { // Test that stack guard page is correctly set for initial and non initial thread // and correctly removed for the initial thread volatile int res; - printf("run_native_overflow %ld\n", (long) gettid()); + printf("run_native_overflow, %s", *(int *)is_other_thread ? "in other thread\n" : "in initial thread\n"); call_method_on_jvm("printAlive"); // Initialize statics used in do_overflow - _kp_rec_count = 0; + _previous_rec_count = 0; _rec_count = 0; set_signal_handler(); - if (! setjmp(context)) { + if (! sigsetjmp(context, 1)) { do_overflow(); } @@ -194,7 +198,7 @@ void *run_native_overflow(void *p) { exit(7); } - if (getpid() != gettid()) { + if (*(int *)is_other_thread == 1) { // For non-initial thread we don't unmap the region but call os::uncommit_memory and keep PROT_NONE // so if host has enough swap space we will get the same SEGV with code SEGV_ACCERR(2) trying // to access it as if the guard page is present. @@ -204,11 +208,11 @@ void *run_native_overflow(void *p) { } // Limit depth of recursion for second run. It can't exceed one for first run. - _kp_rec_count = _rec_count; + _previous_rec_count = _rec_count; _rec_count = 0; set_signal_handler(); - if (! setjmp(context)) { + if (!sigsetjmp(context, 1)) { do_overflow(); } @@ -314,8 +318,8 @@ int main (int argc, const char** argv) { if (strcmp(argv[1], "test_native_overflow_initial") == 0) { printf("\nTesting NATIVE_OVERFLOW\n"); printf("Testing stack guard page behaviour for initial thread\n"); - - run_native_overflow(NULL); + int is_other_thread = 0; + run_native_overflow(&is_other_thread); exit((_failures > 0) ? 1 : 0); } @@ -324,11 +328,11 @@ int main (int argc, const char** argv) { init_thread_or_die(&thr, &thread_attr); printf("\nTesting NATIVE_OVERFLOW\n"); printf("Testing stack guard page behaviour for other thread\n"); - - pthread_create(&thr, &thread_attr, run_native_overflow, NULL); + int is_other_thread = 1; + pthread_create(&thr, &thread_attr, run_native_overflow, &is_other_thread); pthread_join(thr, NULL); - - exit((_failures > 0) ? 1 : 0); + // Other-thread test cannot increase _failure count + exit(0); } fprintf(stderr, "Test ERROR. Unknown parameter %s\n", ((argc > 1) ? argv[1] : "none")); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaProxyClasslist.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaProxyClasslist.java index adafa0d9c698..db431b180eb7 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 static void main(String[] args) throws Exception { 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 d7ce22e3cf1c..796437c04745 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 static void main(String[] args) throws Exception { .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 ea69d2db3cde..be5175e6d6a8 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 static void main(String[] args) throws Exception { 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 4cc6ef81c455..864ce88cd118 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 static void main(String[] args) throws Exception { "-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 static void main(String[] args) throws Exception { "-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 static void main(String[] args) throws Exception { "-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 static void main(String[] args) throws Exception { "-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 f7e15f8fae06..694e653676e4 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 @@ static SimpleCDSAppTester test(String comment, SimpleCDSAppTester tester) throws 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 String[] appCommandLine(RunMode runMode) { @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 String[] appCommandLine(RunMode runMode) { @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 ea5acef8551e..eb7f1dbf11fc 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 static void doTest(String[] classlist, String loadeesJar, String inArchiv 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 b46b48efb629..28d8043cde06 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 @@ static void test() throws Exception { .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 7abfd11b914e..c6c30c164a10 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 @@ static void test() throws Exception { .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 9845fd9549b5..5ff65f854934 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 @@ static void test() throws Exception { "-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 a43888c81cd4..8f0012098925 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 static void doTest(String topArchiveName) throws Exception { "--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 a77c38c21b9a..8bb84424676a 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 static void testBootAppendClassWithAppCDS() throws Exception { "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 bd569732ed5d..9c2039e538be 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 static void main(String... args) throws Exception { 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 static void main(String... args) throws Exception { 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 6c44ad587e39..9985215f7737 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 static void run(String... extra_runtime_args) throws Exception { 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 static void run(String... extra_runtime_args) throws Exception { 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 26bccdf764e1..b55e6cfbd8b7 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 static void runTest() throws Throwable { "-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 0ae4ae231b98..69786e3b3689 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 @@ void testMutateStaticFinalWithXCheckJni(String methodName) throws Exception { 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 @@ void testMutateInstanceFinalWithLogging(String methodName) throws Exception { 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 34249e5fec8a..ab0768267236 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 static void main(String... args) throws Exception { "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 c62402c918bd..9e75d52496f1 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 static void main(String... args) throws Exception { "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 static void main(String... args) throws Exception { "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 c2c966cb0474..3bbec57b158a 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 @@ static void analyzeOutputOn(ProcessBuilder pb) throws Exception { 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 6e114ff6b1d3..c16102ff4488 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 @@ static void test() throws Exception { 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 226dac6f466d..1cf90c1088d8 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 @@ static void analyzeOutputOn(ProcessBuilder pb) throws Exception { 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 88ec76efd12a..a17155092438 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 @@ static void analyzeOutputOn(ProcessBuilder pb) throws Exception { 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 a6a0ee66accc..b2315f585c8a 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/logging/VtablesTest.java b/test/hotspot/jtreg/runtime/logging/VtablesTest.java index a07fe8951737..c87c274d31da 100644 --- a/test/hotspot/jtreg/runtime/logging/VtablesTest.java +++ b/test/hotspot/jtreg/runtime/logging/VtablesTest.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 @@ -55,7 +55,7 @@ public static void main(String[] args) throws Exception { output.shouldContain("NOT overriding with p2.D.nooverride()V"); output.shouldHaveExitValue(0); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:vtables=trace", "p1/C"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:vtables=trace", "p1.C"); output = new OutputAnalyzer(pb.start()); output.shouldContain("transitive overriding superclass "); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleTraceCL.java b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleTraceCL.java index 4750e95c828d..0c57b4f2076a 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 static void main(String[] args) throws Exception { 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 static void main(String[] args) throws Exception { "-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 163a665b687a..7fa80a5b40bf 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 static void main(String[] args) throws Exception { 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 static void main(String[] args) throws Exception { 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 3c5d79f09df5..9acaa1441086 100644 --- a/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java +++ b/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java @@ -69,8 +69,8 @@ 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" }; @@ -120,27 +120,27 @@ static void testOutput(boolean useLP, boolean useTHP, OutputAnalyzer out, HugePa } 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 e8645a91479b..467891bfe1ef 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 static void main(String[] args) throws Exception { 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 0010c5bdd78f..f4dcb4dc1b0c 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 @@ private static void checkAndVerify(OutputAnalyzer dcmdOut, LingeredApp app, File 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 @@ private static OutputAnalyzer attachJcmdHeapDump(File heapDumpFile, long lingere 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/java/lang/Thread/virtual/KlassInit.java b/test/jdk/java/lang/Thread/virtual/KlassInit.java index 4f11d667a2bd..067d4c5a7f44 100644 --- a/test/jdk/java/lang/Thread/virtual/KlassInit.java +++ b/test/jdk/java/lang/Thread/virtual/KlassInit.java @@ -79,7 +79,10 @@ import java.util.stream.Stream; import java.util.stream.Collectors; +import jdk.test.lib.thread.VThreadRunner; + import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.Arguments; @@ -96,6 +99,12 @@ class KlassInit { private static final CountDownLatch finishPutStatic = new CountDownLatch(1); private static final CountDownLatch finishFailedInit = new CountDownLatch(1); + @BeforeAll + static void setup() { + // need >=2 carriers for testing pinning + VThreadRunner.ensureParallelism(2); + } + /** * Test that threads blocked waiting for klass to be initialized * on invokestatic bytecode release the carrier. diff --git a/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java b/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java index 875ac5426ddf..ce57f654e938 100644 --- a/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java +++ b/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.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 @@ -26,6 +26,9 @@ import java.net.http.HttpClient; import java.util.Objects; import java.util.Set; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Map; public final class HttpClientImplAccess { @@ -64,4 +67,29 @@ public static Set getOpenedConnections(final HttpClient client) openedConnections.setAccessible(true); return (Set) openedConnections.get(clientImpl); } + + /** + * Returns all connections in the client's HTTP/2 pool. + */ + public static Collection getHttp2Connections(final HttpClient client) { + Objects.requireNonNull(client, "client"); + final HttpClientImpl clientImpl = impl(client); + if (clientImpl == null) { + throw new IllegalStateException("Unsupported HttpClient implementation"); + } + Http2ClientImpl client2 = clientImpl.client2(); + Map connections = client2.getConnections(); + return connections.values(); + } + + /** + * Returns the cached header encoding buffer for the given Http2Connection. + */ + public static ByteBuffer getCachedHeaderBuffer(final Object conn) { + // The argument to this method is of type Object and not + // Http2Connection because callers outside the module cannot reference + // the package-private Http2Connection class. + Objects.requireNonNull(conn, "conn"); + return ((Http2Connection) conn).getCachedHeaderBuffer(); + } } diff --git a/test/jdk/java/net/httpclient/http2/HeaderEncodingBufferReuseTest.java b/test/jdk/java/net/httpclient/http2/HeaderEncodingBufferReuseTest.java new file mode 100644 index 000000000000..26fb06ec47dc --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/HeaderEncodingBufferReuseTest.java @@ -0,0 +1,139 @@ +/* + * 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. + */ + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.ByteBuffer; +import java.util.Collection; +import javax.net.ssl.SSLContext; +import static java.net.http.HttpClient.Version.HTTP_2; + +import jdk.httpclient.test.lib.common.HttpServerAdapters; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestExchange; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler; +import jdk.internal.net.http.HttpClientImplAccess; +import jdk.test.lib.net.URIBuilder; +import jdk.test.lib.net.SimpleSSLContext; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/* + * @test + * @bug 8383248 + * @summary Verifies that Http2Connection.cachedHeaderBuffer is reused + * across multiple requests on the same connection. + * @library /test/lib /test/jdk/java/net/httpclient/lib + * /test/jdk/java/net/httpclient/access + * @build java.net.http/jdk.internal.net.http.HttpClientImplAccess + * jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.net.SimpleSSLContext + * @run junit/othervm + * ${test.main.class} + */ + +public class HeaderEncodingBufferReuseTest implements HttpServerAdapters { + + static String httpUri; + static SSLContext sslContext; + static HttpTestServer testServer; + + @BeforeAll + static void init() throws Exception { + sslContext = SimpleSSLContext.findSSLContext(); + testServer = HttpTestServer.create(HTTP_2, sslContext); + testServer.addHandler(new OkHandler(), "/test"); + testServer.start(); + httpUri = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(testServer.getAddress().getPort()) + .path("/test") + .build() + .toString(); + } + + @AfterAll + static void teardown() { + testServer.stop(); + } + + @Test + void test() throws Exception { + try (HttpClient client = HttpClient.newBuilder() + .proxy(HttpClient.Builder.NO_PROXY) + .version(HttpClient.Version.HTTP_2) + .sslContext(sslContext) + .build()) { + + // Send an initial request to allocate the header encoding buffer. + assertEquals(200, send(client, httpUri, 2).statusCode()); + + Collection connections = HttpClientImplAccess.getHttp2Connections(client); + assertEquals(1, connections.size()); + Object conn = connections.iterator().next(); + + ByteBuffer cached = HttpClientImplAccess.getCachedHeaderBuffer(conn); + assertNotNull(cached); + + // Send another request and verify the same buffer is reused. + assertEquals(200, send(client, httpUri, 2).statusCode()); + connections = HttpClientImplAccess.getHttp2Connections(client); + assertEquals(1, connections.size()); + assertSame(conn, connections.iterator().next()); + assertSame(cached, HttpClientImplAccess.getCachedHeaderBuffer(conn)); + + // Verify that the buffer is reused when headers span multiple frames. + assertEquals(200, send(client, httpUri, 300).statusCode()); + connections = HttpClientImplAccess.getHttp2Connections(client); + assertEquals(1, connections.size()); + assertSame(conn, connections.iterator().next()); + assertSame(cached, HttpClientImplAccess.getCachedHeaderBuffer(conn)); + } + } + + static HttpResponse send(HttpClient client, String uri, int headerCount) throws Exception { + HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(uri)) + .POST(BodyPublishers.ofString("test")); + for (int i = 0; i < headerCount; i++) { + builder.header("X-Header-" + i, "value-" + "x".repeat(50) + "-" + i); + } + return client.send(builder.build(), BodyHandlers.discarding()); + } + + static class OkHandler implements HttpTestHandler { + @Override + public void handle(HttpTestExchange exchange) throws IOException { + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().close(); + } + } +} diff --git a/test/jdk/java/text/Format/ListFormat/TestListFormat.java b/test/jdk/java/text/Format/ListFormat/TestListFormat.java index 1500a1b08180..e85e98b6cf66 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 + * @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 @@ private static Arguments[] getInstance_1Arg() { 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 '''") }; } @@ -210,6 +222,10 @@ private static Arguments[] parseObject_parsePos() { arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE2), arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE3), arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE4), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE1), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE2), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE3), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE4), }; } @@ -237,13 +253,37 @@ private static Arguments[] getLocale_localeDependent() { }; } - private static Arguments[] getInstance_1Arg_InvalidLongPattern() { + private static final String ZERO_REPEAT = "{0}".repeat(100_000); + private static Arguments[] getInstance_1Arg_InvalidPlaceholder() { return new Arguments[] { - arguments(0, "start pattern is incorrect:"), - arguments(1, "middle pattern is incorrect:"), - arguments(2, "end pattern is incorrect:"), - arguments(3, "pattern for two is incorrect:"), - arguments(4, "pattern for three is incorrect:"), + // Duplicate placeholders + arguments(0, "{0} {0} {1}", "start pattern is incorrect: {0} {0} {1}"), + arguments(0, "{0} {1} {1}", "start pattern is incorrect: {0} {1} {1}"), + arguments(0, "{0} {1} {2}", "start pattern is incorrect: {0} {1} {2}"), + arguments(1, "{0} {0} {1}", "middle pattern is incorrect: {0} {0} {1}"), + arguments(1, "{0} {1} {1}", "middle pattern is incorrect: {0} {1} {1}"), + arguments(1, "{0} {1} {2}", "middle pattern is incorrect: {0} {1} {2}"), + arguments(2, "{0} {0} {1}", "end pattern is incorrect: {0} {0} {1}"), + arguments(2, "{0} {1} {1}", "end pattern is incorrect: {0} {1} {1}"), + arguments(2, "{0} {1} {2}", "end pattern is incorrect: {0} {1} {2}"), + arguments(3, "{0} {0} {1}", "pattern for two is incorrect: {0} {0} {1}"), + arguments(3, "{0} {1} {1}", "pattern for two is incorrect: {0} {1} {1}"), + arguments(3, "{0} {1} {2}", "pattern for two is incorrect: {0} {1} {2}"), + arguments(4, "{0} {2} {1}", "pattern for three is incorrect: {0} {2} {1}"), + arguments(4, "{0} {0} {1} {2}", "pattern for three is incorrect: {0} {0} {1} {2}"), + arguments(4, "{0} {1} {1} {2}", "pattern for three is incorrect: {0} {1} {1} {2}"), + arguments(4, "{0} {1} {2} {2}", "pattern for three is incorrect: {0} {1} {2} {2}"), + arguments(4, ZERO_REPEAT + " {1} {2}", "pattern for three is incorrect: " + ZERO_REPEAT + " {1} {2}"), + + // invalid placeholders + arguments(0, "{0} {1} {", "start pattern is incorrect: {0} {1} {"), + arguments(0, "{0} {1} }", "start pattern is incorrect: {0} {1} }"), + arguments(3, "{0} {1} {3}", "pattern for two is incorrect: {0} {1} {3}"), + arguments(4, "{3} {0} {1}", "pattern for three is incorrect: {3} {0} {1}"), + arguments(4, "{333} {0} {1}", "pattern for three is incorrect: {333} {0} {1}"), + arguments(4, "{0} {1} {abc}", "pattern for three is incorrect: {0} {1} {abc}"), + arguments(4, "{0} {1} {2, number}", "pattern for three is incorrect: {0} {1} {2, number}"), + arguments(4, "{0} {1} {2} {3}", "pattern for three is incorrect: {0} {1} {2} {3}"), }; } @@ -264,7 +304,7 @@ void getInstance_1Arg_IAE(String[] invalidPatterns, String errorMsg) { @ParameterizedTest @MethodSource - void getInstance_1Arg_InvalidLongPattern(int index, String expected) { + void getInstance_1Arg_InvalidPlaceholder(int index, String invalidPattern, String expected) { var patterns = new String[]{ "{0}, {1}", "{0}, {1}", @@ -272,13 +312,12 @@ void getInstance_1Arg_InvalidLongPattern(int index, String expected) { "{0} and {1}", "{0} {1} {2}" }; - patterns[index] = "{0}".repeat(100_000); + patterns[index] = invalidPattern; - // Ensures validation of invalid long patterns completes without timing out var msg = assertThrows(IllegalArgumentException.class, () -> ListFormat.getInstance(patterns)) .getMessage(); - assertEquals(expected, msg.substring(0, Math.min(msg.length(), expected.length()))); + assertEquals(expected, msg); } @ParameterizedTest diff --git a/test/jdk/java/util/TimeZone/AIXTzMappingTest.java b/test/jdk/java/util/TimeZone/AIXTzMappingTest.java new file mode 100644 index 000000000000..6324bb8581a5 --- /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 5fd48efadcc3..9a332202ab3c 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/java/util/concurrent/tck/ForkJoinPoolTest.java b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java index de1caaab2d94..85d7921f2ed8 100644 --- a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java @@ -663,6 +663,23 @@ public void realRun() throws Exception { } } + public void testCallerInterruptedDuringSubmit() throws InterruptedException, ExecutionException { + final Thread submitter = Thread.currentThread(); + final ExecutorService p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + for (int i = 0; i < 512; ++i) { // Enough repetitions such that any race condition is bound to materialize + try { + p.submit(submitter::interrupt).get(); + // If we don't get an InterruptedException, then the current thread should be interrupted + assertTrue(Thread.interrupted()); + } catch (InterruptedException e) { + // If we do get an InterruptedException, then the current thread should not be interrupted + assertTrue(!Thread.interrupted()); + } + } + } + } + /** * get of submit(callable) throws ExecutionException if callable * throws exception diff --git a/test/jdk/javax/accessibility/awt/CheckboxTest.java b/test/jdk/javax/accessibility/awt/CheckboxTest.java new file mode 100644 index 000000000000..7c690c168483 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/CheckboxTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary Checkbox Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main CheckboxTest + */ + +import java.awt.AWTException; +import java.awt.Checkbox; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class CheckboxTest { + + private static Checkbox checkbox; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Checkbox Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Checkbox"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + CheckboxTest checkboxTest = new CheckboxTest(); + EventQueue.invokeAndWait(checkboxTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(checkboxTest::test); + } finally { + checkboxTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Checkbox Test"); + checkbox = new Checkbox("This is a checkbox", true); + + checkbox.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + checkbox.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(checkbox); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyCheckboxAccessibility( + checkbox, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new CheckboxStateTester( + checkbox, + checkbox.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + checkbox.setState(!checkbox.getState()); + + AccessibleTestUtils.verifyCheckboxAccessibility( + checkbox, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new CheckboxStateTester( + checkbox, + checkbox.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class CheckboxStateTester + extends AccessibleStateSetTester { + private final Checkbox checkbox; + private final AccessibleStateSet set; + + private CheckboxStateTester(Checkbox checkbox, AccessibleStateSet set) { + super(checkbox, set); + this.checkbox = checkbox; + this.set = set; + } + + @Override + public void testChecked() { + if (set.contains(AccessibleState.CHECKED)) { + if (!checkbox.getState()) { + throw new RuntimeException( + "AccessibleStateSet contains CHECKED but " + + "this component is not checked"); + } + } else { + if (checkbox.getState()) { + throw new RuntimeException( + "AccessibleStateSet does not contain CHECKED " + + "but this component is checked"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/FrameTest.java b/test/jdk/javax/accessibility/awt/FrameTest.java new file mode 100644 index 000000000000..4abe32465747 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/FrameTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary Frame Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main FrameTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class FrameTest { + + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Frame Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Frame"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + FrameTest frameTest = new FrameTest(); + EventQueue.invokeAndWait(frameTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(frameTest::test); + } finally { + frameTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Frame Test"); + + frame.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + frame.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyFrameAccessibility( + frame, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new FrameStateTester( + frame, + frame.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + frame.setResizable(false); + + AccessibleTestUtils.verifyFrameAccessibility( + frame, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new FrameStateTester( + frame, + frame.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class FrameStateTester + extends AccessibleStateSetTester { + private final Frame component; + private final AccessibleStateSet set; + + private FrameStateTester(Frame frame, AccessibleStateSet set) { + super(frame, set); + this.component = frame; + this.set = set; + } + + @Override + public void testResizable() { + if (set.contains(AccessibleState.RESIZABLE)) { + if (!component.isResizable()) { + throw new RuntimeException( + "AccessibleStateSet contains RESIZABLE but " + + "this component is not resizable"); + } + } else { + if (component.isResizable()) { + throw new RuntimeException( + "AccessibleStateSet does not contain RESIZABLE " + + "but this component is resizable"); + } + } + } + + @Override + public void testActive() { + if (set.contains(AccessibleState.ACTIVE)) { + if (component.getFocusOwner() == null) { + throw new RuntimeException( + "AccessibleStateSet contains ACTIVE but " + + "this component is not active"); + } + } else { + if (component.getFocusOwner() != null) { + throw new RuntimeException( + "AccessibleStateSet does not contain ACTIVE but " + + "this component is active"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/LabelTest.java b/test/jdk/javax/accessibility/awt/LabelTest.java new file mode 100644 index 000000000000..dd837793eb56 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/LabelTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary Label Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main LabelTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class LabelTest { + + private static Label label; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Label Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Label"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + LabelTest labelTest = new LabelTest(); + EventQueue.invokeAndWait(labelTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(labelTest::test); + } finally { + labelTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Label Test"); + label = new Label("This is a label"); + + label.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + label.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(label); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyLabelAccessibility( + label, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new AccessibleStateSetTester( + label, + label.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } +} diff --git a/test/jdk/javax/accessibility/awt/ListTest.java b/test/jdk/javax/accessibility/awt/ListTest.java new file mode 100644 index 000000000000..011d850a4cb1 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/ListTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary List Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main ListTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.List; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class ListTest { + + private static List list; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "List Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, List"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + ListTest listTest = new ListTest(); + EventQueue.invokeAndWait(listTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(listTest::test); + } finally { + listTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("List Test"); + list = new List(); + + list.add("Mercury"); + list.add("Venus"); + list.add("Earth"); + list.add("JavaSoft"); + list.add("Mars"); + list.add("Jupiter"); + list.add("Saturn"); + list.add("Uranus"); + list.add("Neptune"); + list.add("Pluto"); + + list.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + list.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(list); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyListAccessibility( + list, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new ListStateTester( + list, + list.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + list.setMultipleMode(!list.isMultipleMode()); + + AccessibleTestUtils.verifyListAccessibility( + list, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new ListStateTester( + list, + list.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class ListStateTester + extends AccessibleStateSetTester { + private final List list; + private final AccessibleStateSet set; + + private ListStateTester(List list, AccessibleStateSet set) { + super(list, set); + this.list = list; + this.set = set; + } + + @Override + public void testMultiSelectable() { + if (set.contains(AccessibleState.MULTISELECTABLE)) { + if (!list.isMultipleMode()) { + throw new RuntimeException( + "AccessibleStateSet contains MULTISELECTABLE " + + "but this component is not multiselectable"); + } + } else { + if (list.isMultipleMode()) { + throw new RuntimeException( + "AccessibleStateSet does not contain " + + "MULTISELECTABLE but this component is " + + "multiselectable"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/MenuBarTest.java b/test/jdk/javax/accessibility/awt/MenuBarTest.java new file mode 100644 index 000000000000..83445fde61bd --- /dev/null +++ b/test/jdk/javax/accessibility/awt/MenuBarTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary MenuBar Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main MenuBarTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MenuBarTest { + + private static MenuBar menuBar; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Menu Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, MenuBar"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MenuBarTest menuBarTest = new MenuBarTest(); + EventQueue.invokeAndWait(menuBarTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(menuBarTest::test); + } finally { + menuBarTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("MenuBar Test"); + menuBar = new MenuBar(); + + Menu menu = new Menu("Menu 1"); + menu.add(new MenuItem("One")); + menu.add(new MenuItem("Two")); + menuBar.add(menu); + + menuBar.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + menuBar.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setMenuBar(menuBar); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyMenuBarAccessibility( + menuBar, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/MenuItemTest.java b/test/jdk/javax/accessibility/awt/MenuItemTest.java new file mode 100644 index 000000000000..0cfe342e8430 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/MenuItemTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary MenuItem Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main MenuItemTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MenuItemTest { + + private static MenuItem menuItem; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "MenuItem Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, MenuItem"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MenuItemTest menuItemTest = new MenuItemTest(); + EventQueue.invokeAndWait(menuItemTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(menuItemTest::test); + } finally { + menuItemTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("MenuItem Test"); + + MenuBar menuBar = new MenuBar(); + Menu menu = new Menu("Menu"); + menuItem = new MenuItem("This here's a MenuItem"); + + menu.add(menuItem); + menuBar.add(menu); + + menuItem.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + menuItem.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setMenuBar(menuBar); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyMenuItemAccessibility( + menuItem, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/MenuTest.java b/test/jdk/javax/accessibility/awt/MenuTest.java new file mode 100644 index 000000000000..15c51ca42142 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/MenuTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary Menu Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main MenuTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MenuTest { + + private static Menu menu; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Menu Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Menu"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MenuTest menuTest = new MenuTest(); + EventQueue.invokeAndWait(menuTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(menuTest::test); + } finally { + menuTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Menu Test"); + + MenuBar menuBar = new MenuBar(); + menu = new Menu("File"); + menuBar.add(menu); + + menu.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + menu.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setMenuBar(menuBar); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyMenuAccessibility( + menu, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/PanelTest.java b/test/jdk/javax/accessibility/awt/PanelTest.java new file mode 100644 index 000000000000..abfacc7485bf --- /dev/null +++ b/test/jdk/javax/accessibility/awt/PanelTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary Panel Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main PanelTest + */ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class PanelTest { + + private static Panel panel; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Panel Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Panel"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + PanelTest panelTest = new PanelTest(); + EventQueue.invokeAndWait(panelTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(panelTest::test); + } finally { + panelTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Panel Test"); + panel = new Panel(); + + for (int i = 0; i < 5; i++) { + panel.add(new Button("Button #" + i)); + } + + panel.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + panel.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyPanelAccessibility( + panel, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new AccessibleStateSetTester( + panel, + panel.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } +} diff --git a/test/jdk/javax/accessibility/awt/PopupMenuTest.java b/test/jdk/javax/accessibility/awt/PopupMenuTest.java new file mode 100644 index 000000000000..8d329a923221 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/PopupMenuTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary PopupMenu Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main PopupMenuTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.PopupMenu; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class PopupMenuTest { + + private static PopupMenu popupMenu; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "PopupMenu Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, PopupMenu"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + PopupMenuTest popupMenuTest = new PopupMenuTest(); + EventQueue.invokeAndWait(popupMenuTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(popupMenuTest::test); + } finally { + popupMenuTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("PopupMenu Test"); + popupMenu = new PopupMenu("PopupMenu"); + + popupMenu.add("Sleepy"); + popupMenu.add("Happy"); + popupMenu.add("Grumpy"); + popupMenu.add("Dopey"); + + popupMenu.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + popupMenu.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(popupMenu); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyPopupMenuAccessibility( + popupMenu, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/ScrollPaneTest.java b/test/jdk/javax/accessibility/awt/ScrollPaneTest.java new file mode 100644 index 000000000000..7f706647482d --- /dev/null +++ b/test/jdk/javax/accessibility/awt/ScrollPaneTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary ScrollPane Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main ScrollPaneTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.lang.reflect.InvocationTargetException; + +public class ScrollPaneTest { + + private static ScrollPane scrollPane; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "ScrollPane Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, ScrollPane"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + ScrollPaneTest scrollPaneTest = new ScrollPaneTest(); + EventQueue.invokeAndWait(scrollPaneTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(scrollPaneTest::test); + } finally { + scrollPaneTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("ScrollPane Test"); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + + scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + scrollPane.setSize(frame.getSize().width, frame.getSize().height); + scrollPane.add(new Label("This is a label with quite a bit of text.")); + + scrollPane.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + scrollPane.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(scrollPane); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyScrollPaneAccessibility( + scrollPane, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new AccessibleStateSetTester( + scrollPane, + scrollPane.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } +} diff --git a/test/jdk/javax/accessibility/awt/TextAreaTest.java b/test/jdk/javax/accessibility/awt/TextAreaTest.java new file mode 100644 index 000000000000..388a22324f97 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/TextAreaTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary TextArea Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main TextAreaTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextArea; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class TextAreaTest { + + private static TextArea textArea; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "TextArea Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, TextArea"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + TextAreaTest textAreaTest = new TextAreaTest(); + EventQueue.invokeAndWait(textAreaTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(textAreaTest::test); + } finally { + textAreaTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("TextAreaTest"); + String TEXT_CONTENT = """ + 1. Test TextArea javax.accessibility methods + 2. Test TextArea javax.accessibility setAccessibleName + 3. Test TextArea javax.accessibility setAccessibleDescription + 4. Test TextArea javax.accessibility setAccessibleStateSet + """; + textArea = new TextArea(TEXT_CONTENT, 24, 80); + + textArea.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + textArea.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(textArea); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyTextAreaAccessibility( + textArea, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textArea, + textArea.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + textArea.setEditable(false); + + AccessibleTestUtils.verifyTextAreaAccessibility( + textArea, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textArea, + textArea.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class TextStateTester + extends AccessibleStateSetTester { + private final TextArea textArea; + private final AccessibleStateSet stateSet; + + private TextStateTester(TextArea textArea, + AccessibleStateSet stateSet) { + super(textArea, stateSet); + this.textArea = textArea; + this.stateSet = stateSet; + } + + @Override + public void testEditable() { + if (stateSet.contains(AccessibleState.EDITABLE)) { + if (!textArea.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet contains EDITABLE but " + + "this component is not editable"); + } + } else { + if (textArea.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet does not contain EDITABLE " + + "but this component is editable"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/TextFieldTest.java b/test/jdk/javax/accessibility/awt/TextFieldTest.java new file mode 100644 index 000000000000..96deaf3b7bc0 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/TextFieldTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary TextField Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main TextFieldTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextField; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class TextFieldTest { + + private static TextField textField; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "TextField Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, TextField"; + private static final String TEXT = + "I love Cheesy Poofs you love Cheesy Poofs if we didn't " + + "eat Cheesy Poofs we'd be lame!"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + TextFieldTest textFieldTest = new TextFieldTest(); + EventQueue.invokeAndWait(textFieldTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(textFieldTest::test); + } finally { + textFieldTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("TextField Test"); + textField = new TextField(TEXT, 80); + + textField.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + textField.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(textField); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyTextFieldAccessibility( + textField, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textField, + textField.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + textField.setEditable(false); + + AccessibleTestUtils.verifyTextFieldAccessibility( + textField, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textField, + textField.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class TextStateTester + extends AccessibleStateSetTester { + private final TextField textField; + private final AccessibleStateSet set; + + private TextStateTester(TextField textField, AccessibleStateSet set) { + super(textField, set); + this.textField = textField; + this.set = set; + } + + @Override + public void testEditable() { + if (set.contains(AccessibleState.EDITABLE)) { + if (!textField.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet contains EDITABLE but " + + "this component is not editable"); + } + } else { + if (textField.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet does not contain EDITABLE " + + "but this component is editable"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/WindowTest.java b/test/jdk/javax/accessibility/awt/WindowTest.java new file mode 100644 index 000000000000..dc70ce75d907 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/WindowTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1997, 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 headful + * @summary Window Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main WindowTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class WindowTest { + + private static Window window; + + private static final String ACCESSIBLE_NAME = "Window Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Window"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + WindowTest windowTest = new WindowTest(); + EventQueue.invokeAndWait(windowTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(windowTest::test); + } finally { + windowTest.dispose(); + } + } + + private void createGUI() { + window = new Window(new Frame("Frame")); + window.setSize(300, 300); + window.setLocationRelativeTo(null); + + window.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + window.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + window.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (window != null) { + window.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyWindowAccessibility( + window, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new WindowStateTester( + window, + window.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class WindowStateTester + extends AccessibleStateSetTester { + private final Window window; + private final AccessibleStateSet set; + + private WindowStateTester(Window window, AccessibleStateSet set) { + super(window, set); + this.window = window; + this.set = set; + } + + @Override + public void testActive() { + if (set.contains(AccessibleState.ACTIVE)) { + if (window.getFocusOwner() == null) { + throw new RuntimeException( + "AccessibleStateSet contains ACTIVE but " + + "this component is not active"); + } + } else { + if (window.getFocusOwner() != null) { + throw new RuntimeException( + "AccessibleStateSet does not contain ACTIVE " + + "but this component is active"); + } + } + } + } +} diff --git a/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleMenuComponentTester.java b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleMenuComponentTester.java new file mode 100644 index 000000000000..21b91aafbcdc --- /dev/null +++ b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleMenuComponentTester.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1997, 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. + */ + +import java.awt.Font; +import java.awt.MenuComponent; + +import javax.accessibility.AccessibleComponent; + +public class AccessibleMenuComponentTester { + + private final AccessibleComponent acomp; + private final MenuComponent comp; + + public AccessibleMenuComponentTester(MenuComponent menuComponent, + AccessibleComponent ac) { + if (menuComponent == null) { + throw new RuntimeException("MenuComponent should not be null"); + } + + if (ac == null) { + throw new RuntimeException("AccessibleComponent should not be null"); + } + + this.comp = menuComponent; + this.acomp = ac; + } + + // The only method supported by MenuComponents is getFont(). Everything + // else should return null. + public void test() { + testGetBackground(); + testGetBounds(); + testGetCursor(); + testGetFont(); + testGetForeground(); + testGetLocation(); + testGetLocationOnScreen(); + testGetSize(); + testIsEnabled(); + testIsFocusTraversable(); + testIsShowing(); + testIsVisible(); + } + + public void testGetBackground() { + } + + public void testGetBounds() { + } + + public void testGetCursor() { + } + + public void testGetFont() { + Font accessibleFont = acomp.getFont(); + Font componentFont = comp.getFont(); + + if (componentFont == null) { + if (accessibleFont != null) { + throw new RuntimeException( + "MenuComponent.getFont returned null but " + + "AccessibleComponent.getFont did not"); + } + } else if (!componentFont.equals(accessibleFont)) { + throw new RuntimeException( + "AccessibleComponent.getFont does not match " + + "MenuComponent.getFont"); + } + } + + public void testGetForeground() { + } + + public void testGetLocation() { + } + + public void testGetLocationOnScreen() { + } + + public void testGetSize() { + } + + public void testIsEnabled() { + } + + public void testIsFocusTraversable() { + } + + public void testIsShowing() { + } + + public void testIsVisible() { + } +} diff --git a/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java index 2410cff997a7..9de4a8d80893 100644 --- a/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java +++ b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java @@ -22,17 +22,33 @@ */ import java.awt.Button; +import java.awt.Checkbox; import java.awt.Choice; import java.awt.Component; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuComponent; +import java.awt.MenuItem; +import java.awt.Panel; +import java.awt.PopupMenu; import java.awt.Scrollbar; +import java.awt.ScrollPane; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.Window; import java.util.Locale; import java.util.Objects; +import javax.accessibility.Accessible; import javax.accessibility.AccessibleAction; import javax.accessibility.AccessibleComponent; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleText; import javax.accessibility.AccessibleValue; @@ -51,32 +67,22 @@ public static void verifyAccessibleContextCommon( boolean expectSelection, boolean expectText, boolean expectValue) { - Objects.requireNonNull(context, "AccessibleContext must not be null"); - assertExpectedString( - "getAccessibleName", - expectedName, - context.getAccessibleName() - ); + assertExpectedString("getAccessibleName", + expectedName, context.getAccessibleName()); + assertExpectedString("getAccessibleDescription", + expectedDescription, context.getAccessibleDescription()); - assertExpectedString( - "getAccessibleDescription", - expectedDescription, - context.getAccessibleDescription() - ); + AccessibleRole actualRole = context.getAccessibleRole(); + if (actualRole == null) { + throw new RuntimeException("getAccessibleRole returned null"); + } - if (expectedRole != null) { - AccessibleRole actualRole = context.getAccessibleRole(); - if (actualRole == null) { - throw new RuntimeException("getAccessibleRole returned null"); - } - if (!expectedRole.equals(actualRole)) { - throw new RuntimeException(String.format( - "getAccessibleRole returned [%s]; expected [%s]", - actualRole, expectedRole - )); - } + if (!expectedRole.equals(actualRole)) { + throw new RuntimeException( + "getAccessibleRole returned [" + actualRole + + "]; expected [" + expectedRole + "]"); } AccessibleStateSet stateSet = context.getAccessibleStateSet(); @@ -84,10 +90,14 @@ public static void verifyAccessibleContextCommon( throw new RuntimeException("getAccessibleStateSet returned null"); } - assertPresence("getAccessibleAction", expectAction, context.getAccessibleAction()); - assertPresence("getAccessibleSelection", expectSelection, context.getAccessibleSelection()); - assertPresence("getAccessibleText", expectText, context.getAccessibleText()); - assertPresence("getAccessibleValue", expectValue, context.getAccessibleValue()); + assertPresence("getAccessibleAction", + expectAction, context.getAccessibleAction()); + assertPresence("getAccessibleSelection", + expectSelection, context.getAccessibleSelection()); + assertPresence("getAccessibleText", + expectText, context.getAccessibleText()); + assertPresence("getAccessibleValue", + expectValue, context.getAccessibleValue()); } public static void verifyAWTComponentAccessibility( @@ -99,10 +109,13 @@ public static void verifyAWTComponentAccessibility( boolean expectSelection, boolean expectText, boolean expectValue) { - - Objects.requireNonNull(component, "Component under test must not be null"); + Objects.requireNonNull(component, "Component must not be null"); AccessibleContext context = component.getAccessibleContext(); + if (context == null) { + throw new RuntimeException("getAccessibleContext returned null"); + } + verifyAccessibleContextCommon( context, expectedName, @@ -111,12 +124,12 @@ public static void verifyAWTComponentAccessibility( expectAction, expectSelection, expectText, - expectValue - ); + expectValue); assertLocaleMatches(component, context); - AccessibleComponent accessibleComponent = context.getAccessibleComponent(); + AccessibleComponent accessibleComponent = + context.getAccessibleComponent(); if (accessibleComponent == null) { throw new RuntimeException("getAccessibleComponent returned null"); } @@ -124,11 +137,48 @@ public static void verifyAWTComponentAccessibility( new AccessibleComponentTester(component, accessibleComponent).test(); } + public static void verifyButtonAccessibility( + Button button, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(button, "Button must not be null"); + + verifyAWTComponentAccessibility( + button, + expectedName, + expectedDescription, + AccessibleRole.PUSH_BUTTON, + true, + false, + false, + true); + + AccessibleContext context = button.getAccessibleContext(); + verifyClickAction(context, "Button"); + verifyZeroAccessibleValue(context, "Button"); + } + + public static void verifyCheckboxAccessibility( + Checkbox checkbox, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(checkbox, "Checkbox must not be null"); + + verifyAWTComponentAccessibility( + checkbox, + expectedName, + expectedDescription, + AccessibleRole.CHECK_BOX, + true, + false, + false, + true); + } + public static void verifyChoiceAccessibility( Choice choice, String expectedName, String expectedDescription) { - Objects.requireNonNull(choice, "Choice must not be null"); verifyAWTComponentAccessibility( @@ -139,27 +189,85 @@ public static void verifyChoiceAccessibility( true, false, false, - false - ); + false); + } - AccessibleContext context = choice.getAccessibleContext(); + public static void verifyFrameAccessibility( + Frame frame, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(frame, "Frame must not be null"); - AccessibleAction action = context.getAccessibleAction(); - if (action == null) { - throw new RuntimeException("getAccessibleAction should not return null for Choice"); - } + verifyAWTComponentAccessibility( + frame, + expectedName, + expectedDescription, + AccessibleRole.FRAME, + false, + false, + false, + false); + } - AccessibleValue value = context.getAccessibleValue(); - if (value != null) { - throw new RuntimeException("getAccessibleValue should return null for Choice"); - } + public static void verifyLabelAccessibility( + Label label, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(label, "Label must not be null"); + + verifyAWTComponentAccessibility( + label, + expectedName, + expectedDescription, + AccessibleRole.LABEL, + false, + false, + false, + false); + } + + public static void verifyListAccessibility( + List list, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(list, "List must not be null"); + + verifyAWTComponentAccessibility( + list, + expectedName, + expectedDescription, + AccessibleRole.LIST, + false, + true, + false, + false); + + verifyListChildren(list); + } + + public static void verifyPanelAccessibility( + Panel panel, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(panel, "Panel must not be null"); + + verifyAWTComponentAccessibility( + panel, + expectedName, + expectedDescription, + AccessibleRole.PANEL, + false, + false, + false, + false); + + verifyContainerChildren(panel, "Panel"); } public static void verifyScrollbarAccessibility( Scrollbar scrollbar, String expectedName, String expectedDescription) { - Objects.requireNonNull(scrollbar, "Scrollbar must not be null"); verifyAWTComponentAccessibility( @@ -170,165 +278,449 @@ public static void verifyScrollbarAccessibility( false, false, false, - true - ); + true); - AccessibleValue value = scrollbar.getAccessibleContext().getAccessibleValue(); - if (value == null) { - throw new RuntimeException("getAccessibleValue should not return null for Scrollbar"); - } + AccessibleValue value = + scrollbar.getAccessibleContext().getAccessibleValue(); assertIntValueEquals( "getCurrentAccessibleValue", scrollbar.getValue(), - value.getCurrentAccessibleValue() - ); + value.getCurrentAccessibleValue()); assertIntValueEquals( "getMinimumAccessibleValue", scrollbar.getMinimum(), - value.getMinimumAccessibleValue() - ); + value.getMinimumAccessibleValue()); assertIntValueEquals( "getMaximumAccessibleValue", scrollbar.getMaximum(), - value.getMaximumAccessibleValue() - ); + value.getMaximumAccessibleValue()); if (!value.setCurrentAccessibleValue(Integer.valueOf(5))) { - throw new RuntimeException("setCurrentAccessibleValue(5) returned false for Scrollbar"); + throw new RuntimeException( + "setCurrentAccessibleValue should not return false " + + "for Scrollbar"); } assertIntValueEquals( "getCurrentAccessibleValue after setCurrentAccessibleValue(5)", 5, - value.getCurrentAccessibleValue() - ); + value.getCurrentAccessibleValue()); if (scrollbar.getValue() != 5) { throw new RuntimeException( - "setCurrentAccessibleValue(5) did not update Scrollbar.getValue(); actual value: " - + scrollbar.getValue() - ); + "setCurrentAccessibleValue should change the Scrollbar " + + "value"); } } - public static void verifyButtonAccessibility( - Button button, + public static void verifyScrollPaneAccessibility( + ScrollPane scrollPane, String expectedName, String expectedDescription) { + Objects.requireNonNull(scrollPane, "ScrollPane must not be null"); - Objects.requireNonNull(button, "Button must not be null"); + verifyAWTComponentAccessibility( + scrollPane, + expectedName, + expectedDescription, + AccessibleRole.SCROLL_PANE, + false, + false, + false, + false); + } + + public static void verifyTextAreaAccessibility( + TextArea textArea, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(textArea, "TextArea must not be null"); verifyAWTComponentAccessibility( - button, + textArea, expectedName, expectedDescription, - AccessibleRole.PUSH_BUTTON, + AccessibleRole.TEXT, + false, + false, true, + false); + } + + public static void verifyTextFieldAccessibility( + TextField textField, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(textField, "TextField must not be null"); + + verifyAWTComponentAccessibility( + textField, + expectedName, + expectedDescription, + AccessibleRole.TEXT, false, false, - true - ); + true, + false); + } - AccessibleContext context = button.getAccessibleContext(); + public static void verifyWindowAccessibility( + Window window, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(window, "Window must not be null"); + verifyAWTComponentAccessibility( + window, + expectedName, + expectedDescription, + AccessibleRole.WINDOW, + false, + false, + false, + false); + } + + public static void verifyMenuAccessibility( + Menu menu, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(menu, "Menu must not be null"); + + verifyMenuComponentAccessibility( + menu, + expectedName, + expectedDescription, + AccessibleRole.MENU, + true, + true, + false, + true, + "Menu"); + + AccessibleContext context = menu.getAccessibleContext(); + verifyClickAction(context, "Menu"); + verifyZeroAccessibleValue(context, "Menu"); + } + + public static void verifyMenuBarAccessibility( + MenuBar menuBar, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(menuBar, "MenuBar must not be null"); + + verifyMenuComponentAccessibility( + menuBar, + expectedName, + expectedDescription, + AccessibleRole.MENU_BAR, + false, + true, + false, + false, + "MenuBar"); + } + + public static void verifyMenuItemAccessibility( + MenuItem menuItem, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(menuItem, "MenuItem must not be null"); + + verifyMenuComponentAccessibility( + menuItem, + expectedName, + expectedDescription, + AccessibleRole.MENU_ITEM, + true, + true, + false, + true, + "MenuItem"); + + AccessibleContext context = menuItem.getAccessibleContext(); + verifyClickAction(context, "MenuItem"); + verifyZeroAccessibleValue(context, "MenuItem"); + } + + public static void verifyPopupMenuAccessibility( + PopupMenu popupMenu, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(popupMenu, "PopupMenu must not be null"); + + verifyMenuComponentAccessibility( + popupMenu, + expectedName, + expectedDescription, + AccessibleRole.POPUP_MENU, + true, + true, + false, + true, + "PopupMenu"); + + AccessibleContext context = popupMenu.getAccessibleContext(); + verifyClickAction(context, "PopupMenu"); + verifyZeroAccessibleValue(context, "PopupMenu"); + } + + private static void verifyMenuComponentAccessibility( + MenuComponent menuComponent, + String expectedName, + String expectedDescription, + AccessibleRole expectedRole, + boolean expectAction, + boolean expectSelection, + boolean expectText, + boolean expectValue, + String componentName) { + Objects.requireNonNull(menuComponent, + componentName + " must not be null"); + + AccessibleContext context = menuComponent.getAccessibleContext(); + if (context == null) { + throw new RuntimeException("getAccessibleContext returned null"); + } + + verifyAccessibleContextCommon( + context, + expectedName, + expectedDescription, + expectedRole, + expectAction, + expectSelection, + expectText, + expectValue); + + AccessibleComponent accessibleComponent = + context.getAccessibleComponent(); + if (accessibleComponent == null) { + throw new RuntimeException("getAccessibleComponent returned null"); + } + + new AccessibleMenuComponentTester( + menuComponent, accessibleComponent).test(); + } + + private static void verifyClickAction(AccessibleContext context, + String componentName) { AccessibleAction action = context.getAccessibleAction(); if (action == null) { - throw new RuntimeException("getAccessibleAction should not return null for Button"); + throw new RuntimeException( + "getAccessibleAction should not return null for " + + componentName); } int actionCount = action.getAccessibleActionCount(); if (actionCount != 1) { throw new RuntimeException( - "getAccessibleActionCount should return 1 for Button; got " + actionCount - ); + "getAccessibleActionCount returned the wrong number for " + + componentName); } String actionDescription = action.getAccessibleActionDescription(0); if (!"click".equals(actionDescription)) { throw new RuntimeException( - "getAccessibleActionDescription(0) should return \"click\" for Button; got [" - + actionDescription + "]" - ); + "getAccessibleActionDescription returned the wrong " + + "description for " + componentName); } + } + private static void verifyZeroAccessibleValue(AccessibleContext context, + String componentName) { AccessibleValue value = context.getAccessibleValue(); if (value == null) { - throw new RuntimeException("getAccessibleValue should not return null for Button"); + throw new RuntimeException( + "getAccessibleValue should not return null for " + + componentName); } - assertIntValueEquals("getCurrentAccessibleValue", 0, value.getCurrentAccessibleValue()); - assertIntValueEquals("getMinimumAccessibleValue", 0, value.getMinimumAccessibleValue()); - assertIntValueEquals("getMaximumAccessibleValue", 0, value.getMaximumAccessibleValue()); + assertIntValueEquals( + "getCurrentAccessibleValue", + 0, + value.getCurrentAccessibleValue()); + + assertIntValueEquals( + "getMinimumAccessibleValue", + 0, + value.getMinimumAccessibleValue()); + + assertIntValueEquals( + "getMaximumAccessibleValue", + 0, + value.getMaximumAccessibleValue()); if (value.setCurrentAccessibleValue(Integer.valueOf(5))) { throw new RuntimeException( - "setCurrentAccessibleValue(5) should return false for Button" - ); + "setCurrentAccessibleValue should return false for " + + componentName); } assertIntValueEquals( "getCurrentAccessibleValue after setCurrentAccessibleValue(5)", 0, - value.getCurrentAccessibleValue() - ); + value.getCurrentAccessibleValue()); + } + + private static void verifyListChildren(List list) { + AccessibleContext context = list.getAccessibleContext(); + + int childCount = context.getAccessibleChildrenCount(); + if (childCount != list.getItemCount()) { + throw new RuntimeException( + "getAccessibleChildrenCount returned an incorrect value " + + "for List"); + } + + for (int i = 0; i < childCount; i++) { + Accessible child = context.getAccessibleChild(i); + if (child == null) { + throw new RuntimeException( + "getAccessibleChild returned null for child " + i); + } + + AccessibleContext childContext = child.getAccessibleContext(); + if (childContext == null) { + throw new RuntimeException( + "getAccessibleContext returned null for List child " + + i); + } + + if (childContext.getAccessibleRole() != AccessibleRole.LIST_ITEM) { + throw new RuntimeException( + "The AccessibleRole of AccessibleAWTListChild is " + + "incorrect for child " + i); + } + + if (childContext.getAccessibleIndexInParent() != i) { + throw new RuntimeException( + "getAccessibleIndexInParent returned an incorrect " + + "value for AccessibleAWTListChild " + i); + } + + AccessibleStateSet childStateSet = + childContext.getAccessibleStateSet(); + if (childStateSet == null) { + throw new RuntimeException( + "getAccessibleStateSet returned null for List child " + + i); + } + + boolean accessibleSelected = + childStateSet.contains(AccessibleState.SELECTED); + boolean listSelected = list.isIndexSelected(i); + + if (accessibleSelected != listSelected) { + throw new RuntimeException( + "getAccessibleStateSet reports that list item " + i + + (accessibleSelected ? " is " : " is not ") + + "selected but List reports that it " + + (listSelected ? "is" : "is not") + " selected"); + } + } + } + + private static void verifyContainerChildren(Component component, + String componentName) { + AccessibleContext context = component.getAccessibleContext(); + + int childCount = context.getAccessibleChildrenCount(); + if (childCount != component.getAccessibleContext() + .getAccessibleChildrenCount()) { + throw new RuntimeException( + "getAccessibleChildrenCount returned an incorrect value " + + "for " + componentName); + } + + for (int i = 0; i < childCount; i++) { + Accessible child = context.getAccessibleChild(i); + if (child == null) { + throw new RuntimeException( + "getAccessibleChild returned null for " + + componentName + " child " + i); + } + + AccessibleContext childContext = child.getAccessibleContext(); + if (childContext == null) { + throw new RuntimeException( + "getAccessibleContext returned null for " + + componentName + " child " + i); + } + } } - private static void assertExpectedString(String methodName, String expected, String actual) { + private static void assertExpectedString(String methodName, + String expected, + String actual) { if (expected == null) { - throw new RuntimeException("Excepted value is null. Provide " + - "excepted value"); + throw new RuntimeException( + "Expected value for " + methodName + " should not be null"); } if (actual == null) { - throw new RuntimeException(methodName + " returned null; expected" + - " [" + expected + "]"); + throw new RuntimeException( + methodName + " returned null; expected [" + expected + "]"); } + if (!expected.equals(actual)) { - throw new RuntimeException(methodName + " returned [" + actual + - "]; expected [" + expected + "]"); + throw new RuntimeException( + methodName + " returned [" + actual + + "]; expected [" + expected + "]"); } } - private static void assertPresence(String methodName, boolean expectedPresent, Object value) { + private static void assertPresence(String methodName, + boolean expectedPresent, + Object value) { if (expectedPresent && value == null) { - throw new RuntimeException(methodName + " returned null but was expected"); + throw new RuntimeException( + methodName + " returned null but should not"); } + if (!expectedPresent && value != null) { - throw new RuntimeException(methodName + " returned non-null but " + - "was expected to be null"); + throw new RuntimeException( + methodName + " returned non-null but should return null"); } } - private static void assertLocaleMatches(Component component, AccessibleContext context) { + private static void assertLocaleMatches(Component component, + AccessibleContext context) { Locale componentLocale = component.getLocale(); Locale accessibleLocale = context.getLocale(); if (componentLocale == null) { throw new RuntimeException("Component.getLocale returned null"); } + if (accessibleLocale == null) { - throw new RuntimeException("AccessibleContext.getLocale returned null"); + throw new RuntimeException( + "AccessibleContext.getLocale returned null"); } + if (!componentLocale.equals(accessibleLocale)) { - throw new RuntimeException(String.format( - "AccessibleContext.getLocale returned [%s], but Component" + - ".getLocale returned [%s]", - accessibleLocale, componentLocale - )); + throw new RuntimeException( + "AccessibleContext.getLocale returned [" + + accessibleLocale + "], but Component.getLocale returned [" + + componentLocale + "]"); } } - private static void assertIntValueEquals(String methodName, int expected, Number actual) { + private static void assertIntValueEquals(String methodName, + int expected, + Number actual) { if (actual == null) { - throw new RuntimeException(methodName + " returned null; expected [" + expected + "]"); + throw new RuntimeException( + methodName + " returned null; expected [" + expected + "]"); } + if (actual.intValue() != expected) { throw new RuntimeException( - methodName + " returned [" + actual + "]; expected [" + expected + "]" - ); + methodName + " returned [" + actual + + "]; expected [" + expected + "]"); } } } diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorConversionTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorConversionTest.java index 6f0625d7985e..854ffd407c83 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.function.BiConsumer; import java.util.function.Function; import java.util.function.IntFunction; +import jdk.incubator.vector.Float16; abstract class AbstractVectorConversionTest { @@ -156,6 +157,31 @@ static double[] fill_double(double[] a, ToDoubleF f) { 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 @@ static double[] fill_double(double[] a, ToDoubleF f) { 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 @@ else if (src == float.class) { else if (src == double.class) { return DOUBLE_GENERATORS; } + else if (src == Float16.class) { + return FLOAT16_GENERATORS; + } else throw new IllegalStateException(); } @@ -206,11 +239,11 @@ else if (src == double.class) { 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 @@ static Object[][] fixedShapeXFixedShapeSpeciesArgs(VectorShape shape) { 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 @@ static Object[][] fixedShapeXShapeSpeciesArgs(VectorShape srcShape) { 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 @@ static Object[][] fixedShapeXSegmentedCastSpeciesArgs(VectorShape srcShape, bool 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 @@ else if (to == long.class) 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 @@ else if (to == double.class) 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 @@ else if (from == double.class) 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 @@ static void zeroArray(Object a, int offset, int length) { 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 @@ static void conversion_kernel(VectorSpecies srcSpecies, VectorSpecies< 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 @@ static void conversion_kernel(VectorSpecies srcSpecies, VectorSpecies< 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 @@ static void conversion_kernel(VectorSpecies srcSpecies, VectorSpecies< System.arraycopy(rv.toArray(), 0, actual, j, dst_species_len); } } - Assert.assertEquals(actual, expected); } @@ -469,8 +539,14 @@ static void reinterpret_kernel(VectorSpecies srcSpecies, VectorSpecies 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 000000000000..570be3bde632 --- /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 000000000000..ad971e9b9bf2 --- /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 000000000000..dac06d6925f4 --- /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 000000000000..a946e0d85858 --- /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 000000000000..401baf673611 --- /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 000000000000..0e70b4c85ecb --- /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 000000000000..83befc161a51 --- /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 000000000000..94017042b7b5 --- /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 000000000000..931e280c87a1 --- /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 000000000000..d8649c838ee3 --- /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 40de51c90ab7..1573748b925d 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java @@ -1719,9 +1719,14 @@ void viewAsIntegeralLanesTest() { 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 c28dd34c8ef7..059388477e89 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java @@ -1719,9 +1719,14 @@ void viewAsIntegeralLanesTest() { 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 703ef7d358be..3e39d1bc32f0 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java @@ -1719,9 +1719,14 @@ void viewAsIntegeralLanesTest() { 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 ea6846498a38..e78eb2ee2837 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java @@ -1719,9 +1719,14 @@ void viewAsIntegeralLanesTest() { 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 6a85da120541..dbcb69123232 100644 --- a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java @@ -1725,9 +1725,14 @@ void viewAsIntegeralLanesTest() { 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 8b5c4cac616f..6890f4e1cddd 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 a4cea57471ab..c48c658cdd81 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 16343eeaf40b..2531f0483000 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 faae74426e73..b59fd1a793f0 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 5ad7623d2c09..8606b9ba5984 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 b87012a21811..eac7edbbb3f2 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 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]? $Type$.$type$To$Bitstype$Bits(e): 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 6779c78a490a..2168eb95d309 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/jcmd/TestJcmdChangeLogLevel.java b/test/jdk/jdk/jfr/jcmd/TestJcmdChangeLogLevel.java index c4ef5ecfa74f..a6dcd4583837 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.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 @@ 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 static void main(String[] args) throws Exception { 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 f64c99bedbcb..8000199558cb 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.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 @@ private static Object getOption(String name) { } 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 @@ private static void testRepository(){ 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 4a934ebb36da..28e2891a08c0 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 static void main(String[] args) throws Exception { // 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 000000000000..802cd336ebc3 --- /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 000000000000..37222a0310ab --- /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/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java b/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java index 229ab03b568e..9e2c5e909b0f 100644 --- a/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java +++ b/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.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 @@ -32,13 +32,15 @@ import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import jdk.test.lib.security.SecurityUtils; -import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.security.SecurityUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; @@ -50,29 +52,32 @@ public class DisabledCipherSuitesNotNegotiated { private static final String TLS_PROTOCOL = "TLSv1.2"; private static volatile int serverPort = 0; - private static volatile Exception serverException = null; private static final CountDownLatch waitForServer = new CountDownLatch(1); - private static final int WAIT_FOR_SERVER_SECS = 5; + private static final int WAIT_FOR_SERVER_SECS = (int)Utils.adjustTimeout(5); private static final String DISABLED_CIPHERSUITE = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; private static final String DISABLED_CIPHER_WILDCARD = "TLS_ECDH*WITH_AES_256_GCM_*"; + private static volatile Exception serverException = null; private static void runServer(boolean disabledInClient) throws Exception { SSLContext ctx = SSLContext.getInstance(TLS_PROTOCOL); ctx.init(null, null, null); SSLServerSocketFactory factory = ctx.getServerSocketFactory(); + InetAddress address = InetAddress.getLoopbackAddress(); + System.out.println("SERVER listening on " + address); try(SSLServerSocket serverSocket = (SSLServerSocket)factory - .createServerSocket(0, -1, InetAddress.getLoopbackAddress())) { - serverPort = serverSocket.getLocalPort(); - waitForServer.countDown(); - + .createServerSocket(0, -1, address)) { if (disabledInClient) { // set cipher suite to disabled ciphersuite serverSocket.setEnabledCipherSuites(new String[]{DISABLED_CIPHERSUITE}); } - try(SSLSocket clientSocket = (SSLSocket) serverSocket.accept()) { + serverPort = serverSocket.getLocalPort(); + serverSocket.setSoTimeout(WAIT_FOR_SERVER_SECS * 3000); + waitForServer.countDown(); + + try(SSLSocket clientSocket = (SSLSocket)serverSocket.accept()) { try { clientSocket.getInputStream().readAllBytes(); throw new Exception("SERVER: The expected handshake exception was not thrown."); @@ -88,7 +93,9 @@ private static void runClient(boolean disableInClient, int portNumber) throws Ex SSLContext ctx = SSLContext.getInstance(TLS_PROTOCOL); ctx.init(null, null, null); SSLSocketFactory factory = ctx.getSocketFactory(); - try(SSLSocket socket = (SSLSocket)factory.createSocket("localhost", portNumber)) { + InetAddress address = InetAddress.getLoopbackAddress(); + System.out.println("CLIENT: Connecting to " + address); + try(SSLSocket socket = (SSLSocket)factory.createSocket(address, portNumber)) { if (!disableInClient) { socket.setEnabledCipherSuites(new String[]{DISABLED_CIPHERSUITE}); } @@ -104,42 +111,7 @@ private static void runClient(boolean disableInClient, int portNumber) throws Ex public static void main(String [] args) throws Exception { if (args.length == 1) { - // run server-side - final boolean disabledInClient = args[0].equals("client"); - if (!disabledInClient) { - SecurityUtils.addToDisabledTlsAlgs(DISABLED_CIPHER_WILDCARD); - } - try(ExecutorService executorService = Executors.newSingleThreadExecutor()) { - executorService.submit(() -> { - try { - runServer(disabledInClient); - } catch (Exception exc) { - System.out.println("Server Exception:"); - exc.printStackTrace(System.out); - serverException = exc; - throw new RuntimeException(exc); - } - }); - - if (!waitForServer.await(WAIT_FOR_SERVER_SECS, TimeUnit.SECONDS)) { - throw new Exception("Server did not start within " + - WAIT_FOR_SERVER_SECS + " seconds."); - } - - System.out.printf("Server listening on port %d.%nStarting client process...", - serverPort); - - OutputAnalyzer oa = ProcessTools.executeProcess( - ProcessTools.createTestJavaProcessBuilder("DisabledCipherSuitesNotNegotiated", - "" + disabledInClient, "" + serverPort)); - oa.shouldHaveExitValue(0); - System.out.println("Client output:"); - System.out.println(oa.getOutput()); - if (serverException != null) { - throw new Exception ("Server-side threw an unexpected exception: " - + serverException); - } - } + runTest(args[0].equals("client")); } else if (args.length == 2) { // run client-side @@ -147,6 +119,7 @@ public static void main(String [] args) throws Exception { if (disabledInClient) { SecurityUtils.addToDisabledTlsAlgs(DISABLED_CIPHER_WILDCARD); } + runClient(Boolean.parseBoolean(args[0]), Integer.parseInt(args[1])); } else { @@ -155,4 +128,48 @@ public static void main(String [] args) throws Exception { } } + private static void runTest(final boolean disabledInClient) throws Exception { + try(ExecutorService executorService = Executors.newSingleThreadExecutor()) { + Future serverThread = executorService.submit(() -> { + try { + if (!disabledInClient) { + SecurityUtils.addToDisabledTlsAlgs(DISABLED_CIPHER_WILDCARD); + } + runServer(disabledInClient); + } catch (Exception exc) { + serverException = exc; + } + }); + + + if (!waitForServer.await(WAIT_FOR_SERVER_SECS, TimeUnit.SECONDS)) { + throw new Exception("Server did not start within " + + WAIT_FOR_SERVER_SECS + " seconds."); + } + + System.out.printf("Server listening on port %d.%nStarting client process...", + serverPort); + + OutputAnalyzer oa = ProcessTools.executeProcess( + ProcessTools.createTestJavaProcessBuilder( + "DisabledCipherSuitesNotNegotiated", + "" + disabledInClient, "" + serverPort)); + oa.waitFor(); + serverThread.get(); + + System.out.printf("Client process return %d%nCLIENT OUTPUT%n%s%n", + oa.getExitValue(), oa.getOutput()); + if (serverException != null) { + System.out.printf( + "Server thread threw an unexpected exception: %s%n", + serverException); + throw serverException; + } else if (oa.getExitValue() != 0) { + throw new Exception(String.format("Client exit code is non-zero (%d). "+ + "Server did not throw an exception.", + oa.getExitValue())); + } + } + } + } diff --git a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java index ffa8a5308597..16a48fcc6262 100644 --- a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java +++ b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java @@ -103,9 +103,9 @@ class Y { } checkOutput("Foo.html", true, """

  • Constructor Details
      -
    1. Foo(T)
    2. -
    3. Foo(T)
    4. -
    5. Foo(T)
    6. +
    7. Foo(T)
    8. +
    9. Foo(T)
    10. +
    11. Foo(T)
  • """); checkOutput("index-all.html", true, """ @@ -145,9 +145,9 @@ class Y { } checkOutput("Foo.html", true, """
  • Method Details
      -
    1. m(T)
    2. -
    3. m(T)
    4. -
    5. m(T)
    6. +
    7. m(T)
    8. +
    9. m(T)
    10. +
    11. m(T)
  • """); checkOutput("index-all.html", true, """ @@ -210,8 +210,8 @@ class X { } checkOutput("Foo.html", true, """
  • Constructor Details
      -
    1. Foo(T)
    2. -
    3. Foo(T)
    4. +
    5. Foo(T)
    6. +
    7. Foo(T)
  • """); checkOutput("index-all.html", true, """ @@ -242,8 +242,8 @@ class X { } checkOutput("Foo.html", true, """
  • Method Details
      -
    1. m(T)
    2. -
    3. m(T)
    4. +
    5. m(T)
    6. +
    7. m(T)
  • """); checkOutput("index-all.html", true, """ diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java index 17ab97348459..02100d84a1a0 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java @@ -25,7 +25,7 @@ * @test * @bug 7025314 8023700 7198273 8025633 8026567 8081854 8196027 8182765 * 8196200 8196202 8223378 8258659 8261976 8320458 8329537 8350638 - * 8342705 8371021 8373526 + * 8342705 8371021 8373526 8384065 * @summary Make sure the Next/Prev Class links iterate through all types. * Make sure the navagation is 2 columns, not 3. * @library /tools/lib ../../lib @@ -172,6 +172,36 @@ public void testNavLinks(Path base) throws IOException { tb.writeJavaFiles(src, """ package pkg1; public class A { + /** + * Empty ctor + */ + public A() {} + + /** + * Single param ctor + */ + public A(int i) {} + + /** + * A ctor with many params + */ + public A(int i, int j, int x, int y, String s, boolean b) {} + + /** + * A method without parameters + */ + public void noParams() {} + + /** + * A method with a single parameter + */ + public void oneParam(String s) {} + + /** + * A method with lots of parameters + */ + public void manyParams(String s, int i, int j, boolean b, double d, double e) {} + /** * Class with members. */ @@ -217,6 +247,29 @@ public static class Y extends X { "pkg1"); checkExit(Exit.OK); + checkOrder("pkg1/A.html", + """ +
      +
    1. Description
    2. +
    3. Nested Class Summary
    4. +
    5. Constructor Summary
    6. +
    7. Method Summary
    8. +
    9. Constructor Details +
        +
      1. A()
      2. +
      3. A(int)
      4. +
      5. A(int, int, int, int, String, boolean)
      6. +
      +
    10. +
    11. Method Details +
        +
      1. noParams()
      2. +
      3. oneParam(String)
      4. +
      5. manyParams(String, int, int, boolean, double, double)
      6. +
      +
    12. +
    """); + checkOrder("pkg1/A.X.html", """