Skip to content

Commit 1fa43da

Browse files
committed
* fixed AList.sub implementation problem
* added better random AList.sub test
1 parent 0d4a2da commit 1fa43da

5 files changed

Lines changed: 308 additions & 143 deletions

File tree

src/Demo/Scratch/AListSub.fs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
module AListSub
2+
3+
open System.Collections.Generic
4+
open FSharp.Data.Adaptive
5+
open FSharp.Data.Traceable
6+
7+
let run() =
8+
let input = clist ["a"; "b"; "c"; "d"; "e"]
9+
10+
11+
let range =
12+
input
13+
|> AList.sortDescending
14+
|> AList.sub 1 3
15+
16+
let reader = range.GetReader()
17+
18+
let check() =
19+
20+
let rec skip (n : int) (l : list<'a>) =
21+
if n <= 0 then l
22+
else
23+
match l with
24+
| [] -> []
25+
| _ :: r -> skip (n - 1) r
26+
27+
28+
reader.GetChanges AdaptiveToken.Top |> ignore
29+
let real = reader.State |> IndexList.toList
30+
let test = input.Value |> IndexList.toList |> List.sortDescending |> skip 1 |> List.truncate 3
31+
32+
if real <> test then
33+
failwithf "bad: %0A vs %0A" real test
34+
else
35+
printfn "OK: %0A" test
36+
check()
37+
38+
transact (fun () ->
39+
input.Prepend "x" |> ignore
40+
input.Prepend "y" |> ignore
41+
input.Prepend "z" |> ignore
42+
input.Prepend "w" |> ignore
43+
input.Prepend "r" |> ignore
44+
)
45+
check()
46+
47+
transact (fun () ->
48+
input.Clear()
49+
)
50+
check()
51+
52+
transact (fun () ->
53+
input.UpdateTo ["hans"; "sepp"; "hugo"; "franz"] |> ignore
54+
)
55+
check()
56+
57+
transact (fun () ->
58+
input.Append "zitha" |> ignore
59+
)
60+
check()
61+
62+
transact (fun () ->
63+
input.RemoveAt 0 |> ignore
64+
input.RemoveAt 0 |> ignore
65+
input.RemoveAt 0 |> ignore
66+
input.RemoveAt (input.Count - 1) |> ignore
67+
)
68+
check()
69+
70+
transact (fun () ->
71+
input.Clear()
72+
)
73+
check()
74+
75+
let rand = System.Random()
76+
77+
for i in 1 .. 10000 do
78+
transact (fun () ->
79+
let values =
80+
List.init (rand.Next 5) (fun _ -> rand.Next() |> string)
81+
82+
match rand.Next 3 with
83+
| 0 when not (List.isEmpty values) ->
84+
match rand.Next 3 with
85+
| 0 ->
86+
printf "append "
87+
for v in values do input.Append v |> ignore
88+
| 1 ->
89+
printf "prepend "
90+
for v in values do input.Prepend v |> ignore
91+
| _ ->
92+
printf "insert "
93+
for v in values do input.InsertAt (rand.Next (input.Count + 1), v) |> ignore
94+
| 1 when input.Count > 0 ->
95+
printf "remove "
96+
let c = rand.Next(input.Count) + 1
97+
for i in 1 .. c do
98+
input.RemoveAt (rand.Next input.Count) |> ignore
99+
| _ ->
100+
printf "update "
101+
input.UpdateTo values |> ignore
102+
)
103+
check()
104+
105+
106+
()

src/Demo/Scratch/Program.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ open System.Collections.Generic
33
open FSharp.Data.Adaptive
44
open FSharp.Data.Traceable
55

6-
ABag.run()
6+
//ABag.run()
77
//Observable.run()
8-
//LookupAll.example()
8+
//LookupAll.example()
9+
AListSub.run()

src/Demo/Scratch/Scratch.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<Compile Include="Observable.fs" />
1717
<Compile Include="LookupAll.fs" />
1818
<Compile Include="ABag.fs" />
19+
<Compile Include="AListSub.fs" />
1920
<Compile Include="Program.fs" />
2021
</ItemGroup>
2122
<ItemGroup>

src/FSharp.Data.Adaptive/AdaptiveIndexList/AdaptiveIndexList.fs

Lines changed: 99 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,162 +1202,120 @@ module internal AdaptiveIndexListImplementation =
12021202
let mutable minIndex = Index.zero
12031203
let mutable maxIndex = Index.zero
12041204

1205-
override x.Compute(token) =
1206-
let ops = reader.GetChanges token
1205+
override x.Compute(token : AdaptiveToken) =
12071206
let offset = offset.GetValue token
12081207
let count = count.GetValue token
12091208

1210-
let newMinIndex = reader.State.TryGetIndexV offset
1211-
let newMaxIndex = reader.State.TryGetIndexV (offset + count - 1)
1212-
match newMinIndex with
1213-
| ValueSome newMinIndex ->
1214-
let newMaxIndex =
1215-
match newMaxIndex with
1216-
| ValueSome i -> i
1217-
| ValueNone -> reader.State.MaxIndex
1218-
1219-
if MapExt.isEmpty state then
1220-
let resultRange = reader.State.Content.[newMinIndex .. newMaxIndex]
1221-
let delta = resultRange |> MapExt.map (fun _ v -> Set v) |> IndexListDelta
1222-
state <- resultRange
1223-
minIndex <- newMinIndex
1224-
maxIndex <- newMaxIndex
1225-
delta
1226-
elif newMinIndex > maxIndex || newMaxIndex < minIndex then
1227-
let resultRange = reader.State.Content.[newMinIndex .. newMaxIndex]
1228-
let delta =
1229-
IndexListDelta (
1209+
let ops = reader.GetChanges token
1210+
1211+
let newMin =
1212+
match reader.State.TryGetIndexV offset with
1213+
| ValueSome i -> i
1214+
| _ -> Index.after reader.State.MaxIndex
1215+
1216+
let newMax =
1217+
match reader.State.TryGetIndexV (offset + count - 1) with
1218+
| ValueSome i -> i
1219+
| ValueNone -> reader.State.MaxIndex
1220+
1221+
if not reader.State.IsEmpty && newMax >= newMin then
1222+
// new state non-empty
1223+
if newMin > maxIndex || newMax < minIndex then
1224+
// new state completely disjoint from old
1225+
let newState = reader.State.[newMin .. newMax]
1226+
if MapExt.isEmpty state then
1227+
// old state is empty
1228+
state <- newState.Content
1229+
minIndex <- newMin
1230+
maxIndex <- newMax
1231+
newState.Content |> MapExt.map (fun _ v -> Set v) |> IndexListDelta
1232+
else
1233+
// old state non-empty
1234+
let delta =
12301235
MapExt.union
1231-
(state |> MapExt.map (fun _ _ -> Remove))
1232-
(resultRange |> MapExt.map (fun _ v -> Set v))
1233-
)
1234-
state <- resultRange
1235-
minIndex <- newMinIndex
1236-
maxIndex <- newMaxIndex
1237-
delta
1238-
1236+
(state |> MapExt.map (fun _ _ -> Remove))
1237+
(newState.Content |> MapExt.map (fun _ v -> Set v))
1238+
state <- newState.Content
1239+
minIndex <- newMin
1240+
maxIndex <- newMax
1241+
IndexListDelta delta
12391242
else
1240-
let mutable delta = ops.Content.Slice(minIndex, maxIndex)
1241-
let l, d = IndexList.applyDelta (IndexList(minIndex, maxIndex, state)) (IndexListDelta delta)
1242-
state <- l.Content
1243-
delta <- d.Content
1244-
minIndex <- l.MinIndex
1245-
maxIndex <- l.MaxIndex
1246-
1247-
if minIndex > newMinIndex then
1248-
let newBefore = reader.State.Content.Slice(newMinIndex, true, minIndex, false)
1249-
delta <- MapExt.union (newBefore |> MapExt.map (fun _ v -> Set v)) delta
1250-
state <- MapExt.union newBefore state
1251-
minIndex <- newMinIndex
1252-
elif newMinIndex > minIndex then
1253-
let (dropFront, s, newState) = state.Split newMinIndex
1254-
let newState =
1243+
// old and new ranges overlap
1244+
let sharedMin = max newMin minIndex
1245+
let sharedMax = min newMax maxIndex
1246+
1247+
let ns, nd =
1248+
let innerDelta = ops.Content.[sharedMin .. sharedMax]
1249+
IndexList.applyDelta (IndexList(minIndex, maxIndex, state)) (IndexListDelta innerDelta)
1250+
1251+
state <- ns.Content
1252+
let mutable delta = nd.Content
1253+
1254+
if minIndex > newMin then
1255+
let l = reader.State.Content.Slice(newMin, true, minIndex, false)
1256+
delta <- delta.ApplyDelta(l, fun k o v -> ValueSome (Set v))
1257+
state <- MapExt.union l state
1258+
minIndex <- newMin
1259+
elif minIndex < newMin then
1260+
let l, s, rest = state.Split(newMin)
1261+
state <-
12551262
match s with
1256-
| Some v -> MapExt.add newMinIndex v newState
1257-
| None -> newState
1258-
1259-
delta <- MapExt.union (dropFront |> MapExt.map (fun _ _ -> Remove)) delta
1260-
state <- newState
1261-
minIndex <- newMinIndex
1262-
1263-
1264-
if maxIndex > newMaxIndex then
1265-
let (newState, s, dropBack) = state.Split newMaxIndex
1266-
let newState =
1263+
| Some v -> MapExt.add newMin v rest
1264+
| None -> rest
1265+
delta <- delta.ApplyDelta(l, fun k o v -> ValueSome Remove)
1266+
minIndex <- newMin
1267+
1268+
// while minIndex > newMin do
1269+
// let (l, _, _) = MapExt.neighbours minIndex reader.State.Content
1270+
// let (li, lv) = Option.get l // must exist
1271+
// delta <- delta |> MapExt.add li (Set lv)
1272+
// state <- MapExt.add li lv state
1273+
// minIndex <- li
1274+
1275+
// while minIndex < newMin do
1276+
// delta <- delta |> MapExt.add minIndex Remove
1277+
// state <- state |> MapExt.remove minIndex
1278+
// minIndex <- MapExt.minKey state
1279+
1280+
if maxIndex < newMax then
1281+
let r = reader.State.Content.Slice(maxIndex, false, newMax, true)
1282+
delta <- delta.ApplyDelta(r, fun k o v -> ValueSome (Set v))
1283+
state <- MapExt.union state r
1284+
maxIndex <- newMax
1285+
elif maxIndex > newMax then
1286+
let rest, s, r = state.Split newMax
1287+
state <-
12671288
match s with
1268-
| Some v -> MapExt.add newMaxIndex v newState
1269-
| None -> newState
1289+
| Some v -> MapExt.add newMax v rest
1290+
| None -> rest
1291+
delta <- delta.ApplyDelta(r, fun k o v -> ValueSome Remove)
1292+
maxIndex <- newMax
12701293

1271-
delta <- MapExt.union (dropBack |> MapExt.map (fun _ _ -> Remove)) delta
1272-
state <- newState
1273-
maxIndex <- newMaxIndex
1274-
elif newMaxIndex > maxIndex then
1275-
let newAfter = reader.State.Content.Slice(maxIndex, false, newMaxIndex, true)
1276-
delta <- MapExt.union (newAfter |> MapExt.map (fun _ v -> Set v)) delta
1277-
state <- MapExt.union newAfter state
1278-
maxIndex <- newMaxIndex
12791294

1280-
IndexListDelta delta
1281-
| ValueNone ->
1282-
if not (MapExt.isEmpty state) then
1283-
let delta = state |> MapExt.map (fun _ _ -> Remove) |> IndexListDelta.ofMap
1284-
state <- MapExt.empty
1285-
minIndex <- Index.zero
1286-
maxIndex <- Index.zero
1287-
delta
1288-
else
1289-
IndexListDelta.empty
1295+
// while maxIndex < newMax do
1296+
// let (_,_,r) = MapExt.neighbours maxIndex reader.State.Content
1297+
// let (ri, rv) = Option.get r // must exist
1298+
// delta <- delta |> MapExt.add ri (Set rv)
1299+
// state <- MapExt.add ri rv state
1300+
// maxIndex <- ri
12901301

1291-
[<Sealed>]
1292-
type SkipReader<'a>(input : alist<'a>, offset : aval<int>) =
1293-
inherit AbstractReader<IndexListDelta<'a>>(IndexListDelta.empty)
1302+
// while maxIndex > newMax do
1303+
// delta <- delta |> MapExt.add maxIndex Remove
1304+
// state <- state |> MapExt.remove maxIndex
1305+
// maxIndex <- MapExt.maxKey state
12941306

