@@ -1137,6 +1137,56 @@ Return the value of the global inexact flag.
1137
1137
"""
1138
1138
inexact () = return inexact_flag
1139
1139
1140
+
1141
+ """
1142
+ eligible_step(start::Floatmu{szE,szf}, stop::Floatmu{szE,szf}) where {szE,szf}
1143
+ eligible_step(::Type{Floatmu{szE,szf}}, start::Float64, stop::Float64) where {szE,szf}
1144
+
1145
+ Return the smallest `Floatmu{szE,szf}` eligible step allowed to iterate through the domain
1146
+ `[start,stop]`.
1147
+
1148
+ # Examples
1149
+
1150
+ ```jldoctest
1151
+ julia> eligible_step(Floatmu{2,2}(-0.5),Floatmu{2,2}(2.5))
1152
+ 0.5
1153
+ ```
1154
+ """
1155
+ function eligible_step end
1156
+
1157
+ function eligible_step (start:: Floatmu{szE,szf} , stop:: Floatmu{szE,szf} ) where {szE,szf}
1158
+ maxi = max (abs (start),abs (stop))
1159
+ return maxi - prevfloat (maxi) # The difference of two consecutive floats is always representable
1160
+ end
1161
+
1162
+ function eligible_step (:: Type{Floatmu{szE,szf}} , start:: Float64 , stop:: Float64 ) where {szE,szf}
1163
+ return eligible_step (Floatmu {szE,szf} (start),Floatmu {szE,szf} (stop))
1164
+ end
1165
+
1166
+
1167
+ """
1168
+ check_eligibility_step(start::Floatmu{szE,szf}, stop::Floatmu{szE,szf},
1169
+ step::Floatmu{szE,szf}) where {szE,szf}
1170
+
1171
+ Check whether the step `step` can be reliability used for the domain [start, stop].
1172
+ Throw an ArgumentError exception in the negative.
1173
+ """
1174
+ function check_eligibility_step (start:: Floatmu{szE,szf} , stop:: Floatmu{szE,szf} ,
1175
+ step:: Floatmu{szE,szf} ) where {szE,szf}
1176
+ if isnan (start) || isnan (stop) || isinf (start) || isinf (stop)
1177
+ throw (ArgumentError (" bounds of the iteration cannot be NaNs or infinities" ))
1178
+ end
1179
+ if step == 0.0
1180
+ throw (ArgumentError (" the step cannot be zero" ))
1181
+ end
1182
+ # Finding the largest distance between two floats in the domain
1183
+ eligible = eligible_step (start,stop)
1184
+ if step < eligible
1185
+ throw (ArgumentError (" the step cannot be reliably used. Use a step greater or equal to $eligible " ))
1186
+ end
1187
+ end
1188
+
1189
+
1140
1190
"""
1141
1191
FloatmuIterator(start::Floatmu{szE,szf},stop::Floatmu{szE,szf},
1142
1192
step::Floatmu{szE,szf}) where {szE,szf}
@@ -1155,8 +1205,26 @@ can be initialized with two `Floatmu{szE,szf}` or with two `Float64`.
1155
1205
One may iterate from one float to the next (the default) or choose some step.
1156
1206
The step may be a number of floats or an amount to add.
1157
1207
1158
- An ArgumentError is raised if the bounds are NaNs or if the step chosen is zero
1159
- (or rounds to zero when converted to a `Floatmu{szE,szf}`).
1208
+ An ArgumentError is raised if the bounds are NaNs, if the step chosen is zero
1209
+ (or rounds to zero when converted to a `Floatmu{szE,szf}`), or if the
1210
+ step is a value smaller than the largest distance between two consecutive
1211
+ floats in `[last, stop]` (use [`eligible_step`](@ref) to know the smallest
1212
+ value allowed).
1213
+
1214
+ When the step is an amount to add, the bounds cannot be infinities.
1215
+
1216
+ When the step is a number of floats, infinities are allowed for the bounds and are always
1217
+ part of the resulting range:
1218
+ ```jldoctest
1219
+ julia> collect(FloatmuIterator(Floatmu{2,2},-Inf,Inf,5))
1220
+ 6-element Vector{Floatmu{2, 2}}:
1221
+ -Infμ{2, 2}
1222
+ -1.75
1223
+ -0.5
1224
+ 0.75
1225
+ 2.0
1226
+ Infμ{2, 2}
1227
+ ```
1160
1228
1161
1229
# Examples
1162
1230
```jldoctest
@@ -1174,31 +1242,35 @@ julia> L2=[x for x = FloatmuIterator(Floatmu{2, 2}, 0.0, 1.0, 2)]
1174
1242
1.0
1175
1243
```
1176
1244
"""
1177
- struct FloatmuIterator{szE,szf}
1245
+ mutable struct FloatmuIterator{szE,szf}
1178
1246
first:: Floatmu{szE,szf}
1179
1247
last:: Floatmu{szE,szf}
1180
1248
step:: Union{Int,Floatmu{szE,szf}}
1249
+ stopit:: Bool
1181
1250
1182
1251
function FloatmuIterator (start:: Floatmu{szE,szf} ,stop:: Floatmu{szE,szf} ,
1183
1252
step:: Floatmu{szE,szf} ) where {szE,szf}
1184
- if isnan (start) || isnan (stop)
1185
- throw (ArgumentError (" bounds of the iteration cannot be NaNs" ))
1186
- end
1187
- if step == 0.0
1188
- throw (ArgumentError (" the step shall be non-null" ))
1189
- end
1190
- return new {szE,szf} (start,stop,step)
1253
+ check_eligibility_step (start,stop,step);
1254
+
1255
+ return new {szE,szf} (start,stop,step,false )
1191
1256
end
1257
+
1192
1258
function FloatmuIterator (start:: Floatmu{szE,szf} ,stop:: Floatmu{szE,szf} ,
1193
1259
step:: Float64 ) where {szE,szf}
1194
- if isnan (start) || isnan (stop)
1195
- throw (ArgumentError (" bounds of the iteration cannot be NaNs" ))
1196
- end
1197
- if step == 0.0
1198
- throw (ArgumentError (" the step shall be non-null" ))
1199
- end
1200
- return new {szE,szf} (start,stop,Floatmu {szE,szf} (step))
1260
+ mustep = Floatmu {szE,szf} (step)
1261
+ check_eligibility_step (start,stop,mustep)
1262
+ return new {szE,szf} (start,stop,mustep,false )
1263
+ end
1264
+
1265
+ function FloatmuIterator (:: Type{Floatmu{szE,szf}} ,start:: Float64 ,stop:: Float64 ,
1266
+ step:: Float64 ) where {szE,szf}
1267
+ mustart = Floatmu {szE,szf} (float64_to_uint32mu (start, szE, szf),nothing )
1268
+ mustop = Floatmu {szE,szf} (float64_to_uint32mu (stop, szE, szf),nothing )
1269
+ mustep = Floatmu {szE,szf} (step)
1270
+ check_eligibility_step (mustart,mustop,mustep)
1271
+ return new {szE,szf} (mustart, mustop, mustep, false )
1201
1272
end
1273
+
1202
1274
function FloatmuIterator (start:: Floatmu{szE,szf} ,stop:: Floatmu{szE,szf} ,
1203
1275
step:: Int = 1 ) where {szE,szf}
1204
1276
if isnan (start) || isnan (stop)
@@ -1207,8 +1279,9 @@ struct FloatmuIterator{szE,szf}
1207
1279
if step == 0
1208
1280
throw (ArgumentError (" the step shall be non-null" ))
1209
1281
end
1210
- return new {szE,szf} (start,stop,step)
1282
+ return new {szE,szf} (start,stop,step, false )
1211
1283
end
1284
+
1212
1285
function FloatmuIterator (:: Type{Floatmu{szE,szf}} ,start:: Float64 ,stop:: Float64 ,
1213
1286
step:: Int = 1 ) where {szE,szf}
1214
1287
if isnan (start) || isnan (stop)
@@ -1218,39 +1291,37 @@ struct FloatmuIterator{szE,szf}
1218
1291
throw (ArgumentError (" the step shall be non-null" ))
1219
1292
end
1220
1293
return new {szE,szf} (Floatmu {szE,szf} (float64_to_uint32mu (start, szE, szf),nothing ),
1221
- Floatmu {szE,szf} (float64_to_uint32mu (stop, szE, szf),nothing ),step)
1222
- end
1223
- function FloatmuIterator (:: Type{Floatmu{szE,szf}} ,start:: Float64 ,stop:: Float64 ,
1224
- step:: Float64 ) where {szE,szf}
1225
- if isnan (start) || isnan (stop)
1226
- throw (ArgumentError (" bounds of the iteration cannot be NaNs" ))
1227
- end
1228
- mustep = Floatmu {szE,szf} (step)
1229
- if mustep == 0.0
1230
- throw (ArgumentError (" the step shall be non-null" ))
1231
- end
1232
- return new {szE,szf} (Floatmu {szE,szf} (float64_to_uint32mu (start, szE, szf),nothing ),
1233
- Floatmu {szE,szf} (float64_to_uint32mu (stop, szE, szf),nothing ),mustep)
1294
+ Floatmu {szE,szf} (float64_to_uint32mu (stop, szE, szf),nothing ),step,false )
1234
1295
end
1235
1296
end
1236
1297
1237
1298
function iterate (iter:: FloatmuIterator{szE,szf} ,state= iter. first) where {szE,szf}
1238
- if state <= iter. last
1299
+ if state <= iter. last && ! iter . stopit
1239
1300
if iter. step isa Int
1240
- return (state, nextfloat (state,iter. step) )
1301
+ nextstate = nextfloat (state,iter. step)
1241
1302
else
1242
- return ( state,state + iter. step)
1303
+ nextstate = state+ iter. step
1243
1304
end
1305
+ iter. stopit = (state == nextstate)
1306
+ return (state,nextstate)
1244
1307
else
1245
1308
return nothing
1246
1309
end
1247
1310
end
1248
1311
1249
1312
function length (iter:: FloatmuIterator{szE,szf} ) where {szE,szf}
1250
1313
if iter. step isa Int
1251
- return ceil (Int,nb_fp_numbers (iter. first,iter. last)/ iter. step)
1314
+ nr = (nb_fp_numbers (iter. first,iter. last)- 1 )/ iter. step
1315
+ nt = trunc (nr)
1316
+ if isinf (iter. last)
1317
+ # If the right bound is an infinity, it will be included in the range even
1318
+ # if the number of steps does not match => add 1 value more in the range.
1319
+ return Int (nt) + (nt != nr ? 2 : 1 )
1320
+ else
1321
+ return 1 + Int (nt)
1322
+ end
1252
1323
else
1253
- return ceil (Int,(Float64 (iter. last)- Float64 (iter. first))/ Float64 (iter. step))
1324
+ return 1 + trunc (Int,(Float64 (iter. last)- Float64 (iter. first))/ Float64 (iter. step))
1254
1325
end
1255
1326
end
1256
1327
0 commit comments