https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87641
Bug ID: 87641 Summary: std::valarray<T>::sum() fails for types where T() is not a neutral element for addition Product: gcc Version: 7.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: frederic.jardon at gmail dot com Target Milestone: --- ** Compiler version and command-line used are at the end of this message ** The following code: #include <iostream> #include <valarray> using namespace std; int main() { valarray<int> Y(0xf00d, 1); valarray<valarray<int>> X(Y, 1); cout << "X[0].size() = " << X[0].size() << '\n'; cout << "X.sum().size() = " << X.sum().size() << '\n'; } Should print (expected): X[0].size() = 1 X.sum().size() = 1 But it prints (actual): X[0].size() = 1 X.sum().size() = 0 I tracked the issue to this function: // // Compute the sum of elements in range [__f, __l) // This is a naive algorithm. It suffers from cancelling. // In the future try to specialize // for _Tp = float, double, long double using a more accurate // algorithm. // template<typename _Tp> inline _Tp __valarray_sum(const _Tp* __f, const _Tp* __l) { _Tp __r = _Tp(); while (__f != __l) __r += *__f++; return __r; } The implementation assumes that: _Tp __r = _Tp(); __r += *__f; has the same value than *__f, but this is not the case if _Tp() is not a neutral element for addition. For instance a default constructed std::valarray<T> has a size of 0, and the end result will have a size of 0 even though the *__f may be a valarray of size 1. The same problem could occur if _Tp was a custom floating-point-like type whose default constructed value was NaN. Reference to the standard: 26.6.2.8 > This function may only be instantiated for a type T to which operator+= can be > applied. This function returns the sum of all the elements of the array. If > the array has length 0, the behavior is undefined. If the array has length 1, > sum() returns the value of element 0. Otherwise, the returned value is > calculated by applying operator+= to a copy of an element of the array and all > other elements of the array in an unspecified order. The standard clearly state that the initial value of __r should be a **copy of an element of the array** If you provide me a link on how to submit a pull-request I can work on providing a patch. I have reports that other compilers (clang, cl) doesn't exhibit this behavior. Thanks for your attention and the good compiler :) Frederic Jardon ======= compiler / compilation information $ uname -a CYGWIN_NT-10.0 DD1K7KF2 2.11.1(0.329/5/3) 2018-09-05 10:24 x86_64 Cygwin $ LANG="" gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/lto-wrapper.exe Target: x86_64-pc-cygwin Configured with: /cygdrive/i/szsz/tmpp/gcc/gcc-7.3.0-3.x86_64/src/gcc-7.3.0/configure --srcdir=/cygdrive/i/szsz/tmpp/gcc/gcc-7.3.0-3.x86_64/src/gcc-7.3.0 --prefix=/usr --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target=x86_64-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --libexecdir=/usr/lib --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --enable-__cxa_atexit --with-dwarf2 --with-tune=generic --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libcilkrts --enable-libgomp --enable-libitm --enable-libquadmath --enable-libquadmath-support --disable-libssp --enable-libada --disable-symvers --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --enable-linker-build-id --with-default-libstdcxx-abi=gcc4-compatible --enable-libstdcxx-filesystem-ts Thread model: posix gcc version 7.3.0 (GCC) $ g++ valarray-sum.cpp -save-temps -o valarray-sum $ ./valarray-sum.exe X[0].size() = 1 X.sum().size() = 0 I also reproduced the same bug on another system: $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabi/4.9/lto-wrapper Target: arm-linux-gnueabi Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10+deb8u1' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-armel/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-armel --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-armel --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-sjlj-exceptions --with-arch=armv4t --with-float=soft --enable-checking=release --build=arm-linux-gnueabi --host=arm-linux-gnueabi --target=arm-linux-gnueabi Thread model: posix gcc version 4.9.2 (Debian 4.9.2-10+deb8u1) $ uname -a Linux DiskStation 2.6.32.12 #23824 Fri Sep 7 12:47:49 CST 2018 armv5tel GNU/Linux