Implementing ATAN2

An implementation of ATAN2 in PHP. PHP implements ATAN2 but I needed to figure out the algorithm for a microcontroller that didn't, so I prototyped it in PHP.

Here is the code:

class Math {
  public static function atan2( $dy, $dx ) {
    if( $dy > 0 ) {
      if( $dx > 0  ) $tcl = atan($dy/$dx);
      if( $dx < 0  ) $tcl = M_PI - atan(-$dy/$dx);
      if( $dx == 0 ) $tcl = M_PI/2;
    }

    if( $dy < 0 ) {
      if( $dx > 0  ) $tcl = -atan(-$dy/$dx);
      if( $dx < 0  ) $tcl = atan($dy/$dx) - M_PI;
      if( $dx == 0 ) $tcl = -M_PI/2;
    }

    if( $dy == 0 ) {
      if( $dx > 0  ) $tcl = 0.0;
      if( $dx < 0  ) $tcl = M_PI;
      if( $dx == 0 ) $tcl = 0.0; // the 2 points are the same, default to zero
    }

    return $tcl;
  }
}
And here is an example of how to use it:
$heading = 270.0;  // degrees
$Ax =  0.00;
$Ay =  0.00;
$Bx = -7.89;
$By = -0.86;

// get target distance and bearing in degrees
$dx = $Bx-$Ax;
$dy = $By-$Ay;
$dist = sqrt( pow($dx,2) + pow($dy,2) );
$dir = Math::atan2( $dy, $dx ) * 180 / M_PI;
printf( "Target spotted at %0.3f degrees, distance %0.3f !!\n", $dir, $dist );

// get new heading
$diff = $heading - $dir;
if( $diff < -180 ) $diff += 360;
if( $diff > 180 ) $diff -= 360;
printf( "Turn %s %0.3f degrees\n", ($diff < 0 ? 'left' : 'right'), $diff );

Implementing Logic Gates in a Spreadsheet

Here are some of the basic logic gates, implemented as spreadsheet formulas.

GateSpreadsheet Formula
ANDAND(A,B)
OROR(A,B)
NOTNOT(B)
NANDNOT(AND(A,B))
NORNOT(OR(A,B))
XOROR(AND(A,NOT(B)),AND(NOT(A),B))
XNORNOT(OR(NOT(OR(A,NOT(OR(A,B)))),NOT(OR(B,NOT(OR(A,B))))))

It is possible to implement any gate using only NOT and OR (NOR), or with NOT and AND (NAND) gates. For example, here is an AND gate implemented using only NOT and OR gates:

AND using only NOR gatesNOT(OR(NOT(OR(A,A)),NOT(OR(B,B)))

With AND, OR and NOT, we can implement a half adder, like this:

Column AColumn B
A0
B1
Carry (AND)=AND(B1,B2)
Sum (XOR)=OR(AND(B1,NOT(B2)),AND(NOT(B1),B2))

By string together two half adders and OR-ing the carry bit, we can create a full adder:

BitSpreadsheet Formula
A0
B0
Cin0
Cout=AND(B2,B3)
Sum=OR(AND(B2,NOT(B3)),AND(NOT(B2),B3))
Cout=AND(B6,B4)
Sum=OR(AND(B4,NOT(B6)),AND(NOT(B4),B6))
Cout=OR(B7,B5)
Sum=B8

Implementing a 4-bit adder is just a matter of simply replicating the full adder logic four times:

8421
Input A0000
Input B0000
A=B2=C2=D2=E2
B=B3=C3=D3=E3
Cin=C12=D12=E120
Cout=AND(B5,B6)=AND(C5,C6)=AND(D5,D6)=AND(E5,E6)
Sum=OR(AND(B5,NOT(B6)),AND(NOT(B5),B6))=OR(AND(C5,NOT(C6)),AND(NOT(C5),C6))=OR(AND(D5,NOT(D6)),AND(NOT(D5),D6))=OR(AND(E5,NOT(E6)),AND(NOT(E5),E6))
Cout=AND(B7,B9)=AND(C7,C9)=AND(D7,D9)=AND(E7,E9)
Sum=OR(AND(B7,NOT(B9)),AND(NOT(B7),B9))=OR(AND(C7,NOT(C9)),AND(NOT(C7),C9))=OR(AND(D7,NOT(D9)),AND(NOT(D7),D9))=OR(AND(E7,NOT(E9)),AND(NOT(E7),E9))
Cout=OR(B8,B10)=OR(C8,C10)=OR(D8,D10)=OR(E8,E10)
Sum=B11=C11=D11=E11

Radians made easy

If you are in danger of losing your Geek cred because you don't understand radians, fear not! Radians aren't bad, they're just drawn that way.


What is a radian?

Diagram A
You already know some things about degrees, like there are 360 degrees in a circle and that you can measure an angle with two points on the circle's edge (see Diagram A).

Radians are just another way to measure angles. Here's how:

Start with a circle. The radius of the circle is a line from the center of the circle to a point on the edge. In Diagram A, that's the line CA. Start point A moving counterclockwise around the circle. It will trace out an arc as it travels. When the arc is as long as the radius of the circle, stop. Call that point B. You now have an arc AB, and an angle ACB. That angle at C is equivalent to one radian. So, the length of arc AB is the same as the length of the radius of the circle, which is line CA. Here's the rule:
  • The lengths of the arc and the radius are equal.
Next, you already know that the ratio of the circumference of a circle to its diameter is pi, or π, which is 3.14. The formula is C = πd. Since the radius of a circle is half the diameter, then d = 2r, so C = πd = π2r, more commonly written C = 2πr.

Since C = 2πr, and since we already said the radius of the circle equals one radian, setting r = 1 means that C = 2π radians. In other words, there are 2π radians in the circumference of the circle, which is 360 degrees. So, 360 degrees = 2π radians. Knowing that, we can now convert between radians and degrees.

Since there are 2π radians in 360 degrees, we get: 2π rad = 360 deg. Diving both sides by 2π, rad = 360/2π = 180/π. And, because 360 deg = 2π rad: dividing both sides by 360, deg = 2π/360 = π/180. To summarize:
  • Given degrees, you get radians with rad = deg × 180/π.
  • Given radians, you get degrees = rad × π/180.
Radians for common degrees

You'll see charts that tell you 90 degrees equals π/2 radians, or 315 degrees equals 7π/4 radians. How did they get that?

Remember that C = 2π, meaning that there are 2π radians in 360 degrees. To find out how many radians are in, for example, 90 degrees, we just multiply 2π by the ratio 90/360, like this:

radians = 90/360 × 2π.

Reducing the fraction, we get ¼ × 2π, which simplifies to 2π/4, or π/2. So 90 degrees = π/2 radians.

Let's do a few more:

180 degrees = 180/360 × 2π = ½ × 2π = 2π/2 = π radians.
270 degrees = 270/360 × 2π = ¾ × 2π = 6π/4 = 3π/2 radians.
360 degrees = 360/360 × 2π = 2π radians.

Try the calculations for yourself! 45, 135, 225, and 315 degrees are all common angles.