<commit_before>use v6;
use BinarySearch;

enum KnotBasisDirection <Left Right>;

sub infix:<O/>($a, $b)
{
    return 0 if abs($b) < 1e-10;
    return $a / $b;
}

class KnotVector
{
    has @.knots;
    
    multi method new (@u) 
    {
        self.bless(*, knots => @u);
    }
    
    our Str multi method Str() 
    {
        "(" ~ @.knots.join(', ') ~ ")";
    }
    
    our Str multi method perl()
    {
        self.WHAT.perl ~ ".new((" ~ @.knots.map({.perl}).join(', ') ~ "))";        
    }
        
    multi method N0_index($u, KnotBasisDirection $direction = Left)
    {
        given $direction
        {
            when Left { LowerBound(@.knots, $u); }
            when Right { UpperBound(@.knots, $u); }
        }
    }
    
    multi method N_local(Int $n0, Int $p, $u, KnotBasisDirection $direction = Left)
    {
        my @N_prev = 0 xx $p, 1, 0;
        my @N = 0 xx ($p + 2);
        
        my $n0p = $n0 - $p - 1;
        
        for 1..$p -> $q
        {
            for ($p - $q)...($p) -> $i
            {
                @N[$i] = (($u - @.knots[$n0p + $i]) O/ (@.knots[$n0p + $i + $q] - @.knots[$n0p + $i])) * @N_prev[$i]
                + ((@.knots[$n0p + $i + $q + 1] - $u) O/ (@.knots[$n0p + $i + $q + 1] - @.knots[$n0p + $i + 1])) * @N_prev[$i + 1];
            }
            @N_prev = @N;
        }
        @N.pop;

        return @N;
    }
    
    multi method N(Int $p, $u, KnotBasisDirection $direction = Left)
    {
        my $n0 = self.N0_index($u, $direction);
        my @N = 0 xx (@.knots.elems - $p - 1);
        @N[($n0-$p-1)..($n0-1)] = self.N_local($n0, $p, $u, $direction);
        return @N;
    }
}<commit_msg>Change N0_index to take a degree $p and return the start of the interesting region rather than the end.  Also swap LowerBound and UpperBound in it.  Associated changes.<commit_after>use v6;
use BinarySearch;

enum KnotBasisDirection <Left Right>;

sub infix:<O/>($a, $b)
{
    return 0 if abs($b) < 1e-10;
    return $a / $b;
}

class KnotVector
{
    has @.knots;
    
    multi method new (@u) 
    {
        self.bless(*, knots => @u);
    }
    
    our Str multi method Str() 
    {
        "(" ~ @.knots.join(', ') ~ ")";
    }
    
    our Str multi method perl()
    {
        self.WHAT.perl ~ ".new((" ~ @.knots.map({.perl}).join(', ') ~ "))";        
    }
        
    multi method N0_index(Int $p, $u, KnotBasisDirection $direction = Left)
    {
        given $direction
        {
            when Left { UpperBound(@.knots, $u) - $p - 1; }
            when Right { LowerBound(@.knots, $u) - $p - 1; }
        }
    }
    
    multi method N_local(Int $n0, Int $p, $u, KnotBasisDirection $direction = Left)
    {
        my @N_prev = 0 xx $p, 1, 0;
        my @N = 0 xx ($p + 2);
                
        for 1..$p -> $q
        {
            for ($p - $q)...($p) -> $i
            {
                @N[$i] = (($u - @.knots[$n0 + $i]) O/ (@.knots[$n0 + $i + $q] - @.knots[$n0 + $i])) * @N_prev[$i]
                + ((@.knots[$n0 + $i + $q + 1] - $u) O/ (@.knots[$n0 + $i + $q + 1] - @.knots[$n0 + $i + 1])) * @N_prev[$i + 1];
            }
            @N_prev = @N;
        }
        @N.pop;

        return @N;
    }
    
    multi method N(Int $p, $u, KnotBasisDirection $direction = Left)
    {
        my $n0 = self.N0_index($p, $u, $direction);
        my @N = 0 xx (@.knots.elems - $p - 1);
        @N[($n0)..($n0 + $p)] = self.N_local($n0, $p, $u, $direction);
        return @N;
    }
}
{'fraction_non_alphanumeric': 0.19971181556195966, 'fraction_numerical': 0.019596541786743516, 'mean_word_length': 1.5115774240231548, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2800984', 'n_tokens_mistral': 1454, 'n_tokens_neox': 1391, 'n_words': 334}