Last active
August 29, 2015 14:26
-
-
Save unvBell/6d21b854cf719d64ab06 to your computer and use it in GitHub Desktop.
UnitType
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <gtest/gtest.h> | |
#include "Unit.hpp" | |
using namespace bell::unit; | |
namespace { | |
template <typename T> using Number = Unit<T, 0, 0, 0>; | |
template <typename T> using Length = Unit<T, 1, 0, 0>; | |
template <typename T> using Mass = Unit<T, 0, 1, 0>; | |
template <typename T> using Time = Unit<T, 0, 0, 1>; | |
template <typename T> using Velocity = decltype(Length <T>{} / Time <T>{}); | |
template <typename T> using Acceleration = decltype(Velocity <T>{} / Time <T>{}); | |
template <typename T> using Momentum = decltype(Velocity <T>{} * Mass <T>{}); | |
template <typename T> using Force = decltype(Acceleration <T>{} * Mass <T>{}); | |
template <typename T> using Energy = decltype(Length <T>{} * Force <T>{}); | |
template <typename T> using Area = decltype(Length <T>{} * Length <T>{}); | |
template <typename T> using Volume = decltype(Area <T>{} * Length <T>{}); | |
template <typename T> using Density = decltype(Mass <T>{} / Volume <T>{}); | |
template <typename T> using Frequency = decltype(1. / Time<T>{}); | |
constexpr Length<double> operator""_m (long double v) noexcept { return { static_cast<double>(v) }; } | |
constexpr Mass <double> operator""_kg (long double v) noexcept { return { static_cast<double>(v) }; } | |
constexpr Time <double> operator""_sec (long double v) noexcept { return { static_cast<double>(v) }; } | |
} | |
TEST(Bell_Unit, Unit) { | |
using namespace std; | |
constexpr Acceleration <double> gravity = 9.8; | |
constexpr Length <double> height = 3._m + 2._m; | |
constexpr Mass <double> mass = 3._kg; | |
constexpr Energy <double> potential = mass * gravity * height; | |
constexpr Time <double> duration = 2._sec; | |
constexpr Velocity <double> velocity = gravity * duration; | |
constexpr Length <double> position = 1./2 * gravity * duration*duration; | |
constexpr Momentum <double> momentum = velocity * mass; | |
constexpr Energy <double> kinetic = 1./2 * mass * velocity*velocity; | |
constexpr Energy <double> mechanical = potential + kinetic; | |
static_assert(gravity == 9.8 , ""); | |
static_assert(height == 5.0 , ""); | |
static_assert(mass == 3.0 , ""); | |
static_assert(potential == 3.0*9.8*5.0 , ""); | |
static_assert(duration == 2.0 , ""); | |
static_assert(velocity == 9.8*2.0 , ""); | |
static_assert(position == 9.8*2.0*2.0/2 , ""); | |
static_assert(kinetic == 3.0*9.8*9.8*2.0*2.0/2, ""); | |
static_assert(mechanical == potential.get() + kinetic.get(), ""); | |
cout << endl; | |
cout << "gravity : " << gravity << endl; | |
cout << "height : " << height << endl; | |
cout << "mass : " << mass << endl; | |
cout << "potention energy : " << potential << endl; | |
cout << endl; | |
cout << "duration : " << duration << endl; | |
cout << "velocity : " << velocity << endl; | |
cout << "position : " << position << endl; | |
cout << "momentum : " << momentum << endl; | |
cout << "kinetic energy : " << kinetic << endl; | |
cout << endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <ostream> | |
namespace bell { namespace unit { | |
/** | |
* 単位 | |
*/ | |
template <typename Val, int L, int M, int T> | |
class Unit final { | |
Val val_; | |
public: | |
using ValueType = Val; | |
static constexpr int lengthDimension = L; | |
static constexpr int massDimension = M; | |
static constexpr int timeDimension = T; | |
// コンストラクタ | |
constexpr Unit() noexcept : val_() {} | |
constexpr Unit(const Val& val) noexcept : val_(val) {} | |
// 演算子 | |
constexpr Unit operator+() const noexcept { return +val; } | |
constexpr Unit operator-() const noexcept { return -val; } | |
Unit& operator++() noexcept { ++val_; return *this; } | |
Unit& operator--() noexcept { --val_; return *this; } | |
Unit operator++(int) noexcept { Val v = val_++; return v; } | |
Unit operator--(int) noexcept { Val v = val_--; return v; }; | |
constexpr auto operator+(const Unit& a) const noexcept -> Unit<decltype(val_+a.val_),L,M,T> { return val_+a.val_; } | |
constexpr auto operator-(const Unit& a) const noexcept -> Unit<decltype(val_-a.val_),L,M,T> { return val_-a.val_; } | |
template <typename U> constexpr auto operator*(const U& a) const noexcept -> Unit<decltype(val_*a),L,M,T> { return val_*a; } | |
template <typename U> constexpr auto operator/(const U& a) const noexcept -> Unit<decltype(val_/a),L,M,T> { return val_/a; } | |
template <typename U, int L_, int M_, int T_> constexpr auto operator*(const Unit<U,L_,M_,T_>& a) const noexcept -> Unit<decltype(val_*a.get()),L+L_,M+M_,T+T_> { return val_*a.get(); } | |
template <typename U, int L_, int M_, int T_> constexpr auto operator/(const Unit<U,L_,M_,T_>& a) const noexcept -> Unit<decltype(val_/a.get()),L-L_,M-M_,T-T_> { return val_/a.get(); } | |
template <typename U> friend constexpr auto operator*(const U& a, const Unit& b) noexcept -> Unit<decltype(a*b.val_), L, M, T> { return a*b.val_; } | |
template <typename U> friend constexpr auto operator/(const U& a, const Unit& b) noexcept -> Unit<decltype(a/b.val_),-L,-M,-T> { return a/b.val_; } | |
Unit& operator+=(const Unit& a) noexcept { return *this = *this+a; } | |
Unit& operator-=(const Unit& a) noexcept { return *this = *this-a; } | |
Unit& operator*=(const Unit<Val, 0, 0, 0>& a) noexcept { return *this = *this*a; } | |
Unit& operator/=(const Unit<Val, 0, 0, 0>& a) noexcept { return *this = *this/a; } | |
Unit& operator*=(const Val& a) noexcept { return *this = *this*a; } | |
Unit& operator/=(const Val& a) noexcept { return *this = *this/a; } | |
constexpr bool operator< (const Unit<Val, L, M, T>& a) const noexcept { return val_ < a.val_; } | |
constexpr bool operator<=(const Unit<Val, L, M, T>& a) const noexcept { return val_ <= a.val_; } | |
constexpr bool operator> (const Unit<Val, L, M, T>& a) const noexcept { return val_ > a.val_; } | |
constexpr bool operator>=(const Unit<Val, L, M, T>& a) const noexcept { return val_ >= a.val_; } | |
constexpr bool operator==(const Unit<Val, L, M, T>& a) const noexcept { return val_ == a.val_; } | |
constexpr bool operator!=(const Unit<Val, L, M, T>& a) const noexcept { return val_ != a.val_; } | |
constexpr explicit operator bool() const noexcept { | |
return !!val_; | |
} | |
constexpr Val* operator->() const noexcept { | |
return &val_; | |
} | |
template <typename Ch, typename Traits> | |
friend std::basic_ostream<Ch, Traits>& operator<<(std::basic_ostream<Ch, Traits>& os, const Unit& a) noexcept { | |
os << a.val_; | |
if(M) { | |
if(M < 0) os << Ch{'/'}; | |
os << Ch{'k'} << Ch{'g'}; | |
if(abs(M) != 1) os << Ch{'^'} << abs(M); | |
} | |
if(L) { | |
if(L < 0) os << Ch{'/'}; | |
else if(M) os << Ch{'*'}; | |
os << Ch{'m'}; | |
if(abs(L) != 1) os << Ch{'^'} << abs(L); | |
} | |
if(T) { | |
if(T < 0) os << Ch{'/'}; | |
else if(M || L) os << Ch{'*'}; | |
os << Ch{'s'}; | |
if(abs(T) != 1) os << Ch{'^'} << abs(T); | |
} | |
return os; | |
} | |
/** | |
* 値の取得 | |
* @return 現在保持している値 | |
*/ | |
constexpr Val get() const noexcept { | |
return val_; | |
} | |
/** | |
* 値の設定 | |
* @param val 設定する値 | |
* @return this参照 | |
*/ | |
Unit& set(const Val& val) noexcept { | |
val_ = val; | |
return *this; | |
} | |
}; | |
}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment