├── 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( 882 | this ArrayIterator first, 883 | ArrayIterator middle, 884 | ArrayIterator last, 885 | Func comp 886 | ) 887 | { 888 | // TODO find a faster algorithm that doesn't create any garbage 889 | first.Sort(last, comp); 890 | } 891 | 892 | public static bool IsSorted( 893 | this ArrayIterator first, 894 | ArrayIterator last, 895 | Func comp 896 | ) 897 | { 898 | if (first.IsEqual(last)) 899 | { 900 | return true; 901 | } 902 | var next = first; 903 | while ((next = next.GetNext()).NotEqual(last)) 904 | { 905 | if (comp(next.GetCurrent(), first.GetCurrent())) 906 | { 907 | return false; 908 | } 909 | first = first.GetNext(); 910 | } 911 | return true; 912 | } 913 | 914 | public static ArrayIterator IsSortedUntil( 915 | this ArrayIterator first, 916 | ArrayIterator last, 917 | Func comp 918 | ) 919 | { 920 | if (first.IsEqual(last)) 921 | { 922 | return first; 923 | } 924 | var next = first; 925 | while ((next = next.GetNext()).NotEqual(last)) 926 | { 927 | if (comp(next.GetCurrent(), first.GetCurrent())) 928 | { 929 | return next; 930 | } 931 | first = first.GetNext(); 932 | } 933 | return last; 934 | } 935 | 936 | public static void NthElement( 937 | this ArrayIterator first, 938 | ArrayIterator nth, 939 | ArrayIterator last, 940 | Func comp 941 | ) 942 | { 943 | // TODO find a faster algorithm that doesn't create any garbage 944 | first.Sort(last, comp); 945 | } 946 | 947 | public static ArrayIterator LowerBound( 948 | this ArrayIterator first, 949 | ArrayIterator last, 950 | T val, 951 | Func comp 952 | ) 953 | { 954 | var count = first.Distance(last); 955 | while (count > 0) 956 | { 957 | var it = first; 958 | var step = count / 2; 959 | it = it.GetAdvanced(step); 960 | if (comp(it.GetCurrent(), val)) 961 | { 962 | it = it.GetNext(); 963 | first = it; 964 | count -= step + 1; 965 | } 966 | else 967 | { 968 | count = step; 969 | } 970 | } 971 | return first; 972 | } 973 | 974 | public static ArrayIterator UpperBound( 975 | this ArrayIterator first, 976 | ArrayIterator last, 977 | T val, 978 | Func comp 979 | ) 980 | { 981 | var count = Distance(first, last); 982 | while (count > 0) 983 | { 984 | var it = first; 985 | var step = count / 2; 986 | it = it.GetAdvanced(step); 987 | if (comp(val, it.GetCurrent()) == false) 988 | { 989 | it = it.GetNext(); 990 | first = it; 991 | count -= step + 1; 992 | } 993 | else 994 | { 995 | count = step; 996 | } 997 | } 998 | return first; 999 | } 1000 | 1001 | public static void EqualRange( 1002 | this ArrayIterator first, 1003 | ArrayIterator last, 1004 | T val, 1005 | Func comp, 1006 | out ArrayIterator lower, 1007 | out ArrayIterator upper 1008 | ) 1009 | { 1010 | lower = first.LowerBound(last, val, comp); 1011 | upper = lower.UpperBound(last, val, comp); 1012 | } 1013 | 1014 | public static bool BinarySearch( 1015 | this ArrayIterator first, 1016 | ArrayIterator last, 1017 | T val, 1018 | Func comp 1019 | ) 1020 | { 1021 | first = first.LowerBound(last, val, comp); 1022 | return first.NotEqual(last) && comp(val, first.GetCurrent()) == false; 1023 | } 1024 | 1025 | public static ArrayIterator Merge( 1026 | this ArrayIterator first1, 1027 | ArrayIterator last1, 1028 | ArrayIterator first2, 1029 | ArrayIterator last2, 1030 | ArrayIterator result, 1031 | Func comp 1032 | ) 1033 | { 1034 | while (true) 1035 | { 1036 | if (first1.IsEqual(last1)) 1037 | { 1038 | return first2.Copy(last2, result); 1039 | } 1040 | if (first2.IsEqual(last2)) 1041 | { 1042 | return first1.Copy(last1, result); 1043 | } 1044 | if (comp(first2.GetCurrent(), first1.GetCurrent())) 1045 | { 1046 | result.SetCurrent(first2.GetCurrent()); 1047 | first2 = first2.GetNext(); 1048 | } 1049 | else 1050 | { 1051 | result.SetCurrent(first1.GetCurrent()); 1052 | first1 = first1.GetNext(); 1053 | } 1054 | result = result.GetNext(); 1055 | } 1056 | } 1057 | 1058 | public static void InplaceMerge( 1059 | this ArrayIterator first, 1060 | ArrayIterator middle, 1061 | ArrayIterator last, 1062 | Func comp 1063 | ) 1064 | { 1065 | if (first.Index >= middle.Index || middle.Index >= last.Index) 1066 | { 1067 | return; 1068 | } 1069 | if (last.Index - first.Index == 2) 1070 | { 1071 | if (comp(middle.GetCurrent(), first.GetCurrent())) 1072 | { 1073 | Swap(first, middle); 1074 | } 1075 | return; 1076 | } 1077 | ArrayIterator firstCut; 1078 | ArrayIterator secondCut; 1079 | if (middle.Index - first.Index > last.Index - middle.Index) 1080 | { 1081 | firstCut = first.GetAdvanced(first.Distance(middle) / 2); 1082 | secondCut = middle.LowerBound(last, firstCut.GetCurrent(), comp); 1083 | } 1084 | else 1085 | { 1086 | secondCut = middle.GetAdvanced(middle.Distance(last) / 2); 1087 | firstCut = first.UpperBound(middle, secondCut.GetCurrent(), comp); 1088 | } 1089 | Rotate(firstCut, middle, secondCut); 1090 | middle = firstCut.GetAdvanced(middle.Distance(secondCut)); 1091 | InplaceMerge(first, firstCut, middle, comp); 1092 | InplaceMerge(middle, secondCut, last, comp); 1093 | } 1094 | 1095 | public static bool Includes( 1096 | this ArrayIterator first1, 1097 | ArrayIterator last1, 1098 | ArrayIterator first2, 1099 | ArrayIterator last2, 1100 | Func comp 1101 | ) 1102 | { 1103 | while (first2.NotEqual(last2)) 1104 | { 1105 | if ((first1.IsEqual(last1)) || comp(first2.GetCurrent(), first1.GetCurrent())) 1106 | { 1107 | return false; 1108 | } 1109 | if (comp(first1.GetCurrent(), first2.GetCurrent()) == false) 1110 | { 1111 | first2 = first2.GetNext(); 1112 | } 1113 | first1 = first1.GetNext(); 1114 | } 1115 | return true; 1116 | } 1117 | 1118 | public static ArrayIterator SetUnion( 1119 | this ArrayIterator first1, 1120 | ArrayIterator last1, 1121 | ArrayIterator first2, 1122 | ArrayIterator last2, 1123 | ArrayIterator result, 1124 | Func comp 1125 | ) 1126 | { 1127 | while (true) 1128 | { 1129 | if (first1.IsEqual(last1)) 1130 | { 1131 | return first2.Copy(last2, result); 1132 | } 1133 | if (first2.IsEqual(last2)) 1134 | { 1135 | return first1.Copy(last1, result); 1136 | } 1137 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1138 | { 1139 | result.SetCurrent(first1.GetCurrent()); 1140 | first1 = first1.GetNext(); 1141 | } 1142 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1143 | { 1144 | result.SetCurrent(first2.GetCurrent()); 1145 | first2 = first2.GetNext(); 1146 | } 1147 | else 1148 | { 1149 | result.SetCurrent(first1.GetCurrent()); 1150 | first1 = first1.GetNext(); 1151 | first2 = first2.GetNext(); 1152 | } 1153 | result = result.GetNext(); 1154 | } 1155 | } 1156 | 1157 | public static ArrayIterator SetIntersection( 1158 | this ArrayIterator first1, 1159 | ArrayIterator last1, 1160 | ArrayIterator first2, 1161 | ArrayIterator last2, 1162 | ArrayIterator result, 1163 | Func comp 1164 | ) 1165 | { 1166 | while (first1.NotEqual(last1) && first2.NotEqual(last2)) 1167 | { 1168 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1169 | { 1170 | first1 = first1.GetNext(); 1171 | } 1172 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1173 | { 1174 | first2 = first2.GetNext(); 1175 | } 1176 | else 1177 | { 1178 | result.SetCurrent(first1.GetCurrent()); 1179 | result = result.GetNext(); 1180 | first1 = first1.GetNext(); 1181 | first2 = first2.GetNext(); 1182 | } 1183 | } 1184 | return result; 1185 | } 1186 | 1187 | public static ArrayIterator SetDifference( 1188 | this ArrayIterator first1, 1189 | ArrayIterator last1, 1190 | ArrayIterator first2, 1191 | ArrayIterator last2, 1192 | ArrayIterator result, 1193 | Func comp 1194 | ) 1195 | { 1196 | while (first1.NotEqual(last1) && first2.NotEqual(last2)) 1197 | { 1198 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1199 | { 1200 | result.SetCurrent(first1.GetCurrent()); 1201 | result = result.GetNext(); 1202 | first1 = first1.GetNext(); 1203 | } 1204 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1205 | { 1206 | first2 = first2.GetNext(); 1207 | } 1208 | else 1209 | { 1210 | first1 = first1.GetNext(); 1211 | first2 = first2.GetNext(); 1212 | } 1213 | } 1214 | return first1.Copy(last1, result); 1215 | } 1216 | 1217 | public static ArrayIterator SetSymmetricDifference( 1218 | this ArrayIterator first1, 1219 | ArrayIterator last1, 1220 | ArrayIterator first2, 1221 | ArrayIterator last2, 1222 | ArrayIterator result, 1223 | Func comp 1224 | ) 1225 | { 1226 | while (true) 1227 | { 1228 | if (first1.IsEqual(last1)) 1229 | { 1230 | return first2.Copy(last2, result); 1231 | } 1232 | if (first2.IsEqual(last2)) 1233 | { 1234 | return first1.Copy(last1, result); 1235 | } 1236 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1237 | { 1238 | result.SetCurrent(first1.GetCurrent()); 1239 | result = result.GetNext(); 1240 | first1 = first1.GetNext(); 1241 | } 1242 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1243 | { 1244 | result.SetCurrent(first2.GetCurrent()); 1245 | result = result.GetNext(); 1246 | first2 = first2.GetNext(); 1247 | } 1248 | else 1249 | { 1250 | first1 = first1.GetNext(); 1251 | first2 = first2.GetNext(); 1252 | } 1253 | } 1254 | } 1255 | 1256 | public static void PushHeap( 1257 | this ArrayIterator first, 1258 | ArrayIterator last, 1259 | Func comp 1260 | ) 1261 | { 1262 | if (first.Distance(last) < 2) 1263 | { 1264 | return; 1265 | } 1266 | last = last.GetPrev(); 1267 | var temp = last.GetCurrent(); 1268 | var parent = first.GetAdvanced((first.Distance(last) - 1) / 2); 1269 | while (first.Distance(last) > 0 && comp(parent.GetCurrent(), temp)) 1270 | { 1271 | last.SetCurrent(parent.GetCurrent()); 1272 | last = parent; 1273 | parent = first.GetAdvanced((first.Distance(last) - 1) / 2); 1274 | } 1275 | last.SetCurrent(temp); 1276 | } 1277 | 1278 | public static void PopHeap( 1279 | this ArrayIterator first, 1280 | ArrayIterator last, 1281 | Func comp 1282 | ) 1283 | { 1284 | if (first.Distance(last) < 2) 1285 | { 1286 | return; 1287 | } 1288 | last = last.GetPrev(); 1289 | Swap(first, last); 1290 | AdjustHeap(first.Array, first.Index, first.Index, last.Index, comp); 1291 | } 1292 | 1293 | public static void MakeHeap( 1294 | this ArrayIterator first, 1295 | ArrayIterator last, 1296 | Func comp 1297 | ) 1298 | { 1299 | var dist = first.Distance(last); 1300 | if (dist < 2) 1301 | { 1302 | return; 1303 | } 1304 | var parent = (dist - 2) / 2; 1305 | do 1306 | { 1307 | AdjustHeap(first.Array, first.Index, first.Index + parent, last.Index, comp); 1308 | } 1309 | while (parent-- != 0); 1310 | } 1311 | 1312 | public static void SortHeap( 1313 | this ArrayIterator first, 1314 | ArrayIterator last, 1315 | Func comp 1316 | ) 1317 | { 1318 | while (first.Distance(last) > 1) 1319 | { 1320 | last = last.GetPrev(); 1321 | Swap(first, last); 1322 | AdjustHeap(first.Array, first.Index, first.Index, last.Index, comp); 1323 | } 1324 | } 1325 | 1326 | public static ArrayIterator MinElement( 1327 | this ArrayIterator first, 1328 | ArrayIterator last, 1329 | Func comp 1330 | ) 1331 | { 1332 | if (first.IsEqual(last)) 1333 | { 1334 | return last; 1335 | } 1336 | var smallest = first; 1337 | while ((first = first.GetNext()).NotEqual(last)) 1338 | { 1339 | if (comp(first.GetCurrent(), smallest.GetCurrent())) 1340 | { 1341 | smallest = first; 1342 | } 1343 | } 1344 | return smallest; 1345 | } 1346 | 1347 | public static ArrayIterator MaxElement( 1348 | this ArrayIterator first, 1349 | ArrayIterator last, 1350 | Func comp 1351 | ) 1352 | { 1353 | if (first.IsEqual(last)) 1354 | { 1355 | return last; 1356 | } 1357 | var largest = first; 1358 | while ((first = first.GetNext()).NotEqual(last)) 1359 | { 1360 | if (comp(largest.GetCurrent(), first.GetCurrent())) 1361 | { 1362 | largest = first; 1363 | } 1364 | } 1365 | return largest; 1366 | } 1367 | 1368 | public static void MinMaxElement( 1369 | this ArrayIterator first, 1370 | ArrayIterator last, 1371 | Func comp, 1372 | out ArrayIterator min, 1373 | out ArrayIterator max 1374 | ) 1375 | { 1376 | if (first.IsEqual(last)) 1377 | { 1378 | min = last; 1379 | max = last; 1380 | } 1381 | min = first; 1382 | max = first; 1383 | while ((first = first.GetNext()).NotEqual(last)) 1384 | { 1385 | if (comp(first.GetCurrent(), min.GetCurrent())) 1386 | { 1387 | min = first; 1388 | } 1389 | if (comp(max.GetCurrent(), first.GetCurrent())) 1390 | { 1391 | max = first; 1392 | } 1393 | } 1394 | } 1395 | 1396 | public static bool LexicographicalCompare( 1397 | this ArrayIterator first1, 1398 | ArrayIterator last1, 1399 | ArrayIterator first2, 1400 | ArrayIterator last2, 1401 | Func comp 1402 | ) 1403 | { 1404 | while (first1.NotEqual(last1)) 1405 | { 1406 | if (first2.IsEqual(last2) || comp(first2.GetCurrent(), first1.GetCurrent())) 1407 | { 1408 | return false; 1409 | } 1410 | else if (comp(first1.GetCurrent(), first2.GetCurrent())) 1411 | { 1412 | return true; 1413 | } 1414 | first1 = first1.GetNext(); 1415 | first2 = first2.GetNext(); 1416 | } 1417 | return first2.NotEqual(last2); 1418 | } 1419 | 1420 | public static bool NextPermutation( 1421 | this ArrayIterator first, 1422 | ArrayIterator last, 1423 | Func comp 1424 | ) 1425 | { 1426 | var i = last; 1427 | if (first.IsEqual(last) || first.IsEqual((i = i.GetPrev()))) 1428 | { 1429 | return false; 1430 | } 1431 | while (true) 1432 | { 1433 | var ip1 = i; 1434 | if (comp((i = i.GetPrev()).GetCurrent(), ip1.GetCurrent())) 1435 | { 1436 | var j = last; 1437 | while (comp(i.GetCurrent(), (j = j.GetPrev()).GetCurrent()) == false) 1438 | { 1439 | } 1440 | Swap(i, j); 1441 | Reverse(ip1, last); 1442 | return true; 1443 | } 1444 | if (i.IsEqual(first)) 1445 | { 1446 | Reverse(first, last); 1447 | return false; 1448 | } 1449 | } 1450 | } 1451 | 1452 | public static bool PrevPermutation( 1453 | this ArrayIterator first, 1454 | ArrayIterator last, 1455 | Func comp 1456 | ) 1457 | { 1458 | var i = last; 1459 | if (first.IsEqual(last) || first.IsEqual(i = i.GetPrev())) 1460 | { 1461 | return false; 1462 | } 1463 | while (true) 1464 | { 1465 | var ip1 = i; 1466 | if (comp(ip1.GetCurrent(), (i = i.GetPrev()).GetCurrent())) 1467 | { 1468 | var j = last; 1469 | while (comp((j = j.GetPrev()).GetCurrent(), i.GetCurrent()) == false) 1470 | { 1471 | } 1472 | Swap(i, j); 1473 | Reverse(ip1, last); 1474 | return true; 1475 | } 1476 | if (i.IsEqual(first)) 1477 | { 1478 | Reverse(first, last); 1479 | return false; 1480 | } 1481 | } 1482 | } 1483 | 1484 | private static void AdjustHeap( 1485 | this T[] array, 1486 | int first, 1487 | int position, 1488 | int last, 1489 | Func comp 1490 | ) 1491 | { 1492 | var tmp = array[position]; 1493 | int len = last - first; 1494 | int holeIndex = position - first; 1495 | int secondChild = 2 * holeIndex + 2; 1496 | while (secondChild < len) 1497 | { 1498 | if ( 1499 | comp( 1500 | array[first + secondChild], 1501 | array[first + (secondChild - 1)] 1502 | ) 1503 | ) 1504 | { 1505 | --secondChild; 1506 | } 1507 | array[first + holeIndex] = array[first + secondChild]; 1508 | holeIndex = secondChild++; 1509 | secondChild *= 2; 1510 | } 1511 | if (secondChild-- == len) 1512 | { 1513 | array[first + holeIndex] = array[first + secondChild]; 1514 | holeIndex = secondChild; 1515 | } 1516 | var parent = (holeIndex - 1) / 2; 1517 | var topIndex = position - first; 1518 | while (holeIndex != topIndex && comp(array[first + parent], tmp)) 1519 | { 1520 | array[first + holeIndex] = array[first + parent]; 1521 | holeIndex = parent; 1522 | parent = (holeIndex - 1) / 2; 1523 | } 1524 | array[first + holeIndex] = tmp; 1525 | } 1526 | 1527 | public static bool IsHeap( 1528 | this ArrayIterator first, 1529 | ArrayIterator last, 1530 | Func comp 1531 | ) 1532 | { 1533 | return first.IsHeapUntil(last, comp).IsEqual(last); 1534 | } 1535 | 1536 | public static ArrayIterator IsHeapUntil( 1537 | this ArrayIterator first, 1538 | ArrayIterator last, 1539 | Func comp 1540 | ) 1541 | { 1542 | var len = first.Distance(last); 1543 | var p = 0; 1544 | var c = 1; 1545 | var pp = first; 1546 | while (c < len) 1547 | { 1548 | var cp = first.GetAdvanced(c); 1549 | if (comp(pp.GetCurrent(), cp.GetCurrent())) 1550 | { 1551 | return cp; 1552 | } 1553 | c++; 1554 | cp = cp.GetNext(); 1555 | if (c == len) 1556 | { 1557 | return last; 1558 | } 1559 | if (comp(pp.GetCurrent(), cp.GetCurrent())) 1560 | { 1561 | return cp; 1562 | } 1563 | p++; 1564 | pp = pp.GetNext(); 1565 | c = 2 * p + 1; 1566 | } 1567 | return last; 1568 | } 1569 | } 1570 | } -------------------------------------------------------------------------------- /JacksonDunstanIterator/ArrayIterator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee22ec83864a44a27a702c3f69283700 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/JacksonDunstanIterator.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JacksonDunstanIterator", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": true 8 | } -------------------------------------------------------------------------------- /JacksonDunstanIterator/JacksonDunstanIterator.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4d5f9841e34c64cc39b088281a63565b 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/ListIterator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt. 4 | // 5 | //----------------------------------------------------------------------- 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace JacksonDunstanIterator 11 | { 12 | public struct ListIterator 13 | { 14 | public IList List; 15 | public int Index; 16 | } 17 | 18 | public static class ListIteratorExtensions 19 | { 20 | public static ListIterator Begin(this IList list) 21 | { 22 | return new ListIterator { List = list }; 23 | } 24 | 25 | public static ListIterator End(this IList list) 26 | { 27 | return new ListIterator { List = list, Index = list.Count }; 28 | } 29 | 30 | public static ListIterator IteratorAt(this IList list, int index) 31 | { 32 | return new ListIterator { List = list, Index = index }; 33 | } 34 | 35 | public static T GetCurrent(this ListIterator it) 36 | { 37 | return it.List[it.Index]; 38 | } 39 | 40 | public static void SetCurrent(this ListIterator it, T val) 41 | { 42 | it.List[it.Index] = val; 43 | } 44 | 45 | public static ListIterator GetNext(this ListIterator it) 46 | { 47 | it.Index++; 48 | return it; 49 | } 50 | 51 | public static ListIterator GetPrev(this ListIterator it) 52 | { 53 | it.Index--; 54 | return it; 55 | } 56 | 57 | public static bool IsEqual(this ListIterator it, ListIterator other) 58 | { 59 | return it.List == other.List && it.Index == other.Index; 60 | } 61 | 62 | public static bool NotEqual(this ListIterator it, ListIterator other) 63 | { 64 | return it.List != other.List || it.Index != other.Index; 65 | } 66 | 67 | public static ListIterator GetAdvanced(this ListIterator it, int distance) 68 | { 69 | return new ListIterator { List = it.List, Index = it.Index + distance }; 70 | } 71 | 72 | public static int Distance(this ListIterator first, ListIterator last) 73 | { 74 | return last.Index - first.Index; 75 | } 76 | 77 | public static bool AllOf( 78 | this ListIterator first, 79 | ListIterator last, 80 | Func pred 81 | ) 82 | { 83 | while (first.NotEqual(last)) 84 | { 85 | if (pred(first.GetCurrent()) == false) 86 | { 87 | return false; 88 | } 89 | first = first.GetNext(); 90 | } 91 | return true; 92 | } 93 | 94 | public static bool AnyOf( 95 | this ListIterator first, 96 | ListIterator last, 97 | Func pred 98 | ) 99 | { 100 | while (first.NotEqual(last)) 101 | { 102 | if (pred(first.GetCurrent())) 103 | { 104 | return true; 105 | } 106 | first = first.GetNext(); 107 | } 108 | return false; 109 | } 110 | 111 | public static bool NoneOf( 112 | this ListIterator first, 113 | ListIterator last, 114 | Func pred 115 | ) 116 | { 117 | while (first.NotEqual(last)) 118 | { 119 | if (pred(first.GetCurrent())) 120 | { 121 | return false; 122 | } 123 | first = first.GetNext(); 124 | } 125 | return true; 126 | } 127 | 128 | public static void ForEach( 129 | this ListIterator first, 130 | ListIterator last, 131 | Action callback 132 | ) 133 | { 134 | while (first.NotEqual(last)) 135 | { 136 | callback(first.GetCurrent()); 137 | first = first.GetNext(); 138 | } 139 | } 140 | 141 | public static ListIterator Find( 142 | this ListIterator first, 143 | ListIterator last, 144 | T val, 145 | Func pred 146 | ) 147 | { 148 | while (first.NotEqual(last)) 149 | { 150 | if (pred(first.GetCurrent(), val)) 151 | { 152 | return first; 153 | } 154 | first = first.GetNext(); 155 | } 156 | return last; 157 | } 158 | 159 | public static ListIterator FindIf( 160 | this ListIterator first, 161 | ListIterator last, 162 | Func pred 163 | ) 164 | { 165 | while (first.NotEqual(last)) 166 | { 167 | if (pred(first.GetCurrent())) 168 | { 169 | return first; 170 | } 171 | first = first.GetNext(); 172 | } 173 | return last; 174 | } 175 | 176 | public static ListIterator FindIfNot( 177 | this ListIterator first, 178 | ListIterator last, 179 | Func pred 180 | ) 181 | { 182 | while (first.NotEqual(last)) 183 | { 184 | if (pred(first.GetCurrent()) == false) 185 | { 186 | return first; 187 | } 188 | first = first.GetNext(); 189 | } 190 | return last; 191 | } 192 | 193 | public static ListIterator FindEnd( 194 | this ListIterator first1, 195 | ListIterator last1, 196 | ListIterator first2, 197 | ListIterator last2, 198 | Func pred 199 | ) 200 | { 201 | if (first2.IsEqual(last2)) 202 | { 203 | return last1; 204 | } 205 | var ret = last1; 206 | while (first1.NotEqual(last1)) 207 | { 208 | var it1 = first1; 209 | var it2 = first2; 210 | while (pred(it1.GetCurrent(), it2.GetCurrent())) 211 | { 212 | it1 = it1.GetNext(); 213 | it2 = it2.GetNext(); 214 | if (it2.IsEqual(last2)) 215 | { 216 | ret = first1; 217 | break; 218 | } 219 | if (it1.IsEqual(last1)) 220 | { 221 | return ret; 222 | } 223 | } 224 | first1 = first1.GetNext(); 225 | } 226 | return ret; 227 | } 228 | 229 | public static ListIterator FindFirstOf( 230 | this ListIterator first1, 231 | ListIterator last1, 232 | ListIterator first2, 233 | ListIterator last2, 234 | Func pred 235 | ) 236 | { 237 | while (first1.NotEqual(last1)) 238 | { 239 | for (var it = first2; it.NotEqual(last2); it = it.GetNext()) 240 | { 241 | if (pred(it.GetCurrent(), first1.GetCurrent())) 242 | { 243 | return first1; 244 | } 245 | } 246 | first1 = first1.GetNext(); 247 | } 248 | return last1; 249 | } 250 | 251 | public static ListIterator AdjacentFind( 252 | this ListIterator first, 253 | ListIterator last, 254 | Func pred 255 | ) 256 | { 257 | if (first.NotEqual(last)) 258 | { 259 | var next = first; 260 | next = next.GetNext(); 261 | while (next.NotEqual(last)) 262 | { 263 | if (pred(first.GetCurrent(), next.GetCurrent())) 264 | { 265 | return first; 266 | } 267 | first = first.GetNext(); 268 | next = next.GetNext(); 269 | } 270 | } 271 | return last; 272 | } 273 | 274 | public static int Count( 275 | this ListIterator first, 276 | ListIterator last, 277 | T val, 278 | Func pred 279 | ) 280 | { 281 | var count = 0; 282 | while (first.NotEqual(last)) 283 | { 284 | if (pred(first.GetCurrent(), val)) 285 | { 286 | count++; 287 | } 288 | first = first.GetNext(); 289 | } 290 | return count; 291 | } 292 | 293 | public static int CountIf( 294 | this ListIterator first, 295 | ListIterator last, 296 | Func pred 297 | ) 298 | { 299 | var count = 0; 300 | while (first.NotEqual(last)) 301 | { 302 | if (pred(first.GetCurrent())) 303 | { 304 | count++; 305 | } 306 | first = first.GetNext(); 307 | } 308 | return count; 309 | } 310 | 311 | public static void Mismatch( 312 | this ListIterator first1, 313 | ListIterator last1, 314 | ListIterator first2, 315 | Func pred, 316 | out ListIterator mismatch1, 317 | out ListIterator mismatch2 318 | ) 319 | { 320 | while (first1.NotEqual(last1)) 321 | { 322 | if (pred(first1.GetCurrent(), first2.GetCurrent()) == false) 323 | { 324 | break; 325 | } 326 | first1 = first1.GetNext(); 327 | first2 = first2.GetNext(); 328 | } 329 | mismatch1 = first1; 330 | mismatch2 = first2; 331 | } 332 | 333 | public static bool Equal( 334 | this ListIterator first1, 335 | ListIterator last1, 336 | ListIterator first2, 337 | Func pred 338 | ) 339 | { 340 | while (first1.NotEqual(last1)) 341 | { 342 | if (pred(first1.GetCurrent(), first2.GetCurrent()) == false) 343 | { 344 | return false; 345 | } 346 | first1 = first1.GetNext(); 347 | first2 = first2.GetNext(); 348 | } 349 | return true; 350 | } 351 | 352 | public static bool IsPermutation( 353 | this ListIterator first1, 354 | ListIterator last1, 355 | ListIterator first2, 356 | Func pred 357 | ) 358 | { 359 | first1.Mismatch(last1, first2, pred, out first1, out first2); 360 | if (first1.IsEqual(last1)) 361 | { 362 | return true; 363 | } 364 | var last2 = first2; 365 | last2 = last2.GetAdvanced(first1.Distance(last1)); 366 | for (var it1 = first1; it1.NotEqual(last1); it1 = it1.GetNext()) 367 | { 368 | if (first1.Find(it1, it1.GetCurrent(), pred).IsEqual(it1)) 369 | { 370 | var n = first2.Count(last2, it1.GetCurrent(), pred); 371 | if (n == 0 || it1.Count(last1, it1.GetCurrent(), pred) != n) 372 | { 373 | return false; 374 | } 375 | } 376 | } 377 | return true; 378 | } 379 | 380 | public static ListIterator Search( 381 | this ListIterator first1, 382 | ListIterator last1, 383 | ListIterator first2, 384 | ListIterator last2, 385 | Func pred 386 | ) 387 | { 388 | if (first2.IsEqual(last2)) 389 | { 390 | return first1; 391 | } 392 | 393 | while (first1.NotEqual(last1)) 394 | { 395 | var it1 = first1; 396 | var it2 = first2; 397 | while (pred(it1.GetCurrent(), it2.GetCurrent())) 398 | { 399 | it1 = it1.GetNext(); 400 | it2 = it2.GetNext(); 401 | if (it2.IsEqual(last2)) 402 | { 403 | return first1; 404 | } 405 | if (it1.IsEqual(last1)) 406 | { 407 | return last1; 408 | } 409 | } 410 | first1 = first1.GetNext(); 411 | } 412 | return last1; 413 | } 414 | 415 | public static ListIterator SearchN( 416 | this ListIterator first, 417 | ListIterator last, 418 | int count, 419 | T val, 420 | Func pred 421 | ) 422 | { 423 | var limit = first.GetAdvanced(first.Distance(last) - count); 424 | while (first.NotEqual(limit)) 425 | { 426 | var it = first; 427 | var i = 0; 428 | while (pred(val, it.GetCurrent())) 429 | { 430 | it = it.GetNext(); 431 | if (++i == count) 432 | { 433 | return first; 434 | } 435 | } 436 | first = first.GetNext(); 437 | } 438 | return last; 439 | } 440 | 441 | public static ListIterator Copy( 442 | this ListIterator first, 443 | ListIterator last, 444 | ListIterator result 445 | ) 446 | { 447 | while (first.NotEqual(last)) 448 | { 449 | result.SetCurrent(first.GetCurrent()); 450 | result = result.GetNext(); 451 | first = first.GetNext(); 452 | } 453 | return result; 454 | } 455 | 456 | public static ListIterator CopyN( 457 | this ListIterator first, 458 | int n, 459 | ListIterator result 460 | ) 461 | { 462 | while (n > 0) 463 | { 464 | result.SetCurrent(first.GetCurrent()); 465 | result = result.GetNext(); 466 | first = first.GetNext(); 467 | n--; 468 | } 469 | return result; 470 | } 471 | 472 | public static ListIterator CopyIf( 473 | this ListIterator first, 474 | ListIterator last, 475 | ListIterator result, 476 | Func pred 477 | ) 478 | { 479 | while (first.NotEqual(last)) 480 | { 481 | if (pred(first.GetCurrent())) 482 | { 483 | result.SetCurrent(first.GetCurrent()); 484 | result = result.GetNext(); 485 | } 486 | first = first.GetNext(); 487 | } 488 | return result; 489 | } 490 | 491 | public static ListIterator CopyBackward( 492 | this ListIterator first, 493 | ListIterator last, 494 | ListIterator result 495 | ) 496 | { 497 | while (last.NotEqual(first)) 498 | { 499 | result = result.GetPrev(); 500 | last = last.GetPrev(); 501 | result.SetCurrent(last.GetCurrent()); 502 | } 503 | return result; 504 | } 505 | 506 | public static ListIterator SwapRanges( 507 | this ListIterator first1, 508 | ListIterator last1, 509 | ListIterator first2 510 | ) 511 | { 512 | while (first1.NotEqual(last1)) 513 | { 514 | Swap(first1, first2); 515 | first1 = first1.GetNext(); 516 | first2 = first2.GetNext(); 517 | } 518 | return first2; 519 | } 520 | 521 | public static void Swap(this ListIterator a, ListIterator b) 522 | { 523 | var temp = a.GetCurrent(); 524 | a.SetCurrent(b.GetCurrent()); 525 | b.SetCurrent(temp); 526 | } 527 | 528 | public static ListIterator Transform( 529 | this ListIterator first1, 530 | ListIterator last1, 531 | ListIterator result, 532 | Func op 533 | ) 534 | { 535 | while (first1.NotEqual(last1)) 536 | { 537 | result.SetCurrent(op(first1.GetCurrent())); 538 | result = result.GetNext(); 539 | first1 = first1.GetNext(); 540 | } 541 | return result; 542 | } 543 | 544 | public static ListIterator Transform( 545 | this ListIterator first1, 546 | ListIterator last1, 547 | ListIterator first2, 548 | ListIterator result, 549 | Func binaryOp 550 | ) 551 | { 552 | while (first1.NotEqual(last1)) 553 | { 554 | result.SetCurrent(binaryOp(first1.GetCurrent(), first2.GetCurrent())); 555 | first2 = first2.GetNext(); 556 | result = result.GetNext(); 557 | first1 = first1.GetNext(); 558 | } 559 | return result; 560 | } 561 | 562 | public static void ReplaceIf( 563 | this ListIterator first, 564 | ListIterator last, 565 | Func pred, 566 | T newValue 567 | ) 568 | { 569 | while (first.NotEqual(last)) 570 | { 571 | if (pred(first.GetCurrent())) 572 | { 573 | first.SetCurrent(newValue); 574 | 575 | } 576 | first = first.GetNext(); 577 | } 578 | } 579 | 580 | public static ListIterator ReplaceCopyIf( 581 | this ListIterator first, 582 | ListIterator last, 583 | ListIterator result, 584 | Func pred, 585 | T newValue 586 | ) 587 | { 588 | while (first.NotEqual(last)) 589 | { 590 | result.SetCurrent(pred(first.GetCurrent()) ? newValue : first.GetCurrent()); 591 | first = first.GetNext(); 592 | result = result.GetNext(); 593 | } 594 | return result; 595 | } 596 | 597 | public static ListIterator Unique( 598 | this ListIterator first, 599 | ListIterator last, 600 | Func pred 601 | ) 602 | { 603 | if (first.IsEqual(last)) 604 | { 605 | return last; 606 | } 607 | 608 | var result = first; 609 | while ((first = first.GetNext()).NotEqual(last)) 610 | { 611 | if (pred(result.GetCurrent(), first.GetCurrent()) == false) 612 | { 613 | result = result.GetNext(); 614 | result.SetCurrent(first.GetCurrent()); 615 | } 616 | } 617 | result = result.GetNext(); 618 | return result; 619 | } 620 | 621 | public static ListIterator UniqueCopy( 622 | this ListIterator first, 623 | ListIterator last, 624 | ListIterator result, 625 | Func pred 626 | ) 627 | { 628 | if (first.IsEqual(last)) 629 | { 630 | return last; 631 | } 632 | 633 | result.SetCurrent(first.GetCurrent()); 634 | while ((first = first.GetNext()).NotEqual(last)) 635 | { 636 | var val = first.GetCurrent(); 637 | if (pred(result.GetCurrent(), val) == false) 638 | { 639 | result = result.GetNext(); 640 | result.SetCurrent(val); 641 | } 642 | } 643 | result = result.GetNext(); 644 | return result; 645 | } 646 | 647 | public static void Reverse(this ListIterator first, ListIterator last) 648 | { 649 | while ((first.NotEqual(last)) && (first.NotEqual((last = last.GetPrev())))) 650 | { 651 | first.Swap(last); 652 | first = first.GetNext(); 653 | } 654 | } 655 | 656 | public static ListIterator ReverseCopy( 657 | this ListIterator first, 658 | ListIterator last, 659 | ListIterator result 660 | ) 661 | { 662 | while (first.NotEqual(last)) 663 | { 664 | last = last.GetPrev(); 665 | result.SetCurrent(last.GetCurrent()); 666 | result = result.GetNext(); 667 | } 668 | return result; 669 | } 670 | 671 | public static void Rotate( 672 | this ListIterator first, 673 | ListIterator middle, 674 | ListIterator last 675 | ) 676 | { 677 | var next = middle; 678 | while (first.NotEqual(last)) 679 | { 680 | first.Swap(next); 681 | first = first.GetNext(); 682 | next = next.GetNext(); 683 | if (next.IsEqual(last)) 684 | { 685 | next = middle; 686 | } 687 | else if (first.IsEqual(middle)) 688 | { 689 | middle = next; 690 | } 691 | } 692 | } 693 | 694 | public static ListIterator RotateCopy( 695 | this ListIterator first, 696 | ListIterator middle, 697 | ListIterator last, 698 | ListIterator result 699 | ) 700 | { 701 | result = Copy(middle, last, result); 702 | return Copy(first, middle, result); 703 | } 704 | 705 | public static void RandomShuffle( 706 | this ListIterator first, 707 | ListIterator last, 708 | Func gen 709 | ) 710 | { 711 | var n = Distance(first, last); 712 | for (var i = n - 1; i > 0; --i) 713 | { 714 | first.GetAdvanced(i).Swap(first.GetAdvanced(gen(i + 1))); 715 | } 716 | } 717 | 718 | public static bool IsPartitioned( 719 | this ListIterator first, 720 | ListIterator last, 721 | Func pred 722 | ) 723 | { 724 | while (first.NotEqual(last) && pred(first.GetCurrent())) 725 | { 726 | first = first.GetNext(); 727 | } 728 | while (first.NotEqual(last)) 729 | { 730 | if (pred(first.GetCurrent())) 731 | { 732 | return false; 733 | } 734 | first = first.GetNext(); 735 | } 736 | return true; 737 | } 738 | 739 | public static ListIterator Partition( 740 | this ListIterator first, 741 | ListIterator last, 742 | Func pred 743 | ) 744 | { 745 | while (first.NotEqual(last)) 746 | { 747 | while (pred(first.GetCurrent())) 748 | { 749 | first = first.GetNext(); 750 | if (first.IsEqual(last)) 751 | { 752 | return first; 753 | } 754 | } 755 | do 756 | { 757 | last = last.GetPrev(); 758 | if (first.IsEqual(last)) 759 | { 760 | return first; 761 | } 762 | } while (pred(last.GetCurrent()) == false); 763 | first.Swap(last); 764 | first = first.GetNext(); 765 | } 766 | return first; 767 | } 768 | 769 | public static void PartitionCopy( 770 | this ListIterator first, 771 | ListIterator last, 772 | ListIterator resultTrue, 773 | ListIterator resultFalse, 774 | Func pred, 775 | out ListIterator outResultTrue, 776 | out ListIterator outResultFalse 777 | ) 778 | { 779 | while (first.NotEqual(last)) 780 | { 781 | if (pred(first.GetCurrent())) 782 | { 783 | resultTrue.SetCurrent(first.GetCurrent()); 784 | resultTrue = resultTrue.GetNext(); 785 | } 786 | else 787 | { 788 | resultFalse.SetCurrent(first.GetCurrent()); 789 | resultFalse = resultFalse.GetNext(); 790 | } 791 | first = first.GetNext(); 792 | } 793 | outResultTrue = resultTrue; 794 | outResultFalse = resultFalse; 795 | } 796 | 797 | public static ListIterator PartitionPoint( 798 | this ListIterator first, 799 | ListIterator last, 800 | Func pred 801 | ) 802 | { 803 | var n = first.Distance(last); 804 | while (n > 0) 805 | { 806 | var it = first; 807 | var step = n / 2; 808 | it.GetAdvanced(step); 809 | if (pred(it.GetCurrent())) 810 | { 811 | first = it.GetNext(); 812 | n -= step + 1; 813 | } 814 | else 815 | { 816 | n = step; 817 | } 818 | } 819 | return first; 820 | } 821 | 822 | public static void Sort( 823 | this ListIterator first, 824 | ListIterator last, 825 | Func comp 826 | ) 827 | { 828 | // Quicksort 829 | if (first.IsEqual(last)) 830 | { 831 | return; 832 | } 833 | var sep = first; 834 | for (var i = first.GetNext(); i.NotEqual(last); i = i.GetNext()) 835 | { 836 | if (comp(i.GetCurrent(), first.GetCurrent())) 837 | { 838 | sep = sep.GetNext(); 839 | sep.Swap(i); 840 | } 841 | } 842 | first.Swap(sep); 843 | first.Sort(sep, comp); 844 | sep.GetNext().Sort(last, comp); 845 | } 846 | 847 | public static void StableSort( 848 | this ListIterator first, 849 | ListIterator last, 850 | Func comp 851 | ) 852 | { 853 | // TODO find a faster algorithm that doesn't create any garbage than insertion sort 854 | var arr = first.List; 855 | for (var i = first.Index + 1; i < last.Index; i++) 856 | { 857 | var x = arr[i]; 858 | var left = first.Index; 859 | var right = i - 1; 860 | while (left <= right) 861 | { 862 | var middle = (left + right) / 2; 863 | if (comp(x, arr[middle])) 864 | { 865 | right = middle - 1; 866 | } 867 | else 868 | { 869 | left = middle + 1; 870 | } 871 | } 872 | for (var j = i - 1; j >= left; j--) 873 | { 874 | arr[j + 1] = arr[j]; 875 | } 876 | arr[left] = x; 877 | } 878 | } 879 | 880 | public static void PartialSort( 881 | this ListIterator first, 882 | ListIterator middle, 883 | ListIterator last, 884 | Func comp 885 | ) 886 | { 887 | // TODO find a faster algorithm that doesn't create any garbage 888 | first.Sort(last, comp); 889 | } 890 | 891 | public static bool IsSorted( 892 | this ListIterator first, 893 | ListIterator last, 894 | Func comp 895 | ) 896 | { 897 | if (first.IsEqual(last)) 898 | { 899 | return true; 900 | } 901 | var next = first; 902 | while ((next = next.GetNext()).NotEqual(last)) 903 | { 904 | if (comp(next.GetCurrent(), first.GetCurrent())) 905 | { 906 | return false; 907 | } 908 | first = first.GetNext(); 909 | } 910 | return true; 911 | } 912 | 913 | public static ListIterator IsSortedUntil( 914 | this ListIterator first, 915 | ListIterator last, 916 | Func comp 917 | ) 918 | { 919 | if (first.IsEqual(last)) 920 | { 921 | return first; 922 | } 923 | var next = first; 924 | while ((next = next.GetNext()).NotEqual(last)) 925 | { 926 | if (comp(next.GetCurrent(), first.GetCurrent())) 927 | { 928 | return next; 929 | } 930 | first = first.GetNext(); 931 | } 932 | return last; 933 | } 934 | 935 | public static void NthElement( 936 | this ListIterator first, 937 | ListIterator nth, 938 | ListIterator last, 939 | Func comp 940 | ) 941 | { 942 | // TODO find a faster algorithm that doesn't create any garbage 943 | first.Sort(last, comp); 944 | } 945 | 946 | public static ListIterator LowerBound( 947 | this ListIterator first, 948 | ListIterator last, 949 | T val, 950 | Func comp 951 | ) 952 | { 953 | var count = first.Distance(last); 954 | while (count > 0) 955 | { 956 | var it = first; 957 | var step = count / 2; 958 | it = it.GetAdvanced(step); 959 | if (comp(it.GetCurrent(), val)) 960 | { 961 | it = it.GetNext(); 962 | first = it; 963 | count -= step + 1; 964 | } 965 | else 966 | { 967 | count = step; 968 | } 969 | } 970 | return first; 971 | } 972 | 973 | public static ListIterator UpperBound( 974 | this ListIterator first, 975 | ListIterator last, 976 | T val, 977 | Func comp 978 | ) 979 | { 980 | var count = Distance(first, last); 981 | while (count > 0) 982 | { 983 | var it = first; 984 | var step = count / 2; 985 | it = it.GetAdvanced(step); 986 | if (comp(val, it.GetCurrent()) == false) 987 | { 988 | it = it.GetNext(); 989 | first = it; 990 | count -= step + 1; 991 | } 992 | else 993 | { 994 | count = step; 995 | } 996 | } 997 | return first; 998 | } 999 | 1000 | public static void EqualRange( 1001 | this ListIterator first, 1002 | ListIterator last, 1003 | T val, 1004 | Func comp, 1005 | out ListIterator lower, 1006 | out ListIterator upper 1007 | ) 1008 | { 1009 | lower = first.LowerBound(last, val, comp); 1010 | upper = lower.UpperBound(last, val, comp); 1011 | } 1012 | 1013 | public static bool BinarySearch( 1014 | this ListIterator first, 1015 | ListIterator last, 1016 | T val, 1017 | Func comp 1018 | ) 1019 | { 1020 | first = first.LowerBound(last, val, comp); 1021 | return first.NotEqual(last) && comp(val, first.GetCurrent()) == false; 1022 | } 1023 | 1024 | public static ListIterator Merge( 1025 | this ListIterator first1, 1026 | ListIterator last1, 1027 | ListIterator first2, 1028 | ListIterator last2, 1029 | ListIterator result, 1030 | Func comp 1031 | ) 1032 | { 1033 | while (true) 1034 | { 1035 | if (first1.IsEqual(last1)) 1036 | { 1037 | return first2.Copy(last2, result); 1038 | } 1039 | if (first2.IsEqual(last2)) 1040 | { 1041 | return first1.Copy(last1, result); 1042 | } 1043 | if (comp(first2.GetCurrent(), first1.GetCurrent())) 1044 | { 1045 | result.SetCurrent(first2.GetCurrent()); 1046 | first2 = first2.GetNext(); 1047 | } 1048 | else 1049 | { 1050 | result.SetCurrent(first1.GetCurrent()); 1051 | first1 = first1.GetNext(); 1052 | } 1053 | result = result.GetNext(); 1054 | } 1055 | } 1056 | 1057 | public static void InplaceMerge( 1058 | this ListIterator first, 1059 | ListIterator middle, 1060 | ListIterator last, 1061 | Func comp 1062 | ) 1063 | { 1064 | if (first.Index >= middle.Index || middle.Index >= last.Index) 1065 | { 1066 | return; 1067 | } 1068 | if (last.Index - first.Index == 2) 1069 | { 1070 | if (comp(middle.GetCurrent(), first.GetCurrent())) 1071 | { 1072 | Swap(first, middle); 1073 | } 1074 | return; 1075 | } 1076 | ListIterator firstCut; 1077 | ListIterator secondCut; 1078 | if (middle.Index - first.Index > last.Index - middle.Index) 1079 | { 1080 | firstCut = first.GetAdvanced(first.Distance(middle) / 2); 1081 | secondCut = middle.LowerBound(last, firstCut.GetCurrent(), comp); 1082 | } 1083 | else 1084 | { 1085 | secondCut = middle.GetAdvanced(middle.Distance(last) / 2); 1086 | firstCut = first.UpperBound(middle, secondCut.GetCurrent(), comp); 1087 | } 1088 | Rotate(firstCut, middle, secondCut); 1089 | middle = firstCut.GetAdvanced(middle.Distance(secondCut)); 1090 | InplaceMerge(first, firstCut, middle, comp); 1091 | InplaceMerge(middle, secondCut, last, comp); 1092 | } 1093 | 1094 | public static bool Includes( 1095 | this ListIterator first1, 1096 | ListIterator last1, 1097 | ListIterator first2, 1098 | ListIterator last2, 1099 | Func comp 1100 | ) 1101 | { 1102 | while (first2.NotEqual(last2)) 1103 | { 1104 | if ((first1.IsEqual(last1)) || comp(first2.GetCurrent(), first1.GetCurrent())) 1105 | { 1106 | return false; 1107 | } 1108 | if (comp(first1.GetCurrent(), first2.GetCurrent()) == false) 1109 | { 1110 | first2 = first2.GetNext(); 1111 | } 1112 | first1 = first1.GetNext(); 1113 | } 1114 | return true; 1115 | } 1116 | 1117 | public static ListIterator SetUnion( 1118 | this ListIterator first1, 1119 | ListIterator last1, 1120 | ListIterator first2, 1121 | ListIterator last2, 1122 | ListIterator result, 1123 | Func comp 1124 | ) 1125 | { 1126 | while (true) 1127 | { 1128 | if (first1.IsEqual(last1)) 1129 | { 1130 | return first2.Copy(last2, result); 1131 | } 1132 | if (first2.IsEqual(last2)) 1133 | { 1134 | return first1.Copy(last1, result); 1135 | } 1136 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1137 | { 1138 | result.SetCurrent(first1.GetCurrent()); 1139 | first1 = first1.GetNext(); 1140 | } 1141 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1142 | { 1143 | result.SetCurrent(first2.GetCurrent()); 1144 | first2 = first2.GetNext(); 1145 | } 1146 | else 1147 | { 1148 | result.SetCurrent(first1.GetCurrent()); 1149 | first1 = first1.GetNext(); 1150 | first2 = first2.GetNext(); 1151 | } 1152 | result = result.GetNext(); 1153 | } 1154 | } 1155 | 1156 | public static ListIterator SetIntersection( 1157 | this ListIterator first1, 1158 | ListIterator last1, 1159 | ListIterator first2, 1160 | ListIterator last2, 1161 | ListIterator result, 1162 | Func comp 1163 | ) 1164 | { 1165 | while (first1.NotEqual(last1) && first2.NotEqual(last2)) 1166 | { 1167 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1168 | { 1169 | first1 = first1.GetNext(); 1170 | } 1171 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1172 | { 1173 | first2 = first2.GetNext(); 1174 | } 1175 | else 1176 | { 1177 | result.SetCurrent(first1.GetCurrent()); 1178 | result = result.GetNext(); 1179 | first1 = first1.GetNext(); 1180 | first2 = first2.GetNext(); 1181 | } 1182 | } 1183 | return result; 1184 | } 1185 | 1186 | public static ListIterator SetDifference( 1187 | this ListIterator first1, 1188 | ListIterator last1, 1189 | ListIterator first2, 1190 | ListIterator last2, 1191 | ListIterator result, 1192 | Func comp 1193 | ) 1194 | { 1195 | while (first1.NotEqual(last1) && first2.NotEqual(last2)) 1196 | { 1197 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1198 | { 1199 | result.SetCurrent(first1.GetCurrent()); 1200 | result = result.GetNext(); 1201 | first1 = first1.GetNext(); 1202 | } 1203 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1204 | { 1205 | first2 = first2.GetNext(); 1206 | } 1207 | else 1208 | { 1209 | first1 = first1.GetNext(); 1210 | first2 = first2.GetNext(); 1211 | } 1212 | } 1213 | return first1.Copy(last1, result); 1214 | } 1215 | 1216 | public static ListIterator SetSymmetricDifference( 1217 | this ListIterator first1, 1218 | ListIterator last1, 1219 | ListIterator first2, 1220 | ListIterator last2, 1221 | ListIterator result, 1222 | Func comp 1223 | ) 1224 | { 1225 | while (true) 1226 | { 1227 | if (first1.IsEqual(last1)) 1228 | { 1229 | return first2.Copy(last2, result); 1230 | } 1231 | if (first2.IsEqual(last2)) 1232 | { 1233 | return first1.Copy(last1, result); 1234 | } 1235 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1236 | { 1237 | result.SetCurrent(first1.GetCurrent()); 1238 | result = result.GetNext(); 1239 | first1 = first1.GetNext(); 1240 | } 1241 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1242 | { 1243 | result.SetCurrent(first2.GetCurrent()); 1244 | result = result.GetNext(); 1245 | first2 = first2.GetNext(); 1246 | } 1247 | else 1248 | { 1249 | first1 = first1.GetNext(); 1250 | first2 = first2.GetNext(); 1251 | } 1252 | } 1253 | } 1254 | 1255 | public static void PushHeap( 1256 | this ListIterator first, 1257 | ListIterator last, 1258 | Func comp 1259 | ) 1260 | { 1261 | if (first.Distance(last) < 2) 1262 | { 1263 | return; 1264 | } 1265 | last = last.GetPrev(); 1266 | var temp = last.GetCurrent(); 1267 | var parent = first.GetAdvanced((first.Distance(last) - 1) / 2); 1268 | while (first.Distance(last) > 0 && comp(parent.GetCurrent(), temp)) 1269 | { 1270 | last.SetCurrent(parent.GetCurrent()); 1271 | last = parent; 1272 | parent = first.GetAdvanced((first.Distance(last) - 1) / 2); 1273 | } 1274 | last.SetCurrent(temp); 1275 | } 1276 | 1277 | public static void PopHeap( 1278 | this ListIterator first, 1279 | ListIterator last, 1280 | Func comp 1281 | ) 1282 | { 1283 | if (first.Distance(last) < 2) 1284 | { 1285 | return; 1286 | } 1287 | last = last.GetPrev(); 1288 | Swap(first, last); 1289 | AdjustHeap(first.List, first.Index, first.Index, last.Index, comp); 1290 | } 1291 | 1292 | public static void MakeHeap( 1293 | this ListIterator first, 1294 | ListIterator last, 1295 | Func comp 1296 | ) 1297 | { 1298 | var dist = first.Distance(last); 1299 | if (dist < 2) 1300 | { 1301 | return; 1302 | } 1303 | var parent = (dist - 2) / 2; 1304 | do 1305 | { 1306 | AdjustHeap(first.List, first.Index, first.Index + parent, last.Index, comp); 1307 | } 1308 | while (parent-- != 0); 1309 | } 1310 | 1311 | public static void SortHeap( 1312 | this ListIterator first, 1313 | ListIterator last, 1314 | Func comp 1315 | ) 1316 | { 1317 | while (first.Distance(last) > 1) 1318 | { 1319 | last = last.GetPrev(); 1320 | Swap(first, last); 1321 | AdjustHeap(first.List, first.Index, first.Index, last.Index, comp); 1322 | } 1323 | } 1324 | 1325 | private static void AdjustHeap( 1326 | this IList list, 1327 | int first, 1328 | int position, 1329 | int last, 1330 | Func comp 1331 | ) 1332 | { 1333 | var tmp = list[position]; 1334 | int len = last - first; 1335 | int holeIndex = position - first; 1336 | int secondChild = 2 * holeIndex + 2; 1337 | while (secondChild < len) 1338 | { 1339 | if ( 1340 | comp( 1341 | list[first + secondChild], 1342 | list[first + (secondChild - 1)] 1343 | ) 1344 | ) 1345 | { 1346 | --secondChild; 1347 | } 1348 | list[first + holeIndex] = list[first + secondChild]; 1349 | holeIndex = secondChild++; 1350 | secondChild *= 2; 1351 | } 1352 | if (secondChild-- == len) 1353 | { 1354 | list[first + holeIndex] = list[first + secondChild]; 1355 | holeIndex = secondChild; 1356 | } 1357 | var parent = (holeIndex - 1) / 2; 1358 | var topIndex = position - first; 1359 | while (holeIndex != topIndex && comp(list[first + parent], tmp)) 1360 | { 1361 | list[first + holeIndex] = list[first + parent]; 1362 | holeIndex = parent; 1363 | parent = (holeIndex - 1) / 2; 1364 | } 1365 | list[first + holeIndex] = tmp; 1366 | } 1367 | 1368 | public static bool IsHeap( 1369 | this ListIterator first, 1370 | ListIterator last, 1371 | Func comp 1372 | ) 1373 | { 1374 | return first.IsHeapUntil(last, comp).IsEqual(last); 1375 | } 1376 | 1377 | public static ListIterator IsHeapUntil( 1378 | this ListIterator first, 1379 | ListIterator last, 1380 | Func comp 1381 | ) 1382 | { 1383 | var len = first.Distance(last); 1384 | var p = 0; 1385 | var c = 1; 1386 | var pp = first; 1387 | while (c < len) 1388 | { 1389 | var cp = first.GetAdvanced(c); 1390 | if (comp(pp.GetCurrent(), cp.GetCurrent())) 1391 | { 1392 | return cp; 1393 | } 1394 | c++; 1395 | cp = cp.GetNext(); 1396 | if (c == len) 1397 | { 1398 | return last; 1399 | } 1400 | if (comp(pp.GetCurrent(), cp.GetCurrent())) 1401 | { 1402 | return cp; 1403 | } 1404 | p++; 1405 | pp = pp.GetNext(); 1406 | c = 2 * p + 1; 1407 | } 1408 | return last; 1409 | } 1410 | 1411 | public static ListIterator MinElement( 1412 | this ListIterator first, 1413 | ListIterator last, 1414 | Func comp 1415 | ) 1416 | { 1417 | if (first.IsEqual(last)) 1418 | { 1419 | return last; 1420 | } 1421 | var smallest = first; 1422 | while ((first = first.GetNext()).NotEqual(last)) 1423 | { 1424 | if (comp(first.GetCurrent(), smallest.GetCurrent())) 1425 | { 1426 | smallest = first; 1427 | } 1428 | } 1429 | return smallest; 1430 | } 1431 | 1432 | public static ListIterator MaxElement( 1433 | this ListIterator first, 1434 | ListIterator last, 1435 | Func comp 1436 | ) 1437 | { 1438 | if (first.IsEqual(last)) 1439 | { 1440 | return last; 1441 | } 1442 | var largest = first; 1443 | while ((first = first.GetNext()).NotEqual(last)) 1444 | { 1445 | if (comp(largest.GetCurrent(), first.GetCurrent())) 1446 | { 1447 | largest = first; 1448 | } 1449 | } 1450 | return largest; 1451 | } 1452 | 1453 | public static void MinMaxElement( 1454 | this ListIterator first, 1455 | ListIterator last, 1456 | Func comp, 1457 | out ListIterator min, 1458 | out ListIterator max 1459 | ) 1460 | { 1461 | if (first.IsEqual(last)) 1462 | { 1463 | min = last; 1464 | max = last; 1465 | } 1466 | min = first; 1467 | max = first; 1468 | while ((first = first.GetNext()).NotEqual(last)) 1469 | { 1470 | if (comp(first.GetCurrent(), min.GetCurrent())) 1471 | { 1472 | min = first; 1473 | } 1474 | if (comp(max.GetCurrent(), first.GetCurrent())) 1475 | { 1476 | max = first; 1477 | } 1478 | } 1479 | } 1480 | 1481 | public static bool LexicographicalCompare( 1482 | this ListIterator first1, 1483 | ListIterator last1, 1484 | ListIterator first2, 1485 | ListIterator last2, 1486 | Func comp 1487 | ) 1488 | { 1489 | while (first1.NotEqual(last1)) 1490 | { 1491 | if (first2.IsEqual(last2) || comp(first2.GetCurrent(), first1.GetCurrent())) 1492 | { 1493 | return false; 1494 | } 1495 | else if (comp(first1.GetCurrent(), first2.GetCurrent())) 1496 | { 1497 | return true; 1498 | } 1499 | first1 = first1.GetNext(); 1500 | first2 = first2.GetNext(); 1501 | } 1502 | return first2.NotEqual(last2); 1503 | } 1504 | 1505 | public static bool NextPermutation( 1506 | this ListIterator first, 1507 | ListIterator last, 1508 | Func comp 1509 | ) 1510 | { 1511 | var i = last; 1512 | if (first.IsEqual(last) || first.IsEqual((i = i.GetPrev()))) 1513 | { 1514 | return false; 1515 | } 1516 | while (true) 1517 | { 1518 | var ip1 = i; 1519 | if (comp((i = i.GetPrev()).GetCurrent(), ip1.GetCurrent())) 1520 | { 1521 | var j = last; 1522 | while (comp(i.GetCurrent(), (j = j.GetPrev()).GetCurrent()) == false) 1523 | { 1524 | } 1525 | Swap(i, j); 1526 | Reverse(ip1, last); 1527 | return true; 1528 | } 1529 | if (i.IsEqual(first)) 1530 | { 1531 | Reverse(first, last); 1532 | return false; 1533 | } 1534 | } 1535 | } 1536 | 1537 | public static bool PrevPermutation( 1538 | this ListIterator first, 1539 | ListIterator last, 1540 | Func comp 1541 | ) 1542 | { 1543 | var i = last; 1544 | if (first.IsEqual(last) || first.IsEqual(i = i.GetPrev())) 1545 | { 1546 | return false; 1547 | } 1548 | while (true) 1549 | { 1550 | var ip1 = i; 1551 | if (comp(ip1.GetCurrent(), (i = i.GetPrev()).GetCurrent())) 1552 | { 1553 | var j = last; 1554 | while (comp((j = j.GetPrev()).GetCurrent(), i.GetCurrent()) == false) 1555 | { 1556 | } 1557 | Swap(i, j); 1558 | Reverse(ip1, last); 1559 | return true; 1560 | } 1561 | if (i.IsEqual(first)) 1562 | { 1563 | Reverse(first, last); 1564 | return false; 1565 | } 1566 | } 1567 | } 1568 | } 1569 | } 1570 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/ListIterator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aaa2013ff56bf4e2ca87740091937820 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/NativeArrayIterator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt. 4 | // 5 | //----------------------------------------------------------------------- 6 | 7 | // NativeArray was introduced in Unity 2018.1 8 | #if UNITY_2018_1_OR_NEWER 9 | 10 | using System; 11 | using Unity.Collections; 12 | using Unity.Collections.LowLevel.Unsafe; 13 | 14 | namespace JacksonDunstanIterator 15 | { 16 | public struct NativeArrayIterator 17 | where T : struct 18 | { 19 | public NativeArray Array; 20 | public int Index; 21 | } 22 | 23 | public static class NativeArrayIteratorExtensions 24 | { 25 | public static NativeArrayIterator Begin(this NativeArray array) 26 | where T : struct 27 | { 28 | return new NativeArrayIterator { Array = array }; 29 | } 30 | 31 | public static NativeArrayIterator End(this NativeArray array) 32 | where T : struct 33 | { 34 | return new NativeArrayIterator { Array = array, Index = array.Length }; 35 | } 36 | 37 | public static NativeArrayIterator IteratorAt(this NativeArray array, int index) 38 | where T : struct 39 | { 40 | return new NativeArrayIterator { Array = array, Index = index }; 41 | } 42 | 43 | public static T GetCurrent(this NativeArrayIterator it) 44 | where T : struct 45 | { 46 | return it.Array[it.Index]; 47 | } 48 | 49 | public static void SetCurrent(this NativeArrayIterator it, T val) 50 | where T : struct 51 | { 52 | it.Array[it.Index] = val; 53 | } 54 | 55 | public static NativeArrayIterator GetNext(this NativeArrayIterator it) 56 | where T : struct 57 | { 58 | it.Index++; 59 | return it; 60 | } 61 | 62 | public static NativeArrayIterator GetPrev(this NativeArrayIterator it) 63 | where T : struct 64 | { 65 | it.Index--; 66 | return it; 67 | } 68 | 69 | public static unsafe bool IsEqual(this NativeArrayIterator it, NativeArrayIterator other) 70 | where T : struct 71 | { 72 | return it.Array.GetUnsafeReadOnlyPtr() == other.Array.GetUnsafeReadOnlyPtr() 73 | && it.Index == other.Index; 74 | } 75 | 76 | public static unsafe bool NotEqual(this NativeArrayIterator it, NativeArrayIterator other) 77 | where T : struct 78 | { 79 | return it.Array.GetUnsafeReadOnlyPtr() != other.Array.GetUnsafeReadOnlyPtr() 80 | || it.Index != other.Index; 81 | } 82 | 83 | public static NativeArrayIterator GetAdvanced(this NativeArrayIterator it, int distance) 84 | where T : struct 85 | { 86 | return new NativeArrayIterator { Array = it.Array, Index = it.Index + distance }; 87 | } 88 | 89 | public static int Distance(this NativeArrayIterator first, NativeArrayIterator last) 90 | where T : struct 91 | { 92 | return last.Index - first.Index; 93 | } 94 | 95 | public static bool AllOf( 96 | this NativeArrayIterator first, 97 | NativeArrayIterator last, 98 | Func pred 99 | ) 100 | where T : struct 101 | { 102 | while (first.NotEqual(last)) 103 | { 104 | if (pred(first.GetCurrent()) == false) 105 | { 106 | return false; 107 | } 108 | first = first.GetNext(); 109 | } 110 | return true; 111 | } 112 | 113 | public static bool AnyOf( 114 | this NativeArrayIterator first, 115 | NativeArrayIterator last, 116 | Func pred 117 | ) 118 | where T : struct 119 | { 120 | while (first.NotEqual(last)) 121 | { 122 | if (pred(first.GetCurrent())) 123 | { 124 | return true; 125 | } 126 | first = first.GetNext(); 127 | } 128 | return false; 129 | } 130 | 131 | public static bool NoneOf( 132 | this NativeArrayIterator first, 133 | NativeArrayIterator last, 134 | Func pred 135 | ) 136 | where T : struct 137 | { 138 | while (first.NotEqual(last)) 139 | { 140 | if (pred(first.GetCurrent())) 141 | { 142 | return false; 143 | } 144 | first = first.GetNext(); 145 | } 146 | return true; 147 | } 148 | 149 | public static void ForEach( 150 | this NativeArrayIterator first, 151 | NativeArrayIterator last, 152 | Action callback 153 | ) 154 | where T : struct 155 | { 156 | while (first.NotEqual(last)) 157 | { 158 | callback(first.GetCurrent()); 159 | first = first.GetNext(); 160 | } 161 | } 162 | 163 | public static NativeArrayIterator Find( 164 | this NativeArrayIterator first, 165 | NativeArrayIterator last, 166 | T val, 167 | Func pred 168 | ) 169 | where T : struct 170 | { 171 | while (first.NotEqual(last)) 172 | { 173 | if (pred(first.GetCurrent(), val)) 174 | { 175 | return first; 176 | } 177 | first = first.GetNext(); 178 | } 179 | return last; 180 | } 181 | 182 | public static NativeArrayIterator FindIf( 183 | this NativeArrayIterator first, 184 | NativeArrayIterator last, 185 | Func pred 186 | ) 187 | where T : struct 188 | { 189 | while (first.NotEqual(last)) 190 | { 191 | if (pred(first.GetCurrent())) 192 | { 193 | return first; 194 | } 195 | first = first.GetNext(); 196 | } 197 | return last; 198 | } 199 | 200 | public static NativeArrayIterator FindIfNot( 201 | this NativeArrayIterator first, 202 | NativeArrayIterator last, 203 | Func pred 204 | ) 205 | where T : struct 206 | { 207 | while (first.NotEqual(last)) 208 | { 209 | if (pred(first.GetCurrent()) == false) 210 | { 211 | return first; 212 | } 213 | first = first.GetNext(); 214 | } 215 | return last; 216 | } 217 | 218 | public static NativeArrayIterator FindEnd( 219 | this NativeArrayIterator first1, 220 | NativeArrayIterator last1, 221 | NativeArrayIterator first2, 222 | NativeArrayIterator last2, 223 | Func pred 224 | ) 225 | where T : struct 226 | { 227 | if (first2.IsEqual(last2)) 228 | { 229 | return last1; 230 | } 231 | var ret = last1; 232 | while (first1.NotEqual(last1)) 233 | { 234 | var it1 = first1; 235 | var it2 = first2; 236 | while (pred(it1.GetCurrent(), it2.GetCurrent())) 237 | { 238 | it1 = it1.GetNext(); 239 | it2 = it2.GetNext(); 240 | if (it2.IsEqual(last2)) 241 | { 242 | ret = first1; 243 | break; 244 | } 245 | if (it1.IsEqual(last1)) 246 | { 247 | return ret; 248 | } 249 | } 250 | first1 = first1.GetNext(); 251 | } 252 | return ret; 253 | } 254 | 255 | public static NativeArrayIterator FindFirstOf( 256 | this NativeArrayIterator first1, 257 | NativeArrayIterator last1, 258 | NativeArrayIterator first2, 259 | NativeArrayIterator last2, 260 | Func pred 261 | ) 262 | where T : struct 263 | { 264 | while (first1.NotEqual(last1)) 265 | { 266 | for (var it = first2; it.NotEqual(last2); it = it.GetNext()) 267 | { 268 | if (pred(it.GetCurrent(), first1.GetCurrent())) 269 | { 270 | return first1; 271 | } 272 | } 273 | first1 = first1.GetNext(); 274 | } 275 | return last1; 276 | } 277 | 278 | public static NativeArrayIterator AdjacentFind( 279 | this NativeArrayIterator first, 280 | NativeArrayIterator last, 281 | Func pred 282 | ) 283 | where T : struct 284 | { 285 | if (first.NotEqual(last)) 286 | { 287 | var next = first; 288 | next = next.GetNext(); 289 | while (next.NotEqual(last)) 290 | { 291 | if (pred(first.GetCurrent(), next.GetCurrent())) 292 | { 293 | return first; 294 | } 295 | first = first.GetNext(); 296 | next = next.GetNext(); 297 | } 298 | } 299 | return last; 300 | } 301 | 302 | public static int Count( 303 | this NativeArrayIterator first, 304 | NativeArrayIterator last, 305 | T val, 306 | Func pred 307 | ) 308 | where T : struct 309 | { 310 | var count = 0; 311 | while (first.NotEqual(last)) 312 | { 313 | if (pred(first.GetCurrent(), val)) 314 | { 315 | count++; 316 | } 317 | first = first.GetNext(); 318 | } 319 | return count; 320 | } 321 | 322 | public static int CountIf( 323 | this NativeArrayIterator first, 324 | NativeArrayIterator last, 325 | Func pred 326 | ) 327 | where T : struct 328 | { 329 | var count = 0; 330 | while (first.NotEqual(last)) 331 | { 332 | if (pred(first.GetCurrent())) 333 | { 334 | count++; 335 | } 336 | first = first.GetNext(); 337 | } 338 | return count; 339 | } 340 | 341 | public static void Mismatch( 342 | this NativeArrayIterator first1, 343 | NativeArrayIterator last1, 344 | NativeArrayIterator first2, 345 | Func pred, 346 | out NativeArrayIterator mismatch1, 347 | out NativeArrayIterator mismatch2 348 | ) 349 | where T : struct 350 | { 351 | while (first1.NotEqual(last1)) 352 | { 353 | if (pred(first1.GetCurrent(), first2.GetCurrent()) == false) 354 | { 355 | break; 356 | } 357 | first1 = first1.GetNext(); 358 | first2 = first2.GetNext(); 359 | } 360 | mismatch1 = first1; 361 | mismatch2 = first2; 362 | } 363 | 364 | public static bool Equal( 365 | this NativeArrayIterator first1, 366 | NativeArrayIterator last1, 367 | NativeArrayIterator first2, 368 | Func pred 369 | ) 370 | where T : struct 371 | { 372 | while (first1.NotEqual(last1)) 373 | { 374 | if (pred(first1.GetCurrent(), first2.GetCurrent()) == false) 375 | { 376 | return false; 377 | } 378 | first1 = first1.GetNext(); 379 | first2 = first2.GetNext(); 380 | } 381 | return true; 382 | } 383 | 384 | public static bool IsPermutation( 385 | this NativeArrayIterator first1, 386 | NativeArrayIterator last1, 387 | NativeArrayIterator first2, 388 | Func pred 389 | ) 390 | where T : struct 391 | { 392 | first1.Mismatch(last1, first2, pred, out first1, out first2); 393 | if (first1.IsEqual(last1)) 394 | { 395 | return true; 396 | } 397 | var last2 = first2; 398 | last2 = last2.GetAdvanced(first1.Distance(last1)); 399 | for (var it1 = first1; it1.NotEqual(last1); it1 = it1.GetNext()) 400 | { 401 | if (first1.Find(it1, it1.GetCurrent(), pred).IsEqual(it1)) 402 | { 403 | var n = first2.Count(last2, it1.GetCurrent(), pred); 404 | if (n == 0 || it1.Count(last1, it1.GetCurrent(), pred) != n) 405 | { 406 | return false; 407 | } 408 | } 409 | } 410 | return true; 411 | } 412 | 413 | public static NativeArrayIterator Search( 414 | this NativeArrayIterator first1, 415 | NativeArrayIterator last1, 416 | NativeArrayIterator first2, 417 | NativeArrayIterator last2, 418 | Func pred 419 | ) 420 | where T : struct 421 | { 422 | if (first2.IsEqual(last2)) 423 | { 424 | return first1; 425 | } 426 | 427 | while (first1.NotEqual(last1)) 428 | { 429 | var it1 = first1; 430 | var it2 = first2; 431 | while (pred(it1.GetCurrent(), it2.GetCurrent())) 432 | { 433 | it1 = it1.GetNext(); 434 | it2 = it2.GetNext(); 435 | if (it2.IsEqual(last2)) 436 | { 437 | return first1; 438 | } 439 | if (it1.IsEqual(last1)) 440 | { 441 | return last1; 442 | } 443 | } 444 | first1 = first1.GetNext(); 445 | } 446 | return last1; 447 | } 448 | 449 | public static NativeArrayIterator SearchN( 450 | this NativeArrayIterator first, 451 | NativeArrayIterator last, 452 | int count, 453 | T val, 454 | Func pred 455 | ) 456 | where T : struct 457 | { 458 | var limit = first.GetAdvanced(first.Distance(last) - count); 459 | while (first.NotEqual(limit)) 460 | { 461 | var it = first; 462 | var i = 0; 463 | while (pred(val, it.GetCurrent())) 464 | { 465 | it = it.GetNext(); 466 | if (++i == count) 467 | { 468 | return first; 469 | } 470 | } 471 | first = first.GetNext(); 472 | } 473 | return last; 474 | } 475 | 476 | public static NativeArrayIterator Copy( 477 | this NativeArrayIterator first, 478 | NativeArrayIterator last, 479 | NativeArrayIterator result 480 | ) 481 | where T : struct 482 | { 483 | while (first.NotEqual(last)) 484 | { 485 | result.SetCurrent(first.GetCurrent()); 486 | result = result.GetNext(); 487 | first = first.GetNext(); 488 | } 489 | return result; 490 | } 491 | 492 | public static NativeArrayIterator CopyN( 493 | this NativeArrayIterator first, 494 | int n, 495 | NativeArrayIterator result 496 | ) 497 | where T : struct 498 | { 499 | while (n > 0) 500 | { 501 | result.SetCurrent(first.GetCurrent()); 502 | result = result.GetNext(); 503 | first = first.GetNext(); 504 | n--; 505 | } 506 | return result; 507 | } 508 | 509 | public static NativeArrayIterator CopyIf( 510 | this NativeArrayIterator first, 511 | NativeArrayIterator last, 512 | NativeArrayIterator result, 513 | Func pred 514 | ) 515 | where T : struct 516 | { 517 | while (first.NotEqual(last)) 518 | { 519 | if (pred(first.GetCurrent())) 520 | { 521 | result.SetCurrent(first.GetCurrent()); 522 | result = result.GetNext(); 523 | } 524 | first = first.GetNext(); 525 | } 526 | return result; 527 | } 528 | 529 | public static NativeArrayIterator CopyBackward( 530 | this NativeArrayIterator first, 531 | NativeArrayIterator last, 532 | NativeArrayIterator result 533 | ) 534 | where T : struct 535 | { 536 | while (last.NotEqual(first)) 537 | { 538 | result = result.GetPrev(); 539 | last = last.GetPrev(); 540 | result.SetCurrent(last.GetCurrent()); 541 | } 542 | return result; 543 | } 544 | 545 | public static NativeArrayIterator SwapRanges( 546 | this NativeArrayIterator first1, 547 | NativeArrayIterator last1, 548 | NativeArrayIterator first2 549 | ) 550 | where T : struct 551 | { 552 | while (first1.NotEqual(last1)) 553 | { 554 | Swap(first1, first2); 555 | first1 = first1.GetNext(); 556 | first2 = first2.GetNext(); 557 | } 558 | return first2; 559 | } 560 | 561 | public static void Swap(this NativeArrayIterator a, NativeArrayIterator b) 562 | where T : struct 563 | { 564 | var temp = a.GetCurrent(); 565 | a.SetCurrent(b.GetCurrent()); 566 | b.SetCurrent(temp); 567 | } 568 | 569 | public static NativeArrayIterator Transform( 570 | this NativeArrayIterator first1, 571 | NativeArrayIterator last1, 572 | NativeArrayIterator result, 573 | Func op 574 | ) 575 | where T : struct 576 | { 577 | while (first1.NotEqual(last1)) 578 | { 579 | result.SetCurrent(op(first1.GetCurrent())); 580 | result = result.GetNext(); 581 | first1 = first1.GetNext(); 582 | } 583 | return result; 584 | } 585 | 586 | public static NativeArrayIterator Transform( 587 | this NativeArrayIterator first1, 588 | NativeArrayIterator last1, 589 | NativeArrayIterator first2, 590 | NativeArrayIterator result, 591 | Func binaryOp 592 | ) 593 | where T : struct 594 | { 595 | while (first1.NotEqual(last1)) 596 | { 597 | result.SetCurrent(binaryOp(first1.GetCurrent(), first2.GetCurrent())); 598 | first2 = first2.GetNext(); 599 | result = result.GetNext(); 600 | first1 = first1.GetNext(); 601 | } 602 | return result; 603 | } 604 | 605 | public static void ReplaceIf( 606 | this NativeArrayIterator first, 607 | NativeArrayIterator last, 608 | Func pred, 609 | T newValue 610 | ) 611 | where T : struct 612 | { 613 | while (first.NotEqual(last)) 614 | { 615 | if (pred(first.GetCurrent())) 616 | { 617 | first.SetCurrent(newValue); 618 | 619 | } 620 | first = first.GetNext(); 621 | } 622 | } 623 | 624 | public static NativeArrayIterator ReplaceCopyIf( 625 | this NativeArrayIterator first, 626 | NativeArrayIterator last, 627 | NativeArrayIterator result, 628 | Func pred, 629 | T newValue 630 | ) 631 | where T : struct 632 | { 633 | while (first.NotEqual(last)) 634 | { 635 | result.SetCurrent(pred(first.GetCurrent()) ? newValue : first.GetCurrent()); 636 | first = first.GetNext(); 637 | result = result.GetNext(); 638 | } 639 | return result; 640 | } 641 | 642 | public static NativeArrayIterator Unique( 643 | this NativeArrayIterator first, 644 | NativeArrayIterator last, 645 | Func pred 646 | ) 647 | where T : struct 648 | { 649 | if (first.IsEqual(last)) 650 | { 651 | return last; 652 | } 653 | 654 | var result = first; 655 | while ((first = first.GetNext()).NotEqual(last)) 656 | { 657 | if (pred(result.GetCurrent(), first.GetCurrent()) == false) 658 | { 659 | result = result.GetNext(); 660 | result.SetCurrent(first.GetCurrent()); 661 | } 662 | } 663 | result = result.GetNext(); 664 | return result; 665 | } 666 | 667 | public static NativeArrayIterator UniqueCopy( 668 | this NativeArrayIterator first, 669 | NativeArrayIterator last, 670 | NativeArrayIterator result, 671 | Func pred 672 | ) 673 | where T : struct 674 | { 675 | if (first.IsEqual(last)) 676 | { 677 | return last; 678 | } 679 | 680 | result.SetCurrent(first.GetCurrent()); 681 | while ((first = first.GetNext()).NotEqual(last)) 682 | { 683 | var val = first.GetCurrent(); 684 | if (pred(result.GetCurrent(), val) == false) 685 | { 686 | result = result.GetNext(); 687 | result.SetCurrent(val); 688 | } 689 | } 690 | result = result.GetNext(); 691 | return result; 692 | } 693 | 694 | public static void Reverse(this NativeArrayIterator first, NativeArrayIterator last) 695 | where T : struct 696 | { 697 | while ((first.NotEqual(last)) && (first.NotEqual((last = last.GetPrev())))) 698 | { 699 | first.Swap(last); 700 | first = first.GetNext(); 701 | } 702 | } 703 | 704 | public static NativeArrayIterator ReverseCopy( 705 | this NativeArrayIterator first, 706 | NativeArrayIterator last, 707 | NativeArrayIterator result 708 | ) 709 | where T : struct 710 | { 711 | while (first.NotEqual(last)) 712 | { 713 | last = last.GetPrev(); 714 | result.SetCurrent(last.GetCurrent()); 715 | result = result.GetNext(); 716 | } 717 | return result; 718 | } 719 | 720 | public static void Rotate( 721 | this NativeArrayIterator first, 722 | NativeArrayIterator middle, 723 | NativeArrayIterator last 724 | ) 725 | where T : struct 726 | { 727 | var next = middle; 728 | while (first.NotEqual(last)) 729 | { 730 | first.Swap(next); 731 | first = first.GetNext(); 732 | next = next.GetNext(); 733 | if (next.IsEqual(last)) 734 | { 735 | next = middle; 736 | } 737 | else if (first.IsEqual(middle)) 738 | { 739 | middle = next; 740 | } 741 | } 742 | } 743 | 744 | public static NativeArrayIterator RotateCopy( 745 | this NativeArrayIterator first, 746 | NativeArrayIterator middle, 747 | NativeArrayIterator last, 748 | NativeArrayIterator result 749 | ) 750 | where T : struct 751 | { 752 | result = Copy(middle, last, result); 753 | return Copy(first, middle, result); 754 | } 755 | 756 | public static void RandomShuffle( 757 | this NativeArrayIterator first, 758 | NativeArrayIterator last, 759 | Func gen 760 | ) 761 | where T : struct 762 | { 763 | var n = Distance(first, last); 764 | for (var i = n - 1; i > 0; --i) 765 | { 766 | first.GetAdvanced(i).Swap(first.GetAdvanced(gen(i + 1))); 767 | } 768 | } 769 | 770 | public static bool IsPartitioned( 771 | this NativeArrayIterator first, 772 | NativeArrayIterator last, 773 | Func pred 774 | ) 775 | where T : struct 776 | { 777 | while (first.NotEqual(last) && pred(first.GetCurrent())) 778 | { 779 | first = first.GetNext(); 780 | } 781 | while (first.NotEqual(last)) 782 | { 783 | if (pred(first.GetCurrent())) 784 | { 785 | return false; 786 | } 787 | first = first.GetNext(); 788 | } 789 | return true; 790 | } 791 | 792 | public static NativeArrayIterator Partition( 793 | this NativeArrayIterator first, 794 | NativeArrayIterator last, 795 | Func pred 796 | ) 797 | where T : struct 798 | { 799 | while (first.NotEqual(last)) 800 | { 801 | while (pred(first.GetCurrent())) 802 | { 803 | first = first.GetNext(); 804 | if (first.IsEqual(last)) 805 | { 806 | return first; 807 | } 808 | } 809 | do 810 | { 811 | last = last.GetPrev(); 812 | if (first.IsEqual(last)) 813 | { 814 | return first; 815 | } 816 | } while (pred(last.GetCurrent()) == false); 817 | first.Swap(last); 818 | first = first.GetNext(); 819 | } 820 | return first; 821 | } 822 | 823 | public static void PartitionCopy( 824 | this NativeArrayIterator first, 825 | NativeArrayIterator last, 826 | NativeArrayIterator resultTrue, 827 | NativeArrayIterator resultFalse, 828 | Func pred, 829 | out NativeArrayIterator outResultTrue, 830 | out NativeArrayIterator outResultFalse 831 | ) 832 | where T : struct 833 | { 834 | while (first.NotEqual(last)) 835 | { 836 | if (pred(first.GetCurrent())) 837 | { 838 | resultTrue.SetCurrent(first.GetCurrent()); 839 | resultTrue = resultTrue.GetNext(); 840 | } 841 | else 842 | { 843 | resultFalse.SetCurrent(first.GetCurrent()); 844 | resultFalse = resultFalse.GetNext(); 845 | } 846 | first = first.GetNext(); 847 | } 848 | outResultTrue = resultTrue; 849 | outResultFalse = resultFalse; 850 | } 851 | 852 | public static NativeArrayIterator PartitionPoint( 853 | this NativeArrayIterator first, 854 | NativeArrayIterator last, 855 | Func pred 856 | ) 857 | where T : struct 858 | { 859 | var n = first.Distance(last); 860 | while (n > 0) 861 | { 862 | var it = first; 863 | var step = n / 2; 864 | it.GetAdvanced(step); 865 | if (pred(it.GetCurrent())) 866 | { 867 | first = it.GetNext(); 868 | n -= step + 1; 869 | } 870 | else 871 | { 872 | n = step; 873 | } 874 | } 875 | return first; 876 | } 877 | 878 | public static void Sort( 879 | this NativeArrayIterator first, 880 | NativeArrayIterator last, 881 | Func comp 882 | ) 883 | where T : struct 884 | { 885 | // Quicksort 886 | if (first.IsEqual(last)) 887 | { 888 | return; 889 | } 890 | var sep = first; 891 | for (var i = first.GetNext(); i.NotEqual(last); i = i.GetNext()) 892 | { 893 | if (comp(i.GetCurrent(), first.GetCurrent())) 894 | { 895 | sep = sep.GetNext(); 896 | sep.Swap(i); 897 | } 898 | } 899 | first.Swap(sep); 900 | first.Sort(sep, comp); 901 | sep.GetNext().Sort(last, comp); 902 | } 903 | 904 | public static void StableSort( 905 | this NativeArrayIterator first, 906 | NativeArrayIterator last, 907 | Func comp 908 | ) 909 | where T : struct 910 | { 911 | // TODO find a faster algorithm that doesn't create any garbage than insertion sort 912 | var arr = first.Array; 913 | for (var i = first.Index + 1; i < last.Index; i++) 914 | { 915 | var x = arr[i]; 916 | var left = first.Index; 917 | var right = i - 1; 918 | while (left <= right) 919 | { 920 | var middle = (left + right) / 2; 921 | if (comp(x, arr[middle])) 922 | { 923 | right = middle - 1; 924 | } 925 | else 926 | { 927 | left = middle + 1; 928 | } 929 | } 930 | for (var j = i - 1; j >= left; j--) 931 | { 932 | arr[j + 1] = arr[j]; 933 | } 934 | arr[left] = x; 935 | } 936 | } 937 | 938 | public static void PartialSort( 939 | this NativeArrayIterator first, 940 | NativeArrayIterator middle, 941 | NativeArrayIterator last, 942 | Func comp 943 | ) 944 | where T : struct 945 | { 946 | // TODO find a faster algorithm that doesn't create any garbage 947 | first.Sort(last, comp); 948 | } 949 | 950 | public static bool IsSorted( 951 | this NativeArrayIterator first, 952 | NativeArrayIterator last, 953 | Func comp 954 | ) 955 | where T : struct 956 | { 957 | if (first.IsEqual(last)) 958 | { 959 | return true; 960 | } 961 | var next = first; 962 | while ((next = next.GetNext()).NotEqual(last)) 963 | { 964 | if (comp(next.GetCurrent(), first.GetCurrent())) 965 | { 966 | return false; 967 | } 968 | first = first.GetNext(); 969 | } 970 | return true; 971 | } 972 | 973 | public static NativeArrayIterator IsSortedUntil( 974 | this NativeArrayIterator first, 975 | NativeArrayIterator last, 976 | Func comp 977 | ) 978 | where T : struct 979 | { 980 | if (first.IsEqual(last)) 981 | { 982 | return first; 983 | } 984 | var next = first; 985 | while ((next = next.GetNext()).NotEqual(last)) 986 | { 987 | if (comp(next.GetCurrent(), first.GetCurrent())) 988 | { 989 | return next; 990 | } 991 | first = first.GetNext(); 992 | } 993 | return last; 994 | } 995 | 996 | public static void NthElement( 997 | this NativeArrayIterator first, 998 | NativeArrayIterator nth, 999 | NativeArrayIterator last, 1000 | Func comp 1001 | ) 1002 | where T : struct 1003 | { 1004 | // TODO find a faster algorithm that doesn't create any garbage 1005 | first.Sort(last, comp); 1006 | } 1007 | 1008 | public static NativeArrayIterator LowerBound( 1009 | this NativeArrayIterator first, 1010 | NativeArrayIterator last, 1011 | T val, 1012 | Func comp 1013 | ) 1014 | where T : struct 1015 | { 1016 | var count = first.Distance(last); 1017 | while (count > 0) 1018 | { 1019 | var it = first; 1020 | var step = count / 2; 1021 | it = it.GetAdvanced(step); 1022 | if (comp(it.GetCurrent(), val)) 1023 | { 1024 | it = it.GetNext(); 1025 | first = it; 1026 | count -= step + 1; 1027 | } 1028 | else 1029 | { 1030 | count = step; 1031 | } 1032 | } 1033 | return first; 1034 | } 1035 | 1036 | public static NativeArrayIterator UpperBound( 1037 | this NativeArrayIterator first, 1038 | NativeArrayIterator last, 1039 | T val, 1040 | Func comp 1041 | ) 1042 | where T : struct 1043 | { 1044 | var count = Distance(first, last); 1045 | while (count > 0) 1046 | { 1047 | var it = first; 1048 | var step = count / 2; 1049 | it = it.GetAdvanced(step); 1050 | if (comp(val, it.GetCurrent()) == false) 1051 | { 1052 | it = it.GetNext(); 1053 | first = it; 1054 | count -= step + 1; 1055 | } 1056 | else 1057 | { 1058 | count = step; 1059 | } 1060 | } 1061 | return first; 1062 | } 1063 | 1064 | public static void EqualRange( 1065 | this NativeArrayIterator first, 1066 | NativeArrayIterator last, 1067 | T val, 1068 | Func comp, 1069 | out NativeArrayIterator lower, 1070 | out NativeArrayIterator upper 1071 | ) 1072 | where T : struct 1073 | { 1074 | lower = first.LowerBound(last, val, comp); 1075 | upper = lower.UpperBound(last, val, comp); 1076 | } 1077 | 1078 | public static bool BinarySearch( 1079 | this NativeArrayIterator first, 1080 | NativeArrayIterator last, 1081 | T val, 1082 | Func comp 1083 | ) 1084 | where T : struct 1085 | { 1086 | first = first.LowerBound(last, val, comp); 1087 | return first.NotEqual(last) && comp(val, first.GetCurrent()) == false; 1088 | } 1089 | 1090 | public static NativeArrayIterator Merge( 1091 | this NativeArrayIterator first1, 1092 | NativeArrayIterator last1, 1093 | NativeArrayIterator first2, 1094 | NativeArrayIterator last2, 1095 | NativeArrayIterator result, 1096 | Func comp 1097 | ) 1098 | where T : struct 1099 | { 1100 | while (true) 1101 | { 1102 | if (first1.IsEqual(last1)) 1103 | { 1104 | return first2.Copy(last2, result); 1105 | } 1106 | if (first2.IsEqual(last2)) 1107 | { 1108 | return first1.Copy(last1, result); 1109 | } 1110 | if (comp(first2.GetCurrent(), first1.GetCurrent())) 1111 | { 1112 | result.SetCurrent(first2.GetCurrent()); 1113 | first2 = first2.GetNext(); 1114 | } 1115 | else 1116 | { 1117 | result.SetCurrent(first1.GetCurrent()); 1118 | first1 = first1.GetNext(); 1119 | } 1120 | result = result.GetNext(); 1121 | } 1122 | } 1123 | 1124 | public static void InplaceMerge( 1125 | this NativeArrayIterator first, 1126 | NativeArrayIterator middle, 1127 | NativeArrayIterator last, 1128 | Func comp 1129 | ) 1130 | where T : struct 1131 | { 1132 | if (first.Index >= middle.Index || middle.Index >= last.Index) 1133 | { 1134 | return; 1135 | } 1136 | if (last.Index - first.Index == 2) 1137 | { 1138 | if (comp(middle.GetCurrent(), first.GetCurrent())) 1139 | { 1140 | Swap(first, middle); 1141 | } 1142 | return; 1143 | } 1144 | NativeArrayIterator firstCut; 1145 | NativeArrayIterator secondCut; 1146 | if (middle.Index - first.Index > last.Index - middle.Index) 1147 | { 1148 | firstCut = first.GetAdvanced(first.Distance(middle) / 2); 1149 | secondCut = middle.LowerBound(last, firstCut.GetCurrent(), comp); 1150 | } 1151 | else 1152 | { 1153 | secondCut = middle.GetAdvanced(middle.Distance(last) / 2); 1154 | firstCut = first.UpperBound(middle, secondCut.GetCurrent(), comp); 1155 | } 1156 | Rotate(firstCut, middle, secondCut); 1157 | middle = firstCut.GetAdvanced(middle.Distance(secondCut)); 1158 | InplaceMerge(first, firstCut, middle, comp); 1159 | InplaceMerge(middle, secondCut, last, comp); 1160 | } 1161 | 1162 | public static bool Includes( 1163 | this NativeArrayIterator first1, 1164 | NativeArrayIterator last1, 1165 | NativeArrayIterator first2, 1166 | NativeArrayIterator last2, 1167 | Func comp 1168 | ) 1169 | where T : struct 1170 | { 1171 | while (first2.NotEqual(last2)) 1172 | { 1173 | if ((first1.IsEqual(last1)) || comp(first2.GetCurrent(), first1.GetCurrent())) 1174 | { 1175 | return false; 1176 | } 1177 | if (comp(first1.GetCurrent(), first2.GetCurrent()) == false) 1178 | { 1179 | first2 = first2.GetNext(); 1180 | } 1181 | first1 = first1.GetNext(); 1182 | } 1183 | return true; 1184 | } 1185 | 1186 | public static NativeArrayIterator SetUnion( 1187 | this NativeArrayIterator first1, 1188 | NativeArrayIterator last1, 1189 | NativeArrayIterator first2, 1190 | NativeArrayIterator last2, 1191 | NativeArrayIterator result, 1192 | Func comp 1193 | ) 1194 | where T : struct 1195 | { 1196 | while (true) 1197 | { 1198 | if (first1.IsEqual(last1)) 1199 | { 1200 | return first2.Copy(last2, result); 1201 | } 1202 | if (first2.IsEqual(last2)) 1203 | { 1204 | return first1.Copy(last1, result); 1205 | } 1206 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1207 | { 1208 | result.SetCurrent(first1.GetCurrent()); 1209 | first1 = first1.GetNext(); 1210 | } 1211 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1212 | { 1213 | result.SetCurrent(first2.GetCurrent()); 1214 | first2 = first2.GetNext(); 1215 | } 1216 | else 1217 | { 1218 | result.SetCurrent(first1.GetCurrent()); 1219 | first1 = first1.GetNext(); 1220 | first2 = first2.GetNext(); 1221 | } 1222 | result = result.GetNext(); 1223 | } 1224 | } 1225 | 1226 | public static NativeArrayIterator SetIntersection( 1227 | this NativeArrayIterator first1, 1228 | NativeArrayIterator last1, 1229 | NativeArrayIterator first2, 1230 | NativeArrayIterator last2, 1231 | NativeArrayIterator result, 1232 | Func comp 1233 | ) 1234 | where T : struct 1235 | { 1236 | while (first1.NotEqual(last1) && first2.NotEqual(last2)) 1237 | { 1238 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1239 | { 1240 | first1 = first1.GetNext(); 1241 | } 1242 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1243 | { 1244 | first2 = first2.GetNext(); 1245 | } 1246 | else 1247 | { 1248 | result.SetCurrent(first1.GetCurrent()); 1249 | result = result.GetNext(); 1250 | first1 = first1.GetNext(); 1251 | first2 = first2.GetNext(); 1252 | } 1253 | } 1254 | return result; 1255 | } 1256 | 1257 | public static NativeArrayIterator SetDifference( 1258 | this NativeArrayIterator first1, 1259 | NativeArrayIterator last1, 1260 | NativeArrayIterator first2, 1261 | NativeArrayIterator last2, 1262 | NativeArrayIterator result, 1263 | Func comp 1264 | ) 1265 | where T : struct 1266 | { 1267 | while (first1.NotEqual(last1) && first2.NotEqual(last2)) 1268 | { 1269 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1270 | { 1271 | result.SetCurrent(first1.GetCurrent()); 1272 | result = result.GetNext(); 1273 | first1 = first1.GetNext(); 1274 | } 1275 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1276 | { 1277 | first2 = first2.GetNext(); 1278 | } 1279 | else 1280 | { 1281 | first1 = first1.GetNext(); 1282 | first2 = first2.GetNext(); 1283 | } 1284 | } 1285 | return first1.Copy(last1, result); 1286 | } 1287 | 1288 | public static NativeArrayIterator SetSymmetricDifference( 1289 | this NativeArrayIterator first1, 1290 | NativeArrayIterator last1, 1291 | NativeArrayIterator first2, 1292 | NativeArrayIterator last2, 1293 | NativeArrayIterator result, 1294 | Func comp 1295 | ) 1296 | where T : struct 1297 | { 1298 | while (true) 1299 | { 1300 | if (first1.IsEqual(last1)) 1301 | { 1302 | return first2.Copy(last2, result); 1303 | } 1304 | if (first2.IsEqual(last2)) 1305 | { 1306 | return first1.Copy(last1, result); 1307 | } 1308 | if (comp(first1.GetCurrent(), first2.GetCurrent())) 1309 | { 1310 | result.SetCurrent(first1.GetCurrent()); 1311 | result = result.GetNext(); 1312 | first1 = first1.GetNext(); 1313 | } 1314 | else if (comp(first2.GetCurrent(), first1.GetCurrent())) 1315 | { 1316 | result.SetCurrent(first2.GetCurrent()); 1317 | result = result.GetNext(); 1318 | first2 = first2.GetNext(); 1319 | } 1320 | else 1321 | { 1322 | first1 = first1.GetNext(); 1323 | first2 = first2.GetNext(); 1324 | } 1325 | } 1326 | } 1327 | 1328 | public static void PushHeap( 1329 | this NativeArrayIterator first, 1330 | NativeArrayIterator last, 1331 | Func comp 1332 | ) 1333 | where T : struct 1334 | { 1335 | if (first.Distance(last) < 2) 1336 | { 1337 | return; 1338 | } 1339 | last = last.GetPrev(); 1340 | var temp = last.GetCurrent(); 1341 | var parent = first.GetAdvanced((first.Distance(last) - 1) / 2); 1342 | while (first.Distance(last) > 0 && comp(parent.GetCurrent(), temp)) 1343 | { 1344 | last.SetCurrent(parent.GetCurrent()); 1345 | last = parent; 1346 | parent = first.GetAdvanced((first.Distance(last) - 1) / 2); 1347 | } 1348 | last.SetCurrent(temp); 1349 | } 1350 | 1351 | public static void PopHeap( 1352 | this NativeArrayIterator first, 1353 | NativeArrayIterator last, 1354 | Func comp 1355 | ) 1356 | where T : struct 1357 | { 1358 | if (first.Distance(last) < 2) 1359 | { 1360 | return; 1361 | } 1362 | last = last.GetPrev(); 1363 | Swap(first, last); 1364 | AdjustHeap(first.Array, first.Index, first.Index, last.Index, comp); 1365 | } 1366 | 1367 | public static void MakeHeap( 1368 | this NativeArrayIterator first, 1369 | NativeArrayIterator last, 1370 | Func comp 1371 | ) 1372 | where T : struct 1373 | { 1374 | var dist = first.Distance(last); 1375 | if (dist < 2) 1376 | { 1377 | return; 1378 | } 1379 | var parent = (dist - 2) / 2; 1380 | do 1381 | { 1382 | AdjustHeap(first.Array, first.Index, first.Index + parent, last.Index, comp); 1383 | } 1384 | while (parent-- != 0); 1385 | } 1386 | 1387 | public static void SortHeap( 1388 | this NativeArrayIterator first, 1389 | NativeArrayIterator last, 1390 | Func comp 1391 | ) 1392 | where T : struct 1393 | { 1394 | while (first.Distance(last) > 1) 1395 | { 1396 | last = last.GetPrev(); 1397 | Swap(first, last); 1398 | AdjustHeap(first.Array, first.Index, first.Index, last.Index, comp); 1399 | } 1400 | } 1401 | 1402 | public static NativeArrayIterator MinElement( 1403 | this NativeArrayIterator first, 1404 | NativeArrayIterator last, 1405 | Func comp 1406 | ) 1407 | where T : struct 1408 | { 1409 | if (first.IsEqual(last)) 1410 | { 1411 | return last; 1412 | } 1413 | var smallest = first; 1414 | while ((first = first.GetNext()).NotEqual(last)) 1415 | { 1416 | if (comp(first.GetCurrent(), smallest.GetCurrent())) 1417 | { 1418 | smallest = first; 1419 | } 1420 | } 1421 | return smallest; 1422 | } 1423 | 1424 | public static NativeArrayIterator MaxElement( 1425 | this NativeArrayIterator first, 1426 | NativeArrayIterator last, 1427 | Func comp 1428 | ) 1429 | where T : struct 1430 | { 1431 | if (first.IsEqual(last)) 1432 | { 1433 | return last; 1434 | } 1435 | var largest = first; 1436 | while ((first = first.GetNext()).NotEqual(last)) 1437 | { 1438 | if (comp(largest.GetCurrent(), first.GetCurrent())) 1439 | { 1440 | largest = first; 1441 | } 1442 | } 1443 | return largest; 1444 | } 1445 | 1446 | public static void MinMaxElement( 1447 | this NativeArrayIterator first, 1448 | NativeArrayIterator last, 1449 | Func comp, 1450 | out NativeArrayIterator min, 1451 | out NativeArrayIterator max 1452 | ) 1453 | where T : struct 1454 | { 1455 | if (first.IsEqual(last)) 1456 | { 1457 | min = last; 1458 | max = last; 1459 | } 1460 | min = first; 1461 | max = first; 1462 | while ((first = first.GetNext()).NotEqual(last)) 1463 | { 1464 | if (comp(first.GetCurrent(), min.GetCurrent())) 1465 | { 1466 | min = first; 1467 | } 1468 | if (comp(max.GetCurrent(), first.GetCurrent())) 1469 | { 1470 | max = first; 1471 | } 1472 | } 1473 | } 1474 | 1475 | public static bool LexicographicalCompare( 1476 | this NativeArrayIterator first1, 1477 | NativeArrayIterator last1, 1478 | NativeArrayIterator first2, 1479 | NativeArrayIterator last2, 1480 | Func comp 1481 | ) 1482 | where T : struct 1483 | { 1484 | while (first1.NotEqual(last1)) 1485 | { 1486 | if (first2.IsEqual(last2) || comp(first2.GetCurrent(), first1.GetCurrent())) 1487 | { 1488 | return false; 1489 | } 1490 | else if (comp(first1.GetCurrent(), first2.GetCurrent())) 1491 | { 1492 | return true; 1493 | } 1494 | first1 = first1.GetNext(); 1495 | first2 = first2.GetNext(); 1496 | } 1497 | return first2.NotEqual(last2); 1498 | } 1499 | 1500 | public static bool NextPermutation( 1501 | this NativeArrayIterator first, 1502 | NativeArrayIterator last, 1503 | Func comp 1504 | ) 1505 | where T : struct 1506 | { 1507 | var i = last; 1508 | if (first.IsEqual(last) || first.IsEqual((i = i.GetPrev()))) 1509 | { 1510 | return false; 1511 | } 1512 | while (true) 1513 | { 1514 | var ip1 = i; 1515 | if (comp((i = i.GetPrev()).GetCurrent(), ip1.GetCurrent())) 1516 | { 1517 | var j = last; 1518 | while (comp(i.GetCurrent(), (j = j.GetPrev()).GetCurrent()) == false) 1519 | { 1520 | } 1521 | Swap(i, j); 1522 | Reverse(ip1, last); 1523 | return true; 1524 | } 1525 | if (i.IsEqual(first)) 1526 | { 1527 | Reverse(first, last); 1528 | return false; 1529 | } 1530 | } 1531 | } 1532 | 1533 | public static bool PrevPermutation( 1534 | this NativeArrayIterator first, 1535 | NativeArrayIterator last, 1536 | Func comp 1537 | ) 1538 | where T : struct 1539 | { 1540 | var i = last; 1541 | if (first.IsEqual(last) || first.IsEqual(i = i.GetPrev())) 1542 | { 1543 | return false; 1544 | } 1545 | while (true) 1546 | { 1547 | var ip1 = i; 1548 | if (comp(ip1.GetCurrent(), (i = i.GetPrev()).GetCurrent())) 1549 | { 1550 | var j = last; 1551 | while (comp((j = j.GetPrev()).GetCurrent(), i.GetCurrent()) == false) 1552 | { 1553 | } 1554 | Swap(i, j); 1555 | Reverse(ip1, last); 1556 | return true; 1557 | } 1558 | if (i.IsEqual(first)) 1559 | { 1560 | Reverse(first, last); 1561 | return false; 1562 | } 1563 | } 1564 | } 1565 | 1566 | private static void AdjustHeap( 1567 | this NativeArray array, 1568 | int first, 1569 | int position, 1570 | int last, 1571 | Func comp 1572 | ) 1573 | where T : struct 1574 | { 1575 | var tmp = array[position]; 1576 | int len = last - first; 1577 | int holeIndex = position - first; 1578 | int secondChild = 2 * holeIndex + 2; 1579 | while (secondChild < len) 1580 | { 1581 | if ( 1582 | comp( 1583 | array[first + secondChild], 1584 | array[first + (secondChild - 1)] 1585 | ) 1586 | ) 1587 | { 1588 | --secondChild; 1589 | } 1590 | array[first + holeIndex] = array[first + secondChild]; 1591 | holeIndex = secondChild++; 1592 | secondChild *= 2; 1593 | } 1594 | if (secondChild-- == len) 1595 | { 1596 | array[first + holeIndex] = array[first + secondChild]; 1597 | holeIndex = secondChild; 1598 | } 1599 | var parent = (holeIndex - 1) / 2; 1600 | var topIndex = position - first; 1601 | while (holeIndex != topIndex && comp(array[first + parent], tmp)) 1602 | { 1603 | array[first + holeIndex] = array[first + parent]; 1604 | holeIndex = parent; 1605 | parent = (holeIndex - 1) / 2; 1606 | } 1607 | array[first + holeIndex] = tmp; 1608 | } 1609 | 1610 | public static bool IsHeap( 1611 | this NativeArrayIterator first, 1612 | NativeArrayIterator last, 1613 | Func comp 1614 | ) 1615 | where T : struct 1616 | { 1617 | return first.IsHeapUntil(last, comp).IsEqual(last); 1618 | } 1619 | 1620 | public static NativeArrayIterator IsHeapUntil( 1621 | this NativeArrayIterator first, 1622 | NativeArrayIterator last, 1623 | Func comp 1624 | ) 1625 | where T : struct 1626 | { 1627 | var len = first.Distance(last); 1628 | var p = 0; 1629 | var c = 1; 1630 | var pp = first; 1631 | while (c < len) 1632 | { 1633 | var cp = first.GetAdvanced(c); 1634 | if (comp(pp.GetCurrent(), cp.GetCurrent())) 1635 | { 1636 | return cp; 1637 | } 1638 | c++; 1639 | cp = cp.GetNext(); 1640 | if (c == len) 1641 | { 1642 | return last; 1643 | } 1644 | if (comp(pp.GetCurrent(), cp.GetCurrent())) 1645 | { 1646 | return cp; 1647 | } 1648 | p++; 1649 | pp = pp.GetNext(); 1650 | c = 2 * p + 1; 1651 | } 1652 | return last; 1653 | } 1654 | } 1655 | } 1656 | 1657 | #endif -------------------------------------------------------------------------------- /JacksonDunstanIterator/NativeArrayIterator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44acba551e640440691ab0271dea4d7e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc03eeab9cdf54aa4addd8b841f18849 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/JacksonDunstanIteratorTests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JacksonDunstanIteratorTests", 3 | "references": [ 4 | "JacksonDunstanIterator" 5 | ], 6 | "optionalUnityReferences": [ 7 | "TestAssemblies" 8 | ], 9 | "includePlatforms": [ 10 | "Editor" 11 | ], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": false 14 | } -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/JacksonDunstanIteratorTests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8e5c0d282f93e46638b33dc872555153 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/TestArrayIterator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt. 4 | // 5 | //----------------------------------------------------------------------- 6 | 7 | using System; 8 | using System.Linq; 9 | using JacksonDunstanIterator; 10 | using NUnit.Framework; 11 | 12 | public class TestArrayIterator 13 | { 14 | private MonotonicRandom random; 15 | private int[] defaultArr; 16 | private int[] arr; 17 | private int[] arr2; 18 | private int[] arr3; 19 | private int[] arrLong; 20 | private Func AreIntsEqual; 21 | private Func IsIntEven; 22 | private Func IsIntEqualTo2; 23 | private Func IsIntLessThanOrEqualTo2; 24 | private Func IsIntGreaterThan0; 25 | private Func IsIntGreaterThan10; 26 | private Func DoubleInt; 27 | private Func MultiplyInts; 28 | private Func IsIntGreaterThanInt; 29 | private Func IsIntLessThanInt; 30 | private Func RandomIntLessThan; 31 | private int[] OneThreeThreeFour; 32 | private int[] OneThreeTwoFour; 33 | private int[] ThreeTwoOne; 34 | private int[] TwoThree; 35 | private int[] FourTwoThreeOne; 36 | private int[] OneTwoThreeFour; 37 | 38 | [SetUp] 39 | public void SetUp() 40 | { 41 | random = new MonotonicRandom(); 42 | defaultArr = new [] { 1, 2, 2, 3 }; 43 | arr = defaultArr.ToArray(); 44 | arr2 = new int[arr.Length]; 45 | arr3 = new int[arr.Length]; 46 | arrLong = new int[arr.Length * 2]; 47 | AreIntsEqual = (a, b) => a == b; 48 | IsIntEven = i => i % 2 == 0; 49 | IsIntEqualTo2 = i => i == 2; 50 | IsIntLessThanOrEqualTo2 = i => i <= 2; 51 | IsIntGreaterThan0 = i => i > 0; 52 | IsIntGreaterThan10 = i => i > 10; 53 | DoubleInt = i => i * 2; 54 | MultiplyInts = (a, b) => a * b; 55 | IsIntGreaterThanInt = (a, b) => a > b; 56 | IsIntLessThanInt = (a, b) => a < b; 57 | RandomIntLessThan = random.Next; 58 | OneThreeThreeFour = new [] { 1, 3, 3, 4 }; 59 | OneThreeTwoFour = new [] { 1, 3, 2, 4 }; 60 | ThreeTwoOne = new [] { 3, 2, 1 }; 61 | TwoThree = new [] { 2, 3 }; 62 | FourTwoThreeOne = new [] { 4, 2, 3, 1 }; 63 | OneTwoThreeFour = new [] { 1, 2, 3, 4 }; 64 | } 65 | 66 | [Test] 67 | public void GetAdvanced() 68 | { 69 | Assert.That(arr.Begin().GetAdvanced(1).GetCurrent(), Is.EqualTo(2)); 70 | } 71 | 72 | [Test] 73 | public void Distance() 74 | { 75 | Assert.That(arr.Begin().Distance(arr.End()), Is.EqualTo(4)); 76 | } 77 | 78 | [Test] 79 | public void AllOf() 80 | { 81 | Assert.That(arr.Begin().AllOf(arr.End(), IsIntEven), Is.False); 82 | Assert.That(arr.Begin().AllOf(arr.End(), IsIntGreaterThan0), Is.True); 83 | } 84 | 85 | [Test] 86 | public void AnyOf() 87 | { 88 | Assert.That(arr.Begin().AnyOf(arr.End(), IsIntGreaterThan10), Is.False); 89 | Assert.That(arr.Begin().AnyOf(arr.End(), IsIntEqualTo2), Is.True); 90 | } 91 | 92 | [Test] 93 | public void NoneOf() 94 | { 95 | Assert.That(arr.Begin().NoneOf(arr.End(), IsIntEqualTo2), Is.False); 96 | Assert.That(arr.Begin().NoneOf(arr.End(), IsIntGreaterThan10), Is.True); 97 | } 98 | 99 | [Test] 100 | public void ForEach() 101 | { 102 | int index = 0; 103 | arr.Begin().ForEach( 104 | arr.End(), 105 | i => Assert.That(i, Is.EqualTo(arr[index++])) 106 | ); 107 | } 108 | 109 | [Test] 110 | public void Find() 111 | { 112 | Assert.That( 113 | arr.Begin().Find( 114 | arr.End(), 115 | 2, 116 | AreIntsEqual).Index, 117 | Is.EqualTo(1)); 118 | } 119 | 120 | [Test] 121 | public void FindIf() 122 | { 123 | Assert.That( 124 | arr.Begin().FindIf( 125 | arr.End(), 126 | IsIntEven).Index, 127 | Is.EqualTo(1)); 128 | } 129 | 130 | [Test] 131 | public void FindIfNot() 132 | { 133 | Assert.That( 134 | arr.Begin().FindIfNot( 135 | arr.End(), 136 | IsIntEven).Index, 137 | Is.EqualTo(0)); 138 | } 139 | 140 | [Test] 141 | public void FindEnd() 142 | { 143 | Assert.That( 144 | arr.Begin().FindEnd( 145 | arr.End(), 146 | arr.IteratorAt(1), 147 | arr.IteratorAt(2), 148 | AreIntsEqual 149 | ).Index, 150 | Is.EqualTo(2) 151 | ); 152 | } 153 | 154 | [Test] 155 | public void FindFirstOf() 156 | { 157 | Assert.That( 158 | arr.Begin().FindFirstOf( 159 | arr.End(), 160 | arr.IteratorAt(1), 161 | arr.IteratorAt(2), 162 | AreIntsEqual 163 | ).Index, 164 | Is.EqualTo(1) 165 | ); 166 | } 167 | 168 | [Test] 169 | public void AdjacentFind() 170 | { 171 | Assert.That( 172 | arr.Begin().AdjacentFind(arr.End(), AreIntsEqual).Index, 173 | Is.EqualTo(1)); 174 | } 175 | 176 | [Test] 177 | public void Count() 178 | { 179 | Assert.That( 180 | arr.Begin().Count(arr.End(), 2, AreIntsEqual), 181 | Is.EqualTo(2)); 182 | } 183 | 184 | [Test] 185 | public void CountIf() 186 | { 187 | Assert.That(arr.Begin().CountIf(arr.End(), IsIntEven), Is.EqualTo(2)); 188 | } 189 | 190 | [Test] 191 | public void Mismatch() 192 | { 193 | ArrayIterator mm1; 194 | ArrayIterator mm2; 195 | arr.Begin().Mismatch( 196 | arr.End(), 197 | new[] { 1, 3, 3, 4 }.Begin(), 198 | AreIntsEqual, 199 | out mm1, 200 | out mm2 201 | ); 202 | Assert.That(mm1.GetCurrent(), Is.EqualTo(2)); 203 | Assert.That(mm2.GetCurrent(), Is.EqualTo(3)); 204 | } 205 | 206 | [Test] 207 | public void Equal() 208 | { 209 | Assert.That( 210 | arr.Begin().Equal( 211 | arr.End(), 212 | new[] { 1, 3, 2, 3 }.Begin(), 213 | AreIntsEqual), 214 | Is.False); 215 | Assert.That( 216 | arr.Begin().Equal( 217 | arr.End(), 218 | new[] { 1, 2, 2, 3 }.Begin(), 219 | AreIntsEqual), 220 | Is.True); 221 | } 222 | 223 | [Test] 224 | public void IsPermutation() 225 | { 226 | Assert.That( 227 | arr.Begin().IsPermutation( 228 | arr.End(), 229 | new[] { 3, 3, 1, 2 }.Begin(), 230 | AreIntsEqual), 231 | Is.False); 232 | Assert.That( 233 | arr.Begin().IsPermutation( 234 | arr.End(), 235 | new[] { 3, 2, 1, 2 }.Begin(), 236 | AreIntsEqual), 237 | Is.True); 238 | } 239 | 240 | [Test] 241 | public void Search() 242 | { 243 | var sub = new[] { 2, 3 }; 244 | Assert.That( 245 | arr.Begin().Search( 246 | arr.End(), 247 | sub.Begin(), 248 | sub.End(), 249 | AreIntsEqual).Index, 250 | Is.EqualTo(2)); 251 | } 252 | 253 | [Test] 254 | public void SearchN() 255 | { 256 | Assert.That( 257 | arr.Begin().SearchN(arr.End(), 2, 2, AreIntsEqual).Index, 258 | Is.EqualTo(1)); 259 | } 260 | 261 | [Test] 262 | public void Copy() 263 | { 264 | Assert.That( 265 | arr.Begin().Copy(arr.IteratorAt(2), arr2.Begin()).Index, 266 | Is.EqualTo(2)); 267 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 0, 0 })); 268 | } 269 | 270 | [Test] 271 | public void CopyN() 272 | { 273 | Assert.That(arr.Begin().CopyN(3, arr2.Begin()).Index, Is.EqualTo(3)); 274 | Assert.That(arr2, Is.EqualTo(new [] { 1, 2, 2, 0 })); 275 | } 276 | 277 | [Test] 278 | public void CopyIf() 279 | { 280 | Assert.That( 281 | arr.Begin().CopyIf(arr.End(), arr2.Begin(), IsIntEven).Index, 282 | Is.EqualTo(2)); 283 | Assert.That(arr2, Is.EqualTo(new [] { 2, 2, 0, 0 })); 284 | } 285 | 286 | [Test] 287 | public void CopyBackward() 288 | { 289 | Assert.That( 290 | arr.IteratorAt(1).CopyBackward(arr.IteratorAt(3), arr2.End()).Index, 291 | Is.EqualTo(2)); 292 | Assert.That(arr2, Is.EqualTo(new [] { 0, 0, 2, 2 })); 293 | } 294 | 295 | [Test] 296 | public void SwapRanges() 297 | { 298 | Assert.That( 299 | arr.IteratorAt(1).SwapRanges( 300 | arr.IteratorAt(3), 301 | arr2.IteratorAt(1)).Index, 302 | Is.EqualTo(3)); 303 | Assert.That(arr, Is.EqualTo(new [] { 1, 0, 0, 3 })); 304 | Assert.That(arr2, Is.EqualTo(new [] { 0, 2, 2, 0 })); 305 | } 306 | 307 | [Test] 308 | public void Swap() 309 | { 310 | var itA = arr.IteratorAt(0); 311 | var itB = arr.IteratorAt(1); 312 | itA.Swap(itB); 313 | Assert.That(arr, Is.EqualTo(new [] { 2, 1, 2, 3 })); 314 | } 315 | 316 | [Test] 317 | public void TransformDouble() 318 | { 319 | Assert.That( 320 | arr.Begin().Transform(arr.End(), arr.Begin(), DoubleInt).Index, 321 | Is.EqualTo(4)); 322 | Assert.That(arr, Is.EqualTo(new [] { 2, 4, 4, 6 })); 323 | } 324 | 325 | [Test] 326 | public void TransformMultiply() 327 | { 328 | Assert.That( 329 | arr.Begin().Transform( 330 | arr.End(), 331 | arr.Begin(), 332 | arr.Begin(), 333 | MultiplyInts).Index, 334 | Is.EqualTo(4)); 335 | Assert.That(arr, Is.EqualTo(new [] { 1, 4, 4, 9 })); 336 | } 337 | 338 | [Test] 339 | public void ReplaceIf() 340 | { 341 | arr.Begin().ReplaceIf(arr.End(), IsIntEqualTo2, 20); 342 | Assert.That(arr, Is.EqualTo(new [] { 1, 20, 20, 3 })); 343 | } 344 | 345 | [Test] 346 | public void ReplaceCopyIf() 347 | { 348 | Assert.That( 349 | arr.Begin().ReplaceCopyIf( 350 | arr.End(), 351 | arr.Begin(), 352 | IsIntEven, 353 | 200).Index, 354 | Is.EqualTo(4)); 355 | Assert.That(arr, Is.EqualTo(new [] { 1, 200, 200, 3 })); 356 | } 357 | 358 | [Test] 359 | public void Unique() 360 | { 361 | Assert.That( 362 | arr.Begin().Unique(arr.End(), AreIntsEqual).Index, 363 | Is.EqualTo(3)); 364 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 3, 3 })); 365 | } 366 | 367 | [Test] 368 | public void UniqueCopy() 369 | { 370 | Assert.That( 371 | arr.Begin().UniqueCopy(arr.End(), arr2.Begin(), AreIntsEqual).Index, 372 | Is.EqualTo(3)); 373 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 374 | Assert.That(arr2, Is.EqualTo(new [] { 1, 2, 3, 0 })); 375 | } 376 | 377 | [Test] 378 | public void Reverse() 379 | { 380 | arr.Begin().Reverse(arr.End()); 381 | Assert.That(arr, Is.EqualTo(new [] { 3, 2, 2, 1 })); 382 | } 383 | 384 | [Test] 385 | public void ReverseCopy() 386 | { 387 | Assert.That( 388 | arr.Begin().ReverseCopy(arr.End(), arr2.Begin()).Index, 389 | Is.EqualTo(4)); 390 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 2, 3 })); 391 | Assert.That(arr2, Is.EqualTo(new [] { 3, 2, 2, 1 })); 392 | } 393 | 394 | [Test] 395 | public void Rotate() 396 | { 397 | arr.Begin().Rotate(arr.IteratorAt(2), arr.End()); 398 | Assert.That(arr, Is.EqualTo(new [] { 2, 3, 1, 2 })); 399 | } 400 | 401 | [Test] 402 | public void RotateCopy() 403 | { 404 | Assert.That( 405 | arr.Begin().RotateCopy( 406 | arr.IteratorAt(2), 407 | arr.End(), 408 | arr2.Begin()).Index, 409 | Is.EqualTo(4)); 410 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 2, 3 })); 411 | Assert.That(arr2, Is.EqualTo(new [] { 2, 3, 1, 2 })); 412 | } 413 | 414 | [Test] 415 | public void RandomShuffle() 416 | { 417 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan); 418 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 2, 1 })); 419 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan); 420 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 3, 1 })); 421 | } 422 | 423 | [Test] 424 | public void IsPartitioned() 425 | { 426 | Assert.That(arr.Begin().IsPartitioned(arr.End(), IsIntEven), Is.False); 427 | Assert.That( 428 | arr.Begin().IsPartitioned(arr.End(), IsIntLessThanOrEqualTo2), 429 | Is.True); 430 | } 431 | 432 | [Test] 433 | public void Partition() 434 | { 435 | Assert.That( 436 | arr.Begin().Partition(arr.End(), IsIntEven).Index, 437 | Is.EqualTo(2)); 438 | Assert.That(arr, Is.EqualTo(new [] { 2, 2, 1, 3})); 439 | } 440 | 441 | [Test] 442 | public void PartitionCopy() 443 | { 444 | ArrayIterator outResultTrue; 445 | ArrayIterator outResultFalse; 446 | arr.Begin().PartitionCopy( 447 | arr.End(), 448 | arr2.Begin(), 449 | arr3.Begin(), 450 | IsIntEven, 451 | out outResultTrue, 452 | out outResultFalse 453 | ); 454 | Assert.That(outResultTrue.Index, Is.EqualTo(2)); 455 | Assert.That(outResultFalse.Index, Is.EqualTo(2)); 456 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 2, 3 })); 457 | Assert.That(arr2, Is.EqualTo(new [] { 2, 2, 0, 0 })); 458 | Assert.That(arr3, Is.EqualTo(new [] { 1, 3, 0, 0 })); 459 | } 460 | 461 | [Test] 462 | public void PartitionPoint() 463 | { 464 | Assert.That( 465 | arr.Begin().PartitionPoint( 466 | arr.End(), 467 | IsIntLessThanOrEqualTo2).Index, 468 | Is.EqualTo(2)); 469 | } 470 | 471 | [Test] 472 | public void Sort() 473 | { 474 | arr.Begin().Sort(arr.End(), IsIntGreaterThanInt); 475 | Assert.That(arr, Is.EqualTo(new [] { 3, 2, 2, 1 })); 476 | } 477 | 478 | [Test] 479 | public void StableSort() 480 | { 481 | arr.Begin().StableSort(arr.End(), IsIntGreaterThanInt); 482 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 483 | } 484 | 485 | [Test] 486 | public void PartialSort() 487 | { 488 | arr.Begin().PartialSort( 489 | arr.IteratorAt(2), 490 | arr.End(), 491 | IsIntGreaterThanInt); 492 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 493 | } 494 | 495 | [Test] 496 | public void IsSorted() 497 | { 498 | Assert.That(arr.Begin().IsSorted(arr.End(), IsIntLessThanInt), Is.True); 499 | } 500 | 501 | [Test] 502 | public void IsSortedUtil() 503 | { 504 | Assert.That( 505 | OneThreeTwoFour.Begin().IsSortedUntil( 506 | OneThreeTwoFour.End(), 507 | IsIntLessThanInt).Index, 508 | Is.EqualTo(2)); 509 | } 510 | 511 | [Test] 512 | public void NthElement() 513 | { 514 | OneThreeTwoFour.Begin().Copy(OneThreeTwoFour.End(), arr.Begin()); 515 | arr.Begin().NthElement(arr.IteratorAt(2), arr.End(), IsIntLessThanInt); 516 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 3, 4 })); 517 | } 518 | 519 | [Test] 520 | public void LowerBound() 521 | { 522 | Assert.That( 523 | arr.Begin().LowerBound(arr.End(), 2, IsIntLessThanInt).Index, 524 | Is.EqualTo(1)); 525 | } 526 | 527 | [Test] 528 | public void UpperBound() 529 | { 530 | Assert.That( 531 | arr.Begin().UpperBound(arr.End(), 2, IsIntLessThanInt).Index, 532 | Is.EqualTo(3)); 533 | } 534 | 535 | [Test] 536 | public void EqualRange() 537 | { 538 | ArrayIterator equalRangeLower; 539 | ArrayIterator equalRangeUpper; 540 | arr.Begin().EqualRange( 541 | arr.End(), 542 | 2, 543 | IsIntLessThanInt, 544 | out equalRangeLower, 545 | out equalRangeUpper 546 | ); 547 | Assert.That(equalRangeLower.Index, Is.EqualTo(1)); 548 | Assert.That(equalRangeUpper.Index, Is.EqualTo(3)); 549 | } 550 | 551 | [Test] 552 | public void BinarySearch() 553 | { 554 | Assert.That( 555 | arr.Begin().BinarySearch(arr.End(), 2, IsIntLessThanInt), 556 | Is.True); 557 | Assert.That( 558 | arr.Begin().BinarySearch(arr.End(), 9, IsIntLessThanInt), 559 | Is.False); 560 | } 561 | 562 | [Test] 563 | public void Merge() 564 | { 565 | Assert.That( 566 | arr.Begin().Merge( 567 | arr.End(), 568 | OneThreeThreeFour.Begin(), 569 | OneThreeThreeFour.End(), 570 | arrLong.Begin(), 571 | IsIntLessThanInt 572 | ).Index, 573 | Is.EqualTo(8)); 574 | Assert.That(arrLong, Is.EqualTo(new [] { 1, 1, 2, 2, 3, 3, 3, 4 })); 575 | } 576 | 577 | [Test] 578 | public void InplaceMerge() 579 | { 580 | ArrayIterator copyResult = arr.Begin().Copy( 581 | arr.End(), 582 | arrLong.Begin()); 583 | OneThreeThreeFour.Begin().Copy(OneThreeThreeFour.End(), copyResult); 584 | arrLong.Begin().InplaceMerge( 585 | copyResult, 586 | arrLong.End(), 587 | IsIntLessThanInt); 588 | Assert.That(arrLong, Is.EqualTo(new [] { 1, 1, 2, 2, 3, 3, 3, 4 })); 589 | } 590 | 591 | [Test] 592 | public void Includes() 593 | { 594 | Assert.That( 595 | arr.Begin().Includes( 596 | arr.End(), 597 | TwoThree.Begin(), 598 | TwoThree.End(), 599 | IsIntLessThanInt), 600 | Is.True); 601 | } 602 | 603 | [Test] 604 | public void SetUnion() 605 | { 606 | Assert.That( 607 | arr.Begin().SetUnion( 608 | arr.End(), 609 | OneThreeThreeFour.Begin(), 610 | OneThreeThreeFour.End(), 611 | arrLong.Begin(), 612 | IsIntLessThanInt 613 | ).Index, 614 | Is.EqualTo(6)); 615 | Assert.That(arrLong, Is.EqualTo(new[] { 1, 2, 2, 3, 3, 4, 0, 0 })); 616 | } 617 | 618 | [Test] 619 | public void SetIntersection() 620 | { 621 | Assert.That( 622 | arr.Begin().SetIntersection( 623 | arr.End(), 624 | OneThreeThreeFour.Begin(), 625 | OneThreeThreeFour.End(), 626 | arrLong.Begin(), 627 | IsIntLessThanInt 628 | ).Index, 629 | Is.EqualTo(2)); 630 | Assert.That(arrLong, Is.EqualTo(new [] { 1, 3, 0, 0, 0, 0, 0, 0 })); 631 | } 632 | 633 | [Test] 634 | public void SetDifference() 635 | { 636 | Assert.That( 637 | arr.Begin().SetDifference( 638 | arr.End(), 639 | OneThreeThreeFour.Begin(), 640 | OneThreeThreeFour.End(), 641 | arrLong.Begin(), 642 | IsIntLessThanInt 643 | ).Index, 644 | Is.EqualTo(2)); 645 | Assert.That(arrLong, Is.EqualTo(new [] { 2, 2, 0, 0, 0, 0, 0, 0 })); 646 | } 647 | 648 | [Test] 649 | public void SetSymmetricDifference() 650 | { 651 | Assert.That( 652 | arr.Begin().SetSymmetricDifference( 653 | arr.End(), 654 | OneThreeThreeFour.Begin(), 655 | OneThreeThreeFour.End(), 656 | arrLong.Begin(), 657 | IsIntLessThanInt 658 | ).Index, 659 | Is.EqualTo(4)); 660 | Assert.That(arrLong, Is.EqualTo(new [] { 2, 2, 3, 4, 0, 0, 0, 0 })); 661 | } 662 | 663 | [Test] 664 | public void PushHeap() 665 | { 666 | ArrayIterator pushHeapIt = FourTwoThreeOne.Begin().Copy( 667 | FourTwoThreeOne.End(), 668 | arrLong.Begin()); 669 | pushHeapIt.SetCurrent(5); 670 | pushHeapIt = pushHeapIt.GetNext(); 671 | arrLong.Begin().PushHeap(pushHeapIt, IsIntLessThanInt); 672 | Assert.That(arrLong, Is.EqualTo(new [] { 5, 4, 3, 1, 2, 0, 0, 0 })); 673 | } 674 | 675 | [Test] 676 | public void PopHeap() 677 | { 678 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin()); 679 | arr2.Begin().PopHeap(arr2.End(), IsIntLessThanInt); 680 | Assert.That(arr2, Is.EqualTo(new [] { 3, 2, 1, 4 })); 681 | } 682 | 683 | [Test] 684 | public void MakeHeap() 685 | { 686 | OneTwoThreeFour.Begin().Copy(OneTwoThreeFour.End(), arr2.Begin()); 687 | arr2.Begin().MakeHeap(arr2.End(), IsIntLessThanInt); 688 | Assert.That(arr2, Is.EqualTo(new[] { 4, 2, 3, 1 })); 689 | } 690 | 691 | [Test] 692 | public void SortHeap() 693 | { 694 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin()); 695 | arr2.Begin().SortHeap(arr2.End(), IsIntLessThanInt); 696 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 3, 4 })); 697 | } 698 | 699 | [Test] 700 | public void IsHeap() 701 | { 702 | Assert.That( 703 | FourTwoThreeOne.Begin().IsHeap( 704 | FourTwoThreeOne.End(), 705 | IsIntLessThanInt), Is.True); 706 | } 707 | 708 | [Test] 709 | public void IsHeapUntil() 710 | { 711 | Assert.That( 712 | FourTwoThreeOne.Begin().IsHeapUntil( 713 | FourTwoThreeOne.End(), 714 | IsIntLessThanInt).Index, 715 | Is.EqualTo(4)); 716 | } 717 | 718 | [Test] 719 | public void MinElement() 720 | { 721 | Assert.That( 722 | arr.Begin().MinElement(arr.End(), IsIntLessThanInt).Index, 723 | Is.EqualTo(0)); 724 | } 725 | 726 | [Test] 727 | public void MaxElement() 728 | { 729 | Assert.That( 730 | arr.Begin().MaxElement(arr.End(), IsIntLessThanInt).Index, 731 | Is.EqualTo(3)); 732 | } 733 | 734 | [Test] 735 | public void MinMaxElement() 736 | { 737 | ArrayIterator minIt; 738 | ArrayIterator maxIt; 739 | arr.Begin().MinMaxElement( 740 | arr.End(), 741 | IsIntLessThanInt, 742 | out minIt, 743 | out maxIt); 744 | Assert.That(minIt.Index, Is.EqualTo(0)); 745 | Assert.That(maxIt.Index, Is.EqualTo(3)); 746 | } 747 | 748 | [Test] 749 | public void LexicographicCompare() 750 | { 751 | Assert.That( 752 | arr.Begin().LexicographicalCompare( 753 | arr.End(), 754 | arr2.Begin(), 755 | arr2.End(), 756 | IsIntLessThanInt), 757 | Is.False); 758 | Assert.That( 759 | arr2.Begin().LexicographicalCompare( 760 | arr2.End(), 761 | arr.Begin(), 762 | arr.End(), 763 | IsIntLessThanInt), 764 | Is.True); 765 | } 766 | 767 | [Test] 768 | public void NextPermutation() 769 | { 770 | Assert.That( 771 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 772 | Is.True); 773 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 3, 2 })); 774 | 775 | Assert.That( 776 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 777 | Is.True); 778 | Assert.That(arr, Is.EqualTo(new[] { 1, 3, 2, 2 })); 779 | 780 | Assert.That( 781 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 782 | Is.True); 783 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 2, 3 })); 784 | 785 | Assert.That( 786 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 787 | Is.True); 788 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 3, 2 })); 789 | 790 | Assert.That( 791 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 792 | Is.True); 793 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 1, 3 })); 794 | 795 | Assert.That( 796 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 797 | Is.True); 798 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 3, 1 })); 799 | 800 | Assert.That( 801 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 802 | Is.True); 803 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 1, 2 })); 804 | 805 | Assert.That( 806 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 807 | Is.True); 808 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 2, 1 })); 809 | 810 | Assert.That( 811 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 812 | Is.True); 813 | Assert.That(arr, Is.EqualTo(new[] { 3, 1, 2, 2 })); 814 | 815 | Assert.That( 816 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 817 | Is.True); 818 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 1, 2 })); 819 | 820 | Assert.That( 821 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 822 | Is.True); 823 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 824 | 825 | Assert.That( 826 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 827 | Is.False); 828 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 829 | } 830 | 831 | [Test] 832 | public void PrevPermutation() 833 | { 834 | Assert.That( 835 | ThreeTwoOne.Begin().PrevPermutation( 836 | ThreeTwoOne.End(), 837 | IsIntLessThanInt), 838 | Is.True); 839 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 3, 1, 2 })); 840 | 841 | 842 | Assert.That( 843 | ThreeTwoOne.Begin().PrevPermutation( 844 | ThreeTwoOne.End(), 845 | IsIntLessThanInt), 846 | Is.True); 847 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 2, 3, 1 })); 848 | 849 | Assert.That( 850 | ThreeTwoOne.Begin().PrevPermutation( 851 | ThreeTwoOne.End(), 852 | IsIntLessThanInt), 853 | Is.True); 854 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 2, 1, 3 })); 855 | 856 | 857 | Assert.That( 858 | ThreeTwoOne.Begin().PrevPermutation( 859 | ThreeTwoOne.End(), 860 | IsIntLessThanInt), 861 | Is.True); 862 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 1, 3, 2 })); 863 | 864 | 865 | Assert.That( 866 | ThreeTwoOne.Begin().PrevPermutation( 867 | ThreeTwoOne.End(), 868 | IsIntLessThanInt), 869 | Is.True); 870 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 1, 2, 3 })); 871 | 872 | Assert.That( 873 | ThreeTwoOne.Begin().PrevPermutation( 874 | ThreeTwoOne.End(), 875 | IsIntLessThanInt), 876 | Is.False); 877 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 3, 2, 1 })); 878 | } 879 | } -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/TestArrayIterator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 991b342446f344eae8a17c35ddc1c05a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/TestListIterator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt. 4 | // 5 | //----------------------------------------------------------------------- 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using JacksonDunstanIterator; 11 | using NUnit.Framework; 12 | 13 | public class TestListIterator 14 | { 15 | private MonotonicRandom random; 16 | private List defaultArr; 17 | private List arr; 18 | private List arr2; 19 | private List arr3; 20 | private List arrLong; 21 | private Func AreIntsEqual; 22 | private Func IsIntEven; 23 | private Func IsIntEqualTo2; 24 | private Func IsIntLessThanOrEqualTo2; 25 | private Func IsIntGreaterThan0; 26 | private Func IsIntGreaterThan10; 27 | private Func DoubleInt; 28 | private Func MultiplyInts; 29 | private Func IsIntGreaterThanInt; 30 | private Func IsIntLessThanInt; 31 | private Func RandomIntLessThan; 32 | private List OneThreeThreeFour; 33 | private List OneThreeTwoFour; 34 | private List ThreeTwoOne; 35 | private List TwoThree; 36 | private List FourTwoThreeOne; 37 | private List OneTwoThreeFour; 38 | 39 | [SetUp] 40 | public void SetUp() 41 | { 42 | random = new MonotonicRandom(); 43 | defaultArr = new List { 1, 2, 2, 3 }; 44 | arr = defaultArr.ToList(); 45 | arr2 = new int[arr.Count].ToList(); 46 | arr3 = new int[arr.Count].ToList(); 47 | arrLong = new int[arr.Count * 2].ToList(); 48 | AreIntsEqual = (a, b) => a == b; 49 | IsIntEven = i => i % 2 == 0; 50 | IsIntEqualTo2 = i => i == 2; 51 | IsIntLessThanOrEqualTo2 = i => i <= 2; 52 | IsIntGreaterThan0 = i => i > 0; 53 | IsIntGreaterThan10 = i => i > 10; 54 | DoubleInt = i => i * 2; 55 | MultiplyInts = (a, b) => a * b; 56 | IsIntGreaterThanInt = (a, b) => a > b; 57 | IsIntLessThanInt = (a, b) => a < b; 58 | RandomIntLessThan = random.Next; 59 | OneThreeThreeFour = new List { 1, 3, 3, 4 }; 60 | OneThreeTwoFour = new List { 1, 3, 2, 4 }; 61 | ThreeTwoOne = new List { 3, 2, 1 }; 62 | TwoThree = new List { 2, 3 }; 63 | FourTwoThreeOne = new List { 4, 2, 3, 1 }; 64 | OneTwoThreeFour = new List { 1, 2, 3, 4 }; 65 | } 66 | 67 | [Test] 68 | public void GetAdvanced() 69 | { 70 | Assert.That(arr.Begin().GetAdvanced(1).GetCurrent(), Is.EqualTo(2)); 71 | } 72 | 73 | [Test] 74 | public void Distance() 75 | { 76 | Assert.That(arr.Begin().Distance(arr.End()), Is.EqualTo(4)); 77 | } 78 | 79 | [Test] 80 | public void AllOf() 81 | { 82 | Assert.That(arr.Begin().AllOf(arr.End(), IsIntEven), Is.False); 83 | Assert.That(arr.Begin().AllOf(arr.End(), IsIntGreaterThan0), Is.True); 84 | } 85 | 86 | [Test] 87 | public void AnyOf() 88 | { 89 | Assert.That(arr.Begin().AnyOf(arr.End(), IsIntGreaterThan10), Is.False); 90 | Assert.That(arr.Begin().AnyOf(arr.End(), IsIntEqualTo2), Is.True); 91 | } 92 | 93 | [Test] 94 | public void NoneOf() 95 | { 96 | Assert.That(arr.Begin().NoneOf(arr.End(), IsIntEqualTo2), Is.False); 97 | Assert.That(arr.Begin().NoneOf(arr.End(), IsIntGreaterThan10), Is.True); 98 | } 99 | 100 | [Test] 101 | public void ForEach() 102 | { 103 | int index = 0; 104 | arr.Begin().ForEach( 105 | arr.End(), 106 | i => Assert.That(i, Is.EqualTo(arr[index++])) 107 | ); 108 | } 109 | 110 | [Test] 111 | public void Find() 112 | { 113 | Assert.That( 114 | arr.Begin().Find( 115 | arr.End(), 116 | 2, 117 | AreIntsEqual).Index, 118 | Is.EqualTo(1)); 119 | } 120 | 121 | [Test] 122 | public void FindIf() 123 | { 124 | Assert.That( 125 | arr.Begin().FindIf( 126 | arr.End(), 127 | IsIntEven).Index, 128 | Is.EqualTo(1)); 129 | } 130 | 131 | [Test] 132 | public void FindIfNot() 133 | { 134 | Assert.That( 135 | arr.Begin().FindIfNot( 136 | arr.End(), 137 | IsIntEven).Index, 138 | Is.EqualTo(0)); 139 | } 140 | 141 | [Test] 142 | public void FindEnd() 143 | { 144 | Assert.That( 145 | arr.Begin().FindEnd( 146 | arr.End(), 147 | arr.IteratorAt(1), 148 | arr.IteratorAt(2), 149 | AreIntsEqual 150 | ).Index, 151 | Is.EqualTo(2) 152 | ); 153 | } 154 | 155 | [Test] 156 | public void FindFirstOf() 157 | { 158 | Assert.That( 159 | arr.Begin().FindFirstOf( 160 | arr.End(), 161 | arr.IteratorAt(1), 162 | arr.IteratorAt(2), 163 | AreIntsEqual 164 | ).Index, 165 | Is.EqualTo(1) 166 | ); 167 | } 168 | 169 | [Test] 170 | public void AdjacentFind() 171 | { 172 | Assert.That( 173 | arr.Begin().AdjacentFind(arr.End(), AreIntsEqual).Index, 174 | Is.EqualTo(1)); 175 | } 176 | 177 | [Test] 178 | public void Count() 179 | { 180 | Assert.That( 181 | arr.Begin().Count(arr.End(), 2, AreIntsEqual), 182 | Is.EqualTo(2)); 183 | } 184 | 185 | [Test] 186 | public void CountIf() 187 | { 188 | Assert.That(arr.Begin().CountIf(arr.End(), IsIntEven), Is.EqualTo(2)); 189 | } 190 | 191 | [Test] 192 | public void Mismatch() 193 | { 194 | ListIterator mm1; 195 | ListIterator mm2; 196 | arr.Begin().Mismatch( 197 | arr.End(), 198 | new List { 1, 3, 3, 4 }.Begin(), 199 | AreIntsEqual, 200 | out mm1, 201 | out mm2 202 | ); 203 | Assert.That(mm1.GetCurrent(), Is.EqualTo(2)); 204 | Assert.That(mm2.GetCurrent(), Is.EqualTo(3)); 205 | } 206 | 207 | [Test] 208 | public void Equal() 209 | { 210 | Assert.That( 211 | arr.Begin().Equal( 212 | arr.End(), 213 | new List { 1, 3, 2, 3 }.Begin(), 214 | AreIntsEqual), 215 | Is.False); 216 | Assert.That( 217 | arr.Begin().Equal( 218 | arr.End(), 219 | new List { 1, 2, 2, 3 }.Begin(), 220 | AreIntsEqual), 221 | Is.True); 222 | } 223 | 224 | [Test] 225 | public void IsPermutation() 226 | { 227 | Assert.That( 228 | arr.Begin().IsPermutation( 229 | arr.End(), 230 | new List { 3, 3, 1, 2 }.Begin(), 231 | AreIntsEqual), 232 | Is.False); 233 | Assert.That( 234 | arr.Begin().IsPermutation( 235 | arr.End(), 236 | new List { 3, 2, 1, 2 }.Begin(), 237 | AreIntsEqual), 238 | Is.True); 239 | } 240 | 241 | [Test] 242 | public void Search() 243 | { 244 | var sub = new List { 2, 3 }; 245 | Assert.That( 246 | arr.Begin().Search( 247 | arr.End(), 248 | sub.Begin(), 249 | sub.End(), 250 | AreIntsEqual).Index, 251 | Is.EqualTo(2)); 252 | } 253 | 254 | [Test] 255 | public void SearchN() 256 | { 257 | Assert.That( 258 | arr.Begin().SearchN(arr.End(), 2, 2, AreIntsEqual).Index, 259 | Is.EqualTo(1)); 260 | } 261 | 262 | [Test] 263 | public void Copy() 264 | { 265 | Assert.That( 266 | arr.Begin().Copy(arr.IteratorAt(2), arr2.Begin()).Index, 267 | Is.EqualTo(2)); 268 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 0, 0 })); 269 | } 270 | 271 | [Test] 272 | public void CopyN() 273 | { 274 | Assert.That(arr.Begin().CopyN(3, arr2.Begin()).Index, Is.EqualTo(3)); 275 | Assert.That(arr2, Is.EqualTo(new [] { 1, 2, 2, 0 })); 276 | } 277 | 278 | [Test] 279 | public void CopyIf() 280 | { 281 | Assert.That( 282 | arr.Begin().CopyIf(arr.End(), arr2.Begin(), IsIntEven).Index, 283 | Is.EqualTo(2)); 284 | Assert.That(arr2, Is.EqualTo(new [] { 2, 2, 0, 0 })); 285 | } 286 | 287 | [Test] 288 | public void CopyBackward() 289 | { 290 | Assert.That( 291 | arr.IteratorAt(1).CopyBackward(arr.IteratorAt(3), arr2.End()).Index, 292 | Is.EqualTo(2)); 293 | Assert.That(arr2, Is.EqualTo(new [] { 0, 0, 2, 2 })); 294 | } 295 | 296 | [Test] 297 | public void SwapRanges() 298 | { 299 | Assert.That( 300 | arr.IteratorAt(1).SwapRanges( 301 | arr.IteratorAt(3), 302 | arr2.IteratorAt(1)).Index, 303 | Is.EqualTo(3)); 304 | Assert.That(arr, Is.EqualTo(new [] { 1, 0, 0, 3 })); 305 | Assert.That(arr2, Is.EqualTo(new [] { 0, 2, 2, 0 })); 306 | } 307 | 308 | [Test] 309 | public void Swap() 310 | { 311 | var itA = arr.IteratorAt(0); 312 | var itB = arr.IteratorAt(1); 313 | itA.Swap(itB); 314 | Assert.That(arr, Is.EqualTo(new [] { 2, 1, 2, 3 })); 315 | } 316 | 317 | [Test] 318 | public void TransformDouble() 319 | { 320 | Assert.That( 321 | arr.Begin().Transform(arr.End(), arr.Begin(), DoubleInt).Index, 322 | Is.EqualTo(4)); 323 | Assert.That(arr, Is.EqualTo(new [] { 2, 4, 4, 6 })); 324 | } 325 | 326 | [Test] 327 | public void TransformMultiply() 328 | { 329 | Assert.That( 330 | arr.Begin().Transform( 331 | arr.End(), 332 | arr.Begin(), 333 | arr.Begin(), 334 | MultiplyInts).Index, 335 | Is.EqualTo(4)); 336 | Assert.That(arr, Is.EqualTo(new [] { 1, 4, 4, 9 })); 337 | } 338 | 339 | [Test] 340 | public void ReplaceIf() 341 | { 342 | arr.Begin().ReplaceIf(arr.End(), IsIntEqualTo2, 20); 343 | Assert.That(arr, Is.EqualTo(new [] { 1, 20, 20, 3 })); 344 | } 345 | 346 | [Test] 347 | public void ReplaceCopyIf() 348 | { 349 | Assert.That( 350 | arr.Begin().ReplaceCopyIf( 351 | arr.End(), 352 | arr.Begin(), 353 | IsIntEven, 354 | 200).Index, 355 | Is.EqualTo(4)); 356 | Assert.That(arr, Is.EqualTo(new [] { 1, 200, 200, 3 })); 357 | } 358 | 359 | [Test] 360 | public void Unique() 361 | { 362 | Assert.That( 363 | arr.Begin().Unique(arr.End(), AreIntsEqual).Index, 364 | Is.EqualTo(3)); 365 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 3, 3 })); 366 | } 367 | 368 | [Test] 369 | public void UniqueCopy() 370 | { 371 | Assert.That( 372 | arr.Begin().UniqueCopy(arr.End(), arr2.Begin(), AreIntsEqual).Index, 373 | Is.EqualTo(3)); 374 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 375 | Assert.That(arr2, Is.EqualTo(new [] { 1, 2, 3, 0 })); 376 | } 377 | 378 | [Test] 379 | public void Reverse() 380 | { 381 | arr.Begin().Reverse(arr.End()); 382 | Assert.That(arr, Is.EqualTo(new [] { 3, 2, 2, 1 })); 383 | } 384 | 385 | [Test] 386 | public void ReverseCopy() 387 | { 388 | Assert.That( 389 | arr.Begin().ReverseCopy(arr.End(), arr2.Begin()).Index, 390 | Is.EqualTo(4)); 391 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 2, 3 })); 392 | Assert.That(arr2, Is.EqualTo(new [] { 3, 2, 2, 1 })); 393 | } 394 | 395 | [Test] 396 | public void Rotate() 397 | { 398 | arr.Begin().Rotate(arr.IteratorAt(2), arr.End()); 399 | Assert.That(arr, Is.EqualTo(new [] { 2, 3, 1, 2 })); 400 | } 401 | 402 | [Test] 403 | public void RotateCopy() 404 | { 405 | Assert.That( 406 | arr.Begin().RotateCopy( 407 | arr.IteratorAt(2), 408 | arr.End(), 409 | arr2.Begin()).Index, 410 | Is.EqualTo(4)); 411 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 2, 3 })); 412 | Assert.That(arr2, Is.EqualTo(new [] { 2, 3, 1, 2 })); 413 | } 414 | 415 | [Test] 416 | public void RandomShuffle() 417 | { 418 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan); 419 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 2, 1 })); 420 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan); 421 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 3, 1 })); 422 | } 423 | 424 | [Test] 425 | public void IsPartitioned() 426 | { 427 | Assert.That(arr.Begin().IsPartitioned(arr.End(), IsIntEven), Is.False); 428 | Assert.That( 429 | arr.Begin().IsPartitioned(arr.End(), IsIntLessThanOrEqualTo2), 430 | Is.True); 431 | } 432 | 433 | [Test] 434 | public void Partition() 435 | { 436 | Assert.That( 437 | arr.Begin().Partition(arr.End(), IsIntEven).Index, 438 | Is.EqualTo(2)); 439 | Assert.That(arr, Is.EqualTo(new [] { 2, 2, 1, 3})); 440 | } 441 | 442 | [Test] 443 | public void PartitionCopy() 444 | { 445 | ListIterator outResultTrue; 446 | ListIterator outResultFalse; 447 | arr.Begin().PartitionCopy( 448 | arr.End(), 449 | arr2.Begin(), 450 | arr3.Begin(), 451 | IsIntEven, 452 | out outResultTrue, 453 | out outResultFalse 454 | ); 455 | Assert.That(outResultTrue.Index, Is.EqualTo(2)); 456 | Assert.That(outResultFalse.Index, Is.EqualTo(2)); 457 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 2, 3 })); 458 | Assert.That(arr2, Is.EqualTo(new [] { 2, 2, 0, 0 })); 459 | Assert.That(arr3, Is.EqualTo(new [] { 1, 3, 0, 0 })); 460 | } 461 | 462 | [Test] 463 | public void PartitionPoint() 464 | { 465 | Assert.That( 466 | arr.Begin().PartitionPoint( 467 | arr.End(), 468 | IsIntLessThanOrEqualTo2).Index, 469 | Is.EqualTo(2)); 470 | } 471 | 472 | [Test] 473 | public void Sort() 474 | { 475 | arr.Begin().Sort(arr.End(), IsIntGreaterThanInt); 476 | Assert.That(arr, Is.EqualTo(new [] { 3, 2, 2, 1 })); 477 | } 478 | 479 | [Test] 480 | public void StableSort() 481 | { 482 | arr.Begin().StableSort(arr.End(), IsIntGreaterThanInt); 483 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 484 | } 485 | 486 | [Test] 487 | public void PartialSort() 488 | { 489 | arr.Begin().PartialSort( 490 | arr.IteratorAt(2), 491 | arr.End(), 492 | IsIntGreaterThanInt); 493 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 494 | } 495 | 496 | [Test] 497 | public void IsSorted() 498 | { 499 | Assert.That(arr.Begin().IsSorted(arr.End(), IsIntLessThanInt), Is.True); 500 | } 501 | 502 | [Test] 503 | public void IsSortedUtil() 504 | { 505 | Assert.That( 506 | OneThreeTwoFour.Begin().IsSortedUntil( 507 | OneThreeTwoFour.End(), 508 | IsIntLessThanInt).Index, 509 | Is.EqualTo(2)); 510 | } 511 | 512 | [Test] 513 | public void NthElement() 514 | { 515 | OneThreeTwoFour.Begin().Copy(OneThreeTwoFour.End(), arr.Begin()); 516 | arr.Begin().NthElement(arr.IteratorAt(2), arr.End(), IsIntLessThanInt); 517 | Assert.That(arr, Is.EqualTo(new [] { 1, 2, 3, 4 })); 518 | } 519 | 520 | [Test] 521 | public void LowerBound() 522 | { 523 | Assert.That( 524 | arr.Begin().LowerBound(arr.End(), 2, IsIntLessThanInt).Index, 525 | Is.EqualTo(1)); 526 | } 527 | 528 | [Test] 529 | public void UpperBound() 530 | { 531 | Assert.That( 532 | arr.Begin().UpperBound(arr.End(), 2, IsIntLessThanInt).Index, 533 | Is.EqualTo(3)); 534 | } 535 | 536 | [Test] 537 | public void EqualRange() 538 | { 539 | ListIterator equalRangeLower; 540 | ListIterator equalRangeUpper; 541 | arr.Begin().EqualRange( 542 | arr.End(), 543 | 2, 544 | IsIntLessThanInt, 545 | out equalRangeLower, 546 | out equalRangeUpper 547 | ); 548 | Assert.That(equalRangeLower.Index, Is.EqualTo(1)); 549 | Assert.That(equalRangeUpper.Index, Is.EqualTo(3)); 550 | } 551 | 552 | [Test] 553 | public void BinarySearch() 554 | { 555 | Assert.That( 556 | arr.Begin().BinarySearch(arr.End(), 2, IsIntLessThanInt), 557 | Is.True); 558 | Assert.That( 559 | arr.Begin().BinarySearch(arr.End(), 9, IsIntLessThanInt), 560 | Is.False); 561 | } 562 | 563 | [Test] 564 | public void Merge() 565 | { 566 | Assert.That( 567 | arr.Begin().Merge( 568 | arr.End(), 569 | OneThreeThreeFour.Begin(), 570 | OneThreeThreeFour.End(), 571 | arrLong.Begin(), 572 | IsIntLessThanInt 573 | ).Index, 574 | Is.EqualTo(8)); 575 | Assert.That(arrLong, Is.EqualTo(new [] { 1, 1, 2, 2, 3, 3, 3, 4 })); 576 | } 577 | 578 | [Test] 579 | public void InplaceMerge() 580 | { 581 | ListIterator copyResult = arr.Begin().Copy( 582 | arr.End(), 583 | arrLong.Begin()); 584 | OneThreeThreeFour.Begin().Copy(OneThreeThreeFour.End(), copyResult); 585 | arrLong.Begin().InplaceMerge( 586 | copyResult, 587 | arrLong.End(), 588 | IsIntLessThanInt); 589 | Assert.That(arrLong, Is.EqualTo(new [] { 1, 1, 2, 2, 3, 3, 3, 4 })); 590 | } 591 | 592 | [Test] 593 | public void Includes() 594 | { 595 | Assert.That( 596 | arr.Begin().Includes( 597 | arr.End(), 598 | TwoThree.Begin(), 599 | TwoThree.End(), 600 | IsIntLessThanInt), 601 | Is.True); 602 | } 603 | 604 | [Test] 605 | public void SetUnion() 606 | { 607 | Assert.That( 608 | arr.Begin().SetUnion( 609 | arr.End(), 610 | OneThreeThreeFour.Begin(), 611 | OneThreeThreeFour.End(), 612 | arrLong.Begin(), 613 | IsIntLessThanInt 614 | ).Index, 615 | Is.EqualTo(6)); 616 | Assert.That(arrLong, Is.EqualTo(new[] { 1, 2, 2, 3, 3, 4, 0, 0 })); 617 | } 618 | 619 | [Test] 620 | public void SetIntersection() 621 | { 622 | Assert.That( 623 | arr.Begin().SetIntersection( 624 | arr.End(), 625 | OneThreeThreeFour.Begin(), 626 | OneThreeThreeFour.End(), 627 | arrLong.Begin(), 628 | IsIntLessThanInt 629 | ).Index, 630 | Is.EqualTo(2)); 631 | Assert.That(arrLong, Is.EqualTo(new [] { 1, 3, 0, 0, 0, 0, 0, 0 })); 632 | } 633 | 634 | [Test] 635 | public void SetDifference() 636 | { 637 | Assert.That( 638 | arr.Begin().SetDifference( 639 | arr.End(), 640 | OneThreeThreeFour.Begin(), 641 | OneThreeThreeFour.End(), 642 | arrLong.Begin(), 643 | IsIntLessThanInt 644 | ).Index, 645 | Is.EqualTo(2)); 646 | Assert.That(arrLong, Is.EqualTo(new [] { 2, 2, 0, 0, 0, 0, 0, 0 })); 647 | } 648 | 649 | [Test] 650 | public void SetSymmetricDifference() 651 | { 652 | Assert.That( 653 | arr.Begin().SetSymmetricDifference( 654 | arr.End(), 655 | OneThreeThreeFour.Begin(), 656 | OneThreeThreeFour.End(), 657 | arrLong.Begin(), 658 | IsIntLessThanInt 659 | ).Index, 660 | Is.EqualTo(4)); 661 | Assert.That(arrLong, Is.EqualTo(new [] { 2, 2, 3, 4, 0, 0, 0, 0 })); 662 | } 663 | 664 | [Test] 665 | public void PushHeap() 666 | { 667 | ListIterator pushHeapIt = FourTwoThreeOne.Begin().Copy( 668 | FourTwoThreeOne.End(), 669 | arrLong.Begin()); 670 | pushHeapIt.SetCurrent(5); 671 | pushHeapIt = pushHeapIt.GetNext(); 672 | arrLong.Begin().PushHeap(pushHeapIt, IsIntLessThanInt); 673 | Assert.That(arrLong, Is.EqualTo(new [] { 5, 4, 3, 1, 2, 0, 0, 0 })); 674 | } 675 | 676 | [Test] 677 | public void PopHeap() 678 | { 679 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin()); 680 | arr2.Begin().PopHeap(arr2.End(), IsIntLessThanInt); 681 | Assert.That(arr2, Is.EqualTo(new [] { 3, 2, 1, 4 })); 682 | } 683 | 684 | [Test] 685 | public void MakeHeap() 686 | { 687 | OneTwoThreeFour.Begin().Copy(OneTwoThreeFour.End(), arr2.Begin()); 688 | arr2.Begin().MakeHeap(arr2.End(), IsIntLessThanInt); 689 | Assert.That(arr2, Is.EqualTo(new[] { 4, 2, 3, 1 })); 690 | } 691 | 692 | [Test] 693 | public void SortHeap() 694 | { 695 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin()); 696 | arr2.Begin().SortHeap(arr2.End(), IsIntLessThanInt); 697 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 3, 4 })); 698 | } 699 | 700 | [Test] 701 | public void IsHeap() 702 | { 703 | Assert.That( 704 | FourTwoThreeOne.Begin().IsHeap( 705 | FourTwoThreeOne.End(), 706 | IsIntLessThanInt), Is.True); 707 | } 708 | 709 | [Test] 710 | public void IsHeapUntil() 711 | { 712 | Assert.That( 713 | FourTwoThreeOne.Begin().IsHeapUntil( 714 | FourTwoThreeOne.End(), 715 | IsIntLessThanInt).Index, 716 | Is.EqualTo(4)); 717 | } 718 | 719 | [Test] 720 | public void MinElement() 721 | { 722 | Assert.That( 723 | arr.Begin().MinElement(arr.End(), IsIntLessThanInt).Index, 724 | Is.EqualTo(0)); 725 | } 726 | 727 | [Test] 728 | public void MaxElement() 729 | { 730 | Assert.That( 731 | arr.Begin().MaxElement(arr.End(), IsIntLessThanInt).Index, 732 | Is.EqualTo(3)); 733 | } 734 | 735 | [Test] 736 | public void MinMaxElement() 737 | { 738 | ListIterator minIt; 739 | ListIterator maxIt; 740 | arr.Begin().MinMaxElement( 741 | arr.End(), 742 | IsIntLessThanInt, 743 | out minIt, 744 | out maxIt); 745 | Assert.That(minIt.Index, Is.EqualTo(0)); 746 | Assert.That(maxIt.Index, Is.EqualTo(3)); 747 | } 748 | 749 | [Test] 750 | public void LexicographicCompare() 751 | { 752 | Assert.That( 753 | arr.Begin().LexicographicalCompare( 754 | arr.End(), 755 | arr2.Begin(), 756 | arr2.End(), 757 | IsIntLessThanInt), 758 | Is.False); 759 | Assert.That( 760 | arr2.Begin().LexicographicalCompare( 761 | arr2.End(), 762 | arr.Begin(), 763 | arr.End(), 764 | IsIntLessThanInt), 765 | Is.True); 766 | } 767 | 768 | [Test] 769 | public void NextPermutation() 770 | { 771 | Assert.That( 772 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 773 | Is.True); 774 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 3, 2 })); 775 | 776 | Assert.That( 777 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 778 | Is.True); 779 | Assert.That(arr, Is.EqualTo(new[] { 1, 3, 2, 2 })); 780 | 781 | Assert.That( 782 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 783 | Is.True); 784 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 2, 3 })); 785 | 786 | Assert.That( 787 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 788 | Is.True); 789 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 3, 2 })); 790 | 791 | Assert.That( 792 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 793 | Is.True); 794 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 1, 3 })); 795 | 796 | Assert.That( 797 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 798 | Is.True); 799 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 3, 1 })); 800 | 801 | Assert.That( 802 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 803 | Is.True); 804 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 1, 2 })); 805 | 806 | Assert.That( 807 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 808 | Is.True); 809 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 2, 1 })); 810 | 811 | Assert.That( 812 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 813 | Is.True); 814 | Assert.That(arr, Is.EqualTo(new[] { 3, 1, 2, 2 })); 815 | 816 | Assert.That( 817 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 818 | Is.True); 819 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 1, 2 })); 820 | 821 | Assert.That( 822 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 823 | Is.True); 824 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 825 | 826 | Assert.That( 827 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 828 | Is.False); 829 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 830 | } 831 | 832 | [Test] 833 | public void PrevPermutation() 834 | { 835 | Assert.That( 836 | ThreeTwoOne.Begin().PrevPermutation( 837 | ThreeTwoOne.End(), 838 | IsIntLessThanInt), 839 | Is.True); 840 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 3, 1, 2 })); 841 | 842 | 843 | Assert.That( 844 | ThreeTwoOne.Begin().PrevPermutation( 845 | ThreeTwoOne.End(), 846 | IsIntLessThanInt), 847 | Is.True); 848 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 2, 3, 1 })); 849 | 850 | Assert.That( 851 | ThreeTwoOne.Begin().PrevPermutation( 852 | ThreeTwoOne.End(), 853 | IsIntLessThanInt), 854 | Is.True); 855 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 2, 1, 3 })); 856 | 857 | 858 | Assert.That( 859 | ThreeTwoOne.Begin().PrevPermutation( 860 | ThreeTwoOne.End(), 861 | IsIntLessThanInt), 862 | Is.True); 863 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 1, 3, 2 })); 864 | 865 | 866 | Assert.That( 867 | ThreeTwoOne.Begin().PrevPermutation( 868 | ThreeTwoOne.End(), 869 | IsIntLessThanInt), 870 | Is.True); 871 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 1, 2, 3 })); 872 | 873 | Assert.That( 874 | ThreeTwoOne.Begin().PrevPermutation( 875 | ThreeTwoOne.End(), 876 | IsIntLessThanInt), 877 | Is.False); 878 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 3, 2, 1 })); 879 | } 880 | } -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/TestListIterator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b44e2e107a0540f286113b1c02df8ce 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/TestNativeArrayIterator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Jackson Dunstan. See LICENSE.txt. 4 | // 5 | //----------------------------------------------------------------------- 6 | 7 | // NativeArray was introduced in Unity 2018.1 8 | #if UNITY_2018_1_OR_NEWER 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using Unity.Collections; 14 | using JacksonDunstanIterator; 15 | using NUnit.Framework; 16 | 17 | public class TestNativeArrayIterator 18 | { 19 | private List> nativeArrays; 20 | private MonotonicRandom random; 21 | private NativeArray defaultArr; 22 | private NativeArray arr; 23 | private NativeArray arr2; 24 | private NativeArray arr3; 25 | private NativeArray arrLong; 26 | private Func AreIntsEqual; 27 | private Func IsIntEven; 28 | private Func IsIntEqualTo2; 29 | private Func IsIntLessThanOrEqualTo2; 30 | private Func IsIntGreaterThan0; 31 | private Func IsIntGreaterThan10; 32 | private Func DoubleInt; 33 | private Func MultiplyInts; 34 | private Func IsIntGreaterThanInt; 35 | private Func IsIntLessThanInt; 36 | private Func RandomIntLessThan; 37 | private NativeArray OneThreeThreeFour; 38 | private NativeArray OneThreeTwoFour; 39 | private NativeArray ThreeTwoOne; 40 | private NativeArray TwoThree; 41 | private NativeArray FourTwoThreeOne; 42 | private NativeArray OneTwoThreeFour; 43 | 44 | private NativeArray CreateNativeArray(params int[] values) 45 | { 46 | NativeArray array = new NativeArray( 47 | values.Length, 48 | Allocator.Temp); 49 | for (int i = 0; i < values.Length; ++i) 50 | { 51 | array[i] = values[i]; 52 | } 53 | nativeArrays.Add(array); 54 | return array; 55 | } 56 | 57 | private NativeArray CreateEmptyNativeArray(int length) 58 | { 59 | NativeArray array = new NativeArray( 60 | length, 61 | Allocator.Temp); 62 | nativeArrays.Add(array); 63 | return array; 64 | } 65 | 66 | private NativeArray CopyNativeArray(NativeArray values) 67 | { 68 | NativeArray array = new NativeArray( 69 | values.Length, 70 | Allocator.Temp); 71 | for (int i = 0; i < values.Length; ++i) 72 | { 73 | array[i] = values[i]; 74 | } 75 | nativeArrays.Add(array); 76 | return array; 77 | } 78 | 79 | [SetUp] 80 | public void SetUp() 81 | { 82 | nativeArrays = new List>(); 83 | random = new MonotonicRandom(); 84 | defaultArr = CreateNativeArray(1, 2, 2, 3); 85 | arr = CopyNativeArray(defaultArr); 86 | arr2 = CreateEmptyNativeArray(arr.Length); 87 | arr3 = CreateEmptyNativeArray(arr.Length); 88 | arrLong = CreateEmptyNativeArray(arr.Length * 2); 89 | AreIntsEqual = (a, b) => a == b; 90 | IsIntEven = i => i % 2 == 0; 91 | IsIntEqualTo2 = i => i == 2; 92 | IsIntLessThanOrEqualTo2 = i => i <= 2; 93 | IsIntGreaterThan0 = i => i > 0; 94 | IsIntGreaterThan10 = i => i > 10; 95 | DoubleInt = i => i * 2; 96 | MultiplyInts = (a, b) => a * b; 97 | IsIntGreaterThanInt = (a, b) => a > b; 98 | IsIntLessThanInt = (a, b) => a < b; 99 | RandomIntLessThan = random.Next; 100 | OneThreeThreeFour = CreateNativeArray(1, 3, 3, 4); 101 | OneThreeTwoFour = CreateNativeArray(1, 3, 2, 4); 102 | ThreeTwoOne = CreateNativeArray(3, 2, 1); 103 | TwoThree = CreateNativeArray(2, 3); 104 | FourTwoThreeOne = CreateNativeArray(4, 2, 3, 1); 105 | OneTwoThreeFour = CreateNativeArray(1, 2, 3, 4); 106 | } 107 | 108 | [TearDown] 109 | public void TearDown() 110 | { 111 | foreach (NativeArray nativeArray in nativeArrays) 112 | { 113 | nativeArray.Dispose(); 114 | } 115 | } 116 | 117 | [Test] 118 | public void GetAdvanced() 119 | { 120 | Assert.That(arr.Begin().GetAdvanced(1).GetCurrent(), Is.EqualTo(2)); 121 | } 122 | 123 | [Test] 124 | public void Distance() 125 | { 126 | Assert.That(arr.Begin().Distance(arr.End()), Is.EqualTo(4)); 127 | } 128 | 129 | [Test] 130 | public void AllOf() 131 | { 132 | Assert.That(arr.Begin().AllOf(arr.End(), IsIntEven), Is.False); 133 | Assert.That(arr.Begin().AllOf(arr.End(), IsIntGreaterThan0), Is.True); 134 | } 135 | 136 | [Test] 137 | public void AnyOf() 138 | { 139 | Assert.That(arr.Begin().AnyOf(arr.End(), IsIntGreaterThan10), Is.False); 140 | Assert.That(arr.Begin().AnyOf(arr.End(), IsIntEqualTo2), Is.True); 141 | } 142 | 143 | [Test] 144 | public void NoneOf() 145 | { 146 | Assert.That(arr.Begin().NoneOf(arr.End(), IsIntEqualTo2), Is.False); 147 | Assert.That(arr.Begin().NoneOf(arr.End(), IsIntGreaterThan10), Is.True); 148 | } 149 | 150 | [Test] 151 | public void ForEach() 152 | { 153 | int index = 0; 154 | arr.Begin().ForEach( 155 | arr.End(), 156 | i => Assert.That(i, Is.EqualTo(arr[index++])) 157 | ); 158 | } 159 | 160 | [Test] 161 | public void Find() 162 | { 163 | Assert.That( 164 | arr.Begin().Find( 165 | arr.End(), 166 | 2, 167 | AreIntsEqual).Index, 168 | Is.EqualTo(1)); 169 | } 170 | 171 | [Test] 172 | public void FindIf() 173 | { 174 | Assert.That( 175 | arr.Begin().FindIf( 176 | arr.End(), 177 | IsIntEven).Index, 178 | Is.EqualTo(1)); 179 | } 180 | 181 | [Test] 182 | public void FindIfNot() 183 | { 184 | Assert.That( 185 | arr.Begin().FindIfNot( 186 | arr.End(), 187 | IsIntEven).Index, 188 | Is.EqualTo(0)); 189 | } 190 | 191 | [Test] 192 | public void FindEnd() 193 | { 194 | Assert.That( 195 | arr.Begin().FindEnd( 196 | arr.End(), 197 | arr.IteratorAt(1), 198 | arr.IteratorAt(2), 199 | AreIntsEqual 200 | ).Index, 201 | Is.EqualTo(2) 202 | ); 203 | } 204 | 205 | [Test] 206 | public void FindFirstOf() 207 | { 208 | Assert.That( 209 | arr.Begin().FindFirstOf( 210 | arr.End(), 211 | arr.IteratorAt(1), 212 | arr.IteratorAt(2), 213 | AreIntsEqual 214 | ).Index, 215 | Is.EqualTo(1) 216 | ); 217 | } 218 | 219 | [Test] 220 | public void AdjacentFind() 221 | { 222 | Assert.That( 223 | arr.Begin().AdjacentFind(arr.End(), AreIntsEqual).Index, 224 | Is.EqualTo(1)); 225 | } 226 | 227 | [Test] 228 | public void Count() 229 | { 230 | Assert.That( 231 | arr.Begin().Count(arr.End(), 2, AreIntsEqual), 232 | Is.EqualTo(2)); 233 | } 234 | 235 | [Test] 236 | public void CountIf() 237 | { 238 | Assert.That(arr.Begin().CountIf(arr.End(), IsIntEven), Is.EqualTo(2)); 239 | } 240 | 241 | [Test] 242 | public void Mismatch() 243 | { 244 | NativeArrayIterator mm1; 245 | NativeArrayIterator mm2; 246 | arr.Begin().Mismatch( 247 | arr.End(), 248 | CreateNativeArray(1, 3, 3, 4).Begin(), 249 | AreIntsEqual, 250 | out mm1, 251 | out mm2 252 | ); 253 | Assert.That(mm1.GetCurrent(), Is.EqualTo(2)); 254 | Assert.That(mm2.GetCurrent(), Is.EqualTo(3)); 255 | } 256 | 257 | [Test] 258 | public void Equal() 259 | { 260 | Assert.That( 261 | arr.Begin().Equal( 262 | arr.End(), 263 | CreateNativeArray(1, 3, 2, 3).Begin(), 264 | AreIntsEqual), 265 | Is.False); 266 | Assert.That( 267 | arr.Begin().Equal( 268 | arr.End(), 269 | CreateNativeArray(1, 2, 2, 3).Begin(), 270 | AreIntsEqual), 271 | Is.True); 272 | } 273 | 274 | [Test] 275 | public void IsPermutation() 276 | { 277 | Assert.That( 278 | arr.Begin().IsPermutation( 279 | arr.End(), 280 | CreateNativeArray(3, 3, 1, 2).Begin(), 281 | AreIntsEqual), 282 | Is.False); 283 | Assert.That( 284 | arr.Begin().IsPermutation( 285 | arr.End(), 286 | CreateNativeArray(3, 2, 1, 2).Begin(), 287 | AreIntsEqual), 288 | Is.True); 289 | } 290 | 291 | [Test] 292 | public void Search() 293 | { 294 | var sub = CreateNativeArray(2, 3); 295 | Assert.That( 296 | arr.Begin().Search( 297 | arr.End(), 298 | sub.Begin(), 299 | sub.End(), 300 | AreIntsEqual).Index, 301 | Is.EqualTo(2)); 302 | } 303 | 304 | [Test] 305 | public void SearchN() 306 | { 307 | Assert.That( 308 | arr.Begin().SearchN(arr.End(), 2, 2, AreIntsEqual).Index, 309 | Is.EqualTo(1)); 310 | } 311 | 312 | [Test] 313 | public void Copy() 314 | { 315 | Assert.That( 316 | arr.Begin().Copy(arr.IteratorAt(2), arr2.Begin()).Index, 317 | Is.EqualTo(2)); 318 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 0, 0 })); 319 | } 320 | 321 | [Test] 322 | public void CopyN() 323 | { 324 | Assert.That(arr.Begin().CopyN(3, arr2.Begin()).Index, Is.EqualTo(3)); 325 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 2, 0 })); 326 | } 327 | 328 | [Test] 329 | public void CopyIf() 330 | { 331 | Assert.That( 332 | arr.Begin().CopyIf(arr.End(), arr2.Begin(), IsIntEven).Index, 333 | Is.EqualTo(2)); 334 | Assert.That(arr2, Is.EqualTo(new[] { 2, 2, 0, 0 })); 335 | } 336 | 337 | [Test] 338 | public void CopyBackward() 339 | { 340 | Assert.That( 341 | arr.IteratorAt(1).CopyBackward(arr.IteratorAt(3), arr2.End()).Index, 342 | Is.EqualTo(2)); 343 | Assert.That(arr2, Is.EqualTo(new[] { 0, 0, 2, 2 })); 344 | } 345 | 346 | [Test] 347 | public void SwapRanges() 348 | { 349 | Assert.That( 350 | arr.IteratorAt(1).SwapRanges( 351 | arr.IteratorAt(3), 352 | arr2.IteratorAt(1)).Index, 353 | Is.EqualTo(3)); 354 | Assert.That(arr, Is.EqualTo(new[] { 1, 0, 0, 3 })); 355 | Assert.That(arr2, Is.EqualTo(new[] { 0, 2, 2, 0 })); 356 | } 357 | 358 | [Test] 359 | public void Swap() 360 | { 361 | var itA = arr.IteratorAt(0); 362 | var itB = arr.IteratorAt(1); 363 | itA.Swap(itB); 364 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 2, 3 })); 365 | } 366 | 367 | [Test] 368 | public void TransformDouble() 369 | { 370 | Assert.That( 371 | arr.Begin().Transform(arr.End(), arr.Begin(), DoubleInt).Index, 372 | Is.EqualTo(4)); 373 | Assert.That(arr, Is.EqualTo(new[] { 2, 4, 4, 6 })); 374 | } 375 | 376 | [Test] 377 | public void TransformMultiply() 378 | { 379 | Assert.That( 380 | arr.Begin().Transform( 381 | arr.End(), 382 | arr.Begin(), 383 | arr.Begin(), 384 | MultiplyInts).Index, 385 | Is.EqualTo(4)); 386 | Assert.That(arr, Is.EqualTo(new[] { 1, 4, 4, 9 })); 387 | } 388 | 389 | [Test] 390 | public void ReplaceIf() 391 | { 392 | arr.Begin().ReplaceIf(arr.End(), IsIntEqualTo2, 20); 393 | Assert.That(arr, Is.EqualTo(new[] { 1, 20, 20, 3 })); 394 | } 395 | 396 | [Test] 397 | public void ReplaceCopyIf() 398 | { 399 | Assert.That( 400 | arr.Begin().ReplaceCopyIf( 401 | arr.End(), 402 | arr.Begin(), 403 | IsIntEven, 404 | 200).Index, 405 | Is.EqualTo(4)); 406 | Assert.That(arr, Is.EqualTo(new[] { 1, 200, 200, 3 })); 407 | } 408 | 409 | [Test] 410 | public void Unique() 411 | { 412 | Assert.That( 413 | arr.Begin().Unique(arr.End(), AreIntsEqual).Index, 414 | Is.EqualTo(3)); 415 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 3, 3 })); 416 | } 417 | 418 | [Test] 419 | public void UniqueCopy() 420 | { 421 | Assert.That( 422 | arr.Begin().UniqueCopy(arr.End(), arr2.Begin(), AreIntsEqual).Index, 423 | Is.EqualTo(3)); 424 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 425 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 3, 0 })); 426 | } 427 | 428 | [Test] 429 | public void Reverse() 430 | { 431 | arr.Begin().Reverse(arr.End()); 432 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 433 | } 434 | 435 | [Test] 436 | public void ReverseCopy() 437 | { 438 | Assert.That( 439 | arr.Begin().ReverseCopy(arr.End(), arr2.Begin()).Index, 440 | Is.EqualTo(4)); 441 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 442 | Assert.That(arr2, Is.EqualTo(new[] { 3, 2, 2, 1 })); 443 | } 444 | 445 | [Test] 446 | public void Rotate() 447 | { 448 | arr.Begin().Rotate(arr.IteratorAt(2), arr.End()); 449 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 1, 2 })); 450 | } 451 | 452 | [Test] 453 | public void RotateCopy() 454 | { 455 | Assert.That( 456 | arr.Begin().RotateCopy( 457 | arr.IteratorAt(2), 458 | arr.End(), 459 | arr2.Begin()).Index, 460 | Is.EqualTo(4)); 461 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 462 | Assert.That(arr2, Is.EqualTo(new[] { 2, 3, 1, 2 })); 463 | } 464 | 465 | [Test] 466 | public void RandomShuffle() 467 | { 468 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan); 469 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 2, 1 })); 470 | arr.Begin().RandomShuffle(arr.End(), RandomIntLessThan); 471 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 3, 1 })); 472 | } 473 | 474 | [Test] 475 | public void IsPartitioned() 476 | { 477 | Assert.That(arr.Begin().IsPartitioned(arr.End(), IsIntEven), Is.False); 478 | Assert.That( 479 | arr.Begin().IsPartitioned(arr.End(), IsIntLessThanOrEqualTo2), 480 | Is.True); 481 | } 482 | 483 | [Test] 484 | public void Partition() 485 | { 486 | Assert.That( 487 | arr.Begin().Partition(arr.End(), IsIntEven).Index, 488 | Is.EqualTo(2)); 489 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 1, 3 })); 490 | } 491 | 492 | [Test] 493 | public void PartitionCopy() 494 | { 495 | NativeArrayIterator outResultTrue; 496 | NativeArrayIterator outResultFalse; 497 | arr.Begin().PartitionCopy( 498 | arr.End(), 499 | arr2.Begin(), 500 | arr3.Begin(), 501 | IsIntEven, 502 | out outResultTrue, 503 | out outResultFalse 504 | ); 505 | Assert.That(outResultTrue.Index, Is.EqualTo(2)); 506 | Assert.That(outResultFalse.Index, Is.EqualTo(2)); 507 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 508 | Assert.That(arr2, Is.EqualTo(new[] { 2, 2, 0, 0 })); 509 | Assert.That(arr3, Is.EqualTo(new[] { 1, 3, 0, 0 })); 510 | } 511 | 512 | [Test] 513 | public void PartitionPoint() 514 | { 515 | Assert.That( 516 | arr.Begin().PartitionPoint( 517 | arr.End(), 518 | IsIntLessThanOrEqualTo2).Index, 519 | Is.EqualTo(2)); 520 | } 521 | 522 | [Test] 523 | public void Sort() 524 | { 525 | arr.Begin().Sort(arr.End(), IsIntGreaterThanInt); 526 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 527 | } 528 | 529 | [Test] 530 | public void StableSort() 531 | { 532 | arr.Begin().StableSort(arr.End(), IsIntGreaterThanInt); 533 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 534 | } 535 | 536 | [Test] 537 | public void PartialSort() 538 | { 539 | arr.Begin().PartialSort( 540 | arr.IteratorAt(2), 541 | arr.End(), 542 | IsIntGreaterThanInt); 543 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 544 | } 545 | 546 | [Test] 547 | public void IsSorted() 548 | { 549 | Assert.That(arr.Begin().IsSorted(arr.End(), IsIntLessThanInt), Is.True); 550 | } 551 | 552 | [Test] 553 | public void IsSortedUtil() 554 | { 555 | Assert.That( 556 | OneThreeTwoFour.Begin().IsSortedUntil( 557 | OneThreeTwoFour.End(), 558 | IsIntLessThanInt).Index, 559 | Is.EqualTo(2)); 560 | } 561 | 562 | [Test] 563 | public void NthElement() 564 | { 565 | OneThreeTwoFour.Begin().Copy(OneThreeTwoFour.End(), arr.Begin()); 566 | arr.Begin().NthElement(arr.IteratorAt(2), arr.End(), IsIntLessThanInt); 567 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 3, 4 })); 568 | } 569 | 570 | [Test] 571 | public void LowerBound() 572 | { 573 | Assert.That( 574 | arr.Begin().LowerBound(arr.End(), 2, IsIntLessThanInt).Index, 575 | Is.EqualTo(1)); 576 | } 577 | 578 | [Test] 579 | public void UpperBound() 580 | { 581 | Assert.That( 582 | arr.Begin().UpperBound(arr.End(), 2, IsIntLessThanInt).Index, 583 | Is.EqualTo(3)); 584 | } 585 | 586 | [Test] 587 | public void EqualRange() 588 | { 589 | NativeArrayIterator equalRangeLower; 590 | NativeArrayIterator equalRangeUpper; 591 | arr.Begin().EqualRange( 592 | arr.End(), 593 | 2, 594 | IsIntLessThanInt, 595 | out equalRangeLower, 596 | out equalRangeUpper 597 | ); 598 | Assert.That(equalRangeLower.Index, Is.EqualTo(1)); 599 | Assert.That(equalRangeUpper.Index, Is.EqualTo(3)); 600 | } 601 | 602 | [Test] 603 | public void BinarySearch() 604 | { 605 | Assert.That( 606 | arr.Begin().BinarySearch(arr.End(), 2, IsIntLessThanInt), 607 | Is.True); 608 | Assert.That( 609 | arr.Begin().BinarySearch(arr.End(), 9, IsIntLessThanInt), 610 | Is.False); 611 | } 612 | 613 | [Test] 614 | public void Merge() 615 | { 616 | Assert.That( 617 | arr.Begin().Merge( 618 | arr.End(), 619 | OneThreeThreeFour.Begin(), 620 | OneThreeThreeFour.End(), 621 | arrLong.Begin(), 622 | IsIntLessThanInt 623 | ).Index, 624 | Is.EqualTo(8)); 625 | Assert.That(arrLong, Is.EqualTo(new[] { 1, 1, 2, 2, 3, 3, 3, 4 })); 626 | } 627 | 628 | [Test] 629 | public void InplaceMerge() 630 | { 631 | NativeArrayIterator copyResult = arr.Begin().Copy( 632 | arr.End(), 633 | arrLong.Begin()); 634 | OneThreeThreeFour.Begin().Copy(OneThreeThreeFour.End(), copyResult); 635 | arrLong.Begin().InplaceMerge( 636 | copyResult, 637 | arrLong.End(), 638 | IsIntLessThanInt); 639 | Assert.That(arrLong, Is.EqualTo(new[] { 1, 1, 2, 2, 3, 3, 3, 4 })); 640 | } 641 | 642 | [Test] 643 | public void Includes() 644 | { 645 | Assert.That( 646 | arr.Begin().Includes( 647 | arr.End(), 648 | TwoThree.Begin(), 649 | TwoThree.End(), 650 | IsIntLessThanInt), 651 | Is.True); 652 | } 653 | 654 | [Test] 655 | public void SetUnion() 656 | { 657 | Assert.That( 658 | arr.Begin().SetUnion( 659 | arr.End(), 660 | OneThreeThreeFour.Begin(), 661 | OneThreeThreeFour.End(), 662 | arrLong.Begin(), 663 | IsIntLessThanInt 664 | ).Index, 665 | Is.EqualTo(6)); 666 | Assert.That(arrLong, Is.EqualTo(new[] { 1, 2, 2, 3, 3, 4, 0, 0 })); 667 | } 668 | 669 | [Test] 670 | public void SetIntersection() 671 | { 672 | Assert.That( 673 | arr.Begin().SetIntersection( 674 | arr.End(), 675 | OneThreeThreeFour.Begin(), 676 | OneThreeThreeFour.End(), 677 | arrLong.Begin(), 678 | IsIntLessThanInt 679 | ).Index, 680 | Is.EqualTo(2)); 681 | Assert.That(arrLong, Is.EqualTo(new[] { 1, 3, 0, 0, 0, 0, 0, 0 })); 682 | } 683 | 684 | [Test] 685 | public void SetDifference() 686 | { 687 | Assert.That( 688 | arr.Begin().SetDifference( 689 | arr.End(), 690 | OneThreeThreeFour.Begin(), 691 | OneThreeThreeFour.End(), 692 | arrLong.Begin(), 693 | IsIntLessThanInt 694 | ).Index, 695 | Is.EqualTo(2)); 696 | Assert.That(arrLong, Is.EqualTo(new[] { 2, 2, 0, 0, 0, 0, 0, 0 })); 697 | } 698 | 699 | [Test] 700 | public void SetSymmetricDifference() 701 | { 702 | Assert.That( 703 | arr.Begin().SetSymmetricDifference( 704 | arr.End(), 705 | OneThreeThreeFour.Begin(), 706 | OneThreeThreeFour.End(), 707 | arrLong.Begin(), 708 | IsIntLessThanInt 709 | ).Index, 710 | Is.EqualTo(4)); 711 | Assert.That(arrLong, Is.EqualTo(new[] { 2, 2, 3, 4, 0, 0, 0, 0 })); 712 | } 713 | 714 | [Test] 715 | public void PushHeap() 716 | { 717 | NativeArrayIterator pushHeapIt = FourTwoThreeOne.Begin().Copy( 718 | FourTwoThreeOne.End(), 719 | arrLong.Begin()); 720 | pushHeapIt.SetCurrent(5); 721 | pushHeapIt = pushHeapIt.GetNext(); 722 | arrLong.Begin().PushHeap(pushHeapIt, IsIntLessThanInt); 723 | Assert.That(arrLong, Is.EqualTo(new[] { 5, 4, 3, 1, 2, 0, 0, 0 })); 724 | } 725 | 726 | [Test] 727 | public void PopHeap() 728 | { 729 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin()); 730 | arr2.Begin().PopHeap(arr2.End(), IsIntLessThanInt); 731 | Assert.That(arr2, Is.EqualTo(new[] { 3, 2, 1, 4 })); 732 | } 733 | 734 | [Test] 735 | public void MakeHeap() 736 | { 737 | OneTwoThreeFour.Begin().Copy(OneTwoThreeFour.End(), arr2.Begin()); 738 | arr2.Begin().MakeHeap(arr2.End(), IsIntLessThanInt); 739 | Assert.That(arr2, Is.EqualTo(new[] { 4, 2, 3, 1 })); 740 | } 741 | 742 | [Test] 743 | public void SortHeap() 744 | { 745 | FourTwoThreeOne.Begin().Copy(FourTwoThreeOne.End(), arr2.Begin()); 746 | arr2.Begin().SortHeap(arr2.End(), IsIntLessThanInt); 747 | Assert.That(arr2, Is.EqualTo(new[] { 1, 2, 3, 4 })); 748 | } 749 | 750 | [Test] 751 | public void IsHeap() 752 | { 753 | Assert.That( 754 | FourTwoThreeOne.Begin().IsHeap( 755 | FourTwoThreeOne.End(), 756 | IsIntLessThanInt), Is.True); 757 | } 758 | 759 | [Test] 760 | public void IsHeapUntil() 761 | { 762 | Assert.That( 763 | FourTwoThreeOne.Begin().IsHeapUntil( 764 | FourTwoThreeOne.End(), 765 | IsIntLessThanInt).Index, 766 | Is.EqualTo(4)); 767 | } 768 | 769 | [Test] 770 | public void MinElement() 771 | { 772 | Assert.That( 773 | arr.Begin().MinElement(arr.End(), IsIntLessThanInt).Index, 774 | Is.EqualTo(0)); 775 | } 776 | 777 | [Test] 778 | public void MaxElement() 779 | { 780 | Assert.That( 781 | arr.Begin().MaxElement(arr.End(), IsIntLessThanInt).Index, 782 | Is.EqualTo(3)); 783 | } 784 | 785 | [Test] 786 | public void MinMaxElement() 787 | { 788 | NativeArrayIterator minIt; 789 | NativeArrayIterator maxIt; 790 | arr.Begin().MinMaxElement( 791 | arr.End(), 792 | IsIntLessThanInt, 793 | out minIt, 794 | out maxIt); 795 | Assert.That(minIt.Index, Is.EqualTo(0)); 796 | Assert.That(maxIt.Index, Is.EqualTo(3)); 797 | } 798 | 799 | [Test] 800 | public void LexicographicCompare() 801 | { 802 | Assert.That( 803 | arr.Begin().LexicographicalCompare( 804 | arr.End(), 805 | arr2.Begin(), 806 | arr2.End(), 807 | IsIntLessThanInt), 808 | Is.False); 809 | Assert.That( 810 | arr2.Begin().LexicographicalCompare( 811 | arr2.End(), 812 | arr.Begin(), 813 | arr.End(), 814 | IsIntLessThanInt), 815 | Is.True); 816 | } 817 | 818 | [Test] 819 | public void NextPermutation() 820 | { 821 | Assert.That( 822 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 823 | Is.True); 824 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 3, 2 })); 825 | 826 | Assert.That( 827 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 828 | Is.True); 829 | Assert.That(arr, Is.EqualTo(new[] { 1, 3, 2, 2 })); 830 | 831 | Assert.That( 832 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 833 | Is.True); 834 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 2, 3 })); 835 | 836 | Assert.That( 837 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 838 | Is.True); 839 | Assert.That(arr, Is.EqualTo(new[] { 2, 1, 3, 2 })); 840 | 841 | Assert.That( 842 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 843 | Is.True); 844 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 1, 3 })); 845 | 846 | Assert.That( 847 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 848 | Is.True); 849 | Assert.That(arr, Is.EqualTo(new[] { 2, 2, 3, 1 })); 850 | 851 | Assert.That( 852 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 853 | Is.True); 854 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 1, 2 })); 855 | 856 | Assert.That( 857 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 858 | Is.True); 859 | Assert.That(arr, Is.EqualTo(new[] { 2, 3, 2, 1 })); 860 | 861 | Assert.That( 862 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 863 | Is.True); 864 | Assert.That(arr, Is.EqualTo(new[] { 3, 1, 2, 2 })); 865 | 866 | Assert.That( 867 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 868 | Is.True); 869 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 1, 2 })); 870 | 871 | Assert.That( 872 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 873 | Is.True); 874 | Assert.That(arr, Is.EqualTo(new[] { 3, 2, 2, 1 })); 875 | 876 | Assert.That( 877 | arr.Begin().NextPermutation(arr.End(), IsIntLessThanInt), 878 | Is.False); 879 | Assert.That(arr, Is.EqualTo(new[] { 1, 2, 2, 3 })); 880 | } 881 | 882 | [Test] 883 | public void PrevPermutation() 884 | { 885 | Assert.That( 886 | ThreeTwoOne.Begin().PrevPermutation( 887 | ThreeTwoOne.End(), 888 | IsIntLessThanInt), 889 | Is.True); 890 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 3, 1, 2 })); 891 | 892 | 893 | Assert.That( 894 | ThreeTwoOne.Begin().PrevPermutation( 895 | ThreeTwoOne.End(), 896 | IsIntLessThanInt), 897 | Is.True); 898 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 2, 3, 1 })); 899 | 900 | Assert.That( 901 | ThreeTwoOne.Begin().PrevPermutation( 902 | ThreeTwoOne.End(), 903 | IsIntLessThanInt), 904 | Is.True); 905 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 2, 1, 3 })); 906 | 907 | 908 | Assert.That( 909 | ThreeTwoOne.Begin().PrevPermutation( 910 | ThreeTwoOne.End(), 911 | IsIntLessThanInt), 912 | Is.True); 913 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 1, 3, 2 })); 914 | 915 | 916 | Assert.That( 917 | ThreeTwoOne.Begin().PrevPermutation( 918 | ThreeTwoOne.End(), 919 | IsIntLessThanInt), 920 | Is.True); 921 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 1, 2, 3 })); 922 | 923 | Assert.That( 924 | ThreeTwoOne.Begin().PrevPermutation( 925 | ThreeTwoOne.End(), 926 | IsIntLessThanInt), 927 | Is.False); 928 | Assert.That(ThreeTwoOne, Is.EqualTo(new[] { 3, 2, 1 })); 929 | } 930 | } 931 | 932 | #endif -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/TestNativeArrayIterator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8781423279f81406aa4900b0293089fb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/Utils.cs: -------------------------------------------------------------------------------- 1 | class MonotonicRandom 2 | { 3 | private int NextVal; 4 | 5 | public int Next() 6 | { 7 | return NextVal++; 8 | } 9 | 10 | public int Next(int max) 11 | { 12 | return Next() % max; 13 | } 14 | } -------------------------------------------------------------------------------- /JacksonDunstanIterator/Tests/Utils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d7d7a530d7a47684a9be6b6bb6db668d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2018 Jackson Dunstan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5aa4cf43d3787456ab5ea13cba41eb76 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | * A no-GC version of C#'s `IEnumerator` and LINQ 4 | * Inspired by C++'s `` and `` headers 5 | * Useful for any C# project with additional support for Unity 6 | 7 | # Getting Started 8 | 9 | ## Unity Projects 10 | 11 | Clone or download this repository and copy the `JacksonDunstanIterator` directory somewhere inside your Unity project's `Assets` directory. 12 | 13 | ## Non-Unity Projects 14 | 15 | Clone or download this repository and add all the `.cs` files directly under the `JacksonDunstanIterator` directory to your C# project. 16 | 17 | # Usage 18 | 19 | There are three iterator types: 20 | 21 | * `ArrayIterator` for managed arrays (`T[]`) 22 | * `ListIterator` for `List` 23 | * `NativeArrayIterator` for `NativeArray` (automatically compiled out when Unity 2018.1+ isn't available) 24 | 25 | They all have the same API. Here's the basics of using `ArrayIterator`: 26 | 27 | ```csharp 28 | // Get an array 29 | int[] array = new [] { 30, 10, 20, 40 }; 30 | 31 | // Get an iterator to the beginning of the array 32 | ArrayIterator begin = array.Begin(); 33 | 34 | // Get the value of the iterator 35 | int val = begin.GetCurrent(); 36 | 37 | // Move to the next element 38 | ArrayIterator second = begin.GetNext(); 39 | 40 | // Get an iterator to one past the end of the array 41 | ArrayIterator end = array.End(); 42 | 43 | // Reverse [ 10, 20, 40] so the array is [ 30, 40, 20, 10 ] 44 | second.Reverse(end); 45 | 46 | // Search for an element satisfying a condition 47 | ArrayIterator it20 = begin.FindIf(end, e => e < 25); 48 | ``` 49 | 50 | There is much more functionality available. See [the source](JacksonDunstanIterator/ArrayIterator.cs) for more. 51 | 52 | To read about the making of this library, see the _Enumerables Without the Garbage_ series: 53 | 54 | * [Part 1](https://jacksondunstan.com/articles/3471) 55 | * [Part 2](https://jacksondunstan.com/articles/3482) 56 | * [Part 3](https://jacksondunstan.com/articles/3491) 57 | * [Part 4](https://jacksondunstan.com/articles/3508) 58 | * [Part 5](https://jacksondunstan.com/articles/3515) 59 | * [Part 6](https://jacksondunstan.com/articles/3524) 60 | * [Part 7](https://jacksondunstan.com/articles/3541) 61 | * [Part 8](https://jacksondunstan.com/articles/4905) 62 | 63 | # License 64 | 65 | [MIT](LICENSE.txt) -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3f96139b1d9e4abaaa00cb3be917713 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------