Boost logo

Boost :

From: Gero Peterhoff (g.peterhoff_at_[hidden])
Date: 2022-12-26 17:01:52


Am 26.12.22 um 14:18 schrieb John Maddock via Boost:
> On 26/12/2022 12:57, Gero Peterhoff via Boost wrote:
>> Am 25.12.22 um 09:45 schrieb Mathias Gaunard:
>>> On Sat, 24 Dec 2022, 18:38 Gero Peterhoff via Boost, <boost_at_[hidden] <mailto:boost_at_[hidden]>> wrote:
>>>
>>>     Hi John,
>>>     I had already addressed a similar topic and it is a good thing that this is brought up again or that other users see it that way too.
>>>     In principle, as much as possible should be consolidated and simplified (here merging config + predef) in order to be able to provide uniform interfaces/macros without the user having to dig around in the internals of boost.
>>>
>>>     Example: There is BOOST_HAS_FLOAT128+BOOST_HAS_INT128 and BOOST_NO_INT64_T.
>>>     It would make sense to provide a complete set for BOOST_HAS_FLOATxxx and BOOST_HAS_INTxxx
>>>
>>>
>>> Boost.Config uses NO for lack of standard features and HAS for extensions.
>>>
>>>
>>
>> OK. But that's what I mean: the user doesn't care whether a type is only available via an extension or not. He just wants to check whether this type is available -> uniform named macros.
>> Would it be legitimate to introduce BOOST_NO_FLOAT128_T + BOOST_NO_INT128_T and other (like BOOST_NO_INT64_T) to do this?
>
> I guess in principle, since there is no real guarantee that there are any such types, these would all be BOOST_HAS_ macros.
>
> However, I have two questions:
>
> 1) Which Boost library need this?  Generally speaking Config is there for configuring Boost libraries, and as mentioned early in this topic, wasn't originally intended for end-user use.
>
> 2) How would we implement this?  Short of clairvoyance, I don't see how this is possible in the general case for all the integer and floating point widths.
>
> Also, is this not already largely solved in the integer case by <cstdint> ?
>
> In the floating point case, the only major questions, are:
>
> * Do we have __float128 as an extension: this is already covered.
>
> * Is long double a __float128: that can easily determined by querying LDBL_MANT_DIG
>
> What am I missing?
>
> John.

Hi John,
Basically, I'm all about consistency.

integer
Apparently not all platforms have u/int64_t, hence BOOST_NO_INT64_T. Something similar could (I'm not sure) also apply to u/int8_t, eg 16-bit DSPs with CHAR_BIT==16 -> BOOST_NO_INT8_T.
I don't know of any platforms for u/int16/32_t that don't support it, but you never know ... maybe you know which ones.

float
In <boost/math/cstdfloat/cstdfloat_types.hpp> there is BOOST_CSTDFLOAT_HAS_FLOATxxx_NATIVE_TYPE, but then they become undefined. I use BOOST_CSTDFLOAT_FLOATxxx_NATIVE_TYPE. ugly.
So we need BOOST_NO_FLOATxxx_T.


I'll update my config_integer.hpp + config_float.hpp and then send them to you.


In addition, then stand for
float: boost::float128_t + boost::float128_type + boost::math::cstdfloat::detail::float_internal128_t are available
integer: only boost::(u)int128_type, but no boost::(u)int128_t
It would make sense to consolidate this so that there is only boost::xxx128_t and no boost::xxx128_type to eliminate the redundancies and stick to the standard naming scheme.


I would also like to provide macros/traits that check whether a type is natively available on the platform, eg BOOST_NO_NATIVE_xxx_T/is_native. This is especially useful with the float types from std (C++23 stdfloat). Eg I have a complicated algorithm
template <std::floating_point Type> Type foo(const Type arg);
If I call this with Type=std::(b)float16_t and these are not native, the emulation/conversion to/from float is constantly called within foo. This is slow and inaccurate. With the checks I can then implement (pseudo-code):
template <std::floating_point Type> Type foo(const Type arg)
{
if (Type == std::(b)float16_t && !is_native_v<Type>) using type = float;
else using type = Type;

return Type(detail::foo_impl(type(arg));
}
or foo specialize.



There also seems to be an issue with <boost/math/tools/promotion.hpp>.
a) promote_arg returns the correct type
b) for Type=boost::float16_t or std::(b)float16_t deliver
promote_args_2<Type, Type> -> float
promote_args<Type, Type...> -> float
Shouldn't that be Type? See eg <boost/math/special_functions/cbrt.hpp>:

template <typename T, typename Policy>
inline typename tools::promote_args<T>::type cbrt(T z, const Policy& pol)
{
     using result_type = typename tools::promote_args<T>::type;
     using value_type = typename policies::evaluation<result_type, Policy>::type;
     return static_cast<result_type>(detail::cbrt_imp(value_type(z), pol));
}

template <typename T>
inline typename tools::promote_args<T>::type cbrt(T z)
{
     return cbrt(z, policies::policy<>());
}


thx & regards
Gero




Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk