Math-BSpline-Basis

 view release on metacpan or  search on metacpan

lib/Math/BSpline/Basis.pm  view on Meta::CPAN

package Math::BSpline::Basis;
$Math::BSpline::Basis::VERSION = '0.002';
use 5.014;
use warnings;

# ABSTRACT: B-spline basis functions

use Moo 2.002005;
use List::Util 1.26 ('min');
use Ref::Util 0.010 (
    'is_ref',
    'is_plain_hashref',
    'is_blessed_hashref',
    'is_plain_arrayref',
);


around BUILDARGS => sub {
    my ($orig, $class, @args) = @_;
    my $munged_args;

    if (@args == 1) {
        if (!is_ref($args[0])) {
            # We do not understand this and dispatch to Moo (if this
            # is what $orig does, the docu is very sparse).
            return $class->$orig(@args);
        }
        elsif (
            is_plain_hashref($args[0])
            or
            is_blessed_hashref($args[0])
        ) {
            # I am trying to stay as close to Moo's default behavior
            # as I can, this is the only reason why I am supporing
            # hashrefs at all. And since Moo apparently accepts
            # blessed references, I do the same. However, I make a
            # copy, blessed or not.
            #
            # The ugly test is due to an announced change in the
            # behavior of Ref::Util. is_hashref is going to behave
            # like is_plain_hashref does now.  However, the planned
            # replacement called is_any_hashref is not there. So the
            # only future-safe implementation seems to be to use
            # both explicit functions.
            $munged_args = {%{$args[0]}};
        }
        else {
            # We do not understand this and dispatch to Moo (if this
            # is what $orig does, the docu is very sparse).
            return $class->$orig(@args);
        }
    }
    elsif (@args % 2 == 1) {
        # We do not understand this and dispatch to Moo (if this
        # is what $orig does, the docu is very sparse).
        return $class->$orig(@args);
    }
    else {
        $munged_args = {@args};
    }

    if (exists($munged_args->{knot_vector})) {
        # degree is mandatory, so we only deal with the case when it
        # is there. Otherwise we just let Moo do its job.
        if (exists($munged_args->{degree})) {
            # We do not perform any type validation etc, if the
            # attributes are there, we use them assuming that they
            # are valid.
            my $p           = $munged_args->{degree};
            my $U           = $munged_args->{knot_vector};
            my $is_modified = 0;

            # deal with empty array
            if (!defined($U) or !is_plain_arrayref($U) or @$U == 0) {
                $U = [
                    (map { 0 } (0..$p)),
                    (map { 1 } (0..$p)),
                ];
                $is_modified = 1;
            }

            # deal with unsorted
            for (my $i=1;$i<@$U;$i++) {
                if ($U->[$i] < $U->[$i-1]) {
                    $U           = [sort { $a <=> $b } @$U];
                    $is_modified = 1;
                    last;
                }
            }

            # deal with first breakpoint
            for (my $i=1;$i<=$p;$i++) {
                if ($i == @$U or $U->[$i] != $U->[$i-1]) {
                    $U = [@$U] if (!$is_modified);
                    unshift(@$U, $U->[0]);
                    $is_modified = 1;
                }
            }

            # deal with last breakpoint



( run in 1.490 second using v1.01-cache-2.11-cpan-39bf76dae61 )