Repository navigation
Check axis lengths, interpolate them with $, and export the macros (v0.3.0) - #62
Merged
Merged
Conversation
…unit `"4 b -> b"` reduced an axis of length 3, and `a=4` for an ungrouped `a` was never compared with the input: a known length only entered the plan inside a group, as a split. Every length the left side fixes, from an integer, a unit or a keyword, is now checked before anything reshapes, with the input axis and the expected length in the message. A group with one name left to infer must be divisible by the rest. `1` inside parentheses is a unit, as in Python einops, so `(b a 1)` is `(b a)` (#60). An entry the plan builders do not recognize now raises instead of being skipped, which is what turned `(b a 1)` into an empty reshape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ern's type `$x` in a pattern is an axis of length `x`, named after the expression, so the same expression twice is the same axis: `"($h d) n -> d n $h"` splits off `h` and keeps it. The shorthand macros pass the value on as a keyword, and `einops"..."` returns a `BoundPattern` carrying the values beside the pattern, which every op and `einsum` accept. Either way the pattern's type holds only the name, so a length computed at run time leaves the call type stable, which an integer built into a tuple pattern cannot (#34, #35). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`@rearrange`, `@reshape`, `@reduce`, `@repeat` and `@einsum` become the exported interface, so the README's quickstart works after `using Einops`. Lengths that were passed but wrong now throw, which also makes this a minor bump. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #62 +/- ##
==========================================
- Coverage 99.56% 99.49% -0.07%
==========================================
Files 15 15
Lines 683 793 +110
==========================================
+ Hits 680 789 +109
- Misses 3 4 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…ength A name is an index, and an index twice on one side is a diagonal, which is einsum's business. `$k` named its axis after the expression, which mixed the two: `$k` and `$h` were different axes at equal values, and `$k $k` was a duplicate. Now `$k` is what the value would be if written there, an axis of that length that can only be reduced or created, each occurrence its own. So `"(h $k) (w $k) -> h w"` pools and `"a b -> ($k a) ($k b)"` repeats, without duplicate names (#36). Keeping an axis through `rearrange` takes a name and a keyword, `"(h d) n -> d n h"; h`. `einsum` takes no `$`: such an axis could only be summed out, which a name does too. The value still rides beside the pattern, so the type stays stable; only a value of 1 differs from writing 1, staying an axis of length one rather than a unit, since the value cannot decide the plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lengths are checked. Every length the left side of a pattern fixes is now compared with the input before anything reshapes it. That covers integers,
1, and names given a length by keyword. Before,"4 b -> b"reduced an axis of length 3, anda=4for an ungroupedawas never looked at, because a known length only entered the plan inside a group, as a split. A group with one name left to infer must be divisible by the rest. Errors name the input axis, also past an ellipsis:"1 b -> b"on a length-3 axis still throws. That is the same rule, now with the same message.1inside parentheses is a unit, as in Python einops:(b a 1)is(b a), and()or(1)is a length-one axis. An entry the plan builders do not recognize now raises instead of being skipped, which is what turned(b a 1)into an empty reshape (#60). Other integers say where they are allowed: reduced on the left ofreduce, or created on the right ofrepeat.$kinterpolates a length (#35): an axis of lengthk, as if the value were written there, the way Python einops users writef"({k} a)". Like an integer other than 1, it can only be reduced or created, and each occurrence is an axis of its own:The value never enters the pattern's type (#34):
einops"..."returns a new publicBoundPattern, which shows as the pattern with the values in place.A length computed at run time therefore leaves the call type stable, and
@inferredtests cover this. An integer built into a-->tuple pattern still cannot do that, since the type can't tell1from3; the-->docstring now says so and points to the alternatives. For the same reason a value of 1 stays an axis of length one rather than becoming a unit: reduced or created, that gives the same result, but$kis rejected inrearrangewhatever its value.A name is an index, so duplicate names stay rejected. #36 asked for duplicates as a size hint, but an index twice on one side means a diagonal, which is
einsum's business ("k k ->"is the trace, there and in Python).$kcovers the size-hint use case instead. Keeping an axis throughrearrangetakes a name and a keyword,"(h d) n -> d n h"; h.einsumrejects$: such an axis could only be summed out, which a name does too, andeinsumisn't type stable to begin with.Version 0.3.0 requires Julia 1.10 and exports
@rearrange,@reshape,@reduce,@repeatand@einsum, which also makes the README quickstart work afterusing Einops. Breaking for:@reduce) or Einsum.jl (which exports@einsum) alongside Einops; those names now need qualifying.Tests:
test/axis_lengths.jlis new. The full suite passes on Julia 1.10 and 1.13. Zygote passes on 1.12 and Reactant on 1.13, each with new tests for checked and interpolated lengths, including a wrong length throwing while tracing. Doctests and the docs build are clean.Closes #34, closes #35, closes #36, closes #60.
🤖 Generated with Claude Code