Saturday, October 2, 2021

Digest for comp.lang.c++@googlegroups.com - 24 updates in 4 topics

Bonita Montero <Bonita.Montero@gmail.com>: Oct 02 12:09PM +0200

Am 01.10.2021 um 17:37 schrieb wij:
> x=::ldexpl(x,numeric_limits<FType>::digits);
> mint= static_cast<int64_t>(x);
 
> Result (mint) is a negative number, something not right!!!
 
Here, exactly 100 lines with a very convenient double to double
parts and double parts to double conversion:
 
#pragma once
#include <limits>
#include <cstdint>
#include <cassert>
 
struct dbl_parts
{
static_assert(std::numeric_limits<double>::is_iec559, "must be standard
fp");
dbl_parts( double d );
dbl_parts &operator =( double d );
dbl_parts() = default;
operator double();
bool getSign();
std::uint16_t getBiasedExponent();
std::int16_t getExponent();
std::uint64_t getMantissa();
void setSign( bool sign );
void setBiasedExponent( uint16_t exp );
void setExponent( int16_t exp );
void setMantissa( uint64_t mantissa );
private:
union
{
double value;
std::uint64_t binary;
};
};
 
inline
dbl_parts::dbl_parts( double d ) :
value( d )
{
}
 
inline
dbl_parts &dbl_parts::operator =( double d )
{
value = d;
return *this;
}
 
inline
dbl_parts::operator double()
{
return value;
}
 
inline
bool dbl_parts::getSign()
{
return (int64_t)binary < 0;
}
 
inline
std::uint16_t dbl_parts::getBiasedExponent()
{
return (std::uint16_t)(binary >> 52) & 0x7FF;
}
 
inline
int16_t dbl_parts::getExponent()
{
return (int16_t)getBiasedExponent() - 0x3FF;
}
 
inline
std::uint64_t dbl_parts::getMantissa()
{
std::uint16_t bExp = getBiasedExponent();
std::uint64_t hiBit = (uint64_t)(bExp && bExp != 0x7FF) << 52;
return binary & 0xFFFFFFFFFFFFFu | hiBit;
}
 
inline
void dbl_parts::setSign( bool sign )
{
binary = binary & 0x7FFFFFFFFFFFFFFFu | (std::uint64_t)sign << 63;
}
 
inline
void dbl_parts::setBiasedExponent( std::uint16_t exp )
{
assert(exp <= 0x7FF);
binary = binary & 0x800FFFFFFFFFFFFFu | (std::uint64_t)exp << 52;
}
 
inline
void dbl_parts::setExponent( std::int16_t exp )
{
assert(exp >= -0x3FF && exp <= 400);
setBiasedExponent( (uint16_t)(exp - 0x3FF) );
}
 
inline
void dbl_parts::setMantissa( std::uint64_t mantissa )
{
assert((getBiasedExponent() == 0 || getBiasedExponent() == 0x7FF) &&
!(mantissa & -0x10000000000000));
assert(getBiasedExponent() != 0 && getBiasedExponent() != 0x7FF ||
mantissa <= 0x1FFFFFFFFFFFFFu);
binary = binary & 0xFFF0000000000000u | mantissa & 0xFFFFFFFFFFFFFu;
}
Branimir Maksimovic <branimir.maksimovic@icloud.com>: Oct 02 10:59AM

> the conversion to long long have defined behavior, the result of that
> conversion would be the truncated value itself (7.3.10p1), NOT the
> mantissa of the truncated value. What makes you think otherwise?
Because mantissa is whole part of floating point number?
 
--
 
7-77-777
Evil Sinner!
Manfred <noname@add.invalid>: Oct 02 06:58PM +0200

On 10/2/2021 2:23 AM, wij wrote:
>>>> mint= static_cast<int64_t>(x);
 
>>>> Result (mint) is a negative number, something not right!!!
>> I can't duplicate this problem: I get mint:9223372036854775807.
<snip>
> 16777215, ffffff
> 9007199254740991, 1fffffffffffff
> -9223372036854775808, 8000000000000000
 
There are two problems:
 
1)
The templated function uses 'frexp' and 'ldexp', which take both double
arguments (not *long* double), hence UB occurs at those calls for the
'long double' type whenever this type is actually larger than 'double'.
 
