#!/bin/sh
# -*- mode: cperl; coding: utf-8-unix; -*-

eval 'exec ${PERL-perl} -Sx "$0" ${1+"$@"}'
  if 0;

#!perl -w
#line 9
#
# Author:      Peter John Acklam
# Time-stamp:  2023-08-27 18:12:47 Vest-Europa (sommertid)
# E-mail:      pjacklam@online.no
# URL:         http://home.online.no/~pjacklam

use strict;
use warnings;

use lib '/cygdrive/c/share/repos/private/github.com/pjacklam/p5-Math-BigInt/lib';

package Math::BigInt;

sub rsft {
    my ($cls, $x, $y, $b) = @_;
    my $z = $y > 0 ? $cls -> new($x) -> bdiv($cls -> new($b) -> bpow($y))
                   : $cls -> new($x) -> bmul($cls -> new($b) -> bpow(-$y));
    return $z;
}

package main;

use Math::BigInt;

my @x = (-20 .. 20);
my @y = (  0 .. 10);
my @b = ( -6 ..  6);

my $cls = "Math::BigInt";

@x = ("-inf", @x, "inf");
@y = ("-inf", @y, "inf");
@b = ("-inf", @b, "inf");

for my $b (@b) {

    printf "\nb = %s\n\n", $b;

    printf "       y";
    for my $y (@y) {
        printf " %5s", $y;
    }
    printf "\n";

    printf "    x   ";
    for my $y (@y) {
        printf " %5s", "----";
    }
    printf "\n";

    for my $x (@x) {
        printf "%5s | ", $x;
        for my $y (@y) {
            printf " %5s", $cls -> rsft($x, $y, $b);
        }
        printf "\n";

    }
}

__END__

for my $b (@b) {
    for my $x (@x) {
        for my $y (@y) {
            my $z1 = $cls -> brsft($x, $y, $b);
            my $z2 = $y > 0 ? $cls -> new($x) -> bdiv($cls -> new($b) -> bpow($y))
                            : $cls -> new($x) -> bmul($cls -> new($b) -> bpow(-$y));

            my $test = qq|$cls -> brsft(|
              . ($x =~ /inf|nan/i ? qq|"$x"| : $x)
              . qq|, |
              . ($y =~ /inf|nan/i ? qq|"$y"| : $y)
              . qq|, |
              . ($b =~ /inf|nan/i ? qq|"$b"| : $b)
              . qq|) = |
              . ($z2 =~ /inf|nan/i ? qq|"$z2"| : $z2);

            unless (is($z1, $z2, $test)) {
                my $s1 = "$cls -> brsft($x, $y, $b)";
                my $s2 = $y > 0 ? "  $cls -> new($x) -> bdiv($cls -> new($b) -> bpow($y))"
                       :          "  $cls -> new($x) -> bmul($cls -> new($b) -> bpow(" . -$y . "))";
                printf "# %72s : %s\n", $s1, $z1;
                printf "# %72s : %s\n", $s2, $z2;
            }
        }
    }
}

done_testing();

__END__

for my $b (@b) {
    for my $x (@x) {
        for my $y (@y) {
            my $z1 = Math::BigInt -> blsft($x, $y, $b);
            my $z2 = $y > 0 ? Math::BigInt -> new($x) -> bmul(Math::BigInt -> new($b) -> bpow($y))
                   : $y < 0 ? Math::BigInt -> new($x) -> bdiv(Math::BigInt -> new($b) -> bpow(-$y))
                   :          $x;
            unless (cmp_ok($z1, "==", $z2, "Math::BigInt -> blsft($x, $y, $b)")) {
                my $s1 = "Math::BigInt -> blsft($x, $y, $b)";
                my $s2 = $y > 0 ? "Math::BigInt -> new($x) -> bmul(Math::BigInt -> new($b) -> bpow($y))"
                       : $y < 0 ? "Math::BigInt -> new($x) -> bdiv(Math::BigInt -> new($b) -> bpow(" . -$y. "))"
                       :          "$x";
                printf "# %40s : %s\n", $s1, $z1;
                printf "# %40s : %s\n", $s2, $z2;
            }
        }
    }
}

done_testing();

__END__

use strict;
use warnings;

use lib '/cygdrive/c/share/repos/private/github.com/pjacklam/p5-Math-BigInt/lib';

use Math::BigFloat;

$\ = "\n";

Math::BigInt -> accuracy(1000);
Math::BigInt -> upgrade("Math::BigFloat");

Math::BigFloat -> accuracy(1000);
Math::BigFloat -> downgrade("Math::BigInt");

print "mbfa: ", Math::BigFloat -> accuracy() // "undef";
print "mbia: ", Math::BigInt   -> accuracy() // "undef";

my $x = Math::BigFloat -> new(2);

print "x = $x (as ", ref($x), ")";

print "\ncalling: \$x -> blog()";
$x -> blog();


__END__

use Math::BigRat;

my $rat = Math::BigRat->new( '1 / 2' );

print "$rat\n";

my $exp = exp $rat;
print "$exp\n";

exit 0;

__END__

use strict;
use warnings;
use lib 'lib';

use Math::BigFloat only => "GMP";
BEGIN { print Math::BigInt -> config() -> {lib}, "\n"; }

use Math::BigInt;
BEGIN { print Math::BigInt -> config() -> {lib}, "\n"; }


__END__

use lib 'lib';
use Math::BigFloat;

my $pi = Math::BigFloat -> bpi(100);
$pi -> accuracy(undef);

print $pi, "\n";

my $hex = $pi -> to_hex();
print $hex, "\n";

my $pi2 = Math::BigFloat -> from_hex($hex);
$pi2 -> bround(120);

print $pi2, "\n";

my $d = $pi - $pi2;
print $d -> bnstr(), "\n";

__END__

my $err_max = 0;
my $dec_max;

sub check {
    my $dec = shift;
    my $obj  = Math::BigFloat -> new($dec);
    my $hex  = $obj -> to_hex();
    my $obj2 = Math::BigFloat -> from_hex($hex);
    my $err  = abs($obj - $obj2);
    #print $err, "\n";
    if ($err > $err_max) {
        $err_max = $err;
        $dec_max = $dec;
        print "\n";
        print "err: $err\n";
        print "dec: $dec\n";
        print "hex: $hex\n";
        print "dec: $obj2\n";
    }
}

for (1 .. 9999) {
    my $dec = sprintf '.%0.3u', $_;
    #print $dec, "\n";
    check($dec);
}

__END__

for my $rep (1 .. 1000) {
    for my $len (1 .. 100) {
        my $dec = ".";
        $dec .= 1 + int rand 9;       # 1..9
        for my $dig (2 .. $len) {
            $dec .= int rand 10;        # 0..9
        }
        check($dec);
    }
}

__END__

use Math::BigInt;

$it = Math::BigInt -> new("100100100987654321131400");
$rem = $it % 97;
$n = length($it);

