All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opalj.collection.immutable.Long2List.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package collection
package immutable

import java.lang.{Long ⇒ JLong}

/**
 * A growable, immutable linked list based data store for '''long values'''.
 * Though this data store is backed by a linked list, it is not a classical linked list and it
 * does not offer (efficient) head and tail operations. However, compared to a classical linked
 * list the memory usage is reduced significantly and a simple foreach is also faster.
 *
 * This list does not perform any length related checks. I.e., it fails,e.g., in
 * case of `forFirstN` if the size of the list is smaller than expected.
 *
 * Furthermore, all directly implemented methods use `while` loops for maximum
 *
 * @author Michael Eichberg
 */
sealed abstract class Long2List extends Serializable { self ⇒

    def isEmpty: Boolean
    def isSingletonList: Boolean
    def nonEmpty: Boolean

    def head: Long
    def foreach[U](f: Long ⇒ U): Unit
    def forall(p: Long ⇒ Boolean): Boolean
    def foldLeft[B](z: B)(op: (B, Long) ⇒ B): B
    /** Iterates over the first N values. */
    def forFirstN[U](n: Int)(f: Long ⇒ U): Unit

    /**
     * @return An iterator over this list's values. In general, you should prefer using foreach or
     *         the other specialized methods to avoid the overhead incurred by the generation of
     *         the iterator.
     */
    def iterator: LongIterator

    /** Prepends the given value to this list. E.g., `l = 2L +: l`. */
    def +:(v: Long): Long2List

    override def equals(other: Any): Boolean
    override def hashCode(): Int // just added to ensure that we have to override hashCode!

    final override def toString = iterator.mkString("Long2List(", ", ", ")")
}

object Long2List {

    def empty: Long2List = Long2List0

    def apply(v: Long): Long2List = new Long2List1(v, null)

    def apply(v1: Long, v2: Long): Long2List = new Long2List2(v1, v2, null)

    def apply(v1: Long, v2: Long, v3: Long): Long2List = new Long2List3(v1, v2, v3, null)

    def apply(v1: Long, v2: Long, v3: Long, v4: Long): Long2List = {
        new Long2List4(v1, v2, v3, v4, null)
    }

}

/**
 * An empty [[Long2List]].
 *
 * @author Michael Eichberg
 */
case object Long2List0 extends Long2List {

    override def isEmpty: Boolean = true
    override def isSingletonList: Boolean = false
    override def nonEmpty: Boolean = false

    override def head: Long = throw new UnsupportedOperationException
    override def foreach[U](f: Long ⇒ U): Unit = {}
    override def forall(p: Long ⇒ Boolean): Boolean = true
    override def foldLeft[B](z: B)(op: (B, Long) ⇒ B): B = z
    /** Iterates over the first N values. */
    override def forFirstN[U](n: Int)(f: Long ⇒ U): Unit = {}
    override def iterator: LongIterator = LongIterator.empty
    /** Prepends the given value to this list. E.g., `l = 2l +: l`. */
    override def +:(v: Long): Long2List = new Long2List1(v, null)

    override def equals(other: Any): Boolean = {
        other match { case that: AnyRef ⇒ this eq that; case _ ⇒ false }
    }
    override def hashCode(): Int = 37
}

