package java.util import scala.annotation.tailrec object Arrays { def sort[T <: Object](array: Array[Object], comparator: Comparator[T]): Unit = { scala.util.Sorting.stableSort[Object](array, (a: Object, b: Object) => comparator.compare(a.asInstanceOf[T], b.asInstanceOf[T]) < 0) } def fill(a: Array[Boolean], value: Boolean): Unit = fillImpl(a, value) def fill(a: Array[Boolean], fromIndex: Int, toIndex: Int, value: Boolean): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Byte], value: Byte): Unit = fillImpl(a, value) def fill(a: Array[Byte], fromIndex: Int, toIndex: Int, value: Byte): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Char], value: Char): Unit = fillImpl(a, value) def fill(a: Array[Char], fromIndex: Int, toIndex: Int, value: Char): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Short], value: Short): Unit = fillImpl(a, value) def fill(a: Array[Short], fromIndex: Int, toIndex: Int, value: Short): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Int], value: Int): Unit = fillImpl(a, value) def fill(a: Array[Int], fromIndex: Int, toIndex: Int, value: Int): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Long], value: Long): Unit = fillImpl(a, value) def fill(a: Array[Long], fromIndex: Int, toIndex: Int, value: Long): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Float], value: Float): Unit = fillImpl(a, value) def fill(a: Array[Float], fromIndex: Int, toIndex: Int, value: Float): Unit = fillImpl(a, fromIndex, toIndex, value) def fill(a: Array[Double], value: Double): Unit = fillImpl(a, value) def fill(a: Array[Double], fromIndex: Int, toIndex: Int, value: Double): Unit = fillImpl(a, fromIndex, toIndex, value) private def fillImpl[@specialized T](a: Array[T], value: T): Unit = { var i = 0 while (i != a.length) { a(i) = value i += 1 } } private def fillImpl[@specialized T](a: Array[T], fromIndex: Int, toIndex: Int, value: T): Unit = { if (fromIndex > toIndex) throw new IllegalArgumentException if (fromIndex < 0 || toIndex > a.length) throw new ArrayIndexOutOfBoundsException var i = fromIndex while (i != toIndex) { a(i) = value i += 1 } } def fill(a: Array[AnyRef], value: AnyRef): Unit = { var i = 0 while (i < a.length) { a(i) = value i += 1 } } def fill(a: Array[AnyRef], fromIndex: Int, toIndex: Int, value: AnyRef): Unit = { if (fromIndex > toIndex) throw new IllegalArgumentException if (fromIndex < 0 || toIndex > a.length) throw new ArrayIndexOutOfBoundsException var i = fromIndex while (i < toIndex) { a(i) = value i += 1 } } @inline private def checkIndexForBinarySearch( length: Int, start: Int, end: Int): Unit = { if (start > end) throw new IllegalArgumentException("fromIndex(" + start + ") > toIndex(" + end + ")") if (start < 0) throw new ArrayIndexOutOfBoundsException("Array index out of range: " + start) if (end > length) throw new ArrayIndexOutOfBoundsException("Array index out of range: " + end) } def binarySearch(a: Array[Char], key: Char): Int = binarySearchImpl[Char](a, 0, a.length, key, _ < _) def binarySearch(a: Array[Char], startIndex: Int, endIndex: Int, key: Char): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImpl[Char](a, startIndex, endIndex, key, _ < _) } def binarySearch(a: Array[Short], key: Short): Int = binarySearchImpl[Short](a, 0, a.length, key, _ < _) def binarySearch(a: Array[Short], startIndex: Int, endIndex: Int, key: Short): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImpl[Short](a, startIndex, endIndex, key, _ < _) } def binarySearch(a: Array[Int], key: Int): Int = binarySearchImpl[Int](a, 0, a.length, key, _ < _) def binarySearch(a: Array[Int], startIndex: Int, endIndex: Int, key: Int): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImpl[Int](a, startIndex, endIndex, key, _ < _) } def binarySearch(a: Array[Long], key: Long): Int = binarySearchImpl[Long](a, 0, a.length, key, _ < _) def binarySearch(a: Array[Long], startIndex: Int, endIndex: Int, key: Long): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImpl[Long](a, startIndex, endIndex, key, _ < _) } def binarySearch(a: Array[Float], key: Float): Int = binarySearchImpl[Float](a, 0, a.length, key, _ < _) def binarySearch(a: Array[Float], startIndex: Int, endIndex: Int, key: Float): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImpl[Float](a, startIndex, endIndex, key, _ < _) } def binarySearch(a: Array[Double], key: Double): Int = binarySearchImpl[Double](a, 0, a.length, key, _ < _) def binarySearch(a: Array[Double], startIndex: Int, endIndex: Int, key: Double): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImpl[Double](a, startIndex, endIndex, key, _ < _) } @inline @tailrec private def binarySearchImpl[@specialized T](a: Array[T], startIndex: Int, endIndex: Int, key: T, lt: (T, T) => Boolean): Int = { if (startIndex == endIndex) { // Not found -startIndex - 1 } else { // Indices are unsigned 31-bit integer, so this does not overflow val mid = (startIndex + endIndex) >>> 1 val elem = a(mid) if (lt(key, elem)) { binarySearchImpl(a, startIndex, mid, key, lt) } else if (key == elem) { // Found mid } else { binarySearchImpl(a, mid + 1, endIndex, key, lt) } } } def binarySearch(a: Array[AnyRef], key: AnyRef): Int = binarySearchImplRef(a, 0, a.length, key) def binarySearch(a: Array[AnyRef], startIndex: Int, endIndex: Int, key: AnyRef): Int = { checkIndexForBinarySearch(a.length, startIndex, endIndex) binarySearchImplRef(a, startIndex, endIndex, key) } @inline @tailrec def binarySearchImplRef(a: Array[AnyRef], startIndex: Int, endIndex: Int, key: AnyRef): Int = { if (startIndex == endIndex) { // Not found -startIndex - 1 } else { // Indices are unsigned 31-bit integer, so this does not overflow val mid = (startIndex + endIndex) >>> 1 val cmp = key.asInstanceOf[Comparable[AnyRef]].compareTo(a(mid)) if (cmp < 0) { binarySearchImplRef(a, startIndex, mid, key) } else if (cmp == 0) { // Found mid } else { binarySearchImplRef(a, mid + 1, endIndex, key) } } } def copyOf(original: Array[Boolean], newLength: Int): Array[Boolean] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Boolean], start: Int, end: Int): Array[Boolean] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Char], newLength: Int): Array[Char] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Char], start: Int, end: Int): Array[Char] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Byte], newLength: Int): Array[Byte] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Byte], start: Int, end: Int): Array[Byte] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Short], newLength: Int): Array[Short] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Short], start: Int, end: Int): Array[Short] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Int], newLength: Int): Array[Int] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Int], start: Int, end: Int): Array[Int] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Long], newLength: Int): Array[Long] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Long], start: Int, end: Int): Array[Long] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Float], newLength: Int): Array[Float] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Float], start: Int, end: Int): Array[Float] = copyOfRangeImpl(original, start, end, new Array(_)) def copyOf(original: Array[Double], newLength: Int): Array[Double] = copyOfImpl(original, newLength, new Array(_)) def copyOfRange(original: Array[Double], start: Int, end: Int): Array[Double] = copyOfRangeImpl(original, start, end, new Array(_)) @inline private def copyOfImpl[@specialized T](original: Array[T], newLength: Int, newArray: Int => Array[T]): Array[T] = { checkArrayLength(newLength) val copyLength = Math.min(newLength, original.length) val ret = newArray(newLength) System.arraycopy(original, 0, ret, 0, copyLength) ret } @inline private def copyOfRangeImpl[@specialized T](original: Array[T], start: Int, end: Int, newArray: Int => Array[T]): Array[T] = { checkIndicesForCopyOfRange(original.length, start, end) val retLength = end - start val copyLength = Math.min(retLength, original.length - start) val ret = newArray(retLength) System.arraycopy(original, start, ret, 0, copyLength) ret } def copyOf(original: Array[AnyRef], newLength: Int): Array[AnyRef] = { checkArrayLength(newLength) val copyLength = Math.min(newLength, original.length) val ret = java.lang.reflect.Array.newInstance( original.getClass.getComponentType, newLength).asInstanceOf[Array[AnyRef]] System.arraycopy(original, 0, ret, 0, copyLength) ret } def copyOfRange(original: Array[AnyRef], start: Int, end: Int): Array[AnyRef] = { checkIndicesForCopyOfRange(original.length, start, end) val retLength = end - start val copyLength = Math.min(retLength, original.length - start) val ret = java.lang.reflect.Array.newInstance( original.getClass.getComponentType, retLength).asInstanceOf[Array[AnyRef]] System.arraycopy(original, start, ret, 0, copyLength) ret } @inline private def checkArrayLength(len: Int): Unit = { if (len < 0) throw new NegativeArraySizeException } @inline private def checkIndicesForCopyOfRange( len: Int, start: Int, end: Int): Unit = { if (start > end) throw new IllegalArgumentException(start + " > " + end) if (start < 0 || start > len) throw new ArrayIndexOutOfBoundsException } def hashCode(a: Array[Boolean]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Boolean(x).hashCode) } def hashCode(a: Array[Char]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Character(x).hashCode) } def hashCode(a: Array[Byte]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Byte(x).hashCode) } def hashCode(a: Array[Short]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Short(x).hashCode) } def hashCode(a: Array[Int]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Integer(x).hashCode) } def hashCode(a: Array[Long]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Long(x).hashCode) } def hashCode(a: Array[Float]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Float(x).hashCode) } def hashCode(a: Array[Double]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + new java.lang.Double(x).hashCode) } def hashCode(a: Array[AnyRef]): Int = { if (a == null) 0 else a.foldLeft(1)((acc, x) => 31*acc + (if (x == null) 0 else x.hashCode)) } def equals(a: Array[Boolean], b: Array[Boolean]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Char], b: Array[Char]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Byte], b: Array[Byte]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Short], b: Array[Short]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Int], b: Array[Int]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Long], b: Array[Long]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Float], b: Array[Float]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[Double], b: Array[Double]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) def equals(a: Array[AnyRef], b: Array[AnyRef]): Boolean = (a eq b) || (a != null && b != null && a.length == b.length && (0 until a.size).forall(i => a(i) == b(i))) }