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:
Iaroslav Postovalov 2020-12-09 04:59:41 +07:00
parent 84b149fa81
commit 491e2ac7a6
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
5 changed files with 109 additions and 19 deletions

View File

@ -57,6 +57,7 @@ public interface MemoryReader {
/**
* 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
/**
@ -113,6 +114,7 @@ public interface MemoryWriter {
/**
* 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)
/**

View File

@ -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) })
}
}

View File

@ -28,18 +28,18 @@ private class DataViewMemory(val view: DataView) : Memory {
private val reader: MemoryReader = object : MemoryReader {
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 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 =
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() {
// does nothing on JS
@ -52,11 +52,11 @@ private class DataViewMemory(val view: DataView) : Memory {
override val memory: Memory get() = this@DataViewMemory
override fun writeDouble(offset: Int, value: Double) {
view.setFloat64(offset, value, false)
view.setFloat64(offset, value, true)
}
override fun writeFloat(offset: Int, value: Float) {
view.setFloat32(offset, value, false)
view.setFloat32(offset, value, true)
}
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) {
view.setUint16(offset, value, false)
view.setUint16(offset, value, true)
}
override fun writeInt(offset: Int, value: Int) {
view.setInt32(offset, value, false)
view.setInt32(offset, value, true)
}
override fun writeLong(offset: Int, value: Long) {
view.setInt32(offset, (value shr 32).toInt(), littleEndian = false)
view.setInt32(offset + 4, (value and 0xffffffffL).toInt(), littleEndian = false)
view.setInt32(offset, (value shr 32).toInt(), littleEndian = true)
view.setInt32(offset + 4, (value and 0xffffffffL).toInt(), littleEndian = true)
}
override fun release() {
@ -82,7 +82,6 @@ private class DataViewMemory(val view: DataView) : Memory {
}
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].
*/
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))
}

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.memory
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.channels.FileChannel
import java.nio.file.Files
import java.nio.file.Path
@ -31,7 +32,7 @@ internal class ByteBufferMemory(
}
override fun copy(): Memory {
val copy = ByteBuffer.allocate(buffer.capacity())
val copy = ByteBuffer.allocate(buffer.capacity()).order(ByteOrder.LITTLE_ENDIAN)
buffer.rewind()
copy.put(buffer)
copy.flip()
@ -99,7 +100,7 @@ internal class ByteBufferMemory(
* Allocates memory based on a [ByteBuffer].
*/
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

View File

@ -42,7 +42,7 @@ internal class NativeMemory(
override fun readLong(offset: Int) = array.getLongAt(position(offset))
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) {
array.set(position(offset), value)
array[position(offset)] = value
}
override fun writeShort(offset: Int, value: Short) {
@ -76,7 +76,7 @@ internal class NativeMemory(
}
override fun release() {
// does nothing on JVM
// does nothing on Native
}
}