Skip to content

DSL for "numpy" slicing #116

Description

@michalharakal

GitHub Issue: Add Support for Tensor Slicing DSL

Problem Statement

Currently, the tensor library lacks a convenient, numpy-like slicing interface. Users need to work with low-level indexing operations when extracting sub-tensors, which makes the code verbose and error-prone. This creates several challenges:

  • Poor Developer Experience: Manual index calculations are tedious and hard to read
  • Error-Prone Operations: Easy to make off-by-one errors or boundary mistakes
  • Limited Expressiveness: Cannot easily express common slicing patterns like "all elements", "from index to end", etc.
  • Inconsistent API: Lacks the familiar numpy-style slicing that most ML practitioners expect

Solution

Implement a Kotlin DSL for tensor slicing that mimics numpy's slicing syntax, making tensor operations more intuitive and expressive. The DSL should provide:

  1. Segment-based Operations: Each tensor dimension can be sliced using segment operations
  2. Multiple Slice Types: Support for various slicing patterns (all, from, to, range, first, last, at)
  3. Negative Index Support: Handle negative indices like numpy (counting from the end)
  4. Bounds Safety: Automatic bounds checking and clamping for safety
  5. Type Safety: Full Kotlin type safety with generic tensor types

Implementation Components

The solution includes:

  • TensorSliceBuilder<T, V>: Main DSL builder for creating slices
  • SegmentBuilder<T, V>: Builder for individual dimension slicing operations
  • Slice<T, V>: Data class representing a slice with start/end indices
  • Comprehensive test coverage with 90+ test cases covering all operations and edge cases

Usage Examples

Basic Slicing Operations
// Select all elements in a dimension (equivalent to ":" in numpy)
val allElements = slice(tensor) {
    segment {
        all()
    }
}

// Select elements from index 2 to the end
val fromIndex = slice(tensor) {
    segment {
        from(2)
    }
}

// Select elements from start to index 5 (exclusive)
val toIndex = slice(tensor) {
    segment {
        to(5)
    }
}

// Select elements in range [2, 7) (end exclusive)
val rangeSlice = slice(tensor) {
    segment {
        range(2, 7)
    }
}
Single Element Selection
// Select first element
val firstElement = slice(tensor) {
    segment {
        first()
    }
}

// Select last element
val lastElement = slice(tensor) {
    segment {
        last()
    }
}

// Select element at specific index
val atIndex = slice(tensor) {
    segment {
        at(5)
    }
}

// Select element at negative index (from end)
val atNegativeIndex = slice(tensor) {
    segment {
        at(-1) // last element
    }
}
Multi-dimensional Slicing
// Slice a 2D tensor: all rows, columns from index 1 to end
val slicedTensor = slice(tensor2D) {
    segment {
        all() // first dimension: all rows
    }
    segment {
        from(1) // second dimension: columns from index 1
    }
}

// Complex 3D tensor slicing
val complex3DSlice = slice(tensor3D) {
    segment {
        at(1) // first dimension: element at index 1
    }
    segment {
        range(1, 3) // second dimension: range [1, 3)
    }
    segment {
        from(-2) // third dimension: last 2 elements
    }
}
Working with Negative Indices
// Negative indices work like in numpy
val negativeSlicing = slice(tensor) {
    segment {
        from(-3) // last 3 elements
    }
    segment {
        to(-1) // all but the last element
    }
    segment {
        range(-5, -2) // elements from 5th-last to 2nd-last
    }
}

Benefits

  • Intuitive Syntax: Familiar numpy-like slicing operations
  • Type Safety: Full Kotlin type safety with generics
  • Readable Code: Self-documenting slice operations
  • Error Prevention: Automatic bounds checking prevents runtime errors
  • Flexible: Supports complex multi-dimensional slicing patterns
  • Well Tested: Comprehensive test suite with 90+ test cases covering all edge cases

Technical Requirements

  • Kotlin Multiplatform support (Common, JVM, JS, Native)
  • Generic support for different tensor data types (DType and value types)
  • Integration with existing Tensor<T, V> interface
  • Immutable slice operations (returns new Slice objects)
  • Memory efficient (no data copying, only index tracking)

Acceptance Criteria

  • Implement TensorSliceBuilder DSL class
  • Implement SegmentBuilder with all slice operations (all, from, to, range, first, last, at)
  • Support negative indexing for all applicable operations
  • Implement bounds checking and safe index clamping
  • Create comprehensive test suite covering all operations and edge cases
  • Support multi-dimensional tensor slicing
  • Ensure type safety with generic tensor types
  • Add documentation and usage examples
  • Verify compatibility across all supported Kotlin platforms

This DSL will significantly improve the developer experience when working with tensors, making the library more accessible to ML practitioners familiar with numpy's slicing syntax.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions