Deprecate readFloat and writeFloat, unify byte order to LE on all the platforms of kmath-memory, add test of Memory class
This commit is contained in:
parent
84b149fa81
commit
491e2ac7a6
@ -57,6 +57,7 @@ public interface MemoryReader {
|
|||||||
/**
|
/**
|
||||||
* Reads [Float] at certain [offset].
|
* Reads [Float] at certain [offset].
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("readFloat and writeFloat functions work unexpectedly on JS platform, since because their results are widened when used. Consider using readDouble and writeDouble.")
|
||||||
public fun readFloat(offset: Int): Float
|
public fun readFloat(offset: Int): Float
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,6 +114,7 @@ public interface MemoryWriter {
|
|||||||
/**
|
/**
|
||||||
* Writes [Float] at certain [offset].
|
* Writes [Float] at certain [offset].
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("readFloat and writeFloat functions work unexpectedly on JS platform, since because their results are widened when used. Consider using readDouble and writeDouble.")
|
||||||
public fun writeFloat(offset: Int, value: Float)
|
public fun writeFloat(offset: Int, value: Float)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
package kscience.kmath.memory
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class MemoryTest {
|
||||||
|
@Test
|
||||||
|
fun allocateReturnsMemoryWithValidSize() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
assertEquals(64, mem.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rwByte() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
mem.write { writeByte(0, 42.toByte()) }
|
||||||
|
assertEquals(42.toByte(), mem.read { readByte(0) })
|
||||||
|
mem.write { writeByte(1, (-4).toByte()) }
|
||||||
|
assertEquals((-4).toByte(), mem.read { readByte(1) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rwShort() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
mem.write { writeShort(0, 44555.toShort()) }
|
||||||
|
assertEquals(44555.toShort(), mem.read { readShort(0) })
|
||||||
|
mem.write { writeShort(2, (-33333).toShort()) }
|
||||||
|
assertEquals((-33333).toShort(), mem.read { readShort(2) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rwInt() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
mem.write { writeInt(0, 1234444444) }
|
||||||
|
assertEquals(1234444444, mem.read { readInt(0) })
|
||||||
|
mem.write { writeInt(4, -5595959) }
|
||||||
|
assertEquals(-5595959, mem.read { readInt(4) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rwLong() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
mem.write { writeLong(0, 1234444444L) }
|
||||||
|
assertEquals(1234444444L, mem.read { readLong(0) })
|
||||||
|
mem.write { writeLong(4, -5595959L) }
|
||||||
|
assertEquals(-5595959L, mem.read { readLong(4) })
|
||||||
|
mem.write { writeLong(8, 1234444444444149L) }
|
||||||
|
assertEquals(1234444444444149L, mem.read { readLong(8) })
|
||||||
|
mem.write { writeLong(16, -50000333595959L) }
|
||||||
|
assertEquals(-50000333595959L, mem.read { readLong(16) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
@Test
|
||||||
|
fun rwFloat() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
mem.write { writeFloat(0, 12.12345f) }
|
||||||
|
println(1)
|
||||||
|
assertEquals(12.12345027923584, mem.read { readFloat(0) }.toDouble())
|
||||||
|
mem.write { writeFloat(4, -313.13f) }
|
||||||
|
println(2)
|
||||||
|
assertEquals(-313.1300048828125, mem.read { readFloat(4) }.toDouble())
|
||||||
|
mem.write { writeFloat(8, Float.NaN) }
|
||||||
|
println(3)
|
||||||
|
assertEquals(Float.NaN, mem.read { readFloat(8) })
|
||||||
|
mem.write { writeFloat(12, Float.POSITIVE_INFINITY) }
|
||||||
|
println(4)
|
||||||
|
assertEquals(Float.POSITIVE_INFINITY, mem.read { readFloat(12) })
|
||||||
|
mem.write { writeFloat(12, Float.NEGATIVE_INFINITY) }
|
||||||
|
println(5)
|
||||||
|
assertEquals(Float.NEGATIVE_INFINITY, mem.read { readFloat(12) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rwDouble() {
|
||||||
|
val mem = Memory.allocate(64)
|
||||||
|
mem.write { writeDouble(0, 12.12345) }
|
||||||
|
assertEquals(12.12345, mem.read { readDouble(0) })
|
||||||
|
mem.write { writeDouble(8, -313.13) }
|
||||||
|
assertEquals(-313.13, mem.read { readDouble(8) })
|
||||||
|
mem.write { writeDouble(16, Double.NaN) }
|
||||||
|
assertEquals(Double.NaN, mem.read { readDouble(16) })
|
||||||
|
mem.write { writeDouble(24, Double.POSITIVE_INFINITY) }
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, mem.read { readDouble(24) })
|
||||||
|
mem.write { writeDouble(32, Double.NEGATIVE_INFINITY) }
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, mem.read { readDouble(32) })
|
||||||
|
}
|
||||||
|
}
|
@ -28,18 +28,18 @@ private class DataViewMemory(val view: DataView) : Memory {
|
|||||||
private val reader: MemoryReader = object : MemoryReader {
|
private val reader: MemoryReader = object : MemoryReader {
|
||||||
override val memory: Memory get() = this@DataViewMemory
|
override val memory: Memory get() = this@DataViewMemory
|
||||||
|
|
||||||
override fun readDouble(offset: Int): Double = view.getFloat64(offset, false)
|
override fun readDouble(offset: Int): Double = view.getFloat64(offset, true)
|
||||||
|
|
||||||
override fun readFloat(offset: Int): Float = view.getFloat32(offset, false)
|
override fun readFloat(offset: Int): Float = view.getFloat32(offset, true)
|
||||||
|
|
||||||
override fun readByte(offset: Int): Byte = view.getInt8(offset)
|
override fun readByte(offset: Int): Byte = view.getInt8(offset)
|
||||||
|
|
||||||
override fun readShort(offset: Int): Short = view.getInt16(offset, false)
|
override fun readShort(offset: Int): Short = view.getInt16(offset, true)
|
||||||
|
|
||||||
override fun readInt(offset: Int): Int = view.getInt32(offset, false)
|
override fun readInt(offset: Int): Int = view.getInt32(offset, true)
|
||||||
|
|
||||||
override fun readLong(offset: Int): Long =
|
override fun readLong(offset: Int): Long =
|
||||||
view.getInt32(offset, false).toLong() shl 32 or view.getInt32(offset + 4, false).toLong()
|
view.getInt32(offset, true).toLong() shl 32 or view.getInt32(offset + 4, true).toLong()
|
||||||
|
|
||||||
override fun release() {
|
override fun release() {
|
||||||
// does nothing on JS
|
// does nothing on JS
|
||||||
@ -52,11 +52,11 @@ private class DataViewMemory(val view: DataView) : Memory {
|
|||||||
override val memory: Memory get() = this@DataViewMemory
|
override val memory: Memory get() = this@DataViewMemory
|
||||||
|
|
||||||
override fun writeDouble(offset: Int, value: Double) {
|
override fun writeDouble(offset: Int, value: Double) {
|
||||||
view.setFloat64(offset, value, false)
|
view.setFloat64(offset, value, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeFloat(offset: Int, value: Float) {
|
override fun writeFloat(offset: Int, value: Float) {
|
||||||
view.setFloat32(offset, value, false)
|
view.setFloat32(offset, value, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeByte(offset: Int, value: Byte) {
|
override fun writeByte(offset: Int, value: Byte) {
|
||||||
@ -64,16 +64,16 @@ private class DataViewMemory(val view: DataView) : Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun writeShort(offset: Int, value: Short) {
|
override fun writeShort(offset: Int, value: Short) {
|
||||||
view.setUint16(offset, value, false)
|
view.setUint16(offset, value, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeInt(offset: Int, value: Int) {
|
override fun writeInt(offset: Int, value: Int) {
|
||||||
view.setInt32(offset, value, false)
|
view.setInt32(offset, value, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeLong(offset: Int, value: Long) {
|
override fun writeLong(offset: Int, value: Long) {
|
||||||
view.setInt32(offset, (value shr 32).toInt(), littleEndian = false)
|
view.setInt32(offset, (value shr 32).toInt(), littleEndian = true)
|
||||||
view.setInt32(offset + 4, (value and 0xffffffffL).toInt(), littleEndian = false)
|
view.setInt32(offset + 4, (value and 0xffffffffL).toInt(), littleEndian = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun release() {
|
override fun release() {
|
||||||
@ -82,7 +82,6 @@ private class DataViewMemory(val view: DataView) : Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun writer(): MemoryWriter = writer
|
override fun writer(): MemoryWriter = writer
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +97,6 @@ public actual fun Memory.Companion.allocate(length: Int): Memory {
|
|||||||
* and could be mutated independently from the resulting [Memory].
|
* and could be mutated independently from the resulting [Memory].
|
||||||
*/
|
*/
|
||||||
public actual fun Memory.Companion.wrap(array: ByteArray): Memory {
|
public actual fun Memory.Companion.wrap(array: ByteArray): Memory {
|
||||||
@Suppress("CAST_NEVER_SUCCEEDS") val int8Array = array as Int8Array
|
val int8Array = array.unsafeCast<Int8Array>()
|
||||||
return DataViewMemory(DataView(int8Array.buffer, int8Array.byteOffset, int8Array.length))
|
return DataViewMemory(DataView(int8Array.buffer, int8Array.byteOffset, int8Array.length))
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ package space.kscience.kmath.memory
|
|||||||
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
import java.nio.channels.FileChannel
|
import java.nio.channels.FileChannel
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -31,7 +32,7 @@ internal class ByteBufferMemory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(): Memory {
|
override fun copy(): Memory {
|
||||||
val copy = ByteBuffer.allocate(buffer.capacity())
|
val copy = ByteBuffer.allocate(buffer.capacity()).order(ByteOrder.LITTLE_ENDIAN)
|
||||||
buffer.rewind()
|
buffer.rewind()
|
||||||
copy.put(buffer)
|
copy.put(buffer)
|
||||||
copy.flip()
|
copy.flip()
|
||||||
@ -99,7 +100,7 @@ internal class ByteBufferMemory(
|
|||||||
* Allocates memory based on a [ByteBuffer].
|
* Allocates memory based on a [ByteBuffer].
|
||||||
*/
|
*/
|
||||||
public actual fun Memory.Companion.allocate(length: Int): Memory =
|
public actual fun Memory.Companion.allocate(length: Int): Memory =
|
||||||
ByteBufferMemory(checkNotNull(ByteBuffer.allocate(length)))
|
ByteBufferMemory(checkNotNull(ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied
|
* Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied
|
||||||
|
@ -42,7 +42,7 @@ internal class NativeMemory(
|
|||||||
override fun readLong(offset: Int) = array.getLongAt(position(offset))
|
override fun readLong(offset: Int) = array.getLongAt(position(offset))
|
||||||
|
|
||||||
override fun release() {
|
override fun release() {
|
||||||
// does nothing on JVM
|
// does nothing on Native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ internal class NativeMemory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun writeByte(offset: Int, value: Byte) {
|
override fun writeByte(offset: Int, value: Byte) {
|
||||||
array.set(position(offset), value)
|
array[position(offset)] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeShort(offset: Int, value: Short) {
|
override fun writeShort(offset: Int, value: Short) {
|
||||||
@ -76,7 +76,7 @@ internal class NativeMemory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun release() {
|
override fun release() {
|
||||||
// does nothing on JVM
|
// does nothing on Native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user