Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #121694 > unrolled thread
| Started by | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| First post | 2025-02-24 11:48 +0100 |
| Last post | 2025-03-09 14:56 +0200 |
| Articles | 20 on this page of 134 — 8 participants |
Back to article view | Back to comp.lang.c++
a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-24 11:48 +0100
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-24 12:00 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-24 13:48 +0100
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-24 13:09 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-24 14:22 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-24 17:13 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-24 16:19 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-24 17:52 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-25 09:09 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-25 16:17 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-25 17:26 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-25 16:45 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-25 16:57 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-25 19:17 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-25 18:58 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-26 00:36 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-26 04:15 +0100
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-26 08:16 +0000
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-26 14:27 +0200
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-26 14:39 +0000
FP_CONTRACT was : a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-28 16:28 +0200
Re: FP_CONTRACT was : a MSVC and glibc-compatible fmod() Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-03-01 08:35 -0800
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-24 16:22 +0200
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-24 15:10 +0000
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-24 17:33 +0200
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-24 16:48 +0000
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-02-24 22:21 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-25 07:37 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-02-25 23:03 +0000
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-26 02:00 +0200
Re: a MSVC and glibc-compatible fmod() Wuns Haerst <Wuns.Haerst@wurstfabrik.at> - 2025-02-26 04:01 +0100
Re: a MSVC and glibc-compatible fmod() Muttley@DastardlyHQ.org - 2025-02-25 08:24 +0000
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-02-27 21:16 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-28 07:59 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-02-28 12:35 +0200
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-02-28 18:12 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-28 19:23 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-02-28 18:30 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-28 19:31 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-02-28 19:47 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-02-28 20:49 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-03-01 14:37 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-01 16:58 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-03-01 17:11 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-01 21:02 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-03-01 20:32 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-01 21:37 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-03-01 20:45 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 09:40 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-01 22:55 +0200
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 18:54 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 17:59 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 15:41 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 17:10 +0100
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-03-02 16:22 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 17:26 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 19:07 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 18:09 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 18:11 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 19:52 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 18:55 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 20:09 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 19:14 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 19:57 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 22:58 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-03 12:52 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-03 18:10 +0200
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-03 23:55 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-07 09:51 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-03 18:20 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-03 17:30 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-03 19:27 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-03 18:39 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-03 02:01 +0200
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 19:37 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 18:41 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-02 20:00 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-02 19:01 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 01:31 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 07:41 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 11:08 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 10:31 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 11:46 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 10:54 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 12:09 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 11:21 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 14:09 +0200
Re: a MSVC and glibc-compatible fmod() Mr Flibble <leigh@i42.co.uk> - 2025-03-09 15:26 +0000
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 17:02 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 19:55 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 19:10 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 19:27 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 17:23 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 20:04 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 19:11 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 20:11 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 07:24 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 10:46 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 14:26 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 13:45 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 16:33 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 15:46 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 16:59 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 16:11 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 17:43 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 17:13 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 19:51 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 19:00 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 20:38 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 22:34 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 22:36 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 12:47 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 23:52 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 23:57 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-11 09:34 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 12:29 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-11 12:12 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 13:34 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-11 13:10 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 14:55 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-11 14:08 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 15:46 +0200
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 13:51 +0200
Re: a MSVC and glibc-compatible fmod() James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-03-11 14:21 -0400
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-11 20:28 +0200
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-16 13:48 +0200
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-10 13:17 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 12:53 +0100
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-10 12:54 +0100
Re: a MSVC and glibc-compatible fmod() wij <wyniijj5@gmail.com> - 2025-03-09 18:51 +0800
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 12:56 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 14:23 +0200
Re: a MSVC and glibc-compatible fmod() Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-09 13:39 +0100
Re: a MSVC and glibc-compatible fmod() Michael S <already5chosen@yahoo.com> - 2025-03-09 14:56 +0200
Page 5 of 7 — ← Prev page 1 2 3 4 [5] 6 7 Next page →
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-09 11:08 +0200 |
| Message-ID | <20250309110801.0000131a@yahoo.com> |
| In reply to | #121902 |
On Sun, 9 Mar 2025 07:41:26 +0100
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> Am 09.03.2025 um 00:31 schrieb Michael S:
> > This code does not work in plenty of cases. It seems, your test
> > vectors have poor coverage.
> > Try, for example, x=1.8037919852882307, y=2.22605637008665934e-194
>
> cout << hexfloat << myFmod( 1.8037919852882307,
> 2.22605637008665934e-194 ) << endl;
> cout << hexfloat << fmod( 1.8037919852882307,
> 2.22605637008665934e-194 ) << endl;
>
>
> Prints the same result under Linux and Windows.
>
What it prints under Linux is irrelevant. Under Linux it compiles your
original version or its close equivalent that is slow, ugly, but not
buggy.
What it prints under Windows when compiled with clang or gcc is also
irrelevant for the same reason.
The bug is in the new code that is exposed only when compiled with MSVC
compiler.
-- foo.cpp
#include <cstdint>
#include <cassert>
#include <cfenv>
#include <limits>
#include <bit>
using namespace std;
template<bool _32 = false>
double xMyFmod( double x, double y )
{
constexpr uint64_t
SIGN = 1ull << 63,
IMPLICIT = 1ull << 52,
MANT = IMPLICIT - 1,
QBIT = 1ull << 51;
uint64_t const
binX = bit_cast<uint64_t>( x ),
binY = bit_cast<uint64_t>( y );
static auto abs = []( uint64_t m ) { return m & ~SIGN; };
auto isNaN = []( uint64_t m ) { return abs( m ) >=
0x7FF0000000000001u; }; auto isSig = []( uint64_t m ) { return !(m &
QBIT); }; if( isNaN( binX ) ) [[unlikely]] // x == NaN
#if defined(_MSC_VER)
return bit_cast<double>( isNaN( binY ) ? binY | binX &
binY & QBIT : binX );
#else
{
if( isSig( binX ) || isNaN( binY ) && isSig( binY ) )
[[unlikely]] feraiseexcept( FE_INVALID );
return bit_cast<double>( binX | QBIT );
}
#endif
auto isInf = []( uint64_t m ) { return abs( m ) ==
0x7FF0000000000000u; }; if( isNaN( binY ) ) [[unlikely]] // x != NaN ||
y == NaN #if defined(_MSC_VER)
{
if constexpr( _32 )
if( isInf( binX ) )
feraiseexcept( FE_INVALID );
return y;
}
#else
{
if( isSig( binY ) ) [[unlikely]]
feraiseexcept( FE_INVALID );
return bit_cast<double>( binY | QBIT );
}
#endif
if( isInf( binX ) ) // x == Inf
{
feraiseexcept( FE_INVALID );
#if defined(_MSC_VER)
return bit_cast<double>( binX & ~MANT | QBIT );
#else
return -numeric_limits<double>::quiet_NaN();
#endif
}
if( !abs( binY ) ) [[unlikely]] // y == 0
{
feraiseexcept( FE_INVALID );
#if defined(_MSC_VER)
return numeric_limits<double>::quiet_NaN();
#else
return -numeric_limits<double>::quiet_NaN();
#endif
}
if( !abs( binX ) || isInf( binY ) ) [[unlikely]] // x == 0 || y
== Inf return x;
auto exp = []( uint64_t b ) -> int { return b >> 52 & 0x7FF; };
int
expX = exp( binX ),
expY = exp( binY );
auto mant = []( uint64_t b ) { return b & MANT; };
uint64_t
mantX = mant( binX ),
mantY = mant( binY );
int headBits = 11;
static auto normalize = [&]( int &exp, uint64_t &mant )
{
unsigned shift = countl_zero( mant ) - headBits;
mant <<= shift;
exp -= shift;
};
auto build = []( int &exp, uint64_t &mant )
{
if( exp ) [[likely]]
mant |= IMPLICIT;
else
{
exp = 1;
normalize( exp, mant );
}
};
build( expX, mantX );
build( expY, mantY );
int
tailX = countr_zero( mantX ),
tailY = countr_zero( mantY ),
tailBits = tailX <= tailY ? tailX : tailY;
headBits += tailBits;
mantX >>= tailBits;
mantY >>= tailBits;
uint64_t signX = binX & SIGN;
int expDiff;
#if defined(_MSC_VER)
while( (expDiff = expX - expY) > 63 )
{
unsigned long long hi = mantX >> 1, lo = mantX << 63,
remainder; (void)_udiv128( hi, lo, mantY, &remainder );
expX -= 63;
mantX = remainder;
normalize( expX, mantX );
}
#endif
while( (expDiff = expX - expY) > 0 )
{
unsigned bits = expDiff <= headBits ? expDiff :
headBits; if( !(mantX = (mantX << bits) % mantY) ) [[unlikely]]
return bit_cast<double>( signX );
expX -= bits;
normalize( expX, mantX );
}
if( !expDiff && mantX >= mantY ) [[unlikely]]
if( (mantX -= mantY) ) [[likely]]
normalize( expX, mantX );
else
return bit_cast<double>( signX );
mantX <<= tailBits;
mantY <<= tailBits;
if( expX <= 0 ) [[unlikely]]
{
assert(expX >= -51);
mantX = mantX >> (unsigned)(-expX + 1);
expX = 0;
}
return bit_cast<double>( signX | (uint64_t)expX << 52 | mantX &
MANT ); }
double myFmod( double x, double y )
{
return xMyFmod( x, y );
}
inline float myFmod( float x, float y )
{
return (float)xMyFmod<true>( (double)x, (double)y );
}
-- end of foo.cpp
-- bar.cpp
#include <iostream>
using namespace std;
double myFmod( double x, double y );
int main()
{
cout << hexfloat << myFmod(
1.8037919852882307,
2.22605637008665934e-194 ) << endl;
cout << hexfloat << fmod( 1.8037919852882307,
2.22605637008665934e-194 ) << endl;
}
-- end of foo.cpp
W:\foobar>cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.41.34120 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
W:\foobar>cl -nologo -O2 -EHsc -std:c++20 foo.cpp bar.cpp
foo.cpp
bar.cpp
Generating Code...
W:\foobar>foo
0x1.0000000000000p-696
0x0.0000000000000p+0
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 10:31 +0100 |
| Message-ID | <vqjn4h$lmd1$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121903 |
This prints the same result (0.0) under Windows and Linux:
double myFmod( double x, double y )
{
constexpr uint64_t
SIGN = 1ull << 63,
IMPLICIT = 1ull << 52,
MANT = IMPLICIT - 1,
QBIT = 1ull << 51;
uint64_t const
binX = bit_cast<uint64_t>( x ),
binY = bit_cast<uint64_t>( y );
static auto abs = []( uint64_t m ) { return m & ~SIGN; };
auto isNaN = []( uint64_t m ) { return abs( m ) >= 0x7FF0000000000001u; };
auto isSig = []( uint64_t m ) { return !(m & QBIT); };
if( isNaN( binX ) ) [[unlikely]] // x == NaN
#if defined(_MSC_VER)
return bit_cast<double>( isNaN( binY ) ? binY | binX & binY & QBIT :
binX );
#else
{
if( isSig( binX ) || isNaN( binY ) && isSig( binY ) ) [[unlikely]]
feraiseexcept( FE_INVALID );
return bit_cast<double>( binX | QBIT );
}
#endif
if( isNaN( binY ) ) [[unlikely]] // x != NaN || y == NaN
#if defined(_MSC_VER)
return y;
#else
{
if( isSig( binY ) ) [[unlikely]]
feraiseexcept( FE_INVALID );
return bit_cast<double>( binY | QBIT );
}
#endif
auto isInf = []( uint64_t m ) { return abs( m ) == 0x7FF0000000000000u; };
if( isInf( binX ) ) // x == Inf
{
feraiseexcept( FE_INVALID );
#if defined(_MSC_VER)
return bit_cast<double>( binX & ~MANT | QBIT );
#else
return -numeric_limits<double>::quiet_NaN();
#endif
}
if( !abs( binY ) ) [[unlikely]] // y == 0
{
feraiseexcept( FE_INVALID );
#if defined(_MSC_VER)
return numeric_limits<double>::quiet_NaN();
#else
return -numeric_limits<double>::quiet_NaN();
#endif
}
if( !abs( binX ) || isInf( binY ) ) [[unlikely]] // x == 0 || y == Inf
return x;
auto exp = []( uint64_t b ) -> int { return b >> 52 & 0x7FF; };
int
expX = exp( binX ),
expY = exp( binY );
auto mant = []( uint64_t b ) { return b & MANT; };
uint64_t
mantX = mant( binX ),
mantY = mant( binY );
int headBits = 11;
static auto normalize = [&]( int &exp, uint64_t &mant )
{
unsigned shift = countl_zero( mant ) - headBits;
mant <<= shift;
exp -= shift;
};
auto build = []( int &exp, uint64_t &mant )
{
if( exp ) [[likely]]
mant |= IMPLICIT;
else
{
exp = 1;
normalize( exp, mant );
}
};
build( expX, mantX );
build( expY, mantY );
int
tailX = countr_zero( mantX ),
tailY = countr_zero( mantY ),
tailBits = tailX <= tailY ? tailX : tailY;
mantX >>= tailBits;
mantY >>= tailBits;
headBits += tailBits;
uint64_t signX = binX & SIGN;
int expDiff;
#if defined(_MSC_VER) && !defined(__llvm__) && defined(_M_X64)
while( (expDiff = expX - expY) > 0 )
{
unsigned bits = expDiff <= 63 ? expDiff : 63;
unsigned long long hi = mantX >> 64 - bits, lo = mantX << bits, remainder;
(void)_udiv128( hi, lo, mantY, &remainder );
if( !remainder ) [[unlikely]]
return bit_cast<double>( signX );
mantX = remainder;
expX -= bits;
normalize( expX, mantX );
}
#else
while( (expDiff = expX - expY) > 0 )
{
unsigned bits = expDiff <= headBits ? expDiff : headBits;
if( !(mantX = (mantX << bits) % mantY) ) [[unlikely]]
return bit_cast<double>( signX );
expX -= bits;
normalize( expX, mantX );
}
#endif
if( !expDiff && mantX >= mantY ) [[unlikely]]
if( (mantX -= mantY) ) [[likely]]
normalize( expX, mantX );
else
return bit_cast<double>( signX );
mantX <<= tailBits;
mantY <<= tailBits;
if( expX <= 0 ) [[unlikely]]
{
assert(expX >= -51);
mantX = mantX >> (unsigned)(-expX + 1);
expX = 0;
}
return bit_cast<double>( signX | (uint64_t)expX << 52 | mantX & MANT );
}
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-09 11:46 +0200 |
| Message-ID | <20250309114624.00000e85@yahoo.com> |
| In reply to | #121904 |
On Sun, 9 Mar 2025 10:31:02 +0100 Bonita Montero <Bonita.Montero@gmail.com> wrote: > This prints the same result (0.0) under Windows and Linux: > I am no longer going to look at your code until you start posting full files, with all includes and using directives.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 10:54 +0100 |
| Message-ID | <vqjogs$lto0$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121905 |
Am 09.03.2025 um 10:46 schrieb Michael S: >> This prints the same result (0.0) under Windows and Linux: > I am no longer going to look at your code until you start posting full > files, with all includes and using directives. You could simply replace the single function I've shown.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-09 12:09 +0200 |
| Message-ID | <20250309120931.0000036f@yahoo.com> |
| In reply to | #121906 |
On Sun, 9 Mar 2025 10:54:40 +0100 Bonita Montero <Bonita.Montero@gmail.com> wrote: > Am 09.03.2025 um 10:46 schrieb Michael S: > > >> This prints the same result (0.0) under Windows and Linux: > > > I am no longer going to look at your code until you start posting > > full files, with all includes and using directives. > > You could simply replace the single function I've shown. > I can. I don't want to do it. You want me to look at/test your code? You post full code. Simple, isn't it?
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 11:21 +0100 |
| Message-ID | <vqjq3v$m7h6$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121907 |
Am 09.03.2025 um 11:09 schrieb Michael S: > On Sun, 9 Mar 2025 10:54:40 +0100 > Bonita Montero <Bonita.Montero@gmail.com> wrote: > >> Am 09.03.2025 um 10:46 schrieb Michael S: >> >>>> This prints the same result (0.0) under Windows and Linux: >> >>> I am no longer going to look at your code until you start posting >>> full files, with all includes and using directives. >> >> You could simply replace the single function I've shown. >> > > I can. I don't want to do it. > You want me to look at/test your code? You post full code. > Simple, isn't it? I've read you don't trust my tests, so use your own with myFmod.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-09 14:09 +0200 |
| Message-ID | <20250309140932.0000303d@yahoo.com> |
| In reply to | #121908 |
On Sun, 9 Mar 2025 11:21:55 +0100 Bonita Montero <Bonita.Montero@gmail.com> wrote: > Am 09.03.2025 um 11:09 schrieb Michael S: > > On Sun, 9 Mar 2025 10:54:40 +0100 > > Bonita Montero <Bonita.Montero@gmail.com> wrote: > > > >> Am 09.03.2025 um 10:46 schrieb Michael S: > >> > >>>> This prints the same result (0.0) under Windows and Linux: > >> > >>> I am no longer going to look at your code until you start posting > >>> full files, with all includes and using directives. > >> > >> You could simply replace the single function I've shown. > >> > > > > I can. I don't want to do it. > > You want me to look at/test your code? You post full code. > > Simple, isn't it? > > I've read you don't trust my tests, so use your own with myFmod. > ok. I was too curios :( This version produces correct results both when compiled under MSVC and when compiled with other compilers. It is a little faster too. With MSVC on old Intel CPU it is only 2.5 times slower than standard library in relevant range of x/y. Previous version was 3.4 times slower. With gcc and clang it is still more than 6 times slower than standard library. The coding style is now less insane. Measurements in nsec. First result - Intel Skylake at 4.25 GHz Second result - AMD Zen3 at 3.7 GHz abs(x/y) in range that matters [0.5:2**53]: Standard MSVC Library - 11.1 10.4 Standard gnu Library - 5.4 10.7 Yours (MSVc) - 27.6 11.5 Yours (gcc) - 36.4 23.7 Yours (clang) - 37.4 24.3 abs(x/y) in full range [2**-2090:2**2090]: Standard MSVC Library - 109.4 153.5 Standard glib Library - 102.3 155.5 Yours (MSVc) - 134.9 52.6 Yours (gcc) - 284.7 151.8 Yours (clang) - 285.2 156.5
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <leigh@i42.co.uk> |
|---|---|
| Date | 2025-03-09 15:26 +0000 |
| Message-ID | <cocrsjdgqtmvrh221fbhje39aabopvb87h@4ax.com> |
| In reply to | #121911 |
On Sun, 9 Mar 2025 14:09:32 +0200, Michael S <already5chosen@yahoo.com> wrote: >On Sun, 9 Mar 2025 11:21:55 +0100 >Bonita Montero <Bonita.Montero@gmail.com> wrote: > >> Am 09.03.2025 um 11:09 schrieb Michael S: >> > On Sun, 9 Mar 2025 10:54:40 +0100 >> > Bonita Montero <Bonita.Montero@gmail.com> wrote: >> > >> >> Am 09.03.2025 um 10:46 schrieb Michael S: >> >> >> >>>> This prints the same result (0.0) under Windows and Linux: >> >> >> >>> I am no longer going to look at your code until you start posting >> >>> full files, with all includes and using directives. >> >> >> >> You could simply replace the single function I've shown. >> >> >> > >> > I can. I don't want to do it. >> > You want me to look at/test your code? You post full code. >> > Simple, isn't it? >> >> I've read you don't trust my tests, so use your own with myFmod. >> > >ok. I was too curios :( >This version produces correct results both when compiled under MSVC and >when compiled with other compilers. It is a little faster too. >With MSVC on old Intel CPU it is only 2.5 times slower than standard >library in relevant range of x/y. Previous version was 3.4 times >slower. >With gcc and clang it is still more than 6 times slower than standard >library. >The coding style is now less insane. > >Measurements in nsec. >First result - Intel Skylake at 4.25 GHz >Second result - AMD Zen3 at 3.7 GHz > >abs(x/y) in range that matters [0.5:2**53]: >Standard MSVC Library - 11.1 10.4 >Standard gnu Library - 5.4 10.7 >Yours (MSVc) - 27.6 11.5 >Yours (gcc) - 36.4 23.7 >Yours (clang) - 37.4 24.3 > >abs(x/y) in full range [2**-2090:2**2090]: >Standard MSVC Library - 109.4 153.5 >Standard glib Library - 102.3 155.5 >Yours (MSVc) - 134.9 52.6 >Yours (gcc) - 284.7 151.8 >Yours (clang) - 285.2 156.5 So it is slow ergo a pointless alternative to what we already have. /Flibble
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 17:02 +0100 |
| Message-ID | <vqke2j$qa42$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121915 |
Am 09.03.2025 um 16:26 schrieb Mr Flibble: > So it is slow ergo a pointless alternative to what we already have. glibc does it nearly in the same way I do it because the FMA-solution isn't portable. If fma( a, b, c ) is substituted with a * b + c because there's no proper CPU-instruction the whole issue doesn't work. And with support for _udiv128 my solution has about the same performance like the Michael's solution with clang++ 18.1.7.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-09 19:55 +0200 |
| Message-ID | <20250309195521.00003ec4@yahoo.com> |
| In reply to | #121916 |
On Sun, 9 Mar 2025 17:02:32 +0100 Bonita Montero <Bonita.Montero@gmail.com> wrote: > Am 09.03.2025 um 16:26 schrieb Mr Flibble: > > > So it is slow ergo a pointless alternative to what we already have. > > > > glibc does it nearly in the same way I do it because the FMA-solution > isn't portable. > If fma( a, b, c ) is substituted with a * b + c > because there's no proper CPU-instruction the whole issue doesn't > work. FMA solution is portable to any standard-complaint C environment. By standard, it has to work regardless of presence of absence of FMA hardware. In absence of FMA hardware it is expected to be rather slow, but still has to produce correct results. Unfortunately, Microsoft's library implementation of fma() does not work correctly on non-FMA hardware. In case when x*y and z have different signs it fairs somewhat better than when they have the same sign, but still not good enough. So it goes ): Since under msys2 both gcc and clang rely on Microsoft's library, they also do not work correctly on non-FMA CPUs. It would be interesting to test if glibc is better in that regard. Unfortunately, right now I have no access to any glibc-based system that runs on sufficiently old hardware. Anyway, despite all their problems, fma() based solutions are written in standard C language. The same can't be said about solutions that use any variant of 128-bit integer arithmetic, either in form of Gnu __int128 or in form of Microsoft's intrinsic functions. I think that an absence of standardized 128-bit integer math in both C and C++ sucks, but I can not change the fact. > And with support for _udiv128 my solution has about the same > performance like the Michael's solution with clang++ 18.1.7. > I readily admitted that from practical perspective all 3 solutions that I posted here (one of each is incorrect) are pointless. I do have variants that are usefully faster than Standard library for relevant x/y ratios, but I didn't post them here. They achieve the speed boost via direct manipulation of binary64 bit patterns. I am not sure that such solutions are on topic in c.l.c++. Still, what you say about relative speed is true only on newer CPUs and only when compiled with MSVC. On Older CPUs, like Intel Skylake, which is pretty fast CPU on absolute scale and which still constitutes big portion of installed base, your code is significantly slower than mine. Same for newer CPUs with compilers that do not support native long division. Here is comparison vs code that I posted here at 2025-03-03 18:10:08 +0200: Measurements in nsec. First result - Intel Skylake at 4.25 GHz Second result - AMD Zen3 at 3.7 GHz abs(x/y) in range that matters [0.5:2**53]: Standard MSVC Library - 11.1 10.4 Standard gnu Library - 5.4 10.7 Yours (MSVc) - 27.6 11.5 Yours (gcc) - 36.4 23.7 Yours (clang) - 37.4 24.3 my (MSVc) - 10.7 11.3 my (gcc) - 7.7 7.6 my (clang) - 6.3 7.5 abs(x/y) in full range [2**-2090:2**2090]: Standard MSVC Library - 109.4 153.5 Standard glib Library - 102.3 155.5 Yours (MSVc) - 134.9 52.6 Yours (gcc) - 284.7 151.8 Yours (clang) - 285.2 156.5 my (MSVc) - 62.1 61.1 my (gcc) - 60.8 59.1 my (clang) - 59.9 59.3
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 19:10 +0100 |
| Message-ID | <vqklia$rlr2$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121918 |
Am 09.03.2025 um 18:55 schrieb Michael S: > In absence of FMA hardware it is expected to be rather slow, but still > has to produce correct results. Yes, extremely slow. > It would be interesting to test if glibc is better in that regard. glibc uses integer-operations. > I readily admitted that from practical perspective all 3 solutions > that I posted here (one of each is incorrect) are pointless. I've recently posted a comparison of your solution against mine on a Zen4-CPU with MSVC. Your solution is equally performant with close exponents (0x3FF to 0x433) if I compile it unter WSL2 with g++-12. The problem with MSVC is that the trunc() function is extremely slow. In my implementation of your idea (x86 FMA) I use my own function xtrunc which makes the code twice as fast. > Still, what you say about relative speed is true only on newer CPUs and > only when compiled with MSVC. ... I haven't managed to write a 128 / 64 -> 64:64 division with Linux -compilers. __int128 doesn't work since the compiler doesn't see that the result fits in 64 bit and calls a library function for the division which does the subtract and shift steps manually. But your solution has about the same performance on Linux with g++12 like my code with MSVC on a Zen4-CPU.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 19:27 +0100 |
| Message-ID | <vqkmi9$s6jt$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121920 |
Am 09.03.2025 um 19:10 schrieb Bonita Montero:
> I've recently posted a comparison of your solution against mine on
> a Zen4-CPU with MSVC. Your solution is equally performant with close
> exponents (0x3FF to 0x433) if I compile it unter WSL2 with g++-12.
> The problem with MSVC is that the trunc() function is extremely slow.
> In my implementation of your idea (x86 FMA) I use my own function
> xtrunc which makes the code twice as fast.
This is even somewhat faster since I'm using the ROUNDSD instruction
of SSE 4.1; but the difference to my xtrunc-solution is only 13%:
double fmody( double x, double y )
{
if( isnan( x ) ) [[unlikely]]
return x;
if( isnan( y ) ) [[unlikely]]
return y;
if( isinf( x ) || !y ) [[unlikely]]
{
feraiseexcept( FE_INVALID );
return numeric_limits<double>::quiet_NaN();
}
if( !x || isinf( y ) ) [[unlikely]]
return x;
uint64_t sign = bit_cast<uint64_t>( x ) & numeric_limits<int64_t>::min();
x = abs( x );
y = abs( y );
int oldCsr = _mm_getcsr();
constexpr int CHOP = 0x6000;
_mm_setcsr( oldCsr | CHOP );
constexpr uint64_t
EXP = -(1ll << 52),
MANT = ~EXP;
uint64_t binY = bit_cast<uint64_t>( y );
int64_t expY = binY & EXP;
if( !expY ) [[unlikely]]
expY = (uint64_t)(0 - (countl_zero( binY & MANT ) - 12)) << 52;
while( x >= y )
{
auto floor = []( double value )
{
__m128d m;
#if defined(_MSC_VER)
m.m128d_f64[0] = value;
_mm_floor_sd(m, m);
return m.m128d_f64[0];
#else
m[0] = value;
_mm_floor_sd(m, m);
return m[0];
#endif
};
uint64_t yExpAdd = 0;
double div = x / y;
if( div < 0x1.FFFFFFFFFFFFFp+1023 ) [[likely]]
div = xtrunc( div );
else
{
uint64_t
binX = bit_cast<uint64_t>( x ),
newExp = expY + (54ull << 52);
yExpAdd = (binX & EXP) - newExp;
div = xtrunc( bit_cast<double>( newExp | binX & MANT ) / y );
}
auto xfma = []( double a, double b, double c )
{
__m128d mult1, mult2, add;
#if defined(_MSC_VER)
mult1.m128d_f64[0] = a;
mult2.m128d_f64[0] = b;
add.m128d_f64[0] = c;
return _mm_fmadd_sd( mult1, mult2, add ).m128d_f64[0];
#else
mult1[0] = a;
mult2[0] = b;
add[0] = c;
return _mm_fmadd_sd( mult1, mult2, add )[0];
#endif
};
x = xfma( div, -bit_cast<double>( binY + yExpAdd ), x );
if( !x ) [[unlikely]]
return bit_cast<double>( sign );
}
_mm_setcsr( oldCsr );
return bit_cast<double>( sign | bit_cast<uint64_t>( x ) );
}
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 17:23 +0100 |
| Message-ID | <vqkf9p$qh6l$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121911 |
Am 09.03.2025 um 13:09 schrieb Michael S:
> Measurements in nsec.
> First result - Intel Skylake at 4.25 GHz
> Second result - AMD Zen3 at 3.7 GHz
>
> abs(x/y) in range that matters [0.5:2**53]:
> Standard MSVC Library - 11.1 10.4
> Standard gnu Library - 5.4 10.7
> Yours (MSVc) - 27.6 11.5
> Yours (gcc) - 36.4 23.7
> Yours (clang) - 37.4 24.3
>
> abs(x/y) in full range [2**-2090:2**2090]:
> Standard MSVC Library - 109.4 153.5
> Standard glib Library - 102.3 155.5
> Yours (MSVc) - 134.9 52.6
> Yours (gcc) - 284.7 151.8
> Yours (clang) - 285.2 156.5
With MSVC and an arbitrary combination of finite x and y on my
Zen4-machine:
your fmod: 77.1214
my: 38.4486
With MSVC and an arbitrary combination of finite x with exponents
ranging from 0x3FF to 0x433 (close exponents) on my Zen4-machine:
your fmod: 23.6423
my: 9.79146
This is a nearly proper implementation of your idea with FMA-intrinsics
and SSE/AVX control register access:
double fmody( double x, double y )
{
if( isnan( x ) ) [[unlikely]]
return x;
if( isnan( y ) ) [[unlikely]]
return y;
if( isinf( x ) || !y ) [[unlikely]]
{
feraiseexcept( FE_INVALID );
return numeric_limits<double>::quiet_NaN();
}
if( !x || isinf( y ) ) [[unlikely]]
return x;
uint64_t sign = bit_cast<uint64_t>( x ) & numeric_limits<int64_t>::min();
x = abs( x );
y = abs( y );
int oldCsr = _mm_getcsr();
constexpr int CHOP = 0x6000;
_mm_setcsr( oldCsr | CHOP );
constexpr uint64_t
EXP = -(1ll << 52),
MANT = ~EXP;
uint64_t binY = bit_cast<uint64_t>( y );
int64_t expY = binY & EXP;
if( !expY ) [[unlikely]]
expY = (uint64_t)(0 - (countl_zero( binY & MANT ) - 12)) << 52;
while( x >= y )
{
uint64_t yExpAdd = 0;
double div = x / y;
if( div < 0x1.FFFFFFFFFFFFFp+1023 ) [[likely]]
div = xtrunc( div );
else
{
uint64_t
binX = bit_cast<uint64_t>( x ),
newExp = expY + (54ull << 52);
yExpAdd = (binX & EXP) - newExp;
div = xtrunc( bit_cast<double>( newExp | binX & MANT ) / y );
}
__m128d mult1, mult2, add;
#if defined(_MSC_VER)
mult1.m128d_f64[0] = div;
mult2.m128d_f64[0] = -bit_cast<double>( binY + yExpAdd );
add.m128d_f64[0] = x;
x = _mm_fmadd_sd( mult1, mult2, add ).m128d_f64[0];
#else
mult1[0] = div;
mult2[0] = -bit_cast<double>( binY + yExpAdd );
add[0] = x;
x = _mm_fmadd_sd( mult1, mult2, add )[0];
#endif
if( !x ) [[unlikely]]
return bit_cast<double>( sign );
}
_mm_setcsr( oldCsr );
return bit_cast<double>( sign | bit_cast<uint64_t>( x ) );
}
The only thing that doesn't work currently is the support for denormal
values.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-09 20:04 +0200 |
| Message-ID | <20250309200407.0000036c@yahoo.com> |
| In reply to | #121917 |
On Sun, 9 Mar 2025 17:23:26 +0100
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> Am 09.03.2025 um 13:09 schrieb Michael S:
>
> > Measurements in nsec.
> > First result - Intel Skylake at 4.25 GHz
> > Second result - AMD Zen3 at 3.7 GHz
> >
> > abs(x/y) in range that matters [0.5:2**53]:
> > Standard MSVC Library - 11.1 10.4
> > Standard gnu Library - 5.4 10.7
> > Yours (MSVc) - 27.6 11.5
> > Yours (gcc) - 36.4 23.7
> > Yours (clang) - 37.4 24.3
> >
> > abs(x/y) in full range [2**-2090:2**2090]:
> > Standard MSVC Library - 109.4 153.5
> > Standard glib Library - 102.3 155.5
> > Yours (MSVc) - 134.9 52.6
> > Yours (gcc) - 284.7 151.8
> > Yours (clang) - 285.2 156.5
>
> With MSVC and an arbitrary combination of finite x and y on my
> Zen4-machine:
>
> your fmod: 77.1214
> my: 38.4486
>
> With MSVC and an arbitrary combination of finite x with exponents
> ranging from 0x3FF to 0x433 (close exponents) on my Zen4-machine:
>
> your fmod: 23.6423
> my: 9.79146
>
It looks like you didn't pay attention to a "flipflop" version that I
posted at 2025-03-03 18:10:08
> This is a nearly proper implementation of your idea with
> FMA-intrinsics and SSE/AVX control register access:
>
> double fmody( double x, double y )
> {
> if( isnan( x ) ) [[unlikely]]
> return x;
> if( isnan( y ) ) [[unlikely]]
> return y;
> if( isinf( x ) || !y ) [[unlikely]]
> {
> feraiseexcept( FE_INVALID );
> return numeric_limits<double>::quiet_NaN();
> }
> if( !x || isinf( y ) ) [[unlikely]]
> return x;
> uint64_t sign = bit_cast<uint64_t>( x ) &
> numeric_limits<int64_t>::min(); x = abs( x );
> y = abs( y );
> int oldCsr = _mm_getcsr();
> constexpr int CHOP = 0x6000;
> _mm_setcsr( oldCsr | CHOP );
> constexpr uint64_t
> EXP = -(1ll << 52),
> MANT = ~EXP;
> uint64_t binY = bit_cast<uint64_t>( y );
> int64_t expY = binY & EXP;
> if( !expY ) [[unlikely]]
> expY = (uint64_t)(0 - (countl_zero( binY & MANT ) -
> 12)) << 52; while( x >= y )
> {
> uint64_t yExpAdd = 0;
> double div = x / y;
> if( div < 0x1.FFFFFFFFFFFFFp+1023 ) [[likely]]
> div = xtrunc( div );
> else
> {
> uint64_t
> binX = bit_cast<uint64_t>( x ),
> newExp = expY + (54ull << 52);
> yExpAdd = (binX & EXP) - newExp;
> div = xtrunc( bit_cast<double>( newExp | binX
> & MANT ) / y ); }
> __m128d mult1, mult2, add;
> #if defined(_MSC_VER)
> mult1.m128d_f64[0] = div;
> mult2.m128d_f64[0] = -bit_cast<double>( binY +
> yExpAdd ); add.m128d_f64[0] = x;
> x = _mm_fmadd_sd( mult1, mult2, add ).m128d_f64[0];
> #else
> mult1[0] = div;
> mult2[0] = -bit_cast<double>( binY + yExpAdd );
> add[0] = x;
> x = _mm_fmadd_sd( mult1, mult2, add )[0];
> #endif
> if( !x ) [[unlikely]]
> return bit_cast<double>( sign );
> }
> _mm_setcsr( oldCsr );
> return bit_cast<double>( sign | bit_cast<uint64_t>( x ) );
> }
>
> The only thing that doesn't work currently is the support for denormal
> values.
>
I already said that I don't approve non-portable constructs like
_mm_getcsr()/_mm_setcsr() except when they help important cases and
help ALOT. Neither applies here.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 19:11 +0100 |
| Message-ID | <vqklks$rlr2$2@raubtier-asyl.eternal-september.org> |
| In reply to | #121919 |
Am 09.03.2025 um 19:04 schrieb Michael S: > I already said that I don't approve non-portable constructs like > _mm_getcsr()/_mm_setcsr() except when they help important cases and > help ALOT. Neither applies here. The solution is much simpler than your solution since there are no separate fast ans slow paths. The performance is about the same for close exponents like your solution.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-09 20:11 +0100 |
| Message-ID | <vqkp54$so65$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121921 |
Am 09.03.2025 um 19:11 schrieb Bonita Montero: > The solution is much simpler than your solution since there are no > separate fast ans slow paths. The performance is about the same for > close exponents like your solution. And it's somewhat faster if I use the ROUNDSD-intrinsic than my solution before with the xtrunc-function. With MSVC's own trunc() code the performance is not competitive.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-10 07:24 +0100 |
| Message-ID | <vqm0id$17aku$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121919 |
Am 09.03.2025 um 19:04 schrieb Michael S:
> I already said that I don't approve non-portable constructs like
> _mm_getcsr()/_mm_setcsr() except when they help important cases and
> help ALOT. Neither applies here.
I dropped getting and setting the MSCSR-register to set the roun-
ding mode. Now I set the rounding mode directly with the intrinsics
_mm_div_round_sd and and _mm_fmadd_round_sd. Now this more manual
code does help "ALOT", i.e. the solution is 2/3 faster than your
initial solution with clang++-18 under Linux.
But there's still a problem with the denormals.
double fmodMplus( double x, double y )
{
if( isnan( x ) ) [[unlikely]]
return x;
if( isnan( y ) ) [[unlikely]]
return y;
if( isinf( x ) || !y ) [[unlikely]]
{
feraiseexcept( FE_INVALID );
return numeric_limits<double>::quiet_NaN();
}
if( !x || isinf( y ) ) [[unlikely]]
return x;
uint64_t sign = bit_cast<uint64_t>( x ) & numeric_limits<int64_t>::min();
x = abs( x );
y = abs( y );
constexpr uint64_t
EXP = -(1ll << 52),
MANT = ~EXP;
uint64_t binY = bit_cast<uint64_t>( y );
int64_t expY = binY & EXP;
//if( !expY ) [[unlikely]]
//expY = (uint64_t)(0 - (countl_zero( binY & MANT ) - 12)) << 52;
while( x >= y )
{
uint64_t yExpAdd = 0;
__m128d a128, b128;
#if defined(_MSC_VER)
a128.m128d_f64[0] = x;
b128.m128d_f64[0] = y;
double div = _mm_div_round_sd( a128, b128, _MM_FROUND_TO_ZERO |
_MM_FROUND_NO_EXC ).m128d_f64[0];
#else
a128[0] = x;
b128[0] = y;
double div = _mm_div_round_sd( a128, b128, _MM_FROUND_TO_ZERO |
_MM_FROUND_NO_EXC )[0];
#endif
if( div < 0x1.FFFFFFFFFFFFFp+1023 ) [[likely]]
div = xtrunc( div );
else
{
uint64_t
binX = bit_cast<uint64_t>( x ),
newExp = expY + (54ull << 52);
yExpAdd = (binX & EXP) - newExp;
div = xtrunc( bit_cast<double>( newExp | binX & MANT ) / y );
}
x = []( double a, double b, double c )
{
__m128d mult1, mult2, add;
#if defined(_MSC_VER)
mult1.m128d_f64[0] = a;
mult2.m128d_f64[0] = b;
add.m128d_f64[0] = c;
return _mm_fmadd_round_sd( mult1, mult2, add, _MM_FROUND_TO_ZERO |
_MM_FROUND_NO_EXC ).m128d_f64[0];
#else
mult1[0] = a;
mult2[0] = b;
add[0] = c;
return _mm_fmadd_round_sd( mult1, mult2, add, _MM_FROUND_TO_ZERO |
_MM_FROUND_NO_EXC )[0];
#endif
}( div, -bit_cast<double>( binY + yExpAdd ), x );
if( !x ) [[unlikely]]
return bit_cast<double>( sign );
}
return bit_cast<double>( sign | bit_cast<uint64_t>( x ) );
}
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-10 10:46 +0100 |
| Message-ID | <vqmcee$19g55$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121924 |
I tried to use a unsigned __int128 / uint64_t division and I expected
that the compiler calls a library function which does the subtract and
shift manually. But g++ as well as clang++ handle this as a 128 : 64
-> 64#64 division somehow.
And now my original solution is about 23% faster than your solution
for close exponents (exponent difference <= 53) and for arbitrary
exponent differences your solution is about 3% faster.
double fmodO( double x, double y )
{
constexpr uint64_t
SIGN = 1ull << 63,
IMPLICIT = 1ull << 52,
MANT = IMPLICIT - 1,
QBIT = 1ull << 51;
uint64_t const
binX = bit_cast<uint64_t>( x ),
binY = bit_cast<uint64_t>( y );
static auto abs = []( uint64_t m ) { return m & ~SIGN; };
auto isNaN = []( uint64_t m ) { return abs( m ) >= 0x7FF0000000000001u; };
auto isSig = []( uint64_t m ) { return !(m & QBIT); };
if( isNaN( binX ) ) [[unlikely]] // x == NaN
#if defined(_MSC_VER)
return bit_cast<double>( isNaN( binY ) ? binY | binX & binY & QBIT :
binX );
#else
{
if( isSig( binX ) || isNaN( binY ) && isSig( binY ) ) [[unlikely]]
feraiseexcept( FE_INVALID );
return bit_cast<double>( binX | QBIT );
}
#endif
if( isNaN( binY ) ) [[unlikely]] // x != NaN || y == NaN
#if defined(_MSC_VER)
return y;
#else
{
if( isSig( binY ) ) [[unlikely]]
feraiseexcept( FE_INVALID );
return bit_cast<double>( binY | QBIT );
}
#endif
auto isInf = []( uint64_t m ) { return abs( m ) == 0x7FF0000000000000u; };
if( isInf( binX ) ) // x == Inf
{
feraiseexcept( FE_INVALID );
#if defined(_MSC_VER)
return bit_cast<double>( binX & ~MANT | QBIT );
#else
return -numeric_limits<double>::quiet_NaN();
#endif
}
if( !abs( binY ) ) [[unlikely]] // y == 0
{
feraiseexcept( FE_INVALID );
#if defined(_MSC_VER)
return numeric_limits<double>::quiet_NaN();
#else
return -numeric_limits<double>::quiet_NaN();
#endif
}
if( !abs( binX ) || isInf( binY ) ) [[unlikely]] // x == 0 || y == Inf
return x;
auto exp = []( uint64_t b ) -> int { return b >> 52 & 0x7FF; };
int
expX = exp( binX ),
expY = exp( binY );
auto mant = []( uint64_t b ) { return b & MANT; };
uint64_t
mantX = mant( binX ),
mantY = mant( binY );
int headBits = 11;
static auto normalize = [&]( int &exp, uint64_t &mant )
{
unsigned shift = countl_zero( mant ) - headBits;
mant <<= shift;
exp -= shift;
};
auto build = []( int &exp, uint64_t &mant )
{
if( exp ) [[likely]]
mant |= IMPLICIT;
else
{
exp = 1;
normalize( exp, mant );
}
};
build( expX, mantX );
build( expY, mantY );
int
tailX = countr_zero( mantX ),
tailY = countr_zero( mantY ),
tailBits = tailX <= tailY ? tailX : tailY;
mantX >>= tailBits;
mantY >>= tailBits;
headBits += tailBits;
uint64_t signX = binX & SIGN;
int expDiff;
#if defined(_MSC_VER) && !defined(__llvm__) && defined(_M_X64)
while( (expDiff = expX - expY) > 0 )
{
unsigned bits = expDiff <= 63 ? expDiff : 63;
unsigned long long hi = mantX >> 64 - bits, lo = mantX << bits, remainder;
(void)_udiv128( hi, lo, mantY, &remainder );
if( !remainder ) [[unlikely]]
return bit_cast<double>( signX );
mantX = remainder;
expX -= bits;
normalize( expX, mantX );
}
#elif defined(__GNUC__) || defined(__clang__)
while( (expDiff = expX - expY) > 0 )
{
unsigned bits = expDiff <= 63 ? expDiff : 63;
unsigned __int128 dividend = (unsigned __int128)mantX << bits;
mantX = (uint64_t)(dividend % mantY);
if( !mantX ) [[unlikely]]
return bit_cast<double>( signX );
expX -= bits;
normalize( expX, mantX );
}
#else
while( (expDiff = expX - expY) > 0 )
{
unsigned bits = expDiff <= headBits ? expDiff : headBits;
if( !(mantX = (mantX << bits) % mantY) ) [[unlikely]]
return bit_cast<double>( signX );
expX -= bits;
normalize( expX, mantX );
}
#endif
if( !expDiff && mantX >= mantY ) [[unlikely]]
if( (mantX -= mantY) ) [[likely]]
normalize( expX, mantX );
else
return bit_cast<double>( signX );
mantX <<= tailBits;
mantY <<= tailBits;
if( expX <= 0 ) [[unlikely]]
{
assert(expX >= -51);
mantX = mantX >> (unsigned)(-expX + 1);
expX = 0;
}
return bit_cast<double>( signX | (uint64_t)expX << 52 | mantX & MANT );
}
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2025-03-10 14:26 +0200 |
| Message-ID | <20250310142648.00005b3c@yahoo.com> |
| In reply to | #121925 |
On Mon, 10 Mar 2025 10:46:59 +0100
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> I tried to use a unsigned __int128 / uint64_t division and I expected
> that the compiler calls a library function which does the subtract and
> shift manually. But g++ as well as clang++ handle this as a 128 : 64
> -> 64#64 division somehow.
Somehow?
It should be an obvious thing to anybody who cared to think for 15
seconds.
A library-or-compiler starts with hi1=rem(0:x_hi, y). Now hi1 is
guaranteed to be smaller than y, so it's safe to do rem(hi1:x_lo, y).
It is not *very* slow, but still there are 2 dependent division
operations.
So, on machines with slow integer division, like Skylake, it is 1.5-1.7
times slower than a single long division.
On machines with fast long division, like Zen3/4/5 or "performance"
cores on newer Intel CPUs, it is approximately twice slower than a
single long division. Plus call overhead, so 2.5x or so slower overall.
> And now my original solution is about 23% faster than your solution
> for close exponents (exponent difference <= 53) and for arbitrary
> exponent differences your solution is about 3% faster.
>
That's absolutely not what I see.
Here are my measurements:
Measurements in nsec.
First result - Intel Skylake at 4.25 GHz
Second result - AMD Zen3 at 3.7 GHz
abs(x/y) in range that matters [0.5:2**53]:
Standard MSVC Library - 11.1 10.4
Standard gnu Library - 5.4 10.7
Yours (MSVc) - 27.6 11.5
Yours (gcc) - 36.4 23.7
Yours (clang) - 37.4 24.3
my (MSVc) - 10.7 11.3
my (gcc) - 7.7 7.6
my (clang) - 6.3 7.5
Your last (MSVc) - 27.6 11.6
Your last (gcc) - 33.8 28.6
Your last (clang) - 32.6 26.9
abs(x/y) in full range [2**-2090:2**2090]:
Standard MSVC Library - 109.4 153.5
Standard glib Library - 102.3 155.5
Yours (MSVc) - 134.9 52.6
Yours (gcc) - 284.7 151.8
Yours (clang) - 285.2 156.5
my (MSVc) - 62.1 61.1
my (gcc) - 60.8 59.1
my (clang) - 59.9 59.3
Your last (MSVc) - 135.0 52.5
Your last (gcc) - 172.1 137.3
Your last (clang) - 167.7 126.3
It looks like you are not using version that I posted at 2025-03-03
as a reference.
The only case where you code is running at approximately the same speed
as my code is MSVC-generated code on CPUs with fast integer division.
And it was like that since your previous version. I see no changes in
that regard.
> double fmodO( double x, double y )
> {
> constexpr uint64_t
> SIGN = 1ull << 63,
> IMPLICIT = 1ull << 52,
> MANT = IMPLICIT - 1,
> QBIT = 1ull << 51;
> uint64_t const
> binX = bit_cast<uint64_t>( x ),
> binY = bit_cast<uint64_t>( y );
> static auto abs = []( uint64_t m ) { return m & ~SIGN; };
> auto isNaN = []( uint64_t m ) { return abs( m ) >=
> 0x7FF0000000000001u; }; auto isSig = []( uint64_t m ) { return !(m &
> QBIT); }; if( isNaN( binX ) ) [[unlikely]] // x == NaN
> #if defined(_MSC_VER)
> return bit_cast<double>( isNaN( binY ) ? binY | binX
> & binY & QBIT : binX );
> #else
> {
> if( isSig( binX ) || isNaN( binY ) && isSig( binY ) )
> [[unlikely]] feraiseexcept( FE_INVALID );
> return bit_cast<double>( binX | QBIT );
> }
> #endif
> if( isNaN( binY ) ) [[unlikely]] // x != NaN || y == NaN
> #if defined(_MSC_VER)
> return y;
> #else
> {
> if( isSig( binY ) ) [[unlikely]]
> feraiseexcept( FE_INVALID );
> return bit_cast<double>( binY | QBIT );
> }
> #endif
> auto isInf = []( uint64_t m ) { return abs( m ) ==
> 0x7FF0000000000000u; }; if( isInf( binX ) ) // x == Inf
> {
> feraiseexcept( FE_INVALID );
> #if defined(_MSC_VER)
> return bit_cast<double>( binX & ~MANT | QBIT );
> #else
> return -numeric_limits<double>::quiet_NaN();
> #endif
> }
> if( !abs( binY ) ) [[unlikely]] // y == 0
> {
> feraiseexcept( FE_INVALID );
> #if defined(_MSC_VER)
> return numeric_limits<double>::quiet_NaN();
> #else
> return -numeric_limits<double>::quiet_NaN();
> #endif
> }
> if( !abs( binX ) || isInf( binY ) ) [[unlikely]] // x == 0 ||
> y == Inf return x;
> auto exp = []( uint64_t b ) -> int { return b >> 52 & 0x7FF;
> }; int
> expX = exp( binX ),
> expY = exp( binY );
> auto mant = []( uint64_t b ) { return b & MANT; };
> uint64_t
> mantX = mant( binX ),
> mantY = mant( binY );
> int headBits = 11;
> static auto normalize = [&]( int &exp, uint64_t &mant )
> {
> unsigned shift = countl_zero( mant ) - headBits;
> mant <<= shift;
> exp -= shift;
> };
> auto build = []( int &exp, uint64_t &mant )
> {
> if( exp ) [[likely]]
> mant |= IMPLICIT;
> else
> {
> exp = 1;
> normalize( exp, mant );
> }
> };
> build( expX, mantX );
> build( expY, mantY );
> int
> tailX = countr_zero( mantX ),
> tailY = countr_zero( mantY ),
> tailBits = tailX <= tailY ? tailX : tailY;
> mantX >>= tailBits;
> mantY >>= tailBits;
> headBits += tailBits;
> uint64_t signX = binX & SIGN;
> int expDiff;
> #if defined(_MSC_VER) && !defined(__llvm__) && defined(_M_X64)
> while( (expDiff = expX - expY) > 0 )
> {
> unsigned bits = expDiff <= 63 ? expDiff : 63;
> unsigned long long hi = mantX >> 64 - bits, lo =
> mantX << bits, remainder; (void)_udiv128( hi, lo, mantY, &remainder );
> if( !remainder ) [[unlikely]]
> return bit_cast<double>( signX );
> mantX = remainder;
> expX -= bits;
> normalize( expX, mantX );
> }
> #elif defined(__GNUC__) || defined(__clang__)
> while( (expDiff = expX - expY) > 0 )
> {
> unsigned bits = expDiff <= 63 ? expDiff : 63;
> unsigned __int128 dividend = (unsigned __int128)mantX
> << bits; mantX = (uint64_t)(dividend % mantY);
> if( !mantX ) [[unlikely]]
> return bit_cast<double>( signX );
> expX -= bits;
> normalize( expX, mantX );
> }
> #else
> while( (expDiff = expX - expY) > 0 )
> {
> unsigned bits = expDiff <= headBits ? expDiff :
> headBits; if( !(mantX = (mantX << bits) % mantY) ) [[unlikely]]
> return bit_cast<double>( signX );
> expX -= bits;
> normalize( expX, mantX );
> }
> #endif
> if( !expDiff && mantX >= mantY ) [[unlikely]]
> if( (mantX -= mantY) ) [[likely]]
> normalize( expX, mantX );
> else
> return bit_cast<double>( signX );
> mantX <<= tailBits;
> mantY <<= tailBits;
> if( expX <= 0 ) [[unlikely]]
> {
> assert(expX >= -51);
> mantX = mantX >> (unsigned)(-expX + 1);
> expX = 0;
> }
> return bit_cast<double>( signX | (uint64_t)expX << 52 | mantX
> & MANT ); }
You code would be much, much cleaner and more readable if you replace
lambdas with proper functions. Or just write simple expressions like 'x
& MANT' in place.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-03-10 13:45 +0100 |
| Message-ID | <vqmmt1$1bjh1$1@raubtier-asyl.eternal-september.org> |
| In reply to | #121930 |
Am 10.03.2025 um 13:26 schrieb Michael S: > It should be an obvious thing to anybody who cared to think for 15 > seconds. I was wrong and it absolutels isn't obvious. The compiler calls the glibc function __umodti3 of glibc which has a shortcut for results which fit into 64 bit. Although there's an additional call on Linux the code with clang++-18 is still a bit faster than my Windows solution with the _udiv128-intrinsic; that's really surprisng. > A library-or-compiler starts with hi1=rem(0:x_hi, y). Now hi1 is > guaranteed to be smaller than y, so it's safe to do rem(hi1:x_lo, y). > It is not *very* slow, but still there are 2 dependent division > operations. Both parameters are variable so there could be no static evaluation at compile tiime. > Measurements in nsec. > First result - Intel Skylake at 4.25 GHz > Second result - AMD Zen3 at 3.7 GHz > > abs(x/y) in range that matters [0.5:2**53]: > Standard MSVC Library - 11.1 10.4 > Standard gnu Library - 5.4 10.7 > Yours (MSVc) - 27.6 11.5 > Yours (gcc) - 36.4 23.7 > Yours (clang) - 37.4 24.3 > my (MSVc) - 10.7 11.3 > my (gcc) - 7.7 7.6 > my (clang) - 6.3 7.5 > Your last (MSVc) - 27.6 11.6 > Your last (gcc) - 33.8 28.6 > Your last (clang) - 32.6 26.9 > > abs(x/y) in full range [2**-2090:2**2090]: > Standard MSVC Library - 109.4 153.5 > Standard glib Library - 102.3 155.5 > Yours (MSVc) - 134.9 52.6 > Yours (gcc) - 284.7 151.8 > Yours (clang) - 285.2 156.5 > my (MSVc) - 62.1 61.1 > my (gcc) - 60.8 59.1 > my (clang) - 59.9 59.3 > Your last (MSVc) - 135.0 52.5 > Your last (gcc) - 172.1 137.3 > Your last (clang) - 167.7 126.3 This are the clang++-18 results on my Zen4-computer under WSL2 with close exponents (0x3ff to 0x433): fmodO: 9.42929 fmodM: 11.7907 So my code is about 23% faster on my computer. This are the results for arbitrary exponents: fmodO: 41.9115 fmodM: 41.2062 Exactly what I already mentioned. Maybe that depends on the glibc-version because a different glibc version might have different efficient __umodti3 functions. > You code would be much, much cleaner and more readable if you replace > lambdas with proper functions. .. For me that doesn't make a difference.
[toc] | [prev] | [next] | [standalone]
Page 5 of 7 — ← Prev page 1 2 3 4 [5] 6 7 Next page →
Back to top | Article view | comp.lang.c++
csiph-web