2)
On my Linux box numeric_limits<*long* double>::digits is 64
(numeric_limits<double>::digits is 53), so the static_cast<int64_t>(x)
yields UB again.
 
=========
#include <cmath>
#include <limits>
#include <iostream>
 
using namespace std;
#define ENDL endl
 
uint64_t get_mantf(float x)
{
int iexp;
x=frexp(x,&iexp);
x=ldexp(x,numeric_limits<float>::digits);
return static_cast<uint64_t>(x);
};
 
uint64_t get_mant(double x)
{
int iexp;
x=frexp(x,&iexp);
x=ldexp(x,numeric_limits<double>::digits);
return static_cast<uint64_t>(x);
};
 
uint64_t get_mantl(long double x)
{
int iexp;
x=frexp(x,&iexp);
x=ldexp(x,numeric_limits<long double>::digits);
return static_cast<uint64_t>(x);
};
 
int main()
{
cout << dec << numeric_limits<float>::digits << ", " <<
get_mantf(numeric_limits<float>::max()) << ", "
<< hex << get_mantf(numeric_limits<float>::max()) << ENDL;
cout << dec << numeric_limits<double>::digits << ", " <<
get_mant(numeric_limits<double>::max()) << ", "
<< hex << get_mant(numeric_limits<double>::max()) << ENDL;
cout << dec << numeric_limits<long double>::digits << ", " <<
get_mantl(numeric_limits<long double>::max()) << ", "
<< hex << get_mantl(numeric_limits<long double>::max()) << ENDL;
return 0;
}
===================
$ c++ -std=c++11 -O2 -Wall mant.cc && ./a.out
24, 16777215, ffffff
53, 9007199254740991, 1fffffffffffff
64, 18446744073709551615, ffffffffffffffff
Manfred <noname@add.invalid>: Oct 02 07:21PM +0200

On 10/2/2021 6:58 PM, Manfred wrote:
> 24, 16777215, ffffff
> 53, 9007199254740991, 1fffffffffffff
> 64, 18446744073709551615, ffffffffffffffff
 
Sorry, that should have been:
 
=====
uint64_t get_mantf(float x)
{
int iexp;
x=frexpf(x,&iexp);
x=ldexpf(x,numeric_limits<float>::digits);
return static_cast<uint64_t>(x);
};
 
uint64_t get_mant(double x)
{
int iexp;
x=frexp(x,&iexp);
x=ldexp(x,numeric_limits<double>::digits);
return static_cast<uint64_t>(x);
};
 
uint64_t get_mantl(long double x)
{
int iexp;
x=frexpl(x,&iexp);
x=ldexpl(x,numeric_limits<long double>::digits);
return static_cast<uint64_t>(x);
};
=====
 
However, the three distinct functions with frexp and ldexp in all three
still work on my box (I'm guessing gcc is still able to compile the
correct implementation in in this case), but the template doesn't.
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 02 02:57PM -0400

On 10/2/21 6:59 AM, Branimir Maksimovic wrote:
>> conversion would be the truncated value itself (7.3.10p1), NOT the
>> mantissa of the truncated value. What makes you think otherwise?
> Because mantissa is whole part of floating point number?
 
Well, at least I'm clear now about what your confusion is. I'll give you
an answer in two parts:
1. The mantissa of a floating point number (also called the significand,
which is the term used in the C standard in text that is incorporated by
reference into the C++ standard) is something quite different from the
whole part of that number. See
<https://en.m.wikipedia.org/wiki/Significand> for details.
 
2. When a floating point number is greater than LLONG_MAX+1.0, the code
you provided has undefined behavior. That makes sense, since a long long
object cannot represent the whole part of such a number. The actual
behavior can vary from one implementation to another, but on my system,
it does NOT contain the mantissa, either.
 
Consider the following program:
 
#include <iostream>
 
