Update to v106r79 release.

byuu says:

This WIP is just work on nall/primitives ...

Basically, I'm coming to the conclusion that it's just not practical to
try and make Natural/Integer implicitly castable to primitive signed and
unsigned integers. C++ just has too many edge cases there.

I also want to get away from the problem of C++ deciding that all math
operations return 32-bit values, unless one of the parameters is 64-bit,
in which case you get a 64-bit value. You know, so things like
array[-1] won't end up accessing the 4 billionth element of the array.
It's nice to be fancy and minimally size operations (eg 32-bit+32-bit =
33-bit), but it's just too unintuitive. I think all
Natural<X>+Natural<Y> expessions should result in a Natural<64> (eg
natural) type.

nall/primitives/operators.hpp has been removed, and new
Natural<>Natural / Integer<>Integer casts exist. My feeling is that
signed and unsigned types should not be implicitly convertible where
data loss can occur. In the future, I think an integer8*natural8 is
fine to return an integer64, and the bitwise operators are probably all
fine between the two types. I could probably add
(Integer,Natural)+Boolean conversions as well.

To simplify expressions, there are new user-defined literals for _b
(boolean), _n (natural), _i (integer), _r (real), _n# (eg _n8),
_i# (eg _i8), _r# (eg _r32), and _s (nall::string).

In the long-term, my intention is to make the conversion and cast
constructors explicit for primitive types, but obviously that'll shatter
most of higan, so for now that won't be the case.

Something I can do in the future is allow implicit conversion and
casting to (u)int64_t. That may be a nice balance.
This commit is contained in:
Tim Allen 2019-01-15 15:33:20 +11:00
parent 6871e0e32a
commit 17fc6d8d51
10 changed files with 220 additions and 181 deletions

View File

@ -30,7 +30,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.78";
static const string Version = "106.79";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";

View File

