#include <iostream>
#include <cmath>
#include <type_traits>
#include <complex>
/* Common metafunctions: */
template<typename T>
struct zero;
template<typename T>
struct one;
template<typename LHS , typename RHS>
struct add;
template<typename LHS , typename RHS>
struct sub;
template<typename LHS , typename RHS>
struct mul;
template<int base , int exponent>
struct positive_pow : public std::integral_constant<long long int , base * positive_pow<base,exponent-1>::value> {};
template<int base>
struct positive_pow<base,0> : public std::integral_constant<long long int,1> {};
template<long long int number , int shift>
struct decimal_leftshift : public std::integral_constant<long long int,number * positive_pow<10, shift>::value> {};
template<long long int number , int shift>
struct decimal_rightshift : public std::integral_constant<long long int,number / positive_pow<10, shift>::value> {};
template<bool CONDITION , int NUMBER , int SHIFT>
struct decimal_shift_chooser
{
using shifter = decimal_leftshift<NUMBER,SHIFT>;
};
template<long long NUMBER , int SHIFT>
struct decimal_shift_chooser<false,NUMBER,SHIFT>
{
using shifter = decimal_rightshift<NUMBER,-SHIFT>;
};
template<int number , int shift>
struct decimal_shift
{
using shifter = typename decimal_shift_chooser<( shift >= 0 ) , number , shift>::shifter;
static const long long int value = shifter::value;
};
/* Fixed-point implementation: */
using fpbits = long long int;
using fbcount = unsigned int; //Fractional bits count (Precision)
const fbcount DEFAULT_FRACTIONAL_PRECISION = 8;
template<fpbits BITS , fbcount PRECISION = DEFAULT_FRACTIONAL_PRECISION>
struct fixed_point
{
operator float()
{
return (float)BITS * std::pow(10.0f,-(float)PRECISION);
};
};
template<int mantissa , int exponent = 0> // MANTISSA x 10^EXPONENT
using decimal = fixed_point<decimal_shift<mantissa , DEFAULT_FRACTIONAL_PRECISION + exponent>::value>;
template<fpbits BITS , fbcount PRECISION>
struct zero<fixed_point<BITS,PRECISION>> : public fixed_point<0,PRECISION> {};
template<fpbits BITS , fbcount PRECISION>
struct one<fixed_point<BITS,PRECISION>> : public fixed_point<decimal_leftshift<1,PRECISION>::value,PRECISION> {};
template<fpbits BITS1 , fpbits BITS2 , fbcount PRECISION>
struct add<fixed_point<BITS1,PRECISION> , fixed_point<BITS2,PRECISION>> : public fixed_point<BITS1+BITS2 , PRECISION> {};
template<fpbits BITS1 , fpbits BITS2 , fbcount PRECISION>
struct sub<fixed_point<BITS1,PRECISION> , fixed_point<BITS2,PRECISION>> : public fixed_point<BITS1-BITS2 , PRECISION> {};
template<fpbits BITS1 , fpbits BITS2 , fbcount PRECISION>
struct mul<fixed_point<BITS1,PRECISION> , fixed_point<BITS2,PRECISION>> : public fixed_point<decimal_rightshift<BITS1*BITS2,PRECISION>::value , PRECISION> {};
/* Example: */
using pi = decimal<3141592 , -6>; //3141592 x 10^-6 (3,141592)
using pi_2 = mul<pi,decimal<2>>;
using a = decimal<1,-3>;
using b = decimal<1,3>;
using c = mul<a,b>;
using d = sub<b,a>;
using e = add<a,b>;
int main()
{
std::cout << "pi: " << pi() << std::endl;
std::cout << "2*pi: " << pi_2() << std::endl;
std::cout << "a: " << a() << std::endl;
std::cout << "b: " << b() << std::endl;
std::cout << "a*b: " << c() << std::endl;
std::cout << "b-a: " << d() << std::endl;
std::cout << "a+b: " << e() << std::endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KI2luY2x1ZGUgPGNvbXBsZXg+CgovKiBDb21tb24gbWV0YWZ1bmN0aW9uczogKi8KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCB6ZXJvOwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RydWN0IG9uZTsKCgp0ZW1wbGF0ZTx0eXBlbmFtZSBMSFMgLCB0eXBlbmFtZSBSSFM+CnN0cnVjdCBhZGQ7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBMSFMgLCB0eXBlbmFtZSBSSFM+CnN0cnVjdCBzdWI7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBMSFMgLCB0eXBlbmFtZSBSSFM+CnN0cnVjdCBtdWw7CgoKdGVtcGxhdGU8aW50IGJhc2UgLCBpbnQgZXhwb25lbnQ+CnN0cnVjdCBwb3NpdGl2ZV9wb3cgOiBwdWJsaWMgc3RkOjppbnRlZ3JhbF9jb25zdGFudDxsb25nIGxvbmcgaW50ICwgYmFzZSAqIHBvc2l0aXZlX3BvdzxiYXNlLGV4cG9uZW50LTE+Ojp2YWx1ZT4ge307Cgp0ZW1wbGF0ZTxpbnQgYmFzZT4Kc3RydWN0IHBvc2l0aXZlX3BvdzxiYXNlLDA+IDogcHVibGljIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8bG9uZyBsb25nIGludCwxPiB7fTsKCnRlbXBsYXRlPGxvbmcgbG9uZyBpbnQgbnVtYmVyICwgaW50IHNoaWZ0PgpzdHJ1Y3QgZGVjaW1hbF9sZWZ0c2hpZnQgOiBwdWJsaWMgc3RkOjppbnRlZ3JhbF9jb25zdGFudDxsb25nIGxvbmcgaW50LG51bWJlciAqIHBvc2l0aXZlX3BvdzwxMCwgc2hpZnQ+Ojp2YWx1ZT4ge307Cgp0ZW1wbGF0ZTxsb25nIGxvbmcgaW50IG51bWJlciAsIGludCBzaGlmdD4Kc3RydWN0IGRlY2ltYWxfcmlnaHRzaGlmdCA6IHB1YmxpYyBzdGQ6OmludGVncmFsX2NvbnN0YW50PGxvbmcgbG9uZyBpbnQsbnVtYmVyIC8gcG9zaXRpdmVfcG93PDEwLCBzaGlmdD46OnZhbHVlPiB7fTsKCnRlbXBsYXRlPGJvb2wgQ09ORElUSU9OICwgaW50IE5VTUJFUiAsIGludCBTSElGVD4Kc3RydWN0IGRlY2ltYWxfc2hpZnRfY2hvb3Nlcgp7CiAgICB1c2luZyBzaGlmdGVyID0gZGVjaW1hbF9sZWZ0c2hpZnQ8TlVNQkVSLFNISUZUPjsKfTsKCnRlbXBsYXRlPGxvbmcgbG9uZyBOVU1CRVIgLCBpbnQgU0hJRlQ+CnN0cnVjdCBkZWNpbWFsX3NoaWZ0X2Nob29zZXI8ZmFsc2UsTlVNQkVSLFNISUZUPgp7CiAgICB1c2luZyBzaGlmdGVyID0gZGVjaW1hbF9yaWdodHNoaWZ0PE5VTUJFUiwtU0hJRlQ+Owp9OwoKdGVtcGxhdGU8aW50IG51bWJlciAsIGludCBzaGlmdD4Kc3RydWN0IGRlY2ltYWxfc2hpZnQKewogICAgdXNpbmcgc2hpZnRlciA9IHR5cGVuYW1lIGRlY2ltYWxfc2hpZnRfY2hvb3NlcjwoIHNoaWZ0ID49IDAgKSAsIG51bWJlciAsIHNoaWZ0Pjo6c2hpZnRlcjsKICAgIHN0YXRpYyBjb25zdCBsb25nIGxvbmcgaW50IHZhbHVlID0gc2hpZnRlcjo6dmFsdWU7Cn07CgovKiBGaXhlZC1wb2ludCBpbXBsZW1lbnRhdGlvbjogKi8KCnVzaW5nIGZwYml0cyA9IGxvbmcgbG9uZyBpbnQ7CnVzaW5nIGZiY291bnQgPSB1bnNpZ25lZCBpbnQ7IC8vRnJhY3Rpb25hbCBiaXRzIGNvdW50IChQcmVjaXNpb24pCgpjb25zdCBmYmNvdW50IERFRkFVTFRfRlJBQ1RJT05BTF9QUkVDSVNJT04gPSA4OyAKCnRlbXBsYXRlPGZwYml0cyBCSVRTICwgZmJjb3VudCBQUkVDSVNJT04gPSBERUZBVUxUX0ZSQUNUSU9OQUxfUFJFQ0lTSU9OPgpzdHJ1Y3QgZml4ZWRfcG9pbnQKewogICAgb3BlcmF0b3IgZmxvYXQoKQogICAgewogICAgICAgIHJldHVybiAoZmxvYXQpQklUUyAqIHN0ZDo6cG93KDEwLjBmLC0oZmxvYXQpUFJFQ0lTSU9OKTsKICAgIH07Cn07Cgp0ZW1wbGF0ZTxpbnQgbWFudGlzc2EgLCBpbnQgZXhwb25lbnQgPSAwPiAvLyBNQU5USVNTQSB4IDEwXkVYUE9ORU5UCnVzaW5nIGRlY2ltYWwgPSBmaXhlZF9wb2ludDxkZWNpbWFsX3NoaWZ0PG1hbnRpc3NhICwgREVGQVVMVF9GUkFDVElPTkFMX1BSRUNJU0lPTiArIGV4cG9uZW50Pjo6dmFsdWU+OyAKCgp0ZW1wbGF0ZTxmcGJpdHMgQklUUyAsIGZiY291bnQgUFJFQ0lTSU9OPgpzdHJ1Y3QgemVybzxmaXhlZF9wb2ludDxCSVRTLFBSRUNJU0lPTj4+IDogcHVibGljIGZpeGVkX3BvaW50PDAsUFJFQ0lTSU9OPiB7fTsKCnRlbXBsYXRlPGZwYml0cyBCSVRTICwgZmJjb3VudCBQUkVDSVNJT04+CnN0cnVjdCBvbmU8Zml4ZWRfcG9pbnQ8QklUUyxQUkVDSVNJT04+PiA6IHB1YmxpYyBmaXhlZF9wb2ludDxkZWNpbWFsX2xlZnRzaGlmdDwxLFBSRUNJU0lPTj46OnZhbHVlLFBSRUNJU0lPTj4ge307CgoKdGVtcGxhdGU8ZnBiaXRzIEJJVFMxICwgZnBiaXRzIEJJVFMyICwgZmJjb3VudCBQUkVDSVNJT04+CnN0cnVjdCBhZGQ8Zml4ZWRfcG9pbnQ8QklUUzEsUFJFQ0lTSU9OPiAsIGZpeGVkX3BvaW50PEJJVFMyLFBSRUNJU0lPTj4+IDogcHVibGljIGZpeGVkX3BvaW50PEJJVFMxK0JJVFMyICwgUFJFQ0lTSU9OPiB7fTsKCnRlbXBsYXRlPGZwYml0cyBCSVRTMSAsIGZwYml0cyBCSVRTMiAsIGZiY291bnQgUFJFQ0lTSU9OPgpzdHJ1Y3Qgc3ViPGZpeGVkX3BvaW50PEJJVFMxLFBSRUNJU0lPTj4gLCBmaXhlZF9wb2ludDxCSVRTMixQUkVDSVNJT04+PiA6IHB1YmxpYyBmaXhlZF9wb2ludDxCSVRTMS1CSVRTMiAsIFBSRUNJU0lPTj4ge307Cgp0ZW1wbGF0ZTxmcGJpdHMgQklUUzEgLCBmcGJpdHMgQklUUzIgLCBmYmNvdW50IFBSRUNJU0lPTj4Kc3RydWN0IG11bDxmaXhlZF9wb2ludDxCSVRTMSxQUkVDSVNJT04+ICwgZml4ZWRfcG9pbnQ8QklUUzIsUFJFQ0lTSU9OPj4gOiBwdWJsaWMgZml4ZWRfcG9pbnQ8ZGVjaW1hbF9yaWdodHNoaWZ0PEJJVFMxKkJJVFMyLFBSRUNJU0lPTj46OnZhbHVlICwgUFJFQ0lTSU9OPiB7fTsKCgovKiBFeGFtcGxlOiAqLwoKdXNpbmcgcGkgPSBkZWNpbWFsPDMxNDE1OTIgLCAtNj47IC8vMzE0MTU5MiB4IDEwXi02ICgzLDE0MTU5MikKdXNpbmcgcGlfMiA9IG11bDxwaSxkZWNpbWFsPDI+PjsKCnVzaW5nIGEgPSBkZWNpbWFsPDEsLTM+Owp1c2luZyBiID0gZGVjaW1hbDwxLDM+OwoKdXNpbmcgYyA9IG11bDxhLGI+Owp1c2luZyBkID0gc3ViPGIsYT47CnVzaW5nIGUgPSBhZGQ8YSxiPjsKICAgIAppbnQgbWFpbigpCnsKICAgIHN0ZDo6Y291dCA8PCAicGk6ICIgPDwgcGkoKSA8PCBzdGQ6OmVuZGw7CiAgICBzdGQ6OmNvdXQgPDwgIjIqcGk6ICIgPDwgcGlfMigpIDw8IHN0ZDo6ZW5kbDsKCiAgICBzdGQ6OmNvdXQgPDwgImE6ICIgPDwgYSgpIDw8IHN0ZDo6ZW5kbDsKICAgIHN0ZDo6Y291dCA8PCAiYjogIiA8PCBiKCkgPDwgc3RkOjplbmRsOwogICAgc3RkOjpjb3V0IDw8ICJhKmI6ICIgPDwgYygpIDw8IHN0ZDo6ZW5kbDsKICAgIHN0ZDo6Y291dCA8PCAiYi1hOiAiIDw8IGQoKSA8PCBzdGQ6OmVuZGw7CiAgICBzdGQ6OmNvdXQgPDwgImErYjogIiA8PCBlKCkgPDwgc3RkOjplbmRsOwp9