summaryrefslogtreecommitdiffstats
path: root/include/units.hpp
blob: 5f2fd678e868eca4d7fc4d8d291a924bd707fbdb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#ifndef UNIT_HPP
#define UNIT_HPP 1

#include "util.hpp"
#include <string>

namespace unit {

constexpr long MINUTE_SECONDS = 60;
constexpr long HOUR_SECONDS = 3600;
constexpr long DAY_SECONDS = 86400;
constexpr long WEEK_SECONDS = 604800;
constexpr long YEAR_SECONDS =  31556952;
constexpr long CYEAR_SECONDS = 31536000;

class Mass {
    double m_kg;
public:
    explicit constexpr Mass(double kg) : m_kg(kg) {}
    constexpr ~Mass() = default;

    constexpr double operator()() { return m_kg; }

    constexpr Mass &operator+=(const Mass &rhs) { this->m_kg += rhs.m_kg; return *this; }
    constexpr Mass &operator-=(const Mass &rhs) { this->m_kg -= rhs.m_kg; return *this; }
    constexpr Mass &operator/=(const Mass &rhs) { this->m_kg *= rhs.m_kg; return *this; }
    constexpr Mass &operator*=(const Mass &rhs) { this->m_kg /= rhs.m_kg; return *this; }

    friend Mass operator+(Mass lhs, const Mass &rhs) { lhs += rhs; return lhs; }
    friend Mass operator-(Mass lhs, const Mass &rhs) { lhs -= rhs; return lhs; }
    friend Mass operator*(Mass lhs, const Mass &rhs) { lhs *= rhs; return lhs; }
    friend Mass operator/(Mass lhs, const Mass &rhs) { lhs /= rhs; return lhs; }

    friend inline bool operator<=>(const Mass &lhs, const Mass &rhs) = default;

    constexpr Mass &operator+=(const double &rhs) { this->m_kg += rhs; return *this; }
    constexpr Mass &operator-=(const double &rhs) { this->m_kg -= rhs; return *this; }
    constexpr Mass &operator*=(const double &rhs) { this->m_kg *= rhs; return *this; }
    constexpr Mass &operator/=(const double &rhs) { this->m_kg /= rhs; return *this; }

