Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ public interface KernelProvider {
*/
public fun matmulQ8_0(): Q8_0MatmulKernel? = null

/**
* F32 × Q4_0 matmul kernel exposed by this provider, or `null` if
* this provider does not specialize Q4_0. Same fall-through pattern.
*/
public fun matmulQ4_0(): Q4_0MatmulKernel? = null

/**
* Capability query: does this provider carry a kernel for
* [opName] with the given [dtypeKeys]?
Expand Down Expand Up @@ -100,6 +106,7 @@ public interface KernelProvider {
"BFloat16" -> matmulBf16() != null
"Q4_K" -> matmulQ4K() != null
"Q8_0" -> matmulQ8_0() != null
"Q4_0" -> matmulQ4_0() != null
else -> false
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package sk.ainet.backend.api.kernel

/**
* F32 input × Q4_0-packed weights matrix-vector multiply, in canonical
* ggml block layout.
*
* output[outputOffset + o] = Σ_j input[inputOffset + j] · dequant(weight[o, j])
* for j ∈ [0, inputDim), o ∈ [0, outputDim)
*
* Block layout (32-element block, 18 bytes/block; see
* [sk.ainet.lang.tensor.data.Q4_0BlockTensorData] kdoc):
* - bytes 0..1 : `d` (block scale, FP16 LE)
* - bytes 2..17 : 16 bytes packing 32 4-bit codes (split layout — low
* nibbles decode elements 0..15, high nibbles decode elements 16..31)
*
* Per element: `dequant = (code - 8) * d` (the `- 8` bias centres the
* unsigned 4-bit code around zero). Q4_0 has no per-block min / offset.
*
* Implementations MUST NOT mutate `input` or `weight`. They MAY assume
* the arrays do not alias each other or `output`. They MUST fully
* write the `outputDim` floats starting at `output[outputOffset]`.
*
* Packed-weight row-major contract: `weight` holds blocks laid out
* `(blockIdx * outputDim + o) * 18` for output row `o` and input block
* index `blockIdx`. This matches `Q4_0BlockTensorData.packedData`.
*
* `inputDim` MUST be a multiple of 32 (the Q4_0 block size).
*/
public interface Q4_0MatmulKernel {
/**
* @param input FP32 input vector (single row).
* @param inputOffset element offset into [input] where the row starts.
* @param weight packed Q4_0 bytes for the full `outputDim × inputDim` weight tensor.
* @param weightByteOffset byte offset into [weight] where block (0, 0) starts.
* @param inputDim contraction dimension (must be a multiple of 32).
* @param outputDim number of output cells.
* @param output FP32 output vector.
* @param outputOffset element offset into [output] where the row starts.
*/
public fun matmul(
input: FloatArray, inputOffset: Int,
weight: ByteArray, weightByteOffset: Int,
inputDim: Int, outputDim: Int,
output: FloatArray, outputOffset: Int,
)
}
123 changes: 123 additions & 0 deletions skainet-backends/skainet-backend-cpu/api/jvm/skainet-backend-cpu.api
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ public final class sk/ainet/context/DirectCpuExecutionContext : sk/ainet/context
public fun getHooks ()Lsk/ainet/lang/nn/hooks/ForwardHooks;
public fun getInTraining ()Z
public fun getMemoryInfo ()Lsk/ainet/context/MemoryInfo;
public fun getMemoryPlanner ()Lsk/ainet/lang/tensor/storage/MemoryPlanner;
public fun getMemoryTracker ()Lsk/ainet/lang/tensor/storage/MemoryTracker;
public fun getObservers ()Lsk/ainet/context/ExecutionObserverRegistry;
public fun getOps ()Lsk/ainet/lang/tensor/ops/TensorOps;
public fun getPhase ()Lsk/ainet/context/Phase;
public fun getScratch ()Lsk/ainet/lang/tensor/scratch/ScratchPool;
public fun getTensorDataFactory ()Lsk/ainet/lang/tensor/data/TensorDataFactory;
public fun ones (Lsk/ainet/lang/tensor/Shape;Lkotlin/reflect/KClass;)Lsk/ainet/lang/tensor/Tensor;
public fun placeholder (Lsk/ainet/lang/tensor/Shape;Lkotlin/reflect/KClass;)Lsk/ainet/lang/tensor/Tensor;
public fun registerObserver (Lsk/ainet/context/ExecutionObserver;)V
public fun unregisterObserver (Lsk/ainet/context/ExecutionObserver;)V
public fun wrapByteArray (Lsk/ainet/lang/tensor/Shape;Lkotlin/reflect/KClass;[B)Lsk/ainet/lang/tensor/Tensor;
public fun wrapFloatArray (Lsk/ainet/lang/tensor/Shape;Lkotlin/reflect/KClass;[F)Lsk/ainet/lang/tensor/Tensor;
public fun wrapIntArray (Lsk/ainet/lang/tensor/Shape;Lkotlin/reflect/KClass;[I)Lsk/ainet/lang/tensor/Tensor;
public fun zeros (Lsk/ainet/lang/tensor/Shape;Lkotlin/reflect/KClass;)Lsk/ainet/lang/tensor/Tensor;
}

Expand All @@ -33,6 +40,103 @@ public final class sk/ainet/context/DirectCpuExecutionContext$Companion {
public static synthetic fun create$default (Lsk/ainet/context/DirectCpuExecutionContext$Companion;Lsk/ainet/context/Phase;ILjava/lang/Object;)Lsk/ainet/context/DirectCpuExecutionContext;
}

public final class sk/ainet/exec/kernel/PanamaVectorBf16MatmulKernel : sk/ainet/backend/api/kernel/Bf16MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/PanamaVectorBf16MatmulKernel;
public fun matmul ([FII[BII[FIIIII)V
}

public final class sk/ainet/exec/kernel/PanamaVectorKernelProvider : sk/ainet/backend/api/kernel/KernelProvider {
public static final field INSTANCE Lsk/ainet/exec/kernel/PanamaVectorKernelProvider;
public fun getName ()Ljava/lang/String;
public fun getPriority ()I
public fun isAvailable ()Z
public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel;
public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel;
public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel;
public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel;
public fun matmulQ8_0 ()Lsk/ainet/backend/api/kernel/Q8_0MatmulKernel;
public fun supports (Ljava/lang/String;Ljava/util/List;)Z
}

public final class sk/ainet/exec/kernel/PanamaVectorKernelProviderFactory : sk/ainet/backend/api/kernel/KernelProvider {
public fun <init> ()V
public fun getName ()Ljava/lang/String;
public fun getPriority ()I
public fun isAvailable ()Z
public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel;
public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel;
public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel;
public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel;
public fun matmulQ8_0 ()Lsk/ainet/backend/api/kernel/Q8_0MatmulKernel;
public fun supports (Ljava/lang/String;Ljava/util/List;)Z
}

public final class sk/ainet/exec/kernel/PanamaVectorMatmulKernel : sk/ainet/backend/api/kernel/Fp32MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/PanamaVectorMatmulKernel;
public fun matmul ([FII[FII[FIIIII)V
}

public final class sk/ainet/exec/kernel/PanamaVectorQ4KMatmulKernel : sk/ainet/backend/api/kernel/Q4KMatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/PanamaVectorQ4KMatmulKernel;
public fun matmul ([FI[BIII[FI)V
}

public final class sk/ainet/exec/kernel/PanamaVectorQ4_0MatmulKernel : sk/ainet/backend/api/kernel/Q4_0MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/PanamaVectorQ4_0MatmulKernel;
public fun matmul ([FI[BIII[FI)V
}

public final class sk/ainet/exec/kernel/PanamaVectorQ8_0MatmulKernel : sk/ainet/backend/api/kernel/Q8_0MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/PanamaVectorQ8_0MatmulKernel;
public fun matmul ([FI[BIII[FI)V
}

public final class sk/ainet/exec/kernel/ScalarBf16MatmulKernel : sk/ainet/backend/api/kernel/Bf16MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/ScalarBf16MatmulKernel;
public fun matmul ([FII[BII[FIIIII)V
}

public final class sk/ainet/exec/kernel/ScalarKernelProvider : sk/ainet/backend/api/kernel/KernelProvider {
public static final field INSTANCE Lsk/ainet/exec/kernel/ScalarKernelProvider;
public fun getName ()Ljava/lang/String;
public fun getPriority ()I
public fun isAvailable ()Z
public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel;
public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel;
public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel;
public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel;
public fun matmulQ8_0 ()Lsk/ainet/backend/api/kernel/Q8_0MatmulKernel;
public fun supports (Ljava/lang/String;Ljava/util/List;)Z
}

public final class sk/ainet/exec/kernel/ScalarKernelProviderFactory : sk/ainet/backend/api/kernel/KernelProvider {
public fun <init> ()V
public fun getName ()Ljava/lang/String;
public fun getPriority ()I
public fun isAvailable ()Z
public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel;
public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel;
public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel;
public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel;
public fun matmulQ8_0 ()Lsk/ainet/backend/api/kernel/Q8_0MatmulKernel;
public fun supports (Ljava/lang/String;Ljava/util/List;)Z
}

public final class sk/ainet/exec/kernel/ScalarMatmulKernel : sk/ainet/backend/api/kernel/Fp32MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/ScalarMatmulKernel;
public fun matmul ([FII[FII[FIIIII)V
}

public final class sk/ainet/exec/kernel/ScalarQ4_0MatmulKernel : sk/ainet/backend/api/kernel/Q4_0MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/ScalarQ4_0MatmulKernel;
public fun matmul ([FI[BIII[FI)V
}

public final class sk/ainet/exec/kernel/ScalarQ8_0MatmulKernel : sk/ainet/backend/api/kernel/Q8_0MatmulKernel {
public static final field INSTANCE Lsk/ainet/exec/kernel/ScalarQ8_0MatmulKernel;
public fun matmul ([FI[BIII[FI)V
}

public final class sk/ainet/exec/tensor/ops/DefaultCpuOps : sk/ainet/exec/tensor/ops/DefaultCpuOpsBase {
public fun <init> (Lsk/ainet/lang/tensor/data/TensorDataFactory;)V
}
Expand All @@ -49,7 +153,9 @@ public class sk/ainet/exec/tensor/ops/DefaultCpuOpsBase : sk/ainet/lang/tensor/o
public fun conv1d (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;IIII)Lsk/ainet/lang/tensor/Tensor;
public fun conv2d (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;I)Lsk/ainet/lang/tensor/Tensor;
public fun conv3d (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lkotlin/Triple;Lkotlin/Triple;Lkotlin/Triple;I)Lsk/ainet/lang/tensor/Tensor;
public fun convTranspose1d (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;IIIII)Lsk/ainet/lang/tensor/Tensor;
public fun convert (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/types/DType;)Lsk/ainet/lang/tensor/Tensor;
public fun cos (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun divScalar (Lsk/ainet/lang/tensor/Tensor;Ljava/lang/Number;)Lsk/ainet/lang/tensor/Tensor;
public fun divide (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
protected final fun elementwise (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;Lkotlin/jvm/functions/Function3;)Lsk/ainet/lang/tensor/Tensor;
Expand All @@ -64,6 +170,9 @@ public class sk/ainet/exec/tensor/ops/DefaultCpuOpsBase : sk/ainet/lang/tensor/o
protected final fun gradStateFrom ([Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/GradState;
public fun indexSelect (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;I)Lsk/ainet/lang/tensor/Tensor;
public fun leakyRelu (Lsk/ainet/lang/tensor/Tensor;F)Lsk/ainet/lang/tensor/Tensor;
public fun log (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun log10 (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun log2 (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun logSoftmax (Lsk/ainet/lang/tensor/Tensor;I)Lsk/ainet/lang/tensor/Tensor;
public fun lt (Lsk/ainet/lang/tensor/Tensor;F)Lsk/ainet/lang/tensor/Tensor;
protected final fun mapIndex ([ILsk/ainet/lang/tensor/Shape;)[I
Expand All @@ -75,6 +184,9 @@ public class sk/ainet/exec/tensor/ops/DefaultCpuOpsBase : sk/ainet/lang/tensor/o
public fun narrow (Lsk/ainet/lang/tensor/Tensor;III)Lsk/ainet/lang/tensor/Tensor;
protected final fun newTensor (Lsk/ainet/lang/tensor/data/TensorData;Lkotlin/reflect/KClass;[Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun pad2d (Lsk/ainet/lang/tensor/Tensor;IIII)Lsk/ainet/lang/tensor/Tensor;
public fun permute (Lsk/ainet/lang/tensor/Tensor;[I)Lsk/ainet/lang/tensor/Tensor;
public fun pow (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun powScalar (Lsk/ainet/lang/tensor/Tensor;Ljava/lang/Number;)Lsk/ainet/lang/tensor/Tensor;
public fun rdivScalar (Ljava/lang/Number;Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun relu (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
protected final fun requireSameDType (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;)V
Expand All @@ -84,13 +196,15 @@ public class sk/ainet/exec/tensor/ops/DefaultCpuOpsBase : sk/ainet/lang/tensor/o
public fun sigmoid (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun sign (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun silu (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun sin (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun softmax (Lsk/ainet/lang/tensor/Tensor;I)Lsk/ainet/lang/tensor/Tensor;
public fun split (Lsk/ainet/lang/tensor/Tensor;II)Ljava/util/List;
public fun sqrt (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun squeeze (Lsk/ainet/lang/tensor/Tensor;Ljava/lang/Integer;)Lsk/ainet/lang/tensor/Tensor;
public fun subScalar (Lsk/ainet/lang/tensor/Tensor;Ljava/lang/Number;)Lsk/ainet/lang/tensor/Tensor;
public fun subtract (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun sum (Lsk/ainet/lang/tensor/Tensor;Ljava/lang/Integer;)Lsk/ainet/lang/tensor/Tensor;
public fun tanh (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun transpose (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun tril (Lsk/ainet/lang/tensor/Tensor;I)Lsk/ainet/lang/tensor/Tensor;
public fun unfold (Lsk/ainet/lang/tensor/Tensor;III)Lsk/ainet/lang/tensor/Tensor;
Expand All @@ -115,6 +229,15 @@ protected final class sk/ainet/exec/tensor/ops/DefaultCpuOpsBase$CpuTensor : sk/
public fun zeroGrad ()V
}

public final class sk/ainet/exec/tensor/ops/JvmTurboQuantKernels {
public static final field INSTANCE Lsk/ainet/exec/tensor/ops/JvmTurboQuantKernels;
public final fun absMax ([FII)F
public final fun dequantize ([B[F[FI)V
public static synthetic fun dequantize$default (Lsk/ainet/exec/tensor/ops/JvmTurboQuantKernels;[B[F[FIILjava/lang/Object;)V
public final fun quantize ([FI)Lsk/ainet/lang/tensor/ops/turboquant/QuantizedVector;
public final fun walshHadamardButterfly ([FII)V
}

public final class sk/ainet/java/SKaiNET {
public static final field INSTANCE Lsk/ainet/java/SKaiNET;
public static final fun context ()Lsk/ainet/context/ExecutionContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sk.ainet.exec.kernel
import sk.ainet.backend.api.kernel.Bf16MatmulKernel
import sk.ainet.backend.api.kernel.Fp32MatmulKernel
import sk.ainet.backend.api.kernel.KernelProvider
import sk.ainet.backend.api.kernel.Q4_0MatmulKernel
import sk.ainet.backend.api.kernel.Q8_0MatmulKernel

/**
Expand All @@ -25,4 +26,5 @@ public object ScalarKernelProvider : KernelProvider {
override fun matmulFp32(): Fp32MatmulKernel = ScalarMatmulKernel
override fun matmulBf16(): Bf16MatmulKernel = ScalarBf16MatmulKernel
override fun matmulQ8_0(): Q8_0MatmulKernel = ScalarQ8_0MatmulKernel
override fun matmulQ4_0(): Q4_0MatmulKernel = ScalarQ4_0MatmulKernel
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package sk.ainet.exec.kernel

import sk.ainet.backend.api.kernel.Q4_0MatmulKernel

/**
* Scalar reference implementation of [Q4_0MatmulKernel] — straight
* per-block dequant + per-element FMA, no SIMD. Always available on
* every KMP target. Used as:
*
* - The correctness reference that accelerated kernels (Panama Vector,
* native FFM) must match within FP order tolerance.
* - A guaranteed fallback when no accelerated provider is registered.
*
* Block layout (32-element block, 18 bytes):
* - bytes 0..1 : FP16 little-endian scale (`d`)
* - bytes 2..17: 16 bytes packing 32 4-bit codes (split layout)
*
* Dequant per element: `(code - 8) * d`. No min / offset.
*
* Performance is intentionally modest; production paths should pick the
* Panama Vector or native variant via the kernel registry.
*/
public object ScalarQ4_0MatmulKernel : Q4_0MatmulKernel {

private const val BLOCK_SIZE = 32
private const val BYTES_PER_BLOCK = 18

override fun matmul(
input: FloatArray, inputOffset: Int,
weight: ByteArray, weightByteOffset: Int,
inputDim: Int, outputDim: Int,
output: FloatArray, outputOffset: Int,
) {
require(inputDim % BLOCK_SIZE == 0) {
"ScalarQ4_0MatmulKernel: inputDim must be a multiple of $BLOCK_SIZE; got $inputDim"
}
if (outputDim == 0 || inputDim == 0) {
if (outputDim > 0) {
for (o in 0 until outputDim) output[outputOffset + o] = 0f
}
return
}
val blocksPerInputDim = inputDim / BLOCK_SIZE

for (o in 0 until outputDim) {
var acc = 0f
for (blockIdx in 0 until blocksPerInputDim) {
val blockBase = weightByteOffset + (blockIdx * outputDim + o) * BYTES_PER_BLOCK
// FP16 scale: two LE bytes.
val dBits = (weight[blockBase].toInt() and 0xFF) or
((weight[blockBase + 1].toInt() and 0xFF) shl 8)
val d = halfToFloat(dBits)
// 32 codes, blockIdx-th window of the input vector. Split
// layout: low nibbles → elements 0..15, high → 16..31.
val inputBase = inputOffset + blockIdx * BLOCK_SIZE
val codesBase = blockBase + 2
for (j in 0 until 16) {
val b = weight[codesBase + j].toInt() and 0xFF
val lo = (b and 0x0F) - 8
val hi = (b ushr 4) - 8
acc += input[inputBase + j] * lo * d
acc += input[inputBase + 16 + j] * hi * d
}
}
output[outputOffset + o] = acc
}
}

/**
* Convert a 16-bit IEEE-754 half-precision value (low 16 bits of
* [hbits]) to FP32. Mirrors [ScalarQ8_0MatmulKernel]'s inlined helper
* — the skainet-lang-core dequant helper is internal to that module.
*/
private fun halfToFloat(hbits: Int): Float {
val sign = (hbits and 0x8000) shl 16
val exp = (hbits and 0x7C00) shr 10
val mant = hbits and 0x03FF
return when (exp) {
0 -> {
if (mant == 0) Float.fromBits(sign)
else {
var m = mant
var e = -14
while ((m and 0x400) == 0) {
m = m shl 1
e--
}
m = m and 0x3FF
Float.fromBits(sign or ((e + 127) shl 23) or (m shl 13))
}
}
31 -> Float.fromBits(sign or (0xFF shl 23) or (mant shl 13))
else -> Float.fromBits(sign or ((exp - 15 + 127) shl 23) or (mant shl 13))
}
}
}
Loading
Loading