@@ -69,7 +69,7 @@ Base.isempty(d::JuMPContainer) = isempty(_innercontainer(d))
69
69
# 0:K -- range with compile-time starting index
70
70
# S -- general iterable set
71
71
export @gendict
72
- macro gendict (instancename,T,idxpairs, idxsets... )
72
+ macro gendict (instancename,T,idxsets... )
73
73
N = length (idxsets)
74
74
allranges = all (s -> (isexpr (s,:(:)) && length (s. args) == 2 ), idxsets)
75
75
truearray = allranges && all (s -> s. args[1 ] == 1 , idxsets)
@@ -165,12 +165,92 @@ macro gendict(instancename,T,idxpairs,idxsets...)
165
165
=#
166
166
else
167
167
# JuMPDict
168
+ escidxs = [esc (idxset) for idxset in idxsets]
168
169
return :(
169
- $ (esc (instancename)) = JuMPDict {$T,$N} ()
170
+ $ (esc (instancename)) = (if is_unit_ranges ($ (escidxs... ))
171
+ runtime_gendict ($ T, $ (escidxs... ))
172
+ else
173
+ JuMPDict {$T,$N} ()
174
+ end )
170
175
)
171
176
end
172
177
end
173
178
179
+ function runtime_gendict (T,idxsets... )
180
+ N = length (idxsets)
181
+ allranges = all (s -> (typeof (s) <: Range ), idxsets)
182
+ truearray = allranges && all (s -> (first (s) == 1 ), idxsets)
183
+ if allranges
184
+ if truearray
185
+ return Array (T, [last (rng) for rng in idxsets]. .. )
186
+ else
187
+ typename = symbol (string (" JuMPArray" ,gensym ()))
188
+ dictnames = Array (Symbol,N)
189
+ # JuMPArray
190
+ offset = Array (Int,N)
191
+ for i in 1 : N
192
+ offset[i] = 1 - first (idxsets[i])
193
+ end
194
+ typecode = quote
195
+ type $ (typename){T} <: JuMPArray{T,$N}
196
+ innerArray:: Array{T,$N}
197
+ meta:: Dict{Symbol,Any}
198
+ end
199
+ end
200
+ constrlhs = :($ (typename)(innerArray:: Array ))
201
+ constrrhs = :($ (typename)(innerArray, Dict {Symbol,Any} ()))
202
+ getidxlhs = :(Base. getindex (d:: $ (typename)))
203
+ setidxlhs = :(Base. setindex! (d:: $ (typename),val))
204
+ getidxrhs = :(Base. getindex (d. innerArray))
205
+ setidxrhs = :(Base. setindex! (d. innerArray,val))
206
+ maplhs = :(Base. map (f:: Function ,d:: $ (typename)))
207
+ maprhs = :($ (typename)(map (f,d. innerArray),d. meta))
208
+ wraplhs = :(JuMPContainer_from (d:: $ (typename),inner)) # helper function that wraps array into JuMPArray of similar type
209
+ wraprhs = :($ (typename)(inner))
210
+
211
+ nextidxlhs = :(_next_index (d:: $ (typename), k))
212
+ # build up exprs for _next_index
213
+ lidxsets = [ii => symbol (string (" locidxset" ,ii)) for ii in 1 : N]
214
+ nextidxrhs = quote
215
+ subidx = ind2sub (size (d), k)
216
+ $ (Expr (:tuple , [:(subidx[$ ii] - $ (offset[ii])) for ii in 1 : N]. .. ))
217
+ end
218
+ for i in 1 : N
219
+ varname = symbol (string (" x" ,i))
220
+
221
+ push! (getidxlhs. args,:($ varname))
222
+ push! (setidxlhs. args,:($ varname))
223
+
224
+ push! (getidxrhs. args,:(isa ($ varname, Int) ? $ varname+ $ (offset[i]) : $ varname ))
225
+ push! (setidxrhs. args,:($ varname+ $ (offset[i])))
226
+
227
+ end
228
+
229
+ badgetidxlhs = :(Base. getindex (d:: $ (typename),wrong... ))
230
+ badgetidxrhs = :(data = printdata (d);
231
+ error (" Wrong number of indices for " ,data. name, " , expected " ,length (data. indexsets)))
232
+
233
+ funcs = quote
234
+ $ constrlhs = $ constrrhs
235
+ $ getidxlhs = $ getidxrhs
236
+ $ setidxlhs = $ setidxrhs
237
+ $ maplhs = $ maprhs
238
+ $ badgetidxlhs = $ badgetidxrhs
239
+ $ wraplhs = $ wraprhs
240
+ $ nextidxlhs = $ nextidxrhs
241
+ end
242
+
243
+ eval (Expr (:toplevel , typecode))
244
+ eval (Expr (:toplevel , funcs))
245
+
246
+ return eval (:($ (typename)(Array ($ T, [length (idxset) for idxset in $ idxsets]. .. ))))
247
+ end
248
+ else
249
+ error (" Should not reach this point" )
250
+ end
251
+ end
252
+
253
+ @generated is_unit_ranges (idxsets... ) = :($ (all (s -> s <: UnitRange{Int} , idxsets)))
174
254
pushmeta! (x:: JuMPContainer , sym:: Symbol , val) = (x. meta[sym] = val)
175
255
getmeta (x:: JuMPContainer , sym:: Symbol ) = x. meta[sym]
176
256
0 commit comments