Basic Matrix and Matrix Storage implementation #2
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class BooleanStorage(
|
value class BooleanStorage(
|
||||||
val data: BooleanArray,
|
override val data: BooleanArray,
|
||||||
) : MatrixStorage<Boolean> {
|
) : MatrixStorage<Boolean> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class ByteStorage(
|
value class ByteStorage(
|
||||||
val data: ByteArray,
|
override val data: ByteArray,
|
||||||
) : MatrixStorage<Byte> {
|
) : MatrixStorage<Byte> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class CharStorage(
|
value class CharStorage(
|
||||||
val data: CharArray,
|
override val data: CharArray,
|
||||||
) : MatrixStorage<Char> {
|
) : MatrixStorage<Char> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class DoubleStorage(
|
value class DoubleStorage(
|
||||||
val data: DoubleArray,
|
override val data: DoubleArray,
|
||||||
) : MatrixStorage<Double> {
|
) : MatrixStorage<Double> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class FloatStorage(
|
value class FloatStorage(
|
||||||
val data: FloatArray,
|
override val data: FloatArray,
|
||||||
) : MatrixStorage<Float> {
|
) : MatrixStorage<Float> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class IntStorage(
|
value class IntStorage(
|
||||||
val data: IntArray,
|
override val data: IntArray,
|
||||||
) : MatrixStorage<Int> {
|
) : MatrixStorage<Int> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class LongStorage(
|
value class LongStorage(
|
||||||
val data: LongArray,
|
override val data: LongArray,
|
||||||
) : MatrixStorage<Long> {
|
) : MatrixStorage<Long> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.duckdns.davygora.matrix.storage
|
package org.duckdns.davygora.matrix.storage
|
||||||
|
|
||||||
sealed interface MatrixStorage<T> {
|
sealed interface MatrixStorage<T> {
|
||||||
|
val data: Any
|
||||||
|
|
||||||
val size: Int
|
val size: Int
|
||||||
|
|
||||||
operator fun get(index: Int): T
|
operator fun get(index: Int): T
|
||||||
@@ -12,8 +14,18 @@ sealed interface MatrixStorage<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
inline fun <reified T> List<T>.toMatrixStorage() =
|
inline fun <reified T> List<T>.toMatrixStorage(): MatrixStorage<T> {
|
||||||
when (T::class) {
|
firstNotNullOfOrNull { it }
|
||||||
|
|
||||||
|
val elementClass =
|
||||||
|
firstOrNull()
|
||||||
|
?.let { first -> first::class }
|
||||||
|
?.takeIf { clazz ->
|
||||||
|
all { it == null || it::class == clazz }
|
||||||
|
}
|
||||||
|
?: T::class
|
||||||
|
|
||||||
|
return when (elementClass) {
|
||||||
Boolean::class -> (this as List<Boolean>).toBooleanArray().toMatrixStorage()
|
Boolean::class -> (this as List<Boolean>).toBooleanArray().toMatrixStorage()
|
||||||
Byte::class -> (this as List<Byte>).toByteArray().toMatrixStorage()
|
Byte::class -> (this as List<Byte>).toByteArray().toMatrixStorage()
|
||||||
Char::class -> (this as List<Char>).toCharArray().toMatrixStorage()
|
Char::class -> (this as List<Char>).toCharArray().toMatrixStorage()
|
||||||
@@ -24,3 +36,4 @@ inline fun <reified T> List<T>.toMatrixStorage() =
|
|||||||
Short::class -> (this as List<Short>).toShortArray().toMatrixStorage()
|
Short::class -> (this as List<Short>).toShortArray().toMatrixStorage()
|
||||||
else -> this.toTypedArray().toMatrixStorage()
|
else -> this.toTypedArray().toMatrixStorage()
|
||||||
} as MatrixStorage<T>
|
} as MatrixStorage<T>
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class ObjectStorage<T>(
|
value class ObjectStorage<T>(
|
||||||
val data: Array<T>,
|
override val data: Array<T>,
|
||||||
) : MatrixStorage<T> {
|
) : MatrixStorage<T> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage
|
|||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class ShortStorage(
|
value class ShortStorage(
|
||||||
val data: ShortArray,
|
override val data: ShortArray,
|
||||||
) : MatrixStorage<Short> {
|
) : MatrixStorage<Short> {
|
||||||
override val size get() = data.size
|
override val size get() = data.size
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package org.duckdns.davygora.matrix.storage
|
||||||
|
|
||||||
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.kotest.datatest.withData
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
class MatrixStorageTest :
|
||||||
|
FunSpec({
|
||||||
|
val testCases: Map<String, Triple<List<*>, KClass<*>, KClass<*>>> =
|
||||||
|
mapOf(
|
||||||
|
"boolean" to Triple(listOf(true, false), BooleanStorage::class, BooleanArray::class),
|
||||||
|
"byte" to Triple((0..100).map { it.toByte() }, ByteStorage::class, ByteArray::class),
|
||||||
|
"char" to Triple(('a'..'z') + ('A'..'Z') + ('0'..'9'), CharStorage::class, CharArray::class),
|
||||||
|
"double" to Triple((0..100).map { it.toDouble() }, DoubleStorage::class, DoubleArray::class),
|
||||||
|
"float" to Triple((0..100).map { it.toFloat() }, FloatStorage::class, FloatArray::class),
|
||||||
|
"int" to Triple((0..100).map { it }, IntStorage::class, IntArray::class),
|
||||||
|
"long" to Triple((0..100).map { it.toLong() }, LongStorage::class, LongArray::class),
|
||||||
|
"short" to Triple((0..100).map { it.toShort() }, ShortStorage::class, ShortArray::class),
|
||||||
|
"object" to Triple((0..100).map { first -> Pair(first, (0..100).random()) }, ObjectStorage::class, Array<Any>::class),
|
||||||
|
)
|
||||||
|
|
||||||
|
context("list of elements of a given type should produce corresponding storage, size, get and set should work") {
|
||||||
|
withData(
|
||||||
|
testCases,
|
||||||
|
) { (allowedValues, storageClass, dataClass) ->
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
|
||||||
|
val size = (10..1000).random()
|
||||||
|
val list = List(size) { allowedValues.random() }
|
||||||
|
val newList = List(size) { allowedValues.random() }
|
||||||
|
|
||||||
|
// Act
|
||||||
|
|
||||||
|
val storage = list.toMatrixStorage()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
storage::class shouldBe storageClass
|
||||||
|
storage.data::class shouldBe dataClass
|
||||||
|
|
||||||
|
storage.size shouldBe size
|
||||||
|
list.forEachIndexed { index, value -> storage[index] shouldBe value }
|
||||||
|
|
||||||
|
newList.forEachIndexed { index, value -> storage[index] = value }
|
||||||
|
newList.forEachIndexed { index, value -> storage[index] shouldBe value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user