print "it $n $it\n";
print "rem $rem\n";

__END__

use strict;
use warnings;

use Benchmark;

sub bytes_to_value1 {
    my $bytes = shift;

    my $value = 0;
    for my $offset (0 .. length($bytes) - 1) {
        $value *= 256;
        $value += ord substr $bytes, $offset, 1;
    }

    return $value;
}

sub bytes_to_value2 {
    my $bytes = shift;

    my $value = 0;
    for (unpack "(a)*", $bytes) {
        $value <<= 8;
        $value |= ord;
    }

    return $value;
}

timethese(100,
          {
           1 => sub { for ("aaa" .. "zzz") { bytes_to_value1($_); } },
           2 => sub { for ("aaa" .. "zzz") { bytes_to_value2($_); } },
          });

__END__

sub doit {
    my $bytes = shift;
    print "1: ", bytes_to_value1($bytes), "\n";
    print "2: ", bytes_to_value2($bytes), "\n";
}

if (@ARGV) {
    for (@ARGV) {
        doit($_);
    }
} else {
    while (<>) {
        s/\015*\012\z//;
        doit($_)
    }
}

__END__

use Math::BigFloat;

my $y = Math::BigFloat->new(14);
$y->precision(-3);
print $y, " ", $y + 1.5, " ", $y + Math::BigFloat->new(1, 5), " ", Math::BigFloat->new(1,5) + $y;


__END__

use lib '/cygdrive/c/share/repos/private/github.com/pjacklam/p5-Math-Matrix/lib';
use Math::Matrix;

#my $m = 11;
#my $n = 7;

print "=" x 72, "\n";

my $A = Math::Matrix -> randi([-9, 9], 7, 5);
print "\nA =\n\n", $A -> str(), "\n";

my $x_true = Math::Matrix -> randi([-9, 9], 5, 3);
print "\nx =\n\n", $x_true -> str(), "\n";

my $y = $A * $x_true;
print "\ny =\n\n", $y -> str(), "\n";

my ($x, $rel_err, $abs_err, $iter_best) = $y -> mldiv($A, RelTol => 0, MaxIter => 5000);
print "\nxest =\n\n", $x -> str(), "\n\n";
printf "abs_err   = %24.15e\n", $abs_err;
printf "rel_err   = %24.15e\n", $rel_err;
printf "iter_best = %24d\n", $iter_best;

__END__

my @err = ();

my $max_iter = 5;
my $min_err;
my $x_best;

for my $i (0 .. 23) {

    my $res = $A -> mmuladd($x, -$y); # compute the residual
    print "\nres =\n\n", $res -> str(), "\n";

    #my $err = $res -> to_col() -> abs() -> sum() -> str();
    my $err = Math::Matrix::_sum(map { abs } map { @$_ } @$res);
    print "\nsum(abs(\$res)) = $err\n";
    push @err, $err;

    my $dx = $res -> mldiv($A); # compute the delta $x
    print "\ndx =\n\n", $dx -> str(), "\n";

    $x = $x - $dx;              # improve the solution $x
    print "\nxest =\n\n", $x -> str(), "\n";

    #redo OUTER unless $err == 0;
}

my $res = $A -> mmuladd($x, -$y); # compute the residual
print "\nres =\n\n", $res -> str(), "\n";

my $err = $res -> to_col() -> abs() -> sum() -> str();
print "\nsum(abs(\$res)) = $err\n";
push @err, $err;

for my $i (0 .. $#err) {
    printf "%2u = %24.15e\n", $i, $err[$i];
}

__END__

my $m = 6;
my $n = 2;

print "=" x 72, "\n";

my $A = Math::Matrix -> randi([-9, 9], $m, $m);
print "\nA =\n\n", $A -> str(), "\n";

my $x_true = Math::Matrix -> randi([-9, 9], $m, $n);
print "\nx =\n\n", $x_true -> str(), "\n";

my $y = $A * $x_true;
print "\ny =\n\n", $y -> str(), "\n";

my $x = $y -> mldiv($A);
print "\nxest =\n\n", $x -> str(), "\n";

my @err = ();

my $max_iter = 5;
my $min_err;
my $x_best;

for my $i (0 .. 23) {

    my $res = $A -> mmuladd($x, -$y); # compute the residual
    print "\nres =\n\n", $res -> str(), "\n";

    #my $err = $res -> to_col() -> abs() -> sum() -> str();
    my $err = Math::Matrix::_sum(map { abs } map { @$_ } @$res);
    print "\nsum(abs(\$res)) = $err\n";
    push @err, $err;

    my $dx = $res -> mldiv($A); # compute the delta $x
    print "\ndx =\n\n", $dx -> str(), "\n";

    $x = $x - $dx;              # improve the solution $x
    print "\nxest =\n\n", $x -> str(), "\n";

    #redo OUTER unless $err == 0;
}

my $res = $A -> mmuladd($x, -$y); # compute the residual
print "\nres =\n\n", $res -> str(), "\n";

my $err = $res -> to_col() -> abs() -> sum() -> str();
print "\nsum(abs(\$res)) = $err\n";
push @err, $err;

for my $i (0 .. $#err) {
    printf "%2u = %24.15e\n", $i, $err[$i];
}

__END__

my $A = Math::Matrix -> new([[ -8, -5, -6, -3 ],
                             [ -9, -3, -4,  8 ],
                             [ -7, -6,  9, -8 ],
                             [ -2,  5,  0, -4 ]]);

my $x_true = Math::Matrix -> new([[ -5,  1 ],
                                  [ -6, -4 ],
                                  [ -3, -5 ],
                                  [  7,  9 ]]);

my $y = $A * $x_true;

my $x = $y -> mldiv($A);

print $x -> map(sub { sprintf '%.15f', $_ }) -> str();

__END__

    my $res = $A -> mmuladd($x, -$y);   # compute the residual
    print "\nres =\n\n", $res -> str(), "\n";

    #my $err = $res -> to_col() -> abs() -> sum() -> str();
    my $err = Math::Matrix::_sum(map { abs } map { @$_ } @$res);
    print "\nsum(abs(\$res)) = $err / $err2\n";
    push @err, $err;

    my $dx = $res -> mldiv($A); # compute the delta $x
    print "\ndx =\n\n", $dx -> str(), "\n";

    $x = $x - $dx;              # improve the solution $x
    print "\nxest =\n\n", $x -> str(), "\n";

    last if

__END__


use strict;
use warnings;

use lib '/cygdrive/c/share/repos/private/github.com/pjacklam/p5-Math-Matrix/lib';
use Math::Matrix;