int main(void)
{
typedef long double FType;
FType max= std::numeric_limits<FType>::max();
FType large = 0xA.BCDEF0123456789p+16380L;
FType middling = 0xABCDEF01.23456789p0L;
long long maxll = max;
long long largell = large;
long long middlingll = middling;
 
std::cout << std::fixed << "max: " << max << std::endl;
std::cout << "large: " << large << std::endl;
std::cout << "middling: " << middling << std::endl;
 
std::cout << "maxll: " << maxll << std::endl;
std::cout << "largell: " << largell << std::endl;
std::cout << "middlingll: " << middlingll << std::endl;
 
std::cout << std::hexfloat << std::showbase << std::showpoint <<
std::hex << "max: " << max << std::endl;
std::cout << "large: " << large << std::endl;
std::cout << "middling: " << middling << std::endl;
 
std::cout << "maxll: " << maxll << std::endl;
std::cout << "largell: " << largell << std::endl;
std::cout << "middlingll: " << middlingll << std::endl;
}
 
The output from that program on my system is:
 
max:
118973149535723176502126385303097020516906332229462420044032373389173700552297072261641029033652888285354569780749557731442744315367028843419812557385374367867359320070697326320191591828296152436552951064679108661431179063216977883889613478656060039914875343321145491116008867984515486651285234014977303760000912547939396622315138362241783854274391783813871780588948754057516822634765923557697480511372564902088485522249479139937758502601177354918009979622602685950855888360815984690023564513234659447638493985927645628457966177293040780660922910271504608538808795932778162298682754783076808004015069494230341172895777710033571401055977524212405734700738625166011082837911962300846927720096515350020847447079244384854591288672300061908512647211195136146752763351956292759795725027800298079590419313960302147099703527646744553092202267965628099149823208332964124103850923918473478612192169721054348428704835340811304257300221642134891734717423480071488075100206439051723424765600472176809648610799494 341570347632064355862420744350442438056613601760883747816538902780957697597728686007148702828795556714140463261583262360276289631617397848425448686060994827086796804807870251185893083854658422304090880599629459458620190376604844679092600222541053077590106576067134720012584640695703025713896098375799892695455305236856075868317922311363951946885088077187210470520395758748001314313144425494391994017575316933939236688185618912993172910425292123683515992232205099800167710278403536014082929639811512287776813570604578934353545169653956125404884644716978689321167108722908808277835051822885764606221873970285165508372099234948333443522898475123275372663606621390228126470623407535207172405866507951821730346378263135339370677490195019784169044182473806316282858685774143258116536404021840272491339332094921949842244273042701987304453662035026238695780468200360144729199712309553005720614186697485284685618651483271597448120312194675168637934309618961510733006555242148519520176285859509105183947250286 387163249416761380499631979144187025430270675849519200883791516940158174004671147787720145964446117520405945350476472180797576111172084627363927960033967047003761337450955318415007379641260504792325166135484129188421134082301547330475406707281876350361733290800595189632520707167390454777712968226520622565143991937680440029238090311243791261477625596469422198137514696707944687035800439250765945161837981185939204954403611491531078225107269148697980924094677214272701240437718740921675661363493890045123235166814608932240069799317601780533819184998193300841098599393876029260139091141452600372028487213241195542428210183120421610446740462163533690058366460659115629876474552506814500393294140413149540067760295100596225302282300363147382468105964844244132486457313743759509641616804802412935187620466813563687753281467553879887177183651289394719533506188500326760735438867336800207438784965701457609034985757124304510203873049485425670247933932280911052604153852899484920399109194612991249163328991 799809438033787952209313146694614970593966415237594928589096048991612194498998638483702248667224914892467841020618336462741696957630763248023558797524525373703543388296086275342774001633343405508353704850737454481975472222897528108302089868263302028525992308416805453968791141829762998896457648276528750456285492426516521775079951625966922911497778896235667095662713848201819134832168799586365263762097828507009933729439678463987902491451422274252700636394232799848397673998715441855420156224415492665301451550468548925862027608576183712976335876121538256512963353814166394951655600026415918655485005705261143195291991880795452239464962763563017858089669222640623538289853586759599064700838568712381032959192649484625076899225841930548076362021508902214922052806984201835084058693849381549890944546197789302911357651677540623227829831403347327660395223160342282471752818181884430488092132193355086987339586127607367086665237555567580317149010847732009642431878007000879734603290627894355374356444885 1907191616455141155761939399690767415156402826543664026760095087523945507341556135867933066031744720924446513532366647649735400851967040771103640538150073486891798364049570606189535005089840913826869535090066783324472578712196604415284924840041850932811908963634175739897166596000759487800619164094854338758520657116541072260996288150123144377944008749301944744330784388995701842710004808305012177123560622895076269042856800047718893158089358515593863176652948089031267747029662545110861548958395087796755464137944895960527975209874813839762578592105756284401759349324162148339565350189196811389091843795734703269406342890087805846940352453479398080674273236297887100867175802531561302356064878709259865288416350972529537091114317204887747405539054009425375424119317944175137064689643861517718849867010341532542385911089624710885385808688837777258648564145934262121086647588489260031762345960769508849149662444156604419552086811989770240.000000
large:
798441950131984170628030460666810333557348275190265576078984094186809314595841573532599033606882733242214503184515646114757854809285221996356228289554376635019344753920776702760669187940817514531317086140383510733112508649664623633139528050777110074618005617509580146833305060924324246754342390819803294975489244294690457181615916380846787220310100995994303945777913450178570581981686198498193907782547173273698279385392870067122516401380661309429194377571288675510592121362933128690216937551164723903033967732288194633304806974443077506079764506140348104093213176088240569763532433031309628120758051299847190906531282735560740981504351645262405988024022915769015155291537373039452757287714224413271925722965109196412960233450108997556205354431107378518341642987291604090752426939027264213019440145124490661477726747318914574881469961518134515108880857245240185572718139826633083153405462806445652888413410638188733734515336089461690188769941296000310237908472871534924022605781553137758150233789260 358532907145882036161660126945661711839735421711825178177760957818009605928677177600206353608487447867000007661334384127783042012294562593528684725810884617737609254169149626757295679706675640253674305137724007576430362146351195481618750152400954313053997866464669799426096587456831642162987414724896100262164539763660362382092573961783134501772282908098290593289630152876770300417744973458556470142688766464671575130409003788303712422629946652772747989412570452719563049061781235816001067752251851519827096684941366242307880857459992859988995242358876699073496204946189012116094636726007751024562501070868616158003530658455857341162526439165492140517609950096619412732907944896057390196270057177242728156339638540867610924105857412556444579107776816889674631366413677833047161379884532164198993276772896425495083000505555449504361780772635099950677280195245017300352256591786535445649376601829488196382898175912034787015428923592784580276113369666903167358253633530441611097653596975461248061662339 365488473119600829523500459203619456964603129018988931194328288813647101701632839512858929869478394804296698394260954809692417234406205371106893496236967789991565505735586236384677950809842953217931584749260769959701438782478571501334539385640439880396793372493213016627745357811930479029023541095769455142488296966879072936425173785823423491784831896194556031386766634408387982622337724480135007299914446877152530780342928097086987514633283924856437263144768383859171111988014305350935374816502702333251093923757732462792355307789905174719099488759733393438698689634230361403084258533397265120127568961174111327297320782260488730893216700453978837717137622769084406167566152759623181706028976375164646094475146647369281575972522853549552541720923007665948643646011282736873309526428963407898352464481165847664515121092198236329555997024089181776782273133008347683849048553390800664712980340475996260480072720565715887831207483955807832767939883392425546385536716077432630898214899484281107511073792 175413829068138175373955787942264464985983774969783604562637885180871016551868231242254625289486930794202391413454134460390851822972288028367994924347840148793791361918282891665866879658491796934476927641493412928958649240130825652229115711491817767450106062789615541320400721098889852085898259254162735307793046490526388026316295280894798927076625172952033631816193510840287691268927294098058192308372212486275935018916579164964951401297805003291270040660302706760922674620757844937737189874735833048611876587062084398065184497992254250923170482005379707778025178444614040206924597320627466243597003790395509022310055565959173599974814957486832121747812898110468472757711344935141581619768179027277300745026178548690842027389022573413486719086424376549995531862953495262810743844967518912745788410885417320073667346399372144729172804316265474393461925206370016332837493346298714231599348699028709728862988664452830290361646545475793248617512310081372368799772054350231317371686452672996009981551057 400080425522396446487229356262303917938229664789869208363238136397068893440807223464451417926302339445880535875195702287684615206433710292963594791392187167500246785808792158380039590563187800668321919054700778993223664127005039562879931963775644174414234242371897053417500956186032208506564827824530909432144378661326313617577661894233125412875713957392594237250272900479523399925200381753270457862573831453382693219682510773999798436059405397109340096099851440470543315842651194313580726690246948309173037070102422697928865543593593980166075781220064584748135949528803322043763798528128793152883647487108192854012453988821565817611465474933891481140768062268834838833326673555808237357184051468989117126978502141404852191804301542607646946130977410809967278476698460181222465259056386246982267558528987894457868410385101006422099287064483189598631389250604017773829174392421160930626885766469862665970968575978122938895191153280286720.000000
middling: 2882400001.137778
maxll: 9223372036854775807
largell: 9223372036854775807
middlingll: 2882400001
max: 0xf.fffffffffffffffp+16380
large: 0xa.bcdef0123456789p+16380
middling: 0xa.bcdef0123456789p+28
maxll: 0x7fffffffffffffff
largell: 0x7fffffffffffffff
middlingll: 0xabcdef01
 