1295-
let reader = input.GetReader()
1296-
let mutable state = MapExt.empty
1297-
let mutable minIndex = Index.zero
1298-
let mutable currentMaxIndex = Index.zero
1299-
1300-
override x.Compute(token) =
1301-
let ops = reader.GetChanges token
1302-
let offset = offset.GetValue token
1303-
1304-
let newMinIndex = reader.State.TryGetIndexV offset
1305-
match newMinIndex with
1306-
| ValueSome newMinIndex ->
1307-
if MapExt.isEmpty state then
1308-
let resultRange = reader.State.Content.[newMinIndex .. ]
1309-
let delta = resultRange |> MapExt.map (fun _ v -> Set v) |> IndexListDelta
1310-
state <- resultRange
1311-
minIndex <- newMinIndex
1312-
currentMaxIndex <- reader.State.MaxIndex
1313-
delta
1314-
elif newMinIndex > currentMaxIndex then
1315-
let resultRange = reader.State.Content.[newMinIndex .. ]
1316-
let delta =
1317-
IndexListDelta (
1318-
MapExt.union
1319-
(state |> MapExt.map (fun _ _ -> Remove))
1320-
(resultRange |> MapExt.map (fun _ v -> Set v))
1321-
)
1322-
state <- resultRange
1323-
minIndex <- newMinIndex
1324-
currentMaxIndex <- reader.State.MaxIndex
1325-
delta
1326-
1327-
else
1328-
let mutable delta = ops.Content.WithMin minIndex
1329-
let l, d = IndexList.applyDelta (IndexList(minIndex, currentMaxIndex, state)) (IndexListDelta delta)
1330-
state <- l.Content
1331-
delta <- d.Content
1332-
minIndex <- l.MinIndex
1333-
currentMaxIndex <- l.MaxIndex
1334-
1335-
if minIndex > newMinIndex then
1336-
let newBefore = reader.State.Content.Slice(newMinIndex, true, minIndex, false)
1337-
delta <- MapExt.union (newBefore |> MapExt.map (fun _ v -> Set v)) delta
1338-
state <- MapExt.union newBefore state
1339-
minIndex <- newMinIndex
1340-
elif newMinIndex > minIndex then
1341-
let (dropFront, s, newState) = state.Split newMinIndex
1342-
let newState =
1343-
match s with
1344-
| Some v -> MapExt.add newMinIndex v newState
1345-
| None -> newState
1346-
1347-
delta <- MapExt.union (dropFront |> MapExt.map (fun _ _ -> Remove)) delta
1348-
state <- newState
1349-
minIndex <- newMinIndex
13501307

