function atan2(y, x) {
y = new this(y);
x = new this(x);
var r,
pr = this.precision,
rm = this.rounding,
wpr = pr + 4;
// Either NaN
if (!y.s || !x.s) {
r = new this(NaN);
// Both ±Infinity
} else if (!y.d && !x.d) {
r = getPi(this, wpr, 1).times(x.s > 0 ? 0.25 : 0.75);
r.s = y.s;
// x is ±Infinity or y is ±0
} else if (!x.d || y.isZero()) {
r = x.s < 0 ? getPi(this, pr, rm) : new this(0);
r.s = y.s;
// y is ±Infinity or x is ±0
} else if (!y.d || x.isZero()) {
r = getPi(this, wpr, 1).times(0.5);
r.s = y.s;
// Both non-zero and finite
} else if (x.s < 0) {
this.precision = wpr;
this.rounding = 1;
r = this.atan(divide(y, x, wpr, 1));
x = getPi(this, wpr, 1);
this.precision = pr;
this.rounding = rm;
r = y.s < 0 ? r.minus(x) :
r.plus(x);
} else {
r = this.atan(divide(y, x, wpr, 1));
}
return r;
}