-
Notifications
You must be signed in to change notification settings - Fork 0
/
RarrModule.fs
2763 lines (2425 loc) · 145 KB
/
RarrModule.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
namespace FsEx
open System
open System.Collections.Generic
open NiceString
//open Microsoft.FSharp.Core
//open Microsoft.FSharp.Collections
//open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
/// A module for functions on Rarr.
/// A Rarr is a thin wrapper over System.Collections.Generic.List<'T> but with nicer error messages and additional methods.
/// This module has all functions from the FSharp.Core.Array module implemented for Rarr. And more.
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] //need this so doesn't hide Rarr class in C# assemblies (should consider for other extension modules as well)
[<RequireQualifiedAccess>]
module Rarr =
//---------------------------------------------------
// extensions added only in FsEx: (not in FSharp.Core Array module)
//----------------------------------------------------
/// Access the underlying Collections.Generic.List<'T> of the Rarr directly.
/// This is NOT even a shallow copy, mutating it will also change the input Instance of FsEx.Rarr.
let inline getInternalList (rarr: Rarr<'T>) =
rarr.InternalList
/// Gets an item in the Rarr by index.
/// Allows for negative index too ( -1 is last item, like Python)
/// (from the release of F# 5 on a negative index can also be done with '^' prefix. E.g. ^0 for the last item)
let inline getNeg index (rarr: Rarr<'T>)=
let len = rarr.Count
let ii = if index < 0 then len + index else index
if ii<0 || ii >= len then ArgumentException.RaiseBase "FsEx.Rarr.GetNeg: Failed to get index %d from Rarr of %d items: %s" index rarr.Count rarr.ToNiceStringLong
rarr.InternalList.[ii] // access List directly to not check index twice
/// Sets an item in the Rarr by index.
/// Allows for negative index too ( -1 is last item, like Python)
/// (from the release of F# 5 on a negative index can also be done with '^' prefix. E.g. ^0 for the last item)
let inline setNeg index value (rarr: Rarr<'T>)=
let len = rarr.Count
let ii = if index < 0 then len + index else index
if ii<0 || ii >= len then ArgumentException.RaiseBase "FsEx.Rarr.SetNeg: Failed to set index %d to %s from Rarr of %d items: %s" index (toNiceString value) rarr.Count rarr.ToNiceStringLong
rarr.InternalList.[ii] <- value // access List directly to not check index twice
/// Any index will return a value.
/// Rarr is treated as an endless loop in positive and negative direction
let inline getLooped index (rarr: Rarr<'T>)=
let len = rarr.Count
if len=0 then ArgumentException.RaiseBase "FsEx.Rarr.GetLooped: Failed to get index %d from Rarr of 0 items" index
let t = index % len
let ii = if t >= 0 then t else t + len
rarr.InternalList.[ii] // access List directly to not check index twice
/// Any index will set a value.
/// Rarr is treated as an endless loop in positive and negative direction
let inline setLooped index value (rarr: Rarr<'T>) =
let len = rarr.Count
if len=0 then ArgumentException.RaiseBase "FsEx.Rarr.SetLooped: Failed to Set index %d to %s in Rarr of 0 items" index (toNiceString value)
let t = index % len
let ii = if t >= 0 then t else t + len
rarr.InternalList.[ii] <- value // access List directly to not check index twice
/// Get and remove last item from Rarr
let inline pop (rarr: Rarr<'T>) =
if rarr.Count=0 then ArgumentException.RaiseBase "Failed to pop from %s" rarr.ToNiceStringLong
let i = rarr.Count - 1
let v = rarr.InternalList.[i] // access List directly to not check index twice
rarr.InternalList.RemoveAt(i)
v
/// Gets the second last item in the Rarr.
/// Same as this.[this.Count - 2]
let inline secondLast (rarr: Rarr<'T>)=
if rarr.Count < 2 then IndexOutOfRangeException.Raise "FsEx.Rarr.secondLast: Failed to get second last item of %s" rarr.ToNiceStringLong
rarr.InternalList.[rarr.Count - 2]
/// Gets the third last item in the Rarr.
/// Same as this.[this.Count - 3]
let inline thirdLast (rarr: Rarr<'T>)=
if rarr.Count < 3 then IndexOutOfRangeException.Raise "FsEx.Rarr.thirdLast: Failed to get third last item of %s" rarr.ToNiceStringLong
rarr.InternalList.[rarr.Count - 3]
/// Gets the first item in the Rarr.
/// Same as this.[0]
let inline first (rarr: Rarr<'T>)=
if rarr.Count = 0 then IndexOutOfRangeException.Raise "FsEx.Rarr.first: Failed to get first item of %s" rarr.ToNiceStringLong
rarr.InternalList.[0]
/// Gets the the only item in the FsEx.Rarr.
/// Fails if the Rarr does not have exactly one element.
let inline firstAndOnly (rarr: Rarr<'T>) =
if rarr.Count = 0 then IndexOutOfRangeException.Raise "FsEx.Rarr.firstOnly: Failed to get first item of empty Rarr<%s>" (typeof<'T>).FullName
if rarr.Count > 1 then IndexOutOfRangeException.Raise "FsEx.Rarr.firstOnly: Rarr<%s> is expected to have only one item but has %d Rarr: %s" (typeof<'T>).FullName rarr.Count rarr.ToNiceStringLong
rarr.[0]
/// Gets the second item in the Rarr.
/// Same as this.[1]
let inline second (rarr: Rarr<'T>)=
if rarr.Count < 2 then IndexOutOfRangeException.Raise "Rarr.second: Failed to get second item of %s" rarr.ToNiceStringLong
rarr.InternalList.[1]
/// Gets the third item in the Rarr.
/// Same as this.[2]
let inline third (rarr: Rarr<'T>)=
if rarr.Count < 3 then IndexOutOfRangeException.Raise "FsEx.Rarr.third: Failed to get third item of %s" rarr.ToNiceStringLong
rarr.InternalList.[2]
/// Slice the Rarr given start and end index.
/// Allows for negative indices too. ( -1 is last item, like Python)
/// The resulting Rarr includes the end index.
/// Raises an ArgumentException if indices are out of range.
/// If you don't want an exception to be raised for index overflow use Rarr.trim.
/// (from the release of F# 5 on a negative index can also be done with '^' prefix. E.g. ^0 for the last item)
let inline slice startIdx endIdx (rarr: Rarr<'T>) : Rarr<'T> =
rarr.GetSlice(startIdx, endIdx)
/// Trim items from start and end.
/// If the sum of fromStartCount and fromEndCount is bigger than rarr.Count it returns an empty Rarr.
/// If you want an exception to be raised for index overflow use Rarr.slice with negative end index.
let inline trim fromStartCount fromEndCount (rarr: Rarr<'T>) : Rarr<'T> =
let c = rarr.Count
if fromStartCount + fromEndCount >= c then Rarr<'T>(0)
else rarr.GetRange(fromStartCount, c-fromStartCount-fromEndCount)
//------------------------------------------------------------------
//---------------------prev-this-next ------------------------------
//------------------------------------------------------------------
// these functions below also exist on Seq module:
/// Yields Seq from (first, second) up to (second-last, last).
/// Not looped.
/// The resulting seq is one element shorter than the input Rarr.
let windowed2 (rarr:Rarr<'T>) =
if rarr.Count <= 2 then ArgumentException.RaiseBase "FsEx.Rarr.windowed2 input has less than two items:\r\n%s" rarr.ToNiceStringLong
seq { for i = 0 to rarr.Count-2 do rarr.[i], rarr.[i+1] }
/// Yields looped Seq from (first, second) up to (last, first).
/// The resulting seq has the same element count as the input Rarr.
let thisNext (rarr:Rarr<'T>) =
if rarr.Count <= 2 then ArgumentException.RaiseBase "FsEx.Rarr.thisNext input has less than two items:\r\n%s" rarr.ToNiceStringLong
seq { for i = 0 to rarr.Count-2 do rarr.[i], rarr.[i+1]
rarr.[rarr.Count-1], rarr.[0] }
/// Yields looped Seq from (last,first) up to (second-last, last).
/// The resulting seq has the same element count as the input Rarr.
let prevThis (rarr:Rarr<'T>) =
if rarr.Count <= 2 then ArgumentException.RaiseBase "FsEx.Rarr.prevThis input has less than two items:\r\n%s" rarr.ToNiceStringLong
seq { rarr.[rarr.Count-1], rarr.[0]
for i = 0 to rarr.Count-2 do rarr.[i], rarr.[i+1] }
/// Yields Seq from (first, second, third) up to (third-last, second-last, last).
/// Not looped.
/// The resulting seq is two elements shorter than the input Rarr.
let windowed3 (rarr:Rarr<'T>) =
if rarr.Count <= 3 then ArgumentException.RaiseBase "FsEx.Rarr.windowed3 input has less than three items:\r\n%s" rarr.ToNiceStringLong
seq { for i = 0 to rarr.Count-3 do rarr.[i], rarr.[i+1], rarr.[i+2] }
/// Yields looped Seq of from (last, first, second) up to (second-last, last, first).
/// The resulting seq has the same element count as the input Rarr.
let prevThisNext (rarr:Rarr<'T>) =
if rarr.Count <= 3 then ArgumentException.RaiseBase "FsEx.Rarr.prevThisNext input has less than three items:\r\n%s" rarr.ToNiceStringLong
seq{rarr.[rarr.Count-1], rarr.[0], rarr.[1]
for i = 0 to rarr.Count-3 do rarr.[i], rarr.[i+1], rarr.[i+2]
rarr.[rarr.Count-2],rarr.[rarr.Count-1], rarr.[0] }
/// Yields Seq from (0,first, second) up to (lastIndex-1 , second-last, last).
/// Not looped.
/// The resulting seq is one element shorter than the input Rarr.
let windowed2i (rarr:Rarr<'T>) =
if rarr.Count <= 2 then ArgumentException.RaiseBase "FsEx.Rarr.windowed2i input has less than two items:\r\n%s" rarr.ToNiceStringLong
seq { for i = 0 to rarr.Count-2 do i, rarr.[i], rarr.[i+1] }
/// Yields looped Seq from (0,first, second) up to (lastIndex, last, first).
/// The resulting seq has the same element count as the input Rarr.
let iThisNext (rarr:Rarr<'T>) =
if rarr.Count <= 2 then ArgumentException.RaiseBase "FsEx.Rarr.iThisNext input has less than two items:\r\n%s" rarr.ToNiceStringLong
seq { for i = 0 to rarr.Count-2 do i, rarr.[i], rarr.[i+1]
rarr.Count-1, rarr.[rarr.Count-1], rarr.[0] }
/// Yields Seq from (1, first, second, third) up to (lastIndex-1 , third-last, second-last, last).
/// Not looped.
/// The resulting seq is two elements shorter than the input Rarr.
let windowed3i (rarr:Rarr<'T>) =
if rarr.Count <= 3 then ArgumentException.RaiseBase "FsEx.Rarr.windowed3i input has less than three items:\r\n%s" rarr.ToNiceStringLong
seq { for i = 0 to rarr.Count-3 do i+1, rarr.[i], rarr.[i+1], rarr.[i+2] }
/// Yields looped Seq from (1, last, first, second) up to (lastIndex, second-last, last, first)
/// The resulting seq has the same element count as the input Rarr.
let iPrevThisNext (rarr:Rarr<'T>) =
if rarr.Count <= 3 then ArgumentException.RaiseBase "FsEx.Rarr.iPrevThisNext input has less than three items:\r\n%s" rarr.ToNiceStringLong
seq { 0, rarr.[rarr.Count-1], rarr.[0], rarr.[1]
for i = 0 to rarr.Count-3 do i+1, rarr.[i], rarr.[i+1], rarr.[i+2]
rarr.Count-1, rarr.[rarr.Count-2],rarr.[rarr.Count-1], rarr.[0] }
//------------------------------------------------------------------
/// Returns a Rarr containing just one element
[<Obsolete("Has a typo, use Rarr.singleton instead")>]
let singelton (element: 'T) : Rarr<'T> =
let r = Rarr(1)
r.Add element
r
/// <summary>Returns a Rarr that contains one item only.</summary>
/// <param name="value">The input item.</param>
/// <returns>The result Rarr of one item.</returns>
let inline singleton value =
let res = ResizeArray(1)
res.Add value
res |> Rarr.createDirectly
/// <summary>Considers List circular and move elements up for positive integers or down for negative integers.
/// e.g.: rotate +1 [ a, b, c, d] = [ d, a, b, c]
/// e.g.: rotate -1 [ a, b, c, d] = [ b, c, d, a]
/// the amount can even be bigger than the list's size. I will just rotate more than one loop.</summary>
/// <param name="amount">How many elements to shift forward. Or backward if number is negative</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The new result Rarr.</returns>
let inline rotate amount (rarr: Rarr<'T>) : Rarr<'T> =
let r = Rarr(rarr.Count)
let li = rarr.InternalList
for i = 0 to li.Count - 1 do
r.Add <| li.[negIdxLooped (i-amount) rarr.Count]
r
/// <summary>Considers List circular and move elements up till condition is met for the first item.
/// The algorithm takes elements from the end and put them at the start till the first element in the list meets the condition.
/// If the first element in the input meets the condition no changes are made. But still a shallow copy is returned.</summary>
/// <param name="condition">The condition to meet.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The new result Rarr.</returns>
let inline rotateUpTill (condition:'T->bool) (rarr: Rarr<'T>) : Rarr<'T> =
let li = rarr.InternalList
if li.Count=0 then
rarr
elif condition li.[0] then
rarr.Clone()
else
let li = rarr.InternalList
let rec findBackIdx i =
if i = -1 then
ArgumentException.RaiseBase "FsEx.Rarr.rotateUpTill: no item in the list meets the condition:\r\n%s" rarr.ToNiceStringLong
elif condition li.[i] then
i
else
findBackIdx (i-1)
let fi = findBackIdx (li.Count-1)
let r = ResizeArray(rarr.Count)
for i = fi to li.Count - 1 do
r.Add <| li.[i]
for i = 0 to fi - 1 do
r.Add <| li.[i]
Rarr.createDirectly r
/// <summary>Considers List circular and move elements up till condition is met for the last item.
/// The algorithm takes elements from the end and put them at the start till the last element in the list meets the condition.
/// If the last element in the input meets the condition no changes are made. But still a shallow copy is returned.</summary>
/// <param name="condition">The condition to meet.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The new result Rarr.</returns>
let inline rotateUpTillLast (condition:'T->bool) (rarr: Rarr<'T>) : Rarr<'T> =
let li = rarr.InternalList
if li.Count=0 then
rarr
elif condition li.[li.Count-1] then
rarr.Clone()
else
let li = rarr.InternalList
let rec findBackIdx i =
if i = -1 then
ArgumentException.RaiseBase "FsEx.Rarr.rotateUpTill: no item in the list meets the condition:\r\n%s" rarr.ToNiceStringLong
elif condition li.[i] then
i
else
findBackIdx (i-1)
let fi = findBackIdx (li.Count-1)
let r = ResizeArray(rarr.Count)
for i = fi+1 to li.Count - 1 do
r.Add <| li.[i]
for i = 0 to fi do
r.Add <| li.[i]
Rarr.createDirectly r
/// <summary>Considers List circular and move elements down till condition is met for the first item.
/// The algorithm takes elements from the start and put them at the end till the first element in the list meets the condition.
/// If the first element in the input meets the condition no changes are made. But still a shallow copy is returned.</summary>
/// <param name="condition">The condition to meet.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The new result Rarr.</returns>
let inline rotateDownTill (condition:'T->bool) (rarr: Rarr<'T>) : Rarr<'T> =
let li = rarr.InternalList
if li.Count=0 then
rarr
elif condition li.[0] then
rarr.Clone()
else
let li = rarr.InternalList
let k= li.Count
let rec findIdx i =
if i = k then
ArgumentException.RaiseBase "FsEx.Rarr.rotateDownTill: no item in the list meets the condition:\r\n%s" rarr.ToNiceStringLong
elif condition li.[i] then
i
else
findIdx (i+1)
let fi = findIdx (0)
let r = ResizeArray(rarr.Count)
for i = fi to li.Count - 1 do
r.Add <| li.[i]
for i = 0 to fi - 1 do
r.Add <| li.[i]
Rarr.createDirectly r
/// <summary>Considers List circular and move elements down till condition is met for the last item.
/// The algorithm takes elements from the start and put them at the end till the last element in the list meets the condition.
/// If the last element in the input meets the condition no changes are made. But still a shallow copy is returned.</summary>
/// <param name="condition">The condition to meet.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The new result Rarr.</returns>
let inline rotateDownTillLast (condition:'T->bool) (rarr: Rarr<'T>) : Rarr<'T> =
let li = rarr.InternalList
if li.Count=0 then
rarr
elif condition li.[0] then
rarr.Clone()
else
let li = rarr.InternalList
let k= li.Count
let rec findIdx i =
if i = k then
ArgumentException.RaiseBase "FsEx.Rarr.rotateDownTill: no item in the list meets the condition:\r\n%s" rarr.ToNiceStringLong
elif condition li.[i] then
i
else
findIdx (i+1)
let fi = findIdx (0)
let r = ResizeArray(rarr.Count)
for i = fi+1 to li.Count - 1 do
r.Add <| li.[i]
for i = 0 to fi do
r.Add <| li.[i]
Rarr.createDirectly r
/// Structural equality.
/// Compares each element in both lists for equality . Rarrs must also be of same Count
let equals (rarr1: Rarr<'T>) (rarr2: Rarr<'T>) :bool =
rarr1.IsEqualTo(rarr2)
/// Returns true if the given Rarr has just one item.
/// Same as Rarr.hasOne
[<Obsolete("Has a typo, use Rarr.isSingleton instead")>]
let inline isSingelton (rarr : Rarr<'T>) : bool =
rarr.Count = 1
/// Returns true if the given Rarr has just one item.
/// Same as Rarr.hasOne
let inline isSingleton (rarr : Rarr<'T>) : bool =
rarr.Count = 1
/// Returns true if the given Rarr has just one item.
/// Same as Rarr.isSingleton
let inline hasOne (rarr : Rarr<'T>) : bool =
rarr.Count = 1
/// Returns true if the given Rarr is not empty.
let inline isNotEmpty (rarr : Rarr<'T>) : bool =
rarr.Count <> 0
/// Returns true if the given Rarr has count items.
let inline hasItems count (rarr : Rarr<'T>) : bool =
rarr.Count = count
/// Returns true if the given Rarr has equal or more than count items.
let inline hasMinimumItems count (rarr : Rarr<'T>) : bool =
rarr.Count >= count
/// Returns true if the given Rarr has equal or less than count items.
let inline hasMaximumItems count (rarr : Rarr<'T>) : bool =
rarr.Count <= count
/// Swap the values of two given indices in Rarr
let inline swap i j (xs:Rarr<'T>) : unit =
if i < 0 then IndexOutOfRangeException.Raise "FsEx.Rarr.swap: index i can't be less than 0: %d (j: %d)" i j
if i >= xs.Count then IndexOutOfRangeException.Raise "FsEx.Rarr.swap: index i can't be bigger than %d but is %d (j: %d)" (xs.Count-1) i j
if i<>j then
if j < 0 then IndexOutOfRangeException.Raise "FsEx.Rarr.swap: index j can't be less than 0: %d (i: %d)" j i
if j >= xs.Count then IndexOutOfRangeException.Raise "FsEx.Rarr.swap: index j can't be bigger than %d but is %d (i: %d)" (xs.Count-1) j i
// operate on underlying list since indices are checked
let ti = xs.InternalList.[i]
xs.InternalList.[i] <- xs.InternalList.[j]
xs.InternalList.[j] <- ti
/// internal only for finding
module private MinMax =
//TODO test keeping of order if equal !
(*
let inline simple cmpF (xs:Rarr<'T>) =
if xs.Count < 1 then ArgumentException.RaiseBase "FsEx.Rarr.MinMax.simple: Count must be at least one: %s" xs.ToNiceStringLong
let mutable m = xs.[0]
for i=1 to xs.Count-1 do
if cmpF xs.InternalList.[i] m then m <- xs.InternalList.[i]
m
*)
let inline simple2 cmpF (xs:Rarr<'T>) =
if xs.Count < 2 then ArgumentException.RaiseBase "FsEx.Rarr.MinMax.simple2: Count must be at least two: %s" xs.ToNiceStringLong
let mutable m1 = xs.InternalList.[0]
let mutable m2 = xs.InternalList.[1]
for i=1 to xs.Count-1 do
let this = xs.InternalList.[i]
if cmpF this m1 then
m2 <- m1
m1 <- this
elif cmpF this m2 then
m2 <- this
m1,m2
/// If any are equal then the order is kept by using ( a=b || ) since the compare operate does not include the equal test
let inline sort3 cmp a b c =
if a=b || cmp a b then
if cmp b c then a,b,c
else
if cmp a c then a,c,b
else c,a,b
else
if a=c || cmp a c then b,a,c
else
if b=c || cmp b c then b,c,a
else c,b,a
/// If any are equal then the order is kept by using ( a=b || ) since the compare operate does not include the equal test
let inline indexOfSort3By f cmp aa bb cc =
let a = f aa
let b = f bb
let c = f cc
if a=b || cmp a b then
if cmp b c then 0,1,2
else
if cmp a c then 0,2,1
else 2,0,1
else
if a=c || cmp a c then 1,0,2
else
if b=c || cmp b c then 1,2,0
else 2,1,0
let inline simple3 cmpF (xs:Rarr<'T>) =
if xs.Count < 3 then ArgumentException.RaiseBase "FsEx.Rarr.MinMax.simple3: Count must be at least three: %s" xs.ToNiceStringLong
let e1 = xs.InternalList.[0]
let e2 = xs.InternalList.[1]
let e3 = xs.InternalList.[2]
// sort first 3
let mutable m1, m2, m3 = sort3 cmpF e1 e2 e3 // otherwise would fail on sorting first 3, test on Rarr([5;6;3;1;2;0])|> Rarr.max3
for i=3 to xs.Count-1 do
let this = xs.[i]
if cmpF this m1 then
m3 <- m2
m2 <- m1
m1 <- this
elif cmpF this m2 then
m3 <- m2
m2 <- this
elif cmpF this m3 then
m3 <- this
m1,m2,m3
let inline indexByFun cmpF func (xs:Rarr<'T>) =
if xs.Count < 1 then ArgumentException.RaiseBase "FsEx.Rarr.MinMax.indexByFun: Count must be at least one: %s" xs.ToNiceStringLong
let mutable f = func xs.InternalList.[0]
let mutable mf = f
let mutable ii = 0
let li = xs.InternalList
for i=1 to xs.Count-1 do
f <- func li.[i]
if cmpF f mf then
ii <- i
mf <- f
ii
let inline index2ByFun cmpF func (xs:Rarr<'T>) =
if xs.Count < 2 then ArgumentException.RaiseBase "FsEx.Rarr.MinMax.index2ByFun: Count must be at least two: %s" xs.ToNiceStringLong
let mutable i1 = 0
let mutable i2 = 1
let mutable mf1 = func xs.InternalList.[i1]
let mutable mf2 = func xs.InternalList.[i2]
let mutable f = mf1 // placeholder
let li = xs.InternalList
for i=1 to xs.Count-1 do
f <- func li.[i]
if cmpF f mf1 then
i2 <- i1
i1 <- i
mf2 <- mf1
mf1 <- f
elif cmpF f mf2 then
i2 <- i
mf2 <- f
i1,i2
let inline index3ByFun (cmpOp:'U->'U->bool) (byFun:'T->'U) (xs:Rarr<'T>) =
if xs.Count < 3 then ArgumentException.RaiseBase "FsEx.Rarr.MinMax.index3ByFun: Count must be at least three: %s" xs.ToNiceStringLong
// sort first 3
let mutable i1,i2,i3 = indexOfSort3By byFun cmpOp xs.[0] xs.[1] xs.[2] // otherwise would fail on sorting first 3, test on Rarr([5;6;3;1;2;0])|> Rarr.max3
let mutable e1 = byFun xs.InternalList.[i1]
let mutable e2 = byFun xs.InternalList.[i2]
let mutable e3 = byFun xs.InternalList.[i3]
let mutable f = e1 // placeholder
let li = xs.InternalList
for i=3 to xs.Count-1 do
f <- byFun li.[i]
if cmpOp f e1 then
i3 <- i2
i2 <- i1
i1 <- i
e3 <- e2
e2 <- e1
e1 <- f
elif cmpOp f e2 then
i3 <- i2
i2 <- i
e3 <- e2
e2 <- f
elif cmpOp f e3 then
i3 <- i
e3 <- f
i1,i2,i3
(* covered by part copied from Array module:
let min rarr = rarr |> MinMax.simple (<)
let max rarr = rarr |> MinMax.simple (>)
let minBy f rarr = let i = rarr |> MinMax.indexByFun (<) f in rarr.InternalList.[i]
let maxBy f rarr = let i = rarr |> MinMax.indexByFun (>) f in rarr.InternalList.[i]
*)
/// <summary>Returns the index of the smallest of all elements of the Rarr, compared via Operators.max on the function result.</summary>
/// <param name="projection">The function to transform the elements into a type supporting comparison.</param>
/// <param name="rarr">The input Rarr.</param>
/// <exception cref="T:System.ArgumentException">Thrown when the input Rarr is empty.</exception>
/// <returns>The index of the smallest element.</returns>
let inline minIndBy (projection : 'T -> 'Key) (rarr: Rarr<'T>) : int =
rarr |> MinMax.indexByFun (<) projection
/// <summary>Returns the index of the greatest of all elements of the Rarr, compared via Operators.max on the function result.</summary>
/// <param name="projection">The function to transform the elements into a type supporting comparison.</param>
/// <param name="rarr">The input Rarr.</param>
/// <exception cref="T:System.ArgumentException">Thrown when the input Rarr is empty.</exception>
/// <returns>The index of the maximum element.</returns>
let inline maxIndBy (projection : 'T -> 'Key) (rarr: Rarr<'T>) : int =
rarr |> MinMax.indexByFun (>) projection
/// Returns the smallest two elements of the Rarr.
/// If they are equal then the order is kept
let inline min2 rarr = rarr |> MinMax.simple2 (<)
/// Returns the biggest two elements of the Rarr.
/// If they are equal then the order is kept
let inline max2 rarr = rarr |> MinMax.simple2 (>)
// TODO make consistent xml docstring on below functions:
/// Returns the smallest two elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline min2By f rarr =
let i,ii = rarr |> MinMax.index2ByFun (<) f
rarr.InternalList.[i],rarr.InternalList.[ii]
/// Returns the biggest two elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline max2By f rarr =
let i,ii = rarr |> MinMax.index2ByFun (>) f
rarr.InternalList.[i],
rarr.InternalList.[ii]
/// Returns the indices of the two smallest elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline min2IndBy f rarr = rarr |> MinMax.index2ByFun (<) f
/// Returns the indices of the two biggest elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline max2IndBy f rarr = rarr |> MinMax.index2ByFun (>) f
/// Returns the smallest three elements of the Rarr.
/// If they are equal then the order is kept
let inline min3 rarr = rarr |> MinMax.simple3 (<)
/// Returns the biggest three elements of the Rarr.
/// If they are equal then the order is kept
let inline max3 rarr = rarr |> MinMax.simple3 (>)
/// Returns the smallest three elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline min3By f rarr =
let i,ii,iii = rarr |> MinMax.index3ByFun (<) f
rarr.InternalList.[i],
rarr.InternalList.[ii],
rarr.InternalList.[iii]
/// Returns the biggest three elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline max3By f rarr =
let i,ii,iii = rarr |> MinMax.index3ByFun (>) f
rarr.InternalList.[i],
rarr.InternalList.[ii],
rarr.InternalList.[iii]
/// Returns the indices of the three smallest elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline min3IndBy f rarr = rarr |> MinMax.index3ByFun(<) f
/// Returns the indices of the three biggest elements of the Rarr.
/// Elements are compared by applying the predicate function first.
/// If they are equal after function is applied then the order is kept
let inline max3IndBy f rarr = rarr |> MinMax.index3ByFun (>) f
/// Return the length or count of the collection.
/// Same as Rarr.length
let inline count (rarr : Rarr<'T>) : int =
rarr.Count
/// Counts for how many items of the collection the predicate returns true.
/// Same as Rarr.filter and then Rarr.length
let inline countIf (predicate : 'T -> bool) (rarr : Rarr<'T>) : int = //countBy is something else !!
let mutable k = 0
let li = rarr.InternalList
for i=0 to li.Count - 1 do
if predicate li.[i] then
k <- k + 1
k
/// Adds an object to the end of the Rarr.
let inline add item (rarr : Rarr<'T>) : unit =
rarr.Add item
/// Build a Rarr from the given Array.
let inline ofArray (arr : 'T[]) : Rarr<'T> =
let l = ResizeArray(arr.Length)
for i=0 to arr.Length-1 do
l.Add arr.[i]
Rarr.createDirectly l
/// Build a Rarr from the given IList Interface.
let inline ofIList (arr : IList<'T>) : Rarr<'T> =
let l = ResizeArray(arr.Count)
for i=0 to arr.Count-1 do
l.Add arr.[i]
Rarr.createDirectly l
/// Return a fixed-length Array containing the elements of the input Rarr.
let inline toArray (rarr : Rarr<'T>) : 'T[] =
rarr.ToArray()
/// <summary>
/// Splits the collection into two (2) collections, containing the elements for which the
/// given function returns <c>Choice1Of2</c> or <c>Choice2Of2</c>, respectively. This function is similar to
/// <c>Rarr.partition</c>, but it allows the returned collections to have different element types.</summary>
let inline mapPartition partitioner (rarr : Rarr<'T>) : Rarr<'U1> * Rarr<'U2> =
let results1 = Rarr()
let results2 = Rarr()
let len = rarr.Count
let li = rarr.InternalList
for i = 0 to len - 1 do
match partitioner li.[i] with
| Choice1Of2 value ->
results1.Add value
| Choice2Of2 value ->
results2.Add value
results1, results2
/// Applies a function to List
/// If resulting List meets the resultPredicate it is returned , otherwise original input is returned.
let inline applyIfResult (resultPredicate:Rarr<'T> -> bool) (transform:Rarr<'T> -> Rarr<'T>) (rarr: Rarr<'T>) : Rarr<'T> =
let r = transform rarr
if resultPredicate r then r
else rarr
/// Applies a function to List if it meets the inputPredicate, otherwise just returns input.
/// If resulting List meets the resultPredicate it is returned , otherwise original input is returned.
let inline applyIfInputAndResult (inputPredicate:Rarr<'T> -> bool) (resultPredicate:Rarr<'T> -> bool) (transform:Rarr<'T> -> Rarr<'T>) (rarr: Rarr<'T>) : Rarr<'T> =
if inputPredicate rarr then
let r = transform rarr
if resultPredicate r then r
else rarr
else
rarr
/// Returns all elements that exists more than once in Rarr.
/// Each element that exists more than once is only returned once.
/// Returned order is by first occurrence of first duplicate.
let duplicates (xs:Rarr<'T>) =
let h = Hashset<'T>()
let t = Hashset<'T>()
// first Add should be false, second Add true, to recognize the first occurrence of a duplicate:
xs.FindAll (System.Predicate (fun x -> if h.Add x then false else t.Add x))
/// Returns all elements that exists more than once in Rarr.
/// Each element that exists more than once is only returned once.
/// Returned order is by first occurrence of first duplicate.
let duplicatesBy (f:'T->'U) (xs:Rarr<'T>) =
let h = Hashset<'U>()
let t = Hashset<'U>()
// first Add should be false, second Add true, to recognize the first occurrence of a duplicate:
xs.FindAll (System.Predicate (fun x -> let y = f x in if h.Add y then false else t.Add y))
/// <summary>Splits the collection into three collections,
/// first containing the elements for which the given predicate1 returns <c>true</c> ,
/// second containing the elements for which the given predicate2 returns <c>true</c> (and all previous predicates returned <c>false</c>),
/// third the rest.</summary>
/// <param name="predicate1">The first function to test the input elements.</param>
/// <param name="predicate2">The second function to test the input elements.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>Three Rarrs. </returns>
let partition3 (predicate1:'T->bool) (predicate2:'T->bool) (rarr : Rarr<'T>) : Rarr<'T> * Rarr<'T>* Rarr<'T> =
let p1True = Rarr()
let p2True = Rarr()
let allFalse = Rarr()
let len = rarr.Count
let li = rarr.InternalList
for i = 0 to len - 1 do
let el = li.[i]
if predicate1 el then
p1True.Add el
else
if predicate2 el then
p2True.Add el
else
allFalse.Add el
p1True, p2True, allFalse
/// <summary>Splits the collection into four collections,
/// first containing the elements for which the given predicate1 returns <c>true</c> ,
/// second containing the elements for which the given predicate2 returns <c>true</c> (and all previous predicates returned <c>false</c>),
/// third containing the elements for which the given predicate3 returns <c>true</c> (and all previous predicates returned <c>false</c>),
/// fourth the rest.</summary>
/// <param name="predicate1">The first function to test the input elements.</param>
/// <param name="predicate2">The second function to test the input elements.</param>
/// <param name="predicate3">The third function to test the input elements.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>Four Rarrs. </returns>
let partition4 (predicate1:'T->bool) (predicate2:'T->bool) (predicate3:'T->bool) (rarr : Rarr<'T>) : Rarr<'T> * Rarr<'T>* Rarr<'T>* Rarr<'T> =
let p1True = Rarr()
let p2True = Rarr()
let p3True = Rarr()
let allFalse = Rarr()
let len = rarr.Count
let li = rarr.InternalList
for i = 0 to len - 1 do
let el = li.[i]
if predicate1 el then
p1True.Add el
else
if predicate2 el then
p2True.Add el
else
if predicate3 el then
p3True.Add el
else
allFalse.Add el
p1True, p2True, p3True, allFalse
/// <summary>Splits the collection into five collections,
/// first containing the elements for which the given predicate1 returns <c>true</c> ,
/// second containing the elements for which the given predicate2 returns <c>true</c> (and all previous predicates returned <c>false</c>),
/// third containing the elements for which the given predicate3 returns <c>true</c> (and all previous predicates returned <c>false</c>),
/// fourth containing the elements for which the given predicate4 returns <c>true</c> (and all previous predicates returned <c>false</c>),
/// fifth the rest.</summary>
/// <param name="predicate1">The first function to test the input elements.</param>
/// <param name="predicate2">The second function to test the input elements.</param>
/// <param name="predicate3">The third function to test the input elements.</param>
/// <param name="predicate4">The fourth function to test the input elements.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>Five Rarrs. </returns>
let partition5 (predicate1:'T->bool) (predicate2:'T->bool) (predicate3:'T->bool) (predicate4:'T->bool) (rarr : Rarr<'T>) : Rarr<'T> * Rarr<'T>* Rarr<'T>* Rarr<'T>* Rarr<'T> =
let p1True = Rarr()
let p2True = Rarr()
let p3True = Rarr()
let p4True = Rarr()
let allFalse = Rarr()
let len = rarr.Count
let li = rarr.InternalList
for i = 0 to len - 1 do
let el = li.[i]
if predicate1 el then
p1True.Add el
else
if predicate2 el then
p2True.Add el
else
if predicate3 el then
p3True.Add el
else
if predicate4 el then
p4True.Add el
else
allFalse.Add el
p1True, p2True, p3True, p4True, allFalse
//--------------------------------------------------------------------------------------------------------------------
// ------------- implementation adapted form FSharp.Core Array module: ------------------------------------------------
//
// alternatives:
// https://github.com/fsprojects/FSharpx.Collections/blob/master/src/FSharpx.Collections/ResizeArray.fs
// https://github.com/jack-pappas/ExtCore/blob/master/ExtCore/Collections.Rarr.fs
// https://github.com/dotnet/fsharp/tree/master/src/utils
//---------------------------------------------------------------------------------------------------------------------
/// a StructBox for keys in case the key type is itself a type using null as a representation
[<Struct; NoComparison; NoEquality>]
type private StructBox<'T when 'T:equality>(value:'T) = // from fsharp/FSharp.Core/seqcore.fs
member x.Value = value
static member Comparer =
let gcomparer = HashIdentity.Structural<'T>
{ new IEqualityComparer<StructBox<'T>> with
member _.GetHashCode(v) = gcomparer.GetHashCode(v.Value)
member _.Equals(a,b) = gcomparer.Equals(a.Value, b.Value) }
/// <summary>Returns a new Rarr that contains all pairings (or combinations) of elements from the first and second Rarrs.</summary>
/// <param name="rarr1">The first input Rarr.</param>
/// <param name="rarr2">The second input Rarr.</param>
/// <returns>The resulting Rarr of pairs of length: rarr1.Count * rarr2.Count.</returns>
let allPairs (rarr1: Rarr<'T>) (rarr2: Rarr<'U>) :Rarr<'T*'U> =
let res = ResizeArray(rarr1.Count * rarr2.Count)
let l1 = rarr1.InternalList
let l2 = rarr2.InternalList
for i = 0 to rarr1.Count-1 do
for j = 0 to rarr2.Count-1 do
res.Add (l1.[i], l2.[j])
res |> Rarr.createDirectly
/// <summary>Builds a new Rarr that contains the elements of the first Rarr followed by the elements of the second Rarr.
/// When used with the pipeline operator |> the first and only argument to this function with be at the start of the resulting list.
/// This can be counter intuitive. Use the function Rarr.prepend instead to append the first argument at the end of the second argument.</summary>
/// <param name="rarr1">The input Rarr that will be at the beginning.</param>
/// <param name="rarr2">The input Rarr that will be at the end.</param>
/// <returns>The resulting Rarr of length: rarr1.Count + rarr2.Count..</returns>
let inline append (rarr1: Rarr<'T>) (rarr2: Rarr<'T>) =
let res = rarr1.Clone()
res.AddRange(rarr2)
res
/// <summary>Builds a new Rarr that contains the elements of the second Rarr followed by the elements of the first Rarr.
/// When used with the pipeline operator |> the first and only argument to this function with be at the end of the resulting list.
/// Compared to Rarr.append this function has the order of its arguments flipped</summary>
/// <param name="rarr2">The input Rarr that will be at the end.</param>
/// <param name="rarr1">The input Rarr that will be at the beginning.</param>
/// <returns>The resulting Rarr of length: rarr2.Count + rarr1.Count..</returns>
let inline prepend (rarr2: Rarr<'T>) (rarr1: Rarr<'T>) =
let res = rarr1.Clone()
res.AddRange(rarr2)
res
/// <summary>Returns the average of the elements in the Rarr.</summary>
/// <param name="rarr">The input Rarr.</param>
/// <exception cref="T:System.ArgumentException">Thrown when <c>Rarr</c> is empty.</exception>
/// <returns>The average of the elements in the Rarr.</returns>
let inline average (rarr: Rarr<'T>) =
if rarr.Count = 0 then ArgumentException.RaiseBase "FsEx.Rarr.average: Count must be at least one: %s" rarr.ToNiceStringLong
let mutable acc = LanguagePrimitives.GenericZero< ^T>
let li = rarr.InternalList
for i = 0 to li.Count - 1 do
acc <- Checked.(+) acc li.[i]
LanguagePrimitives.DivideByInt< ^T> acc rarr.Count
/// <summary>Returns the average of the elements generated by applying the function to each element of the Rarr.</summary>
/// <param name="projection">The function to transform the Rarr elements before averaging.</param>
/// <param name="rarr">The input Rarr.</param>
/// <exception cref="T:System.ArgumentException">Thrown when <c>Rarr</c> is empty.</exception>
/// <returns>The computed average.</returns>
let inline averageBy (projection: 'T -> ^Key) (rarr: Rarr<'T>) : ^Key =
if rarr.Count = 0 then ArgumentException.RaiseBase "FsEx.Rarr.averageBy: Count must be at least one: %s" rarr.ToNiceStringLong
let mutable acc = LanguagePrimitives.GenericZero< ^Key>
let li = rarr.InternalList
for i = 0 to li.Count - 1 do
acc <- Checked.(+) acc (projection li.[i])
LanguagePrimitives.DivideByInt< ^Key> acc rarr.Count
/// <summary>Applies the given function to each element of the Rarr.
/// Returns the Rarr comprised of the results "x" for each element where
/// the function returns Some(x)</summary>
/// <param name="chooser">The function to generate options from the elements.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The Rarr of results.</returns>
let inline choose (chooser : 'T -> 'U option) (rarr : Rarr<'T>) : Rarr<'U> =
let result = Rarr()
let li = rarr.InternalList
for i = 0 to li.Count - 1 do
match chooser li.[i] with
| None -> ()
| Some value ->
result.Add value
result
/// <summary>Divides the input Rarr into chunks of size at most <c>chunkSize</c>.</summary>
/// <param name="chunkSize">The maximum size of each chunk.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The Rarr divided into chunks.</returns>
/// <exception cref="T:System.ArgumentException">Thrown when <c>chunkSize</c> is not positive.</exception>
let chunkBySize chunkSize (rarr: Rarr<'T>) : Rarr<Rarr<'T>> =
if chunkSize <= 0 then ArgumentException.RaiseBase "FsEx.Rarr.chunkBySize: chunkSize %d must be bigger than 0" chunkSize
let len = rarr.Count
if len = 0 then
Rarr(0)
elif chunkSize > len then
Rarr([rarr.Clone()])
else
let chunkCount = (len - 1) / chunkSize + 1
let res = ResizeArray(chunkCount)
let mutable sub = Rarr(0)
let li = rarr.InternalList
for i=0 to li.Count - 1 do
if i % chunkSize = 0 then
sub <- Rarr(chunkSize)
res.Add(sub)
sub.Add li.[i]
res |> Rarr.createDirectly
/// <summary>For each element of the Rarr, applies the given function. Concatenates all the results and return the combined Rarr.</summary>
/// <param name="mapping">The function to create sub-Rarrs from the input Rarr elements.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns>The concatenation of the sub-Rarrs.</returns>
let collect (mapping: 'T -> Rarr<'U>) (rarr: Rarr<'T>) : Rarr<'U> =
//let collect (mapping: 'T -> seq<'U>) (rarr: Rarr<'T>) : Rarr<'U> = // tests don't pass like that
let res = ResizeArray(rarr.Count)
for e in rarr do
res.AddRange(mapping e)
res |> Rarr.createDirectly
/// <summary>Compares two Rarrs using the given comparison function, element by element.</summary>
/// <param name="comparer">A function that takes an element from each Rarr and returns an int.
/// If it evaluates to a non-zero value iteration is stopped and that value is returned.</param>
/// <param name="rarr1">The first input Rarr.</param>
/// <param name="rarr2">The second input Rarr.</param>
/// <returns>Returns the first non-zero result from the comparison function. If the first Rarr has
/// a larger element, the return value is always positive. If the second Rarr has a larger
/// element, the return value is always negative. When the elements are equal in the two
/// Rarrs, 1 is returned if the first Rarr is longer, 0 is returned if they are equal in
/// length, and -1 is returned when the second Rarr is longer.</returns>
let inline compareWith ((*[<InlineIfLambda>]*) comparer: 'T -> 'T -> int) (rarr1: Rarr<'T>) (rarr2: Rarr<'T>) =
let length1 = rarr1.Count
let length2 = rarr2.Count
let mutable i = 0
let mutable result = 0
if length1 < length2 then
while i < rarr1.Count && result = 0 do
result <- comparer rarr1.InternalList.[i] rarr2.InternalList.[i]
i <- i + 1
else
while i < rarr2.Count && result = 0 do
result <- comparer rarr1.InternalList.[i] rarr2.InternalList.[i]
i <- i + 1
if result <> 0 then result
elif length1 = length2 then 0
elif length1 < length2 then -1
else 1
/// <summary>Builds a new Rarr that contains the elements of each of the given sequence of sequences.</summary>
/// <param name="rarrs">The input sequence of Rarrs.</param>
/// <returns>The concatenation of the sequence of input Rarrs.</returns>
let concat (rarrs: seq<#seq<'T>>) : Rarr<'T>=
//let concat (rarrs: Rarr<Rarr<'T>>) : Rarr<'T> = // test don't pass with this
//if rarrs.Count = 0 then
if Seq.isEmpty rarrs then
Rarr(0)
else
let res = ResizeArray() //rarrs.[0].Clone()
for r in rarrs do res.AddRange(r)
//for i=1 to rarrs.(xs.Count-1) do res.AddRange(rarrs.[i])
res |> Rarr.createDirectly
/// <summary>Tests if the Rarr contains the specified element.</summary>
/// <param name="value">The value to locate in the input Rarr.</param>
/// <param name="rarr">The input Rarr.</param>
/// <returns><c>true</c> if the input Rarr contains the specified element; false otherwise.</returns>
let inline contains value (rarr: Rarr<'T>) =