Skip to content

Commit 7f14e42

Browse files
Merge pull request #130 from sk-ai-net/feature/97-memory-layout
#97 Memory layout
2 parents c1a24c2 + dcc6310 commit 7f14e42

24 files changed

Lines changed: 2723 additions & 147 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
GROUP=sk.ainet.core
2-
VERSION_NAME=0.0.1.1
2+
VERSION_NAME=0.0.1.2
33

44
POM_DESCRIPTION=SKaiNET
55

skainet-lang/skainet-lang-api/src/commonMain/kotlin/sk/ainet/lang/tensor/Shape.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public data class Shape(val dimensions: IntArray) {
88
}
99

1010
val volume: Int
11-
get() = dimensions.fold(1) { a, x -> a * x }
11+
get() = dimensions.fold(if (dimensions.isNotEmpty()) 1 else 0) { a, x -> a * x }
1212

1313
val rank: Int
1414
get() = dimensions.size

skainet-lang/skainet-lang-api/src/commonMain/kotlin/sk/ainet/lang/tensor/Tensor.kt

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,82 +7,82 @@ import sk.ainet.lang.types.DType
77
/**
88
* The core tensor abstraction in the SKaiNET framework, representing a fundamental
99
* architectural decision to compose tensors from data and operations.
10-
*
10+
*
1111
* ## Fundamental Architectural Decision: Tensor Composition
12-
*
12+
*
1313
* This interface embodies a key architectural principle in the SKaiNET framework:
1414
* **tensors are composed of two distinct, complementary components:**
15-
*
15+
*
1616
* 1. **Data Component (`TensorData`)** - Responsible for:
1717
* - Multi-dimensional data storage and indexing
1818
* - Memory layout and access patterns
1919
* - Shape and dimensional metadata
2020
* - Type-safe element access
21-
*
21+
*
2222
* 2. **Operations Component (`TensorOps`)** - Responsible for:
2323
* - Mathematical operations and transformations
2424
* - Computational algorithms
2525
* - Operation chaining and composition
2626
* - Performance-optimized implementations
27-
*
27+
*
2828
* ## Benefits of This Compositional Architecture
29-
*
29+
*
3030
* **Separation of Concerns**: Data management is cleanly separated from computational
3131
* logic, making the codebase more maintainable and easier to understand.
32-
*
32+
*
3333
* **Flexibility**: Different data storage strategies (dense, sparse, distributed) can
3434
* be combined with different operation implementations (CPU, GPU, specialized hardware)
3535
* without tight coupling.
36-
*
36+
*
3737
* **Performance Optimization**: Data layout can be optimized independently from
3838
* computational algorithms, enabling targeted performance improvements.
39-
*
39+
*
4040
* **Extensibility**: New data formats or operation types can be added without
4141
* modifying existing code, following the open-closed principle.
42-
*
42+
*
4343
* **Testability**: Data and operations can be tested independently, improving
4444
* test coverage and reducing complexity.
45-
*
45+
*
4646
* ## Usage Pattern
47-
*
47+
*
4848
* The tensor acts as a unified interface that delegates data access to the `data`
4949
* component and computational operations to the `ops` component, providing a
5050
* seamless experience while maintaining the benefits of compositional design.
51-
*
51+
*
5252
* @param T the data type constraint extending DType, defining the numerical precision
5353
* @param V the actual value type that will be stored and accessed
5454
*/
5555
public interface Tensor<T : DType, V> {
5656
/**
5757
* The data component responsible for storage, indexing, and memory management.
58-
*
58+
*
5959
* This component handles all aspects related to data storage and access,
60-
* including multi-dimensional indexing, shape management, and memory layout
60+
* including multidimensional indexing, shape management, and memory layout
6161
* optimization. It provides the foundation for the tensor's data model.
6262
*/
6363
public val data: TensorData<T, V>
64-
64+
6565
/**
6666
* The operations component responsible for computational algorithms and transformations.
67-
*
67+
*
6868
* This component provides all mathematical operations that can be performed
6969
* on the tensor, from basic arithmetic to complex neural network operations.
7070
* It leverages the data component for element access while encapsulating
7171
* all computational logic.
7272
*/
73-
public val ops: TensorOps<T, V>
73+
public val ops: TensorOps<V>
7474

7575
/**
7676
* The data type descriptor defining the numerical precision and value representation.
77-
*
77+
*
7878
* This property provides metadata about the tensor's data type, enabling
7979
* type-safe operations and appropriate memory allocation strategies.
8080
*/
8181
public val dtype: T
8282

8383
/**
8484
* The shape descriptor inherited from the data component.
85-
*
85+
*
8686
* This property delegates to the data component's shape, maintaining consistency
8787
* between the tensor interface and its underlying data representation.
8888
*/
@@ -91,7 +91,7 @@ public interface Tensor<T : DType, V> {
9191

9292
/**
9393
* The total number of elements in the tensor.
94-
*
94+
*
9595
* This computed property provides quick access to the tensor's total size,
9696
* calculated from the shape's volume. Useful for memory allocation and
9797
* iteration operations.
@@ -101,7 +101,7 @@ public interface Tensor<T : DType, V> {
101101

102102
/**
103103
* The number of dimensions in the tensor.
104-
*
104+
*
105105
* This computed property provides quick access to the tensor's dimensionality,
106106
* derived from the shape's rank. Essential for dimension-aware operations
107107
* and broadcasting compatibility checks.

skainet-lang/skainet-lang-api/src/commonMain/kotlin/sk/ainet/lang/tensor/data/TensorData.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import sk.ainet.lang.types.DType
77
* A fundamental data structure interface that provides indexed access to elements.
88
*
99
* This interface serves as the base for all data structures that need to provide
10-
* element access through multi-dimensional indexing. It is designed to support
10+
* element access through multidimensional indexing. It is designed to support
1111
* efficient access patterns commonly used in neural network computations.
1212
*
1313
* @param T the type of elements that can be accessed
1414
*/
1515
public interface ItemsAccessor<T> {
1616
/**
17-
* Retrieves an element at the specified multi-dimensional indices.
17+
* Retrieves an element at the specified multidimensional indices.
1818
*
1919
* This operator function allows accessing elements using bracket notation
2020
* with variable number of indices, supporting tensors of any dimensionality.
@@ -24,6 +24,12 @@ public interface ItemsAccessor<T> {
2424
* @throws IndexOutOfBoundsException if any index is out of bounds
2525
*/
2626
public operator fun get(vararg indices: Int): T
27+
28+
29+
/**
30+
* Setter
31+
*/
32+
public operator fun set(vararg indices: Int, value: T)
2733
}
2834

2935
/**
@@ -61,4 +67,6 @@ public interface TensorData<T : DType, V> : ItemsAccessor<V> {
6167
* @return the Shape object describing this tensor's dimensional structure
6268
*/
6369
public val shape: Shape
70+
71+
public companion object
6472
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package sk.ainet.lang.tensor.data
2+
3+
import sk.ainet.lang.types.DType
4+
5+
6+
public fun <T: DType,V> TensorData<T,V>.pprint(): String {
7+
return when (this.shape.rank) {
8+
0 -> {
9+
// Scalar - single value
10+
this.toString()
11+
}
12+
1 -> {
13+
// Vector - horizontal representation with parentheses
14+
val sb = StringBuilder()
15+
sb.append("[ ")
16+
for (i in 0 until this.shape[0]) {
17+
if (i > 0) sb.append(", ")
18+
sb.append(this[i].toString())
19+
}
20+
sb.append(" ]")
21+
sb.toString()
22+
}
23+
2 -> {
24+
// Matrix - vertical representation with Unicode brackets
25+
val sb = StringBuilder()
26+
val rows = this.shape[0]
27+
val cols = this.shape[1]
28+
29+
for (i in 0 until rows) {
30+
// Left bracket
31+
val leftBracket = when {
32+
rows == 1 -> "( "
33+
i == 0 -> ""
34+
i == rows - 1 -> ""
35+
else -> ""
36+
}
37+
sb.append(leftBracket)
38+
39+
// Matrix elements
40+
for (j in 0 until cols) {
41+
if (j > 0) sb.append(", ")
42+
sb.append(this[i, j].toString())
43+
}
44+
45+
// Right bracket
46+
val rightBracket = when {
47+
rows == 1 -> " )"
48+
i == 0 -> ""
49+
i == rows - 1 -> ""
50+
else -> ""
51+
}
52+
sb.append(rightBracket)
53+
54+
if (i < rows - 1) sb.append("\n")
55+
}
56+
sb.toString()
57+
}
58+
else -> {
59+
// Higher rank tensors - use toString
60+
this.toString()
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)