I'll use hexadecimal notation in the following comments:
 
The whole part of "max" has the same value as "max" itself. The same is
true of "large". The whole part of middling is 0xABCDEF01. The
fractional part of middling is 0x0.23456789.
 
The mantissas are as follows:
max: 0xffffffffffffffff
large: 0xabcdef0123456789
middling: 0xabcdef0123456789
 
The values stored in "maxll" and "largell" do not match either the whole
part or the mantissa of the corresponding floating point number. Because
"middling" is the only one of the three long double values that is
smaller than LLONG_MAX, the value stored in middlingll is the whole part
of "middling", as it should be, but is quite different from the mantissa
of "middling".
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Oct 02 09:00PM +0200

On 1 Oct 2021 17:37, wij wrote:
> x=::ldexpl(x,numeric_limits<FType>::digits);
> mint= static_cast<int64_t>(x);
 
> Result (mint) is a negative number, something not right!!!
 
Apparently you're trying to obtain the bits of the mantissa of a `long
double` number, represented as an `int64_t` value.
 
A `long double` is in practice either IEEE 754 64-bit, or IEEE 754
80-bit. In Windows that choice depends on the compiler. With Visual C++
(and hence probably also Intel) it's 64-bit, same as type `double`,
while with MinGW g++ (and hence probably also clang) it 80-bit,
originally the x86-family's math coprocessor's extended format. For
80-bit IEEE 754 the mantissa part is 64 bits.
 
With 64-bits mantissa there is a high chance of setting the sign bit of
an `int64_t` to 1, resulting in a negative value. I believe that that
will only /not/ happen for a denormal value, but, I'm tired and might be
wrong about that. Anyway, instead use unsigned types for bit handling.
For example, in this case, use `uint64_t`.
 
However, instead of the shenanigans with `frexpl` and `ldexpl` I'd just
use `memcpy`.
 
Due to the silliness in gcc regarding the standard's "strict aliasing"
rule, I'd not use a reinterpretation pointer cast.
 
 
- Alf
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 02 03:12PM -0400

On 10/2/21 3:00 PM, Alf P. Steinbach wrote:
> will only /not/ happen for a denormal value, but, I'm tired and might be
> wrong about that. Anyway, instead use unsigned types for bit handling.
> For example, in this case, use `uint64_t`.
 
It would be safer and more portable to use FType; there's no portable
guarantee that any integer type is large enough to hold the mantissa,
but FType is.
 
> However, instead of the shenanigans with `frexpl` and `ldexpl` I'd just
> use `memcpy`.
 
The advantage of the code as written is that (if you change mint to have
FType) it will give the correct result even if your assumption about
IEEE 754 is false; that's not the case with memcpy().
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Oct 02 09:23PM +0200

On 2 Oct 2021 21:12, James Kuyper wrote:
 
> It would be safer and more portable to use FType; there's no portable
> guarantee that any integer type is large enough to hold the mantissa,
> but FType is.
 
I believe you intended to write `uintptr_t`, not `FType`.
 
If so, agreed.
 
It's late in the day for me, sorry.
 
 
 
> The advantage of the code as written is that (if you change mint to have
> FType) it will give the correct result even if your assumption about
> IEEE 754 is false; that's not the case with memcpy().
 
Uhm, I'd rather assert IEEE 754 representation
(numeric_limits::is_iec559). Dealing with the bits of just about any
representation seems to me a hopelessly daunting task. :-o
 
 
- Alf
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Oct 02 09:27PM +0200

On 2 Oct 2021 21:23, Alf P. Steinbach wrote:
 
> I believe you intended to write `uintptr_t`, not `FType`.
 
> If so, agreed.
 
> It's late in the day for me, sorry.
 
It's /very/ late.
 
There AFAIK is no suitable type name for the integer type with
sufficient bits to represent the mantissa, or generally >N bits.
 
Unfortunately the standard library doesn't provide a mapping from number
of bits as a value, to integer type with that many bits. It can be done,
on the assumption that all types in `<stdint.h>` are present. And
perhaps one can then define a name like `FType` in terms of that mapping.
 
 
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 02 03:37PM -0400

On 10/2/21 2:59 PM, Branimir Maksimovic wrote:
> large for type 'long double'; maximum is 1.7976931348623157E+308
> [-Wliteral-range]
> Sorry your program is not correct..
 
The value of "large" was chosen to be almost as large as "max" on my
machine. It's apparently larger than LDBL_MAX on your system. A more
portable initializer would be
 
    FType large = 0x0.ABCDEF0123456789p0L * max;
 
Depending upon the value of LDBL_EPSILON on the target implementation,
that definition might result in the mantissa of "large" having fewer
significant digits than it has on mine, but that's not particularly
important.
 
> largell: 0x7fffffffffffffff
> middlingll: 0xabcdef01
 
> Greetings, Branimir.
 
With that change, the value of "large" on my machine changes to
0xa.bcdef0123456788p+16380, with a corresponding (HUGE) change to the
less significant digits of the decimal output, and the mantissa is
therefore 0xabcdef0123456788.
You'll get much different values for "max" and "large" on your system,
since LDBL_MAX is much smaller, but the qualitative comments I made
about those values should still be accurate. There's no guarantees,
since the behavior is undefined, but I would expect that the values of
"maxll" and "largell" will be unchanged.
Manfred <noname@add.invalid>: Oct 02 11:19PM +0200

On 10/2/2021 9:27 PM, Alf P. Steinbach wrote:
 
> It's /very/ late.
 
> There AFAIK is no suitable type name for the integer type with
> sufficient bits to represent the mantissa, or generally >N bits.
 
He meant the FType that is in the original post. I.e. the same floating
point type of the number to be analyzed.
 
Paavo Helde <myfirstname@osa.pri.ee>: Oct 02 10:57PM +0300

29.09.2021 12:46 Ian Collins kirjutas:
>> Writing the string buffer of 418 MB into a disk file: 146 ms
 
> Interesting, thanks for posting.  It's a similar ratio on my machine.  I
> can see that the Windows way of doing things is definitely more burdensome.
 
For curiosity, I also added a non-portable memory map variant to
timings. As expected, it beats all the other methods. On Windows it is
ca 21 times faster than ostream<<int streaming, on Linux it is just 3
times faster. It preallocates a large file in advance and trims it into
the correct size later, it might be one can yet shave off some cycles by
doing something smarter.
 
MSVC++ Win x64 Release:
Traditional streaming (ostream<<int): 16309 ms
Streaming with std::to_chars() directly into streambuf: 1353 ms
Collecting the content in a string buffer of 418 MB: 1123 ms
Writing the string buffer of 418 MB into a disk file: 668 ms
Serializing to memory-mapped file: 753 ms
Speedup of mmap, compared to ostream<<int: 21.6587 times
 
Linux g++ 8.3:
$ g++ -O3 -std=c++17 test7.cpp
$ ./a.out
Traditional streaming (ostream<<int): 2358 ms
Streaming with std::to_chars() directly into streambuf: 1142 ms
Collecting the content in a string buffer of 418 MB: 674 ms
Writing the string buffer of 418 MB into a disk file: 393 ms
Serializing to memory-mapped file: 772 ms
Speedup of mmap, compared to ostream<<int: 3.0544 times
 
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <charconv>
#include <chrono>
#include <cstdint>
#include <fstream>
#include <limits>
#include <stdexcept>
 
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>

No comments: