Basic Matrix and Matrix Storage implementation #2

Merged
yura merged 7 commits from Initial_implementation into main 2026-05-18 09:41:47 +02:00
21 changed files with 331 additions and 2 deletions
Showing only changes of commit b442d9d574 - Show all commits
+1 -1
View File
@@ -35,7 +35,7 @@ kotlin {
kotlin {
jvmToolchain {
languageVersion = JavaLanguageVersion.of(25)
languageVersion = JavaLanguageVersion.of(21)
vendor = JvmVendorSpec.ADOPTIUM
}
}
@@ -0,0 +1,34 @@
package org.duckdns.davygora.matrix
import org.duckdns.davygora.matrix.storage.MatrixStorage
abstract class AbstractMatrix<T>(
override val xSize: Int,
override val ySize: Int,
protected val matrix: MatrixStorage<T>,
) : Matrix<T> {
override fun toString(): String =
(0..<ySize)
.map { y ->
"[\t${(0..<xSize).joinToString("\t") { x -> this[x, y].toString() }}\t]"
}.joinToString { "\n" }
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AbstractMatrix<T>
if (xSize != other.xSize) return false
if (ySize != other.ySize) return false
if (matrix != other.matrix) return false
return true
}
override fun hashCode(): Int {
var result = xSize
result = 31 * result + ySize
result = 31 * result + matrix.hashCode()
return result
}
}
@@ -0,0 +1,10 @@
package org.duckdns.davygora.matrix
import org.duckdns.davygora.matrix.storage.MatrixStorage
abstract class AbstractMutableMatrix<T>(
xSize: Int,
ySize: Int,
matrix: MatrixStorage<T>,
) : AbstractMatrix<T>(xSize, ySize, matrix),
MutableMatrix<T>
@@ -0,0 +1,11 @@
package org.duckdns.davygora.matrix
interface Matrix<T> {
val xSize: Int
val ySize: Int
operator fun get(
x: Int,
y: Int,
): T
}
@@ -0,0 +1,9 @@
package org.duckdns.davygora.matrix
interface MutableMatrix<T> : Matrix<T> {
operator fun set(
x: Int,
y: Int,
value: T,
)
}
@@ -0,0 +1,7 @@
package org.duckdns.davygora.matrix.exception
class MatrixCoordinateOutOfRangeException(
coordName: Char,
coord: Int,
maxCoord: Int,
) : MatrixException("${coordName.uppercaseChar()} coordinate $coord is out of range, allowed is 0..$maxCoord")
@@ -0,0 +1,6 @@
package org.duckdns.davygora.matrix.exception
sealed class MatrixException(
message: String,
cause: Throwable? = null,
) : RuntimeException(message, cause)
@@ -0,0 +1,6 @@
package org.duckdns.davygora.matrix.exception
class MatrixInvalidSizeException(
coordinate: Char,
size: Int,
) : MatrixException("${coordinate.uppercaseChar()} size is invalid: $size (should be > 0)")
@@ -0,0 +1,6 @@
package org.duckdns.davygora.matrix.exception
class MatrixSizeMismatchException(
expectedSize: Int,
actualSize: Int,
) : MatrixException("Matrix size mismatch: expected $expectedSize, actual $actualSize")
@@ -0,0 +1,57 @@
package org.duckdns.davygora.matrix.impl
import org.duckdns.davygora.matrix.AbstractMutableMatrix
import org.duckdns.davygora.matrix.Matrix
import org.duckdns.davygora.matrix.exception.MatrixCoordinateOutOfRangeException
import org.duckdns.davygora.matrix.exception.MatrixInvalidSizeException
import org.duckdns.davygora.matrix.exception.MatrixNotRectangularException
import org.duckdns.davygora.matrix.exception.MatrixSizeMismatchException
import org.duckdns.davygora.matrix.storage.MatrixStorage
import org.duckdns.davygora.memoize.memoize
class ArrayMatrix<T>(
xSize: Int,
ySize: Int,
matrix: MatrixStorage<T>,
) : AbstractMutableMatrix<T>(xSize, ySize, matrix) {
private val size = xSize * ySize
private val maxX = xSize - 1
private val maxY = ySize - 1
init {
if (ySize < 1) throw MatrixInvalidSizeException('y', ySize)
if (xSize < 1) throw MatrixInvalidSizeException('x', xSize)
if (size != matrix.size) throw MatrixSizeMismatchException(size, matrix.size)
}
override operator fun get(
x: Int,
y: Int,
): T = matrix[index(x, y)]
override operator fun set(
x: Int,
y: Int,
value: T,
) {
matrix[index(x, y)] = value
}
private val index = { x: Int, y: Int -> validateY(y) * xSize + validateX(x) }.memoize()
private val validateX = { x: Int -> validateCoord('x', x, maxX) }.memoize()
private val validateY = { y: Int -> validateCoord('y', y, maxY) }.memoize()
private fun validateCoord(
coordName: Char,
coord: Int,
maxCoord: Int,
) = if (coord in
0..maxCoord
) {
coord
} else {
throw MatrixCoordinateOutOfRangeException(coordName, coord, maxCoord)
}
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class BooleanStorage(
val data: BooleanArray,
) : MatrixStorage<Boolean> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Boolean,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class ByteStorage(
val data: ByteArray,
) : MatrixStorage<Byte> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Byte,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class CharStorage(
val data: CharArray,
) : MatrixStorage<Char> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Char,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class DoubleStorage(
val data: DoubleArray,
) : MatrixStorage<Double> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Double,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class FloatStorage(
val data: FloatArray,
) : MatrixStorage<Float> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Float,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class IntStorage(
val data: IntArray,
) : MatrixStorage<Int> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Int,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class LongStorage(
val data: LongArray,
) : MatrixStorage<Long> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Long,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,12 @@
package org.duckdns.davygora.matrix.storage
sealed interface MatrixStorage<T> {
val size: Int
operator fun get(index: Int): T
operator fun set(
index: Int,
value: T,
)
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class ObjectStorage<T>(
val data: Array<T>,
) : MatrixStorage<T> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: T,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}
@@ -0,0 +1,19 @@
package org.duckdns.davygora.matrix.storage
@JvmInline
value class ShortStorage(
val data: ShortArray,
) : MatrixStorage<Short> {
override val size get() = data.size
override operator fun get(index: Int) = data[index]
override fun set(
index: Int,
value: Short,
) {
data[index] = value
}
override fun toString(): String = data.contentToString()
}