private[immutable] abstract class Long2List1_4 extends Long2List {

    final override def isEmpty: Boolean = false
    final override def nonEmpty: Boolean = true

    private[immutable] def rest: Long2List4

    final def restForeach[U](f: Long ⇒ U): Unit = {
        var list: Long2List4 = this.rest
        while (list != null) {
            f(list.v1)
            f(list.v2)
            f(list.v3)
            f(list.v4)
            list = list.rest
        }
    }

    final def restFoldLeft[B](z: B)(op: (B, Long) ⇒ B): B = {
        var r = z
        var list: Long2List4 = this.rest
        while (list != null) {
            r = op(op(op(op(r, list.v1), list.v2), list.v3), list.v4)
            list = list.rest
        }
        r
    }

    final def restForall(p: Long ⇒ Boolean): Boolean = {
        var list: Long2List4 = this.rest
        while (list != null) {
            if (!(p(list.v1) && p(list.v2) && p(list.v3) && p(list.v4)))
                return false;
            list = list.rest
        }
        true
    }

    final def restForFirstN[U](n: Int)(f: Long ⇒ U): Unit = {
        var i = n
        var list: Long2List4 = rest
        while (i > 0) {
            i match {
                case 1 ⇒
                    f(list.v1); i = 0
                case 2 ⇒
                    f(list.v1); f(list.v2); i = 0
                case 3 ⇒
                    f(list.v1); f(list.v2); f(list.v3); i = 0
                case _ ⇒
                    f(list.v1); f(list.v2); f(list.v3); f(list.v4)
                    i -= 4
                    if (i > 0) {
                        list = list.rest
                    }
            }
        }
    }

    final def restIterator(): LongIterator = {
        new LongIterator {
            private[this] var list: Long2List4 = rest
            private[this] var index: Int = 0
            def hasNext: Boolean = list != null
            def next: Long = {
                index match {
                    case 0 ⇒ { index += 1; list.v1 }
                    case 1 ⇒ { index += 1; list.v2 }
                    case 2 ⇒ { index += 1; list.v3 }
                    case 3 ⇒ { index = 0; val v = list.v4; list = list.rest; v }
                }
            }
        }
    }

    // ... this node is also a Long2List4 node
    final def restEquals(otherRest: Long2List4): Boolean = {
        var thisRest = this.rest
        var thatRest = otherRest
        while (thisRest != null && thatRest != null) {
            val equal = thisRest.v1 == thatRest.v1 &&
                thisRest.v2 == thatRest.v2 &&
                thisRest.v3 == thatRest.v3 &&
                thisRest.v4 == thatRest.v4
            if (!equal)
                return false;
            thisRest = thisRest.rest
            thatRest = thatRest.rest
        }
        thatRest == null && thisRest == null
    }

    final def restHashCode(): Int = {
        var h = 31
        var list: Long2List4 = rest
        while (list != null) {
            h += JLong.hashCode(list.v1) * 31
            h += JLong.hashCode(list.v2) * 31
            h += JLong.hashCode(list.v3) * 31
            h += JLong.hashCode(list.v4) * 31
            list = list.rest
        }
        h
    }
}

private[immutable] final class Long2List1(
        private[immutable] val v1:   Long,
        private[immutable] val rest: Long2List4
) extends Long2List1_4 { list ⇒

    override def isSingletonList: Boolean = rest == null

    override def head: Long = v1

    override def foreach[U](f: Long ⇒ U): Unit = {
        f(v1);
        restForeach(f)
    }

    override def foldLeft[B](z: B)(op: (B, Long) ⇒ B): B = {
        restFoldLeft(op(z, v1))(op)
    }

    override def forall(p: Long ⇒ Boolean): Boolean = {
        p(v1) && restForall(p)
    }

    override def forFirstN[U](n: Int)(f: Long ⇒ U): Unit = {
        if (n > 0) {
            f(v1)
            restForFirstN(n - 1)(f)
        }
    }

    override def iterator: LongIterator = {
        var it = LongIterator(v1)
        if (rest != null) it ++= restIterator
        it
    }

    override def +:(v: Long): Long2List = new Long2List2(v, v1, rest)

    override def equals(other: Any): Boolean = {
        other match {
            case that: Long2List1 ⇒
                (that eq this) || (
                    that.v1 == this.v1 && restEquals(that.rest)
                )
            case _ ⇒ false
        }
    }

    override def hashCode(): Int = JLong.hashCode(v1) * 31 + restHashCode()

}

private[immutable] final class Long2List2(
        private[immutable] var v1:   Long,
        private[immutable] var v2:   Long,
        private[immutable] var rest: Long2List4
) extends Long2List1_4 { list ⇒

    override def isSingletonList: Boolean = false

    override def head: Long = v1

    override def foreach[U](f: Long ⇒ U): Unit = { f(v1); f(v2); restForeach(f) }

    override def foldLeft[B](z: B)(op: (B, Long) ⇒ B): B = restFoldLeft(op(op(z, v1), v2))(op)

    override def forall(p: Long ⇒ Boolean): Boolean = p(v1) && p(v2) && restForall(p)

    override def forFirstN[U](n: Int)(f: Long ⇒ U): Unit = {
        if (n > 0) {
            f(v1)
            if (n > 1) {
                f(v2)
                if (n > 2) {
                    restForFirstN(n - 2)(f)
                }
            }
        }
    }

    override def iterator: LongIterator = {
        var it = LongIterator(v1, v2)
        if (rest != null) it ++= restIterator
        it
    }

    override def +:(v: Long): Long2List = new Long2List3(v, v1, v2, rest)

    override def equals(other: Any): Boolean = {
        other match {
            case that: Long2List2 ⇒
                (that eq this) || (
                    that.v1 == this.v1 && that.v2 == this.v2 && restEquals(that.rest)
                )
            case _ ⇒ false
        }
    }

    override def hashCode(): Int = JLong.hashCode(v1) * 31 + JLong.hashCode(v2) * 31 + restHashCode()
}

