00001
00002
00003
00004
00005
00006 #ifndef REALROOT_EXTENDED_H_
00007 #define REALROOT_EXTENDED_H_
00008
00009 #include <cassert>
00010 #include <realroot/scalar.hpp>
00011
00012 namespace mmx {
00013
00014
00015 #define extended_check(A, B) \
00016 assert((A.c == 0 || B.c == 0 || A.c == B.c) && \
00017 (A.c != 0 || A.b == 0) && \
00018 (B.c != 0 || B.b == 0))
00019
00020
00021 #define common_root(A, B) \
00022 (A.c != 0 ? A.c : B.c)
00023
00024 template<class NT_>
00025 struct extended
00026 {
00027
00028
00029 typedef NT_ NT;
00030 typedef scalar<NT> T;
00031 typedef extended<NT> Self;
00032
00033 T a, b, c;
00034
00035 extended()
00036 {
00037 }
00038
00039 extended(const T &a_)
00040 : a(a_),
00041 b(T(0)),
00042 c(T(0))
00043 {
00044 }
00045
00046 extended(const T &a_, const T &b_, const T &c_)
00047 : a(a_),
00048 b(b_),
00049 c(c_)
00050 {
00051 }
00052
00053 static int signof(const T &x)
00054 {
00055 if (x > 0)
00056 return 1;
00057 else if (x < 0)
00058 return -1;
00059 else
00060 return 0;
00061 }
00062
00063 static int compare(const Self &lhs, const Self &rhs)
00064 {
00065 extended_check(lhs, rhs);
00066 Self delta = lhs - rhs;
00067
00068 if (delta.a == 0 && delta.b == 0) return 0;
00069
00070 if (delta.a == 0) return signof(delta.b);
00071 if (delta.b == 0) return signof(delta.a);
00072
00073 if (delta.a < 0 && delta.b < 0) return -1;
00074
00075 if (delta.a > 0 && delta.b > 0) return 1;
00076
00077 T aa = delta.a * delta.a;
00078 T bbc = delta.b * delta.b * delta.c;
00079 if (aa > bbc)
00080 return signof(delta.a);
00081 else
00082 return signof(delta.b);
00083 return 0;
00084 }
00085 };
00086
00087 template<class NT> inline
00088 bool operator == (const extended<NT> &lhs, const extended<NT> &rhs)
00089 {
00090 extended_check(lhs, rhs);
00091 return lhs.a == rhs.a && lhs.b == rhs.b;
00092 }
00093
00094 template<class NT> inline
00095 bool operator != (const extended<NT> &lhs, const extended<NT> &rhs)
00096 {
00097 return !(lhs == rhs);
00098 }
00099
00100 template<class NT> inline
00101 extended<NT> operator *(const extended<NT> &lhs, const extended<NT> &rhs)
00102 {
00103 extended_check(lhs, rhs);
00104 typename extended<NT>::T root = common_root(lhs, rhs);
00105 return extended<NT>(lhs.a * rhs.a + lhs.b * rhs.b * root,
00106 lhs.a * rhs.b + lhs.b * rhs.a,
00107 root);
00108 }
00109
00110 template<class NT> inline
00111 extended<NT> operator /(const extended<NT> &lhs, const extended<NT> &rhs)
00112 {
00113 extended_check(lhs, rhs);
00114 typename extended<NT>::T root = common_root(lhs, rhs);
00115 typename extended<NT>::T denominator = rhs.a * rhs.a - rhs.b * rhs.b * root;
00116 return extended<NT>((lhs.a * rhs.a - lhs.b * rhs.b * lhs.c) / denominator,
00117 (lhs.b * rhs.a - lhs.a * rhs.b) / denominator,
00118 root);
00119 }
00120
00121 template<class NT> inline
00122 extended<NT> operator +(const extended<NT> &lhs, const extended<NT> &rhs)
00123 {
00124 extended_check(lhs, rhs);
00125 typename extended<NT>::T root = common_root(lhs, rhs);
00126 return extended<NT>(lhs.a + rhs.a,
00127 lhs.b + rhs.b,
00128 root);
00129 }
00130
00131 template<class NT> inline
00132 extended<NT> operator -(const extended<NT> &lhs, const extended<NT> &rhs)
00133 {
00134 extended_check(lhs, rhs);
00135 typename extended<NT>::T root = common_root(lhs, rhs);
00136 return extended<NT>(lhs.a - rhs.a,
00137 lhs.b - rhs.b,
00138 root);
00139 }
00140
00141 template<class NT> inline
00142 extended<NT> operator -(const extended<NT> &lhs)
00143 {
00144 return extended<NT>(-lhs.a,
00145 -lhs.b,
00146 lhs.c);
00147 }
00148
00149 template<class NT> inline
00150 extended<NT> &operator <<= (extended<NT> &x, long int s)
00151 {
00152 x.a <<= s;
00153 x.b <<= s;
00154 return x;
00155 }
00156
00157 template<class NT> inline
00158 extended<NT> &operator += (extended<NT> &x, const extended<NT> &other)
00159 {
00160 x = x + other;
00161 return x;
00162 }
00163
00164 template<class NT> inline
00165 extended<NT> &operator -= (extended<NT> &x, const extended<NT> &other)
00166 {
00167 x = x - other;
00168 return x;
00169 }
00170
00171 template<class NT> inline
00172 extended<NT> &operator *= (extended<NT> &x, const extended<NT> &other)
00173 {
00174 x = x * other;
00175 return x;
00176 }
00177
00178 template<class NT> inline
00179 extended<NT> &operator /= (extended<NT> &x, const extended<NT> &other)
00180 {
00181 x = x / other;
00182 return x;
00183 }
00184
00185 template<class NT> inline
00186 bool operator <(const extended<NT> &lhs, const extended<NT> &rhs)
00187 {
00188 return extended<NT>::compare(lhs, rhs) < 0;
00189 }
00190
00191 template<class NT> inline
00192 bool operator <=(const extended<NT> &lhs, const extended<NT> &rhs)
00193 {
00194 return extended<NT>::compare(lhs, rhs) <= 0;
00195 }
00196
00197 template<class NT> inline
00198 bool operator >(const extended<NT> &lhs, const extended<NT> &rhs)
00199 {
00200 return extended<NT>::compare(lhs, rhs) > 0;
00201 }
00202
00203 template<class NT> inline
00204 bool operator >=(const extended<NT> &lhs, const extended<NT> &rhs)
00205 {
00206 return extended<NT>::compare(lhs, rhs) >= 0;
00207 }
00208
00209 #undef extended_check
00210 #undef common_root
00211 }
00212
00213 #endif // REALROOT_EXTENDED_H_