=begin pod :kind("Type") :subkind("class") :category("basic")

=TITLE role Numeric

=SUBTITLE Number or object that can act as a number

    role Numeric { ... }

Common role for numbers and types that can act as numbers.

Binary numeric operations return an object of the "wider" type:

=begin code :lang<text>
Int         narrowest
Rat
FatRat
Num
Complex     widest
=end code

So for example the product of a L<Rat|/type/Rat> and an L<Int|/type/Int> is a L<Rat|/type/Rat>.

Unary operations that in pure math usually return an irrational number
generally return L<Num|/type/Num> in Raku.

=head1 Methods

=head2 method Numeric

Defined as:

    multi method Numeric(Numeric:D: --> Numeric:D)
    multi method Numeric(Numeric:U: --> Numeric:D)

The C<:D> variant simply returns the invocant. The C<:U> variant issues a warning about using
an uninitialized value in numeric context and then returns C<self.new>.

=head2 method Int

    method Int(Numeric:D: --> Int:D)

If this C<Numeric> is equivalent to a C<Real>, return the equivalent of
calling C<truncate> on that C<Real> to get an C<Int>. Fail with
C<X::Numeric::Real> otherwise.

=head2 method Rat

    method Rat(Numeric:D: Real $epsilon = 1.0e-6 --> Rat:D)

If this C<Numeric> is equivalent to a C<Real>, return a C<Rat> which is
within C<$epsilon> of that C<Real>'s value. Fail with C<X::Numeric::Real>
otherwise.

=head2 method Num

    method Num(Numeric:D: --> Num:D)

If this C<Numeric> is equivalent to a C<Real>, return that C<Real> as a C<Num>
as accurately as is possible. Fail with C<X::Numeric::Real> otherwise.

=head2 method narrow

    method narrow(Numeric:D --> Numeric:D)

Returns the number converted to the narrowest type that can hold it without
loss of precision.

    say (4.0 + 0i).narrow.raku;     # OUTPUT: «4␤»
    say (4.0 + 0i).narrow.^name;    # OUTPUT: «Int␤»

=head2 method ACCEPTS

    multi method ACCEPTS(Numeric:D: $other)

Returns C<True> if C<$other> can be coerced to L<Numeric|/type/Numeric> and
is L<numerically equal|/routine/==> to the invocant (or both evaluate
to C<NaN>).

=head2 routine log

    multi sub    log(Numeric:D, Numeric $base = e --> Numeric:D)
    multi method log(Numeric:D: Numeric $base = e --> Numeric:D)

Calculates the logarithm to base C<$base>. Defaults to the natural logarithm.
Returns C<NaN> if C<$base> is negative. Throws an exception if C<$base> is C<1>.

=head2 routine log10

    multi sub    log10(Numeric:D  --> Numeric:D)
    multi method log10(Numeric:D: --> Numeric:D)

Calculates the logarithm to base 10. Returns C<NaN> for negative
arguments and C<-Inf> for C<0>.

=head2 routine log2

    multi sub    log2(Numeric:D)
    multi method log2(Numeric:D:)

Calculates the logarithm to base 2. Returns C<NaN> for negative
arguments and C<-Inf> for C<0>.

=head2 routine exp

    multi sub    exp(Numeric:D, Numeric:D $base = e --> Numeric:D)
    multi method exp(Numeric:D: Numeric:D $base = e --> Numeric:D)

Returns C<$base> to the power of the number, or C<e> to the power of the
number if called without a second argument.

=head2 method roots

    multi method roots(Numeric:D: Int:D $n --> Positional)

Returns a list of the C<$n> complex roots, which evaluate to the original
number when raised to the C<$n>th power.

=head2 routine abs

    multi sub    abs(Numeric:D  --> Real:D)
    multi method abs(Numeric:D: --> Real:D)

Returns the absolute value of the number.

=head2 routine sqrt

    multi sub    sqrt(Numeric:D --> Numeric:D)
    multi method sqrt(Numeric:D --> Numeric:D)

Returns a square root of the number. For real numbers the positive square
root is returned.

On negative real numbers, C<sqrt> returns L<C<NaN>|/type/Num#NaN> rather than a complex number,
in order to not confuse people who are not familiar with complex arithmetic.
If you want to calculate complex square roots, coerce to C<Complex> first, or
use the C<roots> method.

=head2 method conj

    multi method conj(Numeric:D --> Numeric:D)

Returns the complex conjugate of the number. Returns the number itself for
real numbers.

=head2 method Bool

    multi method Bool(Numeric:D:)

Returns C<False> if the number is equivalent to zero, and C<True> otherwise.

=head2 method succ

    method succ(Numeric:D:)

Returns the number incremented by one (successor).

=head2 method pred

    method pred(Numeric:D:)

Returns the number decremented by one (predecessor).

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
