Skip to content

Instantly share code, notes, and snippets.

@burnpanck
Created November 24, 2019 16:11
Show Gist options
  • Save burnpanck/3dca9d272b0d894826221aaa8d309b7a to your computer and use it in GitHub Desktop.
Save burnpanck/3dca9d272b0d894826221aaa8d309b7a to your computer and use it in GitHub Desktop.
#include <vector>
#include <iostream>
#include <algorithm>
#include <cassert>
#include <units/dimensions/temperature.h>
#include <units/dimensions/time.h>
namespace units {
struct fahrenheit : named_scaled_derived_unit<fahrenheit, temperature, "F", ratio<5, 9>> {};
namespace literals {
constexpr auto operator""_F(unsigned long long l) { return quantity<fahrenheit, std::int64_t>(l); }
constexpr auto operator""_F(long double l) { return quantity<fahrenheit, long double>(l); } // TODO: conflicts with gcc GNU extension
} // namespace literals
} // namespace units
using namespace units;
namespace detail {
template <typename Unit>
struct scale_reference_point {};
template <typename Quantity>
static constexpr quantity<kelvin> scale_reference_point_v = scale_reference_point<typename Quantity::unit>::value;
template <>
struct scale_reference_point<fahrenheit> {
static constexpr quantity<kelvin> value = 255.372_K;
};
template <>
struct scale_reference_point<kelvin> {
static constexpr quantity<kelvin> value = 0._K;
};
} // namespace detail
template <typename T>
struct is_absolute : std::false_type {};
template <typename T>
static constexpr bool is_absolute_v = is_absolute<T>::value;
template <typename Unit>
struct absolute {
public:
using offset_type = Unit;
explicit constexpr absolute(offset_type const &v) : offset(v) {}
template <typename V>
constexpr std::enable_if_t<!is_absolute_v<V>,absolute> operator+(V const &delta) const {
return absolute(offset + delta);
}
template <typename V>
constexpr std::enable_if_t<!is_absolute_v<V>,absolute> operator-(V const &delta) const {
return absolute(offset - delta);
}
template <typename V>
constexpr std::enable_if_t<is_absolute_v<V>,offset_type> operator-(V const &other) const {
return offset - other.template to_scale<offset_type>().offset_to_reference();
}
template <typename T>
constexpr absolute<T> to_scale() const {
return absolute<T>(
offset + (
::detail::scale_reference_point_v<offset_type>
- ::detail::scale_reference_point_v<T>
)
);
}
constexpr offset_type offset_to_reference() const {
return offset;
}
private:
offset_type offset; // offset from reference value
};
template <typename T>
struct is_absolute<absolute<T>> : std::true_type {};
/*
get average temperature
( argument for explicit affine quantities)
*/
// https://en.wikipedia.org/wiki/Exponential_smoothing
struct filter{
filter(double k): m_k{k}{ assert( (0 <= k) && (k <= 1));}
template <typename T, typename R>
T operator()( T const & lhs, R const & rhs)const
{
return lhs + (rhs-lhs) * (1.0-m_k);
}
private:
double const m_k;
};
template <typename T, typename T1>
void update(T1 & out, std::vector<T> const & v , double const & filter_k)
{
out = std::accumulate(v.begin(),v.end(),out,filter{filter_k});
}
namespace {
typedef absolute<quantity<kelvin>> K;
typedef absolute<quantity<fahrenheit>> F;
typedef quantity<second> s;
double filter_k = 0.9;
K current_temperature(270.0_K);
s current_time = 1000.0s;
}
int main()
{
std::vector<F> new_values_F = {F(32._F), F(33._F), F(33._F), F(32._F)};
for (; current_time < 1005s; ++current_time){
update(current_temperature,new_values_F, filter_k);
std::cout << "temperature at " << current_time << " = " << current_temperature.offset_to_reference() <<'\n';
}
std::vector<K> new_values = {K(270._K),K(271._K),K(270._K),K(271._K),K(270._K),K(270._K)};
for (; current_time < 1010s; ++current_time){
update(current_temperature,new_values, filter_k);
std::cout << "temperature at " << current_time << " = " << current_temperature.offset_to_reference() <<'\n';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment