## A Piece of Pi

Between masak’s Perl 6 contest and the Perl 6 Advent calendar, I haven’t done a lot of blogging here lately. Apologies!

So, a discussion on #perl6 the other day got me thinking about another possible interesting use of the `Real` role. Here’s the basic class:

```class TimesPi does Real {
has Real \$.x;

method new(\$x) { self.bless(*, :\$x); }
method Bridge() { \$.x * pi; }
method Str() { \$.x ~ "π"; }
method perl() { "({ \$.x })π"; }
}

sub postfix:<π>(\$x) {
TimesPi.new(\$x);
}
```

So, that’s simple enough, right? TimesPi stores a `Real` number `\$.x` internally, and the value it represents is that number times pi. There’s a postfix operator π to make it really easy to construct these numbers. Because we’ve defined a `Bridge` method, this class has access to all the normal methods and operators of `Real`. Still, as presented above it is pretty useless, but defining some operators hints at a useful purposes for this class.

```multi sub infix:<+>(TimesPi \$lhs, TimesPi \$rhs) {
TimesPi.new(\$lhs.x + \$rhs.x);
}

multi sub infix:<->(TimesPi \$lhs, TimesPi \$rhs) {
TimesPi.new(\$lhs.x - \$rhs.x);
}

multi sub prefix:<->(TimesPi \$n) {
TimesPi.new(- \$n.x);
}

multi sub infix:<*>(TimesPi \$lhs, Real \$rhs) {
TimesPi.new(\$lhs.x * \$rhs);
}

multi sub infix:<*>(Real \$lhs, TimesPi \$rhs) {
TimesPi.new(\$lhs * \$rhs.x);
}

multi sub infix:<*>(TimesPi \$lhs, TimesPi \$rhs) {
\$lhs.Bridge * \$rhs.Bridge;
}

multi sub infix:</>(TimesPi \$lhs, Real \$rhs) {
TimesPi.new(\$lhs.x / \$rhs);
}

multi sub infix:</>(TimesPi \$lhs, TimesPi \$rhs) {
\$lhs.x / \$rhs.x;
}
```

With these operators in place, basic arithmetic involving TimesPi numbers will stay in the TimesPi class when appropriate. For instance, if you add two TimesPi numbers, the result will be a TimesPi. The cool thing about this is that it is as exact `\$.x` values allow, rather than forcing everything to be a floating point calculation of limited accuracy.

We can even take things a step further, using this to perform exact trig calculations:

```    multi method sin(TimesPi \$x: \$base = Radians) {
return \$x.Bridge.sin(\$base) unless \$base == Radians;
given \$x.x {
when Int { 0; }
when Rat {
given \$x.x.denominator {
when 1 { 0; }
when 2 { (\$x.x.numerator - 1) %% 4 ?? 1 !! -1 }
# could have a case for 6 as well...
\$x.Bridge.sin;
}
}
default {
\$x.Bridge.sin;
}
}
}
```

This checks for cases where we know the exact value of the result, and returns that if it can, otherwise falling back to the standard `Real.sin` method.

Of course, just when I was feeling like I might be on to something here, I realized that `\$.x` was just the number of degrees in the angle divided by 180. Sigh.