<commit_before>package com.rklaehn.abc

import spire.math.{BinaryMerge2, BinaryMerge}
import spire.util.Opt

import scala.collection.generic.{GenericCompanion, CanBuildFrom}
import scala.collection.mutable.ArrayBuffer
import scala.collection.{mutable, SortedMapLike}
import scala.collection.immutable.SortedMap
import scala.util.hashing.MurmurHash3
import scala.{ specialized => sp }
import spire.algebra.Order

final class ArrayMap[@sp(Int, Long, Double) K, @sp(Int, Long, Double) V](
  private[abc] val keys0: Array[K],
  private[abc] val values0: Array[V]) { self ⇒
  import ArrayMap._

  def iterator = keys0.iterator zip values0.iterator

  def size: Int = keys0.length

  def lastKey: K = keys0.last

  def firstKey: K = keys0.head

  def keys: ArraySet[K] = new ArraySet[K](keys0)

  def values: ArraySeq[V] = new ArraySeq[V](values0)

  def apply(k: K)(implicit kArrayTag: OrderedArrayTag[K]): V = {
    val i = kArrayTag.binarySearch(keys0, 0, keys0.length, k)
    if (i >= 0) values0(i)
    else throw new NoSuchElementException
  }

  def get(k: K)(implicit kArrayTag: OrderedArrayTag[K]): Option[V] = {
    val i = kArrayTag.binarySearch(keys0, 0, keys0.length, k)
    if (i < 0) None else Some(values0(i))
  }

  def merge(that: ArrayMap[K, V])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new MapMerger[K, V](this, that).result

  def mergeWith(that: ArrayMap[K, V], f: (V, V) => V)(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new MapMerger2[K, V](this, that, f).result

  def except(that: ArrayMap[K, V], f: (V, V) ⇒ Opt[V])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new Except[K, V](this, that, f).result

  def filterKeys(f: K ⇒ Boolean)(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] = {
    val rk = kArrayTag.newArray(keys0.length)
    val rv = vArrayTag.newArray(values0.length)
    var ri = 0
    var i = 0
    while(i < keys0.length) {
      if (f(keys0(i))) {
        rk(ri) = keys0(i)
        rv(ri) = values0(i)
        ri += 1
      }
      i += 1
    }
    new ArrayMap[K, V](kArrayTag.resizeInPlace(rk, ri), vArrayTag.resizeInPlace(rv, ri))
  }

  def filter(f: ((K, V)) ⇒ Boolean)(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] = {
    val rk = kArrayTag.newArray(keys0.length)
    val rv = vArrayTag.newArray(values0.length)
    var ri = 0
    var i = 0
    while(i < keys0.length) {
      if (f((keys0(i), values0(i)))) {
        rk(ri) = keys0(i)
        rv(ri) = values0(i)
        ri += 1
      }
      i += 1
    }
    new ArrayMap[K, V](kArrayTag.resizeInPlace(rk, ri), vArrayTag.resizeInPlace(rv, ri))
  }

  def justKeys(keys: ArraySet[K])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new JustKeys[K, V](this, keys).result

  def exceptKeys(keys: ArraySet[K])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new ExceptKeys[K, V](this, keys).result

  def mapValues[@sp(Int, Long, Double) V2: ArrayTag](f: V => V2): ArrayMap[K, V2] = {
    new ArrayMap(keys0, values0.map(f).toArray(ArrayTag[V2].classTag))
  }

  override def toString: String =
    keys0.indices.map(i => s"${keys0(i)}->${values0(i)}").mkString("Map(", ",", ")")
}

object ArrayMap {

  implicit def cbf[CC, @sp(Int, Long, Double) K: OrderedArrayTag, @sp(Int, Long, Double) V: ArrayTag]: CanBuildFrom[CC, (K, V), ArrayMap[K, V]] = new CanBuildFrom[CC, (K, V), ArrayMap[K, V]] {
    def apply(from: CC) = apply()

    def apply() = new ArrayBuffer[(K, V)].mapResult(x ⇒ ArrayMap(x: _*))
  }

  private[this] class ArrayMapBuilder[@sp(Int, Long, Double) K: OrderedArrayTag, @sp(Int, Long, Double) V: ArrayTag] extends scala.collection.mutable.Builder[(K, V), ArrayMap[K, V]] {

    private[this] var reducer = Reducer.create[ArrayMap[K, V]](_ merge _)

    def +=(elem: (K, V)) = {
      reducer.apply(singleton(elem._1, elem._2))
      this<commit_msg>Attempt to wrap ArrayMap as a scala colleciton<commit_after>package com.rklaehn.abc

import spire.math.{BinaryMerge2, BinaryMerge}
import spire.util.Opt

import scala.collection.generic.{GenericCompanion, CanBuildFrom}
import scala.collection.mutable.ArrayBuffer
import scala.collection.{mutable, SortedMapLike}
import scala.collection.immutable.SortedMap
import scala.util.hashing.MurmurHash3
import scala.{ specialized => sp }
import spire.algebra.Order

final class ArrayMap[@sp(Int, Long, Double) K, @sp(Int, Long, Double) V](
  private[abc] val keys0: Array[K],
  private[abc] val values0: Array[V]) { self ⇒
  import ArrayMap._

  def iterator = keys0.iterator zip values0.iterator

  def size: Int = keys0.length

  def lastKey: K = keys0.last

  def firstKey: K = keys0.head

  def keys: ArraySet[K] = new ArraySet[K](keys0)

  def values: ArraySeq[V] = new ArraySeq[V](values0)

  def apply(k: K)(implicit kArrayTag: OrderedArrayTag[K]): V = {
    val i = kArrayTag.binarySearch(keys0, 0, keys0.length, k)
    if (i >= 0) values0(i)
    else throw new NoSuchElementException
  }

  def get(k: K)(implicit kArrayTag: OrderedArrayTag[K]): Option[V] = {
    val i = kArrayTag.binarySearch(keys0, 0, keys0.length, k)
    if (i < 0) None else Some(values0(i))
  }

  def merge(that: ArrayMap[K, V])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new MapMerger[K, V](this, that).result

  def mergeWith(that: ArrayMap[K, V], f: (V, V) => V)(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new MapMerger2[K, V](this, that, f).result

  def except(that: ArrayMap[K, V], f: (V, V) ⇒ Opt[V])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new Except[K, V](this, that, f).result

  def filterKeys(f: K ⇒ Boolean)(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] = {
    val rk = kArrayTag.newArray(keys0.length)
    val rv = vArrayTag.newArray(values0.length)
    var ri = 0
    var i = 0
    while(i < keys0.length) {
      if (f(keys0(i))) {
        rk(ri) = keys0(i)
        rv(ri) = values0(i)
        ri += 1
      }
      i += 1
    }
    new ArrayMap[K, V](kArrayTag.resizeInPlace(rk, ri), vArrayTag.resizeInPlace(rv, ri))
  }

  def filter(f: ((K, V)) ⇒ Boolean)(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] = {
    val rk = kArrayTag.newArray(keys0.length)
    val rv = vArrayTag.newArray(values0.length)
    var ri = 0
    var i = 0
    while(i < keys0.length) {
      if (f((keys0(i), values0(i)))) {
        rk(ri) = keys0(i)
        rv(ri) = values0(i)
        ri += 1
      }
      i += 1
    }
    new ArrayMap[K, V](kArrayTag.resizeInPlace(rk, ri), vArrayTag.resizeInPlace(rv, ri))
  }

  def justKeys(keys: ArraySet[K])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new JustKeys[K, V](this, keys).result

  def exceptKeys(keys: ArraySet[K])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): ArrayMap[K, V] =
    new ExceptKeys[K, V](this, keys).result

  def mapValues[@sp(Int, Long, Double) V2: ArrayTag](f: V => V2): ArrayMap[K, V2] = {
    new ArrayMap(keys0, values0.map(f).toArray(ArrayTag[V2].classTag))
  }

  override def toString: String =
    keys0.indices.map(i => s"${keys0(i)}->${values0(i)}").mkString("Map(", ",", ")")
}

object ArrayMap {

  class AsCollection[K, V](underlying: ArrayMap[K, V])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]) extends SortedMap[K, V] with SortedMapLike[K, V, AsCollection[K, V]] {
    import AsCollection._

    implicit def ordering = Order.ordering(kArrayTag.order)

    override def newBuilder : mutable.Builder[(K, V), AsCollection[K, V]] =
      new ArrayMapBuilder[K, V].mapResult(x ⇒ wrap(x))

    override def empty = wrap(ArrayMap.empty[K, V])

    def valuesIteratorFrom(start: K) = ???

    def rangeImpl(from: Option[K], until: Option[K]) = ???

    def iteratorFrom(start: K) = ???

    def get(key: K) = underlying.get(key)

    def iterator = underlying.iterator

    override def +[V1 >: V](kv: (K, V1)) = {
      val u = underlying.asInstanceOf[ArrayMap[K, V1]]
      implicit val v1ArrayTag = vArrayTag.asInstanceOf[ArrayTag[V1]]
      wrap(u.merge(ArrayMap.singleton(kv._1, kv._2)))
    }

    def -(key: K) = wrap(underlying.exceptKeys(ArraySet.singleton(key)))

    def keysIteratorFrom(start: K) = ???
  }

  object AsCollection {

    implicit def cbf[CC, @sp(Int, Long, Double) K: OrderedArrayTag, @sp(Int, Long, Double) V: ArrayTag]: CanBuildFrom[CC, (K, V), ArrayMap[K, V]] = new CanBuildFrom[CC, (K, V), ArrayMap[K, V]] {
      def apply(from: CC) = apply()

      def apply() = new ArrayBuffer[(K, V)].mapResult(x ⇒ ArrayMap(x: _*))
    }

    def wrap[K, V](underlying: ArrayMap[K, V])(implicit kArrayTag: OrderedArrayTag[K], vArrayTag: ArrayTag[V]): AsCollection[K, V] =
      new AsCollection[K, V](underlying)
  }

  private[this] class ArrayMapBuilder[@sp(Int, Long, Double) K: OrderedArrayTag, @sp(Int, Long, Double) V: ArrayTag] extends scala.collection.mutable.Builder[(K, V), ArrayMap[K, V]] {

    private[this] var reducer = Reducer.create[ArrayMap[K, V]](_ merge _)

    def +=(elem: (K, V)) = {
      reducer.apply(singleton(elem._1, elem._2))
      this
{'fraction_non_alphanumeric': 0.1592977197302216, 'fraction_numerical': 0.012311315704956643, 'mean_word_length': 3.9957219251336897, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6265387', 'n_tokens_mistral': 3597, 'n_tokens_neox': 3499, 'n_words': 825}