### ----------------------------------------------------
### -- Math::NumberTheory
### -- Licenses: Artistic-2.0
### -- Authors: Anton Antonov
### -- File: t/09-arithmetic-functions.rakutest
### ----------------------------------------------------
use v6.d;
use Test;

use lib <. lib>;
use Math::NumberTheory;

plan *;

## 1
subtest {
    is moebius-mu(5), -1, 'standard';
    is moebius-mu(5 + 6i), -1, 'gaussian integer';
    is moebius-mu(-13), -1, 'negative first argument';
    is moebius-mu([3, 11, 8, 678]), (-1, -1, 0, -1), 'generalized';

    # Relationships
    is moebius-mu(11 * 23), moebius-mu(11) * moebius-mu(23), 'completely multiplicative function';
}, 'moebius-mu';

## 2
subtest {
    is liouville-lambda(5), -1, 'standard';
    is liouville-lambda(5 + 6i), -1, 'gaussian integer';
    is liouville-lambda(-13), -1, 'negative first argument';
    is liouville-lambda([3, 11, 8, 678]), (-1, -1, -1, -1), 'generalized';

    # Relationships
    is liouville-lambda(6 * 27), liouville-lambda(6) * liouville-lambda(27), 'completely multiplicative function';
}, 'liouville-lambda';

## 3
subtest {
    is kronecker-delta(0), 1, 'Special value for 0';
    is kronecker-delta(122), 0, '0 for any number ≠ 0 (1)';
    is kronecker-delta(232.33), 0, '0 for any number ≠ 0 (2)';

    is kronecker-delta(232.33, 332.54), 0, 'different real values, args';
    is kronecker-delta([232.33, 332.54, 894.03]), 0, 'different real values, array';

    is kronecker-delta(10, 10, 10), 1, 'same integer values, array';
    is kronecker-delta([10, 10, 10]), 1, 'same integer values, args';

}, 'kronecker-delta';

## 4
#subtest {
    is carmichael-lambda(8), 2, 'simple call for 2^3';
    is carmichael-lambda(24), 2, 'simple call with 3^1 * 2^3';
    is carmichael-lambda(10), 4, 'simple call';
    is carmichael-lambda(-10), 4, 'simple call with negative argument';
    is-deeply carmichael-lambda([2, 4, 7]), (1, 2, 6), 'simple call with list argument';

    # CarmichaelLambda preserves divisibility
    is
            carmichael-lambda(24) mod carmichael-lambda(8),
            24 mod 8,
            'divisibility preserved';

    # LCM of CarmichaelLambda equals CarmichaelLambda of LCM
    is
            ([lcm] |carmichael-lambda([3, 8])),
            carmichael-lambda(3 lcm 8),
            'LCM of CarmichaelLambda';
#}, 'carmichael-lambda';

## 5
subtest {

    is liouville-lambda(356), (-1) ** prime-omega(356);

    # MoebiusM is 0 for non-square-free integers.
    is
            (1 .. 100).map({ moebius-mu($_) != 0 }),
            (1 .. 100).map({ is-square-free($_) }),
            'µ(n) ≠ 0 means square-free';

    # MoebiusMu can be expressed in terms of LiouvilleLambda and KroneckerDelta:
    # µ[n_] := KroneckerDelta[PrimeNu[n], PrimeOmega[n]] * LiouvilleLambda[n];
    sub µ($n) {
        kronecker-delta(prime-nu($n), prime-omega($n)) * liouville-lambda($n)
    };

    is
            (1 .. 100).map({ moebius-mu($_) }),
            (1 .. 100).map({ µ($_) }),
            're-implementation of µ(n) using 𝞭( 𝜂(n), Ω(n) * 𝛌(n))';

}, 'relationships';

done-testing;