OUTER: {
    my $m = 5;
    my $n = 3;

    my @methods = qw< felim_tp felim_pp felim_sp felim_fp >;
    my $A;
    my @F;

  INNER: {
        #print "=" x 72, "\n";
        $A = Math::Matrix -> randi([-9, 9], $m, $m);
        #print "\nA =\n\n", $A -> str(), "\n";

        eval { $A -> felim_np(); };
        redo OUTER if $@;

        @F = ();

        for (my $i = 0 ; $i <= $#methods ; ++$i) {
            my $method = $methods[$i];

            $F[$i] = $A -> $method();
            #redo OUTER if $@;

            my $maxlen = $F[$i] -> to_row() -> map(sub { length }) -> max() -> [0][0];
            redo OUTER if $maxlen > 7;

            #print "\nA -> $method() =\n\n";
            #print $F[$i] -> str(), "\n";

            for (my $j = 0 ; $j < $i ; ++$j) {
                if ($F[$i] -> meq($F[$j])) {
                    print "$methods[$j]() and $methods[$i]() give same result\n";
                    redo INNER;
                }
            }
        }
    }

    # Print.

    print "\n", "=" x 72, "\n";
    print "\nA =\n\n", $A -> str(), "\n";
    for (my $i = 0 ; $i <= $#methods ; ++$i) {
        my $method = $methods[$i];
        print "\nA -> $method() =\n\n";
        print $F[$i] -> str(), "\n";
    }

    print "\nPress any key to continue ...";
    my $input = <STDIN>;
    redo OUTER;
}

__END__

my $x_true = Math::Matrix -> randi([-9, 9], $m, $n);
print "\nx =\n\n", $x_true -> str(), "\n";

my $y = $A * $x_true;
print "\ny =\n\n", $y -> str(), "\n";

my $x = $y -> mldiv($A);
print "\nxest =\n\n", $x -> str(), "\n";





my @err = ();
for my $i (0 .. 23) {

    my $res = $A -> mmuladd($x, -$y); # compute the residual
    print "\nres =\n\n", $res -> str(), "\n";

    my $err = $res -> to_col() -> abs() -> sum() -> str();
    print "\nsum(abs(\$res)) = $err\n";
    push @err, $err;

    my $dx = $res -> mldiv($A); # compute the delta $x
    print "\ndx =\n\n", $dx -> str(), "\n";

    $x = $x - $dx;              # improve the solution $x
    print "\nxest =\n\n", $x -> str(), "\n";

    last if $err == 0;
}

__END__

my $y = Math::Matrix -> new([[  2,  4 ],
                             [ -1,  3 ],
                             [  3, -2 ]]);

my $A = Math::Matrix -> new([[  1,  0,  1 ],
                             [ -1, -1, -7 ],
                             [  1, -1, -4 ]]);

#my $y = Math::Matrix -> new([[  3,  1, -1 ],
#                             [ 11,  5, -6 ],
#                             [ -2, -1,  1 ]]);

#my $x = $A -> catcol($y) -> solve();
#my $x = Math::Matrix -> new([[  2,  17 ],
#                             [ -1,  71 ],
#                             [  0, -13 ]]);
my $x = Math::Matrix -> new([[  1.9999, 16.9999 ],
                             [ -0.9999, 70.9999 ],
                             [  0,     -12.9999 ]]);
print $x, "\n";

my $r = $A -> mmuladd($x, -$y);
print $r, "\n";

my $d = $A -> catcol($r) -> solve();
print $d, "\n";

$x -= $d;
print $x, "\n";

__END__

Math::Matrix -> new([[  2.9999,  0.9999, -0.9999 ],
                     [ 10.9999,  4.9999, -5.9999 ],
                     [ -1.9999, -0.9999,  0.9999 ]]);

my $I = Math::Matrix -> id(3);

my $res = $x * $y - $I;

my $d = $x -> catcol($res) -> solve();
$y -= $d;
print $y;

__END__

my $x = Math::Matrix -> new([[  1,  0,  1 ],
                             [ -1, -1, -7 ],
                             [  1, -1, -4 ]]);

#my $y = Math::Matrix -> new([[  3,  1, -1 ],
#                             [ 11,  5, -6 ],
#                             [ -2, -1,  1 ]]);

my $y = Math::Matrix -> new([[  2.9999,  0.9999, -0.9999 ],
                             [ 10.9999,  4.9999, -5.9999 ],
                             [ -1.9999, -0.9999,  0.9999 ]]);

my $I = Math::Matrix -> id(3);

my $res = $x * $y - $I;

my $d = $x -> catcol($res) -> solve();
$y -= $d;
print $y;

__END__

print $res;

print $x -> mmuladd($y, -$I);


__END__

use lib 'lib';
use Math::Matrix;

use Benchmark ':all';

try( 4, 1000);
try( 6,  150);
try( 8,   25);
try(10,    5);

sub try {
    my ($n, $N) = @_;
    print "\n", "-" x 64, "\n\n";
    print "$N cycles of $N matrices with size $n-by-$n.\n\n";
    print "Generating random matrices ...";
    my @M = ();
    for (my $k = 0 ; $k < $N; ++$k) {
        for (my $i = 0 ; $i < $n ; ++$i) {
            for (my $j = 0 ; $j < $n ; ++$j) {
                $M[$k][$i][$j] = int(19 * rand) - 9;
            }
        }
        $M[$k] = bless $M[$k], 'Math::Matrix';
    }
    printf " done.\n\n";

    timethese($N,
             {
              '0old' => sub {
                  for my $k (0 .. $N-1) { my $d = $M[$k] -> determinant_old(); }
              },
              '1new' => sub {
                  for my $k (0 .. $N-1) { my $d = $M[$k] -> determinant(); }
              },
             }
            );
}

__END__

{
    my ($x, $y);
    $x = -5 + int(11 * Math::Matrix -> rand($n, $n));
    eval { $y = $x -> inv(); };
    redo if $@;
    for (my $i = 0 ; $i < $n ; ++$i) {
        for (my $j = 0 ; $j < $n ; ++$j) {
            $y -> [$i][$j] = sprintf '%.0f', $y -> [$i][$j];
        }
    }
    #if ($@) {
    #    print "\ninversion failed for x = \n", $x, "\n$@\n";
    #    exit;
    #}
    my $xy = $x -> mmul($y);
    redo unless $xy -> is_identity();
    print "-" x 72, "\n";
    print "\n\$x =\n", $x, ";\n";
    print "\n\$y =\n", $y, ";\n";
    print "\nx*y = \n\n", $x*$y, "\n";
    redo;
}

__END__

use Carp qw< carp croak confess cluck >;

if (0) {
    # give a full stack dump on any untrapped exceptions
    local $SIG{__DIE__} = sub {
        confess "Uncaught exception: @_" unless $^S;
    };

    # now promote run-time warnings into stackdumped exceptions
    #   *unless* we're in an try block, in which
    #   case just generate a clucking stackdump instead
    local $SIG{__WARN__} = sub {
        if ($^S) { cluck   "Trapped warning: @_" }
        else     { confess "Deadly warning: @_"  }
    };
}

use lib 'lib';
use Math::Matrix;

my $n = shift;

while (1) {
    print "\n";

    my $x = -5 + int(11 * Math::Matrix -> rand($n, $n));
    #my $x = Math::Matrix -> new([[ 4, -3,  1, -4 ],
    #                             [ 4,  3, -4, -2 ],
    #                             [ 5,  0,  5, -4 ],
    #                             [ 2,  3, -3, -1 ]]);
    print "$x\n";
    my $d1 = $x -> determinant();
    my $d2 = $x -> det();

    print "d1 = $d1\n";
    print "d2 = $d2\n";
    last if sprintf('%.0f', $d1) != sprintf('%.0f', $d2);
}

__END__

my $x =
[[ -5,  0,  8,  7 ],
 [  5,  4,  7,  0 ],
 [ -4,  0,  4,  8 ],
 [ -6, -4, -8,  4 ]];

$x = Math::Matrix -> new($x);

my $y = $x -> invert();

print "-" x 72, "\n";
print "y = \n", $y = $x -> invert(), "\n";
print "-" x 72, "\n";
print "x*y = \n", $x*$y, "\n";
print "-" x 72, "\n";
print $x -> inv(), "\n";
print "-" x 72, "\n";


my ($y, $rpv, $cpv) = $x -> catcol(Math::Matrix -> id(4)) -> felim_fp();
$y = $y -> bsubs();
$y = $y -> splicecol(0, 4);

my $icpv = [];
@$icpv[ @$cpv ] = 0 .. 3;

#@$y = @{$y}[ @$icpv ];
@$y[ @$cpv ] = @$y;

print "rpv  = [ ", join(", ", @$rpv), " ]\n";
print "cpv  = [ ", join(", ", @$cpv), " ]\n";
print "icpv = [ ", join(", ", @$icpv), " ]\n";
print "\n";
print "x    =\n", $x, "\n";
print "\n";
print "y    =\n", $y, "\n";
print "\n";
print "x*y  =\n", $x*$y, "\n";
print "\n";

__END__

$x =
  [[  0, -1,  1 ],
   [ -4,  7,  2 ],
   [  3, -6, -1 ]];

$y =
  [[  5, -7, -9 ],
   [  2, -3, -4 ],
   [  3, -3, -4 ]];

# 3-by-3

$x =
[[  1,  0,  1 ],
 [ -1, -1, -7 ],
 [  1, -1, -4 ]];

$y =
[[  3,  1, -1 ],
 [ 11,  5, -6 ],
 [ -2, -1,  1 ]];

# 4-by-4

$x =
[[  1, -2,  1,  6 ],
 [ -2,  0, -2, -7 ],
 [  1,  1,  2,  7 ],
 [  2, -1,  2,  8 ]];

$y =
[[  2, -5, -1, -5 ],
 [  2, -4, -0, -5 ],
 [ -9, 15,  1, 19 ],
 [  2, -3,  0, -4 ]];

$x =
[[ -2,  1, -4,  0 ],
 [ -1,  0, -3, -1 ],
 [ -2,  5,  3,  8 ],
 [  0, -3, -7, -5 ]];

$y =
[[ -23,  37,   4,  -1 ],
 [ -25,  42,   4,  -2 ],
 [   5,  -8,  -1,  -0 ],
 [   8, -14,  -1,   1 ]];

$x =
[[  0, -1, -4,  5 ],
 [  2,  2,  2, -1 ],
 [ -1,  0, -1, -8 ],
 [  0,  0, -9, -8 ]];

$y =
[[ -128,  -64, -129,   57 ],
 [  153,   77,  154,  -68 ],
 [  -16,   -8,  -16,    7 ],
 [   18,    9,   18,   -8 ]];

$x =
[[ -2,  1, -4,  0 ],
 [ -1,  0, -3, -1 ],
 [ -2,  5,  3,  8 ],
 [  0, -3, -7, -5 ]];

$y =
[[ -23,  37,   4,  -1 ],
 [ -25,  42,   4,  -2 ],
 [   5,  -8,  -1,  -0 ],
 [   8, -14,  -1,   1 ]];

$x =
[[  0, -1, -4,  5 ],
 [  2,  2,  2, -1 ],
 [ -1,  0, -1, -8 ],
 [  0,  0, -9, -8 ]];

$y =
[[ -128,  -64, -129,   57 ],
 [  153,   77,  154,  -68 ],
 [  -16,   -8,  -16,    7 ],
 [   18,    9,   18,   -8 ]];

$x =
[[  4,  0, -4, -3 ],
 [ -1,  0,  1,  1 ],
 [  1,  3,  3,  7 ],
 [ -3,  4,  8, -5 ]];

$y =
[[  -55, -208,    4,   -3 ],
 [   72,  271,   -5,    4 ],
 [  -56, -211,    4,   -3 ],
 [    1,    4,    0,    0 ]];

$x =
[[  8,  8,  4, -1 ],
 [ -5, -4,  2, -9 ],
 [  0,  1,  4,  3 ],
 [ -3, -2,  3, -9 ]];

$y =
[[  -87, -359,   -8,  366 ],
 [   99,  408,    9, -416 ],
 [  -24,  -99,   -2,  101 ],
 [   -1,   -4,   -0,    4 ]];

$x =
[[ -5,  0,  8,  7 ],
 [  5,  4,  7,  0 ],
 [ -4,  0,  4,  8 ],
 [ -6, -4, -8,  4 ]];

$y =
[[   9007199254740984,  13510798882111488, -14636698788954104,  13510798882111488 ],
 [ -16513198633691806, -24769797950537732,  26833947779749200, -24769797950537732 ],
 [   3002399751580329,   4503599627370497,  -4878899596318036,   4503599627370497 ],
 [   3002399751580328,   4503599627370496,  -4878899596318035,   4503599627370496 ]];
$x =
[[ -9, -9, -2,  3 ],
 [  6, -3, -5, -5 ],
 [  1,  6,  5, -2 ],
 [  8,  6,  1, -5 ]];

$y =
[[  -4371140814800775,   4371140814800775,   4371140814800775,  -8742281629601550 ],
 [   4945129002602897,  -4945129002602897,  -4945129002602898,   9890258005205794 ],
 [  -5960646565637420,   5960646565637421,   5960646565637421, -11921293131274840 ],
 [  -2251799813685248,   2251799813685248,   2251799813685248,  -4503599627370496 ]];

# 5-by-5



__END__

my $x = -9 + int(19 * Math::Matrix -> rand(4, 4));
#my $y = -5 + 10 * Math::Matrix -> rand(6, 1);

print $x, "\n";
#print $y, "\n";

my $y = $x -> inv();

print "\n";
print $y, "\n";

print "\n";
print $x * $y, "\n";


__END__

use Math::Approx::Chebyshev ':all';

my $n = 8;
my $f = sub { cos $_[0] };
my ($a, $b) = (0, 1);

