[RFC PATCH] riscv: add vectorized sin
Pincheng Wang <[email protected]> Thu, 9 Jul 2026 18:51:38 +0800
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
Hi all, This revisits the earlier RFC on RVV-based vector math in newlib [1]. Back then one open question was that RISC-V had no vector function ABI comparable to x86_64 and aarch64, so there was no agreed way to name these routines. That is now settled: the name mangling rule was merged into the psABI in June 2026 [2], so I would like to restart the discussion with a concrete implementation to build on. This is a first, self-contained patch: a single function, kept optional and off by default, so we can settle the build integration and confirm the ABI symbol naming before adding more of the sin/cos/exp/log set. Add an RVV implementation of sin for double, exported under the vector function ABI symbol _ZGVr1Nxv_sin (vfloat64m1_t) from the merged psABI rule. This is the LMUL=1, unmasked, vector-length-agnostic variant a compiler emits when vectorizing a scalar sin loop over doubles. Existing scalar sin and the rest of libm are untouched. The vector implementation does a Cody-Waite argument reduction with a three-part pi/2 split and double-double error tracking, then evaluates the fdlibm sin/cos kernel polynomials. Reduction and kernels are built from discrete vfmul/vfadd/vfsub intrinsics so the compensated terms are not lost to FMA contraction. Lanes too large for the fast reduction, as well as Inf/NaN, fall back per-lane to the existing scalar Payne-Hanek reducer __ieee754_rem_pio2, guarded by a vcpop so the common case stays fully vectorized. The worst-case error is <= 1 ULP. The whole thing is guarded by __riscv_vector, so it compiles to an empty object on non-vector multilibs and relies on each multilib's own -march otherwise, keeping the build multilib-safe. A new --enable-vecmath switch (default off) decides whether the vectorized math is built at all; configure and Makefile.in are regenerated accordingly. test_vec_sin.c is a standalone check that walks all three paths and fails if any lane exceeds 1 ULP; its large-argument reference values are precomputed in test_vec_sin_bigref.h. Reviews and suggestions are greatly welcomed! Thanks, Pincheng Wang [1] https://sourceware.org/pipermail/newlib/2025/022175.html [2] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/455 Signed-off-by: Pincheng Wang <[email protected]> --- newlib/Makefile.in | 71 +++-- newlib/configure | 28 ++ newlib/configure.ac | 16 + newlib/libm/machine/riscv/Makefile.inc | 8 + newlib/libm/machine/riscv/test_vec_sin.c | 288 ++++++++++++++++++ .../libm/machine/riscv/test_vec_sin_bigref.h | 250 +++++++++++++++ newlib/libm/machine/riscv/vec_sin.c | 219 +++++++++++++ 7 files changed, 857 insertions(+), 23 deletions(-) create mode 100644 newlib/libm/machine/riscv/test_vec_sin.c create mode 100644 newlib/libm/machine/riscv/test_vec_sin_bigref.h create mode 100644 newlib/libm/machine/riscv/vec_sin.c diff --git a/newlib/Makefile.in b/newlib/Makefile.in index 5d1b1acb5..ec50acc8e 100644 --- a/newlib/Makefile.in +++ b/newlib/Makefile.in @@ -1011,17 +1011,23 @@ check_PROGRAMS = @HAVE_LIBM_MACHINE_SPARC_TRUE@am__append_159 = $(libm_machine_sparc_src) @HAVE_LIBM_MACHINE_SPU_TRUE@am__append_160 = $(libm_machine_spu_src) @HAVE_LIBM_MACHINE_RISCV_TRUE@am__append_161 = $(libm_machine_riscv_src) -@HAVE_LIBM_MACHINE_RISCV_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__append_162 = $(libm_ld128_lsrc) -@HAVE_LIBM_MACHINE_RISCV_TRUE@am__append_163 = + +# Vectorized (RVV) math routines. vec_sin.c is guarded internally on +# __riscv_vector, so it compiles to an empty object for non-vector +# multilibs and relies on each multilib's own -march otherwise (no per-file +# ISA override is applied here, keeping the build multilib-safe). +@HAVE_LIBM_MACHINE_RISCV_TRUE@@NEWLIB_VECMATH_TRUE@am__append_162 = libm/machine/riscv/vec_sin.c +@HAVE_LIBM_MACHINE_RISCV_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__append_163 = $(libm_ld128_lsrc) @HAVE_LIBM_MACHINE_RISCV_TRUE@am__append_164 = -@HAVE_LIBM_MACHINE_X86_64_TRUE@am__append_165 = $(libm_machine_x86_64_src) -@HAVE_LIBM_MACHINE_X86_64_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__append_166 = $(libm_ld80_lsrc) -@HAVE_LIBM_MACHINE_X86_64_TRUE@am__append_167 = +@HAVE_LIBM_MACHINE_RISCV_TRUE@am__append_165 = +@HAVE_LIBM_MACHINE_X86_64_TRUE@am__append_166 = $(libm_machine_x86_64_src) +@HAVE_LIBM_MACHINE_X86_64_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__append_167 = $(libm_ld80_lsrc) @HAVE_LIBM_MACHINE_X86_64_TRUE@am__append_168 = -@HAVE_LIBM_MACHINE_XTENSA_TRUE@@XTENSA_XCHAL_HAVE_FP_SQRT_TRUE@am__append_169 = \ +@HAVE_LIBM_MACHINE_X86_64_TRUE@am__append_169 = +@HAVE_LIBM_MACHINE_XTENSA_TRUE@@XTENSA_XCHAL_HAVE_FP_SQRT_TRUE@am__append_170 = \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@@XTENSA_XCHAL_HAVE_FP_SQRT_TRUE@ libm/machine/xtensa/ef_sqrt.c -@HAVE_LIBM_MACHINE_XTENSA_TRUE@am__append_170 = $(libm_machine_xtensa_src) +@HAVE_LIBM_MACHINE_XTENSA_TRUE@am__append_171 = $(libm_machine_xtensa_src) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ @@ -3752,8 +3758,9 @@ am__objects_159 = libm/fenv/libm_a-feclearexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_RISCV_TRUE@ libm/machine/riscv/libm_a-s_llround.$(OBJEXT) \ @HAVE_LIBM_MACHINE_RISCV_TRUE@ libm/machine/riscv/libm_a-sf_llround.$(OBJEXT) @HAVE_LIBM_MACHINE_RISCV_TRUE@am__objects_187 = $(am__objects_186) -@HAVE_LIBM_MACHINE_RISCV_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__objects_188 = $(am__objects_162) -@HAVE_LIBM_MACHINE_X86_64_TRUE@am__objects_189 = libm/machine/x86_64/libm_a-feclearexcept.$(OBJEXT) \ +@HAVE_LIBM_MACHINE_RISCV_TRUE@@NEWLIB_VECMATH_TRUE@am__objects_188 = libm/machine/riscv/libm_a-vec_sin.$(OBJEXT) +@HAVE_LIBM_MACHINE_RISCV_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__objects_189 = $(am__objects_162) +@HAVE_LIBM_MACHINE_X86_64_TRUE@am__objects_190 = libm/machine/x86_64/libm_a-feclearexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_X86_64_TRUE@ libm/machine/x86_64/libm_a-fegetenv.$(OBJEXT) \ @HAVE_LIBM_MACHINE_X86_64_TRUE@ libm/machine/x86_64/libm_a-fegetexceptflag.$(OBJEXT) \ @HAVE_LIBM_MACHINE_X86_64_TRUE@ libm/machine/x86_64/libm_a-fegetround.$(OBJEXT) \ @@ -3765,10 +3772,10 @@ am__objects_159 = libm/fenv/libm_a-feclearexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_X86_64_TRUE@ libm/machine/x86_64/libm_a-fesetround.$(OBJEXT) \ @HAVE_LIBM_MACHINE_X86_64_TRUE@ libm/machine/x86_64/libm_a-fetestexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_X86_64_TRUE@ libm/machine/x86_64/libm_a-feupdateenv.$(OBJEXT) -@HAVE_LIBM_MACHINE_X86_64_TRUE@am__objects_190 = $(am__objects_189) -@HAVE_LIBM_MACHINE_X86_64_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__objects_191 = $(am__objects_170) -@HAVE_LIBM_MACHINE_XTENSA_TRUE@@XTENSA_XCHAL_HAVE_FP_SQRT_TRUE@am__objects_192 = libm/machine/xtensa/libm_a-ef_sqrt.$(OBJEXT) -@HAVE_LIBM_MACHINE_XTENSA_TRUE@am__objects_193 = libm/machine/xtensa/libm_a-feclearexcept.$(OBJEXT) \ +@HAVE_LIBM_MACHINE_X86_64_TRUE@am__objects_191 = $(am__objects_190) +@HAVE_LIBM_MACHINE_X86_64_TRUE@@HAVE_LONG_DOUBLE_TRUE@am__objects_192 = $(am__objects_170) +@HAVE_LIBM_MACHINE_XTENSA_TRUE@@XTENSA_XCHAL_HAVE_FP_SQRT_TRUE@am__objects_193 = libm/machine/xtensa/libm_a-ef_sqrt.$(OBJEXT) +@HAVE_LIBM_MACHINE_XTENSA_TRUE@am__objects_194 = libm/machine/xtensa/libm_a-feclearexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/libm_a-fegetenv.$(OBJEXT) \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/libm_a-fegetexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/libm_a-fegetexceptflag.$(OBJEXT) \ @@ -3777,8 +3784,8 @@ am__objects_159 = libm/fenv/libm_a-feclearexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/libm_a-feraiseexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/libm_a-fetestexcept.$(OBJEXT) \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/libm_a-feupdateenv.$(OBJEXT) \ -@HAVE_LIBM_MACHINE_XTENSA_TRUE@ $(am__objects_192) -@HAVE_LIBM_MACHINE_XTENSA_TRUE@am__objects_194 = $(am__objects_193) +@HAVE_LIBM_MACHINE_XTENSA_TRUE@ $(am__objects_193) +@HAVE_LIBM_MACHINE_XTENSA_TRUE@am__objects_195 = $(am__objects_194) am_libm_a_OBJECTS = $(am__objects_145) $(am__objects_149) \ $(am__objects_150) $(am__objects_151) $(am__objects_153) \ $(am__objects_155) $(am__objects_156) $(am__objects_157) \ @@ -3787,8 +3794,8 @@ am_libm_a_OBJECTS = $(am__objects_145) $(am__objects_149) \ $(am__objects_169) $(am__objects_171) $(am__objects_173) \ $(am__objects_177) $(am__objects_179) $(am__objects_181) \ $(am__objects_183) $(am__objects_185) $(am__objects_187) \ - $(am__objects_188) $(am__objects_190) $(am__objects_191) \ - $(am__objects_194) + $(am__objects_188) $(am__objects_189) $(am__objects_191) \ + $(am__objects_192) $(am__objects_195) libm_a_OBJECTS = $(am_libm_a_OBJECTS) am_libm_test_test_OBJECTS = libm/test/test.$(OBJEXT) \ libm/test/string.$(OBJEXT) libm/test/convert.$(OBJEXT) \ @@ -4357,8 +4364,8 @@ libm_a_SOURCES = $(am__append_133) $(am__append_136) \ $(am__append_149) $(am__append_150) $(am__append_153) \ $(am__append_156) $(am__append_157) $(am__append_158) \ $(am__append_159) $(am__append_160) $(am__append_161) \ - $(am__append_162) $(am__append_165) $(am__append_166) \ - $(am__append_170) + $(am__append_162) $(am__append_163) $(am__append_166) \ + $(am__append_167) $(am__append_171) libm_a_CFLAGS = $(AM_CFLAGS) $(libm_a_CFLAGS_$(subst /,_,$(@D))) $(libm_a_CFLAGS_$(subst /,_,$(@D)_$(<F))) libm_a_CCASFLAGS = $(AM_CCASFLAGS) $(libm_a_CCASFLAGS_$(subst /,_,$(@D))) $(libm_a_CCASFLAGS_$(subst /,_,$(@D)_$(<F))) libm_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/libm/common $(libm_a_CPPFLAGS_$(subst /,_,$(@D))) $(libm_a_CPPFLAGS_$(subst /,_,$(@D)_$(<F))) @@ -4793,11 +4800,11 @@ LIBM_CHEWOUT_FILES = $(am__append_134) $(am__append_137) \ libm/fenv/feraiseexcept.def libm/fenv/fesetenv.def \ libm/fenv/fesetexceptflag.def libm/fenv/fesetround.def \ libm/fenv/fetestexcept.def libm/fenv/feupdateenv.def \ - $(am__append_145) $(am__append_151) $(am__append_163) \ - $(am__append_167) + $(am__append_145) $(am__append_151) $(am__append_164) \ + $(am__append_168) LIBM_CHAPTERS = $(am__append_135) $(am__append_138) $(am__append_142) \ libm/complex/complex.tex libm/fenv/fenv.tex $(am__append_146) \ - $(am__append_152) $(am__append_164) $(am__append_168) + $(am__append_152) $(am__append_165) $(am__append_169) LIBM_DOCBOOK_OUT_FILES = $(LIBM_CHEWOUT_FILES:.def=.xml) @NEWLIB_HW_FP_TRUE@libm_mathfp_src = \ @NEWLIB_HW_FP_TRUE@ libm/mathfp/s_acos.c libm/mathfp/s_frexp.c libm/mathfp/s_mathcnst.c \ @@ -5409,7 +5416,7 @@ libm_test_test_LDADD = $(CRT0) libm.a libc.a @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/feraiseexcept.c \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/fetestexcept.c \ @HAVE_LIBM_MACHINE_XTENSA_TRUE@ libm/machine/xtensa/feupdateenv.c \ -@HAVE_LIBM_MACHINE_XTENSA_TRUE@ $(am__append_169) +@HAVE_LIBM_MACHINE_XTENSA_TRUE@ $(am__append_170) @HAVE_LIBM_MACHINE_XTENSA_TRUE@libm_a_CFLAGS_libm_machine_xtensa = -D_LIBM all: newlib.h _newlib_version.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -12486,6 +12493,9 @@ libm/machine/riscv/libm_a-s_llround.$(OBJEXT): \ libm/machine/riscv/libm_a-sf_llround.$(OBJEXT): \ libm/machine/riscv/$(am__dirstamp) \ libm/machine/riscv/$(DEPDIR)/$(am__dirstamp) +libm/machine/riscv/libm_a-vec_sin.$(OBJEXT): \ + libm/machine/riscv/$(am__dirstamp) \ + libm/machine/riscv/$(DEPDIR)/$(am__dirstamp) libm/machine/x86_64/$(am__dirstamp): @$(MKDIR_P) libm/machine/x86_64 @: > libm/machine/x86_64/$(am__dirstamp) @@ -14989,6 +14999,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@libm/machine/riscv/$(DEPDIR)/libm_a-sf_llround.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libm/machine/riscv/$(DEPDIR)/libm_a-sf_lrint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libm/machine/riscv/$(DEPDIR)/libm_a-sf_lround.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libm/machine/sparc/$(DEPDIR)/libm_a-feclearexcept.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libm/machine/sparc/$(DEPDIR)/libm_a-fegetenv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libm/machine/sparc/$(DEPDIR)/libm_a-fegetexceptflag.Po@am__quote@ @@ -50334,6 +50345,20 @@ libm/machine/riscv/libm_a-sf_llround.obj: libm/machine/riscv/sf_llround.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libm_a_CPPFLAGS) $(CPPFLAGS) $(libm_a_CFLAGS) $(CFLAGS) -c -o libm/machine/riscv/libm_a-sf_llround.obj `if test -f 'libm/machine/riscv/sf_llround.c'; then $(CYGPATH_W) 'libm/machine/riscv/sf_llround.c'; else $(CYGPATH_W) '$(srcdir)/libm/machine/riscv/sf_llround.c'; fi` +libm/machine/riscv/libm_a-vec_sin.o: libm/machine/riscv/vec_sin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libm_a_CPPFLAGS) $(CPPFLAGS) $(libm_a_CFLAGS) $(CFLAGS) -MT libm/machine/riscv/libm_a-vec_sin.o -MD -MP -MF libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Tpo -c -o libm/machine/riscv/libm_a-vec_sin.o `test -f 'libm/machine/riscv/vec_sin.c' || echo '$(srcdir)/'`libm/machine/riscv/vec_sin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Tpo libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libm/machine/riscv/vec_sin.c' object='libm/machine/riscv/libm_a-vec_sin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libm_a_CPPFLAGS) $(CPPFLAGS) $(libm_a_CFLAGS) $(CFLAGS) -c -o libm/machine/riscv/libm_a-vec_sin.o `test -f 'libm/machine/riscv/vec_sin.c' || echo '$(srcdir)/'`libm/machine/riscv/vec_sin.c + +libm/machine/riscv/libm_a-vec_sin.obj: libm/machine/riscv/vec_sin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libm_a_CPPFLAGS) $(CPPFLAGS) $(libm_a_CFLAGS) $(CFLAGS) -MT libm/machine/riscv/libm_a-vec_sin.obj -MD -MP -MF libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Tpo -c -o libm/machine/riscv/libm_a-vec_sin.obj `if test -f 'libm/machine/riscv/vec_sin.c'; then $(CYGPATH_W) 'libm/machine/riscv/vec_sin.c'; else $(CYGPATH_W) '$(srcdir)/libm/machine/riscv/vec_sin.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Tpo libm/machine/riscv/$(DEPDIR)/libm_a-vec_sin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libm/machine/riscv/vec_sin.c' object='libm/machine/riscv/libm_a-vec_sin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libm_a_CPPFLAGS) $(CPPFLAGS) $(libm_a_CFLAGS) $(CFLAGS) -c -o libm/machine/riscv/libm_a-vec_sin.obj `if test -f 'libm/machine/riscv/vec_sin.c'; then $(CYGPATH_W) 'libm/machine/riscv/vec_sin.c'; else $(CYGPATH_W) '$(srcdir)/libm/machine/riscv/vec_sin.c'; fi` + libm/machine/x86_64/libm_a-feclearexcept.o: libm/machine/x86_64/feclearexcept.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libm_a_CPPFLAGS) $(CPPFLAGS) $(libm_a_CFLAGS) $(CFLAGS) -MT libm/machine/x86_64/libm_a-feclearexcept.o -MD -MP -MF libm/machine/x86_64/$(DEPDIR)/libm_a-feclearexcept.Tpo -c -o libm/machine/x86_64/libm_a-feclearexcept.o `test -f 'libm/machine/x86_64/feclearexcept.c' || echo '$(srcdir)/'`libm/machine/x86_64/feclearexcept.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libm/machine/x86_64/$(DEPDIR)/libm_a-feclearexcept.Tpo libm/machine/x86_64/$(DEPDIR)/libm_a-feclearexcept.Po diff --git a/newlib/configure b/newlib/configure index dd4153173..ef54ba443 100755 --- a/newlib/configure +++ b/newlib/configure @@ -838,6 +838,8 @@ HAVE_SIGNAL_DIR_TRUE CC_FOR_NEWLIB NEWLIB_HW_FP_FALSE NEWLIB_HW_FP_TRUE +NEWLIB_VECMATH_FALSE +NEWLIB_VECMATH_TRUE sys_dir shared_machine_dir machine_dir @@ -1001,6 +1003,7 @@ enable_newlib_long_time_t enable_newlib_use_gdtoa enable_newlib_use_malloc_in_execl enable_newlib_hw_misaligned_access +enable_vecmath enable_multilib enable_target_optspace enable_malloc_debugging @@ -1672,6 +1675,7 @@ Optional Features: --enable-newlib-use-gdtoa Use gdtoa rather than legacy ldtoa --enable-newlib-use-malloc-in-execl use malloc instead of alloca in execl, execle and execlp --enable-newlib-hw-misaligned-access Use hardware word-by-word access instead of byte-by-byte for misaligned memory + --enable-vecmath build vectorized (SIMD) libm math functions --enable-multilib build many library versions (default) --enable-target-optspace optimize for space --enable-malloc-debugging indicate malloc debugging requested @@ -2622,6 +2626,17 @@ else newlib_hw_misaligned_access= fi +# Check whether --enable-vecmath was given. +if test "${enable_vecmath+set}" = set; then : + enableval=$enable_vecmath; case "${enableval}" in + yes) vecmath=yes ;; + no) vecmath=no ;; + *) as_fn_error $? "bad value ${enableval} for vecmath" "$LINENO" 5 ;; + esac +else + vecmath=no +fi + # Default to --enable-multilib # Check whether --enable-multilib was given. if test "${enable_multilib+set}" = set; then : @@ -5301,6 +5316,15 @@ OBJEXT=o + if test x$vecmath = xyes; then + NEWLIB_VECMATH_TRUE= + NEWLIB_VECMATH_FALSE='#' +else + NEWLIB_VECMATH_TRUE='#' + NEWLIB_VECMATH_FALSE= +fi + + newlib_hw_fp=false #AC_ARG_ENABLE(newlib_hw_fp, #[ --enable-newlib-hw-fp Turn on hardware floating point math], @@ -7657,6 +7681,10 @@ if test -z "${ELIX_LEVEL_4_TRUE}" && test -z "${ELIX_LEVEL_4_FALSE}"; then as_fn_error $? "conditional \"ELIX_LEVEL_4\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${NEWLIB_VECMATH_TRUE}" && test -z "${NEWLIB_VECMATH_FALSE}"; then + as_fn_error $? "conditional \"NEWLIB_VECMATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${NEWLIB_HW_FP_TRUE}" && test -z "${NEWLIB_HW_FP_FALSE}"; then as_fn_error $? "conditional \"NEWLIB_HW_FP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/newlib/configure.ac b/newlib/configure.ac index 4640e69c5..50c2246ad 100644 --- a/newlib/configure.ac +++ b/newlib/configure.ac @@ -333,9 +333,25 @@ AC_ARG_ENABLE(newlib-hw-misaligned-access, esac fi], [newlib_hw_misaligned_access=])dnl +dnl Support --enable-vecmath +dnl Build the SIMD/vector variants of libm math functions (currently the +dnl RISC-V Vector routines under libm/machine/riscv). The sources guard +dnl their bodies on the target ISA, so this is safe to enable for a +dnl multilib build; multilibs without the vector extension get empty +dnl objects. +AC_ARG_ENABLE(vecmath, +[ --enable-vecmath build vectorized (SIMD) libm math functions], +[case "${enableval}" in + yes) vecmath=yes ;; + no) vecmath=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for vecmath) ;; + esac], [vecmath=no])dnl + AM_ENABLE_MULTILIB(, ..) NEWLIB_CONFIGURE(.) +AM_CONDITIONAL(NEWLIB_VECMATH, test x$vecmath = xyes) + dnl The following is being disabled because the mathfp library is dnl not up to standard due to inaccuracies caused by some of the dnl floating-point algorithms used. If you wish to work on this, diff --git a/newlib/libm/machine/riscv/Makefile.inc b/newlib/libm/machine/riscv/Makefile.inc index 9ce71e7be..03ec32b96 100644 --- a/newlib/libm/machine/riscv/Makefile.inc +++ b/newlib/libm/machine/riscv/Makefile.inc @@ -16,3 +16,11 @@ %D%/s_llround.c %D%/sf_llround.c libm_a_SOURCES += $(%C%_src) + +if NEWLIB_VECMATH +# Vectorized (RVV) math routines. vec_sin.c is guarded internally on +# __riscv_vector, so it compiles to an empty object for non-vector +# multilibs and relies on each multilib's own -march otherwise (no per-file +# ISA override is applied here, keeping the build multilib-safe). +libm_a_SOURCES += %D%/vec_sin.c +endif diff --git a/newlib/libm/machine/riscv/test_vec_sin.c b/newlib/libm/machine/riscv/test_vec_sin.c new file mode 100644 index 000000000..e358d67e1 --- /dev/null +++ b/newlib/libm/machine/riscv/test_vec_sin.c @@ -0,0 +1,288 @@ +/* + * Accuracy test for the RVV vector sin, _ZGVr1Nxv_sin (double). + * + * The vector result for every lane is compared against a higher-precision + * reference computed with sinl() (long double). On RISC-V long double is + * IEEE binary128 in the ABI but the C library evaluates it at whatever the + * platform provides; either way it carries strictly more precision than + * double here, which is sufficient to measure a <= 1 ULP double result. + * The test walks all three code paths (no-reduction, fast Cody-Waite + * reduction, and the Payne-Hanek slow path) plus adversarial arguments + * close to multiples of pi/2 and pi, and fails (non-zero exit) if any lane + * exceeds 1 ULP. + * + * Build/run (rv64gcv), e.g.: + * riscv64-unknown-elf-gcc -march=rv64gcv -mabi=lp64d -O2 \ + * test_vec_sin.c -L<builddir>/newlib -lm -o test_vec_sin + * qemu-riscv64 -cpu rv64,v=true test_vec_sin + * + * This program is intentionally standalone (not wired into libm.a); it is + * the verification companion for vec_sin.c. + */ + +#include <math.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#if defined(__riscv_vector) +#include <riscv_vector.h> + +extern vfloat64m1_t _ZGVr1Nxv_sin (vfloat64m1_t x); + +/* ulp(x): distance to the next double away from zero at x's magnitude. */ +static double +ulp_of (double x) +{ + if (x == 0.0) + return 0x1p-1074; /* smallest subnormal */ + if (!isfinite (x)) + return INFINITY; + int e; + frexp (x, &e); + int ex = e - 1 - 52; + if (ex < -1074) + ex = -1074; + return ldexp (1.0, ex); +} + +/* Error of got in ULP of the reference, using sinl() as a + * higher-precision reference. Only used where sinl() is trustworthy; + * large arguments are checked against a precomputed table instead (see + * below) because some C libraries have a buggy large-argument long double + * reducer. */ +static double +ulp_error (double x, double got) +{ + long double ref = sinl ((long double) x); + long double diff = (long double) got - ref; + if (diff < 0) + diff = -diff; + double u = ulp_of ((double) ref); + return (double) (diff / (long double) u); +} + +/* Threshold below which the platform sinl() is used as the live reference. + * Above it we rely on the baked-in correctly-rounded reference table. */ +#define SINL_REFERENCE_LIMIT 1.0e12 + +/* Reference table for large arguments, generated offline with a 300-bit + * reference (mpmath). Each entry holds the input's bits and the reference + * sin value as a double-double (hi + lo), which carries ~106 bits, plenty + * to measure a 1 ULP double error. */ +struct ref_entry { uint64_t x, sin_hi, sin_lo; }; +static const struct ref_entry big_ref[] = { +#include "test_vec_sin_bigref.h" +}; + +static double +as_double (uint64_t b) +{ + double d; + memcpy (&d, &b, sizeof d); + return d; +} + +/* A small xorshift PRNG so the test is deterministic and self-contained. */ +static uint64_t rng_state = 0x123456789abcdef0ULL; +static uint64_t +rng_next (void) +{ + uint64_t x = rng_state; + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + rng_state = x; + return x; +} +static double +rng_uniform (double lo, double hi) +{ + double u = (double) (rng_next () >> 11) * 0x1p-53; /* [0,1) */ + return lo + u * (hi - lo); +} + +/* Run one lane-wide batch through _ZGVr1Nxv_sin, updating the worst error. + * Returns the number of lanes that exceeded 1 ULP. */ +static long +check_batch (const double *xs, size_t n, double *worst, double *worst_x) +{ + size_t vl = __riscv_vsetvlmax_e64m1 (); + long fails = 0; + double lanes[64]; + for (size_t off = 0; off < n; off += vl) + { + size_t cnt = (off + vl <= n) ? vl : (n - off); + for (size_t k = 0; k < vl; k++) + lanes[k] = (k < cnt) ? xs[off + k] : 0.0; + vfloat64m1_t xv = __riscv_vle64_v_f64m1 (lanes, vl); + vfloat64m1_t rv = _ZGVr1Nxv_sin (xv); + __riscv_vse64_v_f64m1 (lanes, rv, vl); + for (size_t k = 0; k < cnt; k++) + { + double x = xs[off + k]; + double e = ulp_error (x, lanes[k]); + if (e > *worst) + { + *worst = e; + *worst_x = x; + } + if (e > 1.0) + { + if (fails < 10) + printf (" FAIL x=%.17g got=%.17g err=%.4f ULP\n", + x, lanes[k], e); + fails++; + } + } + } + return fails; +} + +/* Check the large-argument table: each result must be within 1 ULP (one + * representable double) of the correctly-rounded reference. */ +static long +check_big_ref (double *worst, double *worst_x) +{ + size_t vl = __riscv_vsetvlmax_e64m1 (); + size_t n = sizeof big_ref / sizeof big_ref[0]; + long fails = 0; + double lanes[64]; + for (size_t off = 0; off < n; off += vl) + { + size_t cnt = (off + vl <= n) ? vl : (n - off); + for (size_t k = 0; k < vl; k++) + lanes[k] = (k < cnt) ? as_double (big_ref[off + k].x) : 0.0; + vfloat64m1_t rv = _ZGVr1Nxv_sin (__riscv_vle64_v_f64m1 (lanes, vl)); + __riscv_vse64_v_f64m1 (lanes, rv, vl); + for (size_t k = 0; k < cnt; k++) + { + /* Reconstruct the reference as long double from the dd pair. */ + long double ref = (long double) as_double (big_ref[off + k].sin_hi) + + (long double) as_double (big_ref[off + k].sin_lo); + long double diff = (long double) lanes[k] - ref; + if (diff < 0) + diff = -diff; + double e = (double) (diff / (long double) ulp_of ((double) ref)); + if (e > *worst) + { + *worst = e; + *worst_x = as_double (big_ref[off + k].x); + } + if (e > 1.0) + { + if (fails < 10) + printf (" FAIL x=%.17g got=%.17g err=%.4f ULP\n", + as_double (big_ref[off + k].x), lanes[k], e); + fails++; + } + } + } + return fails; +} + +#define NBUF 4096 + +int +main (void) +{ + static double xs[NBUF]; + double worst = 0.0, worst_x = 0.0; + long fails = 0, total = 0; + size_t i; + + /* Region 1: |x| <= pi/4 (no argument reduction). */ + for (i = 0; i < NBUF; i++) + xs[i] = rng_uniform (-M_PI / 4, M_PI / 4); + fails += check_batch (xs, NBUF, &worst, &worst_x); total += NBUF; + + /* Region 2: fast Cody-Waite reduction, growing magnitudes. */ + static const double hi[] = { 3.15, 10.0, 100.0, 1.0e3, 1.0e4, 1.0e5, 9.9e5 }; + for (size_t b = 0; b < sizeof hi / sizeof hi[0]; b++) + { + for (i = 0; i < NBUF; i++) + xs[i] = rng_uniform (-hi[b], hi[b]); + fails += check_batch (xs, NBUF, &worst, &worst_x); total += NBUF; + } + + /* Region 3a: Payne-Hanek slow path, checked live against sinl() while it + * is trustworthy (|x| < SINL_REFERENCE_LIMIT). */ + for (int decade = 6; decade <= 11; decade++) + { + double scale = (double) powl (10.0L, (long double) decade); + for (i = 0; i < NBUF; i++) + { + double s = (rng_next () & 1) ? 1.0 : -1.0; + xs[i] = s * rng_uniform (1.0, 9.9) * scale; + } + fails += check_batch (xs, NBUF, &worst, &worst_x); total += NBUF; + } + + /* Region 3b: very large magnitudes, checked against the correctly-rounded + * reference table (avoids relying on a large-argument sinl()). */ + fails += check_big_ref (&worst, &worst_x); + total += (long) (sizeof big_ref / sizeof big_ref[0]); + + /* Adversarial: arguments very close to k*pi/2 and k*pi where sin is tiny + * and relative error is hardest to control. */ + for (int k = -2048; k <= 2048; k++) + { + i = 0; + xs[i++] = k * (M_PI / 2) + rng_uniform (-1e-5, 1e-5); + xs[i++] = k * M_PI + rng_uniform (-1e-9, 1e-9); + fails += check_batch (xs, i, &worst, &worst_x); total += i; + } + + /* Special values: signed zero must be preserved; Inf/NaN must give NaN. + * Each value is broadcast across a full vector so the check is valid for + * any VLEN (a lane count as small as 2). */ + { + size_t vl = __riscv_vsetvlmax_e64m1 (); + double lanes[64]; + + __riscv_vse64_v_f64m1 (lanes, + _ZGVr1Nxv_sin (__riscv_vfmv_v_f_f64m1 (-0.0, vl)), + vl); + if (!(lanes[0] == 0.0 && signbit (lanes[0]))) + { printf (" FAIL sin(-0) not -0\n"); fails++; } + + __riscv_vse64_v_f64m1 (lanes, + _ZGVr1Nxv_sin (__riscv_vfmv_v_f_f64m1 (0.0, vl)), + vl); + if (!(lanes[0] == 0.0 && !signbit (lanes[0]))) + { printf (" FAIL sin(+0) not +0\n"); fails++; } + + double bad[] = { INFINITY, -INFINITY, NAN }; + for (size_t j = 0; j < sizeof bad / sizeof bad[0]; j++) + { + __riscv_vse64_v_f64m1 (lanes, + _ZGVr1Nxv_sin (__riscv_vfmv_v_f_f64m1 (bad[j], vl)), + vl); + if (!isnan (lanes[0])) + { printf (" FAIL sin(%g) not NaN\n", bad[j]); fails++; } + } + total += 5; + } + + printf ("vec sin: %ld samples, max error %.6f ULP at x=%.17g, %ld failures\n", + total, worst, worst_x, fails); + if (fails == 0 && worst <= 1.0) + { + printf ("PASS: max error <= 1 ULP\n"); + return 0; + } + printf ("FAIL: accuracy bound exceeded\n"); + return 1; +} + +#else /* !__riscv_vector */ + +int +main (void) +{ + printf ("vec sin test skipped: target has no V extension\n"); + return 0; +} + +#endif /* __riscv_vector */ + diff --git a/newlib/libm/machine/riscv/test_vec_sin_bigref.h b/newlib/libm/machine/riscv/test_vec_sin_bigref.h new file mode 100644 index 000000000..9316b1d14 --- /dev/null +++ b/newlib/libm/machine/riscv/test_vec_sin_bigref.h @@ -0,0 +1,250 @@ +/* Auto-generated correctly-rounded reference values for sin(double) at + large arguments. Format: { input_bits, sin_hi_bits, sin_lo_bits }, + where the reference sin value is the double-double sum hi + lo of a + 300-bit computation. Used by test_vec_sin.c. Do not edit. */ + { 0x44a9dbb4ff908fb5ULL, 0xbfefc07760ab6354ULL, 0xbc7d5b4e724faf93ULL }, + { 0xdbfbc15774f33afeULL, 0xbfe77e039dbb7348ULL, 0x3c8564fe62c841d4ULL }, + { 0x6582353d215fa02bULL, 0xbfeefea2e334d557ULL, 0x3c8e2b07fe644ac8ULL }, + { 0x7d7add74a882dee4ULL, 0x3fec31addc7e7074ULL, 0xbc8400ef6e285faeULL }, + { 0xecc7c6178db646b3ULL, 0xbfeb3a89c87e6f8aULL, 0x3c57c5a24ad8aa0dULL }, + { 0xefa504161fd00b47ULL, 0x3fd4a9d75cb23a15ULL, 0x3c725108a2a25ebcULL }, + { 0xe534f4894bd602f3ULL, 0x3fcee79fa978d966ULL, 0xbc61174154f4d9bfULL }, + { 0x4b34e1e2e82d6c82ULL, 0xbf9b1bf927c893e4ULL, 0x3c3c987cd59eb0c5ULL }, + { 0xc9b6efda16235718ULL, 0x3febfe5f23debae6ULL, 0x3c89400a90a9cb18ULL }, + { 0xdeb23e83234ee6a4ULL, 0xbfee81bc183fbd29ULL, 0x3c7eaf076f4d339aULL }, + { 0xc853b24cf82dcb0aULL, 0xbfd4446c07eb46e8ULL, 0x3c70b944bf07dad2ULL }, + { 0xd568845f1020f760ULL, 0x3fd689163edc0d68ULL, 0xbc4f18c6ebade0f0ULL }, + { 0xf847cf0e8587807dULL, 0x3fde71d33d5f6a38ULL, 0x3c5332bf9f650f80ULL }, + { 0xf8688b4915b2340cULL, 0xbfeb2c9a2d97d745ULL, 0xbc501b0b17ab6adfULL }, + { 0x5ad615616b4511ceULL, 0xbfc20243d1eb990bULL, 0x3c5ab46d814c1907ULL }, + { 0x52c3b4beea74ec04ULL, 0xbfe73cac6930c2a1ULL, 0xbc8481737b2688c8ULL }, + { 0xd458c66b9a888eebULL, 0x3fce88ff02fb8173ULL, 0xbc605f0a3fa08a1aULL }, + { 0xcc99d269643e68b2ULL, 0xbfeb6cdb94146eb1ULL, 0x3c6b077f7c570a9aULL }, + { 0xe6e00a19223c11b8ULL, 0x3fda3ec8bf6e8b04ULL, 0xbc593c5f34b4813cULL }, + { 0x7ae9216f4b768e36ULL, 0xbfeff396fdb55b44ULL, 0xbc825a30790a28faULL }, + { 0xd147e7367b556f14ULL, 0x3fe93591e70f67ddULL, 0xbc4b908a8bdc2004ULL }, + { 0x7d4256e4960879dfULL, 0x3fcb4363099b289dULL, 0xbc437a4e18914237ULL }, + { 0xe013c555bfaa270dULL, 0x3fdd595d80386a84ULL, 0x3c6b575848bb9dbeULL }, + { 0xf4f9a1ba87d1e3b9ULL, 0x3fefda0a9cf410e1ULL, 0xbc4d58b14edc3bc2ULL }, + { 0x49453f2165887abfULL, 0xbfdd512f6aeb6113ULL, 0xbc729eef6bc92ff4ULL }, + { 0x536db0a8e2d0428cULL, 0xbfe4bd0d2ccaec08ULL, 0xbc8d7298b2d595b2ULL }, + { 0xf79d9af4393cbd9aULL, 0xbfe6255752046e10ULL, 0xbc52e09f5cf3386dULL }, + { 0xe67fd249d393152aULL, 0x3fc9b6e381429938ULL, 0xbc52ad43a083bfbfULL }, + { 0xd27fcc5f41c6e488ULL, 0x3fde89166b282088ULL, 0xbc7d37769671915dULL }, + { 0xe00a6992ce6c1ce4ULL, 0x3fbdff2baddc9a0bULL, 0xbc47116844da78f5ULL }, + { 0xe77cb1e1b3d58926ULL, 0xbfe1edc413b7d7c7ULL, 0xbc8b8336d45d3d2eULL }, + { 0xf57eda6d1ab72b50ULL, 0xbfe027b6743da17eULL, 0x3c7883c1422e26e5ULL }, + { 0xd7c4f76c9c956f52ULL, 0x3fed074d52442f5bULL, 0xbc8be322b089d744ULL }, + { 0x7c42c48992b0580cULL, 0xbfe2492ce6b315e6ULL, 0xbc8859569449c328ULL }, + { 0x571843d305d135abULL, 0xbfd53de1ad799097ULL, 0x3c78c2f3d6f3e0aaULL }, + { 0x65d262a58c3cb1f6ULL, 0xbfe6a1b96392c030ULL, 0xbc894dba66196a3eULL }, + { 0x716ce75ac6e463beULL, 0x3fe8f8a64f068f5eULL, 0xbc81751252eac2a8ULL }, + { 0x65f17b41fb9183a1ULL, 0x3fed6a2f2e420ce2ULL, 0x3c5ee4c86a4afa2bULL }, + { 0xfa5a0b3667f4182dULL, 0x3fdff8218b12a393ULL, 0x3c622e6b12894a94ULL }, + { 0xe3677e43684b974cULL, 0x3fbba2a2526eab37ULL, 0xbc5af23d8957bd23ULL }, + { 0x4395fb27da08f010ULL, 0xbfe20ed71d689bcaULL, 0x3c7dd0dd7d9b7e25ULL }, + { 0x5e48b0e4203542aeULL, 0xbfea43d41e8dcb1dULL, 0xbc6590d8e451ab33ULL }, + { 0xc5f2512cdba5a27dULL, 0x3fe6f6bc1233ca95ULL, 0x3c87e49f2aec8035ULL }, + { 0xfd4c86f77e590326ULL, 0xbfeaf2a168d330daULL, 0xbc8e2b1e3ad609a3ULL }, + { 0xf0639f90a675b7adULL, 0x3fedafec0a806285ULL, 0xbc8b77d8e8a9394aULL }, + { 0x78d0cf0a55c0c91fULL, 0x3fb78ad5a22f8d64ULL, 0xbc4a55c48540d0daULL }, + { 0x7c8e30d4454b9821ULL, 0x3fefa7b85b3dcd6eULL, 0xbc6b0f9a6bd6f62dULL }, + { 0xea615705de88fe3aULL, 0xbfafe7ed59ec8262ULL, 0x3c4e42bc7b886c90ULL }, + { 0x6c7bfdfab32a81c1ULL, 0xbfee472774a43babULL, 0x3c7e570e1bd15f94ULL }, + { 0x6cd96cd876949553ULL, 0x3fe561fdbcc0e0a9ULL, 0x3c86acde7cd4a8d3ULL }, + { 0x6f94de89c0376a87ULL, 0x3fe9b4ca527c7fa6ULL, 0x3c79cd9d59b54031ULL }, + { 0x6761f60ed01da25eULL, 0xbfe8eae8acb0a66fULL, 0x3c49bebd0cf78fbaULL }, + { 0x56aa284e2c106ca7ULL, 0xbfd5ccaa1a4a745fULL, 0x3c678961367fb9a8ULL }, + { 0x6610826f12575488ULL, 0xbfef225873ba6d75ULL, 0xbc89bf0cb01945bdULL }, + { 0x44b5f074dd5e5f91ULL, 0xbfe44b4390c64229ULL, 0x3c7a58b19f1408efULL }, + { 0x5a7082d0e1c59decULL, 0xbfb6213c825d8b85ULL, 0xbc537503c6e0cddfULL }, + { 0xde8d1fdbab167564ULL, 0xbfd04dc168165571ULL, 0xbc5420b74043fcd9ULL }, + { 0xd6815208d7272823ULL, 0x3feeafb94a2f6c0fULL, 0x3c894a16430feee3ULL }, + { 0xd95a3333ab2184d4ULL, 0x3fe92fdb9ae8b728ULL, 0xbc81fd33677898c4ULL }, + { 0xfb4ae55a83558975ULL, 0x3fec96cd70a1a670ULL, 0xbc8309455f25fb9bULL }, + { 0x4aee072add723ad9ULL, 0xbfe7e06d695d602aULL, 0xbc6a2995709bd38fULL }, + { 0xcd026beefedc96c1ULL, 0xbfef4cf6eb5a884fULL, 0xbc7c798dd1cc293dULL }, + { 0x5f24f8c21a79c3d5ULL, 0xbfea42ddd1c17682ULL, 0xbc84da8a18b3c37dULL }, + { 0x7ae907f70d0b5fdcULL, 0xbfeededb92d58459ULL, 0xbc76785595cf306fULL }, + { 0x6eacef4d70d22d77ULL, 0xbfec426d3578352eULL, 0xbc8b27555d7a823fULL }, + { 0x55d18bddc73d7d19ULL, 0x3fc4a054eba9225aULL, 0xbc6b63485a377d88ULL }, + { 0x42b71f32cbaa673aULL, 0x3fd6da32d22b42e2ULL, 0x3c7bb6b4a5e01209ULL }, + { 0xe2b79014b74eae06ULL, 0xbfee5f431515f7ddULL, 0x3c7aa0b227d87181ULL }, + { 0xf08971259ebf74d2ULL, 0x3fef63ce5ff53438ULL, 0x3c8f49fa1c47cfb4ULL }, + { 0x7152db6cd53dd92dULL, 0xbfeb96537c255382ULL, 0xbc65083aa496ee1dULL }, + { 0xcb11e519f157c3e3ULL, 0xbfcf23c6eec9b1d8ULL, 0x3c530dc6d41dee43ULL }, + { 0xf1f50536ce3945fcULL, 0x3feabe8582ab144cULL, 0x3c4ed7efdcaab868ULL }, + { 0x5e818d6ec72948b7ULL, 0x3fefb59d0ac6a7ecULL, 0xbc8773fd78927ebcULL }, + { 0xea872ae2fbc53ceeULL, 0xbfee82da2a4b8acfULL, 0x3c88a6c64a744977ULL }, + { 0xc3a26f16e32fab53ULL, 0x3feeff799ab2ee50ULL, 0xbc8daf713f015ff9ULL }, + { 0x7bdd5402143da712ULL, 0xbfe8690148e95e74ULL, 0xbc86bfaa806196a6ULL }, + { 0x6cd4bf43e59b9f0eULL, 0x3fefaa5ba89f71f1ULL, 0xbc49803cf49a7cd7ULL }, + { 0xea72a5ee14efc6f9ULL, 0xbfe66a8c814165d9ULL, 0xbc84d79087f03e95ULL }, + { 0xe4b4d7f8d1dc534fULL, 0x3fe666089452f0fcULL, 0x3c6b53a4330e3e6fULL }, + { 0x77e8990d834ef92bULL, 0xbfd66ea9a9b36569ULL, 0x3c578cb1448eddeeULL }, + { 0x4349ce8b6d745fd2ULL, 0xbfdd5fbb025e98c4ULL, 0x3c7e09613d4ff083ULL }, + { 0xc371d094fd81a430ULL, 0xbfd104f4f59c35c9ULL, 0x3c7406abaf7d792fULL }, + { 0xfa8585533ed8dd51ULL, 0x3fec2b3734be7df7ULL, 0x3c5e25fd2daeb9e1ULL }, + { 0x64521026ae008463ULL, 0x3fe2a18f3eabcf7eULL, 0x3c457ffe19249afdULL }, + { 0x4885853ef16bf001ULL, 0xbfebb37f3f88713dULL, 0xbc70871082b5264cULL }, + { 0xfe12ac98fe404e2eULL, 0xbfef82002a84d70dULL, 0xbc7ec475df0e794dULL }, + { 0xf00ea354f646b762ULL, 0xbfeff654fe56c26aULL, 0xbc841144607d36e9ULL }, + { 0x4f31271978b78aa5ULL, 0xbfefd1a01f92c760ULL, 0xbc801970aa1b9229ULL }, + { 0xc9e3c79dbab90bb9ULL, 0xbfeff6ee1b9d4928ULL, 0x3c70daacc547a73bULL }, + { 0xee3ab1e4d905adc7ULL, 0x3fe9ad3b58ce5faeULL, 0xbc82349e67ef73bcULL }, + { 0x6e01c4160382c330ULL, 0xbfdee9413d2b7536ULL, 0xbc77efa54c573babULL }, + { 0x550208bbd0f21d27ULL, 0x3fee8aec0ce7ae7fULL, 0x3c7ba3fbc43960d2ULL }, + { 0x6bcd98be95335228ULL, 0xbfe31b3df53c2b42ULL, 0x3c771dc425139d9eULL }, + { 0xf9e630507811552aULL, 0xbfd67de486e0a39bULL, 0x3c606e8f51ab4b86ULL }, + { 0x5263685b1cfa620fULL, 0x3fea8273913621aeULL, 0xbc87e3327ff1e306ULL }, + { 0xcecf1a824be4d935ULL, 0x3fef65a694b8f8f7ULL, 0x3c71e9660b37b954ULL }, + { 0x4d6aaae2238f3d71ULL, 0xbfc0c1893c492b2dULL, 0xbc61bd68521bb7d3ULL }, + { 0x5364f7af58d26971ULL, 0x3fefda000a3d560fULL, 0x3c70795277604280ULL }, + { 0xddfab1d8ccfb924dULL, 0x3fef8d8c8d9727fbULL, 0xbc80fd17d3fbb7f7ULL }, + { 0x57bf256d425173dbULL, 0x3fef66b11e66188eULL, 0xbc463e50962c783bULL }, + { 0xeaaeee5bc26ca14eULL, 0xbfcd908beb3b7527ULL, 0x3c696e36e746eca9ULL }, + { 0xfd007999e73d0153ULL, 0x3fe6ae4a855588dbULL, 0x3c863a43e53d0b8eULL }, + { 0x7b3d8fcceff22d32ULL, 0x3fef6d651ae0e510ULL, 0x3c89800f562ae087ULL }, + { 0x6e2028b30ae34929ULL, 0xbfed8f7f297ca5b4ULL, 0x3c892297fc4ccd45ULL }, + { 0x68abacd9594c034dULL, 0x3fe393ffc7a9ea72ULL, 0xbc8339bcf7eeed7bULL }, + { 0xf54f48cf65f99808ULL, 0xbfefd28d402b98c7ULL, 0xbc8b98c3ced855d9ULL }, + { 0x74ae2e64b64829d3ULL, 0xbfeff1bf510ba65fULL, 0xbc8dea08c9b6877aULL }, + { 0xf9d8fbc71950c68eULL, 0x3fd4e3f908fe036cULL, 0xbc74400cb90f1963ULL }, + { 0xe9f81d95d3a008daULL, 0xbfeae8bc700ea627ULL, 0x3c82d159fe3fd720ULL }, + { 0xeb15400c5c9c792aULL, 0x3fb266058c34f144ULL, 0x3c3e17808cc9a530ULL }, + { 0x4eb9f786422fb33eULL, 0x3fe0c34f5e8066f5ULL, 0x3c71d7089622959dULL }, + { 0xfc63d8049a9ff525ULL, 0xbfeee6aea91ef94aULL, 0x3c6038b4e2c13e34ULL }, + { 0xced5db4bd4a3d631ULL, 0x3fe525c0c4152120ULL, 0x3c8872446ecdabadULL }, + { 0xeb7db2e753f12d26ULL, 0x3fe18c8a88c059faULL, 0x3c8d1b2c19037bf4ULL }, + { 0x784f96b568580c13ULL, 0xbfdf3badc719754aULL, 0x3c76b1948cd4cde5ULL }, + { 0xd2a41a31c5cf09fbULL, 0x3fd8e0564e905d6fULL, 0xbc659b2e13478961ULL }, + { 0xdc58decaae6fb25cULL, 0x3fe47abeb58598bdULL, 0x3c56abd64019e4beULL }, + { 0x484248ec70ba8047ULL, 0xbfe8d0872ee8db96ULL, 0xbc755ebc8fccf47fULL }, + { 0xd888cf7ed17b95faULL, 0xbfef1d92b8ce5ab1ULL, 0x3c820661260c2966ULL }, + { 0xdf244d931f1d0979ULL, 0xbfea06b9f1861517ULL, 0xbc64eab8fb6a963cULL }, + { 0x42e7bea87a06bb97ULL, 0xbf80cc5df27cc893ULL, 0xbc2f887836ea6188ULL }, + { 0x42e030810af10a8aULL, 0xbf80aa27ab18c146ULL, 0xbc0c8e366f6ce709ULL }, + { 0x42d6915d9129a89dULL, 0x3f4b035c5cbe5317ULL, 0x3bd633e5aafcbce1ULL }, + { 0x42a7e6098a48380aULL, 0xbf8412e0e05c9e80ULL, 0xbc12d461930e9c7fULL }, + { 0x42f0eb1cd187c866ULL, 0x3fa380278e2023a7ULL, 0x3c472837f3881d2cULL }, + { 0x42e9ec8ea0dc5b69ULL, 0x3f9076dabcd77f53ULL, 0x3c06984a658b62a0ULL }, + { 0x42e7c8e1c184db33ULL, 0xbf8b6bf586a5e44aULL, 0x3c219a22965884e5ULL }, + { 0x42f0dd0108ba84b3ULL, 0x3f72dffade7da8e7ULL, 0x3bf99d5f6d5ac851ULL }, + { 0x42cffefaf33ee8c8ULL, 0xbf77d5508a6748eaULL, 0xbc15ed52410bad0dULL }, + { 0x42e3837bfef06182ULL, 0xbf5220a9eb7a8d1aULL, 0xbbf8fc0deedb3253ULL }, + { 0x42f113102aa2ddc9ULL, 0x3f60e1e32e9b8db1ULL, 0x3c042bc681c17a7cULL }, + { 0x42f07a2036b196abULL, 0xbf98ddb068481cf1ULL, 0xbbfe5c3282da937cULL }, + { 0x42f0f9add596adceULL, 0x3f5bd6f6a7a5b109ULL, 0xbbee6fe5848141f4ULL }, + { 0x42d4e078b3fbe60cULL, 0x3f7c85cd69d47748ULL, 0xbc15b27a777f2d08ULL }, + { 0x42d77feb017b379cULL, 0x3f40d4ea3aaad201ULL, 0xbbee49553aee2db0ULL }, + { 0x42eee13ae8acb1e1ULL, 0xbf6e17a8351be2beULL, 0x3bfe6c4f9216c940ULL }, + { 0x42efda72022e8165ULL, 0x3f7401c30a912bffULL, 0x3c0ecb8cc07b0f07ULL }, + { 0x42e597bb5ad08eedULL, 0x3f7184607ea6c688ULL, 0x3c14968ff64f50b3ULL }, + { 0x42e515c33faf2e0bULL, 0x3f878b6a5d032689ULL, 0x3c2979d0e33e7f65ULL }, + { 0x42d076d3e2bc75caULL, 0x3f79b4507d6e5652ULL, 0x3c147b3d3058c04fULL }, + { 0x42ce35a57c9bd40bULL, 0x3f80895f3c2ebc56ULL, 0x3c12225fd8c7e28aULL }, + { 0x42d8e714dd8b95e9ULL, 0xbf8037b6d60448efULL, 0xbc15be19168ff7d1ULL }, + { 0x42ca770e8688ea8eULL, 0x3f55efc64bb3a1d8ULL, 0x3bf41cd8e23cd5b1ULL }, + { 0x42da2e25ac11a92dULL, 0x3f9ba378f9b9309cULL, 0xbc3fda65f378dc03ULL }, + { 0x42e401e6fefeaf9fULL, 0xbf79915f6954ab1aULL, 0xbc0e2da306c553b1ULL }, + { 0x42f0cfc024770e8dULL, 0x3f81d312d07e7249ULL, 0x3be6aa89ba75636eULL }, + { 0x42bf8cc4c2cc9a0eULL, 0x3f7a7a5a068e4480ULL, 0x3c04f792ea0e4bf9ULL }, + { 0x42f119566f205f00ULL, 0xbf93b8b1f9290c22ULL, 0x3c254c90aa55b77fULL }, + { 0x42e4f81f6c2d7c02ULL, 0x3f7d05e7c78b208fULL, 0x3bf615a3a3d40194ULL }, + { 0x42f0fdda33c1a75cULL, 0x3fa156cdcf31fb92ULL, 0xbc3d545f9306c381ULL }, + { 0x42f16a94796b2c34ULL, 0xbf8369fe6bbc4612ULL, 0xbc2557edee6d9916ULL }, + { 0x42e707f284ddea20ULL, 0x3f97a29d65d188f6ULL, 0xbc335e3a48f90c1cULL }, + { 0x42dc8afccd056efeULL, 0xbf6a01e46476fe8fULL, 0x3c011ba54acbc76aULL }, + { 0x42e94b74a40fdd48ULL, 0xbf7003b1a7274281ULL, 0x3be87e3995c16129ULL }, + { 0x42b23f8f465f9e58ULL, 0x3f40f443ccf1832dULL, 0x3be7beefa1b9a940ULL }, + { 0x42ecc8755c949b22ULL, 0x3f9344fd36e8022bULL, 0xbc3c0c2e527b826cULL }, + { 0x42e0b054c53b5d39ULL, 0x3f70e9a011f6d65fULL, 0x3c1b554415ec728aULL }, + { 0x42d3b6b804fbc5a7ULL, 0xbf6bc97e2c0b5246ULL, 0xbc052c094c75f315ULL }, + { 0x42e1ca33a34dec6dULL, 0xbf74d77a65e3010fULL, 0x3c1924471d418048ULL }, + { 0x42eda6f9b07d92f5ULL, 0xbf62aa37ea67bb4eULL, 0x3c00abc80fecc17fULL }, + { 0x42f1b24bc2880f75ULL, 0x3f93477b1d9fe336ULL, 0x3c188184ab1a54e9ULL }, + { 0x42e01543d879e2c9ULL, 0x3f8257edfed1cea8ULL, 0x3c27b03211ee7c35ULL }, + { 0x42ca1a5ec0128654ULL, 0x3f5d6cb12216217bULL, 0x3bf1f0ce3fa4b4caULL }, + { 0x42eb8d66ed98cedaULL, 0x3f92609c01355a2bULL, 0xbc2ddef12e22f6fdULL }, + { 0x42f0a609cc46058cULL, 0xbf7804b5ea754c98ULL, 0xbc1dd427683fe1f8ULL }, + { 0x42f0f8c1866a9f7bULL, 0x3f9c6c87698485d3ULL, 0x3c2d489477eee9b5ULL }, + { 0x42e34cde47414cf8ULL, 0x3f956c29569c60c9ULL, 0x3c3a7633dafe2486ULL }, + { 0x42efa735f8ea6544ULL, 0xbf7309328e1b4768ULL, 0x3c11f842e70c5698ULL }, + { 0x42ce9809b9a64e63ULL, 0xbf80265a51dc5441ULL, 0x3c2e772829673ddfULL }, + { 0x42ec8240dcd90783ULL, 0xbf78d25f06bd3736ULL, 0xbbedd2b59783d940ULL }, + { 0x42e2c94dbd018eabULL, 0x3f8e4da44272b5caULL, 0xbc0dd155219ba6d0ULL }, + { 0x42de0d2d8757b8a6ULL, 0xbf86c793b7d9943dULL, 0xbc23aa3209922a51ULL }, + { 0x42deecaeff996904ULL, 0xbf78fa12771ec7b5ULL, 0xbc19c8fc9ad4948aULL }, + { 0x42e972c23a9fc175ULL, 0xbf71af5132592aedULL, 0xbc1a431c4054a951ULL }, + { 0x42e39a6b08bce147ULL, 0xbf8da8a43f55190aULL, 0xbc2d7ea7a8b2f66bULL }, + { 0x42e5cb6607974ad3ULL, 0xbf7443061c8fa61fULL, 0xbbc99bfa7fa22075ULL }, + { 0x42e6c694c342d903ULL, 0xbf60d88cfaf5ebe8ULL, 0x3c09444cbaf85e3dULL }, + { 0x42da72cf5b9ac96aULL, 0x3f84e565ba209029ULL, 0x3c2051d0fa1aff93ULL }, + { 0x42ef4ccc9d14979eULL, 0xbf8228bec193e115ULL, 0xbbe9dc461434cd3fULL }, + { 0x42ee47a485c27578ULL, 0xbf80395b2498221cULL, 0x3c14101266690f5cULL }, + { 0x42dad2d7d32eba44ULL, 0x3f70238dad3c59caULL, 0x3c1dc82b45d88bc7ULL }, + { 0x42ef95ca6761299dULL, 0xbf5dc89b2f65b1beULL, 0x3bd8a775d7e12eb0ULL }, + { 0x42cb5977aa359db6ULL, 0x3f7fa88c1455ace2ULL, 0x3c0f407ce17827a5ULL }, + { 0x42f1616e2fed4c11ULL, 0x3fa13f9e9a351a2aULL, 0xbc4090ae4b479190ULL }, + { 0x42e82ee2761c74b7ULL, 0x3f72c5a242c6c613ULL, 0x3c05e06f5e516cb6ULL }, + { 0x427b22d12b8ad554ULL, 0x3f5d136909f6c369ULL, 0xbbb4ad6ba4f9b2e6ULL }, + { 0x42e103e86fcd28edULL, 0xbf6d1ca987175599ULL, 0x3c06fdecbadf16ffULL }, + { 0x42e811c70d666bbbULL, 0xbf91984e3a85d010ULL, 0x3c3983d8998e9553ULL }, + { 0x42f1b5f5f276f97aULL, 0xbfa12e2e46e47523ULL, 0xbc4b9646d4f630e7ULL }, + { 0x42e94a54a9c55472ULL, 0xbf80bffd8d482f14ULL, 0x3c2f06a60b20cb7dULL }, + { 0x42dfb5d738e95002ULL, 0x3f858d3ec9d4366fULL, 0xbc18d1f9efacd2aeULL }, + { 0x42dd0da41d84d1ddULL, 0x3f814cd6d4b81456ULL, 0x3c2973826c5b0b65ULL }, + { 0x42c24e8fb5f472afULL, 0x3f825baa7033e089ULL, 0x3bff587965271dc7ULL }, + { 0x42b10644d14b9b6dULL, 0x3f747590605e052dULL, 0xbc16bd5a106c8991ULL }, + { 0x42efab585b64809bULL, 0xbf6d56f83303ff3fULL, 0xbc0f42d166c2ab9fULL }, + { 0x42e85ed862068624ULL, 0x3f7e2c4c0226a1aeULL, 0xbc1ccc9fbe04ac53ULL }, + { 0x42e6d9859145c214ULL, 0x3f7201aad8cd6d2aULL, 0xbbf6a1303210799eULL }, + { 0x4299ef2669ca1626ULL, 0xbf803e0e1dd78addULL, 0xbc1ea5d671866bc4ULL }, + { 0x42e6c20d3c9dd322ULL, 0x3f7cb72dd7256582ULL, 0x3c17c09e4a97519dULL }, + { 0x42e5d1765657f566ULL, 0xbf7f59cfd0379fafULL, 0xbbfe2675f26e0cb4ULL }, + { 0x4274cccccccccccdULL, 0xbfeb652877ab8257ULL, 0x3c8f4bb2d8e7b7beULL }, + { 0xc266666666666666ULL, 0xbfeea4586a2dfee4ULL, 0x3c8bf04c740eb938ULL }, + { 0x4284cccccccccccdULL, 0xbfec50fb070a07b5ULL, 0xbc7324c01f041830ULL }, + { 0xc276666666666666ULL, 0x3fe1a9ed19c2642bULL, 0xbc7b84831233a3aeULL }, + { 0x4294cccccccccccdULL, 0x3fea6147a2dc7225ULL, 0xbc2cff8d76ee2990ULL }, + { 0xc286666666666666ULL, 0xbfed75348cdaf022ULL, 0x3c7647860e225329ULL }, + { 0x42a4cccccccccccdULL, 0xbfeddd4edcbd9f0fULL, 0xbc84bafe3b573c55ULL }, + { 0xc296666666666666ULL, 0xbfe7034dd111a92eULL, 0x3c609c14662e13fdULL }, + { 0x42b4cccccccccccdULL, 0x3fe5743585652dddULL, 0x3c7f753ca1dc3ea1ULL }, + { 0xc2a6666666666666ULL, 0x3feffb2975cf0540ULL, 0x3c700a80104ad5dbULL }, + { 0x42c4cccccccccccdULL, 0xbfefd6153e02dfa7ULL, 0x3c67d00955d2e783ULL }, + { 0xc2b6666666666666ULL, 0xbfb1955d8644e304ULL, 0x3c514eeb4785df2bULL }, + { 0x42d4cccccccccccdULL, 0xbfc9bb5a957ff77cULL, 0x3c6552523bb114e9ULL }, + { 0xc2c6666666666666ULL, 0x3fc18abc1a08cc84ULL, 0x3c63285cde354315ULL }, + { 0x42e4cccccccccccdULL, 0x3fd934df9b1998f7ULL, 0x3c77edbfe8329aedULL }, + { 0xc2d6666666666666ULL, 0x3fd1605cf12f62a3ULL, 0xbc5b400190f82577ULL }, + { 0x42f4cccccccccccdULL, 0x3fe72b4ff19781a8ULL, 0xbc79bca6775772f7ULL }, + { 0xc2e6666666666666ULL, 0x3fe0b9447432258aULL, 0xbc34b3486d93f031ULL }, + { 0x4304cccccccccccdULL, 0x3feff66026744e9eULL, 0xbc78ceb76011db8aULL }, + { 0xc2f6666666666666ULL, 0x3fec842589258a43ULL, 0x3c8be0e63c382022ULL }, + { 0x4314cccccccccccdULL, 0xbfb8c83b02d0edd8ULL, 0xbc56aefa58c5343aULL }, + { 0xc306666666666666ULL, 0x3fe9e0d23d7b63fbULL, 0xbc63df0489efac8aULL }, + { 0x4324cccccccccccdULL, 0x3fc8aa6f0eb7d6e8ULL, 0xbc6f0d05d98ad00bULL }, + { 0xc316666666666666ULL, 0xbfee71d4d43065c8ULL, 0xbc3c11066a7c7820ULL }, + { 0x4334cccccccccccdULL, 0x3fd83415dcc39cf5ULL, 0x3c7ec504249d12f4ULL }, + { 0xc326666666666666ULL, 0x3fe2c090300f8b41ULL, 0xbc64e4612cfafa3fULL }, + { 0x4344cccccccccccdULL, 0x3fe667eadf0c9687ULL, 0xbc7d15e3579ca723ULL }, + { 0xc336666666666666ULL, 0xbfee63daff3f7a38ULL, 0x3c6f422c46d3b643ULL }, + { 0x4354cccccccccccdULL, 0x3feffe7201c77109ULL, 0xbc7a2f5a9a315bc5ULL }, + { 0xc346666666666666ULL, 0xbfe30932a56c8d60ULL, 0xbc7e3ffe82882405ULL }, + { 0x4364cccccccccccdULL, 0x3fa3f1ed89cea39aULL, 0x3c2da0dbd2d9b162ULL }, + { 0xc356666666666666ULL, 0x3fee9a58b002a034ULL, 0xbc6c545be6465beaULL }, + { 0x4374cccccccccccdULL, 0xbfb3ee0d626f0451ULL, 0x3c38d8d5a58deec7ULL }, + { 0xc366666666666666ULL, 0x3fe1e337ef53849dULL, 0xbc6ae2ff488320f3ULL }, + { 0x4384cccccccccccdULL, 0xbfc3de9149623dedULL, 0x3c637241b7759eeaULL }, + { 0xc376666666666666ULL, 0xbfeda9f6565e4ad4ULL, 0xbc8abcda8c5ed688ULL }, + { 0x4394cccccccccccdULL, 0xbfd3a0e90232184bULL, 0x3c7f6e585666b849ULL }, + { 0xc386666666666666ULL, 0xbfe64080b64705d9ULL, 0xbc89732e5261d935ULL }, + { 0x43a4cccccccccccdULL, 0xbfe2aebf3df4916bULL, 0x3c8257a9dbcfe608ULL }, + { 0xc396666666666666ULL, 0x3feffb8ffd30a77eULL, 0xbc836f7b57c09ddaULL }, + { 0x43b4cccccccccccdULL, 0xbfee55fc106d55f0ULL, 0x3c885a72252865aaULL }, + { 0xc3a6666666666666ULL, 0x3fb0d749e0c3b4a7ULL, 0xbc597900b9f6f0fdULL }, + { 0x43c4cccccccccccdULL, 0xbfe34f8ac636abe3ULL, 0x3c8937b74f68ae73ULL }, + { 0xc3b6666666666666ULL, 0xbfc0cdf315af3596ULL, 0x3c512538ad03ee87ULL }, + { 0x43d4cccccccccccdULL, 0x3feecbe57c52f065ULL, 0xbc8f10b1032a8e5aULL }, + { 0xc3c6666666666666ULL, 0xbfd0a8b6f666a71fULL, 0x3c7c1132e46f8c06ULL }, diff --git a/newlib/libm/machine/riscv/vec_sin.c b/newlib/libm/machine/riscv/vec_sin.c new file mode 100644 index 000000000..c4ea93196 --- /dev/null +++ b/newlib/libm/machine/riscv/vec_sin.c @@ -0,0 +1,219 @@ +/* + * Vectorized sin(double) for the RISC-V Vector extension (RVV). + * + * Exports the vector-function-ABI symbol + * + * vfloat64m1_t _ZGVr1Nxv_sin (vfloat64m1_t x); + * + * following the RISC-V vector function calling convention proposed in + * riscv-non-isa/riscv-elf-psabi-doc PR #455. The mangled name decodes as + * "_ZGV" <isa="r"> <lmul=1> <mask="N" (unmasked)> <len="x" (VLA mode)> + * <param="v" (vector)> "_" <func="sin">, i.e. the LMUL=1, unmasked, + * vector-length-agnostic variant that the LLVM/GCC vectorizers emit when + * lowering a scalar sin() over a double loop. + * + * Accuracy: the worst-case error is <= 1 ULP. See test_vec_sin.c. + * + * This file is only meaningful when compiled for a target that has the V + * extension; on scalar multilibs it compiles to an empty translation unit + * so that a single --enable-vecmath build stays multilib-safe (no -march + * override is applied to this file; it relies on the multilib's own ISA). + */ + +#pragma STDC FP_CONTRACT OFF + +#if defined(__riscv_vector) + +#include <math.h> +#include <stddef.h> +#include <riscv_vector.h> + +/* Argument-reduction and polynomial constants (fdlibm, SunPro). pi/2 is + * split into three 33-bit-significand doubles so that n*P{1,2,3} is exact + * for the fast-path range |n| < 2^20, plus a tiny tail P3t. */ +static const double + INVPIO2 = 6.36619772367581382433e-01, /* 2/pi */ + PIO2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ + PIO2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ + PIO2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ + PIO2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +static const double + half = 5.00000000000000000000e-01, + S1 = -1.66666666666666324348e-01, /* sin kernel coefficients */ + S2 = 8.33333333332248946124e-03, + S3 = -1.98412698298579493134e-04, + S4 = 2.75573137070700676789e-06, + S5 = -2.50507602534068634195e-08, + S6 = 1.58969099521155010221e-10, + one = 1.00000000000000000000e+00, + C1 = 4.16666666666666019037e-02, /* cos kernel coefficients */ + C2 = -1.38888888888741095749e-03, + C3 = 2.48015872894767294178e-05, + C4 = -2.75573143513906633035e-07, + C5 = 2.08757232129817482790e-09, + C6 = -1.13596475577881948265e-11; + +/* Above this magnitude the fast Cody-Waite reduction can no longer keep + * n*PIO2_1 exact, so those lanes fall back to the scalar Payne-Hanek + * reducer __ieee754_rem_pio2(). 2^20 is well inside the exact region. */ +#define VEC_SIN_FAST_LIMIT 1.0e6 + +/* Scalar Payne-Hanek reducer shared with the rest of libm. Returns n and + * writes the reduced argument as the unevaluated sum y[0]+y[1], |y[0]+y[1]| + * <= pi/4. Used only by the slow-path lanes. */ +extern __int32_t __ieee754_rem_pio2 (double, double *); + +/* ---- shared double-double trig kernels (scalar reference form) ---------- + * These evaluate sin/cos on [-pi/4, pi/4] given the reduced argument as a + * head+tail pair (y0 large, y1 the correction). They are identical in + * spirit to fdlibm __kernel_sin/__kernel_cos but always take a tail. */ +static double +sin_kernel_scalar (double y0, double y1) +{ + double z = y0 * y0; + double v = z * y0; + double r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); + return y0 - ((z * (half * y1 - v * r) - y1) - v * S1); +} + +static double +cos_kernel_scalar (double y0, double y1) +{ + double z = y0 * y0; + double r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); + return one - (0.5 * z - (z * r - y0 * y1)); +} + +/* Slow path for a single lane: full-range sin using Payne-Hanek reduction. + * Handles |x| >= VEC_SIN_FAST_LIMIT as well as Inf/NaN (rem_pio2 returns + * x-x = NaN for those, which propagates through the kernels). */ +static double +sin_scalar_slow (double x) +{ + double y[2]; + __int32_t n = __ieee754_rem_pio2 (x, y); + /* Renormalize the pair so the kernel sees a clean head+tail. */ + double s = y[0] + y[1]; + double t = y[1] - (s - y[0]); + double sk = sin_kernel_scalar (s, t); + double ck = cos_kernel_scalar (s, t); + double res = (n & 1) ? ck : sk; + return (n & 2) ? -res : res; +} + +/* ---- vector double-double primitives (exact add with error term) -------- + * Written with discrete vfadd/vfsub intrinsics; no fused multiply-add is + * emitted between them, so the Knuth/Dekker error terms are exact. */ +static inline vfloat64m1_t +vtwo_sum (vfloat64m1_t a, vfloat64m1_t b, vfloat64m1_t *err, size_t vl) +{ + vfloat64m1_t s = __riscv_vfadd_vv_f64m1 (a, b, vl); + vfloat64m1_t bb = __riscv_vfsub_vv_f64m1 (s, a, vl); + vfloat64m1_t ap = __riscv_vfsub_vv_f64m1 (a, __riscv_vfsub_vv_f64m1 (s, bb, vl), vl); + vfloat64m1_t bp = __riscv_vfsub_vv_f64m1 (b, bb, vl); + *err = __riscv_vfadd_vv_f64m1 (ap, bp, vl); + return s; +} + +static inline vfloat64m1_t +vfast_two_sum (vfloat64m1_t a, vfloat64m1_t b, vfloat64m1_t *err, size_t vl) +{ + vfloat64m1_t s = __riscv_vfadd_vv_f64m1 (a, b, vl); + *err = __riscv_vfsub_vv_f64m1 (b, __riscv_vfsub_vv_f64m1 (s, a, vl), vl); + return s; +} + +/* Vectorized sin, LMUL=1, unmasked, VLA mode (RISC-V vector function ABI). */ +vfloat64m1_t +_ZGVr1Nxv_sin (vfloat64m1_t x) +{ + size_t vl = __riscv_vsetvlmax_e64m1 (); + + /* ---- fast path: Cody-Waite reduction with dd error tracking ---------- */ + /* n = round(x * 2/pi); fn = (double)n, ni = (int64)n. */ + vfloat64m1_t prod = __riscv_vfmul_vf_f64m1 (x, INVPIO2, vl); + vint64m1_t ni = __riscv_vfcvt_x_f_v_i64m1_rm (prod, __RISCV_FRM_RNE, vl); + vfloat64m1_t fn = __riscv_vfcvt_f_x_v_f64m1 (ni, vl); + + /* r = x - fn*P1 (exact); accumulate the reduction tail in e. */ + vfloat64m1_t r = __riscv_vfsub_vv_f64m1 (x, __riscv_vfmul_vf_f64m1 (fn, PIO2_1, vl), vl); + vfloat64m1_t e, c; + r = vtwo_sum (r, __riscv_vfmul_vf_f64m1 (fn, -PIO2_2, vl), &c, vl); + e = c; + r = vtwo_sum (r, __riscv_vfmul_vf_f64m1 (fn, -PIO2_3, vl), &c, vl); + e = __riscv_vfadd_vv_f64m1 (e, c, vl); + e = __riscv_vfsub_vv_f64m1 (e, __riscv_vfmul_vf_f64m1 (fn, PIO2_3t, vl), vl); + /* renormalize (r + e) into the reduced argument (y0 + y1). */ + vfloat64m1_t y1; + vfloat64m1_t y0 = vfast_two_sum (r, e, &y1, vl); + + /* sin kernel: y0 - ((z*(half*y1 - v*rs) - y1) - v*S1), z=y0^2, v=z*y0 */ + vfloat64m1_t z = __riscv_vfmul_vv_f64m1 (y0, y0, vl); + vfloat64m1_t v = __riscv_vfmul_vv_f64m1 (z, y0, vl); + vfloat64m1_t rs = __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vf_f64m1 (z, S6, vl), S5, vl), vl), S4, vl), vl), S3, vl), vl), S2, vl); + vfloat64m1_t t1 = __riscv_vfsub_vv_f64m1 ( + __riscv_vfmul_vf_f64m1 (y1, half, vl), __riscv_vfmul_vv_f64m1 (v, rs, vl), vl); + vfloat64m1_t t2 = __riscv_vfsub_vv_f64m1 (__riscv_vfmul_vv_f64m1 (z, t1, vl), y1, vl); + vfloat64m1_t t3 = __riscv_vfsub_vv_f64m1 (t2, __riscv_vfmul_vf_f64m1 (v, S1, vl), vl); + vfloat64m1_t sk = __riscv_vfsub_vv_f64m1 (y0, t3, vl); + + /* cos kernel: one - (0.5*z - (z*rc - y0*y1)) */ + vfloat64m1_t rc = __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vv_f64m1 (z, __riscv_vfadd_vf_f64m1 ( + __riscv_vfmul_vf_f64m1 (z, C6, vl), C5, vl), vl), C4, vl), vl), C3, vl), vl), C2, vl), vl), C1, vl), vl); + vfloat64m1_t ck_inner = __riscv_vfsub_vv_f64m1 ( + __riscv_vfmul_vf_f64m1 (z, 0.5, vl), + __riscv_vfsub_vv_f64m1 (__riscv_vfmul_vv_f64m1 (z, rc, vl), + __riscv_vfmul_vv_f64m1 (y0, y1, vl), vl), vl); + vfloat64m1_t ck = __riscv_vfrsub_vf_f64m1 (ck_inner, one, vl); + + /* Quadrant select: (n & 1) ? cos : sin, then negate if (n & 2). */ + vbool64_t use_cos = __riscv_vmsne_vx_i64m1_b64 ( + __riscv_vand_vx_i64m1 (ni, 1, vl), 0, vl); + vfloat64m1_t res = __riscv_vmerge_vvm_f64m1 (sk, ck, use_cos, vl); + vbool64_t neg = __riscv_vmsne_vx_i64m1_b64 ( + __riscv_vand_vx_i64m1 (ni, 2, vl), 0, vl); + res = __riscv_vmerge_vvm_f64m1 (res, __riscv_vfneg_v_f64m1 (res, vl), neg, vl); + + /* sin is odd, so the result must carry the sign of x when it is exactly + * zero (sin(-0) = -0). The only representable input whose result is an + * exact zero is x = +-0, so applying copysign(res, x) to zero lanes is + * safe and matches the scalar sin(). */ + vbool64_t is_zero = __riscv_vmfeq_vf_f64m1_b64 (res, 0.0, vl); + vfloat64m1_t signed_zero = __riscv_vfsgnj_vv_f64m1 ( + __riscv_vfmv_v_f_f64m1 (0.0, vl), x, vl); + res = __riscv_vmerge_vvm_f64m1 (res, signed_zero, is_zero, vl); + + /* ---- slow path: |x| >= limit, and Inf/NaN (which fail the < test) ---- */ + vfloat64m1_t ax = __riscv_vfabs_v_f64m1 (x, vl); + vbool64_t slow = __riscv_vmnot_m_b64 ( + __riscv_vmflt_vf_f64m1_b64 (ax, VEC_SIN_FAST_LIMIT, vl), vl); + if (__riscv_vcpop_m_b64 (slow, vl) > 0) + { + vuint64m1_t idx = __riscv_vid_v_u64m1 (vl); + for (size_t i = 0; i < vl; i++) + { + double xi = __riscv_vfmv_f_s_f64m1_f64 ( + __riscv_vslidedown_vx_f64m1 (x, i, vl)); + if (!(fabs (xi) < VEC_SIN_FAST_LIMIT)) /* true for large/Inf/NaN */ + { + double ri = sin_scalar_slow (xi); + vbool64_t lane = __riscv_vmseq_vx_u64m1_b64 (idx, i, vl); + res = __riscv_vfmerge_vfm_f64m1 (res, ri, lane, vl); + } + } + } + + return res; +} + +#endif /* __riscv_vector */ + -- 2.39.5