<commit_before>use MultiVector::BitEncoded;
use MultiVector::BitEncoded::BasisBlade;
unit class MultiVector::BitEncoded::Optimized does MultiVector::BitEncoded;

has UInt @.basis;
has Real @.reals;
method reals { @!reals }  # overides any previously defined reals method
method bitEncoding { (@!basis Z=> @!reals).MixHash }

method code returns Str { @!basis.join('|') }

submethod BUILD(:@basis, :@reals) {
    fail "expected strictly increasing order in @basis" unless [<] @basis;
    fail "unexpected number of coefficients" unless @basis == @reals;
    @!basis = @basis;
    @!reals = @reals;
}

multi method new(Real $s) { self.new: :basis[0], :reals[$s] }
multi method new(UIntHash $ where !*  ) { self.new(0) }
multi method new(UIntHash $bitEncoding) {
    my @basis = sort $bitEncoding.keys;
    self.new: :@basis, :reals[$bitEncoding{@basis}];
}
multi method new(MultiVector::BitEncoded $ where !*) { self.new(0) }
multi method new(MultiVector::BitEncoded $model    ) {
    my @pairs = sort *.key, $model.pairs;
    self.bless:
    :basis[@pairs».key],
    :reals[@pairs».value];
}

method clean {
    self.reals.none == 0 ??
    self !!
    self.new: self.bitEncoding
}

multi method add(::?CLASS $B) {
    self.new: (self.pairs, |$B.pairs).MixHash;
}
multi method add(Real $s) {
    self.new: (0 => $s, |self.pairs).MixHash;
}

multi method scale(Real $s) { self.new: :@!basis, :reals[@!reals X* $s] }
multi method gp(::?CLASS $A: ::?CLASS $B) { products($A.code, $B.code)<gp>($A, $B) }
multi method ip(::?CLASS $A: ::?CLASS $B) { products($A.code, $B.code)<ip>($A, $B) }
multi method op(::?CLASS $A: ::?CLASS $B) { products($A.code, $B.code)<op>($A, $B) }

sub basis-product(UInt $a, UInt $b) {
    (state @)[$a][$b] //= do {
	my ($A, $B) = map {
	    use MultiVector::BitEncoded::Default;
	    MultiVector::BitEncoded::Default.new: $^x.MixHash;
	}, $a, $b;
	{
	    gp => $A.gp($B).pairs,
	    ip => $A.ip($B).pairs,
	    op => $A.op($B).pairs,
	}
    }
}
sub products(Str $Acode, Str $Bcode) {
    (state %){$Acode}{$Bcode} //= do {
	use MONKEY-SEE-NO-EVAL;<commit_msg>do not use an array as cache!<commit_after>use MultiVector::BitEncoded;
use MultiVector::BitEncoded::BasisBlade;
unit class MultiVector::BitEncoded::Optimized does MultiVector::BitEncoded;

has UInt @.basis;
has Real @.reals;
method reals { @!reals }  # overides any previously defined reals method
method bitEncoding { (@!basis Z=> @!reals).MixHash }

method code returns Str { @!basis.join('|') }

submethod BUILD(:@basis, :@reals) {
    fail "expected strictly increasing order in @basis" unless [<] @basis;
    fail "unexpected number of coefficients" unless @basis == @reals;
    @!basis = @basis;
    @!reals = @reals;
}

multi method new(Real $s) { self.new: :basis[0], :reals[$s] }
multi method new(UIntHash $ where !*  ) { self.new(0) }
multi method new(UIntHash $bitEncoding) {
    my @basis = sort $bitEncoding.keys;
    self.new: :@basis, :reals[$bitEncoding{@basis}];
}
multi method new(MultiVector::BitEncoded $ where !*) { self.new(0) }
multi method new(MultiVector::BitEncoded $model    ) {
    my @pairs = sort *.key, $model.pairs;
    self.bless:
    :basis[@pairs».key],
    :reals[@pairs».value];
}

method clean {
    self.reals.none == 0 ??
    self !!
    self.new: self.bitEncoding
}

multi method add(::?CLASS $B) {
    self.new: (self.pairs, |$B.pairs).MixHash;
}
multi method add(Real $s) {
    self.new: (0 => $s, |self.pairs).MixHash;
}

multi method scale(Real $s) { self.new: :@!basis, :reals[@!reals X* $s] }
multi method gp(::?CLASS $A: ::?CLASS $B) { products($A.code, $B.code)<gp>($A, $B) }
multi method ip(::?CLASS $A: ::?CLASS $B) { products($A.code, $B.code)<ip>($A, $B) }
multi method op(::?CLASS $A: ::?CLASS $B) { products($A.code, $B.code)<op>($A, $B) }

sub basis-product(UInt $a, UInt $b) {
    (state %){$a}{$b} //= do {
	my ($A, $B) = map {
	    use MultiVector::BitEncoded::Default;
	    MultiVector::BitEncoded::Default.new: $^x.MixHash;
	}, $a, $b;
	{
	    gp => $A.gp($B).pairs,
	    ip => $A.ip($B).pairs,
	    op => $A.op($B).pairs,
	}
    }
}
sub products(Str $Acode, Str $Bcode) {
    (state %){$Acode}{$Bcode} //= do {
	use MONKEY-SEE-NO-EVAL;
{'fraction_non_alphanumeric': 0.20358851674641149, 'fraction_numerical': 0.0023923444976076554, 'mean_word_length': 3.971462544589774, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, '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': '1546883', 'n_tokens_mistral': 1688, 'n_tokens_neox': 1627, 'n_words': 393}