X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fcml%2Fet%2Fscalar_promotions.h;fp=src%2Fcml%2Fet%2Fscalar_promotions.h;h=55d033ca5ef52a93053baa679618e5f00f2e8c39;hp=0000000000000000000000000000000000000000;hb=0fffd0097d7b496454413e57b398c903ecc252e4;hpb=79becf045222f385da5a1b9eb79081f6f5266c86 diff --git a/src/cml/et/scalar_promotions.h b/src/cml/et/scalar_promotions.h new file mode 100644 index 0000000..55d033c --- /dev/null +++ b/src/cml/et/scalar_promotions.h @@ -0,0 +1,120 @@ +/* -*- C++ -*- ------------------------------------------------------------ + +Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ + +The Configurable Math Library (CML) is distributed under the terms of the +Boost Software License, v1.0 (see cml/LICENSE for details). + + *-----------------------------------------------------------------------*/ +/** @file + * @brief + */ + +#ifndef scalar_promotions_h +#define scalar_promotions_h + +#include + +namespace cml { +namespace et { + +namespace detail { + +/** @class IntPromote + * @brief Helper template to int-promote a type. + */ +template struct IntPromote +{ + /* Signed -> signed int, unsigned -> unsigned int: */ + typedef typename select_switch::result result; +}; + +} // namespace detail + +/** @class ScalarPromote + * @brief Template for compile-time type promotion via C promotion rules. + */ +template struct ScalarPromote +{ + + /* Integral-promote the types (if possible). */ + typedef typename detail::IntPromote::result E1; + typedef typename detail::IntPromote::result E2; + + /* If sizeof(long) == sizeof(unsigned int), promote to unsigned long. + * Otherwise, sizeof(long) > sizeof(int), so promote to long. + */ + typedef typename select_if::result uint_promotion; + + /* Do the selection on the promoted types: */ + typedef typename select_switch< + type_pair, + +#if defined(CML_USE_LONG_DOUBLE) + type_pair, long double, + type_pair, long double, + type_pair, long double, +#endif + + type_pair, double, + type_pair, double, + type_pair, double, + + type_pair, float, + type_pair, float, + type_pair, float, + + type_pair, void + + >::result float_filter; + + /* The promoted integral types really matter here: */ + typedef typename select_switch< + type_pair, + + type_pair, unsigned long, + type_pair, unsigned long, + type_pair, unsigned long, + + type_pair, long, + type_pair, uint_promotion, + type_pair, uint_promotion, + + type_pair, long, + type_pair, long, + + type_pair, unsigned int, + type_pair, unsigned int, + type_pair, unsigned int, + + type_pair, int, + type_pair, int, + type_pair, int, + + type_pair, void + + >::result int_filter; + + /* Deduce the final type: */ + typedef typename select_if< + same_type::is_true, + int_filter, float_filter>::result type; +}; + +} // namespace et +} // namespace cml + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp