00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef MORE_MATH_QTYPES_H
00032 #define MORE_MATH_QTYPES_H
00033
00034 #include <stdexcept>
00035 #include <iosfwd>
00036 #include <more/bits/mathbits.h>
00037 #include <more/io/fwd.h>
00038
00039
00040 namespace more {
00041 namespace math {
00042
00043 extern "C" {
00044 double sixj_2j(int, int, int, int, int, int);
00045 double ninej_2j(int, int, int, int, int, int, int, int, int);
00046 double clebsch_2j(int, int, int, int, int, int);
00047 double threejm_2j(int, int, int, int, int, int);
00048 }
00049
00050 struct halfint;
00051 struct pm_half;
00052
00053 struct half_tag {
00054 operator halfint();
00055 operator float() const { return .5f; }
00056 operator double() const { return .5; }
00057 operator long double() const { return .5l; }
00058 };
00059 extern half_tag half;
00060 struct minus_half_tag {
00061 operator halfint();
00062 operator float() const { return -.5f; }
00063 operator double() const { return -.5; }
00064 operator long double() const { return -.5l; }
00065 };
00066
00067 inline minus_half_tag
00068 operator-(half_tag) { return minus_half_tag(); }
00069 inline half_tag
00070 operator+(half_tag) { return half_tag(); }
00071 inline half_tag
00072 operator-(minus_half_tag) { return half_tag(); }
00073 inline minus_half_tag
00074 operator+(minus_half_tag) { return minus_half_tag(); }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 struct pm_half {
00087
00088 private:
00089 typedef unsigned char enumerator_type;
00090 static const enumerator_type plus_half = 1;
00091 static const enumerator_type minus_half = 0;
00092
00093 public:
00094 pm_half() {}
00095 pm_half(half_tag const&) : e(plus_half) {}
00096 pm_half(minus_half_tag const&) : e(minus_half) {}
00097 operator float() const { return e==plus_half? .5f : -.5f; }
00098 operator double() const { return e==plus_half? .5 : -.5; }
00099 operator long double() const { return e==plus_half?.5l:-.5l; }
00100 int enumerator() const { return e; }
00101
00102 pm_half& operator++() { e = plus_half; return *this; }
00103 pm_half operator++(int) { pm_half tmp = *this; ++*this; return tmp; }
00104 pm_half& operator--() { e = minus_half; return *this; }
00105 pm_half operator--(int) { pm_half tmp = *this; ++*this; return tmp; }
00106 pm_half operator-() const { return pm_half(enumerator_type(1-e)); }
00107 pm_half operator+() const { return *this; }
00108
00109 bool operator==(pm_half rhs) const { return e==rhs.e; }
00110 bool operator==(half_tag const&) const { return e==plus_half; }
00111 bool operator==(minus_half_tag const&) const { return e==minus_half; }
00112
00113 static minus_half_tag inf() { return minus_half_tag(); }
00114 static half_tag sup() { return half_tag(); }
00115
00116 void sync(io::syncstream& sio);
00117
00118 private:
00119 pm_half(enumerator_type e_) : e(e_) {}
00120 enumerator_type e;
00121 };
00122
00123 inline bool
00124 operator==(half_tag x, pm_half y) { return y == x; }
00125 inline bool
00126 operator==(minus_half_tag x, pm_half y) { return y == x; }
00127
00128 inline bool
00129 operator!=(pm_half x, pm_half y) { return !(x == y); }
00130 inline bool
00131 operator!=(pm_half x, half_tag y) { return !(x == y); }
00132 inline bool
00133 operator!=(pm_half x, minus_half_tag y) { return !(x == y); }
00134 inline bool
00135 operator!=(half_tag x, pm_half y) { return !(x == y); }
00136 inline bool
00137 operator!=(minus_half_tag x, pm_half y) { return !(x == y); }
00138
00139 inline int
00140 operator+(half_tag, pm_half x) { return x.enumerator(); }
00141 inline int
00142 operator+(pm_half x, half_tag) { return x.enumerator(); }
00143 inline int
00144 operator+(minus_half_tag, pm_half x) { return x.enumerator()-1; }
00145 inline int
00146 operator+(pm_half x, minus_half_tag) { return x.enumerator()-1; }
00147 inline int
00148 operator+(pm_half x, pm_half y)
00149 { return x.enumerator()+y.enumerator()-1; }
00150 inline int
00151 operator-(half_tag, pm_half x) { return 1-x.enumerator(); }
00152 inline int
00153 operator-(pm_half x, half_tag) { return x.enumerator()-1; }
00154 inline int
00155 operator-(minus_half_tag, pm_half x) { return -x.enumerator(); }
00156 inline int
00157 operator-(pm_half x, minus_half_tag) { return x.enumerator(); }
00158 inline int
00159 operator-(pm_half x, pm_half y)
00160 { return x.enumerator()-y.enumerator(); }
00161
00162 inline float
00163 operator*(pm_half x, float y)
00164 { if (x == half) return .5f*y; else return -.5f*y; }
00165 inline double
00166 operator*(pm_half x, double y)
00167 { if (x == half) return .5*y; else return -.5*y; }
00168 inline long double
00169 operator*(pm_half x, long double y)
00170 { if (x == half) return .5l*y; else return -.5l*y; }
00171
00172 inline float
00173 operator*(float x, pm_half y)
00174 { if (y == half) return .5f*x; else return -.5f*x; }
00175 inline double
00176 operator*(double x, pm_half y)
00177 { if (y == half) return .5*x; else return -.5*x; }
00178 inline long double
00179 operator*(long double x, pm_half y)
00180 { if (y == half) return .5l*x; else return -.5l*x; }
00181
00182 inline int enumerator(half_tag) { return 1; }
00183 inline int enumerator(minus_half_tag) { return 0; }
00184 inline int enumerator(pm_half x) { return x.enumerator(); }
00185
00186 std::istream& operator>>(std::istream&, pm_half&);
00187 std::ostream& operator<<(std::ostream&, pm_half);
00188
00189
00190
00191
00192
00193
00194 struct halfint {
00195
00196 int twice;
00197 halfint() {}
00198 halfint(int x) : twice(x*2) {}
00199 halfint(const halfint& x) : twice(x.twice) {}
00200 halfint(const pm_half& x) : twice(x==half? 1 : -1) {}
00201 halfint(zero_tag) : twice(0) {}
00202 halfint(one_tag) : twice(2) {}
00203 operator float() const { return twice/2.0f; }
00204 operator double() const { return twice/2.0; }
00205 operator long double() const { return twice/2.0l; }
00206 halfint(int x, half_tag) : twice(x) {}
00207
00208 halfint& operator--() { twice -= 2; return *this; }
00209 halfint& operator++() { twice += 2; return *this; }
00210 halfint operator--(int) { halfint tmp = *this; --*this; return tmp; }
00211 halfint operator++(int) { halfint tmp = *this; ++*this; return tmp; }
00212
00213 void sync(io::syncstream& sio);
00214 };
00215
00216 inline half_tag::operator halfint() { return halfint(1, half); }
00217 inline minus_half_tag::operator halfint() { return halfint(-1, half); }
00218
00219 inline halfint operator*(int x, half_tag) { return halfint(x, half); }
00220 inline halfint operator*(half_tag, int y) { return halfint(y, half); }
00221 inline halfint operator*(int x, minus_half_tag)
00222 { return halfint(-x, half); }
00223 inline halfint operator*(minus_half_tag, int y)
00224 { return halfint(-y, half); }
00225
00226 inline halfint operator+(halfint x, half_tag)
00227 { return halfint(x.twice+1, half); }
00228 inline halfint operator+(half_tag, halfint x)
00229 { return halfint(1+x.twice, half); }
00230 inline halfint operator-(halfint x, half_tag)
00231 { return halfint(x.twice-1, half); }
00232 inline halfint operator-(half_tag, halfint x)
00233 { return halfint(1-x.twice, half); }
00234
00235 inline halfint operator+(halfint x, minus_half_tag)
00236 { return halfint(x.twice-1, half); }
00237 inline halfint operator+(minus_half_tag, halfint x)
00238 { return halfint(x.twice-1, half); }
00239 inline halfint operator-(halfint x, minus_half_tag)
00240 { return halfint(x.twice+1, half); }
00241 inline halfint operator-(minus_half_tag, halfint x)
00242 { return halfint(-1-x.twice, half); }
00243
00244 inline halfint operator+(int x, half_tag) { return halfint(2*x+1, half); }
00245 inline halfint operator+(half_tag, int x) { return halfint(2*x+1, half); }
00246 inline halfint operator-(int x, half_tag) { return halfint(2*x-1, half); }
00247 inline halfint operator-(half_tag, int x) { return halfint(1-2*x, half); }
00248
00249 inline halfint operator+(int x, minus_half_tag)
00250 { return halfint(2*x-1, half); }
00251 inline halfint operator+(minus_half_tag, int x)
00252 { return halfint(2*x-1, half); }
00253 inline halfint operator-(int x, minus_half_tag)
00254 { return halfint(2*x+1, half); }
00255 inline halfint operator-(minus_half_tag, int x)
00256 { return halfint(-1-2*x, half); }
00257
00258 inline float operator*(float x, half_tag) { return .5*x; }
00259 inline float operator*(half_tag, float y) { return .5*y; }
00260 inline float operator*(float x, minus_half_tag) { return -.5*x; }
00261 inline float operator*(minus_half_tag, float y) { return -.5*y; }
00262 inline double operator*(double x, half_tag) { return .5*x; }
00263 inline double operator*(half_tag, double y) { return .5*y; }
00264 inline double operator*(double x, minus_half_tag) { return -.5*x; }
00265 inline double operator*(minus_half_tag, double y) { return -.5*y; }
00266 inline long double operator*(long double x, half_tag) { return .5*x; }
00267 inline long double operator*(half_tag, long double y) { return .5*y; }
00268 inline long double operator*(long double x, minus_half_tag)
00269 { return -.5*x; }
00270 inline long double operator*(minus_half_tag, long double y)
00271 { return -.5*y; }
00272
00273 inline halfint operator+(halfint x, halfint y)
00274 { return (x.twice+y.twice)*half; }
00275 inline halfint operator-(halfint x, halfint y)
00276 { return (x.twice-y.twice)*half; }
00277
00278 inline halfint operator+(halfint x) { return x; }
00279 inline halfint operator-(halfint x) { return (-x.twice)*half; }
00280 inline halfint operator+(halfint x, int y) { return (x.twice+2*y)*half; }
00281 inline halfint operator-(halfint x, int y) { return (x.twice-2*y)*half; }
00282 inline halfint operator*(halfint x, int y) { return (x.twice*y)*half; }
00283 inline float operator*(halfint x, float y) { return (x.twice*y)/2; }
00284 inline double operator*(halfint x, double y) { return (x.twice*y)/2; }
00285 inline long double operator*(halfint x, long double y)
00286 { return (x.twice*y)/2; }
00287
00288 inline halfint operator+(int x, halfint y) { return (2*x+y.twice)*half; }
00289 inline halfint operator-(int x, halfint y) { return (2*x-y.twice)*half; }
00290 inline halfint operator*(int x, halfint y) { return (x*y.twice)*half; }
00291 inline float operator*(float x, halfint y) { return (x*y.twice)/2; }
00292 inline double operator*(double x, halfint y) { return (x*y.twice)/2; }
00293 inline long double operator*(long double x, halfint y)
00294 { return (x*y.twice)/2; }
00295
00296 inline bool operator==(halfint x, halfint y) { return x.twice==y.twice; }
00297 inline bool operator!=(halfint x, halfint y) { return x.twice!=y.twice; }
00298 inline bool operator<(halfint x, halfint y) { return x.twice<y.twice; }
00299 inline bool operator>(halfint x, halfint y) { return x.twice>y.twice; }
00300 inline bool operator<=(halfint x, halfint y) { return x.twice<=y.twice; }
00301 inline bool operator>=(halfint x, halfint y) { return x.twice>=y.twice; }
00302
00303 inline bool operator==(halfint x, int y) { return x.twice==y*2; }
00304 inline bool operator!=(halfint x, int y) { return x.twice!=y*2; }
00305 inline bool operator<(halfint x, int y) { return x.twice<y*2; }
00306 inline bool operator>(halfint x, int y) { return x.twice>y*2; }
00307 inline bool operator<=(halfint x, int y) { return x.twice<=y*2; }
00308 inline bool operator>=(halfint x, int y) { return x.twice>=y*2; }
00309
00310 inline bool operator==(int x, halfint y) { return x*2==y.twice; }
00311 inline bool operator!=(int x, halfint y) { return x*2!=y.twice; }
00312 inline bool operator<(int x, halfint y) { return x*2<y.twice; }
00313 inline bool operator>(int x, halfint y) { return x*2>y.twice; }
00314 inline bool operator<=(int x, halfint y) { return x*2<=y.twice; }
00315 inline bool operator>=(int x, halfint y) { return x*2>=y.twice; }
00316
00317 inline halfint
00318 operator+(int x, pm_half y) {
00319 return halfint(2*x + (y == half? 1 : -1), half);
00320 }
00321 inline halfint
00322 operator-(int x, pm_half y) {
00323 return halfint(2*x - (y == half? 1 : -1), half);
00324 }
00325 inline halfint
00326 operator+(pm_half x, int y) {
00327 return halfint((x == half? 1 : -1) + 2*y, half);
00328 }
00329 inline halfint
00330 operator-(pm_half x, int y) {
00331 return halfint((x == half? 1 : -1) - 2*y, half);
00332 }
00333
00334 inline halfint ceil(halfint x) { return (x.twice+1)/2; }
00335 inline halfint floor(halfint x) { return (x.twice-1)/2; }
00336 inline halfint trunc(halfint x) { return x.twice/2; }
00337 inline int iceil(halfint x) { return (x.twice+1)/2; }
00338 inline int ifloor(halfint x) { return (x.twice-1)/2; }
00339 inline int itrunc(halfint x) { return x.twice/2; }
00340
00341 inline halfint abs(halfint x) { return x.twice >= 0? x : -x; }
00342 inline halfint min(halfint x, halfint y) { return x<y? x : y; }
00343 inline halfint max(halfint x, halfint y) { return x<y? y : x; }
00344
00345 template<typename T>
00346 inline T pow(T x, halfint y) {
00347 if(y.twice%2) return std::pow(x, ifloor(y))*sqrt(x);
00348 else return std::pow(x, itrunc(y));
00349 }
00350 template<typename T>
00351 inline T pow(T x, half_tag) { return sqrt(x); }
00352 template<typename T>
00353 inline T pow(T x, minus_half_tag) { return 1.0/sqrt(x); }
00354
00355 inline double clebsch(halfint j1, halfint j2, halfint j3,
00356 halfint m1, halfint m2, halfint m3) {
00357 return clebsch_2j(j1.twice, j2.twice, j3.twice,
00358 m1.twice, m2.twice, m3.twice);
00359 }
00360
00361 inline double threejm(halfint j1, halfint j2, halfint j3,
00362 halfint m1, halfint m2, halfint m3) {
00363 return threejm_2j(j1.twice, j2.twice, j3.twice,
00364 m1.twice, m2.twice, m3.twice);
00365 }
00366
00367 inline double sixj(halfint j11, halfint j12, halfint j13,
00368 halfint j21, halfint j22, halfint j23) {
00369 return sixj_2j(j11.twice, j12.twice, j13.twice,
00370 j21.twice, j22.twice, j23.twice);
00371 }
00372
00373 inline double ninej(halfint j11, halfint j12, halfint j13,
00374 halfint j21, halfint j22, halfint j23,
00375 halfint j31, halfint j32, halfint j33) {
00376 return ninej_2j(j11.twice, j12.twice, j13.twice,
00377 j21.twice, j22.twice, j23.twice,
00378 j31.twice, j32.twice, j33.twice);
00379 }
00380
00381 inline bool threej(halfint j1, halfint j2, halfint j3) {
00382 return !(j1+j2 < j3) && !(j2+j3 < j1) && !(j3+j1 < j2)
00383 && (j1+j2+j3).twice % 2 == 0;
00384 }
00385 std::ostream& operator<<(std::ostream& out, halfint x);
00386 std::istream& operator>>(std::istream& in, halfint& x);
00387
00388
00389
00390
00391
00392
00393
00394 class pm_one {
00395
00396
00397 private:
00398 typedef unsigned char enumerator_type;
00399 static const enumerator_type plus = 0;
00400 static const enumerator_type minus = 1;
00401 enumerator_type e;
00402
00403 public:
00404 pm_one() {}
00405 explicit pm_one(int i) : e(i >= 0? plus : minus) {}
00406 pm_one(const pm_one& pi) : e(pi.e) {}
00407 pm_one(one_tag) : e(plus) {}
00408 pm_one(minus_one_tag) : e(minus) {}
00409 operator int() const { return e == plus? 1 : -1; }
00410
00411
00412 friend bool operator==(pm_one x, pm_one y) { return x.e == y.e; }
00413 friend bool operator< (pm_one x, pm_one y) { return x.e < y.e; }
00414
00415 friend bool operator==(one_tag, pm_one x) { return x.e == plus; }
00416 friend bool operator==(pm_one x, one_tag) { return x.e == plus; }
00417 friend bool operator==(minus_one_tag, pm_one x) { return x.e == minus; }
00418 friend bool operator==(pm_one x, minus_one_tag) { return x.e == minus; }
00419 friend bool operator< (one_tag, pm_one x) { return false; }
00420 friend bool operator< (pm_one x, one_tag) { return x.e == minus; }
00421 friend bool operator< (minus_one_tag, pm_one x) { return x.e == plus; }
00422 friend bool operator< (pm_one x, minus_one_tag) { return false; }
00423
00424 friend pm_one operator*(pm_one x, pm_one y)
00425 { return x.e == y.e? pm_one(one) : pm_one(-one); }
00426
00427 void sync(more::io::syncstream& sio);
00428 };
00429
00430
00431 inline bool operator!=(pm_one x, pm_one y) { return !(x == y); }
00432 inline bool operator<=(pm_one x, pm_one y) { return !(y < x); }
00433 inline bool operator>(pm_one x, pm_one y) { return y < x; }
00434 inline bool operator>=(pm_one x, pm_one y) { return !(x < y); }
00435 inline bool operator!=(pm_one x, one_tag y) { return !(x == y); }
00436 inline bool operator<=(pm_one x, one_tag y) { return !(y < x); }
00437 inline bool operator>(pm_one x, one_tag y) { return y < x; }
00438 inline bool operator>=(pm_one x, one_tag y) { return !(x < y); }
00439 inline bool operator!=(pm_one x, minus_one_tag y) { return !(x == y); }
00440 inline bool operator<=(pm_one x, minus_one_tag y) { return !(y < x); }
00441 inline bool operator>(pm_one x, minus_one_tag y) { return y < x; }
00442 inline bool operator>=(pm_one x, minus_one_tag y) { return !(x < y); }
00443 inline bool operator!=(one_tag x, pm_one y) { return !(x == y); }
00444 inline bool operator<=(one_tag x, pm_one y) { return !(y < x); }
00445 inline bool operator>(one_tag x, pm_one y) { return y < x; }
00446 inline bool operator>=(one_tag x, pm_one y) { return !(x < y); }
00447 inline bool operator!=(minus_one_tag x, pm_one y) { return !(x == y); }
00448 inline bool operator<=(minus_one_tag x, pm_one y) { return !(y < x); }
00449 inline bool operator>(minus_one_tag x, pm_one y) { return y < x; }
00450 inline bool operator>=(minus_one_tag x, pm_one y) { return !(x < y); }
00451
00452 template< typename T > inline
00453 T operator*(pm_one pi, const T& x) { return pi==one? x : -x; }
00454 template< typename T > inline
00455 T operator*(const T& x, pm_one pi) { return pi==one? x : -x; }
00456
00457 inline pm_one where(bool c, one_tag x, minus_one_tag y)
00458 { if(c) return x; else return y; }
00459 inline pm_one where(bool c, minus_one_tag x, one_tag y)
00460 { if(c) return x; else return y; }
00461 inline one_tag where(bool, one_tag, one_tag) { return one; }
00462 inline minus_one_tag where(bool, minus_one_tag, minus_one_tag)
00463 { return -one; }
00464 inline pm_one where(bool c, pm_one x, pm_one y) { return c? x : y; }
00465
00466 std::ostream& operator<<(std::ostream&, pm_one);
00467 std::istream& operator>>(std::istream&, pm_one&);
00468
00469
00470
00471
00472
00473 #if defined(MORE_BACKWARD) && MORE_BACKWARD < 20010330
00474
00475 template<typename T>
00476 struct range {
00477 typedef T element_type;
00478 range() {}
00479 range(T inf__, T sup__) : sup_(sup__), inf_(inf__) {
00480 if(inf_ > sup_)
00481 throw std::logic_error("inf > sup in range constructor");
00482 }
00483 T& sup() { return sup_; }
00484 T& inf() { return inf_; }
00485 T sup() const { return sup_; }
00486 T inf() const { return inf_; }
00487 void set_sup(T const& x) { sup_ = x; }
00488 void set_inf(T const& x) { inf_ = x; }
00489 T measure() const { return sup_-inf_; }
00490 private:
00491 T sup_, inf_;
00492 };
00493
00494 template<typename T>
00495 inline T sup(const range<T>& x) { return x.sup(); }
00496 template<typename T>
00497 inline T inf(const range<T>& x) { return x.inf(); }
00498 template<typename T>
00499 inline T measure(const range<T>& x) { return x.measure(); }
00500 template<typename T>
00501 inline T center(const range<T>& x) { return .5*(x.sup() + x.inf()); }
00502
00503 template<typename T>
00504 struct cc_range : range<T>
00505 { cc_range() {} cc_range(T x, T y) : range<T>(x, y) {} };
00506 template<typename T>
00507 struct co_range : range<T>
00508 { co_range() {} co_range(T x, T y) : range<T>(x, y) {} };
00509 template<typename T>
00510 struct oc_range : range<T>
00511 { oc_range() {} oc_range(T x, T y) : range<T>(x, y) {} };
00512 template<typename T>
00513 struct oo_range : range<T>
00514 { oo_range() {} oo_range(T x, T y) : range<T>(x, y) {} };
00515
00516 template<typename T>
00517 std::ostream& operator<<(std::ostream& os, range<T> const& x);
00518
00519 typedef pm_one sign;
00520 extern one_tag positive;
00521 extern minus_one_tag negative;
00522 typedef pm_half pmhalf;
00523
00524 #endif
00525
00526 }
00527 using namespace math;
00528 }
00529
00530
00531 #endif