// scientific_units2.cpp : Defines the entry point for the console application.
// with user-defined literals
#include<iostream>
#include<string>
#include <sstream>
#include <iomanip>
using namespace std;
//internally for everything use SI units.
//mass in kilograms,
//time in seconds
//length in meters
template<int M, int L, int T>
class Quantity
{
public:
constexpr Quantity(double val) : value(val){}
constexpr Quantity& operator+=(const Quantity& rhs)
{
value+=rhs.value;
return *this;
}
constexpr Quantity& operator-=(const Quantity& rhs)
{
value-=rhs.value;
return *this;
}
constexpr double Convert(const Quantity& rhs)
{
return value/rhs.value;
}
constexpr double getValue() const
{
return value;
}
private:
double value;
};
template <int M, int L, int T>
constexpr Quantity<M,L,T> operator+(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return Quantity<M,L,T>(lhs)+=rhs;
}
template <int M, int L, int T>
constexpr Quantity<M,L,T> operator-(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return Quantity<M,L,T>(lhs)-=rhs;
}
template <int M1, int L1, int T1, int M2, int L2, int T2>
constexpr Quantity<M1+M2,L1+L2,T1+T2> operator*(const Quantity<M1,L1,T1>& lhs, const Quantity<M2,L2,T2>& rhs)
{
return Quantity<M1+M2,L1+L2,T1+T2>(lhs.getValue()*rhs.getValue());
}
template <int M, int L, int T>
constexpr Quantity<M,L,T> operator*(const double& lhs, const Quantity<M,L,T>& rhs)
{
return Quantity<M,L,T>(lhs*rhs.getValue());
}
template <int M1, int L1, int T1, int M2, int L2, int T2>
constexpr Quantity<M1-M2,L1-L2,T1-T2> operator/(const Quantity<M1,L1,T1>& lhs, const Quantity<M2,L2,T2>& rhs)
{
return Quantity<M1-M2,L1-L2,T1-T2>(lhs.getValue()/rhs.getValue());
}
template <int M, int L, int T>
constexpr Quantity<-M, -L, -T> operator/(double x, const Quantity<M,L,T>& rhs)
{
return Quantity<-M,-L,-T>(x/rhs.getValue());
}
template <int M, int L, int T>
constexpr Quantity<M, L, T> operator/(const Quantity<M,L,T>& rhs, double x)
{
return Quantity<M,L,T>(rhs.getValue()/x);
}
template <int M, int L, int T>
constexpr bool operator==(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return (lhs.getValue()==rhs.getValue());
}
template <int M, int L, int T>
constexpr bool operator!=(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return (lhs.getValue()!=rhs.getValue());
}
template <int M, int L, int T>
constexpr bool operator<=(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return lhs.getValue()<=rhs.getValue();
}
template <int M, int L, int T>
constexpr bool operator>=(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return lhs.getValue()>=rhs.getValue();
}
template <int M, int L, int T>
constexpr bool operator< (const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return lhs.getValue()<rhs.getValue();
}
template <int M, int L, int T>
constexpr bool operator> (const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
return lhs.getValue()>rhs.getValue();
}
typedef Quantity<1,0,0> Mass;
typedef Quantity<0,1,0> Length;
typedef Quantity<0,2,0> Area;
typedef Quantity<0,3,0> Volume;
typedef Quantity<0,0,1> Time;
typedef Quantity<0,1,-1> Speed;
typedef Quantity<0,1,-2> Acceleration;
typedef Quantity<0,0,-1> Frequency;
typedef Quantity<1,1,-2> Force;
typedef Quantity<1,-1,-2> Pressure;
//length units - verify the constants
constexpr Length metre(1.0);
constexpr Length decimetre = metre/10;
constexpr Length centimetre = metre/100;
constexpr Length millimetre = metre/1000;
constexpr Length kilometre = 1000 * metre;
constexpr Length inch = 2.54 * centimetre;
constexpr Length foot = 12 * inch;
constexpr Length yard = 3 * foot;
constexpr Length mile = 5280 * foot;
constexpr Frequency Hz(1.0);
constexpr Area kilometre2 = kilometre*kilometre;
constexpr Area metre2 = metre*metre;
constexpr Area decimetre2 = decimetre*decimetre;
constexpr Area centimetre2 = centimetre*centimetre;
constexpr Area millimetre2 = millimetre * millimetre;
constexpr Area inch2 =inch*inch;
constexpr Area foot2 = foot*foot;
constexpr Area mile2 = mile*mile;
constexpr Volume kilometre3 = kilometre2*kilometre;
constexpr Volume metre3 = metre2*metre;
constexpr Volume decimetre3 = decimetre2*decimetre;
constexpr Volume litre = decimetre3;
constexpr Volume centimetre3 = centimetre2*centimetre;
constexpr Volume millimetre3 = millimetre2 * millimetre;
constexpr Volume inch3 =inch2*inch;
constexpr Volume foot3 = foot2*foot;
constexpr Volume mile3 = mile2*mile;
//time units
constexpr Time second(1.0);
constexpr Quantity<0,0,2> second2(1.0);
constexpr Time minute = 60 * second;
constexpr Time hour = 60 * minute;
constexpr Time day = 24 * hour;
//mass units
constexpr Mass kg(1.0);
constexpr Mass gramme = 0.001 * kg;
constexpr Mass tonne = 1000 * kg;
constexpr Mass ounce = 0.028349523125 * kg;
constexpr Mass pound = 16 * ounce;
constexpr Mass stone = 14 * pound;
constexpr Length operator"" _mm(long double x) { return x*millimetre; }
constexpr Length operator"" _cm(long double x) { return x*centimetre; }
constexpr Length operator"" _m(long double x) { return x*metre; }
constexpr Length operator"" _km(long double x) { return x*kilometre; }
constexpr Length operator"" _mi(long double x) { return x*mile; }
constexpr Length operator"" _yd(long double x) { return x*yard; }
constexpr Length operator"" _ft(long double x) { return x*foot; }
constexpr Length operator"" _in(long double x) { return x*inch; }
constexpr Speed operator"" _mps(long double x) { return Speed(x); };
constexpr Speed operator"" _miph(long double x) { return x*mile/hour; };
constexpr Speed operator"" _kmph(long double x) { return x*kilometre/hour; };
constexpr Frequency operator"" _Hz(long double x) { return Frequency(x); };
constexpr Time operator"" _s(long double x) { return Time(x); };
constexpr Time operator"" _min(long double x) { return x*minute; };
constexpr Time operator"" _h(long double x) { return x*hour; };
constexpr Time operator"" _day(long double x) { return x*day; };
constexpr Mass operator"" _kg(long double x) { return Mass(x); };
constexpr Mass operator"" _g(long double x) { return x*gramme; };
constexpr Mass operator"" _t(long double x) { return x*tonne; };
constexpr Mass operator"" _oz(long double x) { return x*ounce; };
constexpr Mass operator"" _lb(long double x) { return x*pound; };
constexpr Mass operator"" _st(long double x) { return x*stone; };
constexpr Acceleration operator"" _mps2(long double x) { return Acceleration(x); };
#define ConvertTo(_x, _y) (_x).Convert(1.0_##_y)
constexpr long double operator "" _pi(long double x) { return x * 3.1415926535897932384626433832795;}
constexpr long double operator "" _pi(unsigned long long int x) { return x * 3.1415926535897932384626433832795;}
constexpr long double operator "" _sq(long double x) { return x * x;}
constexpr unsigned long long int operator "" _sq(unsigned long long x) { return x * x;}
constexpr unsigned long long ToBinary(unsigned long long x, const char* s)
{
return (!*s ? x : ToBinary(x + x + (*s =='1'? 1 : 0), s+1));
}
constexpr unsigned long long int operator "" _b(const char* s) { return ToBinary(0,s);}
int main()
{
Length length = 100000.0_cm;
//Length LengthinFeet = LengthinCMs*convert(centimetre, foot);
std::cout << std::setprecision(15) << " 100000*centimetre = " << ConvertTo(length,ft) << " feet" << std::endl;
//get in terms of miles and feet
double total_in_miles = ConvertTo(length,mi);
double total_in_feet = ConvertTo(length,ft);
cout << total_in_miles << " miles" << endl;
cout << total_in_feet << " feet" << endl;
std::cout << " 1 foot = " << ConvertTo(1.0_ft,cm) << " cm" << std::endl;
Length Length100 = 100.0_km;
Time time = 2.0_h;
Speed sp1 = Length100 / time; // metre/second
cout << "100 km in 2 hours: " << ConvertTo(sp1,kmph) << " km/hour" << endl;
cout << "100 km in 2 hours: " << ConvertTo(sp1,miph) << " mile/hour" << endl;
Frequency fr1 = 100.0_Hz;
Time interval = 1.0/fr1;
cout << "frequency (1/s): " << ConvertTo(fr1,Hz) << endl;
cout << "interval (s): " << ConvertTo(interval,s) << endl;
Acceleration a1 = 9.8_mps2;
cout << "accelaration (m/s2): " << ConvertTo(a1,mps2) << endl;
cout << "1 mile: " << ConvertTo(1.0_mi, m) << " metres" << endl;
cout << "my mass: " << ConvertTo(80.0_kg,kg) << " kg" << endl;
cout << "my mass: " << ConvertTo(80.0_kg,st) << " stone" << endl;
cout << "my mass: " << ConvertTo(80.0_kg,lb) << " pounds" << endl;
cout << "one pound in grammes: " << ConvertTo(1.0_lb, g) << endl;
cout << "one pound in kg: " << ConvertTo(1.0_lb,kg) << endl;
cout << "one pound in ounces: " << ConvertTo(1.0_lb,oz) << endl;
std::cout << "20 miles = " << ConvertTo(20.0_mi,m) << " metres" << std::endl;
std::cout << "20 miles = " << ConvertTo(20.0_mi,km) << " kilometres" << std::endl;
std::cout << "20 miles = " << ConvertTo(20.0_mi,yd) << " yards" << std::endl;
std::cout << "100 inches = " << ConvertTo(100.0_in,mi) << " miles" << std::endl;
std::cout << "299792458 metres per second = " << ConvertTo(299792458.0_mps,kmph) << " km/h" << std::endl;
std::cout << "299792458 metres per second = " << ConvertTo(299792458.0_mps,miph) << " miles/h" << std::endl;
std::cout << "3.5 hours * 3 miles/hour = " << ConvertTo(3.5_h * 3.0_miph, mi) << " miles" << std::endl;
std::cout << "(3.5 metres/s) / (2 sec) = " << ConvertTo(3.5_mps/2.0_s, mps2) << " m/s2" << std::endl;
std::cout << "2.0 pi = " << 2.0_pi << std::endl;
std::cout << "2 pi = " << 2_pi << std::endl;
std::cout << "-2.0 pi = " << -2_pi << std::endl;
std::cout << "-2.5 pi = " << -2.5_pi << std::endl;
std::cout << " 4^2 = " << 4_sq << std::endl;
std::cout << " 2.5^2 = " << 2.5_sq << std::endl;
std::cout << " 29^2 = " << 29_sq << std::endl;
std::cout << "1101(2) = " << 1101_b << std::endl;
std::cout << "1111 1111 1111 1111 1111(2) = " << std::hex << 11111111111111111111_b << "(16)" << std::endl;
std::cout << "10 1010 1010 1010 1010(2) = " << std::hex << 101010101010101010_b << "(16)" << std::endl;
return 0;
}