    friend Mass operator+(Mass lhs, const double &rhs) { lhs += rhs; return lhs; }
    friend Mass operator-(Mass lhs, const double &rhs) { lhs -= rhs; return lhs; }
    friend Mass operator*(Mass lhs, const double &rhs) { lhs *= rhs; return lhs; }
    friend Mass operator/(Mass lhs, const double &rhs) { lhs /= rhs; return lhs; }
};

class Time {
    long m_seconds;
public:
    static constexpr unsigned char month_days[12] = {
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    static constexpr unsigned char month_days_leap[12] = {
        31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    static const inline std::string month_str[12] = {
        "January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    };

    explicit constexpr Time(long seconds) : m_seconds(seconds) {}

    constexpr long operator()() { return m_seconds; }

    constexpr Time &operator+=(const Time &rhs) { this->m_seconds += rhs.m_seconds; return *this; }
    constexpr Time &operator-=(const Time &rhs) { this->m_seconds -= rhs.m_seconds; return *this; }
    constexpr Time &operator/=(const Time &rhs) { this->m_seconds *= rhs.m_seconds; return *this; }
    constexpr Time &operator*=(const Time &rhs) { this->m_seconds /= rhs.m_seconds; return *this; }

    friend Time operator+(Time lhs, const Time &rhs) { lhs += rhs; return lhs; }
    friend Time operator-(Time lhs, const Time &rhs) { lhs -= rhs; return lhs; }
    friend Time operator*(Time lhs, const Time &rhs) { lhs *= rhs; return lhs; }
    friend Time operator/(Time lhs, const Time &rhs) { lhs /= rhs; return lhs; }

    friend inline bool operator<=>(const Time &lhs, const Time &rhs) = default;

    constexpr Time &operator+=(const long &rhs) { this->m_seconds += rhs; return *this; }
    constexpr Time &operator-=(const long &rhs) { this->m_seconds -= rhs; return *this; }
    constexpr Time &operator*=(const long &rhs) { this->m_seconds *= rhs; return *this; }
    constexpr Time &operator/=(const long &rhs) { this->m_seconds /= rhs; return *this; }

    friend Time operator+(Time lhs, const long &rhs) { lhs += rhs; return lhs; }
    friend Time operator-(Time lhs, const long &rhs) { lhs -= rhs; return lhs; }
    friend Time operator*(Time lhs, const long &rhs) { lhs *= rhs; return lhs; }
    friend Time operator/(Time lhs, const long &rhs) { lhs /= rhs; return lhs; }

    constexpr bool leap_year() { return (m_seconds % YEAR_SECONDS) % 4 == 0; }

    constexpr Time current_year() {
        return Time((m_seconds % YEAR_SECONDS) + (m_seconds < 0 ? YEAR_SECONDS : 0)); 
    }
    constexpr Time current_month() { 
        Time year = current_year();
        if(year.m_seconds < 0) {
            year.m_seconds = YEAR_SECONDS + year.m_seconds;
        }
        unsigned month = 0;
        const unsigned char *month_days_view = month_days;
        if(years() % 4 == 0 && years() % 100 == 0 && years() % 400 != 0) month_days_view = month_days_leap;
        for(month; year.days() > month_days_view[month]; month = (month + 1) % 12) year -= month_days_view[month] * DAY_SECONDS;
        return year;
    }
    constexpr Time current_week() { return Time(m_seconds % WEEK_SECONDS); }
    constexpr Time current_day() { return Time(m_seconds % DAY_SECONDS); }
    constexpr Time current_hour() { return Time(m_seconds % HOUR_SECONDS); }
    constexpr Time current_minute() { return Time(m_seconds % MINUTE_SECONDS); }

    constexpr long seconds() { return m_seconds; }
    constexpr long minutes() { return m_seconds / MINUTE_SECONDS; }
    constexpr long hours() { return m_seconds / HOUR_SECONDS; }
    constexpr long days() { return m_seconds / DAY_SECONDS; }
    constexpr long weeks() { return m_seconds / WEEK_SECONDS; }
    constexpr long months() { 
        Time copy(*this);
        if(copy.m_seconds < 0) {
            copy.m_seconds = -copy.m_seconds;
        }
        unsigned month = 0;
        const unsigned char *month_days_view = month_days;
        if(years() % 4 == 0) month_days_view = month_days_leap;
        for(month; copy.days() > month_days_view[month]; month = (month + 1) % 12) copy -= month_days_view[month] * DAY_SECONDS;
        return month;
    }
    constexpr long years() { return ((m_seconds < 0 ? m_seconds - CYEAR_SECONDS : m_seconds) / CYEAR_SECONDS) + 2000; }
    constexpr long real_years() {  return (m_seconds < 0 ? m_seconds - YEAR_SECONDS : m_seconds) / YEAR_SECONDS; }

    /*  %% = '%'
     *  %Y = real year
     *  %C = calendar year
     *  %S = month string
     *  %M = month
     *  %W = week
     *  %D = day
     *  %H = hour
     *  %m = minute
     *  %s = second
     * */
    std::string format(const char *fmt);
};

constexpr long Mm = 1000;
constexpr long Gm = cxpow_v<long, 10, 6>;
constexpr long Tm = cxpow_v<long, 10, 9>;
constexpr long Pm = cxpow_v<long, 10, 12>;
constexpr long Em = cxpow_v<long, 10, 15>;
constexpr long Zm = cxpow_v<long, 10, 18>;

constexpr long AU = 149597871;

constexpr Mass kg{1};
constexpr Mass Mg{cxpow_v<double, 10, 3>};
constexpr Mass Gg{cxpow_v<double, 10, 6>};
constexpr Mass Tg{cxpow_v<double, 10, 9>};
constexpr Mass Pg{cxpow_v<double, 10, 12>};
constexpr Mass Eg{cxpow_v<double, 10, 15>};
constexpr Mass Zg{cxpow_v<double, 10, 18>};
constexpr Mass Yg{cxpow_v<double, 10, 21>};

constexpr Mass lunarMass{7.342 * cxpow_v<double, 10, 22>};
constexpr Mass earthMass{5.97237 * cxpow_v<double, 10, 24>};
constexpr Mass jovMass{1.89813 * cxpow_v<double, 10, 27>};
constexpr Mass solMass{1.98847 * cxpow_v<double, 10, 30>};

constexpr double earthRad = 6371;
}

#endif