// -*- C++ -*-
//===----------------------------------------------------------------------===//
// C++23 Overlay Header: stdfloat
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP_STDFLOAT
#define _LIBCPP_STDFLOAT

#if __cplusplus >= 202100L

#include <cstddef>

namespace std {

// Standard floating-point types as per C++23

// float32_t is typically equivalent to float on most systems
#ifdef __STDCPP_FLOAT32_T__
    using float32_t = __float32;
#else
    // On most platforms, float is IEEE 754 single precision
    using float32_t = float;
#endif

// float64_t is typically equivalent to double on most systems
#ifdef __STDCPP_FLOAT64_T__
    using float64_t = __float64;
#else
    // On most platforms, double is IEEE 754 double precision
    using float64_t = double;
#endif

// float16_t and bfloat16_t may not be available on all platforms
#ifdef __STDCPP_FLOAT16_T__
    using float16_t = __float16;
#elif defined(__SIZEOF_FLOAT16__)
    // Some compilers may provide __float16 without the macro
    using float16_t = __float16;
#else
    // float16_t not available on this platform
    // Uncomment the following line to provide a fallback (not standard-compliant)
    // using float16_t = float;  // Fallback: not recommended
#endif

// bfloat16_t (brain float) - even less common
#ifdef __STDCPP_BFLOAT16_T__
    using bfloat16_t = __bfloat16;
#elif defined(__SIZEOF_BFLOAT16__)
    // Some compilers may provide __bfloat16
    using bfloat16_t = __bfloat16;
#else
    // bfloat16_t not available on this platform
#endif

// float128_t - rarely available, typically only on some 64-bit systems
#ifdef __STDCPP_FLOAT128_T__
    using float128_t = __float128;
#elif defined(__SIZEOF_FLOAT128__)
    // Some compilers may provide __float128
    using float128_t = __float128;
#else
    // float128_t not available on this platform
    // Could use long double as fallback on some platforms, but not portable
#endif

// Feature macro: define if any extended floating-point types are available
#if (defined(__STDCPP_FLOAT32_T__) || defined(__STDCPP_FLOAT64_T__) || \
     defined(__STDCPP_FLOAT16_T__) || defined(__STDCPP_BFLOAT16_T__) || \
     defined(__STDCPP_FLOAT128_T__) || defined(__SIZEOF_FLOAT16__) || \
     defined(__SIZEOF_BFLOAT16__) || defined(__SIZEOF_FLOAT128__))
    #define __cpp_lib_extended_floating_point 202306L
#else
    // At minimum, float32_t and float64_t are available
    #define __cpp_lib_extended_floating_point 202306L
#endif

} // namespace std

#endif // __cplusplus >= 202100L
#endif // _LIBCPP_STDFLOAT
