/**
 * The namespace for array-specific algorithms.
 */ export namespace ArrayExt { param array param value param start param stop returns export function firstIndexOf < T > ( array , value , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return - 1 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let span ; if ( stop < start ) { span = stop + 1 + ( n - start ) ; } else { span = stop - start + 1 ; } for ( let i = 0 ; i < span ; ++ i ) { let j = ( start + i ) % n ; if ( array [ j ] === value ) { return j ; } } return - 1 ; } param array param value param start param stop returns export function lastIndexOf < T > ( array , value , start = - 1 , stop = 0 ) { let n = array . length ; if ( n === 0 ) { return - 1 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let span ; if ( start < stop ) { span = start + 1 + ( n - stop ) ; } else { span = start - stop + 1 ; } for ( let i = 0 ; i < span ; ++ i ) { let j = ( start - i + n ) % n ; if ( array [ j ] === value ) { return j ; } } return - 1 ; } param array param fn param start param stop returns export function findFirstIndex < T > ( array , fn , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return - 1 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let span ; if ( stop < start ) { span = stop + 1 + ( n - start ) ; } else { span = stop - start + 1 ; } for ( let i = 0 ; i < span ; ++ i ) { let j = ( start + i ) % n ; if ( fn ( array [ j ] , j ) ) { return j ; } } return - 1 ; } param object param fn param start param stop returns export function findLastIndex < T > ( array , fn , start = - 1 , stop = 0 ) { let n = array . length ; if ( n === 0 ) { return - 1 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let d ; if ( start < stop ) { d = start + 1 + ( n - stop ) ; } else { d = start - stop + 1 ; } for ( let i = 0 ; i < d ; ++ i ) { let j = ( start - i + n ) % n ; if ( fn ( array [ j ] , j ) ) { return j ; } } return - 1 ; } param array param fn param start param stop returns export function findFirstValue < T > ( array , fn , start = 0 , stop = - 1 ) { let index = findFirstIndex ( array , fn , start , stop ) ; return index !== - 1 ? array [ index ] : undefined ; } param object param fn param start param stop returns export function findLastValue < T > ( array , fn , start = - 1 , stop = 0 ) { let index = findLastIndex ( array , fn , start , stop ) ; return index !== - 1 ? array [ index ] : undefined ; } param array param value param fn param start param stop returns export function lowerBound < T , U > ( array , value , fn , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return 0 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let begin = start ; let span = stop - start + 1 ; while ( span > 0 ) { let half = span >> 1 ; let middle = begin + half ; if ( fn ( array [ middle ] , value ) < 0 ) { begin = middle + 1 ; span -= half + 1 ; } else { span = half ; } } return begin ; } param array param value param fn param start param stop returns export function upperBound < T , U > ( array , value , fn , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return 0 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let begin = start ; let span = stop - start + 1 ; while ( span > 0 ) { let half = span >> 1 ; let middle = begin + half ; if ( fn ( array [ middle ] , value ) > 0 ) { span = half ; } else { begin = middle + 1 ; span -= half + 1 ; } } return begin ; } param a param b param fn returns export function shallowEqual < T > ( a , b , fn ? ) { if ( a === b ) { return true ; } if ( a . length !== b . length ) { return false ; } for ( let i = 0 , n = a . length ; i < n ; ++ i ) { if ( fn ? ! fn ( a [ i ] , b [ i ] ) : a [ i ] !== b [ i ] ) { return false ; } } return true ; } param array param options returns throws export function slice < T > ( array , options = { } ) { let { start , stop , step } = options ; if ( step === undefined ) { step = 1 ; } if ( step === 0 ) { throw new Error ( 'Slice `step` cannot be zero.' ) ; } let n = array . length ; if ( start === undefined ) { start = step < 0 ? n - 1 : 0 ; } else if ( start < 0 ) { start = Math . max ( start + n , step < 0 ? - 1 : 0 ) ; } else if ( start >= n ) { start = step < 0 ? n - 1 : n ; } if ( stop === undefined ) { stop = step < 0 ? - 1 : n ; } else if ( stop < 0 ) { stop = Math . max ( stop + n , step < 0 ? - 1 : 0 ) ; } else if ( stop >= n ) { stop = step < 0 ? n - 1 : n ; } let length ; if ( ( step < 0 && stop >= start ) || ( step > 0 && start >= stop ) ) { length = 0 ; } else if ( step < 0 ) { length = Math . floor ( ( stop - start + 1 ) / step + 1 ) ; } else { length = Math . floor ( ( stop - start - 1 ) / step + 1 ) ; } let result = [ ] ; for ( let i = 0 ; i < length ; ++ i ) { result [ i ] = array [ start + i * step ] ; } return result ; } /**
     * The namespace for the `slice` function statics.
     */ export namespace slice { /**
         * The options for the `slice` function.
         */ export interface IOptions { /**
             * The starting index of the slice, inclusive.
             *
             * Negative values are taken as an offset from the end
             * of the array.
             *
             * The default is `0` if `step > 0` else `n - 1`.
             */ start ? : number ; /**
             * The stopping index of the slice, exclusive.
             *
             * Negative values are taken as an offset from the end
             * of the array.
             *
             * The default is `n` if `step > 0` else `-n - 1`.
             */ stop ? : number ; /**
             * The step value for the slice.
             *
             * This must not be `0`.
             *
             * The default is `1`.
             */ step ? : number ; } } /**
     * An array-like object which supports item assignment.
     */ export type MutableArrayLike < T > = { readonly length : number ; [ index ] : T ; } ; param array param fromIndex param toIndex export function move < T > ( array , fromIndex , toIndex ) { let n = array . length ; if ( n <= 1 ) { return ; } if ( fromIndex < 0 ) { fromIndex = Math . max ( 0 , fromIndex + n ) ; } else { fromIndex = Math . min ( fromIndex , n - 1 ) ; } if ( toIndex < 0 ) { toIndex = Math . max ( 0 , toIndex + n ) ; } else { toIndex = Math . min ( toIndex , n - 1 ) ; } if ( fromIndex === toIndex ) { return ; } let value = array [ fromIndex ] ; let d = fromIndex < toIndex ? 1 : - 1 ; for ( let i = fromIndex ; i !== toIndex ; i += d ) { array [ i ] = array [ i + d ] ; } array [ toIndex ] = value ; } param array param start param stop export function reverse < T > ( array , start = 0 , stop = - 1 ) { let n = array . length ; if ( n <= 1 ) { return ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } while ( start < stop ) { let a = array [ start ] ; let b = array [ stop ] ; array [ start ++ ] = b ; array [ stop -- ] = a ; } } param array param delta param start param stop export function rotate < T > ( array , delta , start = 0 , stop = - 1 ) { let n = array . length ; if ( n <= 1 ) { return ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } if ( start >= stop ) { return ; } let length = stop - start + 1 ; if ( delta > 0 ) { delta = delta % length ; } else if ( delta < 0 ) { delta = ( ( delta % length ) + length ) % length ; } if ( delta === 0 ) { return ; } let pivot = start + delta ; reverse ( array , start , pivot - 1 ) ; reverse ( array , pivot , stop ) ; reverse ( array , start , stop ) ; } param array param value param start param stop export function fill < T > ( array , value , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let span ; if ( stop < start ) { span = stop + 1 + ( n - start ) ; } else { span = stop - start + 1 ; } for ( let i = 0 ; i < span ; ++ i ) { array [ ( start + i ) % n ] = value ; } } param array param index param value export function insert < T > ( array , index , value ) { let n = array . length ; if ( index < 0 ) { index = Math . max ( 0 , index + n ) ; } else { index = Math . min ( index , n ) ; } for ( let i = n ; i > index ; -- i ) { array [ i ] = array [ i - 1 ] ; } array [ index ] = value ; } param array param index returns export function removeAt < T > ( array , index ) { let n = array . length ; if ( index < 0 ) { index += n ; } if ( index < 0 || index >= n ) { return undefined ; } let value = array [ index ] ; for ( let i = index + 1 ; i < n ; ++ i ) { array [ i - 1 ] = array [ i ] ; } array . length = n - 1 ; return value ; } param array param value param start param stop returns export function removeFirstOf < T > ( array , value , start = 0 , stop = - 1 ) { let index = firstIndexOf ( array , value , start , stop ) ; if ( index !== - 1 ) { removeAt ( array , index ) ; } return index ; } param array param value param start param stop returns export function removeLastOf < T > ( array , value , start = - 1 , stop = 0 ) { let index = lastIndexOf ( array , value , start , stop ) ; if ( index !== - 1 ) { removeAt ( array , index ) ; } return index ; } param array param value param start param stop returns export function removeAllOf < T > ( array , value , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return 0 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let count = 0 ; for ( let i = 0 ; i < n ; ++ i ) { if ( start <= stop && i >= start && i <= stop && array [ i ] === value ) { count ++ ; } else if ( stop < start && ( i <= stop || i >= start ) && array [ i ] === value ) { count ++ ; } else if ( count > 0 ) { array [ i - count ] = array [ i ] ; } } if ( count > 0 ) { array . length = n - count ; } return count ; } param array param fn param start param stop returns export function removeFirstWhere < T > ( array , fn , start = 0 , stop = - 1 ) { let value ; let index = findFirstIndex ( array , fn , start , stop ) ; if ( index !== - 1 ) { value = removeAt ( array , index ) ; } return { index , value } ; } param array param fn param start param stop returns export function removeLastWhere < T > ( array , fn , start = - 1 , stop = 0 ) { let value ; let index = findLastIndex ( array , fn , start , stop ) ; if ( index !== - 1 ) { value = removeAt ( array , index ) ; } return { index , value } ; } param array param fn param start param stop returns export function removeAllWhere < T > ( array , fn , start = 0 , stop = - 1 ) { let n = array . length ; if ( n === 0 ) { return 0 ; } if ( start < 0 ) { start = Math . max ( 0 , start + n ) ; } else { start = Math . min ( start , n - 1 ) ; } if ( stop < 0 ) { stop = Math . max ( 0 , stop + n ) ; } else { stop = Math . min ( stop , n - 1 ) ; } let count = 0 ; for ( let i = 0 ; i < n ; ++ i ) { if ( start <= stop && i >= start && i <= stop && fn ( array [ i ] , i ) ) { count ++ ; } else if ( stop < start && ( i <= stop || i >= start ) && fn ( array [ i ] , i ) ) { count ++ ; } else if ( count > 0 ) { array [ i - count ] = array [ i ] ; } } if ( count > 0 ) { array . length = n - count ; } return count ; } }