From 34ff7f432c6338200c9755815ee7463a62348ecd Mon Sep 17 00:00:00 2001 From: Piotr Tarsa Date: Sun, 17 Dec 2017 22:29:34 +0100 Subject: [PATCH] Separated operations and buffers from items agents. Added specialization on Scala side. This change allows to have multiple different buffers used by a sorting algorithm without the need to implement a specialized items agent for it. Items buffers are grouped in flexible sort specific setups. --- BACKLOG.md | 6 +- .../main/BenchmarksConfigurations.scala | 8 +- .../MeasuringIntSortAlgorithmWrapper.scala | 20 +- build.sbt | 2 +- .../pl/tarsa/sortalgobox/license_header | 3 +- .../common/crossverify/TrackingEnums.scala | 7 +- .../tests/CommonUnitSpecBase.scala | 26 +- .../core/common/ComparisonSortAlgorithm.scala | 29 -- .../core/common/GenericSortAlgorithm.scala | 21 +- .../core/common/ItemsAgentSortAlgorithm.scala | 62 +++ ....scala => SelfMeasuredSortAlgorithm.scala} | 2 +- ...rtAlgorithm.scala => Specialization.scala} | 12 +- .../common/agents/MergeSortItemsAgent.scala | 71 --- .../common/agents/RadixSortItemsAgent.scala | 66 --- .../common/agents/SlicingItemsAgent.scala | 31 -- .../ComparingIntArrayItemsAgent.scala | 47 -- .../MergeSortIntArrayItemsAgent.scala | 70 --- .../RadixSortIntArrayItemsAgent.scala | 73 --- ...RecordingComparingIntArrayItemsAgent.scala | 81 ---- ...VerifyingComparingIntArrayItemsAgent.scala | 82 ---- .../core/common/items/agents/ItemsAgent.scala | 248 ++++++++++ .../common/items/agents/PlainItemsAgent.scala | 117 +++++ .../items/agents/RecordingItemsAgent.scala | 190 ++++++++ .../items/agents/VerifyingItemsAgent.scala | 204 ++++++++ .../items/buffers/ComparableItemsBuffer.scala | 114 +++++ .../buffers/ItemsBuffer.scala} | 16 +- .../items/buffers/NumericItemsBuffer.scala | 126 +++++ .../items/operations/ItemsOperations.scala | 141 ++++++ .../core/crossverify/PureNumberDecoder.scala | 40 +- .../core/crossverify/PureNumberEncoder.scala | 35 +- .../BaseDoubleIntArrayItemsAgentSpec.scala | 50 -- .../BaseSingleIntArrayItemsAgentSpec.scala | 46 -- .../ComparingIntArrayItemsAgentSpec.scala | 92 ---- .../MergeSortIntArrayItemsAgentSpec.scala | 200 -------- .../RadixSortIntArrayItemsAgentSpec.scala | 175 ------- ...rdingComparingIntArrayItemsAgentSpec.scala | 142 ------ ...fyingComparingIntArrayItemsAgentSpec.scala | 164 ------- .../items/agents/ItemsAgentSpecBase.scala | 440 ++++++++++++++++++ .../items/agents/PlainItemsAgentSpec.scala | 72 +++ .../agents/RecordingItemsAgentSpec.scala | 108 +++++ .../agents/VerifyingItemsAgentSpec.scala | 131 ++++++ .../buffers/ComparableItemsBufferSpec.scala | 100 ++++ .../buffers/NumericItemsBufferSpec.scala | 99 ++++ .../operations/ItemsOperationsSpec.scala | 126 +++++ .../crossverify/PureNumberDecoderSpec.scala | 112 +++-- .../crossverify/PureNumberEncoderSpec.scala | 100 ++-- .../crossverify/VerifyBubbleSortSpec.scala | 3 +- .../crossverify/VerifyInsertionSortSpec.scala | 3 +- ...ifySabHeapBinaryOneBasedVariantASpec.scala | 3 +- .../crossverify/VerifySelectionSortSpec.scala | 3 +- .../infrastructure/CrossVerifySpecBase.scala | 23 +- .../natives/agents/comparing_items_agent.hpp | 49 -- .../comparing_array_items_agent.hpp | 90 ---- .../recording_comparing_items_agent.hpp | 113 ----- .../natives/agents/items_agent.hpp | 286 +++++++++++- .../natives/crossverify/number_codec.hpp | 173 ++++--- .../tarsa/sortalgobox/natives/utilities.hpp | 4 +- .../agents/ItemsAgentsBuildComponents.scala | 52 ++- .../crossverify/NativeNumberCodecSpec.scala | 320 ++++++++----- project/Versions.scala | 4 +- project/build.properties | 2 +- .../sortalgobox/sorts/natives/bubble.hpp | 41 +- .../sorts/natives/common/items_handler.hpp | 148 ++---- .../sortalgobox/sorts/natives/common/main.cpp | 19 +- .../sortalgobox/sorts/natives/insertion.hpp | 45 +- .../sorts/natives/sab/agent/sabmain.hpp | 7 - .../natives/sab/agent/sortalgocommon.hpp | 3 - .../agent/sortheapbinaryonebasedvarianta.hpp | 47 +- .../sorts/natives/sab/classic/sabmain.hpp | 26 +- .../sortheapbinaryaheadsimplevarianta.hpp | 18 +- .../sortheapbinaryaheadsimplevariantb.hpp | 17 +- .../sab/classic/sortheapbinarycached.hpp | 26 +- .../sortheapbinarycascadingvarianta.hpp | 19 +- .../sortheapbinarycascadingvariantb.hpp | 19 +- .../sortheapbinaryclusteredvarianta.hpp | 20 +- .../sortheapbinaryclusteredvariantb.hpp | 20 +- .../sortheapbinaryonebasedvarianta.hpp | 19 +- .../sortheapbinaryonebasedvariantb.hpp | 19 +- .../sortheapsimddwordcascadingvariantb.hpp | 23 +- .../sortheapsimddwordcascadingvariantc.hpp | 23 +- .../sab/classic/sortheapsimddwordvariantb.hpp | 23 +- .../sab/classic/sortheapsimddwordvariantc.hpp | 23 +- .../sab/classic/sortquickrandomized.hpp | 43 +- .../sortalgobox/sorts/natives/selection.hpp | 47 +- .../sortalgobox/sorts/natives/std__sort.hpp | 32 +- .../sorts/natives/NativeItemsAgentSort.scala | 16 +- .../sorts/natives/NativeStdSort.scala | 16 +- .../natives/sab/agent/AgentSabBenchmark.scala | 17 +- .../sab/classic/ClassicSabBenchmark.scala | 23 +- .../classic/ClassicSabHeapBinaryCached.scala | 2 +- ...sicSabHeapSimdDwordCascadingVariantB.scala | 2 +- ...sicSabHeapSimdDwordCascadingVariantC.scala | 2 +- .../ClassicSabHeapSimdDwordVariantB.scala | 2 +- .../ClassicSabHeapSimdDwordVariantC.scala | 2 +- .../sorts/opencl/GpuBitonicSort.scala | 4 +- .../sorts/opencl/common/CpuSort.scala | 4 +- .../sorts/scala/ComparisonSortBase.scala | 30 +- .../sorts/scala/bitonic/BitonicSort.scala | 23 +- .../sorts/scala/bubble/BubbleSort.scala | 20 +- .../sorts/scala/heap/BinaryHeap.scala | 43 +- .../sorts/scala/heap/HeapSort.scala | 18 +- .../scala/heap/check/BinaryHeapChecker.scala | 10 +- .../sorts/scala/insertion/InsertionSort.scala | 20 +- .../sorts/scala/merge/MergeSort.scala | 65 ++- .../sorts/scala/quick/QuickSort.scala | 7 +- .../quick/QuickSortWithLimitedCallDepth.scala | 57 +-- .../scala/quick/SinglePivotPartition.scala | 39 +- .../sorts/scala/radix/RadixSort.scala | 56 ++- .../sab/SabHeapBinaryOneBasedVariantA.scala | 59 +-- .../sorts/scala/selection/SelectionSort.scala | 19 +- .../sorts/scala/shell/GapSequence.scala | 6 +- .../scala/shell/HibbardGapSequence.scala | 7 +- .../sorts/scala/shell/ShellSort.scala | 22 +- .../sorts/scala/shell/TokudaGapSequence.scala | 21 +- .../sorts/scala/bitonic/BitonicSortSpec.scala | 7 +- .../sorts/scala/bubble/BubbleSortSpec.scala | 7 +- .../sorts/scala/heap/BinaryHeapSpec.scala | 28 +- .../sorts/scala/heap/HeapSortSpec.scala | 7 +- .../heap/check/BinaryHeapCheckerSpec.scala | 22 +- .../scala/insertion/InsertionSortSpec.scala | 7 +- .../sorts/scala/merge/MergeSortSpec.scala | 7 +- .../quick/SinglePivotPartitionSpec.scala | 34 +- .../sorts/scala/radix/RadixSortSpec.scala | 5 +- .../SabHeapBinaryOneBasedVariantASpec.scala | 4 +- .../scala/selection/SelectionSortSpec.scala | 9 +- .../sortalgobox/sorts/tests/SortChecker.scala | 48 +- 126 files changed, 3942 insertions(+), 2817 deletions(-) delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/ComparisonSortAlgorithm.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/ItemsAgentSortAlgorithm.scala rename core/main_scala/pl/tarsa/sortalgobox/core/common/{MeasuredSortAlgorithm.scala => SelfMeasuredSortAlgorithm.scala} (95%) rename core/main_scala/pl/tarsa/sortalgobox/core/common/{PureSortAlgorithm.scala => Specialization.scala} (75%) delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/MergeSortItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/RadixSortItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/SlicingItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgent.scala delete mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgent.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgent.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgent.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgent.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgent.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBuffer.scala rename core/main_scala/pl/tarsa/sortalgobox/core/common/{agents/ComparingItemsAgent.scala => items/buffers/ItemsBuffer.scala} (72%) create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBuffer.scala create mode 100644 core/main_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperations.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseDoubleIntArrayItemsAgentSpec.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseSingleIntArrayItemsAgentSpec.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgentSpec.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgentSpec.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgentSpec.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgentSpec.scala delete mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgentSpec.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgentSpecBase.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgentSpec.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgentSpec.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgentSpec.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBufferSpec.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBufferSpec.scala create mode 100644 core/test_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperationsSpec.scala delete mode 100644 natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/comparing_items_agent.hpp delete mode 100644 natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/comparing_array_items_agent.hpp delete mode 100644 natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/recording_comparing_items_agent.hpp rename core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ItemsAgent.scala => sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/ComparisonSortBase.scala (56%) diff --git a/BACKLOG.md b/BACKLOG.md index 0eb9dd8..2a3b38f 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -1,14 +1,11 @@ Backlog: + * update README.md * convert native C++ sorts to use items agents * replace asserts with matchers in tests * add ActorRef wrappers with typed `tell` forwarders * remove native C++ items handlers when we are left with items agents only - * make witness classes for native C++ items agents instead of useless - inheritance of empty methods - * use specialization in Scala items agents * implement guards in generated native C++ headers (eg enums) - * decide on int8_t or uint8_t in native C++ number codecs and buffered I/O * implement missing unit tests * reorganize project structure to make more sense * improve web-based GUI @@ -18,3 +15,4 @@ Backlog: * add support for LLVM/ Clang (that could e.g. make tests run quicker) * change license to Apache 2.0 * use lenses from https://github.com/adamw/quicklens + * use ScalaCheck or ScalaProps for property-based testing diff --git a/boot/main_scala/pl/tarsa/sortalgobox/main/BenchmarksConfigurations.scala b/boot/main_scala/pl/tarsa/sortalgobox/main/BenchmarksConfigurations.scala index 8ab5b02..cd965a1 100644 --- a/boot/main_scala/pl/tarsa/sortalgobox/main/BenchmarksConfigurations.scala +++ b/boot/main_scala/pl/tarsa/sortalgobox/main/BenchmarksConfigurations.scala @@ -19,7 +19,7 @@ */ package pl.tarsa.sortalgobox.main -import pl.tarsa.sortalgobox.core.common.MeasuredSortAlgorithm +import pl.tarsa.sortalgobox.core.common.SelfMeasuredSortAlgorithm import pl.tarsa.sortalgobox.core.{Benchmark, NativeBenchmark} import pl.tarsa.sortalgobox.random.Mwc64x import pl.tarsa.sortalgobox.sorts.jre._ @@ -34,12 +34,12 @@ import scala.concurrent.duration.FiniteDuration object BenchmarksConfigurations { val plainSorts: List[(String, AnyRef)] = List( - "BitonicSort" -> new BitonicSort, + "BitonicSort" -> BitonicSort, "SequentialArraysSort" -> SequentialArraysSort.intSort, "ParallelArraySort" -> ParallelArraysSort.intSort ) - val measuredSorts: List[(String, MeasuredSortAlgorithm[Int])] = + val measuredSorts: List[(String, SelfMeasuredSortAlgorithm[Int])] = List( "CpuBitonicSort" -> CpuBitonicSort, "GpuBitonicSort" -> GpuBitonicSort, @@ -72,7 +72,7 @@ object BenchmarksConfigurations { val benchmarks: List[Benchmark] = { nativeBenchmarks ::: measuredSorts.map { - case (sortName: String, sort: MeasuredSortAlgorithm[Int]) => + case (sortName: String, sort: SelfMeasuredSortAlgorithm[Int]) => new Benchmark { override def forSize(itemsNumber: Int, validate: Boolean, diff --git a/boot/main_scala/pl/tarsa/sortalgobox/main/MeasuringIntSortAlgorithmWrapper.scala b/boot/main_scala/pl/tarsa/sortalgobox/main/MeasuringIntSortAlgorithmWrapper.scala index 19efb5d..1798e56 100644 --- a/boot/main_scala/pl/tarsa/sortalgobox/main/MeasuringIntSortAlgorithmWrapper.scala +++ b/boot/main_scala/pl/tarsa/sortalgobox/main/MeasuringIntSortAlgorithmWrapper.scala @@ -19,29 +19,33 @@ */ package pl.tarsa.sortalgobox.main -import pl.tarsa.sortalgobox.core.common.agents.implementations.ComparingIntArrayItemsAgent +import pl.tarsa.sortalgobox.core.common.items.agents.{ + ItemsAgent, + PlainItemsAgent +} import pl.tarsa.sortalgobox.core.common.{ - ComparisonSortAlgorithm, + ComparableItemsAgentSortAlgorithm, GenericIntSortAlgorithm, - MeasuredSortAlgorithm + SelfMeasuredSortAlgorithm } import scala.concurrent.duration.Duration object MeasuringIntSortAlgorithmWrapper { - def apply(plainSortAlgorithm: AnyRef): MeasuredSortAlgorithm[Int] = { + def apply(plainSortAlgorithm: AnyRef): SelfMeasuredSortAlgorithm[Int] = { plainSortAlgorithm match { case sortAlgorithm: GenericIntSortAlgorithm => wrap(sortAlgorithm) - case sortAlgorithm: ComparisonSortAlgorithm => + case sortAlgorithm: ComparableItemsAgentSortAlgorithm => wrap { intArray: Array[Int] => - val itemsAgent = new ComparingIntArrayItemsAgent(intArray) - sortAlgorithm.sort(itemsAgent) + val itemsAgent: ItemsAgent = PlainItemsAgent + val setup = sortAlgorithm.setupSort(intArray) + sortAlgorithm.sortExplicit(setup, itemsAgent) } } } - def wrap(doSorting: (Array[Int]) => Unit): MeasuredSortAlgorithm[Int] = { + def wrap(doSorting: Array[Int] => Unit): SelfMeasuredSortAlgorithm[Int] = { (array: Array[Int]) => val startTime = System.nanoTime() doSorting(array) diff --git a/build.sbt b/build.sbt index 91b683e..af99571 100644 --- a/build.sbt +++ b/build.sbt @@ -60,7 +60,7 @@ lazy val deps = "com.typesafe.akka" %% "akka-actor" % Versions.akka, "com.typesafe.akka" %% "akka-http" % Versions.akkaHttp, "com.jsuereth" %% "scala-arm" % "2.0", - "commons-io" % "commons-io" % "2.5", + "commons-io" % "commons-io" % "2.6", "org.apache.commons" % "commons-math3" % "3.6.1", "org.scalafx" %% "scalafx" % Versions.scalaFx, // test libraries diff --git a/common/main_rsrc/pl/tarsa/sortalgobox/license_header b/common/main_rsrc/pl/tarsa/sortalgobox/license_header index 3adc66d..77f1a69 100644 --- a/common/main_rsrc/pl/tarsa/sortalgobox/license_header +++ b/common/main_rsrc/pl/tarsa/sortalgobox/license_header @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,5 +16,4 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ diff --git a/common/main_scala/pl/tarsa/sortalgobox/common/crossverify/TrackingEnums.scala b/common/main_scala/pl/tarsa/sortalgobox/common/crossverify/TrackingEnums.scala index 2f3d36c..4a64ac1 100644 --- a/common/main_scala/pl/tarsa/sortalgobox/common/crossverify/TrackingEnums.scala +++ b/common/main_scala/pl/tarsa/sortalgobox/common/crossverify/TrackingEnums.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -21,7 +21,8 @@ package pl.tarsa.sortalgobox.common.crossverify object TrackingEnums { object ActionTypes extends Enumeration { - type ActionType = Value - val Size0, Get0, Set0, Copy0, Swap0, Compare, Compare0 = Value + type Action = Value + val Size, Get, Set, Swap, ItemBitsSize, AsLong, GetSlice, CompareEq, + CompareGt, CompareGte, CompareLt, CompareLte = Value } } diff --git a/common/test_scala/pl/tarsa/sortalgobox/tests/CommonUnitSpecBase.scala b/common/test_scala/pl/tarsa/sortalgobox/tests/CommonUnitSpecBase.scala index 60c2328..dc32ba9 100644 --- a/common/test_scala/pl/tarsa/sortalgobox/tests/CommonUnitSpecBase.scala +++ b/common/test_scala/pl/tarsa/sortalgobox/tests/CommonUnitSpecBase.scala @@ -21,7 +21,7 @@ package pl.tarsa.sortalgobox.tests import java.util.concurrent.{Executors, TimeUnit} -import org.scalatest.{FlatSpec, Inside, MustMatchers} +import org.scalatest.{AppendedClues, FlatSpec, Inside, Inspectors, MustMatchers} import scala.concurrent.duration.Duration import scala.concurrent.{ @@ -30,25 +30,33 @@ import scala.concurrent.{ ExecutionContextExecutorService, Future } -import scala.reflect.ClassTag +import scala.reflect.runtime.universe._ abstract class CommonUnitSpecBase extends FlatSpec with MustMatchers - with Inside { - - type TestException = LightException + with Inside + with Inspectors + with AppendedClues { System.setProperty("uniqueLibraryNames", "true") - val `have full code coverage` = "have full code coverage" - - def typeBehavior[T](implicit classTag: ClassTag[T]): Unit = - behavior of classTag.runtimeClass.getSimpleName + type TestException = LightException def testException: Exception = LightException(s"boom in $suiteName") + //noinspection UnitMethodIsParameterless + // TODO add parentheses + def typeBehavior[T: TypeTag]: Unit = + behavior of typeName[T] + + def typeName[T: TypeTag]: String = + typeOf[T].typeSymbol.toString + + val `have full code coverage` = "have full code coverage" + + // TODO remove and mix in Futures trait instead implicit class InstantFuture[T](future: Future[T]) { def readyNow(): Future[T] = Await.ready(future, Duration.Inf) diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/ComparisonSortAlgorithm.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/ComparisonSortAlgorithm.scala deleted file mode 100644 index cdcf763..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/ComparisonSortAlgorithm.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - */ -package pl.tarsa.sortalgobox.core.common - -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent - -abstract class ComparisonSortAlgorithm - extends PureSortAlgorithm[ComparingItemsAgent] { - - override def sort[ItemType](itemsAgent: ComparingItemsAgent[ItemType]): Unit -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/GenericSortAlgorithm.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/GenericSortAlgorithm.scala index 69a9ace..9a79d2f 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/GenericSortAlgorithm.scala +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/GenericSortAlgorithm.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,20 +16,21 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.core.common import scala.reflect.ClassTag -abstract class GenericSortAlgorithm[T: ClassTag](doSorting: (Array[T] => Unit)) - extends (Array[T] => Unit) { - - override def apply(array: Array[T]): Unit = doSorting(array) +sealed abstract class GenericSortAlgorithm[T: ClassTag]( + doSorting: Array[T] => Unit) + extends (Array[T] => Unit) { + + override def apply(array: Array[T]): Unit = + doSorting(array) } -case class GenericIntSortAlgorithm(doSorting: (Array[Int] => Unit)) - extends GenericSortAlgorithm[Int](doSorting) +case class GenericIntSortAlgorithm(doSorting: Array[Int] => Unit) + extends GenericSortAlgorithm[Int](doSorting) -case class GenericLongSortAlgorithm(doSorting: (Array[Long] => Unit)) - extends GenericSortAlgorithm[Long](doSorting) +case class GenericLongSortAlgorithm(doSorting: Array[Long] => Unit) + extends GenericSortAlgorithm[Long](doSorting) diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/ItemsAgentSortAlgorithm.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/ItemsAgentSortAlgorithm.scala new file mode 100644 index 0000000..5bb6f05 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/ItemsAgentSortAlgorithm.scala @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common + +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} +import pl.tarsa.sortalgobox.core.common.items.agents.ItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.NumericItemsBuffer.Evidence + +import scala.language.higherKinds +import scala.{specialized => spec} + +sealed abstract class ItemsAgentSortAlgorithm[Info[_]] { + protected type Agent[_] = ItemsAgent + + type Setup[@spec(Grp) _] + + def setupSort[@spec(Grp) Item: Info](items: Array[Item]): Setup[Item] + + final def sortExplicit[@spec(Grp) Item](sortSetup: Setup[Item], + itemsAgent: ItemsAgent): Unit = { + implicit val setup: Setup[Item] = sortSetup + implicit val agent: Agent[_] = itemsAgent + sort() + } + + protected def sort[@spec(Grp) Item: Setup, _: Agent](): Unit + + protected final def a(implicit itemsAgent: Agent[_]): ItemsAgent = + itemsAgent + + protected final def setup[@spec(Grp) Item: Setup]: Setup[Item] = + implicitly[Setup[Item]] + + sealed trait Permit[+Item] + + protected implicit def permit[Item]: Permit[Item] = thePermit + + private val thePermit = new Permit[Nothing] {} +} + +abstract class ComparableItemsAgentSortAlgorithm + extends ItemsAgentSortAlgorithm[Ordering] + +abstract class NumericItemsAgentSortAlgorithm + extends ItemsAgentSortAlgorithm[Evidence] diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/MeasuredSortAlgorithm.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/SelfMeasuredSortAlgorithm.scala similarity index 95% rename from core/main_scala/pl/tarsa/sortalgobox/core/common/MeasuredSortAlgorithm.scala rename to core/main_scala/pl/tarsa/sortalgobox/core/common/SelfMeasuredSortAlgorithm.scala index ff6b3bf..f53f944 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/MeasuredSortAlgorithm.scala +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/SelfMeasuredSortAlgorithm.scala @@ -21,6 +21,6 @@ package pl.tarsa.sortalgobox.core.common import scala.concurrent.duration.FiniteDuration -abstract class MeasuredSortAlgorithm[T] { +abstract class SelfMeasuredSortAlgorithm[T] { def sort(array: Array[T]): FiniteDuration } diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/PureSortAlgorithm.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/Specialization.scala similarity index 75% rename from core/main_scala/pl/tarsa/sortalgobox/core/common/PureSortAlgorithm.scala rename to core/main_scala/pl/tarsa/sortalgobox/core/common/Specialization.scala index f359833..4989c07 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/PureSortAlgorithm.scala +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/Specialization.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,15 +16,11 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.core.common -import pl.tarsa.sortalgobox.core.common.agents.ItemsAgent - -import scala.language.higherKinds - -abstract class PureSortAlgorithm[AgentType[ItemType] <: ItemsAgent[ItemType]] { +import scala.Specializable.Group - def sort[ItemType](itemsAgent: AgentType[ItemType]): Unit +object Specialization { + final val Group = new Group((Byte, Short, Int, Long)) } diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/MergeSortItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/MergeSortItemsAgent.scala deleted file mode 100644 index 5ec5ee7..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/MergeSortItemsAgent.scala +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents - -abstract class MergeSortItemsAgent[ItemType] - extends ComparingItemsAgent[ItemType] { - override type SelfType <: MergeSortItemsAgent[ItemType] - - def size1: Int - - def get1(i: Int): ItemType - - def set1(i: Int, v: ItemType): Unit - - def swap00(i: Int, j: Int): Unit = { - val temp = get0(i) - set0(i, get0(j)) - set0(j, temp) - } - - def swap01(i: Int, j: Int): Unit = { - val temp = get0(i) - set0(i, get1(j)) - set1(j, temp) - } - - def swap10(i: Int, j: Int): Unit = { - val temp = get1(i) - set1(i, get0(j)) - set0(j, temp) - } - - def swap11(i: Int, j: Int): Unit = { - val temp = get1(i) - set1(i, get1(j)) - set1(j, temp) - } - - def compare00(i: Int, j: Int): Int = compare(get0(i), get0(j)) - - def compare01(i: Int, j: Int): Int = compare(get0(i), get1(j)) - - def compare10(i: Int, j: Int): Int = compare(get1(i), get0(j)) - - def compare11(i: Int, j: Int): Int = compare(get1(i), get1(j)) - - def copy00(i: Int, j: Int, n: Int): Unit - - def copy01(i: Int, j: Int, n: Int): Unit - - def copy10(i: Int, j: Int, n: Int): Unit - - def copy11(i: Int, j: Int, n: Int): Unit -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/RadixSortItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/RadixSortItemsAgent.scala deleted file mode 100644 index b8da344..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/RadixSortItemsAgent.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents - -abstract class RadixSortItemsAgent[ItemType] - extends SlicingItemsAgent[ItemType] { - override type SelfType <: RadixSortItemsAgent[ItemType] - - def size1: Int - - def get1(i: Int): ItemType - - def set1(i: Int, v: ItemType): Unit - - def swap00(i: Int, j: Int): Unit = { - val temp = get0(i) - set0(i, get0(j)) - set0(j, temp) - } - - def swap01(i: Int, j: Int): Unit = { - val temp = get0(i) - set0(i, get1(j)) - set1(j, temp) - } - - def swap10(i: Int, j: Int): Unit = { - val temp = get1(i) - set1(i, get0(j)) - set0(j, temp) - } - - def swap11(i: Int, j: Int): Unit = { - val temp = get1(i) - set1(i, get1(j)) - set1(j, temp) - } - - def copy00(i: Int, j: Int, n: Int): Unit - - def copy01(i: Int, j: Int, n: Int): Unit - - def copy10(i: Int, j: Int, n: Int): Unit - - def copy11(i: Int, j: Int, n: Int): Unit - - def getItemSlice1(i: Int, lowestBit: Int, length: Int): Int = - getItemSlice(get1(i), lowestBit, length) -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/SlicingItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/SlicingItemsAgent.scala deleted file mode 100644 index 0556864..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/SlicingItemsAgent.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents - -abstract class SlicingItemsAgent[ItemType] extends ItemsAgent[ItemType] { - override type SelfType <: SlicingItemsAgent[ItemType] - - def keySizeInBits: Int - - def getItemSlice(v: ItemType, lowestBit: Int, length: Int): Int - - def getItemSlice0(i: Int, lowestBit: Int, length: Int): Int = - getItemSlice(get0(i), lowestBit, length) -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgent.scala deleted file mode 100644 index 7f503bb..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgent.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent - -class ComparingIntArrayItemsAgent(items: Array[Int], base: Int = 0) - extends ComparingItemsAgent[Int] { - override type SelfType = ComparingIntArrayItemsAgent - - override def withBase(newIndexingBase: Int): SelfType = { - if (base == newIndexingBase) this - else new ComparingIntArrayItemsAgent(items, newIndexingBase) - } - - override def size0: Int = - items.length - - override def get0(i: Int): Int = - items(i - base) - - override def set0(i: Int, v: Int): Unit = - items(i - base) = v - - override def copy0(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, items, j - base, n) - - override def compare(a: Int, b: Int): Int = - Ordering.Int.compare(a, b) -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgent.scala deleted file mode 100644 index 6da7ab1..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgent.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.core.common.agents.MergeSortItemsAgent - -class MergeSortIntArrayItemsAgent(items: Array[Int], - buffer: Array[Int], - base: Int = 0) - extends MergeSortItemsAgent[Int] { - override type SelfType = MergeSortIntArrayItemsAgent - - override def withBase(newIndexingBase: Int): SelfType = { - if (base == newIndexingBase) this - else new MergeSortIntArrayItemsAgent(items, buffer, newIndexingBase) - } - - override def size0: Int = - items.length - - override def get0(i: Int): Int = - items(i - base) - - override def set0(i: Int, v: Int): Unit = - items(i - base) = v - - override def copy0(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, items, j - base, n) - - override def size1: Int = - buffer.length - - override def get1(i: Int): Int = - buffer(i - base) - - override def set1(i: Int, v: Int): Unit = - buffer(i - base) = v - - override def compare(a: Int, b: Int): Int = - Ordering.Int.compare(a, b) - - override def copy00(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, items, j - base, n) - - override def copy01(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, buffer, j - base, n) - - override def copy10(i: Int, j: Int, n: Int): Unit = - System.arraycopy(buffer, i - base, items, j - base, n) - - override def copy11(i: Int, j: Int, n: Int): Unit = - System.arraycopy(buffer, i - base, buffer, j - base, n) -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgent.scala deleted file mode 100644 index ff5589c..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgent.scala +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.core.common.agents.RadixSortItemsAgent - -class RadixSortIntArrayItemsAgent(items: Array[Int], - buffer: Array[Int], - base: Int = 0) - extends RadixSortItemsAgent[Int] { - override type SelfType = RadixSortIntArrayItemsAgent - - override def withBase(newIndexingBase: Int): SelfType = { - if (base == newIndexingBase) this - else new RadixSortIntArrayItemsAgent(items, buffer, newIndexingBase) - } - - override def size0: Int = - items.length - - override def get0(i: Int): Int = - items(i - base) - - override def set0(i: Int, v: Int): Unit = - items(i - base) = v - - override def copy0(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, items, j - base, n) - - override def keySizeInBits: Int = 32 - - override def getItemSlice(v: Int, lowestBit: Int, length: Int): Int = { - ((v ^ Int.MinValue) >>> lowestBit) & ((1 << length) - 1) - } - - override def size1: Int = - buffer.length - - override def get1(i: Int): Int = - buffer(i - base) - - override def set1(i: Int, v: Int): Unit = - buffer(i - base) = v - - override def copy00(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, items, j - base, n) - - override def copy01(i: Int, j: Int, n: Int): Unit = - System.arraycopy(items, i - base, buffer, j - base, n) - - override def copy10(i: Int, j: Int, n: Int): Unit = - System.arraycopy(buffer, i - base, items, j - base, n) - - override def copy11(i: Int, j: Int, n: Int): Unit = - System.arraycopy(buffer, i - base, buffer, j - base, n) -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgent.scala deleted file mode 100644 index 3a927ed..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgent.scala +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent -import pl.tarsa.sortalgobox.core.crossverify.PureNumberEncoder - -class RecordingComparingIntArrayItemsAgent( - recorder: PureNumberEncoder, - underlying: ComparingIntArrayItemsAgent) - extends ComparingItemsAgent[Int] { - override type SelfType = RecordingComparingIntArrayItemsAgent - - override def withBase(newIndexingBase: Int): SelfType = { - val newUnderlying = underlying.withBase(newIndexingBase) - if (underlying eq newUnderlying) { - this - } else { - new RecordingComparingIntArrayItemsAgent(recorder, newUnderlying) - } - } - - import recorder._ - - override def size0: Int = - recordedF(Size0, _.size0) - - override def get0(i: Int): Int = - recordedF(Get0, _.get0(i), i) - - override def set0(i: Int, v: Int): Unit = - recordedP(Set0, _.set0(i, v), i) - - override def copy0(i: Int, j: Int, n: Int): Unit = - recordedP(Copy0, _.copy0(i, j, n), i, j, n) - - override def swap0(i: Int, j: Int): Unit = - recordedP(Swap0, _.swap0(i, j), i, j) - - override def compare(a: Int, b: Int): Int = - recordedF(Compare, _.compare(a, b)) - - override def compare0(i: Int, j: Int): Int = - recordedF(Compare0, _.compare0(i, j), i, j) - - @inline - private def recordedP(actionType: ActionType, - action: ComparingIntArrayItemsAgent => Unit, - parameters: Int*): Unit = { - serializeInt(actionType.id) - parameters.foreach(serializeInt) - action(underlying) - } - - @inline - private def recordedF(actionType: ActionType, - action: ComparingIntArrayItemsAgent => Int, - parameters: Int*): Int = { - serializeInt(actionType.id) - parameters.foreach(serializeInt) - action(underlying) - } -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgent.scala deleted file mode 100644 index ceb8a5e..0000000 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgent.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent -import pl.tarsa.sortalgobox.core.crossverify.PureNumberDecoder - -class VerifyingComparingIntArrayItemsAgent( - replayer: PureNumberDecoder, - underlying: ComparingIntArrayItemsAgent, - verify: Boolean => Unit) - extends ComparingItemsAgent[Int] { - override type SelfType = VerifyingComparingIntArrayItemsAgent - - override def withBase(newIndexingBase: Int): SelfType = { - val newUnderlying = underlying.withBase(newIndexingBase) - if (underlying eq newUnderlying) { - this - } else { - new VerifyingComparingIntArrayItemsAgent(replayer, newUnderlying, verify) - } - } - - import replayer._ - - override def size0: Int = - recordedF(Size0, _.size0) - - override def get0(i: Int): Int = - recordedF(Get0, _.get0(i), i) - - override def set0(i: Int, v: Int): Unit = - recordedP(Set0, _.set0(i, v), i) - - override def copy0(i: Int, j: Int, n: Int): Unit = - recordedP(Copy0, _.copy0(i, j, n), i, j, n) - - override def swap0(i: Int, j: Int): Unit = - recordedP(Swap0, _.swap0(i, j), i, j) - - override def compare(a: Int, b: Int): Int = - recordedF(Compare, _.compare(a, b)) - - override def compare0(i: Int, j: Int): Int = - recordedF(Compare0, _.compare0(i, j), i, j) - - @inline - private def recordedP(actionType: ActionType, - action: ComparingIntArrayItemsAgent => Unit, - parameters: Int*): Unit = { - verify(deserializeInt() == actionType.id) - parameters.foreach(parameter => verify(deserializeInt() == parameter)) - action(underlying) - } - - @inline - private def recordedF(actionType: ActionType, - action: ComparingIntArrayItemsAgent => Int, - parameters: Int*): Int = { - verify(deserializeInt() == actionType.id) - parameters.foreach(parameter => verify(deserializeInt() == parameter)) - action(underlying) - } -} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgent.scala new file mode 100644 index 0000000..501ed22 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgent.scala @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + ItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + NumericItemsOperations +} + +import scala.{specialized => spec} + +abstract class ItemsAgent private[items] { + def size[Buffer <: ItemsBuffer[Buffer]](buffer: Buffer): Int + + def get[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int): Item + + def get[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], index: Int): Item + + def set[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int, + value: Item): Unit + + def set[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int, + value: Item): Unit + + def swap[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Unit + + def swap[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Unit + + def itemBitsSize(buffer: NumericItemsBuffer[_]): Int + + def asLong[@spec(Grp) Item](itemsOps: NumericItemsOperations[Item], + value: Item): Long + + final def asLongI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int): Long = + asLong(buffer.itemsOps, get(buffer, index)) + + def getSlice[@spec(Grp) Item](itemsOps: NumericItemsOperations[Item], + value: Item, + lowestBitIndex: Int, + length: Int): Int + + final def getSliceI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int, + lowestBitIndex: Int, + length: Int): Int = + getSlice(buffer.itemsOps, get(buffer, index), lowestBitIndex, length) + + def compareEq[@spec(Grp) Item](itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean + + final def compareEqI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareEq(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareEqI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareEq(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareEqIV[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareEq(buffer.itemsOps, get(buffer, index1), value2) + + final def compareEqIV[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareEq(buffer.itemsOps, get(buffer, index1), value2) + + final def compareEqVI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareEq(buffer.itemsOps, value1, get(buffer, index2)) + + final def compareEqVI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareEq(buffer.itemsOps, value1, get(buffer, index2)) + + def compareGt[@spec(Grp) Item](itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean + + final def compareGtI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareGt(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareGtI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareGt(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareGtIV[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareGt(buffer.itemsOps, get(buffer, index1), value2) + + final def compareGtIV[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareGt(buffer.itemsOps, get(buffer, index1), value2) + + final def compareGtVI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareGt(buffer.itemsOps, value1, get(buffer, index2)) + + final def compareGtVI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareGt(buffer.itemsOps, value1, get(buffer, index2)) + + def compareGte[@spec(Grp) Item](itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean + + final def compareGteI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareGte(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareGteI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareGte(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareGteIV[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareGte(buffer.itemsOps, get(buffer, index1), value2) + + final def compareGteIV[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareGte(buffer.itemsOps, get(buffer, index1), value2) + + final def compareGteVI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareGte(buffer.itemsOps, value1, get(buffer, index2)) + + final def compareGteVI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareGte(buffer.itemsOps, value1, get(buffer, index2)) + + def compareLt[@spec(Grp) Item](itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean + + final def compareLtI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareLt(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareLtI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareLt(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareLtIV[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareLt(buffer.itemsOps, get(buffer, index1), value2) + + final def compareLtIV[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareLt(buffer.itemsOps, get(buffer, index1), value2) + + final def compareLtVI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareLt(buffer.itemsOps, value1, get(buffer, index2)) + + final def compareLtVI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareLt(buffer.itemsOps, value1, get(buffer, index2)) + + def compareLte[@spec(Grp) Item](itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean + + final def compareLteI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareLte(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareLteI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Boolean = + compareLte(buffer.itemsOps, get(buffer, index1), get(buffer, index2)) + + final def compareLteIV[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareLte(buffer.itemsOps, get(buffer, index1), value2) + + final def compareLteIV[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + value2: Item): Boolean = + compareLte(buffer.itemsOps, get(buffer, index1), value2) + + final def compareLteVI[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareLte(buffer.itemsOps, value1, get(buffer, index2)) + + final def compareLteVI[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + value1: Item, + index2: Int): Boolean = + compareLte(buffer.itemsOps, value1, get(buffer, index2)) +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgent.scala new file mode 100644 index 0000000..8e99204 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgent.scala @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + ItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + NumericItemsOperations +} + +import scala.{specialized => spec} + +object PlainItemsAgent extends ItemsAgent { + final override def size[Buffer <: ItemsBuffer[Buffer]](buffer: Buffer): Int = + buffer.length + + final override def get[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int): Item = + buffer.get(index) + + final override def get[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int): Item = + buffer.get(index) + + final override def set[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int, + value: Item): Unit = + buffer.set(index, value) + + final override def set[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int, + value: Item): Unit = + buffer.set(index, value) + + final override def swap[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Unit = { + val item = buffer.get(index1) + buffer.set(index1, buffer.get(index2)) + buffer.set(index2, item) + } + + final override def swap[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Unit = { + val item = buffer.get(index1) + buffer.set(index1, buffer.get(index2)) + buffer.set(index2, item) + } + + final override def itemBitsSize(buffer: NumericItemsBuffer[_]): Int = + buffer.itemsOps.bitsSize + + final override def asLong[@spec(Grp) Item]( + itemsOps: NumericItemsOperations[Item], + value: Item): Long = + itemsOps.asLong(value) + + final override def getSlice[@spec(Grp) Item]( + itemsOps: NumericItemsOperations[Item], + value: Item, + lowestBitIndex: Int, + length: Int): Int = + itemsOps.getSlice(value, lowestBitIndex, length) + + final override def compareEq[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = + itemsOps.compareEq(value1, value2) + + final override def compareGt[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = + itemsOps.compareGt(value1, value2) + + final override def compareGte[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = + itemsOps.compareGte(value1, value2) + + final override def compareLt[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = + itemsOps.compareLt(value1, value2) + + final override def compareLte[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = + itemsOps.compareLte(value1, value2) +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgent.scala new file mode 100644 index 0000000..4667405 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgent.scala @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + ItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + NumericItemsOperations +} +import pl.tarsa.sortalgobox.core.crossverify.PureNumberEncoder + +import scala.{specialized => spec} + +final class RecordingItemsAgent(recorder: PureNumberEncoder) + extends ItemsAgent { + import recorder._ + + private def run = PlainItemsAgent + + override def size[Buffer <: ItemsBuffer[Buffer]](buffer: Buffer): Int = { + serializeAction(ActionTypes.Size) + serializeByteSafe(buffer.id) + val result = run.size(buffer) + serializeInt(result) + result + } + + override def get[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int): Item = { + serializeAction(ActionTypes.Get) + serializeByteSafe(buffer.id) + serializeInt(index) + run.get(buffer, index) + } + + override def get[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int): Item = { + serializeAction(ActionTypes.Get) + serializeByteSafe(buffer.id) + serializeInt(index) + run.get(buffer, index) + } + + override def set[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int, + value: Item): Unit = { + serializeAction(ActionTypes.Set) + serializeByteSafe(buffer.id) + serializeInt(index) + run.set(buffer, index, value) + } + + override def set[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int, + value: Item): Unit = { + serializeAction(ActionTypes.Set) + serializeByteSafe(buffer.id) + serializeInt(index) + run.set(buffer, index, value) + } + + override def swap[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Unit = { + serializeAction(ActionTypes.Swap) + serializeByteSafe(buffer.id) + serializeInt(index1) + serializeInt(index2) + run.swap(buffer, index1, index2) + } + + override def swap[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Unit = { + serializeAction(ActionTypes.Swap) + serializeByteSafe(buffer.id) + serializeInt(index1) + serializeInt(index2) + run.swap(buffer, index1, index2) + } + + override def itemBitsSize(buffer: NumericItemsBuffer[_]): Int = { + serializeAction(ActionTypes.ItemBitsSize) + serializeByteSafe(buffer.id) + val result = run.itemBitsSize(buffer) + serializeByteSafe(result) + result + } + + override def asLong[@spec(Grp) Item](itemsOps: NumericItemsOperations[Item], + value: Item): Long = { + serializeAction(ActionTypes.AsLong) + val result = run.asLong(itemsOps, value) + serializeLong(result) + result + } + + override def getSlice[@spec(Grp) Item](itemsOps: NumericItemsOperations[Item], + value: Item, + lowestBitIndex: Int, + length: Int): Int = { + serializeAction(ActionTypes.GetSlice) + serializeByteSafe(lowestBitIndex) + serializeByteSafe(length) + val result = run.getSlice(itemsOps, value, lowestBitIndex, length) + serializeInt(result) + result + } + + override def compareEq[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + serializeAction(ActionTypes.CompareEq) + val result = run.compareEq(itemsOps, value1, value2) + serializeBit(result) + result + } + + override def compareGt[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + serializeAction(ActionTypes.CompareGt) + val result = run.compareGt(itemsOps, value1, value2) + serializeBit(result) + result + } + + override def compareGte[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + serializeAction(ActionTypes.CompareGte) + val result = run.compareGte(itemsOps, value1, value2) + serializeBit(result) + result + } + + override def compareLt[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + serializeAction(ActionTypes.CompareLt) + val result = run.compareLt(itemsOps, value1, value2) + serializeBit(result) + result + } + + override def compareLte[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + serializeAction(ActionTypes.CompareLte) + val result = run.compareLte(itemsOps, value1, value2) + serializeBit(result) + result + } + + private def serializeAction(action: ActionTypes.Action): Unit = + serializeByteSafe(action.id) + + private def serializeByteSafe(value: Int): Unit = { + val asByte = value.toByte.ensuring(_ == value) + serializeByte(asByte) + } +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgent.scala new file mode 100644 index 0000000..75ac528 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgent.scala @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + ItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + NumericItemsOperations +} +import pl.tarsa.sortalgobox.core.crossverify.PureNumberDecoder + +import scala.{specialized => spec} + +final class VerifyingItemsAgent(replayer: PureNumberDecoder, + verify: Boolean => Unit) + extends ItemsAgent { + private def run = PlainItemsAgent + + override def size[Buffer <: ItemsBuffer[Buffer]](buffer: Buffer): Int = { + verifyAction(ActionTypes.Size) + verifyByte(buffer.id.toByte) + val result = run.size(buffer) + verifyInt(result) + result + } + + override def get[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int): Item = { + verifyAction(ActionTypes.Get) + verifyByte(buffer.id.toByte) + verifyInt(index) + run.get(buffer, index) + } + + override def get[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int): Item = { + verifyAction(ActionTypes.Get) + verifyByte(buffer.id.toByte) + verifyInt(index) + run.get(buffer, index) + } + + override def set[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index: Int, + value: Item): Unit = { + verifyAction(ActionTypes.Set) + verifyByte(buffer.id.toByte) + verifyInt(index) + run.set(buffer, index, value) + } + + override def set[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index: Int, + value: Item): Unit = { + verifyAction(ActionTypes.Set) + verifyByte(buffer.id.toByte) + verifyInt(index) + run.set(buffer, index, value) + } + + override def swap[@spec(Grp) Item](buffer: ComparableItemsBuffer[Item], + index1: Int, + index2: Int): Unit = { + verifyAction(ActionTypes.Swap) + verifyByte(buffer.id.toByte) + verifyInt(index1) + verifyInt(index2) + run.swap(buffer, index1, index2) + } + + override def swap[@spec(Grp) Item](buffer: NumericItemsBuffer[Item], + index1: Int, + index2: Int): Unit = { + verifyAction(ActionTypes.Swap) + verifyByte(buffer.id.toByte) + verifyInt(index1) + verifyInt(index2) + run.swap(buffer, index1, index2) + } + + override def itemBitsSize(buffer: NumericItemsBuffer[_]): Int = { + verifyAction(ActionTypes.ItemBitsSize) + verifyByte(buffer.id.toByte) + val result = run.itemBitsSize(buffer) + verifyByte(result.toByte) + result + } + + override def asLong[@spec(Grp) Item](itemsOps: NumericItemsOperations[Item], + value: Item): Long = { + verifyAction(ActionTypes.AsLong) + val result = run.asLong(itemsOps, value) + verifyLong(result) + result + } + + override def getSlice[@spec(Grp) Item](itemsOps: NumericItemsOperations[Item], + value: Item, + lowestBitIndex: Int, + length: Int): Int = { + verifyAction(ActionTypes.GetSlice) + verifyByte(lowestBitIndex.toByte) + verifyByte(length.toByte) + val result = run.getSlice(itemsOps, value, lowestBitIndex, length) + verifyInt(result) + result + } + + override def compareEq[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + verifyAction(ActionTypes.CompareEq) + val result = run.compareEq(itemsOps, value1, value2) + verifyBit(result) + result + } + + override def compareGt[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + verifyAction(ActionTypes.CompareGt) + val result = run.compareGt(itemsOps, value1, value2) + verifyBit(result) + result + } + + override def compareGte[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + verifyAction(ActionTypes.CompareGte) + val result = run.compareGte(itemsOps, value1, value2) + verifyBit(result) + result + } + + override def compareLt[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + verifyAction(ActionTypes.CompareLt) + val result = run.compareLt(itemsOps, value1, value2) + verifyBit(result) + result + } + + override def compareLte[@spec(Grp) Item]( + itemsOps: ComparableItemsOperations[Item], + value1: Item, + value2: Item): Boolean = { + verifyAction(ActionTypes.CompareLte) + val result = run.compareLte(itemsOps, value1, value2) + verifyBit(result) + result + } + + private def verifyBit(expected: Boolean): Unit = { + val actual = replayer.deserializeBit() + verify(expected == actual) + } + + private def verifyAction(action: ActionTypes.Action): Unit = + verifyByte(action.id.toByte) + + private def verifyByte(expected: Byte): Unit = { + val actual = replayer.deserializeByte() + verify(expected == actual) + } + + private def verifyInt(expected: Int): Unit = { + val actual = replayer.deserializeInt() + verify(expected == actual) + } + + private def verifyLong(expected: Long): Unit = { + val actual = replayer.deserializeLong() + verify(expected == actual) + } +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBuffer.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBuffer.scala new file mode 100644 index 0000000..d8e4212 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBuffer.scala @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.buffers + +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + ItemsOperations +} + +sealed trait ComparableItemsBuffer[@specialized(Group) Item] + extends ItemsBuffer[ComparableItemsBuffer[Item]] { + protected[items] def get(index: Int): Item + protected[items] def set(index: Int, item: Item): Unit + def itemsOps: ComparableItemsOperations[Item] +} + +object ComparableItemsBuffer { + def apply[T: Ordering](id: Int, + array: Array[T], + base: Int): ComparableItemsBuffer[T] = { + array match { + case bytes: Array[Byte] => + new Bytes(id, base, bytes) + case shorts: Array[Short] => + new Shorts(id, base, shorts) + case integers: Array[Int] => + new Integers(id, base, integers) + case longs: Array[Long] => + new Longs(id, base, longs) + case others: Array[T] => + new Others[T](id, base, others) + } + } + + final private class Bytes(val id: Int, val base: Int, array: Array[Byte]) + extends ComparableItemsBuffer[Byte] { + def length: Int = + array.length + def get(index: Int): Byte = + array(index - base) + def set(index: Int, item: Byte): Unit = + array(index - base) = item + def itemsOps: ComparableItemsOperations[Byte] = + ItemsOperations.bytesOps + } + + final private class Shorts(val id: Int, val base: Int, array: Array[Short]) + extends ComparableItemsBuffer[Short] { + def length: Int = + array.length + def get(index: Int): Short = + array(index - base) + def set(index: Int, item: Short): Unit = + array(index - base) = item + def itemsOps: ComparableItemsOperations[Short] = + ItemsOperations.shortOps + } + + final private class Integers(val id: Int, val base: Int, array: Array[Int]) + extends ComparableItemsBuffer[Int] { + def length: Int = + array.length + def get(index: Int): Int = + array(index - base) + def set(index: Int, item: Int): Unit = + array(index - base) = item + def itemsOps: ComparableItemsOperations[Int] = + ItemsOperations.intOps + } + + final private class Longs(val id: Int, val base: Int, array: Array[Long]) + extends ComparableItemsBuffer[Long] { + def length: Int = + array.length + def get(index: Int): Long = + array(index - base) + def set(index: Int, item: Long): Unit = + array(index - base) = item + def itemsOps: ComparableItemsOperations[Long] = + ItemsOperations.longOps + } + + final private class Others[Item: Ordering](val id: Int, + val base: Int, + array: Array[Item]) + extends ComparableItemsBuffer[Item] { + def length: Int = + array.length + def get(index: Int): Item = + array(index - base) + def set(index: Int, item: Item): Unit = + array(index - base) = item + val itemsOps: ComparableItemsOperations[Item] = + ItemsOperations.orderedItemsOps[Item] + } +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ComparingItemsAgent.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ItemsBuffer.scala similarity index 72% rename from core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ComparingItemsAgent.scala rename to core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ItemsBuffer.scala index 198e5b6..e9c7563 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ComparingItemsAgent.scala +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ItemsBuffer.scala @@ -17,16 +17,16 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ -package pl.tarsa.sortalgobox.core.common.agents +package pl.tarsa.sortalgobox.core.common.items.buffers -abstract class ComparingItemsAgent[ItemType] extends ItemsAgent[ItemType] { - override type SelfType <: ComparingItemsAgent[ItemType] +abstract class ItemsBuffer[Self <: ItemsBuffer[Self]] private[items] { + self: Self => - def compare(a: ItemType, b: ItemType): Int + /** Identifier for verification purposes */ + protected[items] def id: Int - def compare0(i: Int, j: Int): Int = - compare(get0(i), get0(j)) + /** Indexing base */ + protected[items] def base: Int - def compareLt0(i: Int, j: Int): Boolean = - compare0(i, j) < 0 + protected[items] def length: Int } diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBuffer.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBuffer.scala new file mode 100644 index 0000000..7510018 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBuffer.scala @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.buffers + +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ItemsOperations, + NumericItemsOperations +} + +sealed trait NumericItemsBuffer[@specialized(Group) Item] + extends ItemsBuffer[NumericItemsBuffer[Item]] { + protected[items] def get(index: Int): Item + protected[items] def set(index: Int, item: Item): Unit + def itemsOps: NumericItemsOperations[Item] +} + +object NumericItemsBuffer { + def apply(id: Int, array: Array[Byte], base: Int): NumericItemsBuffer[Byte] = + new Bytes(id, base, array) + + def apply(id: Int, + array: Array[Short], + base: Int): NumericItemsBuffer[Short] = + new Shorts(id, base, array) + + def apply(id: Int, array: Array[Int], base: Int): NumericItemsBuffer[Int] = + new Integers(id, base, array) + + def apply(id: Int, array: Array[Long], base: Int): NumericItemsBuffer[Long] = + new Longs(id, base, array) + + def apply[Item: Evidence](id: Int, + array: Array[Item], + base: Int): NumericItemsBuffer[Item] = { + array match { + case bytes: Array[Byte] => + apply(id, bytes, base) + case shorts: Array[Short] => + apply(id, shorts, base) + case integers: Array[Int] => + apply(id, integers, base) + case longs: Array[Long] => + apply(id, longs, base) + case _ => + val evidence = implicitly[Evidence[Item]] + val arrayType = array.elemTag.runtimeClass.getSimpleName + throw new IllegalArgumentException( + s"Invalid evidence $evidence for array type $arrayType") + } + } + + final private class Bytes(val id: Int, val base: Int, array: Array[Byte]) + extends NumericItemsBuffer[Byte] { + def length: Int = + array.length + def get(index: Int): Byte = + array(index - base) + def set(index: Int, item: Byte): Unit = + array(index - base) = item + def itemsOps: NumericItemsOperations[Byte] = + ItemsOperations.bytesOps + } + + final private class Shorts(val id: Int, val base: Int, array: Array[Short]) + extends NumericItemsBuffer[Short] { + def length: Int = + array.length + def get(index: Int): Short = + array(index - base) + def set(index: Int, item: Short): Unit = + array(index - base) = item + def itemsOps: NumericItemsOperations[Short] = + ItemsOperations.shortOps + } + + final private class Integers(val id: Int, val base: Int, array: Array[Int]) + extends NumericItemsBuffer[Int] { + def length: Int = + array.length + def get(index: Int): Int = + array(index - base) + def set(index: Int, item: Int): Unit = + array(index - base) = item + def itemsOps: NumericItemsOperations[Int] = + ItemsOperations.intOps + } + + final private class Longs(val id: Int, val base: Int, array: Array[Long]) + extends NumericItemsBuffer[Long] { + def length: Int = + array.length + def get(index: Int): Long = + array(index - base) + def set(index: Int, item: Long): Unit = + array(index - base) = item + def itemsOps: NumericItemsOperations[Long] = + ItemsOperations.longOps + } + + sealed trait Evidence[Item] + + object Evidence { + implicit object BytesEvidence extends Evidence[Byte] + implicit object ShortsEvidence extends Evidence[Short] + implicit object IntegersEvidence extends Evidence[Int] + implicit object LongsEvidence extends Evidence[Long] + } +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperations.scala b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperations.scala new file mode 100644 index 0000000..b1f1001 --- /dev/null +++ b/core/main_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperations.scala @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.operations + +import pl.tarsa.sortalgobox.core.common.Specialization.Group + +sealed trait ComparableItemsOperations[@specialized(Group) Item] { + protected[items] def compareEq(value1: Item, value2: Item): Boolean + protected[items] def compareGt(value1: Item, value2: Item): Boolean + protected[items] def compareGte(value1: Item, value2: Item): Boolean + protected[items] def compareLt(value1: Item, value2: Item): Boolean + protected[items] def compareLte(value1: Item, value2: Item): Boolean +} + +sealed trait NumericItemsOperations[@specialized(Group) Item] + extends ComparableItemsOperations[Item] { + protected[items] def bitsSize: Int + protected[items] def asLong(value: Item): Long + protected[items] def getSlice(value: Item, + lowestBitIndex: Int, + length: Int): Int +} + +private[items] object ItemsOperations { + def orderedItemsOps[Item: Ordering]: ComparableItemsOperations[Item] = { + val ord = Ordering[Item] + new ComparableItemsOperations[Item] { + final def compareEq(value1: Item, value2: Item): Boolean = + ord.equiv(value1, value2) + final def compareGt(value1: Item, value2: Item): Boolean = + ord.gt(value1, value2) + final def compareGte(value1: Item, value2: Item): Boolean = + ord.gteq(value1, value2) + final def compareLt(value1: Item, value2: Item): Boolean = + ord.lt(value1, value2) + final def compareLte(value1: Item, value2: Item): Boolean = + ord.lteq(value1, value2) + } + } + + final val bytesOps: NumericItemsOperations[Byte] = { + new NumericItemsOperations[Byte] { + final def bitsSize: Int = + 8 + final def asLong(value: Byte): Long = + value.toLong + final def getSlice(value: Byte, lowestBitIndex: Int, length: Int): Int = + (value >> lowestBitIndex) & ((1 << length) - 1) + final def compareEq(value1: Byte, value2: Byte): Boolean = + value1 == value2 + final def compareGt(value1: Byte, value2: Byte): Boolean = + value1 > value2 + final def compareGte(value1: Byte, value2: Byte): Boolean = + value1 >= value2 + final def compareLt(value1: Byte, value2: Byte): Boolean = + value1 < value2 + final def compareLte(value1: Byte, value2: Byte): Boolean = + value1 <= value2 + } + } + + final val shortOps: NumericItemsOperations[Short] = { + new NumericItemsOperations[Short] { + final def bitsSize: Int = + 16 + final def asLong(value: Short): Long = + value.toLong + final def getSlice(value: Short, lowestBitIndex: Int, length: Int): Int = + (value >> lowestBitIndex) & ((1 << length) - 1) + final def compareEq(value1: Short, value2: Short): Boolean = + value1 == value2 + final def compareGt(value1: Short, value2: Short): Boolean = + value1 > value2 + final def compareGte(value1: Short, value2: Short): Boolean = + value1 >= value2 + final def compareLt(value1: Short, value2: Short): Boolean = + value1 < value2 + final def compareLte(value1: Short, value2: Short): Boolean = + value1 <= value2 + } + } + + final val intOps: NumericItemsOperations[Int] = { + new NumericItemsOperations[Int] { + final def bitsSize: Int = + 32 + final def asLong(value: Int): Long = + value.toLong + final def getSlice(value: Int, lowestBitIndex: Int, length: Int): Int = + (value >> lowestBitIndex) & ((1 << length) - 1) + final def compareEq(value1: Int, value2: Int): Boolean = + value1 == value2 + final def compareGt(value1: Int, value2: Int): Boolean = + value1 > value2 + final def compareGte(value1: Int, value2: Int): Boolean = + value1 >= value2 + final def compareLt(value1: Int, value2: Int): Boolean = + value1 < value2 + final def compareLte(value1: Int, value2: Int): Boolean = + value1 <= value2 + } + } + + final val longOps: NumericItemsOperations[Long] = { + new NumericItemsOperations[Long] { + final def bitsSize: Int = + 64 + final def asLong(value: Long): Long = + value.toLong + final def getSlice(value: Long, lowestBitIndex: Int, length: Int): Int = + (value >> lowestBitIndex).toInt & ((1 << length) - 1) + final def compareEq(value1: Long, value2: Long): Boolean = + value1 == value2 + final def compareGt(value1: Long, value2: Long): Boolean = + value1 > value2 + final def compareGte(value1: Long, value2: Long): Boolean = + value1 >= value2 + final def compareLt(value1: Long, value2: Long): Boolean = + value1 < value2 + final def compareLte(value1: Long, value2: Long): Boolean = + value1 <= value2 + } + } +} diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoder.scala b/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoder.scala index d46c6d2..363a251 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoder.scala +++ b/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoder.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -17,7 +17,6 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ - package pl.tarsa.sortalgobox.core.crossverify import java.io.InputStream @@ -25,17 +24,34 @@ import java.io.InputStream import scala.annotation.tailrec class PureNumberDecoder(input: InputStream) { + def deserializeBit(): Boolean = { + val value = input.read() + if (value == -1) { + throw new PrematureEndOfInputException + } + if (value > 1) { + throw new ValueOverflowException + } + value == 1 + } + + def deserializeByte(): Byte = { + val value = input.read() + if (value == -1) { + throw new PrematureEndOfInputException + } + value.toByte + } + def deserializeInt(): Int = { @tailrec def deserialize(current: Int, shift: Int): Int = { val value = input.read() if (value == -1) { throw new PrematureEndOfInputException - } else if (value == 0) { - current } else { val chunk = value & 127 - if (chunk != 0 && (shift > 31 || chunk > (Int.MaxValue >> shift))) { + if (shift > 31 || (shift > 0 && chunk >= (1 << (32 - shift)))) { throw new ValueOverflowException } if (value <= 127) { @@ -45,7 +61,10 @@ class PureNumberDecoder(input: InputStream) { } } } - deserialize(0, 0) + val shifted = deserialize(0, 0) + val signFlag = (shifted & 1) == 1 + val absValue = shifted >>> 1 + if (signFlag) ~absValue else absValue } def deserializeLong(): Long = { @@ -54,11 +73,9 @@ class PureNumberDecoder(input: InputStream) { val value = input.read() if (value == -1) { throw new PrematureEndOfInputException - } else if (value == 0) { - current } else { val chunk = value & 127L - if (chunk != 0 && (shift > 63 || chunk > (Long.MaxValue >> shift))) { + if (shift > 63 || (shift > 0 && chunk >= (1L << (64 - shift)))) { throw new ValueOverflowException } if (value <= 127) { @@ -68,6 +85,9 @@ class PureNumberDecoder(input: InputStream) { } } } - deserialize(0, 0) + val shifted = deserialize(0, 0) + val signFlag = (shifted & 1) == 1 + val absValue = shifted >>> 1 + if (signFlag) ~absValue else absValue } } diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoder.scala b/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoder.scala index 70b09ec..6bfad74 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoder.scala +++ b/core/main_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoder.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -17,7 +17,6 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ - package pl.tarsa.sortalgobox.core.crossverify import java.io.OutputStream @@ -25,33 +24,39 @@ import java.io.OutputStream import scala.annotation.tailrec class PureNumberEncoder(output: OutputStream) { - def serializeInt(value: Int): Unit = { + def serializeBit(value: Boolean): Unit = { + val byte: Byte = if (value) 1 else 0 + output.write(byte) + } + + def serializeByte(value: Byte): Unit = + output.write(value) + + def serializeInt(original: Int): Unit = { @tailrec def serialize(value: Int): Unit = { - if (value < 0) { - throw new IllegalArgumentException - } else if (value <= Byte.MaxValue) { - output.write(value) + if ((value >>> 7) == 0) { + output.write(value.toByte) } else { - output.write((value & 127) - 128) - serialize(value >> 7) + output.write((value.toByte & 127) - 128) + serialize(value >>> 7) } } + val value = (original.abs << 1) - (original >>> 31) serialize(value) } - def serializeLong(value: Long): Unit = { + def serializeLong(original: Long): Unit = { @tailrec def serialize(value: Long): Unit = { - if (value < 0) { - throw new IllegalArgumentException - } else if (value <= Byte.MaxValue) { + if ((value >>> 7) == 0) { output.write(value.toByte) } else { - output.write(((value & 127) - 128).toByte) - serialize(value >> 7) + output.write((value.toByte & 127) - 128) + serialize(value >>> 7) } } + val value = (original.abs << 1) - (original >>> 63) serialize(value) } } diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseDoubleIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseDoubleIntArrayItemsAgentSpec.scala deleted file mode 100644 index a2d518a..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseDoubleIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.core.common.agents.ItemsAgent -import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase - -abstract class BaseDoubleIntArrayItemsAgentSpec[AgentType <: ItemsAgent[_]]( - builder: (Array[Int], Array[Int]) => AgentType) - extends CommonUnitSpecBase { - - def readTest(inputItems: Int*)(inputBufferItems: Int*)( - operations: (AgentType => Unit)*) { - val agent = builder(inputItems.toArray, inputBufferItems.toArray) - operations.foreach(_(agent)) - } - - def writeTest(inputItems: Int*)(inputBufferItems: Int*)( - operations: (AgentType => Unit)*)(outputItems: Int*)( - outputBufferItems: Int*) { - val itemsArray = inputItems.toArray - val bufferItemsArray = inputBufferItems.toArray - val agent = builder(itemsArray, bufferItemsArray) - operations.foreach(_(agent)) - assert(itemsArray.toSeq == outputItems) - assert(bufferItemsArray.toSeq == outputBufferItems) - } - - def pureTest(operations: (AgentType => Unit)*): Unit = { - val agent = builder(null, null) - operations.foreach(_(agent)) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseSingleIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseSingleIntArrayItemsAgentSpec.scala deleted file mode 100644 index 25e144b..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/BaseSingleIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import pl.tarsa.sortalgobox.core.common.agents.ItemsAgent -import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase - -abstract class BaseSingleIntArrayItemsAgentSpec[AgentType <: ItemsAgent[_]]( - builder: Array[Int] => AgentType) - extends CommonUnitSpecBase { - - def readTest(inputItems: Int*)(operations: (AgentType => Unit)*) { - val agent = builder(inputItems.toArray) - operations.foreach(_(agent)) - } - - def writeTest(inputItems: Int*)(operations: (AgentType => Unit)*)( - outputItems: Int*) { - val array = inputItems.toArray - val agent = builder(array) - operations.foreach(_(agent)) - assert(array.toSeq == outputItems) - } - - def pureTest(operations: (AgentType => Unit)*): Unit = { - val agent = builder(null) - operations.foreach(_(agent)) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgentSpec.scala deleted file mode 100644 index bf68224..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/ComparingIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -class ComparingIntArrayItemsAgentSpec - extends BaseSingleIntArrayItemsAgentSpec(new ComparingIntArrayItemsAgent(_)) { - typeBehavior[ComparingIntArrayItemsAgent] - - it must "return correct size for empty array" in { - readTest()(a => assert(a.size0 == 0)) - } - - it must "return correct size for non-empty array" in { - readTest(1, 2, 3)(a => assert(a.size0 == 3)) - } - - it must "get proper values" in { - readTest(5, 3, 2, 8)( - a => assert(a.get0(0) == 5), - a => assert(a.get0(1) == 3), - a => assert(a.get0(2) == 2), - a => assert(a.get0(3) == 8) - ) - } - - it must "set proper cells" in { - writeTest(5, 3, 2, 8)( - _.set0(3, 1), - _.set0(1, 2), - _.set0(0, 9), - _.set0(3, 7) - )(9, 2, 2, 7) - } - - it must "copy proper cells" in { - writeTest(5, 3, 2, 8)( - _.copy0(1, 0, 2) - )(3, 2, 2, 8) - } - - it must "swap proper cells" in { - writeTest(5, 3, 2, 8)( - _.swap0(3, 0) - )(8, 3, 2, 5) - } - - it must "compare values properly" in { - pureTest( - a => assert(a.compare(1, 2) == -1), - a => assert(a.compare(2, 1) == 1), - a => assert(a.compare(1, 1) == 0) - ) - } - - it must "compare cells properly" in { - readTest(5, 3, 2, 8, 5)( - a => assert(a.compare0(0, 1) == 1), - a => assert(a.compare0(2, 3) == -1), - a => assert(a.compare0(0, 4) == 0) - ) - } - - it must "work with different indexing bases" in { - readTest(5, 3, 2, 8)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get0(1) == 5), - a => assert(a.withBase(1).get0(4) == 8), - a => assert(a.withBase(-1).get0(-1) == 5), - a => assert(a.withBase(-1).get0(2) == 8), - a => assert(a.withBase(-1).withBase(1).get0(1) == 5), - a => assert(a.withBase(-1).withBase(2).get0(2) == 5), - a => assert(a.withBase(-1).withBase(2).get0(3) == 3) - ) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgentSpec.scala deleted file mode 100644 index f48e98e..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/MergeSortIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -class MergeSortIntArrayItemsAgentSpec - extends BaseDoubleIntArrayItemsAgentSpec( - new MergeSortIntArrayItemsAgent(_, _)) { - typeBehavior[MergeSortIntArrayItemsAgent] - - it must "return correct size for empty array" in { - readTest()()( - a => assert(a.size0 == 0), - a => assert(a.size1 == 0) - ) - } - - it must "return correct size for non-empty items array" in { - readTest(1, 2, 3)(4, 5, 6, 7)( - a => assert(a.size0 == 3), - a => assert(a.size1 == 4) - ) - } - - it must "get proper values" in { - readTest(5, 3, 2, 8)(4, 9, 2, 1)( - a => assert(a.get0(0) == 5), - a => assert(a.get0(1) == 3), - a => assert(a.get0(2) == 2), - a => assert(a.get0(3) == 8), - a => assert(a.get1(0) == 4), - a => assert(a.get1(1) == 9), - a => assert(a.get1(2) == 2), - a => assert(a.get1(3) == 1) - ) - } - - it must "set proper cells" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.set0(3, 1), - _.set1(3, 5), - _.set0(1, 2), - _.set1(1, 0), - _.set0(0, 9), - _.set1(3, 2), - _.set0(3, 7), - _.set1(3, 2) - )(9, 2, 2, 7)(4, 0, 2, 2) - } - - it must "copy proper cells within items (copy0)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy0(1, 0, 2) - )(3, 2, 2, 8)(4, 9, 2, 1) - } - - it must "copy proper cells within items (copy00)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy00(1, 0, 2) - )(3, 2, 2, 8)(4, 9, 2, 1) - } - - it must "copy proper cells within buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy11(1, 0, 2) - )(5, 3, 2, 8)(9, 2, 2, 1) - } - - it must "copy proper cells from items to buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy01(1, 0, 2) - )(5, 3, 2, 8)(3, 2, 2, 1) - } - - it must "copy proper cells from buffer to items" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy10(1, 0, 2) - )(9, 2, 2, 8)(4, 9, 2, 1) - } - - it must "swap proper cells within items (swap0)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap0(3, 0) - )(8, 3, 2, 5)(4, 9, 2, 1) - } - - it must "swap proper cells within items (swap00)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap00(3, 0) - )(8, 3, 2, 5)(4, 9, 2, 1) - } - - it must "swap proper cells within buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap11(3, 0) - )(5, 3, 2, 8)(1, 9, 2, 4) - } - - it must "swap proper cells between items and buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap01(3, 0) - )(5, 3, 2, 4)(8, 9, 2, 1) - } - - it must "swap proper cells between buffer and items" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap10(3, 0) - )(1, 3, 2, 8)(4, 9, 2, 5) - } - - it must "compare values properly" in { - pureTest( - a => assert(a.compare(1, 2) == -1), - a => assert(a.compare(2, 1) == 1), - a => assert(a.compare(1, 1) == 0) - ) - } - - it must "compare cells properly within items (compare0)" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.compare0(0, 1) == 1), - a => assert(a.compare0(2, 3) == -1), - a => assert(a.compare0(0, 4) == 0) - ) - } - - it must "compare cells properly within items (compare00)" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.compare00(0, 1) == 1), - a => assert(a.compare00(2, 3) == -1), - a => assert(a.compare00(0, 4) == 0) - ) - } - - it must "compare cells properly within buffer" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.compare11(0, 1) == -1), - a => assert(a.compare11(2, 3) == 1), - a => assert(a.compare11(0, 4) == 0) - ) - } - - it must "compare cells properly between items and buffer" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.compare01(0, 1) == -1), - a => assert(a.compare01(2, 3) == 1), - a => assert(a.compare01(2, 2) == 0) - ) - } - - it must "compare cells properly between buffer and items" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.compare10(4, 0) == -1), - a => assert(a.compare10(1, 3) == 1), - a => assert(a.compare10(2, 2) == 0) - ) - } - - it must "work with different indexing bases for items" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get0(1) == 5), - a => assert(a.withBase(1).get0(4) == 8), - a => assert(a.withBase(-1).get0(-1) == 5), - a => assert(a.withBase(-1).get0(2) == 8), - a => assert(a.withBase(-1).withBase(1).get0(1) == 5), - a => assert(a.withBase(-1).withBase(2).get0(2) == 5), - a => assert(a.withBase(-1).withBase(2).get0(3) == 3) - ) - } - - it must "work with different indexing bases for buffer" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get1(1) == 4), - a => assert(a.withBase(1).get1(4) == 1), - a => assert(a.withBase(-1).get1(-1) == 4), - a => assert(a.withBase(-1).get1(2) == 1), - a => assert(a.withBase(-1).withBase(1).get1(1) == 4), - a => assert(a.withBase(-1).withBase(2).get1(2) == 4), - a => assert(a.withBase(-1).withBase(2).get1(3) == 9) - ) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgentSpec.scala deleted file mode 100644 index 39639ab..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RadixSortIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -class RadixSortIntArrayItemsAgentSpec - extends BaseDoubleIntArrayItemsAgentSpec( - new RadixSortIntArrayItemsAgent(_, _)) { - typeBehavior[RadixSortIntArrayItemsAgent] - - it must "return correct size for empty array" in { - readTest()()( - a => assert(a.size0 == 0), - a => assert(a.size1 == 0) - ) - } - - it must "return correct size for non-empty items array" in { - readTest(1, 2, 3)(4, 5, 6, 7)( - a => assert(a.size0 == 3), - a => assert(a.size1 == 4) - ) - } - - it must "get proper values" in { - readTest(5, 3, 2, 8)(4, 9, 2, 1)( - a => assert(a.get0(0) == 5), - a => assert(a.get0(1) == 3), - a => assert(a.get0(2) == 2), - a => assert(a.get0(3) == 8), - a => assert(a.get1(0) == 4), - a => assert(a.get1(1) == 9), - a => assert(a.get1(2) == 2), - a => assert(a.get1(3) == 1) - ) - } - - it must "set proper cells" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.set0(3, 1), - _.set1(3, 5), - _.set0(1, 2), - _.set1(1, 0), - _.set0(0, 9), - _.set1(3, 2), - _.set0(3, 7), - _.set1(3, 2) - )(9, 2, 2, 7)(4, 0, 2, 2) - } - - it must "copy proper cells within items (copy0)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy0(1, 0, 2) - )(3, 2, 2, 8)(4, 9, 2, 1) - } - - it must "copy proper cells within items (copy00)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy00(1, 0, 2) - )(3, 2, 2, 8)(4, 9, 2, 1) - } - - it must "copy proper cells within buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy11(1, 0, 2) - )(5, 3, 2, 8)(9, 2, 2, 1) - } - - it must "copy proper cells from items to buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy01(1, 0, 2) - )(5, 3, 2, 8)(3, 2, 2, 1) - } - - it must "copy proper cells from buffer to items" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.copy10(1, 0, 2) - )(9, 2, 2, 8)(4, 9, 2, 1) - } - - it must "swap proper cells within items (swap0)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap0(3, 0) - )(8, 3, 2, 5)(4, 9, 2, 1) - } - - it must "swap proper cells within items (swap00)" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap00(3, 0) - )(8, 3, 2, 5)(4, 9, 2, 1) - } - - it must "swap proper cells within buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap11(3, 0) - )(5, 3, 2, 8)(1, 9, 2, 4) - } - - it must "swap proper cells between items and buffer" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap01(3, 0) - )(5, 3, 2, 4)(8, 9, 2, 1) - } - - it must "swap proper cells between buffer and items" in { - writeTest(5, 3, 2, 8)(4, 9, 2, 1)( - _.swap10(3, 0) - )(1, 3, 2, 8)(4, 9, 2, 5) - } - - it must "return proper key size" in { - pureTest(a => assert(a.keySizeInBits == 32)) - } - - it must "extract slices properly from values" in { - pureTest( - a => assert(a.getItemSlice(123, 1, 3) == 5), - a => assert(a.getItemSlice(1234, 0, 5) == 18), - a => assert(a.getItemSlice(12345, 1, 3) == 4) - ) - } - - it must "extract slices properly from cells" in { - readTest(123, 1234, 12345)(234, 2345, 23456)( - a => assert(a.getItemSlice0(0, 1, 3) == 5), - a => assert(a.getItemSlice0(1, 0, 5) == 18), - a => assert(a.getItemSlice0(2, 1, 3) == 4), - a => assert(a.getItemSlice1(0, 2, 3) == 2), - a => assert(a.getItemSlice1(1, 0, 5) == 9), - a => assert(a.getItemSlice1(2, 3, 3) == 4) - ) - } - - it must "work with different indexing bases for items" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get0(1) == 5), - a => assert(a.withBase(1).get0(4) == 8), - a => assert(a.withBase(-1).get0(-1) == 5), - a => assert(a.withBase(-1).get0(2) == 8), - a => assert(a.withBase(-1).withBase(1).get0(1) == 5), - a => assert(a.withBase(-1).withBase(2).get0(2) == 5), - a => assert(a.withBase(-1).withBase(2).get0(3) == 3) - ) - } - - it must "work with different indexing bases for buffer" in { - readTest(5, 3, 2, 8, 5)(4, 9, 2, 1, 4)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get1(1) == 4), - a => assert(a.withBase(1).get1(4) == 1), - a => assert(a.withBase(-1).get1(-1) == 4), - a => assert(a.withBase(-1).get1(2) == 1), - a => assert(a.withBase(-1).withBase(1).get1(1) == 4), - a => assert(a.withBase(-1).withBase(2).get1(2) == 4), - a => assert(a.withBase(-1).withBase(2).get1(3) == 9) - ) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgentSpec.scala deleted file mode 100644 index 7093b07..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/RecordingComparingIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import java.io.ByteArrayOutputStream - -import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent -import pl.tarsa.sortalgobox.core.crossverify.PureNumberEncoder -import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase - -class RecordingComparingIntArrayItemsAgentSpec extends CommonUnitSpecBase { - typeBehavior[RecordingComparingIntArrayItemsAgent] - - it must "return correct size for empty array" in { - readTest()(a => assert(a.size0 == 0))(Size0.id) - } - - it must "return correct size for non-empty array" in { - readTest(1, 2, 3)(a => assert(a.size0 == 3))(Size0.id) - } - - it must "get proper values" in { - readTest(5, 3, 2, 8)( - a => assert(a.get0(0) == 5), - a => assert(a.get0(1) == 3), - a => assert(a.get0(2) == 2), - a => assert(a.get0(3) == 8) - )(Get0.id, 0, Get0.id, 1, Get0.id, 2, Get0.id, 3) - } - - it must "set proper cells" in { - writeTest(5, 3, 2, 8)( - _.set0(3, 1), - _.set0(1, 2), - _.set0(0, 9), - _.set0(3, 7) - )(9, 2, 2, 7)(Set0.id, 3, Set0.id, 1, Set0.id, 0, Set0.id, 3) - } - - it must "copy proper cells" in { - writeTest(5, 3, 2, 8)( - _.copy0(1, 0, 2) - )(3, 2, 2, 8)(Copy0.id, 1, 0, 2) - } - - it must "swap proper cells" in { - writeTest(5, 3, 2, 8)( - _.swap0(3, 0) - )(8, 3, 2, 5)(Swap0.id, 3, 0) - } - - it must "compare values properly" in { - pureTest( - a => assert(a.compare(1, 2) == -1), - a => assert(a.compare(2, 1) == 1), - a => assert(a.compare(1, 1) == 0) - )(Compare.id, Compare.id, Compare.id) - } - - it must "compare cells properly" in { - readTest(5, 3, 2, 8, 5)( - a => assert(a.compare0(0, 1) == 1), - a => assert(a.compare0(2, 3) == -1), - a => assert(a.compare0(0, 4) == 0) - )(Compare0.id, 0, 1, Compare0.id, 2, 3, Compare0.id, 0, 4) - } - - it must "work with different indexing bases" in { - readTest(5, 3, 2, 8)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get0(1) == 5), - a => assert(a.withBase(1).get0(4) == 8), - a => assert(a.withBase(-1).get0(0) == 3), - a => assert(a.withBase(-1).get0(2) == 8), - a => assert(a.withBase(-1).withBase(1).get0(1) == 5), - a => assert(a.withBase(-1).withBase(2).get0(2) == 5), - a => assert(a.withBase(-1).withBase(2).get0(3) == 3) - )(Seq(1, 4, 0, 2, 1, 2, 3).flatMap(Seq(Get0.id, _)): _*) - } - - def buildRecordingAgent(inputItems: Array[Int]) - : (ByteArrayOutputStream, ComparingItemsAgent[Int]) = { - val recordingStream = new ByteArrayOutputStream() - val recorder = new PureNumberEncoder(recordingStream) - val underlying = new ComparingIntArrayItemsAgent(inputItems) - val recordingAgent = - new RecordingComparingIntArrayItemsAgent(recorder, underlying) - (recordingStream, recordingAgent) - } - - def assertRecordedBytes(recordingStream: ByteArrayOutputStream, - expectedBytes: Seq[Int]): Unit = { - val recordedBytes = recordingStream.toByteArray - assert(recordedBytes.length == expectedBytes.length) - for ((expectedValue, recordedValue) <- expectedBytes.zip(recordedBytes)) { - assert(expectedValue == (recordedValue & 0xFF)) - } - } - - def readTest(inputItems: Int*)( - operations: (ComparingItemsAgent[Int] => Unit)*)( - expectedRecordedBytes: Int*): Unit = { - val (buffer, agent) = buildRecordingAgent(inputItems.toArray) - operations.foreach(_(agent)) - assertRecordedBytes(buffer, expectedRecordedBytes) - } - - def writeTest(inputItems: Int*)( - operations: (ComparingItemsAgent[Int] => Unit)*)(outputItems: Int*)( - expectedRecordedBytes: Int*): Unit = { - val array = inputItems.toArray - val (buffer, agent) = buildRecordingAgent(array) - operations.foreach(_(agent)) - assert(array.toSeq == outputItems) - assertRecordedBytes(buffer, expectedRecordedBytes) - } - - def pureTest(operations: (ComparingItemsAgent[Int] => Unit)*)( - expectedRecordedBytes: Int*): Unit = { - val (buffer, agent) = buildRecordingAgent(null) - operations.foreach(_(agent)) - assertRecordedBytes(buffer, expectedRecordedBytes) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgentSpec.scala deleted file mode 100644 index b7b47fd..0000000 --- a/core/test_scala/pl/tarsa/sortalgobox/core/common/agents/implementations/VerifyingComparingIntArrayItemsAgentSpec.scala +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -package pl.tarsa.sortalgobox.core.common.agents.implementations - -import java.io.{ByteArrayInputStream, InputStream} - -import org.scalatest.exceptions.TestFailedException -import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent -import pl.tarsa.sortalgobox.core.crossverify.{ - PrematureEndOfInputException, - PureNumberDecoder -} -import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase - -class VerifyingComparingIntArrayItemsAgentSpec extends CommonUnitSpecBase { - typeBehavior[VerifyingComparingIntArrayItemsAgent] - - it must "fail for some operations and no recorded bytes" in { - a[PrematureEndOfInputException] mustBe thrownBy { - readTest(1, 2, 3)(_.compare0(1, 2))() - } - } - - it must "fail for no operations and some recorded bytes" in { - a[TestFailedException] mustBe thrownBy { - readTest(1, 2, 3)()(Get0.id, 2) - } - } - - it must "fail for mismatched operations and recorded bytes" in { - a[TestFailedException] mustBe thrownBy { - readTest(1, 2, 3)(_.swap0(1, 0))(Compare0.id, 3) - } - } - - it must "return correct size for empty array" in { - readTest()(a => assert(a.size0 == 0))(Size0.id) - } - - it must "return correct size for non-empty array" in { - readTest(1, 2, 3)(a => assert(a.size0 == 3))(Size0.id) - } - - it must "get proper values" in { - readTest(5, 3, 2, 8)( - a => assert(a.get0(0) == 5), - a => assert(a.get0(1) == 3), - a => assert(a.get0(2) == 2), - a => assert(a.get0(3) == 8) - )(Get0.id, 0, Get0.id, 1, Get0.id, 2, Get0.id, 3) - } - - it must "set proper cells" in { - writeTest(5, 3, 2, 8)( - _.set0(3, 1), - _.set0(1, 2), - _.set0(0, 9), - _.set0(3, 7) - )(9, 2, 2, 7)(Set0.id, 3, Set0.id, 1, Set0.id, 0, Set0.id, 3) - } - - it must "copy proper cells" in { - writeTest(5, 3, 2, 8)( - _.copy0(1, 0, 2) - )(3, 2, 2, 8)(Copy0.id, 1, 0, 2) - } - - it must "swap proper cells" in { - writeTest(5, 3, 2, 8)( - _.swap0(3, 0) - )(8, 3, 2, 5)(Swap0.id, 3, 0) - } - - it must "compare values properly" in { - pureTest( - a => assert(a.compare(1, 2) == -1), - a => assert(a.compare(2, 1) == 1), - a => assert(a.compare(1, 1) == 0) - )(Compare.id, Compare.id, Compare.id) - } - - it must "compare cells properly" in { - readTest(5, 3, 2, 8, 5)( - a => assert(a.compare0(0, 1) == 1), - a => assert(a.compare0(2, 3) == -1), - a => assert(a.compare0(0, 4) == 0) - )(Compare0.id, 0, 1, Compare0.id, 2, 3, Compare0.id, 0, 4) - } - - it must "work with different indexing bases" in { - readTest(5, 3, 2, 8)( - a => assert(a.withBase(0) eq a), - a => assert(a.withBase(1).get0(1) == 5), - a => assert(a.withBase(1).get0(4) == 8), - a => assert(a.withBase(-1).get0(0) == 3), - a => assert(a.withBase(-1).get0(2) == 8), - a => assert(a.withBase(-1).withBase(1).get0(1) == 5), - a => assert(a.withBase(-1).withBase(2).get0(2) == 5), - a => assert(a.withBase(-1).withBase(2).get0(3) == 3) - )(Seq(1, 4, 0, 2, 1, 2, 3).flatMap(Seq(Get0.id, _)): _*) - } - - def verify(condition: Boolean): Unit = { - if (!condition) { - fail() - } - } - - def buildRecordingAgent( - inputItems: Array[Int], - recordedBytes: Seq[Int]): (InputStream, ComparingItemsAgent[Int]) = { - val recordingStream = - new ByteArrayInputStream(recordedBytes.map(_.toByte).toArray) - val replayer = new PureNumberDecoder(recordingStream) - val underlying = new ComparingIntArrayItemsAgent(inputItems) - val recordingAgent = - new VerifyingComparingIntArrayItemsAgent(replayer, underlying, verify) - (recordingStream, recordingAgent) - } - - def readTest(inputItems: Int*)( - operations: (ComparingItemsAgent[Int] => Unit)*)( - recordedBytes: Int*): Unit = { - val (stream, agent) = buildRecordingAgent(inputItems.toArray, recordedBytes) - operations.foreach(_(agent)) - assert(stream.read() == -1) - - } - - def writeTest(inputItems: Int*)( - operations: (ComparingItemsAgent[Int] => Unit)*)(outputItems: Int*)( - recordedBytes: Int*): Unit = { - val array = inputItems.toArray - val (stream, agent) = buildRecordingAgent(array, recordedBytes) - operations.foreach(_(agent)) - assert(array.toSeq == outputItems) - assert(stream.read() == -1) - } - - def pureTest(operations: (ComparingItemsAgent[Int] => Unit)*)( - recordedBytes: Int*): Unit = { - val (stream, agent) = buildRecordingAgent(null, recordedBytes) - operations.foreach(_(agent)) - assert(stream.read() == -1) - } -} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgentSpecBase.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgentSpecBase.scala new file mode 100644 index 0000000..dd4fb30 --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/ItemsAgentSpecBase.scala @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import org.scalactic.source.Position +import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + NumericItemsOperations +} +import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase + +import scala.reflect.runtime.universe.TypeTag + +abstract class ItemsAgentSpecBase[TestedClass: TypeTag] + extends CommonUnitSpecBase { + typeBehavior[TestedClass] + + it must "return size for empty buffer" in { + readTestComparable() { (agent, buf) => + agent.size(buf) mustBe 0 + }(Size.id, bufferId, 0 * 2) + readTestNumeric() { (agent, buf) => + agent.size(buf) mustBe 0 + }(Size.id, bufferId, 0 * 2) + } + + it must "return size for non-empty buffer" in { + readTestComparable(5, 2, 3, 8) { (agent, buf) => + agent.size(buf) mustBe 4 + }(Size.id, bufferId, 4 * 2) + readTestNumeric(5, 2, 3, 8) { (agent, buf) => + agent.size(buf) mustBe 4 + }(Size.id, bufferId, 4 * 2) + } + + it must "get items" in { + readTestComparable(5, 2, 3, 8) { (agent, buf) => + agent.get(buf, 0) mustBe 5 + agent.get(buf, 1) mustBe 2 + agent.get(buf, 2) mustBe 3 + agent.get(buf, 3) mustBe 8 + }((0 to 3).flatMap(i => Seq(Get.id, bufferId, i * 2)): _*) + readTestNumeric(5, 2, 3, 8) { (agent, buf) => + agent.get(buf, 0) mustBe 5 + agent.get(buf, 1) mustBe 2 + agent.get(buf, 2) mustBe 3 + agent.get(buf, 3) mustBe 8 + }((0 to 3).flatMap(i => Seq(Get.id, bufferId, i * 2)): _*) + } + + it must "set items" in { + writeTestComparable(5, 3, 2, 8) { (agent, buf) => + agent.set(buf, 3, 1) + agent.set(buf, 1, 2) + agent.set(buf, 0, 9) + agent.set(buf, 3, 7) + }(9, 2, 2, 7)( + Seq(3, 1, 0, 3).flatMap(i => Seq(Set.id, bufferId, i * 2)): _*) + writeTestNumeric(5, 3, 2, 8) { (agent, buf) => + agent.set(buf, 3, 1) + agent.set(buf, 1, 2) + agent.set(buf, 0, 9) + agent.set(buf, 3, 7) + }(9, 2, 2, 7)( + Seq(3, 1, 0, 3).flatMap(i => Seq(Set.id, bufferId, i * 2)): _*) + } + + it must "swap items" in { + writeTestComparable(5, 3, 2, 8) { (agent, buf) => + agent.swap(buf, 3, 0) + }(8, 3, 2, 5)(Swap.id, bufferId, 3 * 2, 0 * 2) + writeTestNumeric(5, 3, 2, 8) { (agent, buf) => + agent.swap(buf, 3, 0) + }(8, 3, 2, 5)(Swap.id, bufferId, 3 * 2, 0 * 2) + } + + it must "return numeric item size in bits" in { + readTestNumeric() { (agent, buf) => + agent.itemBitsSize(buf) mustBe 32 + }(ItemBitsSize.id, bufferId, 32) + } + + it must "convert numeric item to Long" in { + pureTestNumeric { (agent, ops) => + agent.asLong(ops, -5) mustBe -5L + agent.asLong(ops, 5) mustBe 5L + }(AsLong.id, -5 * -2 - 1, AsLong.id, 5 * 2) + readTestNumeric(-5, 5) { (agent, buf) => + agent.asLongI(buf, 0) mustBe -5L + }(Seq(Get.id, bufferId, 0 * 2, AsLong.id, -5 * -2 - 1): _*) + readTestNumeric(-5, 5) { (agent, buf) => + agent.asLongI(buf, 1) mustBe 5L + }(Seq(Get.id, bufferId, 1 * 2, AsLong.id, 5 * 2): _*) + } + + it must "get slice of numeric item" in { + pureTestNumeric { (agent, ops) => + agent.getSlice(ops, 99, 2, 4) mustBe 8 + agent.getSlice(ops, -99, 2, 4) mustBe 7 + }(GetSlice.id, 2, 4, 8 * 2, GetSlice.id, 2, 4, 7 * 2) + readTestNumeric(-5, 5) { (agent, buf) => + agent.getSliceI(buf, 0, 1, 3) mustBe 5 + agent.getSliceI(buf, 1, 2, 3) mustBe 1 + }(Seq(Get.id, bufferId, 0 * 2, GetSlice.id, 1, 3, 5 * 2) ++ + Seq(Get.id, bufferId, 1 * 2, GetSlice.id, 2, 3, 1 * 2): _*) + } + + it must "compare Comparable items" in { + def opsTest(body: (ItemsAgent, ComparableItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + readTestComparable(5, 3, 2, 8, 5) { (agent, buf) => + body(agent, buf.itemsOps) + }(expectedRecordedBytes: _*) + } + + def bufTest( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit, + expectedRecordedBytes: Seq[Int])(implicit pos: Position): Unit = { + readTestComparable(5, 3, 2, 8, 5) { (agent, buf) => + body(agent, buf) + }(expectedRecordedBytes: _*) + } + + opsTest(_.compareEq(_, 1, 2) mustBe false)(CompareEq.id, 0) + opsTest(_.compareEq(_, 1, 1) mustBe true)(CompareEq.id, 1) + opsTest(_.compareEq(_, 2, 1) mustBe false)(CompareEq.id, 0) + + bufTest(_.compareEqI(_, 0, 1) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareEq.id, 0)) + bufTest(_.compareEqI(_, 0, 0) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareEq.id, 1)) + bufTest(_.compareEqI(_, 1, 0) mustBe false, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareEq.id, 0)) + + bufTest(_.compareEqIV(_, 0, 4) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + bufTest(_.compareEqIV(_, 0, 5) mustBe true, + Seq(Get.id, bufferId, 0, CompareEq.id, 1)) + bufTest(_.compareEqIV(_, 0, 6) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + + bufTest(_.compareEqVI(_, 4, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + bufTest(_.compareEqVI(_, 5, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareEq.id, 1)) + bufTest(_.compareEqVI(_, 6, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + + opsTest(_.compareGt(_, 1, 2) mustBe false)(CompareGt.id, 0) + opsTest(_.compareGt(_, 1, 1) mustBe false)(CompareGt.id, 0) + opsTest(_.compareGt(_, 2, 1) mustBe true)(CompareGt.id, 1) + + bufTest(_.compareGtI(_, 0, 1) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareGt.id, 1)) + bufTest(_.compareGtI(_, 0, 0) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtI(_, 1, 0) mustBe false, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareGt.id, 0)) + + bufTest(_.compareGtIV(_, 0, 4) mustBe true, + Seq(Get.id, bufferId, 0, CompareGt.id, 1)) + bufTest(_.compareGtIV(_, 0, 5) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtIV(_, 0, 6) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + + bufTest(_.compareGtVI(_, 4, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtVI(_, 5, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtVI(_, 6, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareGt.id, 1)) + + opsTest(_.compareGte(_, 1, 2) mustBe false)(CompareGte.id, 0) + opsTest(_.compareGte(_, 1, 1) mustBe true)(CompareGte.id, 1) + opsTest(_.compareGte(_, 2, 1) mustBe true)(CompareGte.id, 1) + + bufTest(_.compareGteI(_, 0, 1) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareGte.id, 1)) + bufTest(_.compareGteI(_, 0, 0) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteI(_, 1, 0) mustBe false, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareGte.id, 0)) + + bufTest(_.compareGteIV(_, 0, 4) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteIV(_, 0, 5) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteIV(_, 0, 6) mustBe false, + Seq(Get.id, bufferId, 0, CompareGte.id, 0)) + + bufTest(_.compareGteVI(_, 4, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareGte.id, 0)) + bufTest(_.compareGteVI(_, 5, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteVI(_, 6, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + + opsTest(_.compareLt(_, 1, 2) mustBe true)(CompareLt.id, 1) + opsTest(_.compareLt(_, 1, 1) mustBe false)(CompareLt.id, 0) + opsTest(_.compareLt(_, 2, 1) mustBe false)(CompareLt.id, 0) + + bufTest(_.compareLtI(_, 0, 1) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareLt.id, 0)) + bufTest(_.compareLtI(_, 0, 0) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtI(_, 1, 0) mustBe true, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareLt.id, 1)) + + bufTest(_.compareLtIV(_, 0, 4) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtIV(_, 0, 5) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtIV(_, 0, 6) mustBe true, + Seq(Get.id, bufferId, 0, CompareLt.id, 1)) + + bufTest(_.compareLtVI(_, 4, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareLt.id, 1)) + bufTest(_.compareLtVI(_, 5, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtVI(_, 6, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + + opsTest(_.compareLte(_, 1, 2) mustBe true)(CompareLte.id, 1) + opsTest(_.compareLte(_, 1, 1) mustBe true)(CompareLte.id, 1) + opsTest(_.compareLte(_, 2, 1) mustBe false)(CompareLte.id, 0) + + bufTest(_.compareLteI(_, 0, 1) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareLte.id, 0)) + bufTest(_.compareLteI(_, 0, 0) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteI(_, 1, 0) mustBe true, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareLte.id, 1)) + + bufTest(_.compareLteIV(_, 0, 4) mustBe false, + Seq(Get.id, bufferId, 0, CompareLte.id, 0)) + bufTest(_.compareLteIV(_, 0, 5) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteIV(_, 0, 6) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + + bufTest(_.compareLteVI(_, 4, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteVI(_, 5, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteVI(_, 6, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareLte.id, 0)) + } + + it must "compare Numeric items" in { + def opsTest(body: (ItemsAgent, NumericItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + readTestNumeric(5, 3, 2, 8, 5) { (agent, buf) => + body(agent, buf.itemsOps) + }(expectedRecordedBytes: _*) + } + + def bufTest( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit, + expectedRecordedBytes: Seq[Int])(implicit pos: Position): Unit = { + readTestNumeric(5, 3, 2, 8, 5) { (agent, buf) => + body(agent, buf) + }(expectedRecordedBytes: _*) + } + + opsTest(_.compareEq(_, 1, 2) mustBe false)(CompareEq.id, 0) + opsTest(_.compareEq(_, 1, 1) mustBe true)(CompareEq.id, 1) + opsTest(_.compareEq(_, 2, 1) mustBe false)(CompareEq.id, 0) + + bufTest(_.compareEqI(_, 0, 1) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareEq.id, 0)) + bufTest(_.compareEqI(_, 0, 0) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareEq.id, 1)) + bufTest(_.compareEqI(_, 1, 0) mustBe false, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareEq.id, 0)) + + bufTest(_.compareEqIV(_, 0, 4) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + bufTest(_.compareEqIV(_, 0, 5) mustBe true, + Seq(Get.id, bufferId, 0, CompareEq.id, 1)) + bufTest(_.compareEqIV(_, 0, 6) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + + bufTest(_.compareEqVI(_, 4, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + bufTest(_.compareEqVI(_, 5, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareEq.id, 1)) + bufTest(_.compareEqVI(_, 6, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareEq.id, 0)) + + opsTest(_.compareGt(_, 1, 2) mustBe false)(CompareGt.id, 0) + opsTest(_.compareGt(_, 1, 1) mustBe false)(CompareGt.id, 0) + opsTest(_.compareGt(_, 2, 1) mustBe true)(CompareGt.id, 1) + + bufTest(_.compareGtI(_, 0, 1) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareGt.id, 1)) + bufTest(_.compareGtI(_, 0, 0) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtI(_, 1, 0) mustBe false, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareGt.id, 0)) + + bufTest(_.compareGtIV(_, 0, 4) mustBe true, + Seq(Get.id, bufferId, 0, CompareGt.id, 1)) + bufTest(_.compareGtIV(_, 0, 5) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtIV(_, 0, 6) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + + bufTest(_.compareGtVI(_, 4, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtVI(_, 5, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareGt.id, 0)) + bufTest(_.compareGtVI(_, 6, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareGt.id, 1)) + + opsTest(_.compareGte(_, 1, 2) mustBe false)(CompareGte.id, 0) + opsTest(_.compareGte(_, 1, 1) mustBe true)(CompareGte.id, 1) + opsTest(_.compareGte(_, 2, 1) mustBe true)(CompareGte.id, 1) + + bufTest(_.compareGteI(_, 0, 1) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareGte.id, 1)) + bufTest(_.compareGteI(_, 0, 0) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteI(_, 1, 0) mustBe false, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareGte.id, 0)) + + bufTest(_.compareGteIV(_, 0, 4) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteIV(_, 0, 5) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteIV(_, 0, 6) mustBe false, + Seq(Get.id, bufferId, 0, CompareGte.id, 0)) + + bufTest(_.compareGteVI(_, 4, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareGte.id, 0)) + bufTest(_.compareGteVI(_, 5, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + bufTest(_.compareGteVI(_, 6, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareGte.id, 1)) + + opsTest(_.compareLt(_, 1, 2) mustBe true)(CompareLt.id, 1) + opsTest(_.compareLt(_, 1, 1) mustBe false)(CompareLt.id, 0) + opsTest(_.compareLt(_, 2, 1) mustBe false)(CompareLt.id, 0) + + bufTest(_.compareLtI(_, 0, 1) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareLt.id, 0)) + bufTest(_.compareLtI(_, 0, 0) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtI(_, 1, 0) mustBe true, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareLt.id, 1)) + + bufTest(_.compareLtIV(_, 0, 4) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtIV(_, 0, 5) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtIV(_, 0, 6) mustBe true, + Seq(Get.id, bufferId, 0, CompareLt.id, 1)) + + bufTest(_.compareLtVI(_, 4, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareLt.id, 1)) + bufTest(_.compareLtVI(_, 5, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + bufTest(_.compareLtVI(_, 6, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareLt.id, 0)) + + opsTest(_.compareLte(_, 1, 2) mustBe true)(CompareLte.id, 1) + opsTest(_.compareLte(_, 1, 1) mustBe true)(CompareLte.id, 1) + opsTest(_.compareLte(_, 2, 1) mustBe false)(CompareLte.id, 0) + + bufTest(_.compareLteI(_, 0, 1) mustBe false, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 2, CompareLte.id, 0)) + bufTest(_.compareLteI(_, 0, 0) mustBe true, + Seq(Get.id, bufferId, 0, Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteI(_, 1, 0) mustBe true, + Seq(Get.id, bufferId, 2, Get.id, bufferId, 0, CompareLte.id, 1)) + + bufTest(_.compareLteIV(_, 0, 4) mustBe false, + Seq(Get.id, bufferId, 0, CompareLte.id, 0)) + bufTest(_.compareLteIV(_, 0, 5) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteIV(_, 0, 6) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + + bufTest(_.compareLteVI(_, 4, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteVI(_, 5, 0) mustBe true, + Seq(Get.id, bufferId, 0, CompareLte.id, 1)) + bufTest(_.compareLteVI(_, 6, 0) mustBe false, + Seq(Get.id, bufferId, 0, CompareLte.id, 0)) + } + + def pureTestComparable( + body: (ItemsAgent, ComparableItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit + + def pureTestNumeric(body: (ItemsAgent, NumericItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit + + def readTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit + + def readTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit + + def writeTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + outputItems: Int*)(expectedRecordedBytes: Int*)( + implicit pos: Position): Unit + + def writeTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)(outputItems: Int*)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit + + // TODO make a def? + val bufferId: Byte = 11 +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgentSpec.scala new file mode 100644 index 0000000..9c2024f --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/PlainItemsAgentSpec.scala @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import org.scalactic.source.Position +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + ItemsOperations, + NumericItemsOperations +} + +class PlainItemsAgentSpec extends ItemsAgentSpecBase[PlainItemsAgent.type] { + private val agent: ItemsAgent = PlainItemsAgent + + override def pureTestComparable( + body: (ItemsAgent, ComparableItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = + body(agent, ItemsOperations.intOps) + + override def pureTestNumeric( + body: (ItemsAgent, NumericItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = + body(agent, ItemsOperations.intOps) + + override def readTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = + body(agent, ComparableItemsBuffer[Int](5, inputItems.toArray, 0)) + + override def readTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = + body(agent, NumericItemsBuffer(5, inputItems.toArray, 0)) + + override def writeTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + outputItems: Int*)(expectedRecordedBytes: Int*)( + implicit pos: Position): Unit = { + val itemsArray = inputItems.toArray + body(agent, ComparableItemsBuffer[Int](5, itemsArray, 0)) + itemsArray.toSeq mustBe outputItems withClue "final array contents invalid" + } + + override def writeTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)(outputItems: Int*)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + val itemsArray = inputItems.toArray + body(agent, NumericItemsBuffer(5, itemsArray, 0)) + itemsArray.toSeq mustBe outputItems withClue "final array contents invalid" + } +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgentSpec.scala new file mode 100644 index 0000000..a0da0ed --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/RecordingItemsAgentSpec.scala @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import java.io.ByteArrayOutputStream + +import org.scalactic.source.Position +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + ItemsOperations, + NumericItemsOperations +} +import pl.tarsa.sortalgobox.core.crossverify.PureNumberEncoder + +class RecordingItemsAgentSpec extends ItemsAgentSpecBase[RecordingItemsAgent] { + override def pureTestComparable( + body: (ItemsAgent, ComparableItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + val (outputStream, agent) = buildRecordingAgent + body(agent, ItemsOperations.intOps) + assertRecordedBytes(outputStream, expectedRecordedBytes) + } + + override def pureTestNumeric( + body: (ItemsAgent, NumericItemsOperations[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + val (outputStream, agent) = buildRecordingAgent + body(agent, ItemsOperations.intOps) + assertRecordedBytes(outputStream, expectedRecordedBytes) + } + + override def readTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + val (outputStream, agent) = buildRecordingAgent + body(agent, ComparableItemsBuffer[Int](bufferId, inputItems.toArray, 0)) + assertRecordedBytes(outputStream, expectedRecordedBytes) + } + + override def readTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + val (outputStream, agent) = buildRecordingAgent + body(agent, NumericItemsBuffer(bufferId, inputItems.toArray, 0)) + assertRecordedBytes(outputStream, expectedRecordedBytes) + } + + override def writeTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + outputItems: Int*)(expectedRecordedBytes: Int*)( + implicit pos: Position): Unit = { + val array = inputItems.toArray + val (stream, agent) = buildRecordingAgent + body(agent, ComparableItemsBuffer[Int](bufferId, array, 0)) + array.toSeq mustBe outputItems withClue "final array contents invalid" + assertRecordedBytes(stream, expectedRecordedBytes) + } + + override def writeTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)(outputItems: Int*)( + expectedRecordedBytes: Int*)(implicit pos: Position): Unit = { + val array = inputItems.toArray + val (stream, agent) = buildRecordingAgent + body(agent, NumericItemsBuffer(bufferId, array, 0)) + array.toSeq mustBe outputItems withClue "final array contents invalid" + assertRecordedBytes(stream, expectedRecordedBytes) + } + + private def buildRecordingAgent: (ByteArrayOutputStream, ItemsAgent) = { + val recordingStream = new ByteArrayOutputStream() + val recorder = new PureNumberEncoder(recordingStream) + val recordingAgent = new RecordingItemsAgent(recorder) + (recordingStream, recordingAgent) + } + + private def assertRecordedBytes( + recordingStream: ByteArrayOutputStream, + expectedBytes: Seq[Int])(implicit pos: Position): Unit = { + val recordedBytes = recordingStream.toByteArray + recordedBytes.length mustBe expectedBytes.length withClue + "recorded bytes number incorrect" + forAll(expectedBytes.zip(recordedBytes)) { + case (expectedValue, recordedValue) => + expectedValue mustBe (recordedValue & 0xFF) + } withClue "recorded bytes content incorrect" + } +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgentSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgentSpec.scala new file mode 100644 index 0000000..267495b --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/agents/VerifyingItemsAgentSpec.scala @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.agents + +import java.io.{ByteArrayInputStream, InputStream} + +import org.scalactic.source.Position +import org.scalatest.exceptions.TestFailedException +import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ +import pl.tarsa.sortalgobox.core.common.items.buffers.{ + ComparableItemsBuffer, + NumericItemsBuffer +} +import pl.tarsa.sortalgobox.core.common.items.operations.{ + ComparableItemsOperations, + ItemsOperations, + NumericItemsOperations +} +import pl.tarsa.sortalgobox.core.crossverify.{ + PrematureEndOfInputException, + PureNumberDecoder +} + +class VerifyingItemsAgentSpec extends ItemsAgentSpecBase[VerifyingItemsAgent] { + + it must "fail for some operations and no recorded bytes" in { + a[PrematureEndOfInputException] mustBe thrownBy { + readTestComparable(1, 2, 3) { (agent, buf) => + agent.compareEqI(buf, 1, 2) + }() + } + } + + it must "fail for no operations and some recorded bytes" in { + a[TestFailedException] mustBe thrownBy { + readTestComparable(1, 2, 3)((_, _) => ())(Get.id, 2) + } + } + + it must "fail for mismatched operations and recorded bytes" in { + a[TestFailedException] mustBe thrownBy { + readTestComparable(1, 2, 3) { (agent, buf) => + agent.swap(buf, 1, 0) + }(CompareEq.id, 3) + } + } + + override def pureTestComparable( + body: (ItemsAgent, ComparableItemsOperations[Int]) => Unit)( + recordedBytes: Int*)(implicit pos: Position): Unit = { + val (stream, agent) = buildVerifyingAgent(recordedBytes) + body(agent, ItemsOperations.intOps) + stream.read() mustBe -1 + } + + override def pureTestNumeric( + body: (ItemsAgent, NumericItemsOperations[Int]) => Unit)( + recordedBytes: Int*)(implicit pos: Position): Unit = { + val (stream, agent) = buildVerifyingAgent(recordedBytes) + body(agent, ItemsOperations.intOps) + stream.read() mustBe -1 + } + + override def readTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + recordedBytes: Int*)(implicit pos: Position): Unit = { + val (stream, agent) = buildVerifyingAgent(recordedBytes) + body(agent, ComparableItemsBuffer[Int](bufferId, inputItems.toArray, 0)) + stream.read() mustBe -1 + } + + override def readTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)(recordedBytes: Int*)( + implicit pos: Position): Unit = { + val (stream, agent) = buildVerifyingAgent(recordedBytes) + body(agent, NumericItemsBuffer(bufferId, inputItems.toArray, 0)) + stream.read() mustBe -1 + } + + override def writeTestComparable(inputItems: Int*)( + body: (ItemsAgent, ComparableItemsBuffer[Int]) => Unit)( + outputItems: Int*)(recordedBytes: Int*)(implicit pos: Position): Unit = { + val array = inputItems.toArray + val (stream, agent) = buildVerifyingAgent(recordedBytes) + body(agent, ComparableItemsBuffer[Int](bufferId, array, 0)) + array.toSeq mustBe outputItems withClue "final array contents invalid" + stream.read() mustBe -1 + } + + override def writeTestNumeric(inputItems: Int*)( + body: (ItemsAgent, NumericItemsBuffer[Int]) => Unit)(outputItems: Int*)( + recordedBytes: Int*)(implicit pos: Position): Unit = { + val array = inputItems.toArray + val (stream, agent) = buildVerifyingAgent(recordedBytes) + body(agent, NumericItemsBuffer(bufferId, array, 0)) + array.toSeq mustBe outputItems withClue "final array contents invalid" + stream.read() mustBe -1 + } + + private def buildVerifyingAgent(recordedBytes: Seq[Int])( + implicit pos: Position): (InputStream, ItemsAgent) = { + val recordingStream = + new ByteArrayInputStream(recordedBytes.map(_.toByte).toArray) + val replayer = new PureNumberDecoder(recordingStream) + val recordingAgent = new VerifyingItemsAgent(replayer, verify) + (recordingStream, recordingAgent) + } + + private def verify(condition: Boolean)(implicit pos: Position): Unit = { + if (!condition) { + fail("verification failed in verifying agent ") + } + } +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBufferSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBufferSpec.scala new file mode 100644 index 0000000..4e0c432 --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/ComparableItemsBufferSpec.scala @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.buffers + +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase + +import scala.reflect.ClassTag +import scala.reflect.runtime.universe.TypeTag + +class ComparableItemsBufferSpec extends CommonUnitSpecBase { + + new Test[Byte](5, 2, 3, 8)(2, 8, 3, 5).register("Byte") + + new Test[Short](5, 2, 3, 8)(2, 8, 3, 5).register("Short") + + new Test[Int](5, 2, 3, 8)(2, 8, 3, 5).register("Int") + + new Test[Long](5, 2, 3, 8)(2, 8, 3, 5).register("Long") + + new Test[String]("c", "a", "b", "d")("a", "d", "b", "c").register("String") + + class Test[@specialized(Group) Item: Ordering: ClassTag: TypeTag]( + before: Item*)(after: Item*) { + def register(typeName: String): Unit = { + typeBehavior[ComparableItemsBuffer[Item]] + + it must s"correctly handle $typeName buffer with base 0" in { + val array = before.toArray.clone() + val buffer = ComparableItemsBuffer(5, array, 0) + + buffer.id mustBe 5 + buffer.base mustBe 0 + buffer.length mustBe array.length + + array.indices.foreach { i => + buffer.get(i) mustBe array(i) + } + + val tmp1 = buffer.get(0) + val tmp2 = buffer.get(1) + val tmp3 = buffer.get(3) + buffer.set(0, tmp2) + buffer.set(1, tmp3) + buffer.set(3, tmp1) + + array must contain theSameElementsInOrderAs after + + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { buffer.get(-1) } + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { + buffer.get(array.length) + } + } + + it must s"correctly handle $typeName buffer with base 1" in { + val array = before.toArray.clone() + val buffer = ComparableItemsBuffer(5, array, 1) + + buffer.id mustBe 5 + buffer.base mustBe 1 + buffer.length mustBe array.length + + array.indices.foreach { i => + buffer.get(i + 1) mustBe array(i) + } + + val tmp1 = buffer.get(1) + val tmp2 = buffer.get(2) + val tmp3 = buffer.get(4) + buffer.set(1, tmp2) + buffer.set(2, tmp3) + buffer.set(4, tmp1) + + array must contain theSameElementsInOrderAs after + + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { buffer.get(0) } + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { + buffer.get(array.length + 1) + } + } + } + } +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBufferSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBufferSpec.scala new file mode 100644 index 0000000..ac547c8 --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/buffers/NumericItemsBufferSpec.scala @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.buffers + +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.buffers.NumericItemsBuffer.Evidence +import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase + +import scala.reflect.ClassTag +import scala.reflect.runtime.universe._ + +class NumericItemsBufferSpec extends CommonUnitSpecBase { + + new Test[Byte](5, 2, 3, 8)(2, 8, 3, 5).register("Byte") + + new Test[Short](5, 2, 3, 8)(2, 8, 3, 5).register("Short") + + new Test[Int](5, 2, 3, 8)(2, 8, 3, 5).register("Int") + + new Test[Long](5, 2, 3, 8)(2, 8, 3, 5).register("Long") + + class Test[@specialized(Group) Item: Evidence: ClassTag: TypeTag]( + before: Item*)(after: Item*) { + def register(typeName: String): Unit = { + typeBehavior[NumericItemsBuffer[Item]] + + it must s"correctly handle $typeName buffer with base 0" in { + val array = before.toArray.clone() + val buffer = NumericItemsBuffer(5, array, 0) + + buffer.id mustBe 5 + buffer.base mustBe 0 + buffer.length mustBe array.length + + array.indices.foreach { i => + buffer.get(i) mustBe array(i) + } + + val tmp1 = buffer.get(0) + val tmp2 = buffer.get(1) + val tmp3 = buffer.get(3) + buffer.set(0, tmp2) + buffer.set(1, tmp3) + buffer.set(3, tmp1) + + array must contain theSameElementsInOrderAs after + + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { buffer.get(-1) } + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { + buffer.get(array.length) + } + } + + it must s"correctly handle $typeName buffer with base 1" in { + val array = before.toArray.clone() + val buffer = NumericItemsBuffer(5, array, 1) + + buffer.id mustBe 5 + buffer.base mustBe 1 + buffer.length mustBe array.length + + array.indices.foreach { i => + buffer.get(i + 1) mustBe array(i) + } + + val tmp1 = buffer.get(1) + val tmp2 = buffer.get(2) + val tmp3 = buffer.get(4) + buffer.set(1, tmp2) + buffer.set(2, tmp3) + buffer.set(4, tmp1) + + array must contain theSameElementsInOrderAs after + + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { buffer.get(0) } + an[ArrayIndexOutOfBoundsException] mustBe thrownBy { + buffer.get(array.length + 1) + } + } + } + } +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperationsSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperationsSpec.scala new file mode 100644 index 0000000..23c531d --- /dev/null +++ b/core/test_scala/pl/tarsa/sortalgobox/core/common/items/operations/ItemsOperationsSpec.scala @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ +package pl.tarsa.sortalgobox.core.common.items.operations + +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase + +import scala.reflect.runtime.universe.TypeTag + +class ItemsOperationsSpec extends CommonUnitSpecBase { + typeBehavior[ComparableItemsOperations[String]] + + it must "correctly compare String values" in { + val itemsOps = ItemsOperations.orderedItemsOps[String] + + itemsOps.compareEq("aa", "aa") mustBe true + itemsOps.compareEq("aa", "bb") mustBe false + itemsOps.compareEq("bb", "aa") mustBe false + + itemsOps.compareGt("aa", "aa") mustBe false + itemsOps.compareGt("aa", "bb") mustBe false + itemsOps.compareGt("bb", "aa") mustBe true + + itemsOps.compareGte("aa", "aa") mustBe true + itemsOps.compareGte("aa", "bb") mustBe false + itemsOps.compareGte("bb", "aa") mustBe true + + itemsOps.compareLt("aa", "aa") mustBe false + itemsOps.compareLt("aa", "bb") mustBe true + itemsOps.compareLt("bb", "aa") mustBe false + + itemsOps.compareLte("aa", "aa") mustBe true + itemsOps.compareLte("aa", "bb") mustBe true + itemsOps.compareLte("bb", "aa") mustBe false + } + + new NumericTest[Byte](ItemsOperations.bytesOps, -5, 5)(ops => { + ops.bitsSize mustBe 8 + + ops.asLong(5) mustBe 5L + ops.asLong(-5) mustBe -5L + + ops.getSlice(99, 2, 4) mustBe 8 + ops.getSlice(-99, 2, 4) mustBe 7 + }).register("Byte") + + new NumericTest[Short](ItemsOperations.shortOps, -5, 5)(ops => { + ops.bitsSize mustBe 16 + + ops.asLong(5) mustBe 5L + ops.asLong(-5) mustBe -5L + + ops.getSlice(99, 2, 4) mustBe 8 + ops.getSlice(-99, 2, 4) mustBe 7 + }).register("Short") + + new NumericTest[Int](ItemsOperations.intOps, -5, 5)(ops => { + ops.bitsSize mustBe 32 + + ops.asLong(5) mustBe 5L + ops.asLong(-5) mustBe -5L + + ops.getSlice(99, 2, 4) mustBe 8 + ops.getSlice(-99, 2, 4) mustBe 7 + }).register("Int") + + new NumericTest[Long](ItemsOperations.longOps, -5, 5)(ops => { + ops.bitsSize mustBe 64 + + ops.asLong(5) mustBe 5L + ops.asLong(-5) mustBe -5L + + ops.getSlice(99, 2, 4) mustBe 8 + ops.getSlice(-99, 2, 4) mustBe 7 + }).register("Long") + + class NumericTest[@specialized(Group) Item: TypeTag]( + itemsOps: NumericItemsOperations[Item], + lower: Item, + higher: Item)(specializedTests: NumericItemsOperations[Item] => Unit) { + def register(typeName: String): Unit = { + typeBehavior[NumericItemsOperations[Item]] + + it must s"correctly compare $typeName values" in { + itemsOps.compareEq(lower, lower) mustBe true + itemsOps.compareEq(lower, higher) mustBe false + itemsOps.compareEq(higher, lower) mustBe false + + itemsOps.compareGt(lower, lower) mustBe false + itemsOps.compareGt(lower, higher) mustBe false + itemsOps.compareGt(higher, lower) mustBe true + + itemsOps.compareGte(lower, lower) mustBe true + itemsOps.compareGte(lower, higher) mustBe false + itemsOps.compareGte(higher, lower) mustBe true + + itemsOps.compareLt(lower, lower) mustBe false + itemsOps.compareLt(lower, higher) mustBe true + itemsOps.compareLt(higher, lower) mustBe false + + itemsOps.compareLte(lower, lower) mustBe true + itemsOps.compareLte(lower, higher) mustBe true + itemsOps.compareLte(higher, lower) mustBe false + + specializedTests(itemsOps) + } + } + } +} diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoderSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoderSpec.scala index e4889d1..e5bd3f4 100644 --- a/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoderSpec.scala +++ b/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberDecoderSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -17,7 +17,6 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ - package pl.tarsa.sortalgobox.core.crossverify import java.io.ByteArrayInputStream @@ -28,6 +27,38 @@ import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class PureNumberDecoderSpec extends CommonUnitSpecBase { typeBehavior[PureNumberDecoder] + it must "deserialize false value" in { + havingContents(0) { codec => + codec.deserializeBit() mustBe false + }(position = 1) + } + + it must "deserialize true value" in { + havingContents(1) { codec => + codec.deserializeBit() mustBe true + }(position = 1) + } + + it must "fail on unexpected value when deserializing boolean" in { + havingContents(8) { codec => + a[ValueOverflowException] mustBe thrownBy { + codec.deserializeBit() + } + }(position = 1) + } + + it must "deserialize positive byte" in { + havingContents(100) { codec => + codec.deserializeByte() mustBe 100 + }(position = 1) + } + + it must "deserialize negative byte" in { + havingContents(-100) { codec => + codec.deserializeByte() mustBe -100 + }(position = 1) + } + it must "fail on deserialization of empty buffer for int" in { havingContents() { codec => a[PrematureEndOfInputException] mustBe thrownBy { @@ -47,30 +78,36 @@ class PureNumberDecoderSpec extends CommonUnitSpecBase { it must "deserialize int zero" in { havingContents(0) { codec => - assert(codec.deserializeInt() == 0) + codec.deserializeInt() mustBe 0 }(position = 1) } - it must "fully deserialize weirdly encoded int zero" in { - havingContents(-128, -128, -128, -128, -128, -128, -128, 0) { codec => - assert(codec.deserializeInt() == 0) - }(position = 8) + it must "deserialize positive int" in { + havingContents(-114, -38, -106, 1) { codec => + codec.deserializeInt() mustBe 1234567 + }(position = 4) } - it must "deserialize positive int" in { - havingContents(-121, -83, 75) { codec => - assert(codec.deserializeInt() == 1234567) - }(position = 3) + it must "deserialize negative int" in { + havingContents(-115, -38, -106, 1) { codec => + codec.deserializeInt() mustBe -1234567 + }(position = 4) } - it must "deserialize max int" in { - havingContents(-1, -1, -1, -1, 7) { codec => - assert(codec.deserializeInt() == Int.MaxValue) + it must "deserialize Int.MaxValue" in { + havingContents(-2, -1, -1, -1, 15) { codec => + codec.deserializeInt() mustBe Int.MaxValue + }(position = 5) + } + + it must "deserialize Int.MinValue" in { + havingContents(-1, -1, -1, -1, 15) { codec => + codec.deserializeInt() mustBe Int.MinValue }(position = 5) } it must "fail on deserialization of slightly too big number for int" in { - havingContents(-1, -1, -1, -1, 8) { codec => + havingContents(-2, -1, -1, -1, 16) { codec => a[ValueOverflowException] mustBe thrownBy { codec.deserializeInt() } @@ -104,31 +141,36 @@ class PureNumberDecoderSpec extends CommonUnitSpecBase { it must "deserialize long zero" in { havingContents(0) { codec => - assert(codec.deserializeLong() == 0L) + codec.deserializeLong() mustBe 0L }(position = 1) } - it must "fully deserialize weirdly encoded long zero" in { - havingContents(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, 0) { codec => - assert(codec.deserializeLong() == 0L) - }(position = 19) + it must "deserialize positive long" in { + havingContents(-112, -24, -56, -23, -105, 7) { codec => + codec.deserializeLong() mustBe 123456789000L + }(position = 6) } - it must "deserialize positive long" in { - havingContents(-120, -76, -28, -12, -53, 3) { codec => - assert(codec.deserializeLong() == 123456789000L) + it must "deserialize negative long" in { + havingContents(-113, -24, -56, -23, -105, 7) { codec => + codec.deserializeLong() mustBe -123456789000L }(position = 6) } - it must "deserialize max long" in { - havingContents(-1, -1, -1, -1, -1, -1, -1, -1, 127) { codec => - assert(codec.deserializeLong() == Long.MaxValue) - }(position = 9) + it must "deserialize Long.MaxValue" in { + havingContents(-2, -1, -1, -1, -1, -1, -1, -1, -1, 1) { codec => + codec.deserializeLong() mustBe Long.MaxValue + }(position = 10) } - it must "fail on deserialization of slightly too big number for long" in { + it must "deserialize Long.MinValue" in { havingContents(-1, -1, -1, -1, -1, -1, -1, -1, -1, 1) { codec => + codec.deserializeLong() mustBe Long.MinValue + }(position = 10) + } + + it must "fail on deserialization of slightly too big number for long" in { + havingContents(-2, -1, -1, -1, -1, -1, -1, -1, -1, 3) { codec => a[ValueOverflowException] mustBe thrownBy { codec.deserializeLong() } @@ -136,22 +178,22 @@ class PureNumberDecoderSpec extends CommonUnitSpecBase { } it must "fail on deserialization of way too big number for long" in { - havingContents(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0) { codec => + havingContents(-2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0) { codec => a[ValueOverflowException] mustBe thrownBy { codec.deserializeLong() } }(position = 10) } - def havingContents(contents: Byte*)(function: PureNumberDecoder => Unit) - (position: Int): Unit = { - val stream = new CountingInputStream(new ByteArrayInputStream( - contents.toArray)) + def havingContents(contents: Byte*)(function: PureNumberDecoder => Unit)( + position: Int): Unit = { + val stream = new CountingInputStream( + new ByteArrayInputStream(contents.toArray)) val codec = new PureNumberDecoder(stream) try { function(codec) } finally { - assert(stream.getCount == position) + stream.getCount mustBe position } } } diff --git a/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoderSpec.scala b/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoderSpec.scala index 818dc52..5cd6353 100644 --- a/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoderSpec.scala +++ b/core/test_scala/pl/tarsa/sortalgobox/core/crossverify/PureNumberEncoderSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -17,11 +17,9 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ - package pl.tarsa.sortalgobox.core.crossverify import java.io.{ByteArrayOutputStream, OutputStream} -import java.util.{Arrays => jArrays} import org.apache.commons.io.output.ThresholdingOutputStream import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase @@ -31,30 +29,58 @@ class PureNumberEncoderSpec extends CommonUnitSpecBase { class OverflowException extends Exception - it must "fail on serializing negative int" in { - havingSize(0) { codec => - an[IllegalArgumentException] mustBe thrownBy { - codec.serializeInt(-1) - } - }() + it must "serialize false value" in { + havingSize() { codec => + codec.serializeBit(false) + }(contents = 0) + } + + it must "serialize true value" in { + havingSize() { codec => + codec.serializeBit(true) + }(contents = 1) + } + + it must "serialize positive byte" in { + havingSize() { codec => + codec.serializeByte(100) + }(contents = 100) + } + + it must "serialize negative byte" in { + havingSize() { codec => + codec.serializeByte(-100) + }(contents = -100) } it must "serialize int zero" in { - havingSize(1) { codec => + havingSize() { codec => codec.serializeInt(0) }(contents = 0) } it must "serialize positive int" in { - havingSize(9) { codec => + havingSize() { codec => codec.serializeInt(1234567) - }(contents = -121, -83, 75) + }(contents = -114, -38, -106, 1) + } + + it must "serialize negative int" in { + havingSize() { codec => + codec.serializeInt(-1234567) + }(contents = -115, -38, -106, 1) } - it must "serialize max int" in { - havingSize(9) { codec => + it must "serialize Int.MaxValue" in { + havingSize() { codec => codec.serializeInt(Int.MaxValue) - }(contents = -1, -1, -1, -1, 7) + }(contents = -2, -1, -1, -1, 15) + } + + it must "serialize Int.MinValue" in { + havingSize() { codec => + codec.serializeInt(Int.MinValue) + }(contents = -1, -1, -1, -1, 15) } it must "fail on int serialization when not enough remaining space" in { @@ -62,33 +88,37 @@ class PureNumberEncoderSpec extends CommonUnitSpecBase { a[OverflowException] mustBe thrownBy { codec.serializeInt(Int.MaxValue) } - }(contents = -1, -1) - } - - it must "fail on serializing negative long" in { - havingSize(0) { codec => - an[IllegalArgumentException] mustBe thrownBy { - codec.serializeLong(-1L) - } - }() + }(contents = -2, -1) } it must "serialize long zero" in { - havingSize(1) { codec => + havingSize() { codec => codec.serializeLong(0L) }(contents = 0) } it must "serialize positive long" in { - havingSize(9) { codec => + havingSize() { codec => codec.serializeLong(123456789000L) - }(contents = -120, -76, -28, -12, -53, 3) + }(contents = -112, -24, -56, -23, -105, 7) + } + + it must "serialize negative long" in { + havingSize() { codec => + codec.serializeLong(-123456789000L) + }(contents = -113, -24, -56, -23, -105, 7) } - it must "serialize max long" in { - havingSize(9) { codec => + it must "serialize Long.MaxValue" in { + havingSize() { codec => codec.serializeLong(Long.MaxValue) - }(contents = -1, -1, -1, -1, -1, -1, -1, -1, 127) + }(contents = -2, -1, -1, -1, -1, -1, -1, -1, -1, 1) + } + + it must "serialize Long.MinValue" in { + havingSize() { codec => + codec.serializeLong(Long.MinValue) + }(contents = -1, -1, -1, -1, -1, -1, -1, -1, -1, 1) } it must "fail on long serialization when not enough remaining space" in { @@ -96,11 +126,11 @@ class PureNumberEncoderSpec extends CommonUnitSpecBase { a[OverflowException] mustBe thrownBy { codec.serializeLong(Long.MaxValue) } - }(-1, -1) + }(-2, -1) } - def havingSize(size: Int)(function: PureNumberEncoder => Unit) - (contents: Byte*): Unit = { + def havingSize(size: Int = 10)(function: PureNumberEncoder => Unit)( + contents: Byte*): Unit = { val baos = new ByteArrayOutputStream() val stream = new ThresholdingOutputStream(size) { override def getStream: OutputStream = @@ -113,8 +143,8 @@ class PureNumberEncoderSpec extends CommonUnitSpecBase { try { function(codec) } finally { - assert(stream.getByteCount == contents.length) - assert(jArrays.equals(baos.toByteArray, contents.toArray)) + stream.getByteCount mustBe contents.length + baos.toByteArray mustBe contents.toArray } } } diff --git a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyBubbleSortSpec.scala b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyBubbleSortSpec.scala index e4c5e99..6f46503 100644 --- a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyBubbleSortSpec.scala +++ b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyBubbleSortSpec.scala @@ -24,9 +24,8 @@ import pl.tarsa.sortalgobox.sorts.natives.NativeBubbleSort import pl.tarsa.sortalgobox.sorts.scala.bubble.BubbleSort class VerifyBubbleSortSpec extends CrossVerifySpecBase { - registerCrossVerifyTest("Bubble Sort", 1234, new NativeBubbleSort(_, _), - new BubbleSort) + BubbleSort) } diff --git a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyInsertionSortSpec.scala b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyInsertionSortSpec.scala index 06e8a12..61a482f 100644 --- a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyInsertionSortSpec.scala +++ b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifyInsertionSortSpec.scala @@ -24,9 +24,8 @@ import pl.tarsa.sortalgobox.sorts.natives.NativeInsertionSort import pl.tarsa.sortalgobox.sorts.scala.insertion.InsertionSort class VerifyInsertionSortSpec extends CrossVerifySpecBase { - registerCrossVerifyTest("Insertion Sort", 1234, new NativeInsertionSort(_, _), - new InsertionSort) + InsertionSort) } diff --git a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySabHeapBinaryOneBasedVariantASpec.scala b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySabHeapBinaryOneBasedVariantASpec.scala index 461571c..c6922b8 100644 --- a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySabHeapBinaryOneBasedVariantASpec.scala +++ b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySabHeapBinaryOneBasedVariantASpec.scala @@ -24,9 +24,8 @@ import pl.tarsa.sortalgobox.sorts.natives.sab.agent.AgentSabHeapBinaryOneBasedVa import pl.tarsa.sortalgobox.sorts.scala.sab.SabHeapBinaryOneBasedVariantA class VerifySabHeapBinaryOneBasedVariantASpec extends CrossVerifySpecBase { - registerCrossVerifyTest("SabHeapBinaryOneBasedVariantA", 12345, new AgentSabHeapBinaryOneBasedVariantA(_, _), - new SabHeapBinaryOneBasedVariantA) + SabHeapBinaryOneBasedVariantA) } diff --git a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySelectionSortSpec.scala b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySelectionSortSpec.scala index f6f031e..c5a35f8 100644 --- a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySelectionSortSpec.scala +++ b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/VerifySelectionSortSpec.scala @@ -24,9 +24,8 @@ import pl.tarsa.sortalgobox.sorts.natives.NativeSelectionSort import pl.tarsa.sortalgobox.sorts.scala.selection.SelectionSort class VerifySelectionSortSpec extends CrossVerifySpecBase { - registerCrossVerifyTest("Selection Sort", 1234, new NativeSelectionSort(_, _), - new SelectionSort) + SelectionSort) } diff --git a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/infrastructure/CrossVerifySpecBase.scala b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/infrastructure/CrossVerifySpecBase.scala index 8112af4..f9b53bf 100644 --- a/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/infrastructure/CrossVerifySpecBase.scala +++ b/crossverify/test_scala/pl/tarsa/sortalgobox/crossverify/infrastructure/CrossVerifySpecBase.scala @@ -24,11 +24,8 @@ import java.nio.file.{Files, Path} import org.apache.commons.io.IOUtils import pl.tarsa.sortalgobox.common.SortAlgoBoxConfiguration.rootTempDir import pl.tarsa.sortalgobox.core.NativeBenchmark -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.implementations.{ - ComparingIntArrayItemsAgent, - VerifyingComparingIntArrayItemsAgent -} +import pl.tarsa.sortalgobox.core.common.ComparableItemsAgentSortAlgorithm +import pl.tarsa.sortalgobox.core.common.items.agents.VerifyingItemsAgent import pl.tarsa.sortalgobox.core.crossverify.PureNumberDecoder import pl.tarsa.sortalgobox.natives.build.NativesCache import pl.tarsa.sortalgobox.random.Mwc64x @@ -39,7 +36,7 @@ abstract class CrossVerifySpecBase extends NativesUnitSpecBase { sortName: String, itemsNumber: Int, nativeSortConstructor: (NativesCache, Option[Path]) => NativeBenchmark, - scalaSort: ComparisonSortAlgorithm): Unit = { + scalaSort: ComparableItemsAgentSortAlgorithm): Unit = { s"Native $sortName" must s"take steps identical to Scala $sortName" in { val recordingFilePath = Files.createTempFile(rootTempDir, "recording", ".bin") @@ -50,14 +47,18 @@ abstract class CrossVerifySpecBase extends NativesUnitSpecBase { val replayer = new PureNumberDecoder(stream) val generator = Mwc64x() val array = Array.fill[Int](itemsNumber)(generator.nextInt()) - val itemsAgent = new VerifyingComparingIntArrayItemsAgent( - replayer, - new ComparingIntArrayItemsAgent(array), - b => assert(b)) - scalaSort.sort(itemsAgent) + val itemsAgent = new VerifyingItemsAgent(replayer, verify) + val sortSetup = scalaSort.setupSort(array) + scalaSort.sortExplicit(sortSetup, itemsAgent) } finally { Files.delete(recordingFilePath) } } } + + private def verify(success: Boolean): Unit = { + if (!success) { + fail() + } + } } diff --git a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/comparing_items_agent.hpp b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/comparing_items_agent.hpp deleted file mode 100644 index 92fecc9..0000000 --- a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/comparing_items_agent.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -#ifndef COMPARING_ITEMS_AGENT_HPP -#define COMPARING_ITEMS_AGENT_HPP - -#include - -#include "items_agent.hpp" - -namespace tarsa { - - enum compare_t { - CompareBelow, CompareEqual, CompareAbove - }; - - template - class ComparingItemsAgent : public ItemsAgent { - public: - template - ComparingItemsAgent withBase() const {} - - compare_t compare(item_t const a, item_t const b) const {} - - bool compareLt(item_t const a, item_t const b) const {} - - compare_t compare0(size_t const i, size_t const j) const {} - - bool compareLt0(size_t const i, size_t const j) const {} - }; -} - -#endif /* COMPARING_ITEMS_AGENT_HPP */ diff --git a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/comparing_array_items_agent.hpp b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/comparing_array_items_agent.hpp deleted file mode 100644 index 3506d0c..0000000 --- a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/comparing_array_items_agent.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -#ifndef COMPARING_ARRAY_ITEMS_AGENT_HPP -#define COMPARING_ARRAY_ITEMS_AGENT_HPP - -#include -#include - -#include "comparing_items_agent.hpp" - -namespace tarsa { - - template - class ComparingArrayItemsAgent : public ComparingItemsAgent { - item_t * const array; - size_t const count; - - public: - ComparingArrayItemsAgent(item_t * const array, size_t const count): - array(array - base), count(count) { - } - - ComparingArrayItemsAgent withBase1() const { - return ComparingArrayItemsAgent(array + base, count); - } - - size_t size0() const { - return count; - } - - item_t get0(size_t const i) const { - return array[i]; - } - - void set0(size_t const i, item_t const v) const { - array[i] = v; - } - - void copy0(size_t const i, size_t const j, size_t const n) const { - memcpy(array + j, array + i, n + sizeof(item_t)); - } - - void swap0(size_t const i, size_t const j) const { - item_t const temp = get0(i); - set0(i, get0(j)); - set0(j, temp); - } - - compare_t compare(item_t const a, item_t const b) const { - if (a < b) { - return CompareBelow; - } else if (a == b) { - return CompareEqual; - } else { - return CompareAbove; - } - } - - bool compareLt(item_t const a, item_t const b) const { - return a < b; - } - - compare_t compare0(size_t const i, size_t const j) const { - return compare(get0(i), get0(j)); - } - - bool compareLt0(size_t const i, size_t const j) const { - return compareLt(get0(i), get0(j)); - } - }; -} - -#endif /* COMPARING_ARRAY_ITEMS_AGENT_HPP */ diff --git a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/recording_comparing_items_agent.hpp b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/recording_comparing_items_agent.hpp deleted file mode 100644 index 66f00ae..0000000 --- a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/implementations/recording_comparing_items_agent.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -#ifndef RECORDING_COMPARING_ITEMS_AGENT_HPP -#define RECORDING_COMPARING_ITEMS_AGENT_HPP - -#include -#include - -#include "action_codes.hpp" -#include "comparing_items_agent.hpp" - -namespace tarsa { - - template class UnderlyingItemsAgent> - struct RecordingComparingItemsAgentSetup { - - template - class RecordingComparingItemsAgent : - public ComparingItemsAgent { - NumberEncoder * const recorder; - UnderlyingItemsAgent const underlying; - - public: - RecordingComparingItemsAgent(NumberEncoder * const recorder, - UnderlyingItemsAgent const underlying): - recorder(recorder), underlying(underlying) { - } - - RecordingComparingItemsAgent withBase1() const { - return RecordingComparingItemsAgent(recorder, - underlying.withBase1()); - } - - size_t size0() const { - recorder->serializeInt(CodeSize0); - return underlying.size0(); - } - - item_t get0(size_t const i) const { - recorder->serializeInt(CodeGet0); - recorder->serializeLong(i); - return underlying.get0(i); - } - - void set0(size_t const i, item_t const v) const { - recorder->serializeInt(CodeSet0); - recorder->serializeLong(i); - underlying.set0(i, v); - } - - void copy0(size_t const i, size_t const j, size_t const n) const { - recorder->serializeInt(CodeCopy0); - recorder->serializeLong(i); - recorder->serializeLong(j); - recorder->serializeLong(n); - underlying.copy0(i, j, n); - } - - void swap0(size_t const i, size_t const j) const { - recorder->serializeInt(CodeSwap0); - recorder->serializeLong(i); - recorder->serializeLong(j); - underlying.swap0(i, j); - } - - compare_t compare(item_t const a, item_t const b) const { - recorder->serializeInt(CodeCompare); - return underlying.compare(a, b); - } - - bool compareLt(item_t const a, item_t const b) const { - recorder->serializeInt(CodeCompare); - return underlying.compareLt(a, b); - } - - compare_t compare0(size_t const i, size_t const j) const { - recorder->serializeInt(CodeCompare0); - recorder->serializeLong(i); - recorder->serializeLong(j); - return underlying.compare0(i, j); - } - - bool compareLt0(size_t const i, size_t const j) const { - recorder->serializeInt(CodeCompare0); - recorder->serializeLong(i); - recorder->serializeLong(j); - return underlying.compareLt0(i, j); - } - }; - - template - using Result = RecordingComparingItemsAgent; - }; -} - -#endif /* RECORDING_COMPARING_ITEMS_AGENT_HPP */ diff --git a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/items_agent.hpp b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/items_agent.hpp index 4b7af2a..c2bbe16 100644 --- a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/items_agent.hpp +++ b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/agents/items_agent.hpp @@ -21,24 +21,294 @@ #define ITEMS_AGENT_HPP #include +#include + +#define ITEMS_AGENT_TYPE_START 8191029952343308046L +#define ITEMS_AGENT_TYPE_PLAIN ITEMS_AGENT_TYPE_START + 1 +#define ITEMS_AGENT_TYPE_RECORDING ITEMS_AGENT_TYPE_START + 2 + +static_assert( + ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_PLAIN || + ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING || + false, "Valid items agent type must be selected"); + +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING +#include "number_codec.hpp" +#include "action_codes.hpp" +#endif namespace tarsa { - template + template + struct Buffer { + item_t * const array; + size_t const length; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + int32_t const id; +#endif + + Buffer(item_t * const array, size_t const length, int32_t const id): + array(array), length(length) +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + , id(id) +#endif + {} + }; + class ItemsAgent { +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + NumberEncoder * const recorder; +#endif + public: - template - ItemsAgent withBase() const {} +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_PLAIN + ItemsAgent() {} +#else + ItemsAgent(NumberEncoder * const recorder): recorder(recorder) {} +#endif + + template + size_t size(Buffer const buffer) { + size_t const result = buffer.length; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeSize); + recorder->serializeByte(buffer.id); + recorder->serializeInt((int32_t) result); +#endif + return result; + } + + template + item_t get(Buffer const buffer, size_t const index) { +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeGet); + recorder->serializeByte(buffer.id); + recorder->serializeInt((int32_t) index); +#endif + return buffer.array[index]; + } + + template + void set(Buffer const buffer, size_t const index, + item_t const value) { +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeSet); + recorder->serializeByte(buffer.id); + recorder->serializeInt((int32_t) index); +#endif + buffer.array[index] = value; + } + + template + void swap(Buffer const buffer, size_t const index1, + size_t const index2) const { +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeSwap); + recorder->serializeByte(buffer.id); + recorder->serializeInt((int32_t) index1); + recorder->serializeInt((int32_t) index2); +#endif + item_t const item = buffer.array[index1]; + buffer.array[index1] = buffer.array[index2]; + buffer.array[index2] = item; + } + + template + int32_t itemBitsSize(Buffer const buffer) { + int32_t result = sizeof(item_t) * 8; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeItemBitsSize); + recorder->serializeByte(buffer.id); + recorder->serializeByte(result); +#endif + return result; + } + + template + int64_t asLong(item_t const value) { + int64_t const result = (int64_t) result; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeAsLong); + recorder->serializeLong(result); +#endif + return result; + } + + template + int64_t asLongI(Buffer const buffer, size_t const index) { + return asLong(get(buffer, index)); + } + + template + int32_t getSlice(item_t const value, int32_t const lowestBitIndex, + int32_t const length) { + int32_t const result = ((int32_t) (value >> lowestBitIndex)) & + ((1 << length) - 1); +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeGetSlice); + recorder->serializeByte(lowestBitIndex); + recorder->serializeByte(length); + recorder->serializeInt(result); +#endif + return result; + } + + template + int32_t getSliceI(Buffer const buffer, size_t const index, + int32_t const lowestBitIndex, int32_t const length) { + return getSlice(get(buffer, index), lowestBitIndex, length); + } + + template + bool compareEq(item_t const value1, item_t const value2) { + bool const result = value1 == value2; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeCompareEq); + recorder->serializeBit(result); +#endif + return result; + } + + template + bool compareEqI(Buffer const buffer, size_t const index1, + size_t const index2) { + item_t const value1 = get(buffer, index1); + item_t const value2 = get(buffer, index2); + return compareEq(value1, value2); + } + + template + bool compareEqIV(Buffer const buffer, size_t const index1, + item_t const value2) { + return compareEq(get(buffer, index1), value2); + } + + template + bool compareEqVI(Buffer const buffer, item_t const value1, + size_t const index2) { + return compareEq(value1, get(buffer, index2)); + } - size_t size0() const {} + template + bool compareGt(item_t const value1, item_t const value2) { + bool const result = value1 > value2; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeCompareGt); + recorder->serializeBit(result); +#endif + return result; + } + + template + bool compareGtI(Buffer const buffer, size_t const index1, + size_t const index2) { + item_t const value1 = get(buffer, index1); + item_t const value2 = get(buffer, index2); + return compareGt(value1, value2); + } + + template + bool compareGtIV(Buffer const buffer, size_t const index1, + item_t const value2) { + return compareGt(get(buffer, index1), value2); + } + + template + bool compareGtVI(Buffer const buffer, item_t const value1, + size_t const index2) { + return compareGt(value1, get(buffer, index2)); + } - item_t get0(size_t const i) const {} - void set0(size_t const i, item_t const v) const {} + template + bool compareGte(item_t const value1, item_t const value2) { + bool const result = value1 >= value2; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeCompareGte); + recorder->serializeBit(result); +#endif + return result; + } + + template + bool compareGteI(Buffer const buffer, size_t const index1, + size_t const index2) { + item_t const value1 = get(buffer, index1); + item_t const value2 = get(buffer, index2); + return compareGte(value1, value2); + } + + template + bool compareGteIV(Buffer const buffer, size_t const index1, + item_t const value2) { + return compareGte(get(buffer, index1), value2); + } + + template + bool compareGteVI(Buffer const buffer, item_t const value1, + size_t const index2) { + return compareGte(value1, get(buffer, index2)); + } - void copy0(size_t const i, size_t const j, size_t const n) const {} + template + bool compareLt(item_t const value1, item_t const value2) { + bool const result = value1 < value2; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeCompareLt); + recorder->serializeBit(result); +#endif + return result; + } + + template + bool compareLtI(Buffer const buffer, size_t const index1, + size_t const index2) { + item_t const value1 = get(buffer, index1); + item_t const value2 = get(buffer, index2); + return compareLt(value1, value2); + } + + template + bool compareLtIV(Buffer const buffer, size_t const index1, + item_t const value2) { + return compareLt(get(buffer, index1), value2); + } + + template + bool compareLtVI(Buffer const buffer, item_t const value1, + size_t const index2) { + return compareLt(value1, get(buffer, index2)); + } - void swap0(size_t const i, size_t const j) const {} + template + bool compareLte(item_t const value1, item_t const value2) { + bool const result = value1 <= value2; +#if ITEMS_AGENT_TYPE == ITEMS_AGENT_TYPE_RECORDING + recorder->serializeByte(CodeCompareLte); + recorder->serializeBit(result); +#endif + return result; + } + + template + bool compareLteI(Buffer const buffer, size_t const index1, + size_t const index2) { + item_t const value1 = get(buffer, index1); + item_t const value2 = get(buffer, index2); + return compareLte(value1, value2); + } + + template + bool compareLteIV(Buffer const buffer, size_t const index1, + item_t const value2) { + return compareLte(get(buffer, index1), value2); + } + + template + bool compareLteVI(Buffer const buffer, item_t const value1, + size_t const index2) { + return compareLte(value1, get(buffer, index2)); + } }; } diff --git a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/crossverify/number_codec.hpp b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/crossverify/number_codec.hpp index 4e806e4..96ffc54 100644 --- a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/crossverify/number_codec.hpp +++ b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/crossverify/number_codec.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -29,7 +29,7 @@ namespace tarsa { class NumberCodec { public: enum error_t { - OK, NegativeValue, ValueOverflow, BufferedIoError + NoError, ValueOverflow, BufferedIoError }; protected: @@ -37,7 +37,7 @@ namespace tarsa { public: NumberCodec() { - error = OK; + error = NoError; } error_t getError() const { @@ -46,8 +46,7 @@ namespace tarsa { char const * showError() const { switch (error) { - case OK: return "OK"; - case NegativeValue: return "NegativeValue"; + case NoError: return "NoError"; case ValueOverflow: return "ValueOverflow"; case BufferedIoError: return "BufferedIoError"; default: return nullptr; @@ -60,20 +59,48 @@ namespace tarsa { public: NumberEncoder(BufferedWriter * const writer): writer(writer) { - error = (writer == nullptr) ? BufferedIoError : OK; + error = (writer == nullptr) ? BufferedIoError : NoError; } void flush() { - if (error == OK && !writer->flush(true)) { + if (error == NoError && !writer->flush(true)) { error = BufferedIoError; } } - void serializeInt(int32_t const value) { - if (error == OK) { - if (value < 0) { - error = NegativeValue; - } else if (value <= INT8_MAX) { + void serializeBit(bool const value) { + if (error == NoError) { + int8_t const byte = value ? 1 : 0; + if (!writer->write(byte)) { + error = BufferedIoError; + } + } + } + + void serializeByte(int8_t const value) { + if (error == NoError) { + if (!writer->write(value)) { + error = BufferedIoError; + } + } + } + + void serializeInt(int32_t const original) { + uint32_t const abs = original < 0 ? -original : original; + uint32_t const value = (abs << 1) - (original < 0); + serializeInt0(value); + } + + void serializeLong(int64_t const original) { + uint64_t const abs = original < 0 ? -original : original; + uint64_t const value = (abs << 1) - (original < 0); + serializeLong0(value); + } + + private: + void serializeInt0(uint32_t const value) { + if (error == NoError) { + if ((value >> 7) == 0) { if (!writer->write(value)) { error = BufferedIoError; } @@ -81,16 +108,14 @@ namespace tarsa { if (!writer->write((value & 127) - 128)) { error = BufferedIoError; } - serializeInt(value >> 7); + serializeInt0(value >> 7); } } } - void serializeLong(int64_t const value) { - if (error == OK) { - if (value < 0) { - error = NegativeValue; - } else if (value <= INT8_MAX) { + void serializeLong0(uint64_t const value) { + if (error == NoError) { + if ((value >> 7) == 0) { if (!writer->write(value)) { error = BufferedIoError; } @@ -98,7 +123,7 @@ namespace tarsa { if (!writer->write((value & 127) - 128)) { error = BufferedIoError; } - serializeLong(value >> 7); + serializeLong0(value >> 7); } } } @@ -109,73 +134,95 @@ namespace tarsa { public: NumberDecoder(BufferedReader * const reader): reader(reader) { - error = (reader == nullptr) ? BufferedIoError : OK; + error = (reader == nullptr) ? BufferedIoError : NoError; } - private: - int32_t deserializeInt0(int32_t const current, int32_t const shift) { - if (error == OK) { + bool deserializeBit() { + if (error == NoError) { int32_t const input = reader->read(); if (input == -1) { error = BufferedIoError; - return -1; + return false; + } else if (input > 1) { + error = ValueOverflow; + return false; } else { - if (input == 0) { - return current; - } else { - int32_t const chunk = input & 127; - if ((chunk != 0) && ((shift > 31) - || (chunk > (INT32_MAX >> shift)))) { - error = ValueOverflow; - return -1; - } else { - int32_t const next = (chunk << shift) + current; - if (input <= 127) { - return next; - } else { - return deserializeInt0(next, shift + 7); - } - } - } + return input == 1; } } } - int64_t deserializeLong0(int64_t const current, int32_t const shift) { - if (error == OK) { + int8_t deserializeByte() { + if (error == NoError) { int32_t const input = reader->read(); if (input == -1) { error = BufferedIoError; return -1; } else { - if (input == 0) { - return current; - } else { - int64_t const chunk = input & 127; - if ((chunk != 0) && ((shift > 63) - || (chunk > (INT64_MAX >> shift)))) { - error = ValueOverflow; - return -1; - } else { - int64_t const next = (chunk << shift) + current; - if (input <= 127) { - return next; - } else { - return deserializeLong0(next, shift + 7); - } - } - } + return input; } } } - public: int32_t deserializeInt() { - return deserializeInt0(0, 0); + uint32_t const shifted = deserializeInt0(0u, 0); + bool const signFlag = shifted & 1; + int32_t const absValue = shifted >> 1; + return signFlag ? ~absValue : absValue; } int64_t deserializeLong() { - return deserializeLong0(0L, 0); + uint64_t const shifted = deserializeLong0(0uL, 0); + bool const signFlag = shifted & 1; + int64_t const absValue = shifted >> 1; + return signFlag ? ~absValue : absValue; + } + + private: + uint32_t deserializeInt0(uint32_t const current, int32_t const shift) { + if (error == NoError) { + int32_t const input = reader->read(); + if (input == -1) { + error = BufferedIoError; + return 1; + } else { + uint32_t const chunk = input & 127; + if (shift > 31 || + (shift > 0 && chunk >= (1u << 32 - shift))) { + error = ValueOverflow; + return 1; + } + uint32_t const next = (chunk << shift) + current; + if (input <= 127) { + return next; + } else { + return deserializeInt0(next, shift + 7); + } + } + } + } + + uint64_t deserializeLong0(uint64_t const current, int32_t const shift) { + if (error == NoError) { + int32_t const input = reader->read(); + if (input == -1) { + error = BufferedIoError; + return 1; + } else { + uint64_t const chunk = input & 127; + if (shift > 63 || + (shift > 0 && chunk >= (1uL << 64 - shift))) { + error = ValueOverflow; + return 1; + } + uint64_t const next = (chunk << shift) + current; + if (input <= 127) { + return next; + } else { + return deserializeLong0(next, shift + 7); + } + } + } } }; } diff --git a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/utilities.hpp b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/utilities.hpp index 8635f1b..5b6fc95 100644 --- a/natives/main_rsrc/pl/tarsa/sortalgobox/natives/utilities.hpp +++ b/natives/main_rsrc/pl/tarsa/sortalgobox/natives/utilities.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -46,7 +46,7 @@ void safeDelete(T* &pointer) { template void safeFree(T* &pointer) { free(pointer); - pointer == nullptr; + pointer = nullptr; } #endif /* UTILITIES_HPP */ diff --git a/natives/main_scala/pl/tarsa/sortalgobox/natives/agents/ItemsAgentsBuildComponents.scala b/natives/main_scala/pl/tarsa/sortalgobox/natives/agents/ItemsAgentsBuildComponents.scala index 7be4637..df2cf8b 100644 --- a/natives/main_scala/pl/tarsa/sortalgobox/natives/agents/ItemsAgentsBuildComponents.scala +++ b/natives/main_scala/pl/tarsa/sortalgobox/natives/agents/ItemsAgentsBuildComponents.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -21,27 +21,43 @@ package pl.tarsa.sortalgobox.natives.agents import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes import pl.tarsa.sortalgobox.common.crossverify.TrackingEnums.ActionTypes._ -import pl.tarsa.sortalgobox.natives.build.{NativeBuildComponentFromString, NativeComponentsSupport} +import pl.tarsa.sortalgobox.natives.build.{ + NativeBuildComponent, + NativeBuildComponentFromString, + NativeComponentsSupport +} import pl.tarsa.sortalgobox.natives.generators.NativeEnumGenerator object ItemsAgentsBuildComponents extends NativeComponentsSupport { - val trackingEnum = Seq(NativeBuildComponentFromString( - NativeEnumGenerator("tracking_codes_t", "Code", ActionTypes) - (Size0 -> "Size0", Get0 -> "Get0", Set0 -> "Set0", Copy0 -> "Copy0", - Swap0 -> "Swap0", Compare -> "Compare", Compare0 -> "Compare0"), - "action_codes.hpp")) - - val standard = makeResourceComponents( - ("/pl/tarsa/sortalgobox/natives/agents/", "items_agent.hpp"), - ("/pl/tarsa/sortalgobox/natives/agents/", "comparing_items_agent.hpp"), - ("/pl/tarsa/sortalgobox/natives/agents/implementations/", - "comparing_array_items_agent.hpp")) + val trackingEnum = Seq( + NativeBuildComponentFromString( + NativeEnumGenerator("tracking_codes_t", "Code", ActionTypes)( + Size -> "Size", + Get -> "Get", + Set -> "Set", + Swap -> "Swap", + ItemBitsSize -> "ItemBitsSize", + AsLong -> "AsLong", + GetSlice -> "GetSlice", + CompareEq -> "CompareEq", + CompareGt -> "CompareGt", + CompareGte -> "CompareGte", + CompareLt -> "CompareLt", + CompareLte -> "CompareLte" + ), + "action_codes.hpp" + )) - val recording = standard ++ + val standard: Seq[NativeBuildComponent] = { makeResourceComponents( + ("/pl/tarsa/sortalgobox/natives/agents/", "items_agent.hpp") + ) + } + + val recording: Seq[NativeBuildComponent] = { + standard ++ makeResourceComponents( ("/pl/tarsa/sortalgobox/natives/", "buffered_io.hpp"), - ("/pl/tarsa/sortalgobox/natives/agents/implementations/", - "recording_comparing_items_agent.hpp"), - ("/pl/tarsa/sortalgobox/natives/crossverify/", "number_codec.hpp")) ++ - trackingEnum + ("/pl/tarsa/sortalgobox/natives/crossverify/", "number_codec.hpp") + ) ++ trackingEnum + } } diff --git a/natives/test_scala/pl/tarsa/sortalgobox/natives/crossverify/NativeNumberCodecSpec.scala b/natives/test_scala/pl/tarsa/sortalgobox/natives/crossverify/NativeNumberCodecSpec.scala index 267f006..c03ca1f 100644 --- a/natives/test_scala/pl/tarsa/sortalgobox/natives/crossverify/NativeNumberCodecSpec.scala +++ b/natives/test_scala/pl/tarsa/sortalgobox/natives/crossverify/NativeNumberCodecSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -23,22 +23,23 @@ import pl.tarsa.sortalgobox.natives.build._ import pl.tarsa.sortalgobox.tests.NativesUnitSpecBase class NativeNumberCodecSpec extends NativesUnitSpecBase { - behavior of "NativeNumberCodec" - import NativeNumberCodecSpec._ + import TestMode._ + + behavior of "NativeNumberCodec" for ((Test(testName, testMode, _), testIndex) <- tests.zipWithIndex) { it must testName in { val input = Seq(testIndex.toString) val execResult = testNativesCache.runCachedProgram(buildConfig, input) val flags = execResult.stdOut.lines.map(_.toInt != 0).toList - import TestMode._ testMode match { - case SerializeInt | SerializeLong => + case SerializeBit | SerializeByte | SerializeInt | SerializeLong => val List(a, b) = flags assert(a, ", contents") assert(b, ", error status") - case DeserializeInt | DeserializeLong => + case DeserializeBit | DeserializeByte | DeserializeInt | + DeserializeLong => val List(a, b, c) = flags assert(a, ", decoded value") assert(b, ", buffer position") @@ -54,106 +55,183 @@ object NativeNumberCodecSpec extends NativeComponentsSupport { object TestMode extends Enumeration { type TestMode = Value - val SerializeInt, DeserializeInt, SerializeLong, DeserializeLong = Value + val SerializeBit, DeserializeBit, SerializeByte, DeserializeByte, + SerializeInt, DeserializeInt, SerializeLong, DeserializeLong = Value } - import TestMode._ case class Test(name: String, mode: TestMode, params: String) val tests: List[Test] = List[(String, TestMode, String)]( - ("fail on serializing negative int", SerializeInt, - "0, -1, nullptr, 0, NumberCodec::NegativeValue"), - ("serialize int zero", SerializeInt, - "1, 0, new int8_t[1]{0}, 1, NumberCodec::OK"), - ("serialize positive int", SerializeInt, - "9, 1234567, new int8_t[3]{-121, -83, 75}, 3, NumberCodec::OK"), - ("serialize max int", SerializeInt, - "9, INT32_MAX, new int8_t[5]{-1, -1, -1, -1, 7}, 5, NumberCodec::OK"), - ("fail on int serialization when not enough remaining space", SerializeInt, - s"2, INT32_MAX, new int8_t[2]{(int8_t) $filler, (int8_t) $filler}, 2, " + - "NumberCodec::BufferedIoError"), - ("fail on deserialization of empty buffer for int", DeserializeInt, - "nullptr, 0, -1, 0, NumberCodec::BufferedIoError"), + ("serialize false value", + SerializeBit, + "1, false, new int8_t[1]{0}, 1, NumberCodec::NoError"), + ("serialize true value", + SerializeBit, + "1, true, new int8_t[1]{1}, 1, NumberCodec::NoError"), + ("deserialize false value", + DeserializeBit, + "new int8_t[1]{0}, 1, false, 1, NumberCodec::NoError"), + ("deserialize true value", + DeserializeBit, + "new int8_t[1]{1}, 1, true, 1, NumberCodec::NoError"), + ("fail on unexpected value when deserializing boolean", + DeserializeBit, + "new int8_t[1]{8}, 1, false, 1, NumberCodec::ValueOverflow"), + ("serialize positive byte", + SerializeByte, + "1, 100, new int8_t[1]{100}, 1, NumberCodec::NoError"), + ("serialize negative byte", + SerializeByte, + "1, -100, new int8_t[1]{-100}, 1, NumberCodec::NoError"), + ("deserialize positive byte", + DeserializeByte, + "new int8_t[1]{100}, 1, 100, 1, NumberCodec::NoError"), + ("deserialize negative byte", + DeserializeByte, + "new int8_t[1]{-100}, 1, -100, 1, NumberCodec::NoError"), + ("serialize int zero", + SerializeInt, + "1, 0, new int8_t[1]{0}, 1, NumberCodec::NoError"), + ("serialize positive int", + SerializeInt, + "9, 1234567, new int8_t[4]{-114, -38, -106, 1}, 4, NumberCodec::NoError"), + ("serialize negative int", + SerializeInt, + "9, -1234567, new int8_t[4]{-115, -38, -106, 1}, 4, NumberCodec::NoError"), + ("serialize INT32_MAX", + SerializeInt, + "9, INT32_MAX, new int8_t[5]{-2, -1, -1, -1, 15}, 5, " + + "NumberCodec::NoError"), + ("serialize INT32_MIN", + SerializeInt, + "9, INT32_MIN, new int8_t[5]{-1, -1, -1, -1, 15}, 5, " + + "NumberCodec::NoError"), + ("fail on int serialization when not enough remaining space", + SerializeInt, + s"2, INT32_MAX, new int8_t[2]{-2, -1}, 2, NumberCodec::BufferedIoError"), + ("fail on deserialization of empty buffer for int", + DeserializeInt, + "nullptr, 0, -1, 0, NumberCodec::BufferedIoError"), ("fail on deserialization of unfinished negative sequence for int", - DeserializeInt, "new int8_t[3]{-1, -2, -3}, 3, -1, 3, " + - "NumberCodec::BufferedIoError"), - ("deserialize int zero", DeserializeInt, - "new int8_t[1]{0}, 1, 0, 1, NumberCodec::OK"), - ("fully deserialize weirdly encoded int zero", DeserializeInt, - "new int8_t[8]{-128, -128, -128, -128, -128, -128, -128, 0}, 8, 0, 8, " + - "NumberCodec::OK"), - ("deserialize positive int", DeserializeInt, - "new int8_t[3]{-121, -83, 75}, 3, 1234567, 3, NumberCodec::OK"), - ("deserialize max int", DeserializeInt, - "new int8_t[5]{-1, -1, -1, -1, 7}, 5, INT32_MAX, 5, NumberCodec::OK"), + DeserializeInt, + "new int8_t[3]{-1, -2, -3}, 3, -1, 3, " + + "NumberCodec::BufferedIoError"), + ("deserialize int zero", + DeserializeInt, + "new int8_t[1]{0}, 1, 0, 1, NumberCodec::NoError"), + ("deserialize positive int", + DeserializeInt, + "new int8_t[4]{-114, -38, -106, 1}, 4, 1234567, 4, NumberCodec::NoError"), + ("deserialize negative int", + DeserializeInt, + "new int8_t[4]{-115, -38, -106, 1}, 4, -1234567, 4, NumberCodec::NoError"), + ("deserialize INT32_MAX", + DeserializeInt, + "new int8_t[5]{-2, -1, -1, -1, 15}, 5, INT32_MAX, 5, " + + "NumberCodec::NoError"), + ("deserialize INT32_MIN", + DeserializeInt, + "new int8_t[5]{-1, -1, -1, -1, 15}, 5, INT32_MIN, 5, " + + "NumberCodec::NoError"), ("fail on deserialization of slightly too big number for int", - DeserializeInt, "new int8_t[5]{-1, -1, -1, -1, 8}, 5, -1, 5, " + - "NumberCodec::ValueOverflow"), - ("fail on deserialization of way too big number for int", DeserializeInt, - "new int8_t[6]{-1, -1, -1, -1, -1, 1}, 6, -1, 5, " + - "NumberCodec::ValueOverflow"), - ("fail on serializing negative long", SerializeLong, - "0, -1L, nullptr, 0, NumberCodec::NegativeValue"), - ("serialize long zero", SerializeLong, - "1, 0, new int8_t[1]{0}, 1, NumberCodec::OK"), - ("serialize positive long", SerializeLong, - "9, 123456789000L, new int8_t[6]{-120, -76, -28, -12, -53, 3}, 6, " + - "NumberCodec::OK"), - ("serialize max long", SerializeLong, - "9, INT64_MAX, new int8_t[9]{-1, -1, -1, -1, -1, -1, -1, -1, 127}, 9," + - "NumberCodec::OK"), + DeserializeInt, + "new int8_t[5]{-2, -1, -1, -1, 16}, 5, -1, 5, " + + "NumberCodec::ValueOverflow"), + ("fail on deserialization of way too big number for int", + DeserializeInt, + "new int8_t[6]{-1, -1, -1, -1, -1, 1}, 6, -1, 5, " + + "NumberCodec::ValueOverflow"), + ("serialize long zero", + SerializeLong, + "1, 0, new int8_t[1]{0}, 1, NumberCodec::NoError"), + ("serialize positive long", + SerializeLong, + "9, 123456789000L, new int8_t[6]{-112, -24, -56, -23, -105, 7}, 6, " + + "NumberCodec::NoError"), + ("serialize negative long", + SerializeLong, + "9, -123456789000L, new int8_t[6]{-113, -24, -56, -23, -105, 7}, 6, " + + "NumberCodec::NoError"), + ("serialize INT64_MAX", + SerializeLong, + "10, INT64_MAX, new int8_t[10]{-2, -1, -1, -1, -1, -1, -1, -1, -1, 1}, " + + "10, NumberCodec::NoError"), + ("serialize INT64_MIN", + SerializeLong, + "10, INT64_MIN, new int8_t[10]{-1, -1, -1, -1, -1, -1, -1, -1, -1, 1}, " + + "10, NumberCodec::NoError"), ("fail on long serialization when not enough remaining space", - SerializeLong, s"2, INT64_MAX, new int8_t[2]{(int8_t) $filler, " + - s"(int8_t) $filler}, 2, NumberCodec::BufferedIoError"), - ("fail on deserialization of empty buffer for long", DeserializeLong, - "nullptr, 0, -1, 0, NumberCodec::BufferedIoError"), + SerializeLong, + s"2, INT64_MAX, new int8_t[2]{-2, -1}, 2, NumberCodec::BufferedIoError"), + ("fail on deserialization of empty buffer for long", + DeserializeLong, + "nullptr, 0, -1, 0, NumberCodec::BufferedIoError"), ("fail on deserialization of unfinished negative sequence for long", - DeserializeLong, "new int8_t[3]{-1, -2, -3}, 3, -1, 3, " + - "NumberCodec::BufferedIoError"), - ("deserialize long zero", DeserializeLong, - "new int8_t[1]{0}, 1, 0, 1, NumberCodec::OK"), - ("fully deserialize weirdly encoded long zero", DeserializeLong, - "new int8_t[19]{-128, -128, -128, -128, -128, -128, -128, -128, -128, " + - "-128, -128, -128, -128, -128, -128, -128, -128, -128, 0}, 19, 0, " + - "19, NumberCodec::OK"), - ("deserialize positive long", DeserializeLong, - "new int8_t[6]{-120, -76, -28, -12, -53, 3}, 6, 123456789000L, 6, " + - "NumberCodec::OK"), - ("deserialize max long", DeserializeLong, - "new int8_t[9]{-1, -1, -1, -1, -1, -1, -1, -1, 127}, 9, INT64_MAX, 9, " + - "NumberCodec::OK"), + DeserializeLong, + "new int8_t[3]{-1, -2, -3}, 3, -1, 3, " + + "NumberCodec::BufferedIoError"), + ("deserialize long zero", + DeserializeLong, + "new int8_t[1]{0}, 1, 0, 1, NumberCodec::NoError"), + ("deserialize positive long", + DeserializeLong, + "new int8_t[6]{-112, -24, -56, -23, -105, 7}, 6, 123456789000L, 6, " + + "NumberCodec::NoError"), + ("deserialize negative long", + DeserializeLong, + "new int8_t[6]{-113, -24, -56, -23, -105, 7}, 6, -123456789000L, 6, " + + "NumberCodec::NoError"), + ("deserialize INT64_MAX", + DeserializeLong, + "new int8_t[10]{-2, -1, -1, -1, -1, -1, -1, -1, -1, 1}, 10, INT64_MAX, " + + "10, NumberCodec::NoError"), + ("deserialize INT64_MIN", + DeserializeLong, + "new int8_t[10]{-1, -1, -1, -1, -1, -1, -1, -1, -1, 1}, 10, INT64_MIN, " + + "10, NumberCodec::NoError"), ("fail on deserialization of slightly too big number for long", - DeserializeLong, "new int8_t[10]{-1, -1, -1, -1, -1, -1, -1, -1, -1, " + - "1}, 10, -1, 10, NumberCodec::ValueOverflow"), - ("fail on deserialization of way too big number for long", DeserializeLong, - "new int8_t[11]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0}, 11, -1, " + - "10, NumberCodec::ValueOverflow") + DeserializeLong, + "new int8_t[10]{-2, -1, -1, -1, -1, -1, -1, -1, -1, 3}, 10, -1, 10, " + + "NumberCodec::ValueOverflow"), + ("fail on deserialization of way too big number for long", + DeserializeLong, + "new int8_t[11]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0}, 11, -1, " + + "10, NumberCodec::ValueOverflow") ).map(Test.tupled) - val system_includes = List("cstdlib", "cstring", "iostream").map(s => s"<$s>") - val local_includes = List("number_codec.hpp").map('"' + _ + '"') + val systemIncludes: List[String] = + List("cstdlib", "cstring", "iostream").map(s => s"<$s>") - def stringify_include(quotedFile: String) = s"#include $quotedFile" + val localIncludes: List[String] = + List("number_codec.hpp").map('"' + _ + '"') - val includes_string = List(system_includes, local_includes) - .map(_.map(stringify_include).mkString("\n")).mkString("", "\n\n", "\n") + def stringifyInclude(quotedFile: String): String = + s"#include $quotedFile" - val enums_string = "\nenum test_t {\n" + tests.map(_.name).zipWithIndex.map { - case (name, index) => - val filteredName = name.replace(' ', '_') - s" $filteredName = $index" - }.mkString("", ",\n", "\n") + "};\n" + val includesStr: String = + List(systemIncludes, localIncludes) + .map(_.map(stringifyInclude).mkString("\n")) + .mkString("", "\n\n", "\n") - def test_serialize_string(camel: String, bits: String) = + val enumsStr: String = + tests.zipWithIndex + .map { + case (test, index) => + val filteredName = test.name.replace(' ', '_') + s" $filteredName = $index" + } + .mkString("\nenum test_t {\n", ",\n", "\n};\n") + + def testSerializeStr(camel: String, cType: String) = s""" -void testSerialize$camel(size_t const bufferSize, int${bits}_t const value, +void testSerialize$camel(size_t const bufferSize, $cType const value, int8_t const * const expectedOutput, size_t const expectedOutputLength, tarsa::NumberCodec::error_t const expectedError) { uint8_t * const buffer = new uint8_t[bufferSize]; memset(buffer, $filler, bufferSize); tarsa::BufferedArrayWriter * writer = - new tarsa::BufferedArrayWriter(buffer, bufferSize, 5); + new tarsa::BufferedArrayWriter(buffer, bufferSize, 1); tarsa::NumberEncoder e(writer); e.serialize$camel(value); @@ -169,13 +247,10 @@ void testSerialize$camel(size_t const bufferSize, int${bits}_t const value, } """ - val test_serialize_int_string = test_serialize_string("Int", "32") - val test_serialize_long_string = test_serialize_string("Long", "64") - - def test_deserialize_string(camel: String, bits: String) = + def testDeserializeStr(camel: String, cType: String) = s""" void testDeserialize$camel(int8_t const * const _input, - size_t const inputLength, int${bits}_t const expectedValue, + size_t const inputLength, $cType const expectedValue, size_t const expectedInputPosition, tarsa::NumberCodec::error_t const expectedError) { uint8_t * const input = new uint8_t[inputLength]; @@ -184,7 +259,7 @@ void testDeserialize$camel(int8_t const * const _input, new tarsa::BufferedArrayReader(input, inputLength, 5); tarsa::NumberDecoder d(reader); - int${bits}_t const decodedValue = d.deserialize$camel(); + $cType const decodedValue = d.deserialize$camel(); std::cout << (decodedValue == expectedValue) << std::endl; std::cout << (reader->getPosition() == expectedInputPosition) << std::endl; @@ -196,23 +271,27 @@ void testDeserialize$camel(int8_t const * const _input, } """ - val test_deserialize_int_string = test_deserialize_string("Int", "32") - val test_deserialize_long_string = test_deserialize_string("Long", "64") - - val main_body = { - val cases = tests.map { case Test(name, mode, params) => - val filteredName = name.replace(' ', '_') - val modeString = mode match { - case SerializeInt => "SerializeInt" - case DeserializeInt => "DeserializeInt" - case SerializeLong => "SerializeLong" - case DeserializeLong => "DeserializeLong" + val mainBody: String = { + val cases = tests + .map { + case Test(name, mode, params) => + val filteredName = name.replace(' ', '_') + val modeString = mode match { + case SerializeBit => "SerializeBit" + case DeserializeBit => "DeserializeBit" + case SerializeByte => "SerializeByte" + case DeserializeByte => "DeserializeByte" + case SerializeInt => "SerializeInt" + case DeserializeInt => "DeserializeInt" + case SerializeLong => "SerializeLong" + case DeserializeLong => "DeserializeLong" + } + s""" case $filteredName: + | test$modeString($params); + | break;""".stripMargin } - "" + - s" case $filteredName:\n" + - s" test$modeString($params);\n" + - s" break;" - }.mkString("\n") + .mkString("\n") + s""" using namespace tarsa; @@ -230,15 +309,28 @@ $cases """ } - val sourceCode = includes_string + enums_string + - test_serialize_int_string + test_serialize_long_string + - test_deserialize_int_string + test_deserialize_long_string + main_body + val sourceCode: String = { + val helperFunctions = + for { + builder <- List(testSerializeStr _, testDeserializeStr _) + (coderType, cType) <- List("Bit" -> "bool", + "Byte" -> "int8_t", + "Int" -> "int32_t", + "Long" -> "int64_t") + } yield { + builder(coderType, cType) + } + (includesStr :: enumsStr :: helperFunctions ::: List(mainBody)).mkString + } val mainSourceFile = "spec.cpp" - val specBuildComponent = NativeBuildComponentFromString(sourceCode, - mainSourceFile) - val buildConfig = NativeBuildConfig(makeResourceComponents( - ("/pl/tarsa/sortalgobox/natives/", "buffered_io.hpp"), - ("/pl/tarsa/sortalgobox/natives/crossverify/", "number_codec.hpp") - ) :+ specBuildComponent, mainSourceFile) + val specBuildComponent = + NativeBuildComponentFromString(sourceCode, mainSourceFile) + val buildConfig = NativeBuildConfig( + makeResourceComponents( + ("/pl/tarsa/sortalgobox/natives/", "buffered_io.hpp"), + ("/pl/tarsa/sortalgobox/natives/crossverify/", "number_codec.hpp") + ) :+ specBuildComponent, + mainSourceFile + ) } diff --git a/project/Versions.scala b/project/Versions.scala index 6754eb5..9506a7d 100644 --- a/project/Versions.scala +++ b/project/Versions.scala @@ -21,8 +21,8 @@ object Versions { val theScala = "2.12.4" - val akka = "2.5.6" - val akkaHttp = "10.0.10" + val akka = "2.5.8" + val akkaHttp = "10.0.11" val scalaFx = "8.0.144-R12" val scalaTest = "3.0.4" diff --git a/project/build.properties b/project/build.properties index 839ac03..e323605 100644 --- a/project/build.properties +++ b/project/build.properties @@ -18,4 +18,4 @@ # 3. This notice may not be removed or altered from any source distribution. # -sbt.version = 1.0.3 +sbt.version = 1.0.4 diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/bubble.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/bubble.hpp index dbdc0db..4b7953f 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/bubble.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/bubble.hpp @@ -17,27 +17,40 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MAIN_HPP -#define MAIN_HPP +#ifndef BUBBLE_HPP +#define BUBBLE_HPP #include #include "items_handler.hpp" -template class ItemsAgent, typename item_t> -void sort(ItemsAgent agent) { - for (size_t i = agent.size0() - 1; i >= 1; i--) { - for (size_t j = 0; j < i; j++) { - if (agent.compare0(j, j + 1) == tarsa::CompareAbove) { - agent.swap0(j, j + 1); +namespace tarsa { + + template + class Sorter { + ItemsAgent a; + Buffer buf; + + public: + Sorter(ItemsAgent const agent, item_t * const array, + size_t const length): a(agent), + buf(Buffer(array, length, 0)) {} + + void sort() { + for (size_t i = a.size(buf) - 1; i >= 1; i--) { + for (size_t j = 0; j < i; j++) { + if (a.compareGtI(buf, j, j + 1)) { + a.swap(buf, j, j + 1); + } + } } } - } -} + }; -template -void sortPerform(items_handler_t &itemsHandler) { - sort(*itemsHandler.agent); + template + Sorter * makeSorter(items_handler_t &handler) { + return new Sorter(*handler.agent, handler.input, handler.size); + } } -#endif /* MAIN_HPP */ +#endif /* BUBBLE_HPP */ diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/items_handler.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/items_handler.hpp index 8f23b81..205bb2b 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/items_handler.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/items_handler.hpp @@ -25,149 +25,83 @@ #include "utilities.hpp" -#define ITEMS_HANDLER_START 5346324 -#define ITEMS_HANDLER_AGENT_COMPARING ITEMS_HANDLER_START + 1 -#define ITEMS_HANDLER_AGENT_RECORDING_COMPARING ITEMS_HANDLER_START + 2 -#define ITEMS_HANDLER_RAW ITEMS_HANDLER_START + 3 -#define ITEMS_HANDLER_RAW_REFERENCE ITEMS_HANDLER_START + 4 -#define ITEMS_HANDLER_SAB_CACHED ITEMS_HANDLER_START + 5 +#define ITEMS_HANDLER_START -8564120874858705559L +#define ITEMS_HANDLER_AGENT_PLAIN ITEMS_HANDLER_START + 1 +#define ITEMS_HANDLER_AGENT_RECORDING ITEMS_HANDLER_START + 2 +#define ITEMS_HANDLER_REFERENCE ITEMS_HANDLER_START + 3 static_assert( - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING || - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING || - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW || - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW_REFERENCE || - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED || + ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_PLAIN || + ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING || + ITEMS_HANDLER_TYPE == ITEMS_HANDLER_REFERENCE || false, "Valid items handler type must be selected"); -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING -#include "comparing_array_items_agent.hpp" -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING -#include "buffered_io.hpp" -#include "number_codec.hpp" -#include "recording_comparing_items_agent.hpp" +#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING +#define ITEMS_AGENT_TYPE ITEMS_AGENT_TYPE_RECORDING +#else +#define ITEMS_AGENT_TYPE ITEMS_AGENT_TYPE_PLAIN #endif +#include "items_agent.hpp" #include "mwc64x.hpp" template struct items_handler_t { -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING - tarsa::ComparingArrayItemsAgent * agent; -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING - tarsa::BufferedWriter * writer; - tarsa::NumberEncoder * numberEncoder; - tarsa::ComparingArrayItemsAgent * basicAgent; - tarsa::RecordingComparingItemsAgentSetup:: - Result * agent; -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW_REFERENCE || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED item_t * input; size_t size; +#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING + tarsa::BufferedWriter * writer; + tarsa::NumberEncoder * numberEncoder; #endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED - int8_t * scratchpad; -#endif + tarsa::ItemsAgent * agent; }; template -items_handler_t sortItemsHandlerPrepare(item_t * const input, - size_t const size) { -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING +items_handler_t sortItemsHandlerPrepare(size_t const size) { + int32_t * work; + checkZero(posix_memalign((void**) &work, 128, sizeof (int32_t) * size)); + mwc64xFill(work, size); + items_handler_t itemsHandler; + itemsHandler.input = work; + itemsHandler.size = size; +#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING std::string recordingFilePath; std::cin >> recordingFilePath; -#endif - items_handler_t itemsHandler; -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING - itemsHandler.agent = checkNonNull( - new tarsa::ComparingArrayItemsAgent(input, size)); -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING itemsHandler.writer = checkNonNull(new tarsa::BufferedFileWriter( recordingFilePath, 1 << 20, true)); itemsHandler.numberEncoder = checkNonNull( new tarsa::NumberEncoder(itemsHandler.writer)); - itemsHandler.basicAgent = checkNonNull( - new tarsa::ComparingArrayItemsAgent(input, size)); - itemsHandler.agent = checkNonNull(new tarsa:: - RecordingComparingItemsAgentSetup:: - Result(itemsHandler.numberEncoder, *itemsHandler.basicAgent)); -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW_REFERENCE || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED - itemsHandler.input = input; - itemsHandler.size = size; -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED - checkZero(posix_memalign((void**) &itemsHandler.scratchpad, 128, - sizeof (int8_t) * size)); + itemsHandler.agent = checkNonNull( + new tarsa::ItemsAgent(itemsHandler.numberEncoder)); +#else + itemsHandler.agent = checkNonNull(new tarsa::ItemsAgent()); #endif return itemsHandler; } +/** @returns true if agent checks passed */ template -void sortItemsHandlerReleasePreValidation( - items_handler_t &itemsHandler) { -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING +bool sortItemsHandlerFinish(items_handler_t &itemsHandler) { +#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING safeDelete(itemsHandler.agent); itemsHandler.numberEncoder->flush(); + bool const checksPassed = + itemsHandler.numberEncoder->getError() == tarsa::NumberCodec::NoError; safeDelete(itemsHandler.numberEncoder); safeDelete(itemsHandler.writer); -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED - safeFree(itemsHandler.scratchpad); -#endif -} - -template -void sortItemsHandlerReleasePostValidation( - items_handler_t &itemsHandler) { -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING + return checksPassed; +#else safeDelete(itemsHandler.agent); -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING - safeDelete(itemsHandler.basicAgent); + return true; #endif } template bool sortValidate(items_handler_t const &itemsHandler) { -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING -#define compareItemsLt(index1, index2) \ - itemsHandler.agent->compareLt0(index1, index2) -#define getItem(index) itemsHandler.agent->get0(index) -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING -#define compareItemsLt(index1, index2) \ - itemsHandler.basicAgent->compareLt0(index1, index2) -#define getItem(index) itemsHandler.basicAgent->get0(index) -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW_REFERENCE || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED item_t const * const work = itemsHandler.input; -#define compareItemsLt(index1, index2) (work[index1] < work[index2]) -#define getItem(index) work[index] -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_COMPARING - size_t const size = itemsHandler.agent->size0(); -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_AGENT_RECORDING_COMPARING - size_t const size = itemsHandler.basicAgent->size0(); -#endif -#if ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_RAW_REFERENCE || \ - ITEMS_HANDLER_TYPE == ITEMS_HANDLER_SAB_CACHED size_t const size = itemsHandler.size; -#endif -#if ITEMS_HANDLER_TYPE != ITEMS_HANDLER_RAW_REFERENCE +#if ITEMS_HANDLER_TYPE != ITEMS_HANDLER_REFERENCE item_t * reference; checkZero(posix_memalign((void**) &reference, 128, sizeof (item_t) * size)); mwc64xFill(reference, size); @@ -175,14 +109,12 @@ bool sortValidate(items_handler_t const &itemsHandler) { #endif bool valid = true; for (size_t i = 0; valid && (i < size); i++) { - valid &= (i == 0) || !compareItemsLt(i, i - 1); -#if ITEMS_HANDLER_TYPE != ITEMS_HANDLER_RAW_REFERENCE - valid &= getItem(i) == reference[i]; + valid &= (i == 0) || work[i - 1] <= work[i]; +#if ITEMS_HANDLER_TYPE != ITEMS_HANDLER_REFERENCE + valid &= work[i] == reference[i]; #endif } return valid; -#undef compareItems -#undef getItem } #endif // ITEMS_HANDLER_HPP diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/main.cpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/main.cpp index 2a2890c..5c89567 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/main.cpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/common/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -40,27 +40,24 @@ int main(int argc, char** argv) { size_t size; std::cin >> shouldValidate >> size; - int32_t * work; - checkZero(posix_memalign((void**) &work, 128, sizeof (int32_t) * size)); - mwc64xFill(work, size); - - items_handler_t itemsHandler = sortItemsHandlerPrepare(work, size); + items_handler_t itemsHandler = + sortItemsHandlerPrepare(size); + tarsa::Sorter * sorter = tarsa::makeSorter(itemsHandler); auto startingChrono = std::chrono::system_clock::now(); - sortPerform(itemsHandler); + sorter->sort(); auto elapsedChrono = std::chrono::system_clock::now() - startingChrono; uint64_t elapsedChronoNanoseconds = std::chrono::duration_cast(elapsedChrono).count(); printf("%lx\n", elapsedChronoNanoseconds); + safeDelete(sorter); - sortItemsHandlerReleasePreValidation(itemsHandler); + bool const agentChecksPassed = sortItemsHandlerFinish(itemsHandler); if (shouldValidate) { - bool const valid = sortValidate(itemsHandler); + bool const valid = agentChecksPassed && sortValidate(itemsHandler); std::cout << (valid ? "pass" : "fail") << std::endl; } - sortItemsHandlerReleasePostValidation(itemsHandler); - return EXIT_SUCCESS; } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/insertion.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/insertion.hpp index 89764db..616be51 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/insertion.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/insertion.hpp @@ -17,28 +17,41 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MAIN_HPP -#define MAIN_HPP +#ifndef INSERTION_HPP +#define INSERTION_HPP #include #include "items_handler.hpp" -template class ItemsAgent, typename item_t> -void sort(ItemsAgent agent) { - size_t const size = agent.size0(); - for (size_t i = 1; i < size; i++) { - size_t j = i; - while (j > 0 && agent.compare0(j - 1, j) == tarsa::CompareAbove) { - agent.swap0(j - 1, j); - j -= 1; +namespace tarsa { + + template + class Sorter { + ItemsAgent a; + Buffer buf; + + public: + Sorter(ItemsAgent const agent, item_t * const array, + size_t const length): a(agent), + buf(Buffer(array, length, 0)) {} + + void sort() { + size_t const size = a.size(buf); + for (size_t i = 1; i < size; i++) { + size_t j = i; + while (j > 0 && a.compareGtI(buf, j - 1, j)) { + a.swap(buf, j - 1, j); + j -= 1; + } + } } - } -} + }; -template -void sortPerform(items_handler_t &itemsHandler) { - sort(*itemsHandler.agent); + template + Sorter * makeSorter(items_handler_t &handler) { + return new Sorter(*handler.agent, handler.input, handler.size); + } } -#endif /* MAIN_HPP */ +#endif /* INSERTION_HPP */ diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sabmain.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sabmain.hpp index 4698d05..7a3e0ca 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sabmain.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sabmain.hpp @@ -22,11 +22,4 @@ #include xstr(SORT_HEADER) -using namespace tarsa; - -template -void sortPerform(items_handler_t &itemsHandler) { - tarsa::SORT_ALGO(*itemsHandler.agent); -} - #endif /* SABMAIN_HPP */ diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortalgocommon.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortalgocommon.hpp index b636a4f..fe465eb 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortalgocommon.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortalgocommon.hpp @@ -22,7 +22,4 @@ #ifndef SORTALGOCOMMON_HPP #define SORTALGOCOMMON_HPP -namespace tarsa { -} - #endif /* SORTALGOCOMMON_HPP */ diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortheapbinaryonebasedvarianta.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortheapbinaryonebasedvarianta.hpp index e697e19..74303a7 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortheapbinaryonebasedvarianta.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/agent/sortheapbinaryonebasedvarianta.hpp @@ -26,21 +26,23 @@ namespace tarsa { - template class ItemsAgent, typename item_t> - class TheSorter { - ItemsAgent agent; + template + class Sorter { + ItemsAgent a; + Buffer buf; public: - TheSorter(ItemsAgent agent): agent(agent) { - } + Sorter(ItemsAgent const agent, item_t * const array, + size_t const length): a(agent), + buf(Buffer(array - 1, length, 0)) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } void heapify() { - size_t const count = agent.size0(); + size_t const count = a.size(buf); for (ssize_t item = count / 2; item >= 1; item--) { siftDown(item, count); } @@ -53,25 +55,25 @@ namespace tarsa { ssize_t const right = left + 1; if (right <= end) { - if (agent.compareLt0(root, left)) { - if (agent.compareLt0(left, right)) { - agent.swap0(root, right); + if (a.compareLtI(buf, root, left)) { + if (a.compareLtI(buf, left, right)) { + a.swap(buf, root, right); root = right; } else { - agent.swap0(root, left); + a.swap(buf, root, left); root = left; } } else { - if (agent.compareLt0(root, right)) { - agent.swap0(root, right); + if (a.compareLtI(buf, root, right)) { + a.swap(buf, root, right); root = right; } else { return; } } } else { - if (left == end && agent.compareLt0(root, left)) { - agent.swap0(root, left); + if (left == end && a.compareLtI(buf, root, left)) { + a.swap(buf, root, left); } return; } @@ -79,22 +81,17 @@ namespace tarsa { } void drainHeap() { - size_t const count = agent.size0(); + size_t const count = a.size(buf); for (ssize_t next = count; next > 1; next--) { - agent.swap0(next, 1); + a.swap(buf, next, 1); siftDown(1, next - 1); } } }; - template class ItemsAgent, typename item_t> - void OneBasedBinaryHeapSortVariantA(ItemsAgent agent) { - TheSorter(agent).heapsort(); - } - - template class ItemsAgent, typename item_t> - void OneBasedBinaryHeapSortVariantA(ItemsAgent agent) { - OneBasedBinaryHeapSortVariantA(agent.withBase1()); + template + Sorter * makeSorter(items_handler_t &handler) { + return new Sorter(*handler.agent, handler.input, handler.size); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sabmain.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sabmain.hpp index 544c14f..675ab48 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sabmain.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sabmain.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -20,28 +20,14 @@ #ifndef SABMAIN_HPP #define SABMAIN_HPP -#if defined(SORT_CACHED) && defined(SORT_SIMD) -#error Unsupported combination -#endif - #include xstr(SORT_HEADER) -using namespace tarsa; - -#define ComparisonOperator genericComparisonOperator +namespace tarsa { -template -void sortPerform(items_handler_t &itemsHandler) { - int32_t * const work = itemsHandler.input; - size_t const size = itemsHandler.size; -#if defined(SORT_SIMD) - tarsa::SORT_ALGO(work, size); -#elif defined(SORT_CACHED) - tarsa::SORT_ALGO(work, size, - itemsHandler.scratchpad); -#else - tarsa::SORT_ALGO(work, size); -#endif + template + Sorter * makeSorter(items_handler_t &handler) { + return makeSorter(handler.input, handler.size); + } } #endif /* SABMAIN_HPP */ diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevarianta.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevarianta.hpp index 6fc290c..ba6507e 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevarianta.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevarianta.hpp @@ -70,26 +70,20 @@ namespace tarsa { public: TheSorter(ItemType * const a, ssize_t const count): - a(a), count(count) { - } + a(a - 1), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp> - void BinaryHeapSortAheadSimpleVariantA(ItemType * const a, - ssize_t const count) { - TheSorter(a - 1, count).heapsort(); - } + template + using Sorter = TheSorter; template - void BinaryHeapSortAheadSimpleVariantA(ItemType * const a, - ssize_t const count) { - BinaryHeapSortAheadSimpleVariantA( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevariantb.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevariantb.hpp index c35c693..f5bf50d 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevariantb.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryaheadsimplevariantb.hpp @@ -68,26 +68,21 @@ namespace tarsa { public: TheSorter(ItemType * const a, ssize_t const count): - a(a), count(count) { + a(a - 1), count(count) { } - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp> - void BinaryHeapSortAheadSimpleVariantB(ItemType * const a, - ssize_t const count) { - TheSorter(a - 1, count).heapsort(); - } + template + using Sorter = TheSorter; template - void BinaryHeapSortAheadSimpleVariantB(ItemType * const a, - ssize_t const count) { - BinaryHeapSortAheadSimpleVariantB( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycached.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycached.hpp index 7146936..9d533af 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycached.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycached.hpp @@ -413,11 +413,14 @@ namespace tarsa { public: TheSorter(ItemType * const a, ssize_t const count, - int8_t * const cachedComparisonsTable): - a(a), count(count), cachedComparisonsTable(cachedComparisonsTable) { + int8_t * const scratchpad): a(a), count(count), + cachedComparisonsTable(scratchpad) {} + + virtual ~TheSorter() { + free(cachedComparisonsTable); } - void heapsort() { + void sort() { heapify(); initCachedComparisons(); #ifndef NDEBUG @@ -427,17 +430,16 @@ namespace tarsa { } }; - template compOp> - void CachedComparisonsBinaryHeapSort(ItemType * const a, - ssize_t const count, int8_t * const scratchpad) { - TheSorter(a, count, scratchpad).heapsort(); - } + template + using Sorter = TheSorter; template - void CachedComparisonsBinaryHeapSort(ItemType * const a, - ssize_t const count, int8_t * const scratchpad) { - CachedComparisonsBinaryHeapSort( - a, count, scratchpad); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + int8_t * scratchpad; + checkZero(posix_memalign((void**) &scratchpad, 128, + sizeof (int8_t) * count)); + return new TheSorter(a, count, + scratchpad); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvarianta.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvarianta.hpp index a15ef06..4ca6556 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvarianta.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvarianta.hpp @@ -114,26 +114,21 @@ namespace tarsa { } public: - TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { - } + TheSorter(ItemType * const a, ssize_t const count): + a(a - 1), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp> - void BinaryHeapSortCascadingVariantA(ItemType * const a, - ssize_t const count) { - TheSorter(a - 1, count).heapsort(); - } + template + using Sorter = TheSorter; template - void BinaryHeapSortCascadingVariantA(ItemType * const a, - ssize_t const count) { - BinaryHeapSortCascadingVariantA( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvariantb.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvariantb.hpp index 0933d07..8af199e 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvariantb.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinarycascadingvariantb.hpp @@ -155,26 +155,21 @@ namespace tarsa { } public: - TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { - } + TheSorter(ItemType * const a, ssize_t const count): + a(a - 1), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp> - void BinaryHeapSortCascadingVariantB(ItemType * const a, - ssize_t const count) { - TheSorter(a - 1, count).heapsort(); - } + template + using Sorter = TheSorter; template - void BinaryHeapSortCascadingVariantB(ItemType * const a, - ssize_t const count) { - BinaryHeapSortCascadingVariantB( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvarianta.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvarianta.hpp index e62c7bf..c906814 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvarianta.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvarianta.hpp @@ -143,27 +143,21 @@ namespace tarsa { } public: - TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { - } + TheSorter(ItemType * const a, ssize_t const count): + a(a), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp, - ssize_t clusterLevels = 4 > - void ClusteredBinaryHeapSortVariantA(ItemType * const a, - ssize_t const count) { - TheSorter(a, count).heapsort(); - } + template + using Sorter = TheSorter; template - void ClusteredBinaryHeapSortVariantA(ItemType * const a, - ssize_t const count) { - ClusteredBinaryHeapSortVariantA( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvariantb.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvariantb.hpp index 888f0a3..622a0f4 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvariantb.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryclusteredvariantb.hpp @@ -259,27 +259,21 @@ namespace tarsa { } public: - TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { - } + TheSorter(ItemType * const a, ssize_t const count): + a(a), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp, - ssize_t clusterLevels = 5 > - void ClusteredBinaryHeapSortVariantB(ItemType * const a, - ssize_t const count) { - TheSorter(a, count).heapsort(); - } + template + using Sorter = TheSorter; template - void ClusteredBinaryHeapSortVariantB(ItemType * const a, - ssize_t const count) { - ClusteredBinaryHeapSortVariantB( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvarianta.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvarianta.hpp index 618a7b3..0bb4984 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvarianta.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvarianta.hpp @@ -77,26 +77,21 @@ namespace tarsa { } public: - TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { - } + TheSorter(ItemType * const a, ssize_t const count): + a(a - 1), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp> - void ClassicOneBasedBinaryHeapSortVariantA(ItemType * const a, - ssize_t const count) { - TheSorter(a - 1, count).heapsort(); - } + template + using Sorter = TheSorter; template - void ClassicOneBasedBinaryHeapSortVariantA(ItemType * const a, - ssize_t const count) { - ClassicOneBasedBinaryHeapSortVariantA(a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvariantb.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvariantb.hpp index 1368fa6..4b79151 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvariantb.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapbinaryonebasedvariantb.hpp @@ -76,26 +76,21 @@ namespace tarsa { } public: - TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { - } + TheSorter(ItemType * const a, ssize_t const count): + a(a - 1), count(count) {} - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template compOp> - void OneBasedBinaryHeapSortVariantB(ItemType * const a, - ssize_t const count) { - TheSorter(a - 1, count).heapsort(); - } + template + using Sorter = TheSorter; template - void OneBasedBinaryHeapSortVariantB(ItemType * const a, - ssize_t const count) { - OneBasedBinaryHeapSortVariantB( - a, count); + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantb.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantb.hpp index 267311f..880a3ad 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantb.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantb.hpp @@ -92,6 +92,11 @@ namespace tarsa { ssize_t queueStoreIndex; ssize_t queue[QueueSize]; + static_assert(Payload == false, "payload not implemented"); + static_assert(std::is_same::value || + std::is_same::value, + "parameters invalid or specialization missing"); + /* * based on: http://stackoverflow.com/a/23592221/492749 */ @@ -184,21 +189,19 @@ namespace tarsa { TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { } - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template - void SimdDwordCascadingHeapSortVariantB(ItemType * const a, - ssize_t const count) { - static_assert(Payload == false, "payload not implemented"); - bool constexpr ok = std::is_same::value - || std::is_same::value; - static_assert(ok, "parameters invalid or specialization missing"); - TheSorter::value, Ascending, - Payload>(a, count).heapsort(); + template + using Sorter = TheSorter; + + template + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter::value, + true, false>(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantc.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantc.hpp index 0b927ce..0b44cf5 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantc.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordcascadingvariantc.hpp @@ -92,6 +92,11 @@ namespace tarsa { ssize_t queueStoreIndex; ssize_t queue[QueueSize]; + static_assert(Payload == false, "payload not implemented"); + static_assert(std::is_same::value || + std::is_same::value, + "parameters invalid or specialization missing"); + /* * based on: http://stackoverflow.com/a/23593786/492749 */ @@ -188,21 +193,19 @@ namespace tarsa { TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { } - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template - void SimdDwordCascadingHeapSortVariantC(ItemType * const a, - ssize_t const count) { - static_assert(Payload == false, "payload not implemented"); - bool constexpr ok = std::is_same::value - || std::is_same::value; - static_assert(ok, "parameters invalid or specialization missing"); - TheSorter::value, Ascending, - Payload>(a, count).heapsort(); + template + using Sorter = TheSorter; + + template + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter::value, + true, false>(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantb.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantb.hpp index 84b8a02..588059e 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantb.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantb.hpp @@ -87,6 +87,11 @@ namespace tarsa { ItemType * const a; ssize_t const count; + static_assert(Payload == false, "payload not implemented"); + static_assert(std::is_same::value || + std::is_same::value, + "parameters invalid or specialization missing"); + /* * based on: http://stackoverflow.com/a/23592221/492749 */ @@ -145,21 +150,19 @@ namespace tarsa { TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { } - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template - void SimdDwordHeapSortVariantB(ItemType * const a, - ssize_t const count) { - static_assert(Payload == false, "payload not implemented"); - bool constexpr ok = std::is_same::value - || std::is_same::value; - static_assert(ok, "parameters invalid or specialization missing"); - TheSorter::value, Ascending, - Payload>(a, count).heapsort(); + template + using Sorter = TheSorter; + + template + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter::value, + true, false>(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantc.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantc.hpp index 1e9c377..6bed707 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantc.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortheapsimddwordvariantc.hpp @@ -87,6 +87,11 @@ namespace tarsa { ItemType * const a; ssize_t const count; + static_assert(Payload == false, "payload not implemented"); + static_assert(std::is_same::value || + std::is_same::value, + "parameters invalid or specialization missing"); + /* * based on: http://stackoverflow.com/a/23593786/492749 */ @@ -149,21 +154,19 @@ namespace tarsa { TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { } - void heapsort() { + void sort() { heapify(); drainHeap(); } }; - template - void SimdDwordHeapSortVariantC(ItemType * const a, - ssize_t const count) { - static_assert(Payload == false, "payload not implemented"); - bool constexpr ok = std::is_same::value - || std::is_same::value; - static_assert(ok, "parameters invalid or specialization missing"); - TheSorter::value, Ascending, - Payload>(a, count).heapsort(); + template + using Sorter = TheSorter; + + template + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter::value, + true, false>(a, count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortquickrandomized.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortquickrandomized.hpp index a100269..a83a7c1 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortquickrandomized.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/sab/classic/sortquickrandomized.hpp @@ -1,7 +1,7 @@ /* * sortquickrandomized.hpp -- sorting algorithms benchmark * - * Copyright (C) 2014 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2014 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -27,12 +27,13 @@ namespace tarsa { - namespace privateRandomizedQuickSort { + template compOp, + ssize_t threshold> + class TheSorter { + ItemType * const a; + ssize_t const count; - template compOp, - ssize_t threshold> - void quicksort(ItemType * const a, ssize_t const left, - ssize_t const right) { + void quicksort(ssize_t const left, ssize_t const right) { ItemType x; if (right - left > threshold) { x = a[(rand() % (right - left + 1)) + left]; @@ -53,22 +54,26 @@ namespace tarsa { } } - if (left < j) quicksort(a, left, j); - if (right > i) quicksort(a, i, right); + if (left < j) quicksort(left, j); + if (right > i) quicksort(i, right); } - } - template compOp, - ssize_t threshold = 100 > - void RandomizedQuickSort(ItemType * const a, ssize_t const count) { - privateRandomizedQuickSort::quicksort( - a, 0, count - 1); - } + public: + TheSorter(ItemType * const a, ssize_t const count): a(a), count(count) { + } + + void sort() { + quicksort(0, count - 1); + } + }; + + template + using Sorter = TheSorter; - template - void RandomizedQuickSort(ItemType * const a, ssize_t const count) { - RandomizedQuickSort( - a, count); + template + Sorter * makeSorter(ItemType * const a, ssize_t const count) { + return new TheSorter(a, + count); } } diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/selection.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/selection.hpp index b244183..df8f25d 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/selection.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/selection.hpp @@ -17,30 +17,43 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MAIN_HPP -#define MAIN_HPP +#ifndef SELECTION_HPP +#define SELECTION_HPP #include #include "items_handler.hpp" -template class ItemsAgent, typename item_t> -void sort(ItemsAgent agent) { - size_t const size = agent.size0(); - for (size_t i = 0; i < size - 1; i++) { - size_t minIndex = i; - for (size_t j = i + 1; j < size; j++) { - if (agent.compare0(minIndex, j) == tarsa::CompareAbove) { - minIndex = j; +namespace tarsa { + + template + class Sorter { + ItemsAgent a; + Buffer buf; + + public: + Sorter(ItemsAgent const agent, item_t * const array, + size_t const length): a(agent), + buf(Buffer(array, length, 0)) {} + + void sort() { + size_t const size = a.size(buf); + for (size_t i = 0; i < size - 1; i++) { + size_t minIndex = i; + for (size_t j = i + 1; j < size; j++) { + if (a.compareGtI(buf, minIndex, j)) { + minIndex = j; + } + } + a.swap(buf, i, minIndex); } } - agent.swap0(i, minIndex); - } -} + }; -template -void sortPerform(items_handler_t &itemsHandler) { - sort(*itemsHandler.agent); + template + Sorter * makeSorter(items_handler_t &handler) { + return new Sorter(*handler.agent, handler.input, handler.size); + } } -#endif /* MAIN_HPP */ +#endif /* SELECTION_HPP */ diff --git a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/std__sort.hpp b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/std__sort.hpp index 9bd8e85..4e9d152 100644 --- a/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/std__sort.hpp +++ b/sorts/main_rsrc/pl/tarsa/sortalgobox/sorts/natives/std__sort.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -17,15 +17,31 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MAIN_HPP -#define MAIN_HPP +#ifndef STD__SORT_HPP +#define STD__SORT_HPP #include "items_handler.hpp" -template -void sortPerform(items_handler_t &itemsHandler) { - item_t * const work = itemsHandler.input; - std::sort(work, work + itemsHandler.size); +namespace tarsa { + + template + class Sorter { + item_t * const array; + size_t const length; + + public: + Sorter(item_t * const array, size_t const length): array(array), + length(length) {} + + void sort() { + std::sort(array, array + length); + } + }; + + template + Sorter * makeSorter(items_handler_t &handler) { + return new Sorter(handler.input, handler.size); + } } -#endif /* MAIN_HPP */ +#endif /* STD__SORT_HPP */ diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeItemsAgentSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeItemsAgentSort.scala index 2cac50d..d37776b 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeItemsAgentSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeItemsAgentSort.scala @@ -23,6 +23,7 @@ import java.lang.Long.parseLong import java.nio.file.Path import pl.tarsa.sortalgobox.core.NativeBenchmark +import pl.tarsa.sortalgobox.core.exceptions.VerificationFailedException import pl.tarsa.sortalgobox.natives.agents.ItemsAgentsBuildComponents import pl.tarsa.sortalgobox.natives.build.{ CompilerDefine, @@ -45,9 +46,9 @@ abstract class NativeItemsAgentSort( override val buildConfig: NativeBuildConfig = { val algoDefines = Seq( CompilerDefine("ITEMS_HANDLER_TYPE", if (recordingFileOpt.isDefined) { - Some("ITEMS_HANDLER_AGENT_RECORDING_COMPARING") + Some("ITEMS_HANDLER_AGENT_RECORDING") } else { - Some("ITEMS_HANDLER_AGENT_COMPARING") + Some("ITEMS_HANDLER_AGENT_PLAIN") }), CompilerDefine("SORT_MECHANICS", Some(sortAlgorithmComponent.fileName)) ) @@ -74,8 +75,15 @@ abstract class NativeItemsAgentSort( val execResult = nativesCache.runCachedProgram(buildConfig, input) val lines = execResult.stdOut.lines.toList if (validate) { - val valid = lines(1) == "pass" - assert(valid) + val valid = lines.isDefinedAt(1) && lines(1) == "pass" + if (!valid) { + val errorMsg = s"""$name failed: + |- exit code: ${execResult.exitValue} + |- stdOut: ${execResult.stdOut} + |- stdErr: ${execResult.stdErr} + """.stripMargin + throw new VerificationFailedException(errorMsg) + } } val nanosTaken = parseLong(lines.head, 16) Duration.fromNanos(nanosTaken) diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeStdSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeStdSort.scala index ee4d186..9fc2205 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeStdSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/NativeStdSort.scala @@ -22,6 +22,7 @@ package pl.tarsa.sortalgobox.sorts.natives import java.lang.Long.parseLong import pl.tarsa.sortalgobox.core.NativeBenchmark +import pl.tarsa.sortalgobox.core.exceptions.VerificationFailedException import pl.tarsa.sortalgobox.natives.build.{ CompilerDefine, CompilerOptions, @@ -42,7 +43,7 @@ class NativeStdSort(parallel: Boolean, override val buildConfig: NativeBuildConfig = { val algoDefines = Seq( - CompilerDefine("ITEMS_HANDLER_TYPE", Some("ITEMS_HANDLER_RAW_REFERENCE")), + CompilerDefine("ITEMS_HANDLER_TYPE", Some("ITEMS_HANDLER_REFERENCE")), CompilerDefine("SORT_MECHANICS", Some("std__sort.hpp"))) ++ Some(CompilerDefine("_GLIBCXX_PARALLEL", None)).filter(_ => parallel) val compilerOptions = CompilerOptions( @@ -57,9 +58,17 @@ class NativeStdSort(parallel: Boolean, val execResult = nativesCache.runCachedProgram(buildConfig, input) val lines = execResult.stdOut.lines.toList if (validate) { - val valid = lines(1) == "pass" - assert(valid) + val valid = lines.isDefinedAt(1) && lines(1) == "pass" + if (!valid) { + val errorMsg = s"""$name failed: + |- exit code: ${execResult.exitValue} + |- stdOut: ${execResult.stdOut} + |- stdErr: ${execResult.stdErr} + """.stripMargin + throw new VerificationFailedException(errorMsg) + } } + val nanosTaken = parseLong(lines.head, 16) Duration.fromNanos(nanosTaken) } @@ -70,6 +79,7 @@ object NativeStdSort extends NativeComponentsSupport { NativeMwc64x.header ++ makeResourceComponents( ("/pl/tarsa/sortalgobox/natives/", "macros.hpp"), ("/pl/tarsa/sortalgobox/natives/", "utilities.hpp"), + ("/pl/tarsa/sortalgobox/natives/agents/", "items_agent.hpp"), ("/pl/tarsa/sortalgobox/sorts/natives/common/", "main.cpp"), ("/pl/tarsa/sortalgobox/sorts/natives/common/", "items_handler.hpp"), ("/pl/tarsa/sortalgobox/sorts/natives/", "std__sort.hpp") diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/agent/AgentSabBenchmark.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/agent/AgentSabBenchmark.scala index f4a9fc7..206a16c 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/agent/AgentSabBenchmark.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/agent/AgentSabBenchmark.scala @@ -23,6 +23,7 @@ import java.lang.Long.parseLong import java.nio.file.Path import pl.tarsa.sortalgobox.core.NativeBenchmark +import pl.tarsa.sortalgobox.core.exceptions.VerificationFailedException import pl.tarsa.sortalgobox.natives.build.{ CompilerDefine, CompilerOptions, @@ -44,9 +45,9 @@ abstract class AgentSabBenchmark(sortAlgoName: String, override val buildConfig: NativeBuildConfig = { val algoDefines = Seq( CompilerDefine("ITEMS_HANDLER_TYPE", if (recordingFileOpt.isDefined) { - Some("ITEMS_HANDLER_AGENT_RECORDING_COMPARING") + Some("ITEMS_HANDLER_AGENT_RECORDING") } else { - Some("ITEMS_HANDLER_AGENT_COMPARING") + Some("ITEMS_HANDLER_AGENT_PLAIN") }), CompilerDefine("SORT_ALGO", Some(sortAlgoName)), CompilerDefine("SORT_HEADER", Some(sortHeader)), @@ -75,9 +76,17 @@ abstract class AgentSabBenchmark(sortAlgoName: String, val execResult = nativesCache.runCachedProgram(buildConfig, input) val lines = execResult.stdOut.lines.toList if (validate) { - val valid = lines(1) == "pass" - assert(valid) + val valid = lines.isDefinedAt(1) && lines(1) == "pass" + if (!valid) { + val errorMsg = s"""$name failed: + |- exit code: ${execResult.exitValue} + |- stdOut: ${execResult.stdOut} + |- stdErr: ${execResult.stdErr} + """.stripMargin + throw new VerificationFailedException(errorMsg) + } } + val nanosTaken = parseLong(lines.head, 16) Duration.fromNanos(nanosTaken) } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabBenchmark.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabBenchmark.scala index 3e03933..1e4262f 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabBenchmark.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabBenchmark.scala @@ -37,23 +37,16 @@ import scala.concurrent.duration.{Duration, FiniteDuration} class ClassicSabBenchmark(sortAlgoName: String, sortHeader: String, - nativesCache: NativesCache, - itemsHandlerType: String = "ITEMS_HANDLER_RAW", - sortCached: Boolean = false, - sortSimd: Boolean = false) + nativesCache: NativesCache) extends NativeBenchmark { override val buildConfig: NativeBuildConfig = { - val sortTypeDefines = Seq( - ("SORT_CACHED", sortCached), - ("SORT_SIMD", sortSimd) - ).collect { case (defineName, true) => CompilerDefine(defineName, None) } val algoDefines = Seq( - CompilerDefine("ITEMS_HANDLER_TYPE", Some(itemsHandlerType)), + CompilerDefine("ITEMS_HANDLER_TYPE", Some("ITEMS_HANDLER_AGENT_PLAIN")), CompilerDefine("SORT_ALGO", Some(sortAlgoName)), CompilerDefine("SORT_HEADER", Some(sortHeader)), CompilerDefine("SORT_MECHANICS", Some("sabmain.hpp")) - ) ++ sortTypeDefines + ) val compilerOptions = CompilerOptions( defines = CompilerOptions.defaultDefines ++ algoDefines) NativeBuildConfig(ClassicSabBenchmark.components(sortHeader), @@ -68,9 +61,14 @@ class ClassicSabBenchmark(sortAlgoName: String, val execResult = nativesCache.runCachedProgram(buildConfig, input) val lines = execResult.stdOut.lines.toList if (validate) { - val valid = lines(1) == "pass" + val valid = lines.isDefinedAt(1) && lines(1) == "pass" if (!valid) { - throw new VerificationFailedException() + val errorMsg = s"""$sortAlgoName failed: + |- exit code: ${execResult.exitValue} + |- stdOut: ${execResult.stdOut} + |- stdErr: ${execResult.stdErr} + """.stripMargin + throw new VerificationFailedException(errorMsg) } } val nanosTaken = parseLong(lines.head, 16) @@ -85,6 +83,7 @@ object ClassicSabBenchmark extends NativeComponentsSupport { NativeMwc64x.header ++ makeResourceComponents( ("/pl/tarsa/sortalgobox/natives/", "macros.hpp"), ("/pl/tarsa/sortalgobox/natives/", "utilities.hpp"), + ("/pl/tarsa/sortalgobox/natives/agents/", "items_agent.hpp"), ("/pl/tarsa/sortalgobox/sorts/natives/common/", "main.cpp"), ("/pl/tarsa/sortalgobox/sorts/natives/common/", "items_handler.hpp"), (sabNamePrefix, "sabmain.hpp"), diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapBinaryCached.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapBinaryCached.scala index 19bc2a4..9b12317 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapBinaryCached.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapBinaryCached.scala @@ -26,4 +26,4 @@ class ClassicSabHeapBinaryCached( extends ClassicSabBenchmark( sortAlgoName = "CachedComparisonsBinaryHeapSort", sortHeader = "sortheapbinarycached.hpp", - nativesCache, "ITEMS_HANDLER_SAB_CACHED", sortCached = true) + nativesCache) diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantB.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantB.scala index 418bc71..c896085 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantB.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantB.scala @@ -26,4 +26,4 @@ class ClassicSabHeapSimdDwordCascadingVariantB( extends ClassicSabBenchmark( sortAlgoName = "SimdDwordCascadingHeapSortVariantB", sortHeader = "sortheapsimddwordcascadingvariantb.hpp", - nativesCache, sortSimd = true) + nativesCache) diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantC.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantC.scala index b0e7573..782b09e 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantC.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordCascadingVariantC.scala @@ -26,4 +26,4 @@ class ClassicSabHeapSimdDwordCascadingVariantC( extends ClassicSabBenchmark( sortAlgoName = "SimdDwordCascadingHeapSortVariantC", sortHeader = "sortheapsimddwordcascadingvariantc.hpp", - nativesCache, sortSimd = true) + nativesCache) diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantB.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantB.scala index b7300c6..9d71734 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantB.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantB.scala @@ -26,4 +26,4 @@ class ClassicSabHeapSimdDwordVariantB( extends ClassicSabBenchmark( sortAlgoName = "SimdDwordHeapSortVariantB", sortHeader = "sortheapsimddwordvariantb.hpp", - nativesCache, sortSimd = true) + nativesCache) diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantC.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantC.scala index 11bb291..b1da869 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantC.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/natives/sab/classic/ClassicSabHeapSimdDwordVariantC.scala @@ -26,4 +26,4 @@ class ClassicSabHeapSimdDwordVariantC( extends ClassicSabBenchmark( sortAlgoName = "SimdDwordHeapSortVariantC", sortHeader = "sortheapsimddwordvariantc.hpp", - nativesCache, sortSimd = true) + nativesCache) diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/GpuBitonicSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/GpuBitonicSort.scala index 2965938..fe0b21a 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/GpuBitonicSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/GpuBitonicSort.scala @@ -23,7 +23,7 @@ import java.nio.{ByteBuffer, ByteOrder} import org.jocl.CL._ import org.jocl.{Pointer, Sizeof, cl_event, cl_mem} -import pl.tarsa.sortalgobox.core.common.MeasuredSortAlgorithm +import pl.tarsa.sortalgobox.core.common.SelfMeasuredSortAlgorithm import pl.tarsa.sortalgobox.opencl.{ CLCache, CLDeviceContext, @@ -34,7 +34,7 @@ import pl.tarsa.sortalgobox.opencl.{ import scala.concurrent.duration.{Duration, FiniteDuration} import scala.io.Source -object GpuBitonicSort extends MeasuredSortAlgorithm[Int] { +object GpuBitonicSort extends SelfMeasuredSortAlgorithm[Int] { val sourceCodePath = "/pl/tarsa/sortalgobox/sorts/opencl/GpuBitonicSort.cl" override def sort(array: Array[Int]): FiniteDuration = diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/common/CpuSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/common/CpuSort.scala index d8cb70b..c3dc8ad 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/common/CpuSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/opencl/common/CpuSort.scala @@ -23,7 +23,7 @@ import java.nio.{ByteBuffer, ByteOrder} import org.jocl.CL._ import org.jocl.{Pointer, Sizeof, cl_event, cl_mem} -import pl.tarsa.sortalgobox.core.common.MeasuredSortAlgorithm +import pl.tarsa.sortalgobox.core.common.SelfMeasuredSortAlgorithm import pl.tarsa.sortalgobox.opencl.{ CLCache, CLDeviceContext, @@ -34,7 +34,7 @@ import pl.tarsa.sortalgobox.opencl.{ import scala.concurrent.duration.{Duration, FiniteDuration} import scala.io.Source -class CpuSort(sourceCodePath: String) extends MeasuredSortAlgorithm[Int] { +class CpuSort(sourceCodePath: String) extends SelfMeasuredSortAlgorithm[Int] { override def sort(array: Array[Int]): FiniteDuration = CLCache.withCpuContext(sort(array, _)) diff --git a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ItemsAgent.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/ComparisonSortBase.scala similarity index 56% rename from core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ItemsAgent.scala rename to sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/ComparisonSortBase.scala index b817076..0ef1ce2 100644 --- a/core/main_scala/pl/tarsa/sortalgobox/core/common/agents/ItemsAgent.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/ComparisonSortBase.scala @@ -17,24 +17,22 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ -package pl.tarsa.sortalgobox.core.common.agents +package pl.tarsa.sortalgobox.sorts.scala -abstract class ItemsAgent[ItemType] { - type SelfType <: ItemsAgent[ItemType] +import pl.tarsa.sortalgobox.core.common.ComparableItemsAgentSortAlgorithm +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer +import scala.{specialized => spec} - def withBase(newIndexingBase: Int): SelfType +abstract class ComparisonSortBase extends ComparableItemsAgentSortAlgorithm { + class Setup[@spec(Group) Item: Permit]( + val buffer1: ComparableItemsBuffer[Item]) - def size0: Int + override def setupSort[@spec(Group) Item: Ordering]( + items: Array[Item]): Setup[Item] = + new Setup(ComparableItemsBuffer(0, items, 0)) - def get0(i: Int): ItemType - - def set0(i: Int, v: ItemType): Unit - - def copy0(i: Int, j: Int, n: Int) - - def swap0(i: Int, j: Int): Unit = { - val temp = get0(i) - set0(i, get0(j)) - set0(j, temp) - } + protected final def buf1[@spec(Group) Item: Setup] + : ComparableItemsBuffer[Item] = + setup[Item].buffer1 } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSort.scala index 1418db8..b58eedd 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,20 +16,19 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.bitonic -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -class BitonicSort extends ComparisonSortAlgorithm { - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ +object BitonicSort extends ComparisonSortBase { + override def sort[@specialized(Group) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] - val size = size0 - val phasesPerBlock = Stream.iterate(1)(_ + 1) + val size = a.size(buf) + val phasesPerBlock = Iterator + .iterate(1)(_ + 1) .takeWhile(phases => (1L << (phases - 1)) < size) for (phasesInBlock <- phasesPerBlock; phase <- phasesInBlock to 1 by -1) { @@ -45,8 +44,8 @@ class BitonicSort extends ComparisonSortAlgorithm { val lower = upper + halfBlockSize (upper, lower) } - if (second < size && compare0(first, second) > 0) { - swap0(first, second) + if (second < size && a.compareGtI(buf, first, second)) { + a.swap(buf, first, second) } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSort.scala index 4ff36d7..7aad8c7 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,22 +16,20 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.bubble -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -class BubbleSort extends ComparisonSortAlgorithm { - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ +object BubbleSort extends ComparisonSortBase { + override def sort[@specialized(Group) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] - for (i <- size0 - 1 to 1 by -1; + for (i <- a.size(buf) - 1 to 1 by -1; j <- 0 until i) { - if (compare0(j, j + 1) > 0) { - swap0(j, j + 1) + if (a.compareGtI(buf, j, j + 1)) { + a.swap(buf, j, j + 1) } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeap.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeap.scala index b14d54f..264f1a3 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeap.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeap.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,28 +16,31 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.heap -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.agents.ItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer import scala.annotation.tailrec -class BinaryHeap[ItemType](val itemsAgent: ComparingItemsAgent[ItemType]) { +class BinaryHeap[@specialized(Group) Item] protected[heap] ( + val itemsAgent: ItemsAgent, + val buf: ComparableItemsBuffer[Item]) { import itemsAgent._ var size = 0 - def addElem(a: ItemType): Unit = { - set0(size, a) + def addElem(a: Item): Unit = { + set(buf, size, a) size += 1 siftUp(size - 1) } - def extractTop: ItemType = { - val result = get0(0) - set0(0, get0(size - 1)) + def extractTop: Item = { + val result = get(buf, 0) + set(buf, 0, get(buf, size - 1)) size -= 1 siftDown(0) result @@ -47,8 +50,8 @@ class BinaryHeap[ItemType](val itemsAgent: ComparingItemsAgent[ItemType]) { final def siftUp(currentIndex: Int): Unit = { if (currentIndex > 0) { val parentIndex = getParentIndex(currentIndex) - if (compare0(parentIndex, currentIndex) < 0) { - swap0(currentIndex, parentIndex) + if (compareLtI(buf, parentIndex, currentIndex)) { + swap(buf, currentIndex, parentIndex) siftUp(parentIndex) } } @@ -58,27 +61,29 @@ class BinaryHeap[ItemType](val itemsAgent: ComparingItemsAgent[ItemType]) { final def siftDown(currentIndex: Int): Unit = { var maxIndex = currentIndex val firstChildIndex = currentIndex * 2 + 1 - if (firstChildIndex < size && compare0(firstChildIndex, maxIndex) > 0) { + if (firstChildIndex < size && compareGtI(buf, firstChildIndex, maxIndex)) { maxIndex = firstChildIndex } val secondChildIndex = firstChildIndex + 1 - if (secondChildIndex < size && compare0(secondChildIndex, maxIndex) > 0) { + if (secondChildIndex < size && compareGtI(buf, secondChildIndex, maxIndex)) { maxIndex = secondChildIndex } - swap0(currentIndex, maxIndex) + swap(buf, currentIndex, maxIndex) if (maxIndex != currentIndex) { siftDown(maxIndex) } } - def getParentIndex(childIndex: Int) = (childIndex - 1) / 2 + def getParentIndex(childIndex: Int): Int = + (childIndex - 1) / 2 } object BinaryHeap { - def apply[ItemType](itemsAgent: ComparingItemsAgent[ItemType]): - BinaryHeap[ItemType] = { - val heap = new BinaryHeap[ItemType](itemsAgent) - heap.size = itemsAgent.size0 + def apply[@specialized(Group) Item]( + itemsAgent: ItemsAgent, + buffer: ComparableItemsBuffer[Item]): BinaryHeap[Item] = { + val heap = new BinaryHeap[Item](itemsAgent, buffer) + heap.size = itemsAgent.size(buffer) heapify(heap) heap } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSort.scala index 6fc85a9..7562c26 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,22 +16,20 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.heap -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -class HeapSort extends ComparisonSortAlgorithm { - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ +object HeapSort extends ComparisonSortBase { + override def sort[@specialized(Group) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] - val heap = BinaryHeap[ItemType](itemsAgent) + val heap = BinaryHeap[Item](a, buf) while (heap.size > 0) { val top = heap.extractTop - set0(heap.size, top) + a.set(buf, heap.size, top) } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapChecker.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapChecker.scala index eeb8a3b..c6d7666 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapChecker.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapChecker.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,17 +16,19 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.heap.check +import pl.tarsa.sortalgobox.core.common.Specialization.Group import pl.tarsa.sortalgobox.sorts.scala.heap.BinaryHeap object BinaryHeapChecker { - def check[ItemType](heap: BinaryHeap[ItemType]) = { + def check[@specialized(Group) Item](heap: BinaryHeap[Item]): Boolean = { import heap.itemsAgent._ val size = heap.size - (1 until size).forall(i => compare0(heap.getParentIndex(i), i) >= 0) + (1 until size).forall { i => + compareGteI(heap.buf, heap.getParentIndex(i), i) + } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSort.scala index 5c0f418..201cbe6 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,22 +16,20 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.insertion -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -class InsertionSort extends ComparisonSortAlgorithm { - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ +object InsertionSort extends ComparisonSortBase { + override def sort[@specialized(Group) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] - for (i <- 1 until size0) { + for (i <- 1 until a.size(buf)) { var j = i - while (j > 0 && compare0(j - 1, j) > 0) { - swap0(j - 1, j) + while (j > 0 && a.compareGtI(buf, j - 1, j)) { + a.swap(buf, j - 1, j) j -= 1 } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSort.scala index 64e3b2d..58d188a 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,48 +16,73 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.merge -import pl.tarsa.sortalgobox.core.common.PureSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.MergeSortItemsAgent +import pl.tarsa.sortalgobox.core.common.ComparableItemsAgentSortAlgorithm +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer + +import scala.{specialized => spec} + +object MergeSort extends ComparableItemsAgentSortAlgorithm { + class Setup[@spec(Group) Item: Permit]( + val buffer1: ComparableItemsBuffer[Item], + val buffer2: ComparableItemsBuffer[Item]) + + override def setupSort[@spec(Group) Item: Ordering]( + items: Array[Item]): Setup[Item] = { + new Setup(ComparableItemsBuffer(0, items, 0), + ComparableItemsBuffer(0, items.clone(), 0)) + } -class MergeSort extends PureSortAlgorithm[MergeSortItemsAgent] { - override def sort[ItemType]( - itemsAgent: MergeSortItemsAgent[ItemType]): Unit = { - import itemsAgent._ + override protected def sort[@spec(Group) Item: Setup, _: Agent](): Unit = { + val buf1 = setup[Item].buffer1 + val buf2 = setup[Item].buffer2 - val n = size0 - for (width <- Stream.iterate(1L)(_ * 2).takeWhile(_ < n)) { + val n = a.size(buf1) + for (width <- Iterator.iterate(1L)(_ * 2).takeWhile(_ < n)) { for (i <- 0L until n by width * 2) { val start = Math.min(i, n) val med = Math.min(start + width, n) val next = Math.min(med + width, n) - bottomUpMerge(itemsAgent, start.toInt, med.toInt, next.toInt) + bottomUpMerge(start.toInt, med.toInt, next.toInt) + } + for (i <- 0 until n) { + a.set(buf1, i, a.get(buf2, i)) } - copy10(0, 0, n) } } - private def bottomUpMerge[ItemType](itemsAgent: MergeSortItemsAgent[ItemType], - start: Int, med: Int, next: Int): Unit = { - import itemsAgent._ + private def bottomUpMerge[@spec(Group) Item: Setup, _: Agent]( + start: Int, + med: Int, + next: Int): Unit = { + val buf1 = setup[Item].buffer1 + val buf2 = setup[Item].buffer2 var left = start var right = med var dest = start while (left < med && right < next) { - if (compare00(left, right) <= 0) { - set1(dest, get0(left)) + if (a.compareLteI(buf1, left, right)) { + a.set(buf2, dest, a.get(buf1, left)) left += 1 } else { - set1(dest, get0(right)) + a.set(buf2, dest, a.get(buf1, right)) right += 1 } dest += 1 } - copy01(left, dest, med - left) - copy01(right, dest + med - left, next - right) + while (left < med) { + a.set(buf2, dest, a.get(buf1, left)) + left += 1 + dest += 1 + } + while (right < next) { + a.set(buf2, dest, a.get(buf1, right)) + right += 1 + dest += 1 + } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSort.scala index 7b9d4f5..2e94506 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,12 +16,11 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.quick -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -abstract class QuickSort extends ComparisonSortAlgorithm { +abstract class QuickSort extends ComparisonSortBase { def partition: SinglePivotPartition } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSortWithLimitedCallDepth.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSortWithLimitedCallDepth.scala index 66db084..fa58af8 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSortWithLimitedCallDepth.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/QuickSortWithLimitedCallDepth.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,59 +16,60 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.quick -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} -class QuickSortWithLimitedCallDepth(val partition: SinglePivotPartition) - extends QuickSort { +import scala.{specialized => spec} - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ - sortManualTcoOuter(itemsAgent, 0, size0) +class QuickSortWithLimitedCallDepth(val partition: SinglePivotPartition) + extends QuickSort { + override def sort[@spec(Grp) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] + sortManualTcoOuter(0, a.size(buf)) } - def sortManualTcoOuter[ItemType](itemsAgent: ComparingItemsAgent[ItemType], - start: Int, after: Int): Unit = { + def sortManualTcoOuter[@spec(Grp) Item: Setup, _: Agent](start: Int, + after: Int): Unit = { var currentStart = start var currentAfter = after while (currentAfter - currentStart > 1) { - val (newStart, newAfter) = - sortManualTcoInner(itemsAgent, currentAfter, currentStart) + val (newStart, newAfter) = sortManualTcoInner(currentAfter, currentStart) currentStart = newStart currentAfter = newAfter } } - def sortManualTcoInner[ItemType](itemsAgent: ComparingItemsAgent[ItemType], - after: Int, start: Int) = { - val (leftAfter, rightStart) = selectPivotAndComputePartitionsBounds( - itemsAgent, start, after) - spawnSmallerAndReturnBiggerPartition(itemsAgent, start, after, - leftAfter, rightStart) + def sortManualTcoInner[@spec(Grp) Item: Setup, _: Agent]( + after: Int, + start: Int): (Int, Int) = { + val (leftAfter, rightStart) = + selectPivotAndComputePartitionsBounds(start, after) + spawnSmallerAndReturnBiggerPartition(start, after, leftAfter, rightStart) } - def selectPivotAndComputePartitionsBounds[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType], start: Int, after: Int) = { + def selectPivotAndComputePartitionsBounds[@spec(Grp) Item: Setup, _: Agent]( + start: Int, + after: Int): (Int, Int) = { val pivotIndex = (after - start) / 2 + start - val (leftAfter, rightStart) = partition.partitionAndComputeBounds( - itemsAgent, start, after, pivotIndex) + val (leftAfter, rightStart) = partition + .partitionAndComputeBounds(a, buf1[Item], start, after, pivotIndex) (leftAfter, rightStart) } - def spawnSmallerAndReturnBiggerPartition[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType], - start: Int, after: Int, leftAfter: Int, rightStart: Int) = { + def spawnSmallerAndReturnBiggerPartition[@spec(Grp) Item: Setup, _: Agent]( + start: Int, + after: Int, + leftAfter: Int, + rightStart: Int): (Int, Int) = { val leftPartitionSize = leftAfter - start val rightPartitionSize = after - rightStart if (leftPartitionSize < rightPartitionSize) { - sortManualTcoOuter(itemsAgent, start, leftAfter) + sortManualTcoOuter(start, leftAfter) (rightStart, after) } else { - sortManualTcoOuter(itemsAgent, rightStart, after) + sortManualTcoOuter(rightStart, after) (start, leftAfter) } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartition.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartition.scala index a56cd2c..471f9f0 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartition.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartition.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,23 +16,24 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.quick -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent - -private [sortalgobox] -class SinglePivotPartition { - def partitionAndComputeBounds[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType], - start: Int, after: Int, pivotIndex: Int): (Int, Int) = { - import itemsAgent._ +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.core.common.items.agents.ItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer +private[sortalgobox] class SinglePivotPartition { + def partitionAndComputeBounds[@specialized(Group) Item]( + a: ItemsAgent, + buf: ComparableItemsBuffer[Item], + start: Int, + after: Int, + pivotIndex: Int): (Int, Int) = { var notBiggerAfter: Int = start var notSmallerStart: Int = after - def partitionNonEmptyArray(pivot: ItemType): Unit = { + def partitionNonEmptyArray(pivot: Item): Unit = { while (thereIsNotPartitionedPortion) { growPartitionsWithoutSwapping(pivot) if (thereIsNotPartitionedPortion) { @@ -43,35 +44,35 @@ class SinglePivotPartition { def thereIsNotPartitionedPortion = notBiggerAfter < notSmallerStart - def growPartitionsWithoutSwapping(pivot: ItemType): Unit = { + def growPartitionsWithoutSwapping(pivot: Item): Unit = { growLeftPartitionUntilBlocked(pivot) growRightPartitionUntilBlocked(pivot) } - def growLeftPartitionUntilBlocked(pivot: ItemType): Unit = { + def growLeftPartitionUntilBlocked(pivot: Item): Unit = { while (thereIsNotPartitionedPortion && - compare(get0(notBiggerAfter), pivot) < 0) { + a.compareLtIV(buf, notBiggerAfter, pivot)) { notBiggerAfter += 1 } } - def growRightPartitionUntilBlocked(pivot: ItemType): Unit = { + def growRightPartitionUntilBlocked(pivot: Item): Unit = { while (thereIsNotPartitionedPortion && - compare(get0(notSmallerStart - 1), pivot) > 0) { + a.compareGtIV(buf, notSmallerStart - 1, pivot)) { notSmallerStart -= 1 } } def growBlockedPartitionsBySwap(): Unit = { notSmallerStart -= 1 - swap0(notBiggerAfter, notSmallerStart) + a.swap(buf, notBiggerAfter, notSmallerStart) notBiggerAfter += 1 } def computeOptimizedPartitionsBounds = { if (partitionsOverlap) { assert(partitionsOverlapMinimally, - s"Overlap is: ${notBiggerAfter - notSmallerStart}") + s"Overlap is: ${notBiggerAfter - notSmallerStart}") (notBiggerAfter - 1, notSmallerStart + 1) } else { (notBiggerAfter, notSmallerStart) @@ -83,7 +84,7 @@ class SinglePivotPartition { def partitionsOverlap = notBiggerAfter > notSmallerStart if (thereIsNotPartitionedPortion) { - val pivot = get0(pivotIndex) + val pivot = a.get(buf, pivotIndex) partitionNonEmptyArray(pivot) } computeOptimizedPartitionsBounds diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSort.scala index dd15dbe..20bf895 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,42 +16,56 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.radix +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} import pl.tarsa.sortalgobox.core.common._ -import pl.tarsa.sortalgobox.core.common.agents.RadixSortItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.NumericItemsBuffer +import pl.tarsa.sortalgobox.core.common.items.buffers.NumericItemsBuffer.Evidence + +import scala.{specialized => spec} -class RadixSort(radixBits: Int = 8) - extends PureSortAlgorithm[RadixSortItemsAgent] { +class RadixSort(radixBits: Int = 8) extends NumericItemsAgentSortAlgorithm { + class Setup[@spec(Grp) Item: Permit](val buffer1: NumericItemsBuffer[Item], + val buffer2: NumericItemsBuffer[Item]) - override def sort[ItemType]( - itemsAgent: RadixSortItemsAgent[ItemType]): Unit = { - import itemsAgent._ + override def setupSort[@spec(Grp) Item: Evidence]( + items: Array[Item]): Setup[Item] = { + new Setup(NumericItemsBuffer(0, items, 0), + NumericItemsBuffer(0, items.clone(), 0)) + } - val n = size0 + override protected def sort[@spec(Grp) Item: Setup, _: Agent](): Unit = { + val buf1 = setup[Item].buffer1 + val buf2 = setup[Item].buffer2 + val ops = buf1.itemsOps + + val n = a.size(buf1) val radix = 1 << radixBits - val shiftsAndLengths = Stream.iterate(0)(_ + radixBits) - .takeWhile(_ < keySizeInBits) - .map(shift => (shift, Math.min(radixBits, keySizeInBits - shift))) - for ((shift, length) <- shiftsAndLengths) { + val shifts = Stream + .iterate(0)(_ + radixBits) + .takeWhile(_ < a.itemBitsSize(buf1)) + for (shift <- shifts) { + val length = Math.min(radixBits, a.itemBitsSize(buf1) - shift) val counts = Array.ofDim[Int](radix) - for (i <- 0 until size0) { - val item = get0(i) - counts(getItemSlice(item, shift, length)) += 1 + for (i <- 0 until n) { + val item = a.get(buf1, i) + counts(a.getSlice(ops, item, shift, length)) += 1 } val prefixSums = Array.ofDim[Int](radix) for (value <- 1 until radix) { prefixSums(value) = prefixSums(value - 1) + counts(value - 1) } - for (i <- 0 until size0) { - val item = get0(i) - val keyPart = getItemSlice(item, shift, length) - set1(prefixSums(keyPart), item) + for (i <- 0 until n) { + val item = a.get(buf1, i) + val keyPart = a.getSlice(ops, item, shift, length) + a.set(buf2, prefixSums(keyPart), item) prefixSums(keyPart) += 1 } - copy10(0, 0, n) + for (i <- 0 until n) { + a.set(buf1, i, a.get(buf2, i)) + } } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantA.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantA.scala index f04bca7..14fa21c 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantA.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantA.scala @@ -19,32 +19,33 @@ */ package pl.tarsa.sortalgobox.sorts.scala.sab -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.{Group => Grp} +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase import scala.annotation.tailrec +import scala.{specialized => spec} -class SabHeapBinaryOneBasedVariantA extends ComparisonSortAlgorithm { - override def sort[ItemType](agent: ComparingItemsAgent[ItemType]): Unit = { - heapsort(agent.withBase(1)) - } +object SabHeapBinaryOneBasedVariantA extends ComparisonSortBase { + override def setupSort[@spec(Grp) Item: Ordering]( + items: Array[Item]): Setup[Item] = + new Setup(ComparableItemsBuffer(0, items, 1)) - private def heapsort[ItemType](agent: ComparingItemsAgent[ItemType]): Unit = { - heapify(agent) - drainHeap(agent) + override def sort[@spec(Grp) Item: Setup, _: Agent](): Unit = { + heapify() + drainHeap() } - private def heapify[ItemType](agent: ComparingItemsAgent[ItemType]): Unit = { - val count = agent.size0 + private def heapify[@spec(Grp) Item: Setup, _: Agent](): Unit = { + val count = a.size(buf1[Item]) for (item <- (count / 2) to 1 by -1) { - siftDown(agent, item, count) + siftDown(item, count) } } - private def siftDown[ItemType](agent: ComparingItemsAgent[ItemType], - start: Int, - end: Int): Unit = { - import agent._ + private def siftDown[@spec(Grp) Item: Setup, _: Agent](start: Int, + end: Int): Unit = { + val buf = buf1[Item] @tailrec def siftStep(root: Int): Unit = { @@ -52,23 +53,23 @@ class SabHeapBinaryOneBasedVariantA extends ComparisonSortAlgorithm { val right = left + 1 if (right <= end) { - if (compareLt0(root, left)) { - if (compareLt0(left, right)) { - swap0(root, right) + if (a.compareLtI(buf, root, left)) { + if (a.compareLtI(buf, left, right)) { + a.swap(buf, root, right) siftStep(right) } else { - swap0(root, left) + a.swap(buf, root, left) siftStep(left) } } else { - if (compareLt0(root, right)) { - swap0(root, right) + if (a.compareLtI(buf, root, right)) { + a.swap(buf, root, right) siftStep(right) } } } else { - if (left == end && compareLt0(root, left)) { - swap0(root, left) + if (left == end && a.compareLtI(buf, root, left)) { + a.swap(buf, root, left) } } } @@ -76,12 +77,12 @@ class SabHeapBinaryOneBasedVariantA extends ComparisonSortAlgorithm { siftStep(start) } - private def drainHeap[ItemType]( - agent: ComparingItemsAgent[ItemType]): Unit = { - val count = agent.size0 + private def drainHeap[@spec(Grp) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] + val count = a.size(buf) for (next <- count until 1 by -1) { - agent.swap0(next, 1) - siftDown(agent, 1, next - 1) + a.swap(buf, next, 1) + siftDown(1, next - 1) } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSort.scala index a44be3b..9194e0e 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -19,25 +19,24 @@ */ package pl.tarsa.sortalgobox.sorts.scala.selection -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -class SelectionSort extends ComparisonSortAlgorithm { - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ +object SelectionSort extends ComparisonSortBase { + override def sort[@specialized(Group) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] - val size = size0 + val size = a.size(buf) for (i <- 0 to size - 2) { val j = ((i + 1) until size).foldLeft(i) { case (lastMinIndex, itemIndex) => - if (compare0(lastMinIndex, itemIndex) > 0) { + if (a.compareGtI(buf, lastMinIndex, itemIndex)) { itemIndex } else { lastMinIndex } } - swap0(i, j) + a.swap(buf, i, j) } } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/GapSequence.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/GapSequence.scala index f1056d9..9a62b86 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/GapSequence.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/GapSequence.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,12 +16,12 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.shell abstract class GapSequence { protected def sequence: Array[Int] - def forSize(n: Int) = sequence.dropWhile(_ >= n) + def forSize(n: Int): Array[Int] = + sequence.dropWhile(_ >= n) } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/HibbardGapSequence.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/HibbardGapSequence.scala index 6435b68..b8b7818 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/HibbardGapSequence.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/HibbardGapSequence.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,11 +16,10 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.shell object HibbardGapSequence extends GapSequence { - - protected val sequence = Array.iterate(Int.MaxValue, 31)(_ / 2).tail + protected val sequence: Array[Int] = + Array.iterate(Int.MaxValue, 31)(_ / 2).tail } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/ShellSort.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/ShellSort.scala index 605f89d..1f1ecf2 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/ShellSort.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/ShellSort.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,23 +16,21 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.shell -import pl.tarsa.sortalgobox.core.common.ComparisonSortAlgorithm -import pl.tarsa.sortalgobox.core.common.agents.ComparingItemsAgent +import pl.tarsa.sortalgobox.core.common.Specialization.Group +import pl.tarsa.sortalgobox.sorts.scala.ComparisonSortBase -class ShellSort(gapSequence: GapSequence) extends ComparisonSortAlgorithm { - override def sort[ItemType]( - itemsAgent: ComparingItemsAgent[ItemType]): Unit = { - import itemsAgent._ +class ShellSort(gapSequence: GapSequence) extends ComparisonSortBase { + override def sort[@specialized(Group) Item: Setup, _: Agent](): Unit = { + val buf = buf1[Item] - for (gap <- gapSequence.forSize(size0); - i <- gap until size0) { + for (gap <- gapSequence.forSize(a.size(buf)); + i <- gap until a.size(buf)) { var j = i - while (j >= gap && compare0(j - gap, j) > 0) { - swap0(j - gap, j) + while (j >= gap && a.compareGtI(buf, j - gap, j)) { + a.swap(buf, j - gap, j) j -= gap } } diff --git a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/TokudaGapSequence.scala b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/TokudaGapSequence.scala index fc3d63b..88f1d0a 100644 --- a/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/TokudaGapSequence.scala +++ b/sorts/main_scala/pl/tarsa/sortalgobox/sorts/scala/shell/TokudaGapSequence.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,15 +16,20 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.shell object TokudaGapSequence extends GapSequence { - - protected val sequence = Stream.iterate(1)(_ + 1).map { k => - val numerator = BigInt(9).pow(k) - BigInt(4).pow(k) - val denominator = BigInt(5) * BigInt(4).pow(k - 1) - numerator / denominator - }.takeWhile(_ < BigInt(Int.MaxValue)).map(_.toInt).toArray.reverse + protected val sequence: Array[Int] = + Iterator + .iterate(1)(_ + 1) + .map { k => + val numerator = BigInt(9).pow(k) - BigInt(4).pow(k) + val denominator = BigInt(5) * BigInt(4).pow(k - 1) + numerator / denominator + } + .takeWhile(_ < BigInt(Int.MaxValue)) + .map(_.toInt) + .toArray + .reverse } diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSortSpec.scala index 20a35e0..385c177 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bitonic/BitonicSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,7 +16,6 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.bitonic @@ -24,9 +23,9 @@ import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class BitonicSortSpec extends CommonUnitSpecBase { - typeBehavior[BitonicSort] + typeBehavior[BitonicSort.type] - def sort = new BitonicSort + private def sort = BitonicSort it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSortSpec.scala index 95cb4e9..dbae389 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/bubble/BubbleSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,7 +16,6 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.bubble @@ -24,9 +23,9 @@ import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class BubbleSortSpec extends CommonUnitSpecBase { - typeBehavior[BubbleSort] + typeBehavior[BubbleSort.type] - def sort = new BubbleSort + private def sort = BubbleSort it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeapSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeapSpec.scala index 677297a..6985ffd 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeapSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/BinaryHeapSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,11 +16,11 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.heap -import pl.tarsa.sortalgobox.core.common.agents.implementations.ComparingIntArrayItemsAgent +import pl.tarsa.sortalgobox.core.common.items.agents.PlainItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer import pl.tarsa.sortalgobox.sorts.scala.heap.check.BinaryHeapChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase @@ -28,26 +28,28 @@ import scala.language.implicitConversions import scala.util.Random class BinaryHeapSpec extends CommonUnitSpecBase { + typeBehavior[BinaryHeap[Int]] - typeBehavior[BinaryHeap[_]] + private def agent = PlainItemsAgent - implicit def intArrayToComparingItemsAgent(array: Array[Int]): - ComparingIntArrayItemsAgent = new ComparingIntArrayItemsAgent(array) + implicit def intArrayToComparableItemsBuffer( + array: Array[Int]): ComparableItemsBuffer[Int] = + ComparableItemsBuffer(0, array, 0) it must "build empty heap" in { - val heap = BinaryHeap(Array.emptyIntArray) + val heap = BinaryHeap(agent, Array.emptyIntArray) assert(BinaryHeapChecker.check(heap)) } it must "build single element heap" in { - val heap = BinaryHeap(Array(5)) + val heap = BinaryHeap(agent, Array(5)) assert(BinaryHeapChecker.check(heap)) } it must "build a few elements heap" in { val generator = new Random(seed = 0) val elems = Stream.continually(generator.nextInt(100)).take(10) - val heap = BinaryHeap(Array(elems: _*)) + val heap = BinaryHeap(agent, Array(elems: _*)) assert(BinaryHeapChecker.check(heap)) } @@ -55,7 +57,7 @@ class BinaryHeapSpec extends CommonUnitSpecBase { val generator = new Random(seed = 0) val size = 100 val storage = Array.ofDim[Int](size) - val heap = new BinaryHeap(storage) + val heap = new BinaryHeap(agent, storage) (0 until size).foreach { _ => heap.addElem(generator.nextInt()) assert(BinaryHeapChecker.check(heap)) @@ -63,7 +65,7 @@ class BinaryHeapSpec extends CommonUnitSpecBase { } it must "fail on extraction from empty heap" in { - val heap = BinaryHeap(Array.emptyIntArray) + val heap = BinaryHeap(agent, Array.emptyIntArray) intercept[IndexOutOfBoundsException] { heap.extractTop } @@ -71,13 +73,13 @@ class BinaryHeapSpec extends CommonUnitSpecBase { it must "extract the only element from heap" in { val element = 5 - val heap = BinaryHeap(Array(element)) + val heap = BinaryHeap(agent, Array(element)) assertResult(element)(heap.extractTop) assertResult(0)(heap.size) } it must "extract maximum element from heap" in { - val heap = BinaryHeap(Array(5, 8, 3, 1)) + val heap = BinaryHeap(agent, Array(5, 8, 3, 1)) assertResult(8)(heap.extractTop) assertResult(3)(heap.size) } diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSortSpec.scala index ad3e79a..4b42bde 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/HeapSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,7 +16,6 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.heap @@ -24,9 +23,9 @@ import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class HeapSortSpec extends CommonUnitSpecBase { - typeBehavior[HeapSort] + typeBehavior[HeapSort.type] - def sort = new HeapSort + private def sort = HeapSort it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapCheckerSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapCheckerSpec.scala index 97f958d..445b20a 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapCheckerSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/heap/check/BinaryHeapCheckerSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,26 +16,28 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.heap.check -import pl.tarsa.sortalgobox.core.common.agents.implementations.ComparingIntArrayItemsAgent +import pl.tarsa.sortalgobox.core.common.items.agents.PlainItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer import pl.tarsa.sortalgobox.sorts.scala.heap.BinaryHeap import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase import scala.language.implicitConversions class BinaryHeapCheckerSpec extends CommonUnitSpecBase { - typeBehavior[BinaryHeapChecker.type] - implicit def intArrayToComparingItemsAgent(array: Array[Int]): - ComparingIntArrayItemsAgent = new ComparingIntArrayItemsAgent(array) + private def agent = PlainItemsAgent + + implicit def intArrayToComparableItemsBuffer( + array: Array[Int]): ComparableItemsBuffer[Int] = + ComparableItemsBuffer(0, array, 0) it must "handle empty heap" in { val array = Array.emptyIntArray - val heap = new BinaryHeap(array) { + val heap = new BinaryHeap(agent, array) { size = array.length } assert(BinaryHeapChecker.check(heap)) @@ -43,7 +45,7 @@ class BinaryHeapCheckerSpec extends CommonUnitSpecBase { it must "handle single element heap" in { val array = Array(5) - val heap = new BinaryHeap(array) { + val heap = new BinaryHeap(agent, array) { size = array.length } assert(BinaryHeapChecker.check(heap)) @@ -51,7 +53,7 @@ class BinaryHeapCheckerSpec extends CommonUnitSpecBase { it must "handle multiple element heap" in { val array = Array(5, 3, 4, 3, 2, 4) - val heap = new BinaryHeap(array) { + val heap = new BinaryHeap(agent, array) { size = array.length } assert(BinaryHeapChecker.check(heap)) @@ -59,7 +61,7 @@ class BinaryHeapCheckerSpec extends CommonUnitSpecBase { it must "detect violations of heap property" in { val array = Array(3, 3, 5, 2, 3) - val heap = new BinaryHeap(array) { + val heap = new BinaryHeap(agent, array) { size = array.length } assert(!BinaryHeapChecker.check(heap)) diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSortSpec.scala index 21497f8..aedf341 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/insertion/InsertionSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,7 +16,6 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.insertion @@ -24,9 +23,9 @@ import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class InsertionSortSpec extends CommonUnitSpecBase { - typeBehavior[InsertionSort] + typeBehavior[InsertionSort.type] - def sort = new InsertionSort + private def sort = InsertionSort it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSortSpec.scala index cab6e4c..8227357 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/merge/MergeSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,7 +16,6 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.merge @@ -24,9 +23,9 @@ import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class MergeSortSpec extends CommonUnitSpecBase { - typeBehavior[MergeSort] + typeBehavior[MergeSort.type] - def sort = new MergeSort + private def sort = MergeSort it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartitionSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartitionSpec.scala index 86cc8c7..5efc168 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartitionSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/quick/SinglePivotPartitionSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,27 +16,29 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.quick -import pl.tarsa.sortalgobox.core.common.agents.implementations.ComparingIntArrayItemsAgent +import pl.tarsa.sortalgobox.core.common.items.agents.PlainItemsAgent +import pl.tarsa.sortalgobox.core.common.items.buffers.ComparableItemsBuffer import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase import scala.language.implicitConversions class SinglePivotPartitionSpec extends CommonUnitSpecBase { - typeBehavior[SinglePivotPartition] - implicit def intArrayToComparingItemsAgent(array: Array[Int]): - ComparingIntArrayItemsAgent = new ComparingIntArrayItemsAgent(array) + private def agent = PlainItemsAgent + + implicit def intArrayToComparableItemsBuffer( + array: Array[Int]): ComparableItemsBuffer[Int] = + ComparableItemsBuffer(0, array, 0) it must "handle empty arrays" in { val array = Array[Int]() val partition = new SinglePivotPartition - val (leftAfter, rightStart) = partition.partitionAndComputeBounds( - array, 0, array.length, 0) + val (leftAfter, rightStart) = + partition.partitionAndComputeBounds(agent, array, 0, array.length, 0) leftAfter mustBe 0 rightStart mustBe 0 } @@ -44,8 +46,8 @@ class SinglePivotPartitionSpec extends CommonUnitSpecBase { it must "handle single element arrays" in { val array = Array(5) val partition = new SinglePivotPartition - val (leftAfter, rightStart) = partition.partitionAndComputeBounds( - array, 0, array.length, 0) + val (leftAfter, rightStart) = + partition.partitionAndComputeBounds(agent, array, 0, array.length, 0) leftAfter must be <= rightStart array mustBe Array(5) } @@ -54,8 +56,8 @@ class SinglePivotPartitionSpec extends CommonUnitSpecBase { def freshArray = Array(1, 2, 3, 5, 8, 13, 21) val array = freshArray val partition = new SinglePivotPartition - val (leftAfter, rightStart) = partition.partitionAndComputeBounds( - array, 0, array.length, 0) + val (leftAfter, rightStart) = + partition.partitionAndComputeBounds(agent, array, 0, array.length, 0) leftAfter mustBe 0 rightStart mustBe 1 array(0) mustBe 1 @@ -68,10 +70,10 @@ class SinglePivotPartitionSpec extends CommonUnitSpecBase { val partition = new SinglePivotPartition val pivotIndex = 3 val pivot = array(pivotIndex) - val (leftAfter, rightStart) = partition.partitionAndComputeBounds( - array, 0, array.length, pivotIndex) - all (array.slice(0, leftAfter)) must be <= pivot - all (array.slice(rightStart, array.length)) must be >= pivot + val (leftAfter, rightStart) = partition + .partitionAndComputeBounds(agent, array, 0, array.length, pivotIndex) + all(array.slice(0, leftAfter)) must be <= pivot + all(array.slice(rightStart, array.length)) must be >= pivot array.sorted mustBe freshArray.sorted } } diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSortSpec.scala index 292ddc2..f568544 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/radix/RadixSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,7 +16,6 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.radix @@ -41,6 +40,6 @@ class RadixSortSpec extends CommonUnitSpecBase { } it must "sort random array" in { - SortChecker(sort).forArrayOfSize(100) + SortChecker(sort).forArrayOfSize(100, 31) } } diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantASpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantASpec.scala index 0089863..488f08a 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantASpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/sab/SabHeapBinaryOneBasedVariantASpec.scala @@ -23,9 +23,9 @@ import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase class SabHeapBinaryOneBasedVariantASpec extends CommonUnitSpecBase { - typeBehavior[SabHeapBinaryOneBasedVariantA] + typeBehavior[SabHeapBinaryOneBasedVariantA.type] - def sort = new SabHeapBinaryOneBasedVariantA + private def sort = SabHeapBinaryOneBasedVariantA it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSortSpec.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSortSpec.scala index 173dc19..aa3e8d7 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSortSpec.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/scala/selection/SelectionSortSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,17 +16,16 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.scala.selection import pl.tarsa.sortalgobox.sorts.tests.SortChecker import pl.tarsa.sortalgobox.tests.CommonUnitSpecBase -class SelectionSortSpec extends CommonUnitSpecBase { - typeBehavior[SelectionSort] +class SelectionSortSpec extends CommonUnitSpecBase { + typeBehavior[SelectionSort.type] - def sort = new SelectionSort + private def sort = SelectionSort it must "handle empty array" in { SortChecker(sort).forEmptyArray() diff --git a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/tests/SortChecker.scala b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/tests/SortChecker.scala index 7322d67..02854df 100644 --- a/sorts/test_scala/pl/tarsa/sortalgobox/sorts/tests/SortChecker.scala +++ b/sorts/test_scala/pl/tarsa/sortalgobox/sorts/tests/SortChecker.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Piotr Tarsa ( http://github.com/tarsa ) + * Copyright (C) 2015 - 2017 Piotr Tarsa ( http://github.com/tarsa ) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -16,19 +16,19 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. - * */ package pl.tarsa.sortalgobox.sorts.tests import org.scalatest.MustMatchers -import pl.tarsa.sortalgobox.core.common._ -import pl.tarsa.sortalgobox.core.common.agents.implementations._ +import pl.tarsa.sortalgobox.core.common.items.agents.PlainItemsAgent +import pl.tarsa.sortalgobox.core.common.{ + ComparableItemsAgentSortAlgorithm, + NumericItemsAgentSortAlgorithm, + SelfMeasuredSortAlgorithm +} import pl.tarsa.sortalgobox.random.Mwc64x -import pl.tarsa.sortalgobox.sorts.scala.merge.MergeSort -import pl.tarsa.sortalgobox.sorts.scala.radix.RadixSort -class SortCheckerInt(doSorting: (Array[Int]) => Unit) extends MustMatchers { - +class SortCheckerInt(doSorting: Array[Int] => Unit) extends MustMatchers { def forEmptyArray(): Unit = { val array = Array.emptyIntArray doSorting(array) @@ -46,16 +46,16 @@ class SortCheckerInt(doSorting: (Array[Int]) => Unit) extends MustMatchers { array mustBe Array(2, 3, 5, 8) } - def forArrayOfSize(size: Int): Unit = { + def forArrayOfSize(size: Int, bits: Int = 32): Unit = { val generator = new Mwc64x - val array = Array.fill(size)(generator.nextInt()) + val array = Array.fill(size)(generator.next(bits)) val sortedArray = array.sorted doSorting(array) array mustBe sortedArray } } -class SortCheckerLong(doSorting: (Array[Long]) => Unit) extends MustMatchers { +class SortCheckerLong(doSorting: Array[Long] => Unit) extends MustMatchers { def forEmptyArray(): Unit = { val array = Array.emptyLongArray @@ -84,26 +84,20 @@ class SortCheckerLong(doSorting: (Array[Long]) => Unit) extends MustMatchers { } object SortChecker { - def apply(measuredSortAlgorithm: MeasuredSortAlgorithm[Int]): SortCheckerInt = - new SortCheckerInt(array => measuredSortAlgorithm.sort(array)) - - def apply(comparisonSortAlgorithm: ComparisonSortAlgorithm): SortCheckerInt = - new SortCheckerInt(intArray => { - val itemsAgent = new ComparingIntArrayItemsAgent(intArray) - comparisonSortAlgorithm.sort(itemsAgent) - }) + def apply(algorithm: SelfMeasuredSortAlgorithm[Int]): SortCheckerInt = + new SortCheckerInt(array => algorithm.sort(array)) - def apply(mergeSort: MergeSort): SortCheckerInt = + def apply(algorithm: ComparableItemsAgentSortAlgorithm): SortCheckerInt = { new SortCheckerInt(intArray => { - val buffer = Array.ofDim[Int](intArray.length) - val itemsAgent = new MergeSortIntArrayItemsAgent(intArray, buffer) - mergeSort.sort(itemsAgent) + val sortSetup = algorithm.setupSort(intArray) + algorithm.sortExplicit(sortSetup, PlainItemsAgent) }) + } - def apply(radixSort: RadixSort): SortCheckerInt = + def apply(algorithm: NumericItemsAgentSortAlgorithm): SortCheckerInt = { new SortCheckerInt(intArray => { - val buffer = Array.ofDim[Int](intArray.length) - val itemsAgent = new RadixSortIntArrayItemsAgent(intArray, buffer) - radixSort.sort(itemsAgent) + val sortSetup = algorithm.setupSort(intArray) + algorithm.sortExplicit(sortSetup, PlainItemsAgent) }) + } }