summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/pair.h
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/pair.h')
-rw-r--r--Build/source/utils/asymptote/pair.h259
1 files changed, 259 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/pair.h b/Build/source/utils/asymptote/pair.h
new file mode 100644
index 00000000000..b37b778ecbf
--- /dev/null
+++ b/Build/source/utils/asymptote/pair.h
@@ -0,0 +1,259 @@
+/*****
+ * pair.h
+ * Andy Hammerlindl 2002/05/16
+ *
+ * Stores a two-dimensional point similar to the pair type in MetaPost.
+ * In some cases, pairs behave as complex numbers.
+ *
+ * A pair is a guide as a pair alone can be used to describe a path.
+ * The solve and subsolve methods are fairly straight forward as solve
+ * returns a path with just the pair and subsolve just adds the pair to
+ * the structure.
+ *****/
+
+#ifndef PAIR_H
+#define PAIR_H
+
+#include <cassert>
+#include <cmath>
+#include <iostream>
+#include <fstream>
+
+#include "common.h"
+#include "angle.h"
+
+namespace camp {
+
+class jsofstream : public std::ofstream {
+public:
+ jsofstream() {}
+ jsofstream(const string& name) : std::ofstream(name.c_str()) {}
+ void open(const string& name) {std::ofstream::open(name.c_str());}
+
+ template<class T>
+ jsofstream& operator << (const T& x) {
+ (std::ofstream&)(*this) << x;
+ return *this;
+ }
+};
+
+class pair : public gc {
+ double x;
+ double y;
+
+public:
+ pair() : x(0.0), y(0.0) {}
+ pair(double x, double y=0.0) : x(x), y(y) {}
+
+ double getx() const { return x; }
+ double gety() const { return y; }
+
+ bool isreal() {return y == 0;}
+
+ friend pair operator+ (const pair& z, const pair& w)
+ {
+ return pair(z.x+w.x,z.y+w.y);
+ }
+
+ friend pair operator- (const pair& z, const pair& w)
+ {
+ return pair(z.x-w.x,z.y-w.y);
+ }
+
+ friend pair operator- (const pair& z)
+ {
+ return pair(-z.x,-z.y);
+ }
+
+ // Complex multiplication
+ friend pair operator* (const pair& z, const pair& w)
+ {
+ return pair(z.x*w.x-z.y*w.y,z.x*w.y+w.x*z.y);
+ }
+
+ const pair& operator+= (const pair& w)
+ {
+ x += w.x;
+ y += w.y;
+ return *this;
+ }
+
+ const pair& operator-= (const pair& w)
+ {
+ x -= w.x;
+ y -= w.y;
+ return *this;
+ }
+
+ const pair& operator*= (const pair& w)
+ {
+ (*this) = (*this) * w;
+ return (*this);
+ }
+
+ const pair& operator/= (const pair& w)
+ {
+ (*this) = (*this) / w;
+ return (*this);
+ }
+
+ const pair& scale (double xscale, double yscale)
+ {
+ x *= xscale;
+ y *= yscale;
+ return *this;
+ }
+
+ friend pair operator/ (const pair &z, double t)
+ {
+ if (t == 0.0)
+ reportError("division by 0");
+ t=1.0/t;
+ return pair(z.x*t, z.y*t);
+ }
+
+ friend pair operator/ (const pair& z, const pair& w)
+ {
+ if (!w.nonZero())
+ reportError("division by pair (0,0)");
+
+ double t = 1.0 / (w.x*w.x + w.y*w.y);
+ return pair(t*(z.x*w.x + z.y*w.y),
+ t*(-z.x*w.y + w.x*z.y));
+ }
+
+ friend bool operator== (const pair& z, const pair& w)
+ {
+ return z.x == w.x && z.y == w.y;
+ }
+
+ friend bool operator!= (const pair& z, const pair& w)
+ {
+ return z.x != w.x || z.y != w.y;
+ }
+
+ double abs2() const
+ {
+ return x*x + y*y;
+ }
+
+ double length() const
+ {
+ return sqrt(abs2());
+ }
+
+ friend double length(const pair& z)
+ {
+ return z.length();
+ }
+
+ double angle(bool warn=true) const
+ {
+ return camp::angle(x,y,warn);
+ }
+
+ friend double angle(const pair& z, bool warn=true)
+ {
+ return z.angle(warn);
+ }
+
+ friend pair unit(const pair& z)
+ {
+ double scale=z.length();
+ if(scale == 0.0) return z;
+ scale=1.0/scale;
+ return pair(z.x*scale,z.y*scale);
+ }
+
+ friend pair conj(const pair& z)
+ {
+ return pair(z.x,-z.y);
+ }
+
+ friend double dot(const pair& z, const pair& w)
+ {
+ return z.x*w.x+z.y*w.y;
+ }
+
+ friend double cross(const pair& z, const pair& w)
+ {
+ return z.x*w.y-z.y*w.x;
+ }
+
+// Return the principal branch of the square root (non-negative real part).
+ friend pair Sqrt(const pair& z) {
+ double mag=z.length();
+ if(mag == 0.0) return pair(0.0,0.0);
+ else if(z.x > 0) {
+ double re=sqrt(0.5*(mag+z.x));
+ return pair(re,0.5*z.y/re);
+ } else {
+ double im=sqrt(0.5*(mag-z.x));
+ if(z.y < 0) im=-im;
+ return pair(0.5*z.y/im,im);
+ }
+ }
+
+ bool nonZero() const
+ {
+ return x != 0.0 || y != 0.0;
+ }
+
+ friend istream& operator >> (istream& s, pair& z)
+ {
+ char c;
+ s >> ws;
+ bool paren=s.peek() == '('; // parenthesis are optional
+ if(paren) s >> c;
+ s >> z.x >> ws;
+ if(!s.eof() && s.peek() == ',') s >> c >> z.y;
+ else {
+ if(paren && !s.eof()) s >> z.y;
+ else z.y=0.0;
+ }
+ if(paren) {
+ s >> ws;
+ if(s.peek() == ')') s >> c;
+ }
+
+ return s;
+ }
+
+ friend ostream& operator << (ostream& out, const pair& z)
+ {
+ out << "(" << z.x << "," << z.y << ")";
+ return out;
+ }
+
+ friend jsofstream& operator << (jsofstream& out, const pair& z)
+ {
+ out << "[" << z.x << "," << z.y << "]";
+ return out;
+ }
+
+ friend class box;
+};
+
+// Calculates exp(i * theta), useful for unit vectors.
+inline pair expi(double theta)
+{
+ if(theta == 0.0) return pair(1.0,0.0); // Frequently occurring case
+ return pair(cos(theta),sin(theta));
+}
+
+// Complex exponentiation
+inline pair pow(const pair& z, const pair& w)
+{
+ double u=w.getx();
+ double v=w.gety();
+ if(z == 0.0) return w == 0.0 ? 1.0 : 0.0;
+ double logr=0.5*log(z.abs2());
+ double th=z.angle();
+ return exp(logr*u-th*v)*expi(logr*v+th*u);
+}
+
+} //namespace camp
+
+GC_DECLARE_PTRFREE(camp::pair);
+
+#endif