├── GcTests.meta
├── GcTests
├── GcTest.cs
├── GcTest.cs.meta
├── GcTestScene.unity
└── GcTestScene.unity.meta
├── JacksonDunstanIterator.meta
├── JacksonDunstanIterator
├── ArrayIterator.cs
├── ArrayIterator.cs.meta
├── JacksonDunstanIterator.asmdef
├── JacksonDunstanIterator.asmdef.meta
├── ListIterator.cs
├── ListIterator.cs.meta
├── NativeArrayIterator.cs
├── NativeArrayIterator.cs.meta
├── Tests.meta
└── Tests
│ ├── JacksonDunstanIteratorTests.asmdef
│ ├── JacksonDunstanIteratorTests.asmdef.meta
│ ├── TestArrayIterator.cs
│ ├── TestArrayIterator.cs.meta
│ ├── TestListIterator.cs
│ ├── TestListIterator.cs.meta
│ ├── TestNativeArrayIterator.cs
│ ├── TestNativeArrayIterator.cs.meta
│ ├── Utils.cs
│ └── Utils.cs.meta
├── LICENSE.txt
├── LICENSE.txt.meta
├── README.md
└── README.md.meta
/GcTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f880bc781dfc14dba9f1809283d18580
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/GcTests/GcTest.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt.
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Linq;
9 | using UnityEngine;
10 | using JacksonDunstanIterator;
11 |
12 | ///
13 | /// Script to test whether the library creates any garbage. Run it with the
14 | /// Unity profiler in "deep" mode and check the "Gc Alloc" column for
15 | /// GcTest.Start().
16 | ///
17 | public class GcTest : MonoBehaviour
18 | {
19 | private static readonly System.Random random = new System.Random();
20 | private static readonly int[] defaultArr = { 1, 2, 2, 3 };
21 | private static readonly int[] arr = defaultArr.ToArray();
22 | private static readonly int[] arr2 = new int[arr.Length];
23 | private static readonly int[] arr3 = new int[arr.Length];
24 | private static readonly int[] arrLong = new int[arr.Length * 2];
25 | private static readonly Func AreIntsEqual = (a, b) => a == b;
26 | private static readonly Func IsIntEven = i => i % 2 == 0;
27 | private static readonly Func IsIntEqualTo2 = i => i == 2;
28 | private static readonly Func IsIntLessThanOrEqualTo2 = i => i <= 2;
29 | private static readonly Func IsIntGreaterThan0 = i => i > 0;
30 | private static readonly Func IsIntGreaterThan10 = i => i > 10;
31 | private static readonly Func DoubleInt = i => i * 2;
32 | private static readonly Func MultiplyInts = (a, b) => a * b;
33 | private static readonly Func IsIntGreaterThanInt = (a, b) => a > b;
34 | private static readonly Func IsIntLessThanInt = (a, b) => a < b;
35 | private static readonly Action NoOp = i => { };
36 | private static readonly Func RandomIntLessThan = random.Next;
37 | private static int[] OneThreeThreeFour = { 1, 3, 3, 4 };
38 | private static int[] OneThreeTwoFour = { 1, 3, 2, 4 };
39 | private static int[] ThreeThreeOneTwo = { 3, 3, 1, 2 };
40 | private static int[] ThreeTwoOneTwo = { 3, 2, 1, 2 };
41 | private static int[] ThreeTwoOne = { 3, 2, 1 };
42 | private static int[] TwoThree = { 2, 3 };
43 | private static int[] FourTwoThreeOne = { 4, 2, 3, 1 };
44 | private static int[] OneTwoThreeFour = { 1, 2, 3, 4 };
45 |
46 | void Start()
47 | {
48 | arr.Begin().GetAdvanced(1).GetCurrent();
49 | arr.Begin().Distance(arr.End());
50 | arr.Begin().AllOf(arr.End(), IsIntEven);
51 | arr.Begin().AllOf(arr.End(), IsIntGreaterThan0);
52 | arr.Begin().AnyOf(arr.End(), IsIntGreaterThan10);
53 | arr.Begin().AnyOf(arr.End(), IsIntEqualTo2);
54 | arr.Begin().NoneOf(arr.End(), IsIntEqualTo2);
55 | arr.Begin().NoneOf(arr.End(), IsIntGreaterThan10);
56 | arr.Begin().ForEach(arr.End(), NoOp);
57 | arr.Begin().Find(arr.End(), 2, AreIntsEqual);
58 | arr.Begin().FindIf(arr.End(), IsIntEven);
59 | arr.Begin().FindIfNot(arr.End(), IsIntEven);
60 | arr.Begin().FindEnd(
61 | arr.End(),
62 | arr.IteratorAt(1),
63 | arr.IteratorAt(2),
64 | AreIntsEqual
65 | );
66 | arr.Begin().FindFirstOf(
67 | arr.End(),
68 | arr.IteratorAt(1),
69 | arr.IteratorAt(2),
70 | AreIntsEqual
71 | );
72 | arr.Begin().AdjacentFind(arr.End(), AreIntsEqual);
73 | arr.Begin().Count(arr.End(), 2, AreIntsEqual);
74 | arr.Begin().CountIf(arr.End(), IsIntEven);
75 | ArrayIterator mm1;
76 | ArrayIterator mm2;
77 | arr.Begin().Mismatch(
78 | arr.End(),
79 | OneThreeThreeFour.Begin(),
80 | AreIntsEqual,
81 | out mm1,
82 | out mm2
83 | );
84 | arr.Begin().IsPermutation(arr.End(), ThreeThreeOneTwo.Begin(), AreIntsEqual);
85 | arr.Begin().IsPermutation(arr.End(), ThreeTwoOneTwo.Begin(), AreIntsEqual);
86 | arr.Begin().Search(arr.End(), TwoThree.Begin(), TwoThree.End(), AreIntsEqual);
87 | arr.Begin().SearchN(arr.End(), 2, 2, AreIntsEqual);
88 | arr.Begin().Copy(arr.IteratorAt(2), arr2.Begin());
89 | arr.Begin().CopyN(3, arr2.Begin());
90 | arr.Begin().CopyIf(arr.End(), arr2.Begin(), IsIntEven);
91 | arr.IteratorAt(1).CopyBackward(arr.IteratorAt(3), arr2.End());
92 | arr.IteratorAt(1).SwapRanges(arr.IteratorAt(3), arr2.IteratorAt(1));
93 | var itA = arr.IteratorAt(0);
94 | var itB = arr.IteratorAt(1);
95 | itA.Swap(itB);
96 | arr.Begin().Transform(arr.End(), arr.Begin(), DoubleInt);
97 | arr.Begin().Transform(arr.End(), arr.Begin(), arr.Begin(), MultiplyInts);
98 | arr.Begin().ReplaceIf(arr.End(), IsIntEqualTo2, 20);
99 | arr.Begin().ReplaceCopyIf(arr.End(), arr.Begin(), IsIntEven, 200);
100 | arr.Begin().Unique(arr.End(), AreIntsEqual);
101 | arr.Begin().UniqueCopy(arr.End(), arr2.Begin(), AreIntsEqual);
102 | arr.Begin().Reverse(arr.End());
103 | arr.Begin().ReverseCopy(arr.End(), arr2.Begin());
104 | arr.Begin().Rotate(arr.IteratorAt(2), arr.End());
105 | arr.Begin().RotateCopy(arr.IteratorAt(2), arr.End(), arr2.Begin());
106 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan);
107 | arr.Begin().Copy(arr.End(), arr2.Begin());
108 | arr2.Begin().RandomShuffle(arr2.End(), RandomIntLessThan);
109 | arr.Begin().IsPartitioned(arr.End(), IsIntEven);
110 | arr.Begin().IsPartitioned(arr.End(), IsIntLessThanOrEqualTo2);
111 | arr.Begin().Partition(arr.End(), IsIntEven);
112 | ArrayIterator outResultTrue;
113 | ArrayIterator outResultFalse;
114 | arr.Begin().PartitionCopy(
115 | arr.End(),
116 | arr2.Begin(),
117 | arr3.Begin(),
118 | IsIntEven,
119 | out outResultTrue,
120 | out outResultFalse
121 | );
122 | arr.Begin().PartitionPoint(arr.End(), IsIntLessThanOrEqualTo2);
123 | arr.Begin().Sort(arr.End(), IsIntGreaterThanInt);
124 | arr.Begin().StableSort(arr.End(), IsIntGreaterThanInt);
125 | arr.Begin().PartialSort(arr.IteratorAt(2), arr.End(), IsIntGreaterThanInt);
126 | arr.Begin().IsSorted(arr.End(), IsIntLessThanInt);
127 | OneThreeTwoFour.Begin().IsSortedUntil(OneThreeTwoFour.End(), IsIntLessThanInt);
128 | OneThreeTwoFour.Begin().Copy(OneThreeTwoFour.End(), arr.Begin());
129 | arr.Begin().NthElement(arr.IteratorAt(2), arr.End(), IsIntLessThanInt);
130 | arr.Begin().LowerBound(arr.End(), 2, IsIntLessThanInt);
131 | arr.Begin().UpperBound(arr.End(), 2, IsIntLessThanInt);
132 | ArrayIterator equalRangeLower;
133 | ArrayIterator equalRangeUpper;
134 | arr.Begin().EqualRange(
135 | arr.End(),
136 | 2,
137 | IsIntLessThanInt,
138 | out equalRangeLower,
139 | out equalRangeUpper
140 | );
141 | arr.Begin().BinarySearch(arr.End(), 2, IsIntLessThanInt);
142 | arr.Begin().BinarySearch(arr.End(), 9, IsIntLessThanInt);
143 | arr.Begin().Merge(
144 | arr.End(),
145 | OneThreeThreeFour.Begin(),
146 | OneThreeThreeFour.End(),
147 | arrLong.Begin(),
148 | IsIntLessThanInt
149 | );
150 | var copyResult = arr.Begin().Copy(arr.End(), arrLong.Begin());
151 | OneThreeThreeFour.Begin().Copy(OneThreeThreeFour.End(), copyResult);
152 | arrLong.Begin().InplaceMerge(copyResult, arrLong.End(), IsIntLessThanInt);
153 | arr.Begin().Includes(arr.End(), TwoThree.Begin(), TwoThree.End(), IsIntLessThanInt);
154 | arr.Begin().SetUnion(
155 | arr.End(),
156 | OneThreeThreeFour.Begin(),
157 | OneThreeThreeFour.End(),
158 | arrLong.Begin(),
159 | IsIntLessThanInt
160 | );
161 | arr.Begin().SetIntersection(
162 | arr.End(),
163 | OneThreeThreeFour.Begin(),
164 | OneThreeThreeFour.End(),
165 | arrLong.Begin(),
166 | IsIntLessThanInt
167 | );
168 | arr.Begin().SetDifference(
169 | arr.End(),
170 | OneThreeThreeFour.Begin(),
171 | OneThreeThreeFour.End(),
172 | arrLong.Begin(),
173 | IsIntLessThanInt
174 | );
175 | arr.Begin().SetSymmetricDifference(
176 | arr.End(),
177 | OneThreeThreeFour.Begin(),
178 | OneThreeThreeFour.End(),
179 | arrLong.Begin(),
180 | IsIntLessThanInt
181 | );
182 | var pushHeapIt = FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arrLong.Begin());
183 | pushHeapIt.SetCurrent(5);
184 | pushHeapIt = pushHeapIt.GetNext();
185 | arrLong.Begin().PushHeap(pushHeapIt, IsIntLessThanInt);
186 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin());
187 | arr2.Begin().PopHeap(arr2.End(), IsIntLessThanInt);
188 | OneTwoThreeFour.Begin().Copy(OneTwoThreeFour.End(), arr2.Begin());
189 | arr2.Begin().MakeHeap(arr2.End(), IsIntLessThanInt);
190 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin());
191 | arr2.Begin().SortHeap(arr2.End(), IsIntLessThanInt);
192 | FourTwoThreeOne.Begin().IsHeap(FourTwoThreeOne.End(), IsIntLessThanInt);
193 | FourTwoThreeOne.Begin().IsHeapUntil(FourTwoThreeOne.End(), IsIntLessThanInt);
194 | arr.Begin().MinElement(arr.End(), IsIntLessThanInt);
195 | arr.Begin().MaxElement(arr.End(), IsIntLessThanInt);
196 | ArrayIterator minIt;
197 | ArrayIterator maxIt;
198 | arr.Begin().MinMaxElement(arr.End(), IsIntLessThanInt, out minIt, out maxIt);
199 | arr.Begin().LexicographicalCompare(
200 | arr.End(),
201 | arr2.Begin(),
202 | arr2.End(),
203 | IsIntLessThanInt
204 | );
205 | arr2.Begin().LexicographicalCompare(
206 | arr2.End(),
207 | arr.Begin(),
208 | arr.End(),
209 | IsIntLessThanInt
210 | );
211 | while (arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt))
212 | {
213 | }
214 | while (ThreeTwoOne.Begin().PrevPermutation(ThreeTwoOne.End(), IsIntLessThanInt))
215 | {
216 | }
217 | }
218 | }
--------------------------------------------------------------------------------
/GcTests/GcTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 691d6f50ac92a45d197af6f77c0f3b58
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/GcTests/GcTestScene.unity:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!29 &1
4 | OcclusionCullingSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_OcclusionBakeSettings:
8 | smallestOccluder: 5
9 | smallestHole: 0.25
10 | backfaceThreshold: 100
11 | m_SceneGUID: 00000000000000000000000000000000
12 | m_OcclusionCullingData: {fileID: 0}
13 | --- !u!104 &2
14 | RenderSettings:
15 | m_ObjectHideFlags: 0
16 | serializedVersion: 9
17 | m_Fog: 0
18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
19 | m_FogMode: 3
20 | m_FogDensity: 0.01
21 | m_LinearFogStart: 0
22 | m_LinearFogEnd: 300
23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
26 | m_AmbientIntensity: 1
27 | m_AmbientMode: 0
28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
30 | m_HaloStrength: 0.5
31 | m_FlareStrength: 1
32 | m_FlareFadeSpeed: 3
33 | m_HaloTexture: {fileID: 0}
34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
35 | m_DefaultReflectionMode: 0
36 | m_DefaultReflectionResolution: 128
37 | m_ReflectionBounces: 1
38 | m_ReflectionIntensity: 1
39 | m_CustomReflection: {fileID: 0}
40 | m_Sun: {fileID: 0}
41 | m_IndirectSpecularColor: {r: 0.3731316, g: 0.38074902, b: 0.3587254, a: 1}
42 | m_UseRadianceAmbientProbe: 0
43 | --- !u!157 &3
44 | LightmapSettings:
45 | m_ObjectHideFlags: 0
46 | serializedVersion: 11
47 | m_GIWorkflowMode: 0
48 | m_GISettings:
49 | serializedVersion: 2
50 | m_BounceScale: 1
51 | m_IndirectOutputScale: 1
52 | m_AlbedoBoost: 1
53 | m_TemporalCoherenceThreshold: 1
54 | m_EnvironmentLightingMode: 0
55 | m_EnableBakedLightmaps: 1
56 | m_EnableRealtimeLightmaps: 1
57 | m_LightmapEditorSettings:
58 | serializedVersion: 10
59 | m_Resolution: 2
60 | m_BakeResolution: 40
61 | m_AtlasSize: 1024
62 | m_AO: 0
63 | m_AOMaxDistance: 1
64 | m_CompAOExponent: 1
65 | m_CompAOExponentDirect: 0
66 | m_Padding: 2
67 | m_LightmapParameters: {fileID: 0}
68 | m_LightmapsBakeMode: 1
69 | m_TextureCompression: 1
70 | m_FinalGather: 0
71 | m_FinalGatherFiltering: 1
72 | m_FinalGatherRayCount: 256
73 | m_ReflectionCompression: 2
74 | m_MixedBakeMode: 2
75 | m_BakeBackend: 1
76 | m_PVRSampling: 1
77 | m_PVRDirectSampleCount: 32
78 | m_PVRSampleCount: 500
79 | m_PVRBounces: 2
80 | m_PVRFilterTypeDirect: 0
81 | m_PVRFilterTypeIndirect: 0
82 | m_PVRFilterTypeAO: 0
83 | m_PVRFilteringMode: 1
84 | m_PVRCulling: 1
85 | m_PVRFilteringGaussRadiusDirect: 1
86 | m_PVRFilteringGaussRadiusIndirect: 5
87 | m_PVRFilteringGaussRadiusAO: 2
88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5
89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2
90 | m_PVRFilteringAtrousPositionSigmaAO: 1
91 | m_ShowResolutionOverlay: 1
92 | m_LightingDataAsset: {fileID: 0}
93 | m_UseShadowmask: 1
94 | --- !u!196 &4
95 | NavMeshSettings:
96 | serializedVersion: 2
97 | m_ObjectHideFlags: 0
98 | m_BuildSettings:
99 | serializedVersion: 2
100 | agentTypeID: 0
101 | agentRadius: 0.5
102 | agentHeight: 2
103 | agentSlope: 45
104 | agentClimb: 0.4
105 | ledgeDropHeight: 0
106 | maxJumpAcrossDistance: 0
107 | minRegionArea: 2
108 | manualCellSize: 0
109 | cellSize: 0.16666667
110 | manualTileSize: 0
111 | tileSize: 256
112 | accuratePlacement: 0
113 | debug:
114 | m_Flags: 0
115 | m_NavMeshData: {fileID: 0}
116 | --- !u!1 &70518809
117 | GameObject:
118 | m_ObjectHideFlags: 0
119 | m_CorrespondingSourceObject: {fileID: 0}
120 | m_PrefabInternal: {fileID: 0}
121 | serializedVersion: 6
122 | m_Component:
123 | - component: {fileID: 70518811}
124 | - component: {fileID: 70518810}
125 | m_Layer: 0
126 | m_Name: GcTest
127 | m_TagString: Untagged
128 | m_Icon: {fileID: 0}
129 | m_NavMeshLayer: 0
130 | m_StaticEditorFlags: 0
131 | m_IsActive: 1
132 | --- !u!114 &70518810
133 | MonoBehaviour:
134 | m_ObjectHideFlags: 0
135 | m_CorrespondingSourceObject: {fileID: 0}
136 | m_PrefabInternal: {fileID: 0}
137 | m_GameObject: {fileID: 70518809}
138 | m_Enabled: 1
139 | m_EditorHideFlags: 0
140 | m_Script: {fileID: 11500000, guid: 691d6f50ac92a45d197af6f77c0f3b58, type: 3}
141 | m_Name:
142 | m_EditorClassIdentifier:
143 | --- !u!4 &70518811
144 | Transform:
145 | m_ObjectHideFlags: 0
146 | m_CorrespondingSourceObject: {fileID: 0}
147 | m_PrefabInternal: {fileID: 0}
148 | m_GameObject: {fileID: 70518809}
149 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
150 | m_LocalPosition: {x: 0, y: 0, z: 0}
151 | m_LocalScale: {x: 1, y: 1, z: 1}
152 | m_Children: []
153 | m_Father: {fileID: 0}
154 | m_RootOrder: 0
155 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
156 |
--------------------------------------------------------------------------------
/GcTests/GcTestScene.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6a360ecd42bac4475bcccfd4685f55af
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/JacksonDunstanIterator.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e9c98c966c67d45ba8fbcff10e564fc6
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/JacksonDunstanIterator/ArrayIterator.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt.
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using System;
8 |
9 | namespace JacksonDunstanIterator
10 | {
11 | public struct ArrayIterator
12 | {
13 | public T[] Array;
14 | public int Index;
15 | }
16 |
17 | public static class ArrayIteratorExtensions
18 | {
19 | public static ArrayIterator Begin(this T[] array)
20 | {
21 | return new ArrayIterator { Array = array };
22 | }
23 |
24 | public static ArrayIterator End(this T[] array)
25 | {
26 | return new ArrayIterator { Array = array, Index = array.Length };
27 | }
28 |
29 | public static ArrayIterator IteratorAt(this T[] array, int index)
30 | {
31 | return new ArrayIterator { Array = array, Index = index };
32 | }
33 |
34 | public static T GetCurrent(this ArrayIterator it)
35 | {
36 | return it.Array[it.Index];
37 | }
38 |
39 | public static void SetCurrent(this ArrayIterator it, T val)
40 | {
41 | it.Array[it.Index] = val;
42 | }
43 |
44 | public static ArrayIterator GetNext(this ArrayIterator it)
45 | {
46 | it.Index++;
47 | return it;
48 | }
49 |
50 | public static ArrayIterator GetPrev(this ArrayIterator it)
51 | {
52 | it.Index--;
53 | return it;
54 | }
55 |
56 | public static bool IsEqual(this ArrayIterator it, ArrayIterator other)
57 | {
58 | return it.Array == other.Array && it.Index == other.Index;
59 | }
60 |
61 | public static bool NotEqual(this ArrayIterator it, ArrayIterator other)
62 | {
63 | return it.Array != other.Array || it.Index != other.Index;
64 | }
65 |
66 | public static ArrayIterator GetAdvanced(this ArrayIterator it, int distance)
67 | {
68 | return new ArrayIterator { Array = it.Array, Index = it.Index + distance };
69 | }
70 |
71 | public static int Distance(this ArrayIterator first, ArrayIterator last)
72 | {
73 | return last.Index - first.Index;
74 | }
75 |
76 | public static bool AllOf(
77 | this ArrayIterator first,
78 | ArrayIterator last,
79 | Func pred
80 | )
81 | {
82 | while (first.NotEqual(last))
83 | {
84 | if (pred(first.GetCurrent()) == false)
85 | {
86 | return false;
87 | }
88 | first = first.GetNext();
89 | }
90 | return true;
91 | }
92 |
93 | public static bool AnyOf(
94 | this ArrayIterator first,
95 | ArrayIterator last,
96 | Func pred
97 | )
98 | {
99 | while (first.NotEqual(last))
100 | {
101 | if (pred(first.GetCurrent()))
102 | {
103 | return true;
104 | }
105 | first = first.GetNext();
106 | }
107 | return false;
108 | }
109 |
110 | public static bool NoneOf(
111 | this ArrayIterator first,
112 | ArrayIterator last,
113 | Func pred
114 | )
115 | {
116 | while (first.NotEqual(last))
117 | {
118 | if (pred(first.GetCurrent()))
119 | {
120 | return false;
121 | }
122 | first = first.GetNext();
123 | }
124 | return true;
125 | }
126 |
127 | public static void ForEach(
128 | this ArrayIterator first,
129 | ArrayIterator last,
130 | Action callback
131 | )
132 | {
133 | while (first.NotEqual(last))
134 | {
135 | callback(first.GetCurrent());
136 | first = first.GetNext();
137 | }
138 | }
139 |
140 | public static ArrayIterator Find(
141 | this ArrayIterator first,
142 | ArrayIterator last,
143 | T val,
144 | Func pred
145 | )
146 | {
147 | while (first.NotEqual(last))
148 | {
149 | if (pred(first.GetCurrent(), val))
150 | {
151 | return first;
152 | }
153 | first = first.GetNext();
154 | }
155 | return last;
156 | }
157 |
158 | public static ArrayIterator FindIf(
159 | this ArrayIterator first,
160 | ArrayIterator last,
161 | Func pred
162 | )
163 | {
164 | while (first.NotEqual(last))
165 | {
166 | if (pred(first.GetCurrent()))
167 | {
168 | return first;
169 | }
170 | first = first.GetNext();
171 | }
172 | return last;
173 | }
174 |
175 | public static ArrayIterator FindIfNot(
176 | this ArrayIterator first,
177 | ArrayIterator last,
178 | Func pred
179 | )
180 | {
181 | while (first.NotEqual(last))
182 | {
183 | if (pred(first.GetCurrent()) == false)
184 | {
185 | return first;
186 | }
187 | first = first.GetNext();
188 | }
189 | return last;
190 | }
191 |
192 | public static ArrayIterator FindEnd(
193 | this ArrayIterator first1,
194 | ArrayIterator last1,
195 | ArrayIterator first2,
196 | ArrayIterator last2,
197 | Func pred
198 | )
199 | {
200 | if (first2.IsEqual(last2))
201 | {
202 | return last1;
203 | }
204 | var ret = last1;
205 | while (first1.NotEqual(last1))
206 | {
207 | var it1 = first1;
208 | var it2 = first2;
209 | while (pred(it1.GetCurrent(), it2.GetCurrent()))
210 | {
211 | it1 = it1.GetNext();
212 | it2 = it2.GetNext();
213 | if (it2.IsEqual(last2))
214 | {
215 | ret = first1;
216 | break;
217 | }
218 | if (it1.IsEqual(last1))
219 | {
220 | return ret;
221 | }
222 | }
223 | first1 = first1.GetNext();
224 | }
225 | return ret;
226 | }
227 |
228 | public static ArrayIterator FindFirstOf(
229 | this ArrayIterator first1,
230 | ArrayIterator last1,
231 | ArrayIterator first2,
232 | ArrayIterator last2,
233 | Func pred
234 | )
235 | {
236 | while (first1.NotEqual(last1))
237 | {
238 | for (var it = first2; it.NotEqual(last2); it = it.GetNext())
239 | {
240 | if (pred(it.GetCurrent(), first1.GetCurrent()))
241 | {
242 | return first1;
243 | }
244 | }
245 | first1 = first1.GetNext();
246 | }
247 | return last1;
248 | }
249 |
250 | public static ArrayIterator AdjacentFind(
251 | this ArrayIterator first,
252 | ArrayIterator last,
253 | Func pred
254 | )
255 | {
256 | if (first.NotEqual(last))
257 | {
258 | var next = first;
259 | next = next.GetNext();
260 | while (next.NotEqual(last))
261 | {
262 | if (pred(first.GetCurrent(), next.GetCurrent()))
263 | {
264 | return first;
265 | }
266 | first = first.GetNext();
267 | next = next.GetNext();
268 | }
269 | }
270 | return last;
271 | }
272 |
273 | public static int Count(
274 | this ArrayIterator first,
275 | ArrayIterator last,
276 | T val,
277 | Func pred
278 | )
279 | {
280 | var count = 0;
281 | while (first.NotEqual(last))
282 | {
283 | if (pred(first.GetCurrent(), val))
284 | {
285 | count++;
286 | }
287 | first = first.GetNext();
288 | }
289 | return count;
290 | }
291 |
292 | public static int CountIf(
293 | this ArrayIterator first,
294 | ArrayIterator last,
295 | Func pred
296 | )
297 | {
298 | var count = 0;
299 | while (first.NotEqual(last))
300 | {
301 | if (pred(first.GetCurrent()))
302 | {
303 | count++;
304 | }
305 | first = first.GetNext();
306 | }
307 | return count;
308 | }
309 |
310 | public static void Mismatch(
311 | this ArrayIterator first1,
312 | ArrayIterator last1,
313 | ArrayIterator first2,
314 | Func pred,
315 | out ArrayIterator mismatch1,
316 | out ArrayIterator mismatch2
317 | )
318 | {
319 | while (first1.NotEqual(last1))
320 | {
321 | if (pred(first1.GetCurrent(), first2.GetCurrent()) == false)
322 | {
323 | break;
324 | }
325 | first1 = first1.GetNext();
326 | first2 = first2.GetNext();
327 | }
328 | mismatch1 = first1;
329 | mismatch2 = first2;
330 | }
331 |
332 | public static bool Equal(
333 | this ArrayIterator first1,
334 | ArrayIterator last1,
335 | ArrayIterator first2,
336 | Func pred
337 | )
338 | {
339 | while (first1.NotEqual(last1))
340 | {
341 | if (pred(first1.GetCurrent(), first2.GetCurrent()) == false)
342 | {
343 | return false;
344 | }
345 | first1 = first1.GetNext();
346 | first2 = first2.GetNext();
347 | }
348 | return true;
349 | }
350 |
351 | public static bool IsPermutation(
352 | this ArrayIterator first1,
353 | ArrayIterator last1,
354 | ArrayIterator first2,
355 | Func pred
356 | )
357 | {
358 | first1.Mismatch(last1, first2, pred, out first1, out first2);
359 | if (first1.IsEqual(last1))
360 | {
361 | return true;
362 | }
363 | var last2 = first2;
364 | last2 = last2.GetAdvanced(first1.Distance(last1));
365 | for (var it1 = first1; it1.NotEqual(last1); it1 = it1.GetNext())
366 | {
367 | if (first1.Find(it1, it1.GetCurrent(), pred).IsEqual(it1))
368 | {
369 | var n = first2.Count(last2, it1.GetCurrent(), pred);
370 | if (n == 0 || it1.Count(last1, it1.GetCurrent(), pred) != n)
371 | {
372 | return false;
373 | }
374 | }
375 | }
376 | return true;
377 | }
378 |
379 |
380 |
381 | public static ArrayIterator Search(
382 | this ArrayIterator first1,
383 | ArrayIterator last1,
384 | ArrayIterator first2,
385 | ArrayIterator last2,
386 | Func pred
387 | )
388 | {
389 | if (first2.IsEqual(last2))
390 | {
391 | return first1;
392 | }
393 |
394 | while (first1.NotEqual(last1))
395 | {
396 | var it1 = first1;
397 | var it2 = first2;
398 | while (pred(it1.GetCurrent(), it2.GetCurrent()))
399 | {
400 | it1 = it1.GetNext();
401 | it2 = it2.GetNext();
402 | if (it2.IsEqual(last2))
403 | {
404 | return first1;
405 | }
406 | if (it1.IsEqual(last1))
407 | {
408 | return last1;
409 | }
410 | }
411 | first1 = first1.GetNext();
412 | }
413 | return last1;
414 | }
415 |
416 | public static ArrayIterator SearchN(
417 | this ArrayIterator first,
418 | ArrayIterator last,
419 | int count,
420 | T val,
421 | Func pred
422 | )
423 | {
424 | var limit = first.GetAdvanced(first.Distance(last) - count);
425 | while (first.NotEqual(limit))
426 | {
427 | var it = first;
428 | var i = 0;
429 | while (pred(val, it.GetCurrent()))
430 | {
431 | it = it.GetNext();
432 | if (++i == count)
433 | {
434 | return first;
435 | }
436 | }
437 | first = first.GetNext();
438 | }
439 | return last;
440 | }
441 |
442 | public static ArrayIterator Copy(
443 | this ArrayIterator first,
444 | ArrayIterator last,
445 | ArrayIterator result
446 | )
447 | {
448 | while (first.NotEqual(last))
449 | {
450 | result.SetCurrent(first.GetCurrent());
451 | result = result.GetNext();
452 | first = first.GetNext();
453 | }
454 | return result;
455 | }
456 |
457 | public static ArrayIterator CopyN(
458 | this ArrayIterator first,
459 | int n,
460 | ArrayIterator result
461 | )
462 | {
463 | while (n > 0)
464 | {
465 | result.SetCurrent(first.GetCurrent());
466 | result = result.GetNext();
467 | first = first.GetNext();
468 | n--;
469 | }
470 | return result;
471 | }
472 |
473 | public static ArrayIterator CopyIf(
474 | this ArrayIterator first,
475 | ArrayIterator last,
476 | ArrayIterator result,
477 | Func pred
478 | )
479 | {
480 | while (first.NotEqual(last))
481 | {
482 | if (pred(first.GetCurrent()))
483 | {
484 | result.SetCurrent(first.GetCurrent());
485 | result = result.GetNext();
486 | }
487 | first = first.GetNext();
488 | }
489 | return result;
490 | }
491 |
492 | public static ArrayIterator CopyBackward(
493 | this ArrayIterator first,
494 | ArrayIterator last,
495 | ArrayIterator result
496 | )
497 | {
498 | while (last.NotEqual(first))
499 | {
500 | result = result.GetPrev();
501 | last = last.GetPrev();
502 | result.SetCurrent(last.GetCurrent());
503 | }
504 | return result;
505 | }
506 |
507 | public static ArrayIterator SwapRanges(
508 | this ArrayIterator first1,
509 | ArrayIterator last1,
510 | ArrayIterator first2
511 | )
512 | {
513 | while (first1.NotEqual(last1))
514 | {
515 | Swap(first1, first2);
516 | first1 = first1.GetNext();
517 | first2 = first2.GetNext();
518 | }
519 | return first2;
520 | }
521 |
522 | public static void Swap(this ArrayIterator a, ArrayIterator b)
523 | {
524 | var temp = a.GetCurrent();
525 | a.SetCurrent(b.GetCurrent());
526 | b.SetCurrent(temp);
527 | }
528 |
529 | public static ArrayIterator Transform(
530 | this ArrayIterator first1,
531 | ArrayIterator last1,
532 | ArrayIterator result,
533 | Func op
534 | )
535 | {
536 | while (first1.NotEqual(last1))
537 | {
538 | result.SetCurrent(op(first1.GetCurrent()));
539 | result = result.GetNext();
540 | first1 = first1.GetNext();
541 | }
542 | return result;
543 | }
544 |
545 | public static ArrayIterator Transform(
546 | this ArrayIterator first1,
547 | ArrayIterator last1,
548 | ArrayIterator first2,
549 | ArrayIterator result,
550 | Func binaryOp
551 | )
552 | {
553 | while (first1.NotEqual(last1))
554 | {
555 | result.SetCurrent(binaryOp(first1.GetCurrent(), first2.GetCurrent()));
556 | first2 = first2.GetNext();
557 | result = result.GetNext();
558 | first1 = first1.GetNext();
559 | }
560 | return result;
561 | }
562 |
563 | public static void ReplaceIf(
564 | this ArrayIterator first,
565 | ArrayIterator last,
566 | Func pred,
567 | T newValue
568 | )
569 | {
570 | while (first.NotEqual(last))
571 | {
572 | if (pred(first.GetCurrent()))
573 | {
574 | first.SetCurrent(newValue);
575 |
576 | }
577 | first = first.GetNext();
578 | }
579 | }
580 |
581 | public static ArrayIterator ReplaceCopyIf(
582 | this ArrayIterator first,
583 | ArrayIterator last,
584 | ArrayIterator result,
585 | Func pred,
586 | T newValue
587 | )
588 | {
589 | while (first.NotEqual(last))
590 | {
591 | result.SetCurrent(pred(first.GetCurrent()) ? newValue : first.GetCurrent());
592 | first = first.GetNext();
593 | result = result.GetNext();
594 | }
595 | return result;
596 | }
597 |
598 | public static ArrayIterator Unique(
599 | this ArrayIterator first,
600 | ArrayIterator last,
601 | Func pred
602 | )
603 | {
604 | if (first.IsEqual(last))
605 | {
606 | return last;
607 | }
608 |
609 | var result = first;
610 | while ((first = first.GetNext()).NotEqual(last))
611 | {
612 | if (pred(result.GetCurrent(), first.GetCurrent()) == false)
613 | {
614 | result = result.GetNext();
615 | result.SetCurrent(first.GetCurrent());
616 | }
617 | }
618 | result = result.GetNext();
619 | return result;
620 | }
621 |
622 | public static ArrayIterator UniqueCopy(
623 | this ArrayIterator first,
624 | ArrayIterator last,
625 | ArrayIterator result,
626 | Func pred
627 | )
628 | {
629 | if (first.IsEqual(last))
630 | {
631 | return last;
632 | }
633 |
634 | result.SetCurrent(first.GetCurrent());
635 | while ((first = first.GetNext()).NotEqual(last))
636 | {
637 | var val = first.GetCurrent();
638 | if (pred(result.GetCurrent(), val) == false)
639 | {
640 | result = result.GetNext();
641 | result.SetCurrent(val);
642 | }
643 | }
644 | result = result.GetNext();
645 | return result;
646 | }
647 |
648 | public static void Reverse(this ArrayIterator first, ArrayIterator last)
649 | {
650 | while ((first.NotEqual(last)) && (first.NotEqual((last = last.GetPrev()))))
651 | {
652 | first.Swap(last);
653 | first = first.GetNext();
654 | }
655 | }
656 |
657 | public static ArrayIterator ReverseCopy(
658 | this ArrayIterator first,
659 | ArrayIterator last,
660 | ArrayIterator result
661 | )
662 | {
663 | while (first.NotEqual(last))
664 | {
665 | last = last.GetPrev();
666 | result.SetCurrent(last.GetCurrent());
667 | result = result.GetNext();
668 | }
669 | return result;
670 | }
671 |
672 | public static void Rotate(
673 | this ArrayIterator first,
674 | ArrayIterator middle,
675 | ArrayIterator last
676 | )
677 | {
678 | var next = middle;
679 | while (first.NotEqual(last))
680 | {
681 | first.Swap(next);
682 | first = first.GetNext();
683 | next = next.GetNext();
684 | if (next.IsEqual(last))
685 | {
686 | next = middle;
687 | }
688 | else if (first.IsEqual(middle))
689 | {
690 | middle = next;
691 | }
692 | }
693 | }
694 |
695 | public static ArrayIterator RotateCopy(
696 | this ArrayIterator first,
697 | ArrayIterator middle,
698 | ArrayIterator last,
699 | ArrayIterator result
700 | )
701 | {
702 | result = Copy(middle, last, result);
703 | return Copy(first, middle, result);
704 | }
705 |
706 | public static void RandomShuffle(
707 | this ArrayIterator first,
708 | ArrayIterator last,
709 | Func gen
710 | )
711 | {
712 | var n = Distance(first, last);
713 | for (var i = n - 1; i > 0; --i)
714 | {
715 | first.GetAdvanced(i).Swap(first.GetAdvanced(gen(i + 1)));
716 | }
717 | }
718 |
719 | public static bool IsPartitioned(
720 | this ArrayIterator first,
721 | ArrayIterator last,
722 | Func pred
723 | )
724 | {
725 | while (first.NotEqual(last) && pred(first.GetCurrent()))
726 | {
727 | first = first.GetNext();
728 | }
729 | while (first.NotEqual(last))
730 | {
731 | if (pred(first.GetCurrent()))
732 | {
733 | return false;
734 | }
735 | first = first.GetNext();
736 | }
737 | return true;
738 | }
739 |
740 | public static ArrayIterator Partition(
741 | this ArrayIterator first,
742 | ArrayIterator last,
743 | Func pred
744 | )
745 | {
746 | while (first.NotEqual(last))
747 | {
748 | while (pred(first.GetCurrent()))
749 | {
750 | first = first.GetNext();
751 | if (first.IsEqual(last))
752 | {
753 | return first;
754 | }
755 | }
756 | do
757 | {
758 | last = last.GetPrev();
759 | if (first.IsEqual(last))
760 | {
761 | return first;
762 | }
763 | } while (pred(last.GetCurrent()) == false);
764 | first.Swap(last);
765 | first = first.GetNext();
766 | }
767 | return first;
768 | }
769 |
770 | public static void PartitionCopy(
771 | this ArrayIterator first,
772 | ArrayIterator last,
773 | ArrayIterator resultTrue,
774 | ArrayIterator resultFalse,
775 | Func pred,
776 | out ArrayIterator outResultTrue,
777 | out ArrayIterator outResultFalse
778 | )
779 | {
780 | while (first.NotEqual(last))
781 | {
782 | if (pred(first.GetCurrent()))
783 | {
784 | resultTrue.SetCurrent(first.GetCurrent());
785 | resultTrue = resultTrue.GetNext();
786 | }
787 | else
788 | {
789 | resultFalse.SetCurrent(first.GetCurrent());
790 | resultFalse = resultFalse.GetNext();
791 | }
792 | first = first.GetNext();
793 | }
794 | outResultTrue = resultTrue;
795 | outResultFalse = resultFalse;
796 | }
797 |
798 | public static ArrayIterator PartitionPoint(
799 | this ArrayIterator first,
800 | ArrayIterator last,
801 | Func pred
802 | )
803 | {
804 | var n = first.Distance(last);
805 | while (n > 0)
806 | {
807 | var it = first;
808 | var step = n / 2;
809 | it.GetAdvanced(step);
810 | if (pred(it.GetCurrent()))
811 | {
812 | first = it.GetNext();
813 | n -= step + 1;
814 | }
815 | else
816 | {
817 | n = step;
818 | }
819 | }
820 | return first;
821 | }
822 |
823 | public static void Sort(
824 | this ArrayIterator first,
825 | ArrayIterator last,
826 | Func comp
827 | )
828 | {
829 | // Quicksort
830 | if (first.IsEqual(last))
831 | {
832 | return;
833 | }
834 | var sep = first;
835 | for (var i = first.GetNext(); i.NotEqual(last); i = i.GetNext())
836 | {
837 | if (comp(i.GetCurrent(), first.GetCurrent()))
838 | {
839 | sep = sep.GetNext();
840 | sep.Swap(i);
841 | }
842 | }
843 | first.Swap(sep);
844 | first.Sort(sep, comp);
845 | sep.GetNext().Sort(last, comp);
846 | }
847 |
848 | public static void StableSort(
849 | this ArrayIterator first,
850 | ArrayIterator last,
851 | Func comp
852 | )
853 | {
854 | // TODO find a faster algorithm that doesn't create any garbage than insertion sort
855 | var arr = first.Array;
856 | for (var i = first.Index + 1; i < last.Index; i++)
857 | {
858 | var x = arr[i];
859 | var left = first.Index;
860 | var right = i - 1;
861 | while (left <= right)
862 | {
863 | var middle = (left + right) / 2;
864 | if (comp(x, arr[middle]))
865 | {
866 | right = middle - 1;
867 | }
868 | else
869 | {
870 | left = middle + 1;
871 | }
872 | }
873 | for (var j = i - 1; j >= left; j--)
874 | {
875 | arr[j + 1] = arr[j];
876 | }
877 | arr[left] = x;
878 | }
879 | }
880 |
881 | public static void PartialSort