You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+37-6Lines changed: 37 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ The primitives in this package support downstream packages such as [Einops.jl](h
11
11
12
12
## Motivation
13
13
14
-
Julia infamously struggles with "double wrappers", particularly on GPUs, triggering generic fallbacks that use scalar indexing. This can make users particularly wary when working with views and lazy permutations. In the case of `reshape`, the *structure* of the new shape relative to the old shape is completely neglected, and an array may for example become a reshape of a view:
14
+
Julia infamously struggles with "double wrappers", particularly on GPUs, triggering generic fallbacks that use scalar indexing. This can make users wary when working with views and lazy permutations. In the case of `reshape`, the *structure* of the new shape relative to the old shape is completely neglected, and an array may for example become a reshape of a view:
We use `size(y, 1)` in our reshape, but despite preserving the first dimension (the one dimension only partially sliced) it evaluates to an integer at runtime, and Julia has no way of knowing that it represents preserving the first dimension. The size could in theory be constant-propagated [if the size wasn't dynamic](https://github.com/JuliaArrays/FixedSizeArrays.jl), [or if the size is embedded in the type](https://github.com/JuliaArrays/StaticArrays.jl), but even then, integers alone are not useful once passed through `reshape`.
28
+
We use `size(y, 1)` in our reshape, but despite preserving the first dimension (the one dimension only partially sliced) it evaluates to an integer at runtime, and Julia has no way of knowing that it represents preserving the first dimension.
29
+
30
+
The size could in theory be constant-propagated [if the size wasn't dynamic](https://github.com/JuliaArrays/FixedSizeArrays.jl), or [if the size is embedded in the type](https://github.com/JuliaArrays/StaticArrays.jl). But even then, integers alone are not useful once passed through `reshape`.
29
31
30
32
Rewrap provides types like `Keep`, `Merge`, and `Split` that encode reshape structure at compile-time, enabling rewrapping optimizations.
31
33
@@ -74,8 +76,38 @@ The view is commuted past the reshape: the parent array gets reshaped first, the
74
76
75
77
## Features
76
78
77
-
-`..` (from [EllipsisNotation.jl](https://github.com/SciML/EllipsisNotation.jl)) is replaced with `Keep(..)` when passed to `reshape`.
78
-
-`:` can be used like normal, but under the hood it gets replaced by `Merge(..)` when passed to `reshape`.
79
+
### Local Reshape Operations
80
+
81
+
These operations are passed to `reshape` and consume/emit a specific number of dimensions:
|`Reshape(ops, x)`| Apply a tuple of local reshape operations to array `x`. |
99
+
|`Permute(perm)`| Permute axes, unwrapping existing `PermutedDimsArray` when possible. |
100
+
|`Reduce(f; dims)`| Reduce over dimensions, unwrapping lazy permutes when only reduced dims were permuted. |
101
+
|`Repeat(repeats)`| Repeat array along dimensions, pushing through `PermutedDimsArray` to avoid scalar indexing. |
102
+
103
+
### Enhanced Base Functions
104
+
105
+
Rewrap also provides optimized versions of common operations:
106
+
107
+
-`Rewrap.reshape(x, ops...)` — reshape with full Rewrap semantics (no type piracy concerns)
108
+
-`Base.reshape(x, ops...)` — reshape with Rewrap semantics (must include a `LocalReshape`)
109
+
-`Rewrap.dropdims(x; dims)` — drop singleton dimensions while preserving wrapper types
110
+
-`Rewrap.vec(x)` — flatten to vector, preserving views when possible
79
111
80
112
## Limitations
81
113
@@ -86,7 +118,6 @@ julia> reshape(z, Keep(), :)
86
118
135131517
87
119
246141618
88
120
```
89
-
- Direct arguments of reshape can not be integers when an axis operation is present.
90
121
-`..` and `:` alone won't use Rewrap.jl, as defining such methods would be type piracy. In these cases, `Keep(..)` and `Merge(..)` should be used instead.
91
122
92
123
## Installation
@@ -98,4 +129,4 @@ Pkg.add("Rewrap")
98
129
99
130
## Contributing
100
131
101
-
At the moment, Rewrap explicitly defines optimizations in big codegen monoliths for generated function specializations, making the source code hard to parse. Ideally it would use a more modular approach. If you have any ideas or suggestions, please feel free to open an issue or a pull request.
132
+
Rewrap uses generated functions with compile-time type analysis to produce specialized code for each reshape pattern. We welcome ideas for making the implementation more modular — please feel free to open an issue or pull request.
0 commit comments