my $c = chebcoef($n, $f, $a, $b);
print "$_\n" for @$c;

    # Compare approximation to exact value.
    for (my $x = 0 ; $x <= 1 ; $x += 0.125) {
        my $ya = chebeval($x, $a, $b, $c);  # approximation
        my $ye = $f->($x);                  # exact
        printf "%10.3f %20.16f %20.16f %20.16f\n",
          $x, $ya, $ye, $ya - $ye;
    }


__END__

=pod

perl -I/cygdrive/c/perl/math-dists/05-devel/Math-BigInt-1.999801/lib -MMath::BigInt -wle 'print for Math::BigInt->VERSION, Math::BigInt->new($ARGV[0])->band($ARGV[1])' --

=cut

use lib '/cygdrive/c/share/repos/private/github.com/pjacklam/p5-Math-BigInt/lib';

    use strict;
    use warnings;
    use Math::BigFloat;

    my $x = Math::BigFloat -> new(6);
    $x -> accuracy(5);

    my $y = Math::BigFloat -> new(4);
    $y -> precision(-3);

    my $zadd = $x + $y;     # = NaN
    my $zmul = $x * $y;     # = NaN
    my $zsub = $x - $y;     # = NaN
    my $zdiv = $x / $y;     # = NaN
    my $zpow = $x ** $y;    # = NaN

print $zadd, "\n";
print $zmul, "\n";
print $zsub, "\n";
print $zdiv, "\n";
print $zpow, "\n";

__END__

use Data::Dumper;

Math::BigFloat -> accuracy(80);

my $x = Math::BigFloat -> new(2);
print "x = $x\n";

$x -> bfround(-4);
print "x = $x\n";

#print Data::Dumper -> Dumper([$x]), "\n";
$x -> blsft(2, 10);
print "x = $x\n";

#print Data::Dumper -> Dumper([$x]), "\n";

__END__

print " bstr(): ", $x -> bstr(), "\n";
print "bsstr(): ", $x -> bsstr(), "\n";
print "bnstr(): ", $x -> bnstr(), "\n";
print "bestr(): ", $x -> bestr(), "\n";


__END__

use Math::BigInt;
use Math::BigInt::CalcEmu;

die "Usage: try.pl X Y\n" unless @ARGV == 2;
my $xstr = 0 + shift();
my $ystr = 0 + shift();

my $xsgn = $xstr < 0 ? '-' : '+';
my $ysgn = $ystr < 0 ? '-' : '+';
my $xval = abs $xstr;
my $yval = abs $ystr;

{
    print "\n";
    my $x = Math::BigInt -> new($xsgn . $xval);
    my $y = Math::BigInt -> new($ysgn . $yval);

    print "x = ", $xsgn, $xval, "\n";
    print "y = ", $ysgn, $yval, "\n";

    my $sx = $x->{sign} eq '+' ? 1 : -1;
    my $sy = $y->{sign} eq '+' ? 1 : -1;

    # The following modifies $x in-place ...
    Math::BigInt::__emu_band('Math::BigInt::Class',
                             $x, $y, $sx, $sy);

    my $zsgn = $x -> {sign};
    my $zval = $x -> copy() -> babs() -> bstr();
    print "z = ", $zsgn, $zval, "\n";
}

{
    print "\n";
    my $x = Math::BigInt::Calc->_new($xval);
    my $y = Math::BigInt::Calc->_new($yval);
    print "x = ", $xsgn, Math::BigInt::Calc -> _str($x), "\n";
    print "y = ", $ysgn, Math::BigInt::Calc -> _str($y), "\n";

    my ($z, $zsgn) = Math::BigInt::Calc->_sand($x, $y, $xsgn, $ysgn);
    print "z = ", $zsgn, Math::BigInt::Calc -> _str($z), "\n";
}

__END__


__END__

use v5.14;
use strict;
use warnings;

use SVG;

my $svg = SVG -> new();

# a 10-pointsaw-tooth pattern
my $xv = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
my $yv = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1];

my $points = $svg->get_path(
    x       => $xv,
    y       => $yv,
    -type   => 'polyline',
    -closed => 'true' #specify that the polyline is closed.
);

my $tag = $svg->polyline (
    %$points,
    id    =>'pline_1',
    style => {
        'fill-opacity' => 0,
        'stroke'       => 'rgb(250,123,23)'
    }
);


print $svg -> xmlify();

__END__

#use lib 'lib';

use Math::BigInt;

Math::BigInt->precision(-4);

my $x = Math::BigInt->new(5, 3, undef);
say "x = ", $x;
say "a = ", $x->accuracy()  // "undef";
say "p = ", $x->precision() // "undef";

__END__

exit

use lib '/cygdrive/c/perl/math-dists/05-devel/Math-BigInt-1.999802/lib';
use Math::BigInt;

use Math::BigInt::Lib;

print "\n";
print "       Math::BigInt ", Math::BigInt -> VERSION(), "\n";
print "  Math::BigInt::Lib ", Math::BigInt::Lib -> VERSION(), "\n";
print "\n";

my ($x, $y) = @ARGV;

my $ax = abs $x;
my $ay = abs $y;

my $sx = $x < 0 ? '-' : '+';
my $sy = $y < 0 ? '-' : '+';

# Math::BigInt

my $xobj = Math::BigInt -> new($x);
my $yobj = Math::BigInt -> new($y);

my $zobj = $xobj -> copy() -> band($yobj);

print "$zobj\n";

# Math::BigInt::Calc

my $xlib = Math::BigInt::Calc -> _new($ax);
my $ylib = Math::BigInt::Calc -> _new($ay);

$xlib = Math::BigInt::Calc -> _copy($xlib);
my ($zlib, $slib) =
  Math::BigInt::Calc -> _signed_and($xlib, $ylib, $sx, $sy);

print $slib eq '-' ? '-' : '', $zlib, "\n";

__END__


use lib 't', 'lib';

use Math::BigInt::Calc;
use Math::BigInt::Lib::TestUtil qw< randstr >;

print "Using Math::BigInt::Calc version ", Math::BigInt::Calc -> VERSION, "\n";

