/// Constructors
// new Point()
(x=0, y=0)

// new Point(1)
(x=1, y=undefined)

// new Point(1, 2)
(x=1, y=2)

// new Point({}, 2)
(x=[object Object], y=2)


/// Add
// point.add(new Point(1, 2))
(x=1, y=2)

// point.add({x: 3, y: 4})
(x=3, y=4)

// point.add(undefined)
(x=NaN, y=NaN)

// point
(x=0, y=0)

// point.add(other)
  get point.y
  get other.y
  get point.x
  get other.x
(x=4, y=6)


/// Subtract
// point.subtract(new Point(1, 2))
(x=-1, y=-2)

// point.subtract({x: 3, y: 4})
(x=-3, y=-4)

// point.subtract(undefined)
(x=NaN, y=NaN)

// point
(x=0, y=0)

// point.subtract(other)
  get point.y
  get other.y
  get point.x
  get other.x
(x=-2, y=-2)


/// Distance
// Point.distance(new Point(), new Point())
0

// Point.distance(new Point())
NaN

// Point.distance(new Point(), new Point(), new Point())
0

// Point.distance(new Point(-100, 200), new Point(100, 200))
200

// Point.distance({x: -100, y: 200}, new Point(100, 200))
undefined

// Point.distance(point, other)
  get point.y
  get other.y
  get point.x
  get other.x
200

// Point.distance(point, other), point has overridden subtract
  subtract (x=100, y=200)
  get result.length
42


/// Equals
// point.equals(new Point(1, 2))
false

// point.equals(point)
true

// point.equals({x: 3, y: 4})
false

// point.equals({x: 0, y: 0})
false

// point.equals({x: 0, y: 0, __proto__: Point.prototype})
true

// point.equals(null)
false

// new Point('1', '2').equals(new Point(1, 2))
true

// new Point(NaN, NaN).equals(new Point(NaN, NaN))
true

// Point.prototype.equals.call({x: 0, y: 0}, new Point())
true

// point
(x=0, y=0)


/// Equals: property access order
// point.equals(other), all equal
  get other.x
  get point.x
  get other.y
  get point.y
true

// point.equals(other), x differs
  get other.x
  get point.x
false


/// Clone
// point
(x=1, y=2)

// clone
(x=1, y=2)

// point === clone
false

// point.equals(clone)
true

// point.clone()
  get point.y
  get point.x
(x=1, y=2)


/// Interpolate
// Point.interpolate(new Point(-100, -200), new Point(100, 200), -1)
(x=300, y=600)

// Point.interpolate(new Point(-100, -200), new Point(100, 200), 0)
(x=100, y=200)

// Point.interpolate(new Point(-100, -200), new Point(100, 200), 0.5)
(x=0, y=0)

// Point.interpolate(new Point(-100, -200), new Point(100, 200), 1)
(x=-100, y=-200)

// Point.interpolate(new Point(-100, -200), new Point(100, 200), 2)
(x=-300, y=-600)

// Point.interpolate(new Point(-100, -200), new Point(100, 200))
(x=NaN, y=NaN)

// Point.interpolate()
(x=NaN, y=NaN)

// Point.interpolate(new Point('10', '0'), new Point('20', '0'), 0.5)
(x=20-5, y=00)


/// Interpolate: property access order
// Point.interpolate(point, other, tracingFactor)
  get other.y
  get point.y
  get other.y
  valueOf
  get other.x
  get point.x
  get other.x
  valueOf
(x=0, y=0)


/// Length
// new Point().length
0

// new Point(100, 0).length
100

// new Point(0, -200).length
200

// point.length
  get point.x
  get point.x
  get point.y
  get point.y
5


/// Normalize
// new Point().normalize(10)
(x=0, y=0)

// new Point().normalize(-5)
(x=0, y=0)

// new Point(100, 200).normalize(10)
(x=4.47213595499958, y=8.94427190999916)

// new Point(100, 200).normalize(-5)
(x=-2.23606797749979, y=-4.47213595499958)

// new Point(-200, 100).normalize(10)
(x=-8.94427190999916, y=4.47213595499958)

// new Point(-200, 100).normalize(-5)
(x=4.47213595499958, y=-2.23606797749979)

// new Point(-200, 100).normalize()
(x=NaN, y=NaN)

// new Point(NaN, 100).normalize()
(x=NaN, y=100)

// new Point(undefined, 100).normalize(3)
(x=undefined, y=100)

// new Point(100, null).normalize(1)
(x=100, y=null)

// new Point(1e308, 1e308).normalize(1)
(x=0, y=0)

// new Point(1, 3).normalize(3.3)
(x=1.04355162785556, y=3.1306548835667)

// Point.prototype.normalize.call({x: 3, y: 4}, 10)
(x=3, y=4)


/// Normalize: side effects
// new Point(3, 4).normalize(tracingLength)
  valueOf
(x=6, y=8)

// new Point().normalize(tracingLength)
(x=0, y=0)

// new Point(Infinity, 1).normalize(tracingLength)
  valueOf
(x=NaN, y=0)

// point.normalize(10), point has tracing x and y
  get point.x
  get point.x
  get point.y
  get point.y
  get point.x
  set point.x = 6
  get point.y
  set point.y = 8
  get point.x
  get point.y
(x=6, y=8)

// point.normalize(10), point has tracing x, y and length
  get point.length
  get point.x
  set point.x = 6
  get point.y
  set point.y = 8
  get point.x
  get point.y
(x=6, y=8)


/// Offset
// point = new Point()
(x=0, y=0)

// point.offset(100, 200)
(x=100, y=200)

// point.offset(-1000, -2000)
(x=-900, y=-1800)

// point.offset(500)
(x=-400, y=NaN)

// point.offset(1, 2)
  get point.x
  set point.x = 4
  get point.y
  set point.y = 6


/// Polar
// Point.polar(5, Math.atan(3/4))
(x=4, y=3)

// Point.polar(5)
(x=NaN, y=NaN)

// Point.polar(0, Math.atan(3/4))
(x=0, y=0)


/// Polar: evaluation order
// Point.polar(tracingLength, Math.atan(3/4))
  Math.sin(0.643501108793284)
  valueOf
  Math.cos(0.643501108793284)
  valueOf
(x=4, y=3)


/// ToString
// point.toString()
  get point.x
  get point.y
(x=1, y=2)