@ -171,9 +171,10 @@ auto TLCS900H::instructionLoadCarry(Source source, Offset offset) -> void {
//note: an 8-bit lookup table is faster (when in L1/L2 cache), but much more code
auto TLCS900H::instructionMirror(Register<uint16> register) -> void {
auto data = load(register);
uint8 lo = (data.byte(0) * 0x80200802ull & 0x884422110ull) * 0x101010101ull >> 32;
uint8 hi = (data.byte(1) * 0x80200802ull & 0x884422110ull) * 0x101010101ull >> 32;
store(register, lo << 8 | hi << 0);
data = data << 1 & 0xaaaa | data >> 1 & 0x5555;
data = data << 2 & 0xcccc | data >> 2 & 0x3333;
data = data << 4 & 0xf0f0 | data >> 4 & 0x0f0f;
store(register, data << 8 | data >> 8);
}
template<typename Target, typename Source>

View File

@ -15,7 +15,7 @@ namespace nall {
#include <nall/primitives/integer.hpp>
#include <nall/primitives/real.hpp>
#include <nall/primitives/types.hpp>
//#include <nall/primitives/operators.hpp>
#include <nall/primitives/literals.hpp>
namespace nall {
template<int Bits> auto Natural<Bits>::integer() const -> Integer<Bits> { return Integer<Bits>(*this); }

View File

@ -16,8 +16,10 @@ template<int Requested> struct Integer {
static inline constexpr auto sign() -> utype { return 1ull << Precision - 1; }
inline Integer() : data(0) {}
template<int Bits> inline Integer(Integer<Bits> value) { data = mask(value); }
template<typename T> inline Integer(const T& value) { data = mask(value); }
explicit inline operator bool() const { return data; }
inline operator type() const { return data; }
inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; }
@ -45,7 +47,7 @@ template<int Requested> struct Integer {
template<typename T> inline auto& operator ^=(const T& value) { lhs = mask(lhs ^ rhs); return *this; }
template<typename T> inline auto& operator |=(const T& value) { lhs = mask(lhs | rhs); return *this; }
#undef lhs
#undef rfs
#undef rhs
inline auto bits(int lo, int hi) -> BitRange<Requested> { return {(utype&)data, lo, hi}; }
inline auto bit(int index) -> BitRange<Requested> { return {(utype&)data, index, index}; }
@ -78,4 +80,29 @@ private:
type data;
};
#define ALL 64
#define ADD 64 //LHS + RHS
#define INC 64 //1 + (LHS >= RHS ? LHS : RHS)
#define MAX 64 //LHS >= RHS ? LHS : RHS
#define MIN 64 //LHS <= RHS ? LHS : RHS
#define lhs (int64_t)(typename Integer<LHS>::type)l
#define rhs (typename Integer<RHS>::type)r
template<int LHS, int RHS> inline auto operator *(Integer<LHS> l, Integer<RHS> r) { return Integer<ADD>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator /(Integer<LHS> l, Integer<RHS> r) { return Integer<LHS>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator %(Integer<LHS> l, Integer<RHS> r) { return Integer<LHS>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator +(Integer<LHS> l, Integer<RHS> r) { return Integer<INC>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator -(Integer<LHS> l, Integer<RHS> r) { return Integer<INC>{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator<<(Integer<LHS> l, Integer<RHS> r) { return Integer<ALL>{lhs << rhs}; }
template<int LHS, int RHS> inline auto operator>>(Integer<LHS> l, Integer<RHS> r) { return Integer<LHS>{lhs >> rhs}; }
template<int LHS, int RHS> inline auto operator &(Integer<LHS> l, Integer<RHS> r) { return Integer<MAX>{lhs & rhs}; }
template<int LHS, int RHS> inline auto operator ^(Integer<LHS> l, Integer<RHS> r) { return Integer<MAX>{lhs ^ rhs}; }
template<int LHS, int RHS> inline auto operator |(Integer<LHS> l, Integer<RHS> r) { return Integer<MAX>{lhs | rhs}; }
#undef ALL
#undef ADD
#undef INC
#undef MAX
#undef MIN
#undef lhs
#undef rhs
}

View File

@ -0,0 +1,143 @@
#pragma once
namespace nall {
inline auto operator"" _b(unsigned long long value) { return boolean{value}; }
inline auto operator"" _n(unsigned long long value) { return natural{value}; }
inline auto operator"" _i(unsigned long long value) { return integer{value}; }
inline auto operator"" _r(long double value) { return real{value}; }
inline auto operator"" _n1(unsigned long long value) { return natural1{value}; }
inline auto operator"" _n2(unsigned long long value) { return natural2{value}; }
inline auto operator"" _n3(unsigned long long value) { return natural3{value}; }
inline auto operator"" _n4(unsigned long long value) { return natural4{value}; }
inline auto operator"" _n5(unsigned long long value) { return natural5{value}; }
inline auto operator"" _n6(unsigned long long value) { return natural6{value}; }
inline auto operator"" _n7(unsigned long long value) { return natural7{value}; }
inline auto operator"" _n8(unsigned long long value) { return natural8{value}; }
inline auto operator"" _n9(unsigned long long value) { return natural9{value}; }
inline auto operator"" _n10(unsigned long long value) { return natural10{value}; }
inline auto operator"" _n11(unsigned long long value) { return natural11{value}; }
inline auto operator"" _n12(unsigned long long value) { return natural12{value}; }
inline auto operator"" _n13(unsigned long long value) { return natural13{value}; }
inline auto operator"" _n14(unsigned long long value) { return natural14{value}; }
inline auto operator"" _n15(unsigned long long value) { return natural15{value}; }
inline auto operator"" _n16(unsigned long long value) { return natural16{value}; }
inline auto operator"" _n17(unsigned long long value) { return natural17{value}; }
inline auto operator"" _n18(unsigned long long value) { return natural18{value}; }
inline auto operator"" _n19(unsigned long long value) { return natural19{value}; }
inline auto operator"" _n20(unsigned long long value) { return natural20{value}; }
inline auto operator"" _n21(unsigned long long value) { return natural21{value}; }
inline auto operator"" _n22(unsigned long long value) { return natural22{value}; }
inline auto operator"" _n23(unsigned long long value) { return natural23{value}; }
inline auto operator"" _n24(unsigned long long value) { return natural24{value}; }
inline auto operator"" _n25(unsigned long long value) { return natural25{value}; }
inline auto operator"" _n26(unsigned long long value) { return natural26{value}; }
inline auto operator"" _n27(unsigned long long value) { return natural27{value}; }
inline auto operator"" _n28(unsigned long long value) { return natural28{value}; }
inline auto operator"" _n29(unsigned long long value) { return natural29{value}; }
inline auto operator"" _n30(unsigned long long value) { return natural30{value}; }
inline auto operator"" _n31(unsigned long long value) { return natural31{value}; }
inline auto operator"" _n32(unsigned long long value) { return natural32{value}; }
inline auto operator"" _n33(unsigned long long value) { return natural33{value}; }
inline auto operator"" _n34(unsigned long long value) { return natural34{value}; }
inline auto operator"" _n35(unsigned long long value) { return natural35{value}; }
inline auto operator"" _n36(unsigned long long value) { return natural36{value}; }
inline auto operator"" _n37(unsigned long long value) { return natural37{value}; }
inline auto operator"" _n38(unsigned long long value) { return natural38{value}; }
inline auto operator"" _n39(unsigned long long value) { return natural39{value}; }
inline auto operator"" _n40(unsigned long long value) { return natural40{value}; }
inline auto operator"" _n41(unsigned long long value) { return natural41{value}; }
inline auto operator"" _n42(unsigned long long value) { return natural42{value}; }
inline auto operator"" _n43(unsigned long long value) { return natural43{value}; }
inline auto operator"" _n44(unsigned long long value) { return natural44{value}; }
inline auto operator"" _n45(unsigned long long value) { return natural45{value}; }
inline auto operator"" _n46(unsigned long long value) { return natural46{value}; }
inline auto operator"" _n47(unsigned long long value) { return natural47{value}; }
inline auto operator"" _n48(unsigned long long value) { return natural48{value}; }
inline auto operator"" _n49(unsigned long long value) { return natural49{value}; }
inline auto operator"" _n50(unsigned long long value) { return natural50{value}; }
inline auto operator"" _n51(unsigned long long value) { return natural51{value}; }
inline auto operator"" _n52(unsigned long long value) { return natural52{value}; }
inline auto operator"" _n53(unsigned long long value) { return natural53{value}; }
inline auto operator"" _n54(unsigned long long value) { return natural54{value}; }
inline auto operator"" _n55(unsigned long long value) { return natural55{value}; }
inline auto operator"" _n56(unsigned long long value) { return natural56{value}; }
inline auto operator"" _n57(unsigned long long value) { return natural57{value}; }
inline auto operator"" _n58(unsigned long long value) { return natural58{value}; }
inline auto operator"" _n59(unsigned long long value) { return natural59{value}; }
inline auto operator"" _n60(unsigned long long value) { return natural60{value}; }
inline auto operator"" _n61(unsigned long long value) { return natural61{value}; }
inline auto operator"" _n62(unsigned long long value) { return natural62{value}; }
inline auto operator"" _n63(unsigned long long value) { return natural63{value}; }
inline auto operator"" _n64(unsigned long long value) { return natural64{value}; }
inline auto operator"" _i1(unsigned long long value) { return integer1{value}; }
inline auto operator"" _i2(unsigned long long value) { return integer2{value}; }
inline auto operator"" _i3(unsigned long long value) { return integer3{value}; }
inline auto operator"" _i4(unsigned long long value) { return integer4{value}; }
inline auto operator"" _i5(unsigned long long value) { return integer5{value}; }
inline auto operator"" _i6(unsigned long long value) { return integer6{value}; }
inline auto operator"" _i7(unsigned long long value) { return integer7{value}; }
inline auto operator"" _i8(unsigned long long value) { return integer8{value}; }
inline auto operator"" _i9(unsigned long long value) { return integer9{value}; }
inline auto operator"" _i10(unsigned long long value) { return integer10{value}; }
inline auto operator"" _i11(unsigned long long value) { return integer11{value}; }
inline auto operator"" _i12(unsigned long long value) { return integer12{value}; }
inline auto operator"" _i13(unsigned long long value) { return integer13{value}; }
inline auto operator"" _i14(unsigned long long value) { return integer14{value}; }
inline auto operator"" _i15(unsigned long long value) { return integer15{value}; }
inline auto operator"" _i16(unsigned long long value) { return integer16{value}; }
inline auto operator"" _i17(unsigned long long value) { return integer17{value}; }
inline auto operator"" _i18(unsigned long long value) { return integer18{value}; }
inline auto operator"" _i19(unsigned long long value) { return integer19{value}; }
inline auto operator"" _i20(unsigned long long value) { return integer20{value}; }
inline auto operator"" _i21(unsigned long long value) { return integer21{value}; }
inline auto operator"" _i22(unsigned long long value) { return integer22{value}; }
inline auto operator"" _i23(unsigned long long value) { return integer23{value}; }
inline auto operator"" _i24(unsigned long long value) { return integer24{value}; }
inline auto operator"" _i25(unsigned long long value) { return integer25{value}; }
inline auto operator"" _i26(unsigned long long value) { return integer26{value}; }
inline auto operator"" _i27(unsigned long long value) { return integer27{value}; }
inline auto operator"" _i28(unsigned long long value) { return integer28{value}; }
inline auto operator"" _i29(unsigned long long value) { return integer29{value}; }
inline auto operator"" _i30(unsigned long long value) { return integer30{value}; }
inline auto operator"" _i31(unsigned long long value) { return integer31{value}; }
inline auto operator"" _i32(unsigned long long value) { return integer32{value}; }
inline auto operator"" _i33(unsigned long long value) { return integer33{value}; }
inline auto operator"" _i34(unsigned long long value) { return integer34{value}; }
inline auto operator"" _i35(unsigned long long value) { return integer35{value}; }
inline auto operator"" _i36(unsigned long long value) { return integer36{value}; }
inline auto operator"" _i37(unsigned long long value) { return integer37{value}; }
inline auto operator"" _i38(unsigned long long value) { return integer38{value}; }
inline auto operator"" _i39(unsigned long long value) { return integer39{value}; }
inline auto operator"" _i40(unsigned long long value) { return integer40{value}; }
inline auto operator"" _i41(unsigned long long value) { return integer41{value}; }
inline auto operator"" _i42(unsigned long long value) { return integer42{value}; }
inline auto operator"" _i43(unsigned long long value) { return integer43{value}; }
inline auto operator"" _i44(unsigned long long value) { return integer44{value}; }
inline auto operator"" _i45(unsigned long long value) { return integer45{value}; }
inline auto operator"" _i46(unsigned long long value) { return integer46{value}; }
inline auto operator"" _i47(unsigned long long value) { return integer47{value}; }
inline auto operator"" _i48(unsigned long long value) { return integer48{value}; }
inline auto operator"" _i49(unsigned long long value) { return integer49{value}; }
inline auto operator"" _i50(unsigned long long value) { return integer50{value}; }
inline auto operator"" _i51(unsigned long long value) { return integer51{value}; }
inline auto operator"" _i52(unsigned long long value) { return integer52{value}; }
inline auto operator"" _i53(unsigned long long value) { return integer53{value}; }
inline auto operator"" _i54(unsigned long long value) { return integer54{value}; }
inline auto operator"" _i55(unsigned long long value) { return integer55{value}; }
inline auto operator"" _i56(unsigned long long value) { return integer56{value}; }
inline auto operator"" _i57(unsigned long long value) { return integer57{value}; }
inline auto operator"" _i58(unsigned long long value) { return integer58{value}; }
inline auto operator"" _i59(unsigned long long value) { return integer59{value}; }
inline auto operator"" _i60(unsigned long long value) { return integer60{value}; }
inline auto operator"" _i61(unsigned long long value) { return integer61{value}; }
inline auto operator"" _i62(unsigned long long value) { return integer62{value}; }
inline auto operator"" _i63(unsigned long long value) { return integer63{value}; }
inline auto operator"" _i64(unsigned long long value) { return integer64{value}; }
inline auto operator"" _r32(long double value) { return real32{value}; }
inline auto operator"" _r64(long double value) { return real32{value}; }
}

View File

@ -14,8 +14,10 @@ template<int Requested> struct Natural {
static inline constexpr auto mask() -> type { return ~0ull >> 64 - bits(); }
inline Natural() : data(0) {}
template<int Bits> inline Natural(Natural<Bits> value) { data = mask(value); }
template<typename T> inline Natural(const T& value) { data = mask(value); }
explicit inline operator bool() const { return data; }
inline operator type() const { return data; }
inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; }
@ -76,4 +78,29 @@ private:
type data;
};
#define ALL 64
#define ADD 64 //LHS + RHS
#define INC 64 //1 + (LHS >= RHS ? LHS : RHS)
#define MAX 64 //LHS >= RHS ? LHS : RHS
#define MIN 64 //LHS <= RHS ? LHS : RHS
#define lhs (uint64_t)(typename Natural<LHS>::type)l
#define rhs (typename Natural<RHS>::type)r
template<int LHS, int RHS> inline auto operator *(Natural<LHS> l, Natural<RHS> r) { return Natural<ADD>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator /(Natural<LHS> l, Natural<RHS> r) { return Natural<LHS>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator %(Natural<LHS> l, Natural<RHS> r) { return Natural<LHS>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator +(Natural<LHS> l, Natural<RHS> r) { return Natural<INC>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator -(Natural<LHS> l, Natural<RHS> r) { return Natural<INC>{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator<<(Natural<LHS> l, Natural<RHS> r) { return Natural<ALL>{lhs << rhs}; }
template<int LHS, int RHS> inline auto operator>>(Natural<LHS> l, Natural<RHS> r) { return Natural<LHS>{lhs >> rhs}; }
template<int LHS, int RHS> inline auto operator &(Natural<LHS> l, Natural<RHS> r) { return Natural<MAX>{lhs & rhs}; }
template<int LHS, int RHS> inline auto operator ^(Natural<LHS> l, Natural<RHS> r) { return Natural<MAX>{lhs ^ rhs}; }
template<int LHS, int RHS> inline auto operator |(Natural<LHS> l, Natural<RHS> r) { return Natural<MAX>{lhs | rhs}; }
#undef ALL
#undef ADD
#undef INC
#undef MAX
#undef MIN
#undef lhs
#undef rhs
}

View File

@ -1,174 +0,0 @@
#pragma once
namespace nall {
//attempt to keep Natural / Integer types when performing a math operation against another Natural / Integer or primitive type
//try not to lose any data through truncation (eg Natural<32> + Natural<32> -> Natural<64>)
//complex SFINAE is needed to prevent the creation of ambiguous operator overloads
#define Type PrimitiveType
#define Compatible PrimitiveCompatible
#define CastExpand PrimitiveCastExpand
#define CastShrink PrimitiveCastShrink
#define CastDouble PrimitiveCastDouble
#define CastLarger PrimitiveCastLarger
#define CastLesser PrimitiveCastLesser
template<typename T> struct Type {
using type = T;
static inline constexpr uint bits = 8 * sizeof(T);
};
template<> struct Type<Boolean> {
using type = typename Boolean::type;
static inline constexpr uint bits = Boolean::bits();
};
template<int Precision> struct Type<Natural<Precision>> {
using type = typename Natural<Precision>::type;
static inline constexpr uint bits = Natural<Precision>::bits();
};
template<int Precision> struct Type<Integer<Precision>> {
using type = typename Integer<Precision>::type;
static inline constexpr uint bits = Integer<Precision>::bits();
};
template<int Precision> struct Type<Real<Precision>> {
using type = typename Real<Precision>::type;
static inline constexpr uint bits = Real<Precision>::bits();
};
//compatible: SFINAE operator enable
template<typename LHS, typename RHS, typename = void> struct Compatible { static const bool value = false; };
template<int LHS, typename RHS> struct Compatible<Natural<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { static const bool value = true; };
template<typename LHS, int RHS> struct Compatible<LHS, Natural<RHS>, enable_if_t<is_integral_v<LHS>>> { static const bool value = true; };
template<int LHS, int RHS> struct Compatible<Natural<LHS>, Natural<RHS>> { static const bool value = true; };
template<int LHS, typename RHS> struct Compatible<Integer<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { static const bool value = true; };
template<typename LHS, int RHS> struct Compatible<LHS, Integer<RHS>, enable_if_t<is_integral_v<LHS>>> { static const bool value = true; };
template<int LHS, int RHS> struct Compatible<Integer<LHS>, Integer<RHS>> { static const bool value = true; };
//expand: LHS+RHS bits
template<typename LHS, typename RHS, typename = void> struct CastExpand { using type = void; };
template<int LHS, typename RHS> struct CastExpand<Natural<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Natural<LHS + Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastExpand<LHS, Natural<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Natural<Type<LHS>::bits + RHS>; };
template<int LHS, int RHS> struct CastExpand<Natural<LHS>, Natural<RHS>> { using type = Natural<LHS + RHS>; };
template<int LHS, typename RHS> struct CastExpand<Integer<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Integer<LHS + Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastExpand<LHS, Integer<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Integer<Type<LHS>::bits + RHS>; };
template<int LHS, int RHS> struct CastExpand<Integer<LHS>, Integer<RHS>> { using type = Integer<LHS + RHS>; };
//shrink: LHS-RHS bits
template<typename LHS, typename RHS, typename = void> struct CastShrink { using type = void; };
template<int LHS, typename RHS> struct CastShrink<Natural<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Natural<LHS - Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastShrink<LHS, Natural<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Natural<Type<LHS>::bits - RHS>; };
template<int LHS, int RHS> struct CastShrink<Natural<LHS>, Natural<RHS>> { using type = Natural<LHS - RHS>; };
template<int LHS, typename RHS> struct CastShrink<Integer<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Integer<LHS - Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastShrink<LHS, Integer<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Integer<Type<LHS>::bits - RHS>; };
template<int LHS, int RHS> struct CastShrink<Integer<LHS>, Integer<RHS>> { using type = Integer<LHS - RHS>; };
//double: 1+max(LHS,RHS) bits
template<typename LHS, typename RHS, typename = void> struct CastDouble { using type = void; };
template<int LHS, typename RHS> struct CastDouble<Natural<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Natural<1 + (LHS >= Type<RHS>::bits ? LHS : Type<RHS>::bits)>; };
template<typename LHS, int RHS> struct CastDouble<LHS, Natural<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Natural<1 + (Type<LHS>::bits >= RHS ? Type<LHS>::bits : RHS)>; };
template<int LHS, int RHS> struct CastDouble<Natural<LHS>, Natural<RHS>> { using type = Natural<1 + (LHS >= RHS ? LHS : RHS)>; };
template<int LHS, typename RHS> struct CastDouble<Integer<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Integer<1 + (LHS >= Type<RHS>::bits ? LHS : Type<RHS>::bits)>; };
template<typename LHS, int RHS> struct CastDouble<LHS, Integer<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Integer<1 + (Type<LHS>::bits >= RHS ? Type<LHS>::bits : RHS)>; };
template<int LHS, int RHS> struct CastDouble<Integer<LHS>, Integer<RHS>> { using type = Integer<1 + (LHS >= RHS ? LHS : RHS)>; };
//larger: max(LHS,RHS) bits
template<typename LHS, typename RHS, typename = void> struct CastLarger { using type = void; };
template<int LHS, typename RHS> struct CastLarger<Natural<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Natural<LHS >= Type<RHS>::bits ? LHS : Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastLarger<LHS, Natural<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Natural<Type<LHS>::bits >= RHS ? Type<LHS>::bits : RHS>; };
template<int LHS, int RHS> struct CastLarger<Natural<LHS>, Natural<RHS>> { using type = Natural<LHS >= RHS ? LHS : RHS>; };
template<int LHS, typename RHS> struct CastLarger<Integer<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Integer<LHS >= Type<RHS>::bits ? LHS : Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastLarger<LHS, Integer<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Integer<Type<LHS>::bits >= RHS ? Type<LHS>::bits : RHS>; };
template<int LHS, int RHS> struct CastLarger<Integer<LHS>, Integer<RHS>> { using type = Integer<LHS >= RHS ? LHS : RHS>; };
//lesser: min(LHS,RHS) bits
template<typename LHS, typename RHS, typename = void> struct CastLesser { using type = void; };
template<int LHS, typename RHS> struct CastLesser<Natural<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Natural<LHS <= Type<RHS>::bits ? LHS : Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastLesser<LHS, Natural<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Natural<Type<LHS>::bits <= RHS ? Type<LHS>::bits : RHS>; };
template<int LHS, int RHS> struct CastLesser<Natural<LHS>, Natural<RHS>> { using type = Natural<LHS <= RHS ? LHS : RHS>; };
template<int LHS, typename RHS> struct CastLesser<Integer<LHS>, RHS, enable_if_t<is_integral_v<RHS>>> { using type = Integer<LHS <= Type<RHS>::bits ? LHS : Type<RHS>::bits>; };
template<typename LHS, int RHS> struct CastLesser<LHS, Integer<RHS>, enable_if_t<is_integral_v<LHS>>> { using type = Integer<Type<LHS>::bits <= RHS ? Type<LHS>::bits : RHS>; };
template<int LHS, int RHS> struct CastLesser<Integer<LHS>, Integer<RHS>> { using type = Integer<LHS <= RHS ? LHS : RHS>; };
#define TP template<typename LHS, typename RHS, typename = enable_if_t<Compatible<LHS, RHS>::value>>
#define Source typename Type<LHS>::type
#define Expand typename CastExpand<LHS, RHS>::type
#define Shrink typename CastShrink<LHS, RHS>::type
#define Double typename CastDouble<LHS, RHS>::type
#define Larger typename CastLarger<LHS, RHS>::type
#define Lesser typename CastLesser<LHS, RHS>::type
#define TLE typename Type<typename CastExpand<LHS, RHS>::type>::type
#define TLN typename Type<LHS>::type
#define TRN typename Type<RHS>::type
#if 1
TP inline auto operator *(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs * (TRN)rhs}; }
TP inline auto operator /(const LHS& lhs, const RHS& rhs) -> Source { return {(TLN)lhs / (TRN)rhs}; }
TP inline auto operator %(const LHS& lhs, const RHS& rhs) -> Source { return {(TLN)lhs % (TRN)rhs}; }
TP inline auto operator +(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs + (TRN)rhs}; }
TP inline auto operator -(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs - (TRN)rhs}; }
TP inline auto operator<<(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs << (TRN)rhs}; }
TP inline auto operator>>(const LHS& lhs, const RHS& rhs) -> Source { return {(TLN)lhs >> (TRN)rhs}; }
TP inline auto operator &(const LHS& lhs, const RHS& rhs) -> Lesser { return {(TLN)lhs & (TRN)rhs}; }
TP inline auto operator ^(const LHS& lhs, const RHS& rhs) -> Larger { return {(TLN)lhs ^ (TRN)rhs}; }
TP inline auto operator |(const LHS& lhs, const RHS& rhs) -> Larger { return {(TLN)lhs | (TRN)rhs}; }
#endif
#if 0
TP inline auto operator *(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs * (TRN)rhs}; }
TP inline auto operator /(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs / (TRN)rhs}; }
TP inline auto operator %(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs % (TRN)rhs}; }
TP inline auto operator +(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs + (TRN)rhs}; }
TP inline auto operator -(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs - (TRN)rhs}; }
TP inline auto operator<<(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs << (TRN)rhs}; }
TP inline auto operator>>(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs >> (TRN)rhs}; }
TP inline auto operator &(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs & (TRN)rhs}; }
TP inline auto operator ^(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs ^ (TRN)rhs}; }
TP inline auto operator |(const LHS& lhs, const RHS& rhs) -> Expand { return {(TLE)lhs | (TRN)rhs}; }
#endif
#undef TP
#undef Source
#undef Expand
#undef Shrink
#undef Double
#undef Larger
#undef Lesser
#undef TLE
#undef TLN
#undef TRN
#undef Type
#undef Compatible
#undef CastExpand
#undef CastShrink
#undef CastDouble
#undef CastLarger
#undef CastLesser
}

View File

@ -34,4 +34,14 @@ private:
type data;
};
#define lhs (long double)(typename Real<LHS>::type)l
#define rhs (typename Real<RHS>::type)r
template<int LHS, int RHS> inline auto operator*(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator/(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator%(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator+(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator-(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs - rhs}; }
#undef lhs
#undef rhs
}

View File

@ -329,6 +329,8 @@ struct string_format : vector<string> {
inline auto append() -> type&;
};
inline auto operator"" _s(const char* value, std::size_t) -> string { return {value}; }
}
#include <nall/string/view.hpp>
@ -360,4 +362,4 @@ struct string_format : vector<string> {
#include <nall/string/markup/xml.hpp>
#include <nall/string/transform/cml.hpp>
#include <nall/string/transform/dml.hpp>
//#include <nall/string/transform/dml.hpp>

View File

@ -41,4 +41,7 @@ enum XlibConstants : int {
#undef None
#undef True
#undef MAX
#undef MIN
#endif