terminal/src/inc/til/math.h
Dustin L. Howett (MSFT) dfc15780c7
add til::math, use it for float conversions to point, size (#5150)
This pull request introduces the `til::math` namespace, which provides some casting functions to be used in support of `til::point` and `til::size`. When point/size want to ingest a floating-point structure, they _must_ be instructed on how to convert those floating-point values into integers.

This enables:

```
Windows::Foundation::Point wfPoint = /* ... */;
til::point tp{ til::math::rounding, wfPoint };
```

Future thoughts: should the TilMath types be stackable? Right now, you cannot get "checked + rounding" behavior (where it throws if it doesn't fit) so everything is saturating.

## PR Checklist
* [x] Closes a request by Michael
* [x] I've discussed this with core contributors already
2020-03-27 22:48:49 +00:00

86 lines
3 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
namespace til
{
// The til::math namespace contains TIL math guidance casts;
// they are intended to be used as the first argument to
// floating-point universal converters elsewhere in the til namespace.
namespace math
{
namespace details
{
struct ceiling_t
{
template<typename O, typename T>
static O cast(T val)
{
if constexpr (std::is_floating_point_v<T>)
{
THROW_HR_IF(E_ABORT, ::std::isnan(val));
return ::base::saturated_cast<O>(::std::ceil(val));
}
else
{
return ::base::saturated_cast<O>(val);
}
}
};
struct flooring_t
{
template<typename O, typename T>
static O cast(T val)
{
if constexpr (std::is_floating_point_v<T>)
{
THROW_HR_IF(E_ABORT, ::std::isnan(val));
return ::base::saturated_cast<O>(::std::floor(val));
}
else
{
return ::base::saturated_cast<O>(val);
}
}
};
struct rounding_t
{
template<typename O, typename T>
static O cast(T val)
{
if constexpr (std::is_floating_point_v<T>)
{
THROW_HR_IF(E_ABORT, ::std::isnan(val));
return ::base::saturated_cast<O>(::std::round(val));
}
else
{
return ::base::saturated_cast<O>(val);
}
}
};
struct truncating_t
{
template<typename O, typename T>
static O cast(T val)
{
if constexpr (std::is_floating_point_v<T>)
{
THROW_HR_IF(E_ABORT, ::std::isnan(val));
}
return ::base::saturated_cast<O>(val);
}
};
}
static constexpr details::ceiling_t ceiling; // positives become more positive, negatives become less negative
static constexpr details::flooring_t flooring; // positives become less positive, negatives become more negative
static constexpr details::rounding_t rounding; // it's rounding, from math class
static constexpr details::truncating_t truncating; // drop the decimal point, regardless of how close it is to the next value
}
}