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

org.scalameter.Gen.scala Maven / Gradle / Ivy

The newest version!
package org.scalameter



import collection._
import org.scalameter.picklers.Pickler
import org.scalameter.picklers.Implicits._



/** Base class for ScalaMeter generators.
 *
 *  Generators create warmup and benchmark datasets for running benchmarks.
 *  They support neat combinator-style syntax for composing more complex
 *  generators out of simpler ones.
 */
abstract class Gen[T] extends Serializable {
  self =>

  def map[S](f: T => S): Gen[S] = new Gen[S] {
    def warmupset = for (x <- self.warmupset) yield f(x)
    def dataset = for (params <- self.dataset) yield params
    def generate(params: Parameters) = f(self.generate(params))
    def cardinality: Int = self.cardinality
  }

  def flatMap[S](f: T => Gen[S]): Gen[S] = new Gen[S] {
    def warmupset = for {
      x <- self.warmupset
      y <- f(x).warmupset
    } yield y
    def dataset = for {
      selfparams <- self.dataset
      x = self.generate(selfparams)
      thatparams <- f(x).dataset
    } yield selfparams ++ thatparams
    def generate(params: Parameters) = {
      val x = self.generate(params)
      val mapped = f(x)
      mapped.generate(params)
    }
    def cardinality: Int = {
      val c1 = self.cardinality
      val c2 = f(self.generate(self.dataset.next())).cardinality
      c1 * c2
    }
  }

  def cross[S](that: Gen[S]): Gen[(T, S)] = for {
    x <- self
    y <- that
  } yield (x, y)

  def rename(mapping: (String, String)*): Gen[T] = new Gen[T] {
    val reverseMapping = mapping.map(kv => (kv._2, kv._1))
    def warmupset = self.warmupset
    def dataset = self.dataset.map(params => params map {
      case (k, v) => (mapping.toMap.applyOrElse(k, (k: String) => k), v)
    })
    def generate(params: Parameters) = self.generate(params map {
      case (k, v) => (reverseMapping.toMap.applyOrElse(k, (k: String) => k), v)
    })

    override def cardinality: Int = self.cardinality
  }

  def warmupset: Iterator[T]

  def dataset: Iterator[Parameters]

  def generate(params: Parameters): T

  def cardinality: Int

  def cached: Gen[T] = new Gen[T] {
    @transient lazy val cachedWarmupset = self.warmupset.toSeq
    @transient lazy val cachedDataset = self.dataset.map(p => (p, self.generate(p))).toMap

    def axes = cachedDataset.head._1.axisData.keys.toSet
    def warmupset = cachedWarmupset.iterator
    def dataset = self.dataset
    def generate(params: Parameters) = {
      val desiredParams = Parameters(params.axisData.filterKeys(k => axes.contains(k)).toSeq: _*)
      cachedDataset(desiredParams)
    }
    def cardinality: Int = Gen.this.cardinality
  }

}


object Gen {

  def unit(axisName: String): Gen[Unit] = new Gen[Unit] {
    def warmupset = Iterator.single(())
    def dataset = Iterator.single(Parameters((Parameter[Unit](axisName), ())))
    def generate(params: Parameters) = params[Unit](axisName)
    def cardinality: Int = 1
  }

  def single[T: Pickler](axisName: String)(v: T): Gen[T] = enumeration(axisName)(v)

  def range(axisName: String)(from: Int, upto: Int, hop: Int): Gen[Int] = new Gen[Int] {
    def warmupset = Iterator.single(upto)
    def dataset = (from to upto by hop).iterator.map(x => Parameters(Parameter[Int](axisName) -> x))
    def generate(params: Parameters) = params[Int](axisName)
    def cardinality: Int = math.max(1, (upto - from) / hop)
  }