for my $n (8 .. 100) {
    for (1 .. 10) {
        my $xstr = randstr $n, 10;
        my $x = Math::BigInt::Calc -> _new($xstr);

        # $s0 should be exact or too small

        my $s0   = Math::BigInt::Calc -> _sqrt($x);
        my $s0sq = Math::BigInt::Calc -> _mul(Math::BigInt::Calc -> _copy($s0), $s0);

        my $acmp0 = Math::BigInt::Calc -> _acmp($s0sq, $x);
        next if $acmp0 == 0;

        # $s1 should be too big

        my $s1   = Math::BigInt::Calc -> _inc(Math::BigInt::Calc -> _copy($s0));
        my $s1sq = Math::BigInt::Calc -> _mul(Math::BigInt::Calc -> _copy($s1), $s1);

        if ($acmp0 > 0) {
        }
        my $acmp1 = Math::BigInt::Calc -> _acmp($s1sq, $x);


        my $expected = int sqrt $xstr;
        if ($expected * $expected > $xstr) {
            die "$expected";
        }

        if (Math::BigInt::Calc -> _str($s) != $expected) {
            die "sqrt($xstr) = ", int(sqrt($xstr)), ", but got $s";
        }
}

__END__

for my $xstr (1 .. 2_147_483_647) {
    my $x = Math::BigInt::Calc -> _new($xstr);
    my $s = Math::BigInt::Calc -> _sqrt($x);

    my $expected = int sqrt $xstr;
    if ($expected * $expected > $xstr) {
        die "$expected";
    }

    if (Math::BigInt::Calc -> _str($s) != $expected) {
        die "sqrt($xstr) = ", int(sqrt($xstr)), ", but got $s";
    }
}

__END__


#my $x = Math::BigInt::Calc -> _new($ARGV[0]); print Math::BigInt::Calc -> _sqrt($x)' -- 400000000000000000000000000000000000

__END__

use Math::BigFloat;

sub bpi {
    my ($a, $p, $r) = @_;
    $a = 40 unless defined $a && $a ne '';
    $p = undef if defined($p) && $p eq '';
    $r = 'even' if !defined($r) || (defined($r) && $r eq '');

    my $n = defined($a) ? $a : 1 - $p;

    die "Number of digits is too big\n" if $n > 2020;

    # 75 x 27 = 2025 digits

    my $all_digits = <<EOF;
314159265358979323846264338327950288419716939937510582097494459230781640628
620899862803482534211706798214808651328230664709384460955058223172535940812
848111745028410270193852110555964462294895493038196442881097566593344612847
564823378678316527120190914564856692346034861045432664821339360726024914127
372458700660631558817488152092096282925409171536436789259036001133053054882
046652138414695194151160943305727036575959195309218611738193261179310511854
807446237996274956735188575272489122793818301194912983367336244065664308602
139494639522473719070217986094370277053921717629317675238467481846766940513
200056812714526356082778577134275778960917363717872146844090122495343014654
958537105079227968925892354201995611212902196086403441815981362977477130996
051870721134999999837297804995105973173281609631859502445945534690830264252
230825334468503526193118817101000313783875288658753320838142061717766914730
359825349042875546873115956286388235378759375195778185778053217122680661300
192787661119590921642019893809525720106548586327886593615338182796823030195
EOF

    # Should we round up?

    my $round_up;

    # From the string above, we need to extract the number of digits we want
    # plus extra characters for the newlines.

    my $nchrs = $n + int($n / 75);

    # Extract the digits we want.

    my $digits = substr($all_digits, 0, $nchrs);

    # Find out whether we should round up or down. Since pi is a transcendental
    # number, we only have to look at one digit after the last digit we want.

    if ($r eq '+inf') {
        $round_up = 1;
    } elsif ($r eq 'trunc' || $r eq 'zero' || $r eq '-inf') {
        $round_up = 0;
    } else {
        my $next_digit = substr($all_digits, $nchrs, 1);
        $round_up = $next_digit lt '5' ? 0 : 1;
    }

    # Remove the newlines.
    $digits =~ tr/0-9//cd;

    # Do the rounding. We could easily make the regex substitution handle all
    # cases, but we avoid using the regex engine when it is simple to avoid it.

    if ($round_up) {
        my $last_digit = substr($digits, -1, 1);
        if ($last_digit lt '9') {
            substr($digits, -1, 1) = ++$last_digit;
        } else {
            $digits =~ s/([0-8])(9+)$/ ($1 + 1) . ("0" x CORE::length($2)) /e;
        }
    }

    # Append the exponent and convert to an object.

    my $pi = Math::BigFloat -> new($digits . 'e-' . ($n - 1));
    $pi -> {_a} = $a if defined $a;
    $pi -> {_p} = $r if defined $p;

    return $pi;
}

print bpi(@ARGV), "\n";


__END__

my $inf = 1e9999;
my $nan = $inf - $inf;

sub atan { CORE::atan2($_[0], 1) }
sub isnan { !($_[0] <= 0 || $_[0] > 0) }

sub atan2 {
    my ($y, $x) = @_;

    return $nan if isnan($x) || isnan($y);

    if ($x == $inf) {
        if ($y == $inf) {
            my $pi14 = CORE::atan2(1, 1);
            return $pi14;
        } elsif ($y == -$inf) {
            my $pi14 = CORE::atan2(1, 1);
            return -$pi14;
        } else {
            return 0;
        }
    }

    if ($x == -$inf) {
        if ($y == $inf) {
            my $pi34 = CORE::atan2(1, -1);
            return $pi34;
        } elsif ($y == -$inf) {
            my $pi34 = CORE::atan2(1, -1);
            return -$pi34;
        } elsif ($y >= 0) {
            my $pi = CORE::atan2(0, -1);
            return $pi;
        } else {                                # y < 0
            my $pi = CORE::atan2(0, -1);
            return -$pi;
        }
    }

    elsif ($x > 0) {
        if ($y == $inf) {
            my $pi12 = CORE::atan2(1, 0);
            return $pi12;
        } elsif ($y == -$inf) {
            my $pi12 = CORE::atan2(1, 0);
            return $pi12;
        } else {
            my $atan = atan($y / $x);
            return $atan;
        }
    }

    elsif ($x < 0) {                            # x < 0
        my $atan = atan($y / $x);
        my $pi = CORE::atan2(0, -1);
        if ($y >= 0) {
            return $atan + $pi;
        } else {
            return $atan - $pi;
        }
    }

    else {                                      # x = 0
        if ($y > 0) {
            my $pi12 = CORE::atan2(1, 0);
            return $pi12;
        } elsif ($y < 0) {
            my $pi12 = CORE::atan2(1, 0);
            return -$pi12;
        } else {
            return 0;
        }
    }
}

my ($y, $x) = @ARGV;
print "CORE:atan2($y, $x) = ", CORE::atan2($y, $x), "\n";
print "     atan2($y, $x) = ", &atan2($y, $x), "\n";

__END__

package Foo::Bar;

use Moose;

has [qw/ baz blah frob /] => (is => 'rw');

package main;

use Foo::Bar;

my $obj = Foo::Bar -> new();

#my $val = $obj -> baz();
my $val = $obj -> get('baz');

require Data::Dumper;
print Data::Dumper -> Dump([$val], ['$val']);

1;

__END__

use lib '/cygdrive/c/perl/math-dists/05-devel/Math-BigInt-1.999705/lib';

use Math::BigFloat lib => 'GMP';
use Test::More;

my $nmin =  13_380;
my $nmax = 250_000;

#Math::BigFloat -> round_mode('+inf');

my $ref = Math::BigFloat -> bpi($nmax + 100) -> bround($nmax);
for my $n ($nmin .. $nmax) {
    my $x = Math::BigFloat -> bpi($n);
    my $y = $ref -> copy() -> bround($n);
    is($x, $y, "bpi($n)");
}

done_testing();

__END__

use Test::More tests => 507068;

use Algorithm::Combinatorics qw< variations >;

use Test::More;

sub new {
    my ($str, $op) = @_;

    unless (defined $str) {
        require Carp;
        Carp::carp("Use of uninitialized value in $op");
        return 0;
    }

    my $val = 0;
    my $is_numeric = "";

    if ($str =~ / ^
                  \s*
                  ( [+-]? (?:\d+(?:\.\d*)?|\.\d+)(?:[Ee][+-]?\d+)? )
                  \s*
                  (\S.*)?
                  \z
                /x)
    {
        $val = $1;
        $is_numeric = ! defined($2);
    }

    unless ($is_numeric) {
        require Carp;
        Carp::carp(qq|Argument "$str" isn't numeric in $op|);
    }

    return $val;
}

#my $elements = ['0', 'b', 'x', '1', '1', '_', '_', '9', 'z'];
my $elements = ['2', '3', '4', '.', 'e', '+', '-', '+', '-', '_'];

for my $k (0 .. @$elements) {
    my $seen = {};
    for my $variation (variations($elements, $k)) {
        my $str = join "", @$variation;
        next if $seen -> {$str}++;
        print qq|#\n# 0 + "$str"\n#\n|;

        my $i;
        my @warnings;
        local $SIG{__WARN__} = sub {
            my $warning = shift;
            $warning =~ s/ at .*\z//s;
            $warnings[$i] = $warning;
        };

        $i = 0;
        my $want_val  = eval { 0 + "$str" };
        my $want_warn = $warnings[$i];

        $i = 1;
        my $got_val   = new("$str");
        my $got_warn  = $warnings[$i];

        is($got_val, $want_val,
           qq|0 + "$str" returns the value: $want_val|);

        is($got_warn, $want_warn,
           qq|new("$str") issues | .
           (length($want_warn) ? "the warning: $want_warn" : "no warning"));
    }
}

__END__

package Foo;

sub new {
    my $class = shift;
    print $class, "\n";
    my $self = {};
    bless $self, $class;
    return $self;
}

package Foo::Bar;

our @ISA = qw< Foo >;

package main;

my $obj = Foo::Bar -> new();


__END__

# check whether integer bdiv and bmuladd are complementary
# n should be equal to d * (n / d) + (n % d)

use strict;
use warnings;
use Test::More tests => 4;
use Math::BigInt;

sub check {
    my ($n, $d) = map { Math::BigInt->new($_) } @_;
    my ($q, $r) = $n->copy->bdiv($d);
    my $n2 = $d * $q + $r;
    is $n2, $n, sprintf q["%3s = %2s * %2s + %2s"], $n, $d, $q, $r;
}

check( 22,  5);
check( 22, -5);
check(-22,  5);
check(-22, -5);

__END__

use strict;
use Math::BigFloat;
my $n = Math::BigFloat->new(-10);
my $d = Math::BigFloat->new(5);
my $q = $n / $d;
my $r = $n % $d;
print "n=$n d=$d ->  q=$q  r=$r\n";

__END__

use strict;
use warnings;
use Benchmark qw(cmpthese);
use lib '/cygdrive/c/perl/math-dists/05-devel/Math-BigInt-1.999701/lib';
use Math::BigFloat;
print "\n", Math::BigFloat -> VERSION(), ":\n\n";
our $x  = Math::BigFloat->new( '1234567890' x 20 );
our $x2 = Math::BigFloat->new( '2234567890' x 20 );
cmpthese( -10, { log_2x => sub { $x2->copy->blog }, log_x => sub {$x->copy->blog } });

__END__

#use lib '/cygdrive/c/perl/math-dists/05-devel/Math-BigInt-1.991/lib';
#use lib '/cygdrive/c/perl/math-dists/05-devel/bignum-0.37/lib';

use lib '/cygdrive/c/src/perl/dist/math-dists/perl-5.10.0/perl-5.10.0/lib';

use bignum;

print bignum -> VERSION(), "\n";
print Math::BigInt -> VERSION(), "\n";

my $num = 2**1000;
my $sum = 0;

while ($num =~ m/(\d{1})/g){
     $sum += int($1);
}

print "sum = $sum\n";

__END__

# This doesn't work beacause the first few digits of the regex match are
# strange or incorrect characters.  Eventually this solution worked:

my $num = 2**1000;
my $sum = 0;

print "num = $num\n";

while ($num =~ m/(\d{1})/g){
     print $1;
     $sum += int($1);
}

print "sum = $sum\n";

__END__

use lib '/cygdrive/c/perl/math-dists/04-inst/Math-BigInt/Math-BigInt-1.999702/lib';
use lib '/cygdrive/c/perl/math-dists/05-devel/Math-BigRat-0.260801/lib';

use Math::BigInt;
use Math::BigRat;
use Test::More;

printf "Math::BigInt %s\n", Math::BigInt -> VERSION();
printf "Math::BigRat %s\n", Math::BigRat -> VERSION();
printf "\n";

my $plinf = 1e999 ** 1e999;
my $plnan = $plinf - $plinf;

my @x = ($plnan, $plinf, -$plinf, -3 .. 3);
my @y = ($plnan, $plinf, -$plinf, -3 .. 3);

# a ≡ b (mod m) implies that there exists a k so that a = b + km.

for my $x (@x) {
    for my $y (@y) {
        my $z;
        if ($y == 0) {
            if (abs($x) == $plinf) {
                $z = $plnan;
            } else {
                $z = $x;
            }
        } else {
            $z = $x % $y;
        }

        #print "$x % $y = $z\n";

        my $mbix = Math::BigInt -> new($x);
        my $mbiy = Math::BigInt -> new($y);
        my $mbiz = $mbix -> copy() -> bmod($mbiy);

        my $mbrx = Math::BigRat -> new($x);
        my $mbry = Math::BigRat -> new($y);
        my $mbrz = $mbrx -> copy() -> bmod($mbry);

        is($mbiz, $z, "$x % $y = $z");
    }
}

done_testing();

__END__

use 5.014;
use utf8;
use strict;
use autodie;
use warnings;
use warnings    qw< FATAL  utf8     >;
use open        qw< :std  :utf8     >;
use charnames   qw< :full >;
use feature     qw< unicode_strings >;

use File::Basename      qw< basename >;
use Carp                qw< carp croak confess cluck >;
use Encode              qw< encode decode >;
use Unicode::Normalize  qw< NFD NFC >;

#use Algorithm::Combinatorics qw< subsets >;

END { close STDOUT }

if (grep /\P{ASCII}/ => @ARGV) {
   @ARGV = map { decode("UTF-8", $_) } @ARGV;
}

$0 = basename($0);  # shorter messages
$| = 1;

binmode(DATA, ":utf8");

# give a full stack dump on any untrapped exceptions
local $SIG{__DIE__} = sub {
    confess "Uncaught exception: @_" unless $^S;
};

# now promote run-time warnings into stackdumped exceptions
#   *unless* we're in an try block, in which
#   case just generate a clucking stackdump instead
local $SIG{__WARN__} = sub {
    if ($^S) { cluck   "Trapped warning: @_" }
    else     { confess "Deadly warning: @_"  }
};

while (<>)  {
    chomp;
    #$_ = NFD($_);

    # Split the line into "words";

    my $n = 3;

    s/^\s+//;
    s/\s+\z//;
    s/\s+/ /g;

    #print "<$_>\n";

    next if
        m{
             .^

             | Dåset(bekken|veien)
             | Saasenveien trimløype
             | Sirikjerkeveien trimløype
             | Slettfjellveien trimløype
             | Strandvannet \s+ rundt
             | Tur \s+ til \s+ Jerpeton
             | Ulland \s+ power \s+ trail
             | V\.V\. \s+ PT
             | Vatnebrynrunden
             | [Pp]owertrail

             | 3 \s+ vann \s+ og \s+ ei \s+ elv \s+ med \s+ fosser
             | A(lle)? \s+ v(eier)? \s+ f(ører)? \s+ t(il)? \s+ Røyningsbu
             | Brentås \s+ rundtur
             | En \s+ av \s+ våre \s+ rundturer
             | En \s+ historisk \s+ vandring \s+ \S \s+ Drammen
             | En \s+ historisk \s+ vandring \s+ \S \s+ Nedre \s+ Eiker
             | En \s+ tur \s+ på \s+ Kråkerøy
             | Flautangen \s+ rundtur
             | Fredrikstad \s* marka \s+ PT
             | Frierstien, \s+ Brevik \s+ - \s+ Herøya
             | Frierstien, \s+ Herøya \s+ - \s+ Brevik
             | GMF \s+ GA \s+ VC \s+ DL
             | Gjerstadvannet \s+ rundt
             | Historisk \s+ vandring \s+ Kjølebrønd
             | Hortensmarka \s+ Rundtur
             | Hulkaleieren \s+ Rundtur
             | Hydrostranda \s+ rundtur
             | Kalvelifjellet \s+ - \s+ Godfjell \s+ WT
             | Litt \s+ sprek \s+ 2: \s+ Norges \s+ geografiske \s+ midtpunkt
             | Lysløypa \s+ - \s+ En \s+ liten \s+ rundtur \s+ i \s+ skogen
             | Mossemarka \s+ PT
             | Postrute \s+ - \s+ Varaldskogen
             | Postveien \s+ Sann?idal-Gjerstad
             | Postveien \s+ Tur \s+ [1-3]
             | Postveien \s+ og \s+ RundTur
             | Postveien \s+ og \s+ RundTur \s+ 1 \s+
             | Preståsen \s+ Rundtur
             | På \s+ tur \s+ i \s+ Bærumsmarka
             | På \s+ tur \s+ til \s+ Sprinkelet
             | RundTur \s+ 3 \s+ timer \s+ 9,2 \s+ km
             | Rundtur \s+ Hvitsten \s+ – \s+ Ramme \s+ - \s+ Puttskog
             | Rundtur \s+ Tjenna
             | Rundtur \s+ Viddaseter
             | Rundtur \s+ i \s+ Høg \s+ – \s+ Jæren \s+ Energipark
             | Rundtur \s+ med \s+ bil
             | Rundtur \s+ på \s+ Herre
             | Rundtur \s+ til \s+ Straumane
             | Rundtur \s+ ved \s+ Rapentangen
             | Rundtur \s+ Årum \s+ - \s+ Presteseter
             | Rundtur \s+ Årum \s+ - \s+ Ruggefjell
             | Skau-tur \s+ i \s+ Kroken
             | Solbakkefjellet \s+ rundt
             | Storås \s+ rundtur \s+ nr
             | Stålfjelsaksla \s+ - \s+ Solstad \s+ Rundtur
             | Sykkeltrailen \s+ Bom \s+ t \s+ Bom
             | Sykkeltur \s+ i \s+ Kroken
             | Sørenget \s* - \s* Leirvika
             | Tur \s+ i \s+ Rådeskogen \s+ WT
             | Turløype ( \s+ \d )? \s+ på \s+ Herre
             | Use \s+ Your \s+ Feet, \s+ and \s+ walk
             | Ut \s+ på \s+ tur, \s+ aldri \s+ sur \s+ :-D
             | Ved \s+ foten \s+ av \s+ Kvarsnestind \s+ PT
             | Vegårshei \s+ på \s+ x \s+ og \s+ tvers
             | WT \s+ 85 \s+ km
             | WT \s+ Svanstul \s+ - \s+ Horta
             | på \s+ tur \s+ i \s+ skarboskauen

     }x;

    #my $words = [ / ( [[:alpha:]] \w* ) /gx ];
    my $words = [ split /\s+/, $_ ];
    next if @$words < $n;

    my $imax = @$words - $n;
    for (my $i = 0 ; $i <= $imax ; ++ $i) {
        say join(" ", @$words[$i .. ($i + $n -1 )])
          or die "$0: print failed: $!\n";
    }
}


__END__

use Geo::Ellipsoid;

my $geo = Geo::Ellipsoid -> new(
   ellipsoid=>'WGS84',
   units=>'degrees',
   distance_units => 'kilometer',
   longitude => 1,
  );

$| = 1;

sub commify {
    my $text = reverse $_[0];
    $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
    return scalar reverse $text;
}

for (my $i = 1 ; ; $i ++) {
    my $lat0    =  -90 + rand 180;
    my $lon0    = -180 + rand 360;
    my $range   = rand (40075 / 2);
    my $bearing = rand 360;
    my ($lat1, $lon1) =  $geo -> at($lat0, $lon0, $range, $bearing);
    if ($lat1 < -90 && $lat1 > 90) {
        printf qq|\n%17.12f %17.12f|, $lat1, $lon1;
        print qq| \$geo -> at($lat0, $lon0, $range, $bearing);\n|;
        exit;
    }
    print "\r", commify($i) unless $i % 100_000;
}

__END__

$geo = Geo::Ellipsoid->new(
        ellipsoid=>'WGS84',
        units=>'degrees',
        distance_units => 'kilometer',
        longitude=>1,
);

my @origin = ( 48.849954, 2.333179 ); # paris
my $range = 300;

print<<EOF;
<?xml version="1.0"?>
<gpx version="1.0" creator="Geo::Ellipsoid" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
  <trk>
    <name>Track</name>
    <trkseg>
EOF

for($bearing=0; $bearing<=360; $bearing +=10 ) {
        my ($lat,$lon) = $geo->at( @origin, $range, $bearing );
        #$lon = $lon - 360 if $lon > 180;
        printf("\t\t<trkpt lat=\"%s\" lon=\"%s\"></trkpt>\n", $lat, $lon);
}

print<<EOF;
    </trkseg>
  </trk>
</gpx>
EOF