13511308
IndexListDelta delta
1352-
| ValueNone ->
1353-
if not (MapExt.isEmpty state) then
1354-
let delta = state |> MapExt.map (fun _ _ -> Remove) |> IndexListDelta.ofMap
1309+
else
1310+
// new state is empty
1311+
if MapExt.isEmpty state then
1312+
IndexListDelta.empty
1313+
else
1314+
let delta = state |> MapExt.map (fun _ _ -> Remove) |> IndexListDelta
13551315
state <- MapExt.empty
13561316
minIndex <- Index.zero
1357-
currentMaxIndex <- Index.zero
1317+
maxIndex <- Index.zero
13581318
delta
1359-
else
1360-
IndexListDelta.empty
13611319

13621320
/// Gets the current content of the alist as IndexList.
13631321
let inline force (list : alist<'T>) =
@@ -1709,7 +1667,7 @@ module AList =
17091667
if count.IsConstant && list.IsConstant then
17101668
constant (fun () -> IndexList.skip (AVal.force count) (force list))
17111669
else
1712-
ofReader (fun () -> SkipReader(list, count))
1670+
ofReader (fun () -> SubReader(list, count, AVal.constant Int32.MaxValue))
17131671

17141672
let skip (count: int) (list: alist<'T>) =
17151673
skipA (AVal.constant count) list

0 commit comments

Comments
 (0)