/* ZArrayAlgo.hpp Author: James Russell Created: 1/12/2012 Purpose: Generalized algorithm implementations for use with ZArray. License: This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See http://sam.zoy.org/wtfpl/COPYING for more details. */ #pragma once #ifndef _ZARRAYALGO_HPP #define _ZARRAYALGO_HPP #include #include namespace ZArrayAlgo { //Forward Declaration of FindFirst template size_t FindFirst(const ZArray& _array, const T& _value, size_t _start, size_t _end); //Forward Declaration of FindSub template size_t FindSub(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2); //Forward Declaration of Unique template size_t Unique(ZArray& _array, size_t _start, size_t _end); /* public ZArrayAlgo::Append Appends the specified range of one array to another. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to append to @param _other - the array to append to the end of _array @param _start - the starting index of _other @param _end - the ending index of _other (exclusive) @return (void) @assert - if _end < _start if _start or _end out of bounds */ template void Append(ZArray& _array, const ZArray& _other, size_t _start, size_t _end) { if (_start == _end) return; const size_t start = _other.BoundsCheck(_start, _other.Size()); const size_t end = _other.BoundsCheck(_end, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Append - Cannot append with end < start!"); #endif const size_t initialSize = _array.Size(); const size_t delta = end - start; _array.Resize(_array.Size() + delta); for (size_t i = 0; i < delta; i++) _array.Data()[initialSize + i] = _other.Data()[start + i]; } /* public ZArrayAlgo::Append Appends one array to another. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to append to @param _other - the array to append to the end of _array @return (void) */ template void Append(ZArray& _array, const ZArray& _other) { Append(_array, _other, 0, _other.Size()); } /* public ZArrayAlgo::Apply Maps the provided unary functor over the array between the given indices, mutating in place. @param F - unary functor [(T&) -> void] used to operate on array[i] @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to map the function over @param _functor - instance of the unary functor F @param _start - the index to start looking at @param _end - the end index (exclusive) @return (void) @assert - if _end < _start if _start or _end out of bounds */ template void Apply(ZArray& _array, F _functor, size_t _start, size_t _end) { if (_start == _end) return; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Map - Cannot map with end < start!"); #endif for (size_t i = start; i < end; i++) _functor(_array.Data()[i]); } /* public ZArrayAlgo::Apply Maps the provided unary functor over the array, mutating in place. @param F - unary functor [(T&) -> void] used to operate on array[i] @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to map the function over @param _functor - instance of the unary functor F @return (void) */ template void Apply(ZArray& _array, F _functor) { Apply(_array, _functor, 0, _array.Size()); } /* public ZArrayAlgo::Concatenate Concatenates sections of two arrays and returns a new array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the first array @param _s1 - the start index on the first array @param _e1 - the ending index on the first array (exclusive) @param _other - the array that will be @param _s2 - the start index on the second array @param _e2 - the end index on the second array (exclusive) @return (ZArray) @assert - if _s1 < _e1 or _s2 < _e2 if _s1, _e1, _s2, or _e2 out of bounds */ template ZArray Concatenate(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { if (_s1 == _e1) return _other; else if (_s2 == _e2) return _array; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _other.BoundsCheck(_s2, _other.Size()); const size_t e2 = _other.BoundsCheck(_e2, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::Merge - Cannot merge with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::Merge - Cannot merge with e2 < s2!"); #endif const size_t delta1 = e1 - s1; const size_t delta2 = e2 - s2; const size_t newSize = delta1 + delta2; if (newSize == 0) return ZArray(); ZArray ret(&_array.Data()[s1], delta1, newSize); ret.Resize(newSize); for (size_t i = 0; i < delta2; i++) ret.Data()[delta1 + i] = _other.Data()[s2 + i]; return ret; } /* public ZArrayAlgo::Concatenate Concatenates an array to another and returns a new array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the first array @param _other - the second array @return (ZArray) - the result of concatenation */ template ZArray Concatenate(const ZArray& _array, const ZArray& _other) { return Concatenate(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::Contains Determines if the array contains the given value between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to check for the value @param _value - the value to search for @param _start - the index to start searching at @param _end - the end index (exclusive) @return (bool) - true if found, false otherwise @assert - if _end < _start if _start or _end out of bounds */ template bool Contains(const ZArray& _array, const T& _value, size_t _start, size_t _end) { return FindFirst(_array, _value, _start, _end) != ZSTL::InvalidPos; } /* public ZArrayAlgo::Contains Determines if the array contains the given value. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to check for the value @param _value - the value to search for @return (bool) - true if found, false otherwise */ template bool Contains(const ZArray& _array, const T& _value) { return Contains(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::ContainsSub Determines if the array contains the given sub array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to check for the value @param _other - the sub array to search for @param _start - the starting index @param _end - the ending index (exclusive) @return (bool) - true if found, false otherwise @assert - if _end < _start if _start or _end out of bounds */ template bool ContainsSub(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { return FindSub(_array, _s1, _e1, _other, _s2, _e2) != ZSTL::InvalidPos; } /* public ZArrayAlgo::ContainsSub Determines if the array contains the given sub array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to check for the value @param _other - the sub array to search for @return (bool) - true if found, false otherwise */ template bool ContainsSub(const ZArray& _array, const ZArray& _other) { return ContainsSub(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::Copy Copies a number of given elements into the given range of the provided array, from the provided range in the other array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to copy data into @param _s1 - the starting index to copy to @param _e1 - the ending index to copy to (exclusive) @param _other - the array to copy data from @param _s2 - the starting index to copy from @param _e2 - the ending index to copy to (exclusive) @return (void) @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template void Copy(ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _other.BoundsCheck(_s2, _other.Size()); const size_t e2 = _other.BoundsCheck(_e2, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::Copy - Cannot copy with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::Copy - Cannot copy with e2 < s2!"); #endif size_t i, j; for (i = s1, j = s2; i < e1 && j < e2; i++, j++) _array.Data()[i] = _other.Data()[j]; } /* public ZArrayAlgo::Copy Copies the elements of one array into the other. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to copy data into @param _other - the array to copy data from @param _count - the number of elements to copy @return (void) @assert - if _count > array size or other size */ template void Copy(ZArray& _array, const ZArray& _other) { return Copy(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::Count Returns the number of occurrences of the given value in the given range of the provided array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to count in @param _value - the value to search for @param _start - the index to start at @param _end - the ending index (exclusive) @return (size_t) - the number of occurrences of _value at and after _index @assert - if _end < _start if _start or _end out of bounds */ template size_t Count(const ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Count - Cannot count with end < start!"); #endif size_t count = 0; for (size_t i = start; i < end; i++) { if (_array.Data()[i] == _value) count++; } return count; } /* public ZArrayAlgo::Count Returns the number of occurrences of the given value in the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to count in @param _value - the value to search for @return (size_t) - the number of occurrences of _value at and after _index */ template size_t Count(const ZArray& _array, const T& _value) { return Count(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::EndsWith Used to determine if the given region of the provided array ends with the contents of the given region of the other array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to check @param _s1 - the starting index to check against @param _e1 - the ending index to check against (exclusive) @param _other - the array to check from @param _s2 - the starting index to check from @param _e2 - the ending index to check to (exclusive) @return (bool) - true if the array ends with the provided values, false otherwise @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template bool EndsWith(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { return FindSub(_array, _s1, _e1, _other, _s2, _e2) == (_e1 - (_e2 - _s2)); } /* public ZArrayAlgo::EndsWith Used to determine if the provided array ends with the values contained in the other array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to check @param _other - the array to check from @return (bool) - true if the array ends with the provided values, false otherwise */ template bool EndsWith(const ZArray& _array, const ZArray& _other) { return EndsWith(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::Equal Determines if the arrays are equivalent in the given subsections, up to the length of the shortest subsection. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to compare @param _s1 - the starting index to compare @param _e1 - the ending index to compare (exclusive) @param _other - the array to compare against @param _s2 - the starting index to compare against @param _e2 - the ending index to compare against (exclusive) @return (bool) - true if ranges are equivalent, false otherwise @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template bool Equal(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return false; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _other.BoundsCheck(_s2, _other.Size()); const size_t e2 = _other.BoundsCheck(_e2, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::Equal - Cannot compare with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::Equal - Cannot compare with e2 < s2!"); #endif size_t i, j; for (i = s1, j = s2; i < e1 && j < e2; i++, j++) if (!(_array.Data()[i] == _other.Data()[j])) return false; return true; } /* public ZArrayAlgo::Equal Determines if the arrays are equal in both size and contents. @param _array - the array to check @param _other - the array to check against @return (bool) - true if equivalent, false otherwise */ template bool Equal(const ZArray& _array, const ZArray& _other) { return _array.Equals(_other); } /* public ZArrayAlgo::Fill Fills a section of the array full of a given value. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to fill full of values @param _value - the value to fill into the array @param _start - the starting index @param _end - the ending index (exclusive) @return (void) @assert - if _end < _start if _start or _end out of bounds */ template void Fill(ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Fill - Cannot fill with end < start!"); #endif for (size_t i = start; i < end; i++) _array.Data()[i] = _value; } /* public ZArrayAlgo::Fill Fills the array full of the given value. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to fill full of values @param _value - the value to fill into the array @return (void) */ template void Fill(ZArray& _array, const T& _value) { Fill(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::Find Finds the Nth occurrence of a value in the provided region of the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to search @param _value - the value to find @param _count - the number of occurrences which should be skipped (meaning an index to the (N+1)th occurrence is returned) @param _start - the starting index @param _end - the ending index (exclusive) @return (size_t) - index of the (N+1)th occurrence @assert - if _end < _start if _start or _end out of bounds */ template size_t Find(const ZArray& _array, const T& _value, size_t _count, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Find - Cannot find with end < start!"); #endif size_t j = _count; for (size_t i = start; i < end; i++) { if(_array.Data()[i] == _value) { if (j == 0) return i; j--; } } return ZSTL::InvalidPos; } /* public ZArrayAlgo::Find Finds the Nth occurrence of a value in the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to search @param _value - the value to find @param _count - the number of occurrences which should be skipped (meaning an index to the (N+1)th occurrence is returned) @return (size_t) - index of the (N+1)th occurrence */ template size_t Find(const ZArray&_array, const T& _value, size_t _count) { return Find(_array, _value, _count, 0, _array.Size()); } /* public ZArrayAlgo::FindAll Finds all the things in the array of the provided value and returns their indices. Note that this will return the indices in order of appearance in the searched array. @param _array - the list to search through @param _value - the value to search for @param _start - the starting index (inclusive) to search from @param _end - the ending index (exclusive) to search from @return (ZArray) - array of indices where values appeared (empty list of none found) @assert - if _end < _start if _start or _end out of bounds */ template ZArray FindAll(const ZArray& _array, const T& _value, size_t _start, size_t _end) { ZArray locations(_array.Size() + 1); if (_start == _end) return locations; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Fill - Cannot fill with end < start!"); #endif for (size_t i = start; i < end; i++) { if (_array.Data()[i] == _value) locations.PushBack(i); } return locations; } /* public ZArrayAlgo::FindAll Finds all the things in the array of the provided value and returns their indices. Note that this will return the indices in order of appearance in the searched array. @param _array - the list to search through @param _value - the value to search for @return (ZArray) - array of indices where values appeared (empty list of none found) */ template ZArray FindAll(const ZArray& _array, const T& _value) { return ZArrayAlgo::FindAll(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::FindAllOf Finds all the things in the given region of the array that are equal to one of the provided values and returns their indices. Note that this will return the indices in order of appearance in the searched array. @param _array - the list to search through @param _value - the values to search for @param _array - the array to compare @param _s1 - the starting index to search @param _e1 - the ending index to search (exclusive) @param _other - the array to compare against @param _s2 - the starting index to find @param _e2 - the ending index to find (exclusive) @return (ZArray) - array of indices where values appeared (empty of none found) @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template ZArray FindAllOf(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _values, size_t _s2, size_t _e2) { ZArray locations(_array.Size() + 1); if (_s1 == _e1 || _s2 == _e2) return locations; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _values.BoundsCheck(_s2, _values.Size()); const size_t e2 = _values.BoundsCheck(_e2, _values.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::FindAllOf - Cannot find with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::FindAllOf - Cannot find with e2 < s2!"); #endif for (size_t i = s1; i < e1; i++) { for (size_t j = s2; j < e2; j++) { if ( _array.Data()[i] == _values.Data()[j] ) { locations.PushBack(i); break; } } } return locations; } /* public ZArrayAlgo::FindAllOf Finds all the things in the array that are equal to one of the provided values and returns their indices. Note that this will return the indices in order of appearance in the searched array. @param _array - the list to search through @param _value - the values to search for @return (ZArray) - array of indices where values appeared (empty of none found) */ template ZArray FindAllOf(const ZArray& _array, const ZArray& _values) { return FindAllOf(_array, 0, _array.Size(), _values, 0, _values.Size()); } /* public ZArrayAlgo::FindIf Finds a value in the provided range of the array that evaluates a unary functor to true. @param F - unary functor [(const T&) -> bool] used to test array[i] @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _functor - instance of the unary functor F to test with @param _end - the end index (exclusive) @return (size_t) - the first instance that evaluates to true from _functor (ZSTL::InvalidPos if not found) @assert - if _end < _start if _start or _end out of bounds */ template size_t FindIf(const ZArray& _array, F _functor, size_t _start, size_t _end) { if (_start == _end) return 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Find - Cannot find with end < start!"); #endif for (size_t i = start; i < end; i++) { if (_functor(_array.Data()[i])) return i; } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindIf Finds a value in the array that evaluates a unary functor to true. @param F - unary functor [(const T&) -> bool] used to test array[i] @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _functor - instance of the unary functor F to test with @return (size_t) - the first instance that evaluates to true from _functor (ZSTL::InvalidPos if not found) */ template size_t FindIf(const ZArray& _array, F _functor) { return FindIf(_array, _functor, 0, _array.Size()); } /* public ZArrayAlgo::FindFirst Looks for the first occurrence of the value between the specified indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to look for @param _start - the index to start looking at @param _end - the end index (exclusive) @return (size_t) - the index of the first match (ZSTL::InvalidPos if not found) @assert - if _end < _start if _start or _end out of bounds */ template size_t FindFirst(const ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FindFirstOf - Cannot find with end < start!"); #endif for (size_t i = start; i < end; i++) { if (_array.Data()[i] == _value) return i; } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindFirst Looks for the first occurrence of the specified value in the given array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to look for @return (size_t) - the index of the first match (ZSTL::InvalidPos if not found) */ template size_t FindFirst(const ZArray& _array, const T& _value) { return FindFirst(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::FindFirstOf Looks for the first occurrence of one of the given values between the specified indices. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _s1 - the starting index in array @param _e1 - the ending index in array (exclusive) @param _values - the values to look for @param _s2 - the starting index in values @param _e2 - the ending index in values (exclusive) @return (size_t) - the index of the first match (ZSTL::InvalidPos if not found) @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template size_t FindFirstOf(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _values, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return ZSTL::InvalidPos; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _values.BoundsCheck(_s2, _values.Size()); const size_t e2 = _values.BoundsCheck(_e2, _values.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::FindFirstOf - Cannot find with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::FindFirstOf - Cannot find with e2 < s2!"); #endif for (size_t i = s1; i < e1; i++) { for (size_t j = s2; j < e2; j++) { if ( _array.Data()[i] == _values.Data()[j] ) return i; } } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindFirstOf Looks for the first occurrence of one of the specified values in the given array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _values - the values to look for @return (size_t) - the index of the first match (ZSTL::InvalidPos if not found) */ template size_t FindFirstOf(const ZArray& _array, const ZArray& _values) { return FindFirstOf(_array, 0, _array.Size(), _values, 0, _values.Size()); } /* public ZArrayAlgo::FindFirstNot Looks for the first occurrence of a value that is not the provided value between the specified indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to avoid @param _start - the index to start looking at @param _end - the end index (exclusive) @return (size_t) - the index of the first non-match (ZSTL::InvalidPos if not found) @assert - if _end < _start if _start or _end out of bounds */ template size_t FindFirstNot(const ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FindFirstNot - Cannot find with end < start!"); #endif for (size_t i = start; i < end; i++) { if (!(_array.Data()[i] == _value)) return i; } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindFirstNot Looks for the first occurrence of a value that is not the provided value in the given array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to avoid @return (size_t) - the index of the first non-match (ZSTL::InvalidPos if not found) */ template size_t FindFirstNot(const ZArray& _array, const T& _value) { return FindFirstNot(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::FindFirstNotOf Looks for the first occurrence of a value that is not one of the provided values between the specified indices. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _s1 - the starting index in array @param _e1 - the ending index in array (exclusive) @param _values - the values to avoid @param _s2 - the starting index in values @param _e2 - the ending index in values (exclusive) @return (size_t) - the index of the first non-match (ZSTL::InvalidPos if not found) @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template size_t FindFirstNotOf(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _values, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return ZSTL::InvalidPos; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _values.BoundsCheck(_s2, _values.Size()); const size_t e2 = _values.BoundsCheck(_e2, _values.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::FindFirstNotOf - Cannot find with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::FindFirstNotOf - Cannot find with e2 < s2!"); #endif for (size_t i = s1; i < e1; i++) { for (size_t j = s2; j < e2; j++) { if ( _array.Data()[i] == _values.Data()[j] ) break; if (j == e2 - 1) return i; } } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindFirstNotOf Looks for the first occurrence of a value that is not one of the provided values in the given array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _values - the values to avoid @return (size_t) - the index of the first non-match (ZSTL::InvalidPos if not found) */ template size_t FindFirstNotOf(const ZArray& _array, const ZArray& _values) { return FindFirstNotOf(_array, 0, _array.Size(), _values, 0, _values.Size()); } /* public ZArrayAlgo::FindLast Finds the last occurrence of the specified value in the array between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to find @param _start - the index to start looking at @param _end - the end index (exclusive) @return (size_t) - the final occurrence of _value in the array (ZSTL::InvalidPos if not found) @assert - if _end < _start if _start or _end out of bounds */ template size_t FindLast(const ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FindLast - Cannot find with end < start!"); #endif for (size_t i = end; i > start; i--) { if (_array.Data()[i - 1] == _value) return i - 1; } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindLast Finds the last occurrence of the specified value in the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to find @return (size_t) - the final occurrence of _value in the array (ZSTL::InvalidPos if not found) */ template size_t FindLast(const ZArray& _array, const T& _value) { return FindLast(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::FindLastOf Finds the last occurrence of one of the specified values in the array between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _s1 - the starting index in array @param _e1 - the ending index in array (exclusive) @param _values - the values to look for @param _s2 - the starting index in values @param _e2 - the ending index in values (exclusive) @return (size_t) - the index of the last match (ZSTL::InvalidPos if not found) @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template size_t FindLastOf(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _values, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return ZSTL::InvalidPos; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _values.BoundsCheck(_s2, _values.Size()); const size_t e2 = _values.BoundsCheck(_e2, _values.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::FindFirstNotOf - Cannot find with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::FindFirstNotOf - Cannot find with e2 < s2!"); #endif for (size_t i = e1; i > s1; i--) { for (size_t j = s2; j < e2; j++) { if (_array.Data()[i - 1] == _values.Data()[j]) return i - 1; } } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindLastOf Finds the last occurrence of one of the specified values in the array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _value - the value to find @return (size_t) - the final occurrence of _value in the array (ZSTL::InvalidPos if not found) */ template size_t FindLastOf(const ZArray& _array, const ZArray& _values) { return FindLastOf(_array, 0, _array.Size(), _values, 0, _values.Size()); } /* public ZArrayAlgo::FindLastNot Finds the last occurrence of a value that is not the specified value in the array. between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to avoid @param _start - the index to start looking at @param _end - the end index (exclusive) @return (size_t) - the final occurrence of a non-match in the array (ZSTL::InvalidPos if not found) @assert - if _end < _start if _start or _end out of bounds */ template size_t FindLastNot(const ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FindLastNotOf - Cannot find with end < start!"); #endif for (size_t i = end; i > start; i--) { if (!(_array.Data()[i - 1] == _value)) return i - 1; } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindLastNot Finds the last occurrence of a value that is not the specified value in the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to find elements in @param _value - the value to avoid @return (size_t) - the final occurrence of a non-match in the array (ZSTL::InvalidPos if not found) */ template size_t FindLastNot(const ZArray& _array, const T& _value) { return FindLastNot(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::FindLastNotOf Finds the last occurrence of a value that is not one of the specified values in the array between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type for the values array @param _array - the array to find elements in @param _s1 - the starting index in array @param _e1 - the ending index in array (exclusive) @param _values - the values to avoid @param _s2 - the starting index in values @param _e2 - the ending index in values (exclusive) @return (size_t) - the index of the last non0match (ZSTL::InvalidPos if not found) @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template size_t FindLastNotOf(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _values, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return ZSTL::InvalidPos; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _values.BoundsCheck(_s2, _values.Size()); const size_t e2 = _values.BoundsCheck(_e2, _values.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::FindFirstNotOf - Cannot find with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::FindFirstNotOf - Cannot find with e2 < s2!"); #endif for (size_t i = e1; i > s1; i--) { for (size_t j = s2; j < e2; j++) { if (_array.Data()[i - 1] == _values.Data()[j]) break; if (j == e2 - 1) return i - 1; } } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindLastNotOf Finds the last occurrence of a value that is not one of the specified values in the array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the values array @param _array - the array to find elements in @param _values - the values to avoid @return (size_t) - the final occurrence of a non-match in the array (ZSTL::InvalidPos if not found) */ template size_t FindLastNotOf(const ZArray& _array, const ZArray& _values) { return FindLastNotOf(_array, 0, _array.Size(), _values, 0, _values.Size()); } /* public ZArrayAlgo::FindSub Looks for the first occurrence of a sub array within the given array in the given region. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to search in @param _s1 - the starting index in _array @param _e1 - the ending index in _array (exclusive) @param _other - the values to search for @param _s2 - the starting index in _other @param _e2 - the ending index in _other (exclusive) @return (size_t) - index to the first occurrence of the sub array @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template size_t FindSub(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return ZSTL::InvalidPos; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _other.BoundsCheck(_s2, _other.Size()); const size_t e2 = _other.BoundsCheck(_e2, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::FindSub - Cannot compare with e1 < s1!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::FindSub - Cannot compare with e2 < s2!"); #endif // easy case: subarray is empty if (_other.Empty()) return ZSTL::InvalidPos; // easy case: subarray can't fit into array if ( _array.Size() <= e2 - s2) return ZSTL::InvalidPos; // easy case: subarray can't fit into region of array if ( e1 - s1 < e2 - s2) return ZSTL::InvalidPos; for (size_t i = s1; i <= e1 - (e2 - s2); i++) { if (_array.Data()[i] == _other.Data()[s2]) { // short-circuit if matching just one thing if (e2 - s2 == 1) return i; size_t arrayOffset = i + 1; // matched first element, so now try the ccccombo for (size_t j = s2 + 1; j < e2; j++) { if (_array.Data()[arrayOffset] != _other.Data()[j]) break; if ((arrayOffset+1) - i == e2 - s2) return i; arrayOffset++; // won't overrun due to (_array.Size() <= e2-s2) constraint } } } return ZSTL::InvalidPos; } /* public ZArrayAlgo::FindSub Looks for the first occurrence of a sub array within the given array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to look in @param _other - the sub array to look for @return (size_t) - index to the first occurrence of the sub array */ template size_t FindSub(const ZArray& _array, const ZArray& _other) { return FindSub(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::FoldLeft Executes an iterative fold left on the provided array in the given region. Given an initial value V, an array region containing [ 1, 2, 3, 4 ] and a functor that emulates the + operation, fold left produces the following result: FoldLeft( [ 1, 2, 3, 4 ], (+), V ) -> ( ( (V + 1) + 2 ) + 3 ) + 4 @param F - binary functor [(const T&, const T&) -> T] for the fold operation @param V - the initial value type and accumulated type @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to accumulate on @param _functor - instance of the binary functor F to test with @param _initialValue - the initial value for the fold operation @param _start - the starting index @param _end - the ending index (exclusive) @return (V) - the accumulated value @assert - if _end < _start if _start or _end out of bounds */ template V FoldLeft(const ZArray& _array, F _functor, V _initialValue, size_t _start, size_t _end ) { if (_start == _end) return _initialValue; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FoldLeft - Cannot fold with end < start!"); #endif for (size_t i = start; i < end; i++) _initialValue = _functor(_initialValue, _array.Data()[i]); return _initialValue; } /* public ZArrayAlgo::FoldLeft Executes an iterative fold left on the provided array. Given an initial value V, an array containing [ 1, 2, 3, 4 ] and a functor that emulates the + operation, fold left produces the following result: FoldLeft( [ 1, 2, 3, 4 ], (+), V ) -> ( ( (V + 1) + 2 ) + 3 ) + 4 @param F - binary functor [(const T&, const T&) -> T] used for the fold operation @param V - the initial value type and accumulated type @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to accumulate on @param _functor - instance of the binary functor F to test with @param _initialValue - the initial value for the fold operation @return (V) - the accumulated value */ template V FoldLeft(const ZArray& _array, F _functor, V _initialValue) { return FoldLeft(_array, _functor, _initialValue, 0, _array.Size()); } /* public ZArrayAlgo::FoldRight Executes an iterative fold right on the provided array in the given region. Given an initial value V, an array region containing [ 1, 2, 3, 4 ] and a functor that emulates the + operation, fold right produces the following result: FoldRight( [ 1, 2, 3, 4 ], (+), V ) -> 1 + ( 2 + ( 3 + ( 4 + V ) ) ) @param F - binary functor [(const T&, const T&) -> T] for the fold operation @param V - the initial value type and accumulated type @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to accumulate on @param _functor - instance of the binary functor F to test with @param _initialValue - the initial value for the fold operation @param _start - the starting index @param _end - the ending index (exclusive) @return (V) - the accumulated value @assert - if _end < _start if _start or _end out of bounds */ template V FoldRight(const ZArray& _array, F _functor, V _initialValue, size_t _start, size_t _end ) { if (_start == _end) return _initialValue; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FoldLeft - Cannot fold with end < start!"); #endif for (size_t i = end; i > start; i--) _initialValue = _functor(_array.Data()[i - 1], _initialValue); return _initialValue; } /* public ZArrayAlgo::FoldRight Executes an iterative fold right on the provided array. Given an initial value V, an array containing [ 1, 2, 3, 4 ] and a functor that emulates the + operation, fold right produces the following result: FoldRight( [ 1, 2, 3, 4 ], (+), V ) -> 1 + ( 2 + ( 3 + ( 4 + V ) ) ) @param F - binary functor [(const T&, const T&) -> T] used for the fold operation the first argument is the value at the current point in the array the second argument is the current accumulated value @param V - the initial value type and accumulated type @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to accumulate on @param _functor - instance of the binary functor F to test with @param _initialValue - the initial value for the fold operation @return (V) - the accumulated value */ template V FoldRight(const ZArray& _array, F _functor, V _initialValue) { return FoldRight(_array, _functor, _initialValue, 0, _array.Size()); } /* public ZArrayAlgo::Generate Fills the given region of the array with values generated from the provided generator functor. @param F - binary functor [(size_t, size_t) -> T] used to generate the first argument is the current number in the generated sequence the second argument is the number of generations remaining @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to generate values for @param _functor - instance of the binary functor GF to generate values with @param _start - the starting index @param _end - the ending index (exclusive) @return (void) @assert - if _end < _start if _start or _end out of bounds */ template void Generate(ZArray& _array, GF _generator, size_t _start, size_t _end) { if (_start == _end) return; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::FindLastNotOf - Cannot find with end < start!"); #endif for (size_t i = start; i < end; i++) _array.Data()[i] = _generator( i - start, end - start); } /* public ZArrayAlgo::Generate Fills the array with values generated from the provided generator functor. @param F - binary functor [(size_t, size_t) -> T] used to generate the first argument is the current number in the generated sequence the second argument is the number of generations remaining @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to generate values for @param _functor - instance of the binary functor GF to generate values with @return (void) */ template void Generate(ZArray& _array, GF _generator) { ZArrayAlgo::Generate( _array, _generator, 0, _array.Size()); } /* public ZArrayAlgo::Map Maps the provided functor over the array between the given indices, returning a transformed array and leaving the original array intact. @param F - the unary functor ([T&] -> void) to transform the array with @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to transform @param _functor - instance of the unary functor F to operate on @param _start - the starting index @param _end - the ending index (exclusive) @return (ZArray) the transformed array @assert - if _end < _start if _start or _end out of bounds */ template ZArray Map(const ZArray& _array, F _functor, size_t _start, size_t _end) { const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Map - Cannot transform with end < start!"); #endif ZArray ret(&_array.Data()[start], end - start); for (size_t i = 0; i < end - start ; i++) _functor(ret.Data()[i]); return ret; } /* public ZArrayAlgo::Map Maps the provided functor over the array, returning a transformed array and leaving the original array intact. @param F - the unary functor ([T&] -> void) to transform the array with @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to transform @param _functor - instance of the unary functor F to operate on @return (ZArray) the transformed array */ template ZArray Map(const ZArray& _array, F _functor) { return Map(_array, _functor, 0, _array.Size()); } /* public ZArrayAlgo::Max Function to find the index of the first instance of the max value of an array. @param _array - the array to find the max of @param _comparator - the comparator to use when determining maximum @param _start - the starting index (inclusive) to begin searching for the maximum from @param _end - the ending index (exclusive) for the search @return (size_t) - the index of the maximum value */ template size_t Max(const ZArray& _array, CF _comparator, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Max - Cannot remove with end < start!"); ZSTL_ASSERT(_array.Empty() == false, "ZArrayAlgo::Max - Cannot find min of empty array!\n"); #endif size_t maxIndex = start; for (size_t i = start; i < end; i++) { if ( _comparator( _array[maxIndex], _array[i]) < 0) maxIndex = i; } return maxIndex; } /* public ZArrayAlgo::Max Function to find the index of the first instance of the max value of an array. @param _array - the array to find the max of @return (size_t) - the index of the maximum value */ template size_t Max(const ZArray& _array) { return Max(_array, ZComparator(), 0, _array.Size()); } /* public ZArrayAlgo::Max Function to find the index of the first instance of the max value of an array. @param _array - the array to find the max of @param _comparator - the comparator to use when determining maximum @return (size_t) - the index of the maximum value */ template size_t Max(const ZArray& _array, CF _comparator) { return Max(_array, _comparator, 0, _array.Size()); } /* public ZArrayAlgo::Max Function to find the index of the first instance of the max value of an array. @param _array - the array to find the max of @param _start - the starting index (inclusive) to begin searching for the maximum from @param _end - the ending index (exclusive) for the search @return (size_t) - the index of the maximum value */ template size_t Max(const ZArray& _array, size_t _start, size_t _end) { return Max(_array, ZComparator(), _start, _end); } /* public ZArrayAlgo::Min Function to find the index of the first instance of the min value of an array. @param _array - the array to find the min of @param _comparator - the comparator to use when determining minimum @param _start - the starting index (inclusive) to begin searching for the minimum from @param _end - the ending index (exclusive) for the search @return (size_t) - the index of the minimum value */ template size_t Min(const ZArray& _array, CF _comparator, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Min - Cannot remove with end < start!"); ZSTL_ASSERT(_array.Empty() == false, "ZArrayAlgo::Min - Cannot find min of empty array!\n"); #endif size_t maxIndex = start; for (size_t i = start; i < end; i++) { if ( _comparator( _array[maxIndex], _array[i]) > 0) maxIndex = i; } return maxIndex; } /* public ZArrayAlgo::Min Function to find the index of the first instance of the min value of an array. @param _array - the array to find the min of @return (size_t) - the index of the minimum value */ template size_t Min(const ZArray& _array) { return Min(_array, ZComparator(), 0, _array.Size()); } /* public ZArrayAlgo::Min Function to find the index of the first instance of the min value of an array. @param _array - the array to find the min of @param _comparator - the comparator to use when determining minimum @return (size_t) - the index of the minimum value */ template size_t Min(const ZArray& _array, CF _comparator) { return Min(_array, _comparator, 0, _array.Size()); } /* public ZArrayAlgo::Min Function to find the index of the first instance of the min value of an array. @param _array - the array to find the min of @param _start - the starting index (inclusive) to begin searching for the minimum from @param _end - the ending index (exclusive) for the search @return (size_t) - the index of the minimum value */ template size_t Min(const ZArray& _array, size_t _start, size_t _end) { return Min(_array, ZComparator(), _start, _end); } /* public ZArrayUtil::Remove Removes the first occurrence of the given element in the given range. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _value - the value to remove @param _start - the index to start at @param _end - the ending index (exclusive) @return (size_t) - the index at which the first occurrence was removed from, ZSTL::InvalidPos if no occurrence @assert - if _end < _start if _start or _end out of bounds */ template size_t Remove(ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return ZSTL::InvalidPos; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Remove - Cannot remove with end < start!"); #endif for (size_t i = start; i < end; i++) { if (_array.Data()[i] == _value) { _array.Erase(i); return i; } } return ZSTL::InvalidPos; } /* public ZArrayUtil::Remove Removes the first occurrence of the given element in the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _element - the element to remove @return (size_t) - the index at which the first occurrence was removed from, ZSTL::InvalidPos if no occurrence */ template size_t Remove(ZArray& _array, const T& _element) { return Remove(_array, _element, 0, _array.Size()); } /* public ZArrayUtil::RemoveAll Removes all occurrences of the given element in the given range. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _value - the value to remove @param _start - the index to start at @param _end - the ending index (exclusive) @return (size_t) - number of occurrences removed @assert - if _end < _start if _start or _end out of bounds */ template size_t RemoveAll(ZArray& _array, const T& _value, size_t _start, size_t _end) { if (_start == _end) return 0; size_t count = 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::RemoveAll - Cannot remove with end < start!"); #endif for (size_t i = end; i > start; i--) { if (_array.Data()[i - 1] == _value) { _array.Erase(i - 1); count++; } } return count; } /* public ZArrayUtil::RemoveAll Removes all occurrences of the given element from the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _value - the value to remove @return (size_t) - number of occurrences removed */ template size_t RemoveAll(ZArray& _array, const T& _value) { return RemoveAll(_array, _value, 0, _array.Size()); } /* public ZArrayAlgo::RemoveIf Removes elements from the array in the given range when the provided unary functor evaluates to true. @param F - unary functor ([const T&] -> bool) used to test elements @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _functor - functor instance of F used to evaluate elements @param _start - the index to start at @param _end - the ending index (exclusive) @return (size_t) - the number of elements removed @assert - if _end < _start if _start or _end out of bounds */ template size_t RemoveIf(ZArray& _array, F _functor, size_t _start, size_t _end) { if (_start == _end) return 0; size_t count = 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::RemoveIf - Cannot remove with end < start!"); #endif size_t toCheck = end - start; size_t i = end-1; while (toCheck > 0) { if (_functor(_array.Data()[i])) { _array.Erase(i); count++; } i--; toCheck--; } return count; } /* public ZArrayAlgo::RemoveIf Removes elements from the array when the provided unary functor evaluates to true. @param F - unary functor ([const T&] -> bool) used to test elements @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _functor - functor instance of F used to evaluate elements @return (size_t) - the number of elements removed */ template size_t RemoveIf(ZArray& _array, F _functor) { return RemoveIf(_array, _functor, 0, _array.Size()); } /* public ZArrayAlgo::RemoveUpTo Removes up to the provided number of occurrences of a value from the array in the specified range. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _value - the value to look for @param _count - the maximum number of times to remove the value @param _start - the index to start at @param _end - the ending index (exclusive) @return (size_t) - the number of occurrences removed @assert - if _end < _start if _start or _end out of bounds */ template size_t RemoveUpTo(ZArray& _array, const T& _value, size_t _count, size_t _start, size_t _end) { if (_start == _end) return 0; size_t count = 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::RemoveUpTo - Cannot remove with end < start!"); #endif for (size_t i = end - 1; i < end && i >= start&& count < _count; i--) { if (_array.Data()[i] == _value) { _array.Erase(i); count++; } } return count; } /* public ZArrayAlgo::RemoveUpTo Removes up to the provided number of occurrences of a value from the array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to remove elements from @param _value - the value to look for @param _count - the maximum number of times to remove the value @return (size_t) - the number of occurrences removed */ template size_t RemoveUpTo(ZArray& _array, const T& _value, size_t _count) { return RemoveUpTo(_array, _value, _count, 0, _array.Size()); } /* public ZArrayAlgo::Replace Finds and replaces all occurrences of the provided element with another in the given region. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to replace values in @param _value - the value to look for @param _newValue - the value to replace with @param _start - the starting index @param _end - the ending index (exclusive) @return (size_t) - the number of values replaced @assert - if _end < _start if _start or _end out of bounds */ template size_t Replace(ZArray& _array, const T& _value, const T& _newValue, size_t _start, size_t _end) { if (_start == _end) return 0; size_t count = 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Replace - Cannot replace with end < start!"); #endif for (size_t i = start; i < end; i++) { if (_array.Data()[i] == _value) { _array.Data()[i] = _newValue; count++; } } return count; } /* public ZArrayAlgo::Replace Finds and replaces all occurrences of the provided element with another. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to replace values in @param _value - the value to look for @param _newValue - the value to replace with @return (size_t) - the number of values replaced */ template size_t Replace(ZArray& _array, const T& _value, const T& _newValue) { return Replace(_array, _value, _newValue, 0, _array.Size()); } /* public ZArrayAlgo::ReplaceIf Replaces values in the array when the provided unary functor evaluates to true within the given range. @param F - unary functor ([const &] -> bool) to use to evaluate elements @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to replace elements in @param _functor - instance of unary functor F to use @param _newValue - the value to replace with @param _start - the starting index @param _end - the ending index (exclusive) @return (size_t) - the number of replaced elements @assert - if _end < _start if _start or _end out of bounds */ template size_t ReplaceIf(ZArray& _array, F _functor, const T& _newValue, size_t _start, size_t _end) { if (_start == _end) return 0; size_t count = 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::ReplaceIf - Cannot replace with end < start!"); #endif for (size_t i = start; i < end; i++) { if (_functor(_array.Data()[i])) { _array.Data()[i] = _newValue; count++; } } return count; } /* public ZArrayAlgo::ReplaceIf Replaces values in the array when the provided unary functor evaluates to true. @param F - unary functor ([const &] -> bool) to use to evaluate elements @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to replace elements in @param _functor - instance of unary functor F to use @param _newValue - the value to replace with @return (size_t) - the number of replaced elements */ template size_t ReplaceIf(ZArray& _array, F _functor, const T& _newValue) { return ReplaceIf(_array, _functor, _newValue, 0, _array.Size()); } /* public ZArrayAlgo::Reverse Reverses an array in place between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to reverse @param _start - the starting index @param _end - the ending index (exclusive) @return (void) */ template void Reverse(ZArray& _array, size_t _start, size_t _end) { if (_start == _end) return; T temp; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Reverse - Cannot reverse with end < start!"); #endif if (start == end) return; // note that the assert above and the _start == _end protect this from crashing for start = end = 0 for (size_t i = start, j = end - 1; i < j; i++, j--) { temp = _array.Data()[i]; _array.Data()[i] = _array.Data()[j]; _array.Data()[j] = temp; } } /* public ZArrayAlgo::Reverse Reverses an array in place. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to reverse @return (void) */ template void Reverse(ZArray& _array) { Reverse(_array, 0, _array.Size()); } /* public ZArrayAlgo::Rotate Function to shift an array so that a given element is at the front. [ 0 1 2 3 4 5] --> [ 3 4 5 0 1 2 3] ^ pivot point @param _array - array to pivot @param _pivot - index to pivot (inclusive) @param _start - starting index (inclusive) of array slice to rotate @param _end - ending index (exclusive) of array slice to rotate @return (void) @assert - if _pivot, _start, or _end out of bounds if _pivot >= end if _pivot < _start */ template void Rotate(ZArray& _array, size_t _pivot, size_t _start, size_t _end) { if (_start == _end) return; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t pivot = _array.BoundsCheck(_pivot, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Reverse - Cannot reverse with end < start!"); ZSTL_ASSERT(pivot >= start, "ZArrayAlgo::Rotate - Cannot rotate with pivot before start!"); ZSTL_ASSERT(pivot < end, "ZArrayAlgo::Rotate - Cannot rotate with pivot past end!"); #endif ZArray temp(_array.Size()); // copy everything before the part to rotate for (size_t i = 0; i < _start; i++) temp.PushBack(_array.Data()[i]); // copy everything including and after the pivot for (size_t i = pivot; i < end ; i++) temp.PushBack(_array.Data()[i]); // copy everything up to the pivot for (size_t i = start; i < pivot; i++) temp.PushBack(_array.Data()[i]); // copy everything left after the end section for (size_t i = _end; i < _array.Size(); i++) temp.PushBack(_array.Data()[i]); _array.Copy(temp); } /* public ZArrayAlgo::Rotate Function to shift an array so that a given element is at the front. [ 0 1 2 3 4 5] --> [ 3 4 5 0 1 2 3] ^ pivot point @param _array - array to pivot @param _pivot - index to pivot (inclusive) @return (void) @assert - if _pivot out of bounds */ template void Rotate(ZArray& _array, size_t _pivot) { return ZArrayAlgo::Rotate(_array, _pivot, 0, _array.Size()); } /* public ZArrayAlgo::SetIntersection Function to compute the intersection of two arrays. [ A B C ] ^ [ C D E ] -> [ C ] @param _array - first array @param _s1 - starting index (inclusive) of first array @param _e1 - ending index (exclusive) of first array @param _other - second array @param _s2 - starting index (inclusive) of second array @param _e2 - starting index (exclusive) of second array @return (ZArray) - array with unique elements from the intersection of the two arrays @assert - if s1 > e1 if s2 > e2 if s1, e1, s2, e2 out of bounds */ template ZArray SetIntersection(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { if (_s1 == _e1 || _s2 == _e2) return ZArray(); const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _other.BoundsCheck(_s2, _other.Size()); const size_t e2 = _other.BoundsCheck(_e2, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::SetUnion - Cannot accumulate with first list end < start!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::SetUnion - Cannot accumulate with second list end < start!"); #endif ZArray ret(e1-s1,e1-s1); Copy(ret, 0, e1-s1, _array, s1, e1); Unique(ret, 0, ret.Size()); for (size_t i = ret.Size(); i > 0; i--) { if (Contains(_other, ret.Data()[(i-1)], s2, e2) == false) ret.Erase(i-1); } return ret; } /* public ZArrayAlgo::SetIntersection Function to compute the intersection of two arrays. [ A B C ] ^ [ C D E ] -> [ C ] @param _array - first array @param _other - second array @return (ZArray) - array with unique elements from the intersection of the two arrays */ template ZArray SetIntersection(const ZArray& _array, const ZArray& _other) { return SetIntersection(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::SetUnion Function to compute the union of two arrays. [ A B C ] U [ C D E ] -> [ A B C D E] @param _array - first array @param _s1 - starting index (inclusive) of first array @param _e1 - ending index (exclusive) of first array @param _other - second array @param _s2 - starting index (inclusive) of second array @param _e2 - starting index (exclusive) of second array @return (ZArray) - array with unique elements from the union of the two arrays @assert - if s1 > e1 if s2 > e2 if s1, e1, s2, e2 out of bounds */ template ZArray SetUnion(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { if (_s1 == _e1) return _other; else if (_s2 == _e2) return _array; ZArray ret; const size_t s1 = _array.BoundsCheck(_s1, _array.Size()); const size_t e1 = _array.BoundsCheck(_e1, _array.Size() + 1); // 1 to allow indexing of end const size_t s2 = _other.BoundsCheck(_s2, _other.Size()); const size_t e2 = _other.BoundsCheck(_e2, _other.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(s1 <= e1, "ZArrayAlgo::SetUnion - Cannot accumulate with first list end < start!"); ZSTL_ASSERT(s2 <= e2, "ZArrayAlgo::SetUnion - Cannot accumulate with second list end < start!"); #endif for (size_t i = _s1; i < _e1; i++) { if (Contains(ret, _array[i]) == false) ret.PushBack(_array[i]); } for (size_t i = _s2; i < _e2; i++) { if (Contains(ret, _other[i]) == false) ret.PushBack(_other[i]); } return ret; } /* public ZArrayAlgo::SetUnion Function to compute the union of two arrays. [ A B C ] U [ C D E ] -> [ A B C D E] @param _array - first array @param _other - second array @return (ZArray) - array with unique elements from the union of the two arrays */ template ZArray SetUnion(const ZArray& _array, const ZArray& _other) { return SetUnion(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::Slice Removes a section of the provided array and returns a new array containing the data. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to excise data from @param _start - the index to start at @param _end - the ending index (exclusive) @return (ZArray) - the array slice @assert - if _end < _start if _start or _end out of bounds */ template ZArray Slice(ZArray& _array, size_t _start, size_t _end) { if (_start == _end) return ZArray(); ZArray ret(_array, _start, _end); _array.Erase(_start, _end); return ret; } /* public ZArrayAlgo::Sort Sorts an array in place using the provided comparator and algorithm between the given indices. @param CF - the comparator functor to use [(const T&, const T&) -> int] that compares values returns negative value if first value < second value returns positive value if first value > second value returns 0 if first value == second value @param AF - the algorithm functor to use [(CF&, T*, size_t) -> void] that sorts the array @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to sort @param _comparator - the comparator used to sort the contained values @param _algorithm - the array sort algorithm to use to sort the array @param _start - the starting index @param _end - the ending index (exclusive) @return (void) @assert - if _end < _start if _start or _end out of bounds */ template void Sort(ZArray& _array, CF _comparator, AF _algorithm, size_t _start, size_t _end) { if (_start == _end) return; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Sort - Cannot sort with end < start!"); #endif const size_t sliceSize = end - start; _algorithm(_comparator, &_array.Data()[start], sliceSize); } /* public ZArrayAlgo::Sort Sorts an array in place using the default comparator (uses operator <) and a non-stable quick sort. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to sort @return (void) */ template void Sort(ZArray& _array) { ZComparator comparator; ZArrayQuickSort algorithm; Sort(_array, comparator, algorithm, 0, _array.Size()); } /* public ZArrayAlgo::Sort Sorts an array in place using the default comparator (uses operator <) and uses a non-stable quick sort between the given indices. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to sort @param _start - the starting index @param _end - the ending index (exclusive) @return (void) @assert - if _end < _start if _start or _end out of bounds */ template void Sort(ZArray& _array, size_t _start, size_t _end) { ZComparator comparator; ZArrayQuickSort algorithm; Sort(_array, comparator, algorithm, _start, _end); } /* public ZArrayAlgo::Sort Sorts an array in place using the provided comparator and a non-stable quick sort algorithm. @param CF - the comparator functor to use [(const T&, const T&) -> int] that compares values returns negative value if first value < second value returns positive value if first value > second value returns 0 if first value == second value @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to sort @param _comparator - the comparator used to sort the contained values @return (void) */ template void Sort(ZArray& _array, CF _comparator) { ZArrayQuickSort algorithm; Sort(_array, _comparator, algorithm, 0, _array.Size()); } /* public ZArrayAlgo::Split Splits a range of the array into a set of arrays at locations that have a value contained in the provided set of delimiters. The delimiters are consumed from the array in the process. The array is split only up to the provided number of times. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the delimiter array @param _array - the array to split @param _delimiters - the set of delimiter values to split on @param _count - the maximum number of times to split the array @param _start - the starting index @param _end - the ending index (exclusive) @return (ZArray< ZArray >) - array of subsections of the original array @assert - if _end < _start if _start or _end out of bounds */ template ZArray< ZArray > Split(const ZArray& _array, const ZArray& _values, size_t _count, size_t _start, size_t _end) { ZArray< ZArray > sections(_array.Size() + 1); if (_start == _end) return sections; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Split - Cannot split with end < start!"); #endif //Location of the previous delimiter size_t previous = start; for (size_t i = start; i < end; i++) { if (sections.Size() == _count) //Break out if we have reached our count limit break; for (size_t j = 0; j < _values.Size(); j++) { if ( _array.Data()[i] == _values.Data()[j] ) { if (i > previous) //If we have more than just one of the delimiters sections.PushBack( ZArray(_array, previous, i) ); previous = i + 1; break; } } } if (previous != end) //Add the final section sections.PushBack( ZArray(_array, previous, end) ); return sections; } /* public ZArrayAlgo::Split Splits the array into a set of arrays at locations that have a value contained in the provided set of delimiters. The delimiters are consumed from the array in the process. The array is split only up to the provided number of times. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the delimiter array @param _array - the array to split @param _delimiters - the set of delimiter values to split on @param _count - the maximum number of times to split the array @return (ZArray< ZArray >) - array of subsections of the original array */ template ZArray< ZArray > Split(const ZArray& _array, const ZArray& _delimiters, size_t _count) { return Split(_array, _delimiters, _count, 0, _array.Size()); } /* public ZArrayAlgo::Split Splits the array into a set of arrays at locations that have a value contained in the provided set of delimiters. The delimiters are consumed from the array in the process. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the delimiter array @param _array - the array to split @param _delimiters - the set of delimiter values to split on @return (ZArray< ZArray >) - array of subsections of the original array */ template ZArray< ZArray > Split(const ZArray& _array, const ZArray& _delimiters) { return Split(_array, _delimiters, _array.Size(), 0, _array.Size()); } /* public ZArrayAlgo::StartsWith Used to determine if the given region of the provided array starts with the contents of the given region of the other array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to check @param _s1 - the starting index to check against @param _e1 - the ending index to check against (exclusive) @param _other - the array to check from @param _s2 - the starting index to check from @param _e2 - the ending index to check to (exclusive) @return (bool) - true if the array starts with the provided values, false otherwise @assert - if _s1, _e1, _s2, or _e2 out of bounds if _e1 < _s1 or _e2 < _s2 */ template bool StartsWith(const ZArray& _array, size_t _s1, size_t _e1, const ZArray& _other, size_t _s2, size_t _e2) { return FindSub(_array, _s1, _e1, _other, _s2, _e2) == _s1; } /* public ZArrayAlgo::StartsWith Used to determine if the provided array starts with the contents of the other array. @param T - the type held by the array @param A - the allocator type of the array @param B - the allocator type of the other array @param _array - the array to check @param _other - the array to check from @return (bool) - true if the array ends with the provided values, false otherwise */ template bool StartsWith(const ZArray& _array, const ZArray& _other) { return StartsWith(_array, 0, _array.Size(), _other, 0, _other.Size()); } /* public ZArrayAlgo::Sum Returns the result of summing (via operator +) all the elements within a range in the array. @param V - the initial value type and sum type @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to accumulate on @param _initialValue - the initial value for the accumulation @param _start - the starting index @param _end - the ending index (exclusive) @return (V) - the accumulated value @assert - if _end < _start if _start or _end out of bounds */ template V Sum(const ZArray& _array, V _initialValue, size_t _start, size_t _end) { if (_start == _end) return _initialValue; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Accumulate - Cannot accumulate with end < start!"); #endif for (size_t i = start; i < end; i++) _initialValue = _initialValue + _array.Data()[i]; return _initialValue; } /* public ZArrayAlgo::Sum Returns the result of summing (via operator +) all the elements in the array. @param V - the initial value type and sum type @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to accumulate on @param _initialValue - the initial value for the accumulation @return (V) - the accumulated value */ template V Sum(const ZArray& _array, V _initialValue) { return Sum(_array, _initialValue, 0, _array.Size()); } /* public ZArrayUtil::SwapElements Swaps the values in two indices to this array. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to swap elements in @param _i - the first value @param _j - the second value @return (void) @assert - if _i or _j are out of bounds */ template void SwapElements(ZArray& _array, size_t _start, size_t _end) { if (_start == _end) return; const size_t i = _array.BoundsCheck(_start, _array.Size()); const size_t j = _array.BoundsCheck(_end, _array.Size()); T temp = _array.Data()[i]; _array.Data()[i] = _array.Data()[j]; _array.Data()[j] = temp; } /* public ZArrayAlgo::Unique Makes all the values in an array unique within the given range. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to make full of unique values @param _start - the starting index @param _end - the ending index (exclusive) @return (size_t) - the number of values removed @assert - if _end < _start if _start or _end out of bounds */ template size_t Unique(ZArray& _array, size_t _start, size_t _end) { if (_start == _end) return 0; const size_t start = _array.BoundsCheck(_start, _array.Size()); const size_t end = _array.BoundsCheck(_end, _array.Size() + 1); // 1 to allow indexing of end #if !ZSTL_DISABLE_RUNTIME_CHECKS ZSTL_ASSERT(start <= end, "ZArrayAlgo::Unique - Cannot make unique with end < start!"); #endif size_t removed = 0; for (size_t i = start; i < end - removed; i++) { for (size_t j = end - removed - 1; j > i; j--) { if (_array.Data()[i] == _array.Data()[j]) { removed++; _array.Erase(j); } } } return removed; } /* public ZArrayAlgo::Unique Makes all the values in an array unique. @param T - the type held by the array @param A - the allocator type of the array @param _array - the array to make full of unique values @return (size_t) - the number of values removed */ template size_t Unique(ZArray& _array) { return Unique(_array, 0, _array.Size()); } } #endif