  def enumeration[T: Pickler](axisName: String)(xs: T*): Gen[T] = new Gen[T] {
    def warmupset = Iterator.single(xs.last)
    def dataset = xs.iterator.map(x => Parameters(Parameter[T](axisName) -> x))
    def generate(params: Parameters) = params[T](axisName)
    def cardinality: Int = xs.size
  }

  def exponential(axisName: String)(from: Int, until: Int, factor: Int): Gen[Int] = new Gen[Int] {
    def warmupset = Iterator.single((until - from) / 2)
    def dataset = Iterator.iterate(from)(_ * factor).takeWhile(_ <= until).map(x => Parameters(Parameter[Int](axisName) -> x))
    def generate(params: Parameters) = params[Int](axisName)
    def cardinality: Int = math.max(1, math.log(until / from) / math.log(factor)).toInt
  }

  /* combinators */

  def crossProduct[P, Q](p: Gen[P], q: Gen[Q]): Gen[(P, Q)] = {
    for {
      pv <- p
      qv <- q
    } yield (pv, qv)
  }

  def crossProduct[P, Q, R](p: Gen[P], q: Gen[Q], r: Gen[R]): Gen[(P, Q, R)] = {
    for {
      pv <- p
      qv <- q
      rv <- r
    } yield (pv, qv, rv)
  }

  def crossProduct[P, Q, R, S](
    p: Gen[P], q: Gen[Q], r: Gen[R], s: Gen[S]
  ): Gen[(P, Q, R, S)] = {
    for {
      pv <- p
      qv <- q
      rv <- r
      sv <- s
    } yield (pv, qv, rv, sv)
  }

  /** Provides most collection generators given that a size generator is defined.
   */
  trait Collections {

    def sizes: Gen[Int]

    /* sequences */

    def lists = for {
      size <- sizes
    } yield (0 until size).toList
  
    def arrays = for {
      size <- sizes
    } yield (0 until size).toArray
  
    def vectors = for {
      size <- sizes
    } yield (0 until size).toVector
   
    def arraybuffers = for {
      size <- sizes
    } yield mutable.ArrayBuffer(0 until size: _*)
  
    def ranges = for {
      size <- sizes
    } yield 0 until size
  
    /* maps */
  
    def hashtablemaps = for {
      size <- sizes
    } yield {
      val hm = mutable.HashMap[Int, Int]()
      for (x <- 0 until size) hm(x) = x
      hm
    }
   
  
    def linkedhashtablemaps = for {
      size <- sizes
    } yield {
      val hm = mutable.LinkedHashMap[Int, Int]()
      for (x <- 0 until size) hm(x) = x
      hm
    }
    
    def hashtriemaps = for {
      size <- sizes
    } yield {
      var hm = immutable.HashMap[Int, Int]()
      for (x <- 0 until size) hm += ((x, x))
      hm
    }
  
    def redblackmaps = for {
      size <- sizes
    } yield {
      var am = immutable.TreeMap[Int, Int]()
      for (x <- 0 until size) am += ((x, x))
      am
    }
  
    /* sets */
  
    def hashtablesets = for {
      size <- sizes
    } yield {
      val hs = mutable.HashSet[Int]()
      for (x <- 0 until size) hs.add(x)
      hs
    }
    
    def linkedhashtablesets = for {
      size <- sizes
    } yield {
      val hs = mutable.LinkedHashSet[Int]()
      for (x <- 0 until size) hs.add(x)
      hs
    }
    
    def avlsets = for {
      size <- sizes
    } yield {
      val as = mutable.TreeSet[Int]()
      for (x <- 0 until size) as.add(x)
      as
    }
  
    def redblacksets = for {
      size <- sizes
    } yield {
      var as = immutable.TreeSet[Int]()
      for (x <- 0 until size) as += x
      as
    }
  
    def hashtriesets = for {
      size <- sizes
    } yield {
      var hs = immutable.HashSet[Int]()
      for (x <- 0 until size) hs += x
      hs
    }

  }

}



















© 2015 - 2025 Weber Informatics LLC | Privacy Policy