1- struct CartesianProduct{A,B}
1+ struct CartesianPair{A,B}
2+ a:: A
3+ b:: B
4+ end
5+ arguments (a:: CartesianPair ) = (a. a, a. b)
6+ arguments (a:: CartesianPair , n:: Int ) = arguments (a)[n]
7+
8+ arg1 (a:: CartesianPair ) = a. a
9+ arg2 (a:: CartesianPair ) = a. b
10+
11+ × (a, b) = CartesianPair (a, b)
12+
13+ function Base. show (io:: IO , a:: CartesianPair )
14+ print (io, a. a, " × " , a. b)
15+ return nothing
16+ end
17+
18+ struct CartesianProduct{TA,TB,A<: AbstractVector{TA} ,B<: AbstractVector{TB} } < :
19+ AbstractVector{CartesianPair{TA,TB}}
220 a:: A
321 b:: B
422end
@@ -13,15 +31,19 @@ function Base.show(io::IO, a::CartesianProduct)
1331 return nothing
1432end
1533
16- × (a, b) = CartesianProduct (a, b)
34+ × (a:: AbstractVector , b:: AbstractVector ) = CartesianProduct (a, b)
1735Base. length (a:: CartesianProduct ) = length (a. a) * length (a. b)
18- Base. getindex (a:: CartesianProduct , i :: CartesianProduct ) = a . a[i . a] × a . b[i . b]
36+ Base. size (a:: CartesianProduct ) = ( length (a),)
1937
20- function Base. iterate (a:: CartesianProduct , state... )
21- x = iterate (Iterators. product (a. a, a. b), state... )
22- isnothing (x) && return x
23- next, new_state = x
24- return × (next... ), new_state
38+ function Base. getindex (a:: CartesianProduct , i:: CartesianProduct )
39+ return arg1 (a)[arg1 (i)] × arg2 (a)[arg2 (i)]
40+ end
41+ function Base. getindex (a:: CartesianProduct , i:: CartesianPair )
42+ return arg1 (a)[arg1 (i)] × arg2 (a)[arg2 (i)]
43+ end
44+ function Base. getindex (a:: CartesianProduct , i:: Int )
45+ I = Tuple (CartesianIndices ((length (arg1 (a)), length (arg2 (a))))[i])
46+ return a[I[1 ] × I[2 ]]
2547end
2648
2749struct CartesianProductUnitRange{T,P<: CartesianProduct ,R<: AbstractUnitRange{T} } < :
4466function CartesianProductUnitRange (a, b)
4567 return CartesianProductUnitRange (a × b)
4668end
47- to_range (a:: AbstractUnitRange ) = a
48- to_range (i:: Integer ) = Base. OneTo (i)
49- cartesianrange (a, b) = cartesianrange (to_range (a) × to_range (b))
69+ to_product_indices (a:: AbstractUnitRange ) = a
70+ to_product_indices (i:: Integer ) = Base. OneTo (i)
71+ cartesianrange (a, b) = cartesianrange (to_product_indices (a) × to_product_indices (b))
72+ function cartesianrange (p:: CartesianPair )
73+ p′ = to_product_indices (arg1 (p)) × to_product_indices (arg2 (p))
74+ return cartesianrange (p′)
75+ end
5076function cartesianrange (p:: CartesianProduct )
51- p′ = to_range (p . a) × to_range (p . b )
77+ p′ = to_product_indices ( arg1 (p)) × to_product_indices ( arg2 (p) )
5278 return cartesianrange (p′, Base. OneTo (length (p′)))
5379end
80+ function cartesianrange (p:: CartesianPair , range:: AbstractUnitRange )
81+ p′ = to_product_indices (arg1 (p)) × to_product_indices (arg2 (p))
82+ return cartesianrange (p′, range)
83+ end
5484function cartesianrange (p:: CartesianProduct , range:: AbstractUnitRange )
55- p′ = to_range (p . a) × to_range (p . b )
85+ p′ = to_product_indices ( arg1 (p)) × to_product_indices ( arg2 (p) )
5686 return CartesianProductUnitRange (p′, range)
5787end
5888
5989function Base. axes (r:: CartesianProductUnitRange )
60- return (CartesianProductUnitRange (r. product, only (axes (r. range))),)
90+ return (CartesianProductUnitRange (cartesianproduct (r), only (axes (unproduct (r)))),)
91+ end
92+
93+ function Base. checkindex (:: Type{Bool} , inds:: CartesianProductUnitRange , i:: CartesianPair )
94+ return checkindex (Bool, arg1 (inds), arg1 (i)) && checkindex (Bool, arg2 (inds), arg2 (i))
6195end
6296
6397using Base. Broadcast: DefaultArrayStyle
@@ -66,12 +100,12 @@ for f in (:+, :-)
66100 function Broadcast. broadcasted (
67101 :: DefaultArrayStyle{1} , :: typeof ($ f), r:: CartesianProductUnitRange , x:: Integer
68102 )
69- return CartesianProductUnitRange (r . product , $ f .(r . range , x))
103+ return CartesianProductUnitRange (cartesianproduct (r) , $ f .(unproduct (r) , x))
70104 end
71105 function Broadcast. broadcasted (
72106 :: DefaultArrayStyle{1} , :: typeof ($ f), x:: Integer , r:: CartesianProductUnitRange
73107 )
74- return CartesianProductUnitRange (r . product , $ f .(x, r . range ))
108+ return CartesianProductUnitRange (cartesianproduct (r) , $ f .(x, unproduct (r) ))
75109 end
76110 end
77111end
0 commit comments