private[immutable] final class Long2List3(
        private[immutable] var v1:   Long,
        private[immutable] var v2:   Long,
        private[immutable] var v3:   Long,
        private[immutable] var rest: Long2List4
) extends Long2List1_4 { list ⇒

    override def isSingletonList: Boolean = false

    override def head: Long = v1

    override def foreach[U](f: Long ⇒ U): Unit = { f(v1); f(v2); f(v3); restForeach(f) }

    override def foldLeft[B](z: B)(op: (B, Long) ⇒ B): B = {
        restFoldLeft(op(op(op(z, v1), v2), v3))(op)
    }

    override def forall(p: Long ⇒ Boolean): Boolean = p(v1) && p(v2) && p(v3) && restForall(p)

    override def forFirstN[U](n: Int)(f: Long ⇒ U): Unit = {
        if (n > 0) {
            f(v1)
            if (n > 1) {
                f(v2)
                if (n > 2) {
                    f(v3)
                    if (n > 3) {
                        restForFirstN(n - 3)(f)

                    }
                }
            }
        }
    }

    override def iterator: LongIterator = {
        var it = LongIterator(v1, v2, v3)
        if (rest != null) it ++= restIterator
        it
    }

    override def +:(v: Long): Long2List = new Long2List4(v, v1, v2, v3, rest)

    override def equals(other: Any): Boolean = {
        other match {
            case that: Long2List3 ⇒
                (that eq this) || (
                    that.v1 == v1 && that.v2 == v2 && that.v3 == v3 && restEquals(that.rest)
                )
            case _ ⇒ false
        }
    }

    override def hashCode(): Int = {
        JLong.hashCode(v1) * 31 + JLong.hashCode(v2) * 31 + JLong.hashCode(v3) * 31 + restHashCode()
    }
}

private[immutable] final class Long2List4(
        private[immutable] var v1:   Long,
        private[immutable] var v2:   Long,
        private[immutable] var v3:   Long,
        private[immutable] var v4:   Long,
        private[immutable] var rest: Long2List4
) extends Long2List1_4 { list ⇒

    override def isSingletonList: Boolean = false

    override def head: Long = v1

    override def foreach[U](f: Long ⇒ U): Unit = {
        f(v1); f(v2); f(v3); f(v4); restForeach(f)
    }

    override def foldLeft[B](z: B)(op: (B, Long) ⇒ B): B = {
        restFoldLeft(op(op(op(op(z, v1), v2), v3), v4))(op)
    }

    override def forall(p: Long ⇒ Boolean): Boolean = {
        p(v1) && p(v2) && p(v3) && p(v4) && restForall(p)
    }

    override def forFirstN[U](n: Int)(f: Long ⇒ U): Unit = {
        if (n > 0) {
            f(v1)
            if (n > 1) {
                f(v2)
                if (n > 2) {
                    f(v3)
                    if (n > 3) {
                        f(v4)
                        if (n > 4) {
                            restForFirstN(n - 4)(f)
                        }
                    }
                }
            }
        }
    }

    override def iterator: LongIterator = {
        var it = LongIterator(v1, v2, v3, v4)
        if (rest != null) it ++= restIterator
        it
    }

    override def +:(v: Long): Long2List = new Long2List1(v, this)

    override def equals(other: Any): Boolean = {
        other match {
            case that: Long2List4 ⇒
                (that eq this) || (
                    that.v1 == v1 && that.v2 == v2 && that.v3 == v3 && that.v4 == v4 &&
                    restEquals(that.rest)
                )
            case _ ⇒ false
        }
    }

    override def hashCode(): Int = {
        JLong.hashCode(v1) * 31 +
            JLong.hashCode(v2) * 31 +
            JLong.hashCode(v3) * 31 +
            JLong.hashCode(v4) * 31 +
            restHashCode()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy