diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3b9005997..25f2cfd0d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,6 +1,5 @@
-# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/build.yml
+name: Gradle build
 
-name: build
 on: [ push ]
 
 jobs:
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 000000000..29a2ed649
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,31 @@
+name: Dokka publication
+
+on:
+  push:
+    branches:
+      - master
+
+jobs:
+  build:
+    runs-on: ubuntu-20.04
+    steps:
+      - name: Checkout the repo
+        uses: actions/checkout@v2
+      - name: Set up JDK 11
+        uses: actions/setup-java@v1
+        with:
+          java-version: 11
+      - name: Cache gradle
+        uses: actions/cache@v2
+        with:
+          path: ~/.gradle/caches
+          key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }}
+          restore-keys: |
+            ubuntu-20.04-gradle-
+      - name: Build
+        run: ./gradlew build --no-daemon --stacktrace
+      - name: Deploy to GitHub Pages
+        uses: JamesIves/github-pages-deploy-action@4.1.0
+        with:
+            branch: gh-pages
+            folder: build/dokka/htmlMultiModule
diff --git a/.github/workflows/deploy.yml b/.github/workflows/publish.yml
similarity index 52%
rename from .github/workflows/deploy.yml
rename to .github/workflows/publish.yml
index 997755816..42fa6d3b6 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/publish.yml
@@ -1,10 +1,15 @@
-# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/deploy.yml
+name: Gradle publish
 
-name: deploy
-on: workflow_dispatch
+on:
+  workflow_dispatch:
+  release:
+    types:
+      - created
 
 jobs:
-  build:
+  publish:
+    environment:
+      name: publish
     strategy:
       matrix:
         os: [macOS-latest, windows-latest]
@@ -33,13 +38,22 @@ jobs:
           key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
           restore-keys: |
             ${{ runner.os }}-gradle-
-      - name: Publish Mac Artifacts
-        if: matrix.os == 'macOS-latest'
-        run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }}
-        env:
-          signingKey: ${{ secrets.SIGNING_KEY }}
       - name: Publish Windows Artifacts
         if: matrix.os == 'windows-latest'
-        run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }}
-        env:
-          signingKey: ${{ secrets.SIGNING_KEY }}
+        run: >
+          ./gradlew release --no-daemon
+          -Ppublishing.enabled=true
+          -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
+          -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
+          -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
+          -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
+      - name: Publish Mac Artifacts
+        if: matrix.os == 'macOS-latest'
+        run: >
+          ./gradlew release --no-daemon
+          -Ppublishing.enabled=true
+          -Ppublishing.platform=macosX64
+          -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
+          -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
+          -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
+          -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7033df7f..47690e36a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,12 +2,20 @@
 
 ## [Unreleased]
 ### Added
+- ScaleOperations interface
+- Field extends ScaleOperations
 
 ### Changed
+- Exponential operations merged with hyperbolic functions
+- Space is replaced by Group. Space is reserved for vector spaces.
+- VectorSpace is now a vector space
+- 
 
 ### Deprecated
 
 ### Removed
+- Nearest in Domain. To be implemented in geometry package.
+- Number multiplication and division in main Algebra chain
 
 ### Fixed
 
diff --git a/build.gradle.kts b/build.gradle.kts
index cb3cb1a3b..113107f69 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -20,7 +20,7 @@ allprojects {
     }
 
     group = "space.kscience"
-    version = "0.2.0"
+    version = "0.3.0"
 }
 
 subprojects {
@@ -32,9 +32,9 @@ readme {
 }
 
 ksciencePublish {
-    spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven"
-    bintrayRepo = "kscience"
-    githubProject = "kmath"
+    github("kmath")
+    space()
+    sonatype()
 }
 
 apiValidation {
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index 77152dc0a..0301e4d67 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -92,6 +92,14 @@ benchmark {
         iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
         include("ExpressionsInterpretersBenchmark")
     }
+
+    configurations.register("matrixInverse") {
+        warmups = 1 // number of warmup iterations
+        iterations = 3 // number of iterations
+        iterationTime = 500 // time in seconds per iteration
+        iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
+        include("MatrixInverseBenchmark")
+    }
 }
 
 kotlin.sourceSets.all {
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt
index 535778844..43b698c03 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt
@@ -1,34 +1,38 @@
 package space.kscience.kmath.benchmarks
 
-import org.openjdk.jmh.annotations.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
 import java.nio.IntBuffer
 
 @State(Scope.Benchmark)
 internal class ArrayBenchmark {
     @Benchmark
-    fun benchmarkArrayRead() {
+    fun benchmarkArrayRead(blackhole: Blackhole) {
         var res = 0
-        for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i]
+        for (i in 1..size) res += array[size - i]
+        blackhole.consume(res)
     }
 
     @Benchmark
-    fun benchmarkBufferRead() {
+    fun benchmarkBufferRead(blackhole: Blackhole) {
         var res = 0
-        for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.arrayBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i]
+        for (i in 1..size) res += arrayBuffer[size - i]
+        blackhole.consume(res)
     }
 
     @Benchmark
-    fun nativeBufferRead() {
+    fun nativeBufferRead(blackhole: Blackhole) {
         var res = 0
-        for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.nativeBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i]
+        for (i in 1..size) res += nativeBuffer[size - i]
+        blackhole.consume(res)
     }
 
-    companion object {
-        const val size: Int = 1000
-        val array: IntArray = IntArray(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) { it }
-        val arrayBuffer: IntBuffer = IntBuffer.wrap(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array)
-        val nativeBuffer: IntBuffer = IntBuffer.allocate(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size).also { for (i in 0 until space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) it.put(i, i) }
+    private companion object {
+        private const val size = 1000
+        private val array = IntArray(size) { it }
+        private val arrayBuffer = IntBuffer.wrap(array)
+        private val nativeBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) }
     }
 }
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
index 1afb4e52c..1c3bbab75 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
@@ -1,8 +1,8 @@
 package space.kscience.kmath.benchmarks
 
-import org.openjdk.jmh.annotations.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
 import space.kscience.kmath.complex.Complex
 import space.kscience.kmath.complex.complex
 import space.kscience.kmath.structures.MutableBuffer
@@ -28,7 +28,7 @@ internal class BufferBenchmark {
         }
     }
 
-    companion object {
-        const val size: Int = 100
+    private companion object {
+        private const val size = 100
     }
 }
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
index 39eeb24d3..dbf373929 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
@@ -1,67 +1,65 @@
 package space.kscience.kmath.benchmarks
 
 import kotlinx.benchmark.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
-import space.kscience.kmath.commons.linear.CMMatrixContext
-import space.kscience.kmath.ejml.EjmlMatrixContext
-import space.kscience.kmath.linear.BufferMatrixContext
-import space.kscience.kmath.linear.Matrix
-import space.kscience.kmath.linear.RealMatrixContext
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
+import space.kscience.kmath.commons.linear.CMLinearSpace
+import space.kscience.kmath.ejml.EjmlLinearSpace
+import space.kscience.kmath.linear.LinearSpace
+import space.kscience.kmath.linear.invoke
 import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.invoke
-import space.kscience.kmath.structures.Buffer
 import kotlin.random.Random
 
 @State(Scope.Benchmark)
 internal class DotBenchmark {
     companion object {
         val random = Random(12224)
-        val dim = 1000
+        const val dim = 1000
 
         //creating invertible matrix
-        val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
-        val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
+        val matrix1 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
+        val matrix2 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
 
-        val cmMatrix1 = CMMatrixContext { matrix1.toCM() }
-        val cmMatrix2 = CMMatrixContext { matrix2.toCM() }
+        val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
+        val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
 
-        val ejmlMatrix1 = EjmlMatrixContext { matrix1.toEjml() }
-        val ejmlMatrix2 = EjmlMatrixContext { matrix2.toEjml() }
+        val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() }
+        val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() }
     }
 
     @Benchmark
-    fun cmDot() {
-        CMMatrixContext {
-            cmMatrix1 dot cmMatrix2
+    fun cmDot(blackhole: Blackhole) {
+        CMLinearSpace.run {
+            blackhole.consume(cmMatrix1 dot cmMatrix2)
         }
     }
 
     @Benchmark
-    fun ejmlDot() {
-        EjmlMatrixContext {
-            ejmlMatrix1 dot ejmlMatrix2
+    fun ejmlDot(blackhole: Blackhole) {
+        EjmlLinearSpace {
+            blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
         }
     }
 
     @Benchmark
-    fun ejmlDotWithConversion() {
-        EjmlMatrixContext {
-            matrix1 dot matrix2
+    fun ejmlDotWithConversion(blackhole: Blackhole) {
+        EjmlLinearSpace {
+            blackhole.consume(matrix1 dot matrix2)
         }
     }
 
     @Benchmark
-    fun bufferedDot() {
-        BufferMatrixContext(RealField, Buffer.Companion::real).invoke {
-            matrix1 dot matrix2
+    fun bufferedDot(blackhole: Blackhole) {
+        LinearSpace.auto(RealField).invoke {
+            blackhole.consume(matrix1 dot matrix2)
         }
     }
 
     @Benchmark
-    fun realDot() {
-        RealMatrixContext {
-            matrix1 dot matrix2
+    fun realDot(blackhole: Blackhole) {
+        LinearSpace.real {
+            blackhole.consume(matrix1 dot matrix2)
         }
     }
 }
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
index a9c0fe703..e5cfbf9f6 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
@@ -1,64 +1,62 @@
 package space.kscience.kmath.benchmarks
 
-import org.openjdk.jmh.annotations.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
 import space.kscience.kmath.asm.compile
 import space.kscience.kmath.ast.mstInField
 import space.kscience.kmath.expressions.Expression
 import space.kscience.kmath.expressions.expressionInField
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.expressions.symbol
-import space.kscience.kmath.operations.Field
 import space.kscience.kmath.operations.RealField
 import space.kscience.kmath.operations.bindSymbol
 import kotlin.random.Random
 
 @State(Scope.Benchmark)
 internal class ExpressionsInterpretersBenchmark {
-    private val algebra: Field<Double> = RealField
-    val x by symbol
-
     @Benchmark
-    fun functionalExpression() {
+    fun functionalExpression(blackhole: Blackhole) {
         val expr = algebra.expressionInField {
             val x = bindSymbol(x)
             x * const(2.0) + const(2.0) / x - const(16.0)
         }
 
-        invokeAndSum(expr)
+        invokeAndSum(expr, blackhole)
     }
 
     @Benchmark
-    fun mstExpression() {
+    fun mstExpression(blackhole: Blackhole) {
         val expr = algebra.mstInField {
             val x = bindSymbol(x)
-            x * 2.0 + 2.0 / x - 16.0
+            x * 2.0 + number(2.0) / x - 16.0
         }
 
-        invokeAndSum(expr)
+        invokeAndSum(expr, blackhole)
     }
 
     @Benchmark
-    fun asmExpression() {
+    fun asmExpression(blackhole: Blackhole) {
         val expr = algebra.mstInField {
             val x = bindSymbol(x)
-            x * 2.0 + 2.0 / x - 16.0
+            x * 2.0 + number(2.0) / x - 16.0
         }.compile()
 
-        invokeAndSum(expr)
+        invokeAndSum(expr, blackhole)
     }
 
     @Benchmark
-    fun rawExpression() {
+    fun rawExpression(blackhole: Blackhole) {
         val expr = Expression<Double> { args ->
             val x = args.getValue(x)
             x * 2.0 + 2.0 / x - 16.0
         }
-        invokeAndSum(expr)
+
+        invokeAndSum(expr, blackhole)
     }
 
-    private fun invokeAndSum(expr: Expression<Double>) {
+    private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
         val random = Random(0)
         var sum = 0.0
 
@@ -66,6 +64,11 @@ internal class ExpressionsInterpretersBenchmark {
             sum += expr(x to random.nextDouble())
         }
 
-        println(sum)
+        blackhole.consume(sum)
+    }
+
+    private companion object {
+        private val algebra = RealField
+        private val x by symbol
     }
 }
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt
deleted file mode 100644
index 22e735e12..000000000
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package space.kscience.kmath.benchmarks
-
-import kotlinx.benchmark.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
-import space.kscience.kmath.commons.linear.CMMatrixContext
-import space.kscience.kmath.commons.linear.CMMatrixContext.dot
-import space.kscience.kmath.commons.linear.inverse
-import space.kscience.kmath.ejml.EjmlMatrixContext
-import space.kscience.kmath.ejml.inverse
-import space.kscience.kmath.linear.Matrix
-import space.kscience.kmath.linear.MatrixContext
-import space.kscience.kmath.linear.inverseWithLup
-import space.kscience.kmath.linear.real
-import kotlin.random.Random
-
-@State(Scope.Benchmark)
-internal class LinearAlgebraBenchmark {
-    companion object {
-        val random = Random(1224)
-        val dim = 100
-
-        //creating invertible matrix
-        val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
-        val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
-        val matrix = l dot u
-    }
-
-    @Benchmark
-    fun kmathLupInversion() {
-        MatrixContext.real.inverseWithLup(matrix)
-    }
-
-    @Benchmark
-    fun cmLUPInversion() {
-        with(CMMatrixContext) {
-            inverse(matrix)
-        }
-    }
-
-    @Benchmark
-    fun ejmlInverse() {
-        with(EjmlMatrixContext) {
-            inverse(matrix)
-        }
-    }
-}
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
new file mode 100644
index 000000000..7aa8ac975
--- /dev/null
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
@@ -0,0 +1,48 @@
+package space.kscience.kmath.benchmarks
+
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
+import space.kscience.kmath.commons.linear.CMLinearSpace
+import space.kscience.kmath.commons.linear.inverse
+import space.kscience.kmath.ejml.EjmlLinearSpace
+import space.kscience.kmath.ejml.inverse
+import space.kscience.kmath.linear.LinearSpace
+import space.kscience.kmath.linear.inverseWithLup
+import space.kscience.kmath.linear.invoke
+import kotlin.random.Random
+
+@State(Scope.Benchmark)
+internal class MatrixInverseBenchmark {
+    companion object {
+        val random = Random(1224)
+        const val dim = 100
+
+        private val space = LinearSpace.real
+
+        //creating invertible matrix
+        val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
+        val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
+        val matrix = space { l dot u }
+    }
+
+    @Benchmark
+    fun kmathLupInversion(blackhole: Blackhole) {
+        blackhole.consume(LinearSpace.real.inverseWithLup(matrix))
+    }
+
+    @Benchmark
+    fun cmLUPInversion(blackhole: Blackhole) {
+        with(CMLinearSpace) {
+            blackhole.consume(inverse(matrix))
+        }
+    }
+
+    @Benchmark
+    fun ejmlInverse(blackhole: Blackhole) {
+        with(EjmlLinearSpace) {
+            blackhole.consume(inverse(matrix))
+        }
+    }
+}
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
index 5bcc09cdb..aeee0dafe 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
@@ -1,8 +1,9 @@
 package space.kscience.kmath.benchmarks
 
-import org.openjdk.jmh.annotations.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.operations.RealField
 import space.kscience.kmath.structures.Buffer
@@ -10,35 +11,38 @@ import space.kscience.kmath.structures.Buffer
 @State(Scope.Benchmark)
 internal class NDFieldBenchmark {
     @Benchmark
-    fun autoFieldAdd() {
+    fun autoFieldAdd(blackhole: Blackhole) {
         with(autoField) {
             var res: NDStructure<Double> = one
             repeat(n) { res += one }
+            blackhole.consume(res)
         }
     }
 
     @Benchmark
-    fun specializedFieldAdd() {
+    fun specializedFieldAdd(blackhole: Blackhole) {
         with(specializedField) {
             var res: NDStructure<Double> = one
             repeat(n) { res += 1.0 }
+            blackhole.consume(res)
         }
     }
 
 
     @Benchmark
-    fun boxingFieldAdd() {
+    fun boxingFieldAdd(blackhole: Blackhole) {
         with(genericField) {
             var res: NDStructure<Double> = one
             repeat(n) { res += 1.0 }
+            blackhole.consume(res)
         }
     }
 
-    companion object {
-        const val dim: Int = 1000
-        const val n: Int = 100
-        val autoField = NDAlgebra.auto(RealField, dim, dim)
-        val specializedField: RealNDField = NDAlgebra.real(dim, dim)
-        val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
+    private companion object {
+        private const val dim = 1000
+        private const val n = 100
+        private val autoField = NDAlgebra.auto(RealField, dim, dim)
+        private val specializedField = NDAlgebra.real(dim, dim)
+        private val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
     }
 }
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
index 370258bc6..c511173a9 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
@@ -1,51 +1,61 @@
 package space.kscience.kmath.benchmarks
 
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
 import org.jetbrains.bio.viktor.F64Array
-import org.openjdk.jmh.annotations.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
-import space.kscience.kmath.nd.*
+import space.kscience.kmath.nd.NDAlgebra
+import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.auto
+import space.kscience.kmath.nd.real
 import space.kscience.kmath.operations.RealField
 import space.kscience.kmath.viktor.ViktorNDField
 
 @State(Scope.Benchmark)
 internal class ViktorBenchmark {
-    final val dim: Int = 1000
-    final val n: Int = 100
-
-    // automatically build context most suited for given type.
-    final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
-    final val realField: RealNDField = NDAlgebra.real(dim, dim)
-    final val viktorField: ViktorNDField = ViktorNDField(dim, dim)
-
     @Benchmark
-    fun automaticFieldAddition() {
+    fun automaticFieldAddition(blackhole: Blackhole) {
         with(autoField) {
             var res: NDStructure<Double> = one
             repeat(n) { res += 1.0 }
+            blackhole.consume(res)
         }
     }
 
     @Benchmark
-    fun realFieldAddition() {
+    fun realFieldAddition(blackhole: Blackhole) {
         with(realField) {
             var res: NDStructure<Double> = one
             repeat(n) { res += 1.0 }
+            blackhole.consume(res)
         }
     }
 
     @Benchmark
-    fun viktorFieldAddition() {
+    fun viktorFieldAddition(blackhole: Blackhole) {
         with(viktorField) {
             var res = one
             repeat(n) { res += 1.0 }
+            blackhole.consume(res)
         }
     }
 
     @Benchmark
-    fun rawViktor() {
+    fun rawViktor(blackhole: Blackhole) {
         val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
         var res = one
         repeat(n) { res = res + one }
+        blackhole.consume(res)
+    }
+
+    private companion object {
+        private const val dim = 1000
+        private const val n = 100
+
+        // automatically build context most suited for given type.
+        private val autoField = NDAlgebra.auto(RealField, dim, dim)
+        private val realField = NDAlgebra.real(dim, dim)
+        private val viktorField = ViktorNDField(dim, dim)
     }
 }
diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
index 9f99b002a..0036b615c 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
@@ -1,48 +1,53 @@
 package space.kscience.kmath.benchmarks
 
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
 import org.jetbrains.bio.viktor.F64Array
-import org.openjdk.jmh.annotations.Benchmark
-import org.openjdk.jmh.annotations.Scope
-import org.openjdk.jmh.annotations.State
-import space.kscience.kmath.nd.*
+import space.kscience.kmath.nd.NDAlgebra
+import space.kscience.kmath.nd.auto
+import space.kscience.kmath.nd.real
 import space.kscience.kmath.operations.RealField
 import space.kscience.kmath.viktor.ViktorNDField
 
 @State(Scope.Benchmark)
 internal class ViktorLogBenchmark {
-    final val dim: Int = 1000
-    final val n: Int = 100
-
-    // automatically build context most suited for given type.
-    final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
-    final val realField: RealNDField = NDAlgebra.real(dim, dim)
-    final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim))
-
-
     @Benchmark
-    fun realFieldLog() {
-        with(realField) {
+    fun realFieldLog(blackhole: Blackhole) {
+        with(realNdField) {
             val fortyTwo = produce { 42.0 }
             var res = one
             repeat(n) { res = ln(fortyTwo) }
+            blackhole.consume(res)
         }
     }
 
     @Benchmark
-    fun viktorFieldLog() {
+    fun viktorFieldLog(blackhole: Blackhole) {
         with(viktorField) {
             val fortyTwo = produce { 42.0 }
             var res = one
             repeat(n) { res = ln(fortyTwo) }
+            blackhole.consume(res)
         }
     }
 
     @Benchmark
-    fun rawViktorLog() {
+    fun rawViktorLog(blackhole: Blackhole) {
         val fortyTwo = F64Array.full(dim, dim, init = 42.0)
-        var res: F64Array
-        repeat(n) {
-            res = fortyTwo.log()
-        }
+        lateinit var res: F64Array
+        repeat(n) { res = fortyTwo.log() }
+        blackhole.consume(res)
+    }
+
+    private companion object {
+        private const val dim = 1000
+        private const val n = 100
+
+        // automatically build context most suited for given type.
+        private val autoField = NDAlgebra.auto(RealField, dim, dim)
+        private val realNdField = NDAlgebra.real(dim, dim)
+        private val viktorField = ViktorNDField(intArrayOf(dim, dim))
     }
 }
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
index ee0f4a492..c342fc3ef 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
@@ -6,10 +6,10 @@ import space.kscience.kmath.operations.RealField
 fun main() {
     val expr = RealField.mstInField {
         val x = bindSymbol("x")
-        x * 2.0 + 2.0 / x - 16.0
+        x * 2.0 + number(2.0) / x - 16.0
     }
 
-    repeat(10000000){
+    repeat(10000000) {
         expr.invoke("x" to 1.0)
     }
 }
\ No newline at end of file
diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
new file mode 100644
index 000000000..8dd3d7f6b
--- /dev/null
+++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
@@ -0,0 +1,28 @@
+package space.kscience.kmath.linear
+
+import space.kscience.kmath.real.*
+import space.kscience.kmath.structures.RealBuffer
+
+fun main() {
+    val x0 = Point(0.0, 0.0, 0.0)
+    val sigma = Point(1.0, 1.0, 1.0)
+
+    val gaussian: (Point<Double>) -> Double = { x ->
+        require(x.size == x0.size)
+        kotlin.math.exp(-((x - x0) / sigma).square().sum())
+    }
+
+    fun ((Point<Double>) -> Double).grad(x: Point<Double>): Point<Double> {
+        require(x.size == x0.size)
+        return RealBuffer(x.size) { i ->
+            val h = sigma[i] / 5
+            val dVector = RealBuffer(x.size) { if (it == i) h else 0.0 }
+            val f1 = invoke(x + dVector / 2)
+            val f0 = invoke(x - dVector / 2)
+            (f1 - f0) / h
+        }
+    }
+
+    println(gaussian.grad(x0))
+
+}
\ No newline at end of file
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt
index 111cfec80..0c914468d 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt
@@ -3,8 +3,8 @@ package space.kscience.kmath.structures
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.NumbersAddOperations
 import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.RingWithNumbers
 import java.util.*
 import java.util.stream.IntStream
 
@@ -15,7 +15,7 @@ import java.util.stream.IntStream
 class StreamRealNDField(
     override val shape: IntArray,
 ) : NDField<Double, RealField>,
-    RingWithNumbers<NDStructure<Double>>,
+    NumbersAddOperations<NDStructure<Double>>,
     ExtendedField<NDStructure<Double>> {
 
     private val strides = DefaultStrides(shape)
@@ -79,25 +79,29 @@ class StreamRealNDField(
         return NDBuffer(strides, array.asBuffer())
     }
 
-    override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map() { power(it, pow) }
+    override fun NDStructure<Double>.unaryMinus(): NDStructure<Double> = map { -it }
 
-    override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { exp(it) }
+    override fun scale(a: NDStructure<Double>, value: Double): NDStructure<Double> = a.map { it * value }
 
-    override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { ln(it) }
+    override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map { power(it, pow) }
 
-    override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sin(it) }
-    override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cos(it) }
-    override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tan(it) }
-    override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asin(it) }
-    override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acos(it) }
-    override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atan(it) }
+    override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(it) }
 
-    override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sinh(it) }
-    override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cosh(it) }
-    override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tanh(it) }
-    override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asinh(it) }
-    override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acosh(it) }
-    override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atanh(it) }
+    override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { ln(it) }
+
+    override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sin(it) }
+    override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cos(it) }
+    override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tan(it) }
+    override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { asin(it) }
+    override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { acos(it) }
+    override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { atan(it) }
+
+    override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sinh(it) }
+    override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cosh(it) }
+    override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tanh(it) }
+    override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { asinh(it) }
+    override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { acosh(it) }
+    override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { atanh(it) }
 }
 
 fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)
\ No newline at end of file
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
index 13d6f00e4..66d85edff 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
@@ -7,7 +7,7 @@ import kotlin.system.measureTimeMillis
 @Suppress("UNUSED_VARIABLE")
 fun main() {
     val n = 6000
-    val structure = NDStructure.build(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 }
+    val structure = NDStructure.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 }
     structure.mapToBuffer { it + 1 } // warm-up
     val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } }
     println("Structure mapping finished in $time1 millis")
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
index fdd631238..d2d130ab4 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
@@ -5,7 +5,7 @@ import space.kscience.kmath.dimensions.D3
 import space.kscience.kmath.dimensions.DMatrixContext
 import space.kscience.kmath.dimensions.Dimension
 
-private fun DMatrixContext<Double>.simple() {
+private fun DMatrixContext<Double, *>.simple() {
     val m1 = produce<D2, D3> { i, j -> (i + j).toDouble() }
     val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() }
 
@@ -17,7 +17,7 @@ private object D5 : Dimension {
     override val dim: UInt = 5u
 }
 
-private fun DMatrixContext<Double>.custom() {
+private fun DMatrixContext<Double, *>.custom() {
     val m1 = produce<D2, D5> { i, j -> (i + j).toDouble() }
     val m2 = produce<D5, D2> { i, j -> (i - j).toDouble() }
     val m3 = produce<D2, D2> { i, j -> (i - j).toDouble() }
diff --git a/gradle.properties b/gradle.properties
index 1a2a263ac..e28e22e8e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,9 +1,10 @@
 kotlin.code.style=official
-kotlin.mpp.enableGranularSourceSetsMetadata=true
 kotlin.mpp.stability.nowarn=true
-kotlin.native.enableDependencyPropagation=false
 kotlin.parallel.tasks.in.project=true
 org.gradle.configureondemand=true
-org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
+org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
 org.gradle.parallel=true
-systemProp.org.gradle.internal.publish.checksums.insecure=true
+
+kotlin.mpp.enableGranularSourceSetsMetadata=true
+kotlin.native.enableDependencyPropagation=false
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2a563242c..442d9132e 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt
index 7bea65684..5ed39687b 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt
@@ -18,25 +18,25 @@ public object MstAlgebra : NumericAlgebra<MST> {
 }
 
 /**
- * [Space] over [MST] nodes.
+ * [Group] over [MST] nodes.
  */
-public object MstSpace : Space<MST>, NumericAlgebra<MST> {
-    public override val zero: MST.Numeric by lazy { number(0.0) }
+public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
+    public override val zero: MST.Numeric = number(0.0)
 
     public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
     public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
-    public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
+    public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b)
     public override operator fun MST.unaryPlus(): MST.Unary =
-        unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this)
+        unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this)
 
     public override operator fun MST.unaryMinus(): MST.Unary =
-        unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this)
+        unaryOperationFunction(GroupOperations.MINUS_OPERATION)(this)
 
     public override operator fun MST.minus(b: MST): MST.Binary =
-        binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b)
+        binaryOperationFunction(GroupOperations.MINUS_OPERATION)(this, b)
 
-    public override fun multiply(a: MST, k: Number): MST.Binary =
-        binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k))
+    public override fun scale(a: MST, value: Double): MST.Binary =
+        binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
 
     public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
         MstAlgebra.binaryOperationFunction(operation)
@@ -49,25 +49,26 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
  * [Ring] over [MST] nodes.
  */
 @OptIn(UnstableKMathAPI::class)
-public object MstRing : Ring<MST>, RingWithNumbers<MST> {
-    public override val zero: MST.Numeric
-        get() = MstSpace.zero
+public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
+    public override val zero: MST.Numeric  get() = MstGroup.zero
+    public override val one: MST.Numeric = number(1.0)
 
-    public override val one: MST.Numeric by lazy { number(1.0) }
+    public override fun number(value: Number): MST.Numeric = MstGroup.number(value)
+    public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
+    public override fun add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b)
+
+    public override fun scale(a: MST, value: Double): MST.Binary =
+        MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value))
 
-    public override fun number(value: Number): MST.Numeric = MstSpace.number(value)
-    public override fun bindSymbol(value: String): MST.Symbolic = MstSpace.bindSymbol(value)
-    public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
-    public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
     public override fun multiply(a: MST, b: MST): MST.Binary =
         binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
 
-    public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus }
-    public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus }
-    public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b }
+    public override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus }
+    public override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus }
+    public override operator fun MST.minus(b: MST): MST.Binary = MstGroup { this@minus - b }
 
     public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
-        MstSpace.binaryOperationFunction(operation)
+        MstGroup.binaryOperationFunction(operation)
 
     public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
         MstAlgebra.unaryOperationFunction(operation)
@@ -77,17 +78,18 @@ public object MstRing : Ring<MST>, RingWithNumbers<MST> {
  * [Field] over [MST] nodes.
  */
 @OptIn(UnstableKMathAPI::class)
-public object MstField : Field<MST>, RingWithNumbers<MST> {
-    public override val zero: MST.Numeric
-        get() = MstRing.zero
+public object MstField : Field<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
+    public override val zero: MST.Numeric get() = MstRing.zero
 
-    public override val one: MST.Numeric
-        get() = MstRing.one
+    public override val one: MST.Numeric get() = MstRing.one
 
-    public override fun bindSymbol(value: String): MST.Symbolic = MstRing.bindSymbol(value)
+    public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
     public override fun number(value: Number): MST.Numeric = MstRing.number(value)
     public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
-    public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
+
+    public override fun scale(a: MST, value: Double): MST.Binary =
+        MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value))
+
     public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
     public override fun divide(a: MST, b: MST): MST.Binary =
         binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
@@ -107,13 +109,10 @@ public object MstField : Field<MST>, RingWithNumbers<MST> {
  * [ExtendedField] over [MST] nodes.
  */
 public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
-    public override val zero: MST.Numeric
-        get() = MstField.zero
+    public override val zero: MST.Numeric get() = MstField.zero
+    public override val one: MST.Numeric get() = MstField.one
 
-    public override val one: MST.Numeric
-        get() = MstField.one
-
-    public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value)
+    public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
     public override fun number(value: Number): MST.Numeric = MstRing.number(value)
     public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
     public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
@@ -121,14 +120,17 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
     public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg)
     public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg)
     public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg)
-    public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.SINH_OPERATION)(arg)
-    public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg)
-    public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg)
-    public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg)
-    public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg)
-    public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg)
+    public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.SINH_OPERATION)(arg)
+    public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.COSH_OPERATION)(arg)
+    public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.TANH_OPERATION)(arg)
+    public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ASINH_OPERATION)(arg)
+    public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
+    public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
     public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
-    public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k)
+
+    public override fun scale(a: MST, value: Double): MST =
+        binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
+
     public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b)
     public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b)
     public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt
index 412dde32c..63dfb38f7 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt
@@ -54,13 +54,13 @@ public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
 ): MstExpression<T, A> = MstExpression(this, mstAlgebra.block())
 
 /**
- * Builds [MstExpression] over [Space].
+ * Builds [MstExpression] over [Group].
  *
  * @author Alexander Nozik
  */
-public inline fun <reified T : Any, A : Space<T>> A.mstInSpace(block: MstSpace.() -> MST): MstExpression<T, A> {
+public inline fun <reified T : Any, A : Group<T>> A.mstInGroup(block: MstGroup.() -> MST): MstExpression<T, A> {
     contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
-    return MstExpression(this, MstSpace.block())
+    return MstExpression(this, MstGroup.block())
 }
 
 /**
@@ -94,13 +94,13 @@ public inline fun <reified T : Any, A : ExtendedField<T>> A.mstInExtendedField(b
 }
 
 /**
- * Builds [MstExpression] over [FunctionalExpressionSpace].
+ * Builds [MstExpression] over [FunctionalExpressionGroup].
  *
  * @author Alexander Nozik
  */
-public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T, A> {
+public inline fun <reified T : Any, A : Group<T>> FunctionalExpressionGroup<T, A>.mstInGroup(block: MstGroup.() -> MST): MstExpression<T, A> {
     contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
-    return algebra.mstInSpace(block)
+    return algebra.mstInGroup(block)
 }
 
 /**
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt
index 492a5d11f..bb34254b1 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt
@@ -12,12 +12,12 @@ import kotlin.test.assertEquals
 internal class TestESTreeConsistencyWithInterpreter {
     @Test
     fun mstSpace() {
-        val res1 = MstSpace.mstInSpace {
+        val res1 = MstGroup.mstInGroup {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    number(3.toByte()) - (number(2.toByte()) + (multiply(
+                    number(3.toByte()) - (number(2.toByte()) + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
                 ),
 
@@ -25,12 +25,12 @@ internal class TestESTreeConsistencyWithInterpreter {
             ) + bindSymbol("x") + zero
         }("x" to MST.Numeric(2))
 
-        val res2 = MstSpace.mstInSpace {
+        val res2 = MstGroup.mstInGroup {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    number(3.toByte()) - (number(2.toByte()) + (multiply(
+                    number(3.toByte()) - (number(2.toByte()) + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
                 ),
 
@@ -46,9 +46,9 @@ internal class TestESTreeConsistencyWithInterpreter {
         val res1 = ByteRing.mstInRing {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    (bindSymbol("x") - (2.toByte() + (multiply(
+                    (bindSymbol("x") - (2.toByte() + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + 1.toByte()))) * 3.0 - 1.toByte()
                 ),
 
@@ -59,9 +59,9 @@ internal class TestESTreeConsistencyWithInterpreter {
         val res2 = ByteRing.mstInRing {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    (bindSymbol("x") - (2.toByte() + (multiply(
+                    (bindSymbol("x") - (2.toByte() + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + 1.toByte()))) * 3.0 - 1.toByte()
                 ),
                 number(1)
@@ -75,7 +75,7 @@ internal class TestESTreeConsistencyWithInterpreter {
     fun realField() {
         val res1 = RealField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
@@ -83,7 +83,7 @@ internal class TestESTreeConsistencyWithInterpreter {
 
         val res2 = RealField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
@@ -96,7 +96,7 @@ internal class TestESTreeConsistencyWithInterpreter {
     fun complexField() {
         val res1 = ComplexField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
@@ -104,7 +104,7 @@ internal class TestESTreeConsistencyWithInterpreter {
 
         val res2 = ComplexField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt
index 6e2f85327..27bf2f167 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt
@@ -2,7 +2,7 @@ package space.kscience.kmath.estree
 
 import space.kscience.kmath.ast.mstInExtendedField
 import space.kscience.kmath.ast.mstInField
-import space.kscience.kmath.ast.mstInSpace
+import space.kscience.kmath.ast.mstInGroup
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.operations.RealField
 import kotlin.random.Random
@@ -12,14 +12,14 @@ import kotlin.test.assertEquals
 internal class TestESTreeOperationsSupport {
     @Test
     fun testUnaryOperationInvocation() {
-        val expression = RealField.mstInSpace { -bindSymbol("x") }.compile()
+        val expression = RealField.mstInGroup { -bindSymbol("x") }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-2.0, res)
     }
 
     @Test
     fun testBinaryOperationInvocation() {
-        val expression = RealField.mstInSpace { -bindSymbol("x") + number(1.0) }.compile()
+        val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-1.0, res)
     }
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt
index be4aff34f..9a38ce81a 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt
@@ -14,9 +14,9 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
 import com.github.h0tk3y.betterParse.parser.ParseResult
 import com.github.h0tk3y.betterParse.parser.Parser
 import space.kscience.kmath.operations.FieldOperations
+import space.kscience.kmath.operations.GroupOperations
 import space.kscience.kmath.operations.PowerOperations
 import space.kscience.kmath.operations.RingOperations
-import space.kscience.kmath.operations.SpaceOperations
 
 /**
  * better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4.
@@ -55,7 +55,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
         .or(binaryFunction)
         .or(unaryFunction)
         .or(singular)
-        .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) })
+        .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(GroupOperations.MINUS_OPERATION, it) })
         .or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
 
     private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b ->
@@ -77,9 +77,9 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
         operator = plus or minus use TokenMatch::type
     ) { a, op, b ->
         if (op == plus)
-            MST.Binary(SpaceOperations.PLUS_OPERATION, a, b)
+            MST.Binary(GroupOperations.PLUS_OPERATION, a, b)
         else
-            MST.Binary(SpaceOperations.MINUS_OPERATION, a, b)
+            MST.Binary(GroupOperations.MINUS_OPERATION, a, b)
     }
 
     override val rootParser: Parser<MST> by subSumChain
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt
index 0f2328db6..7cc1497d0 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt
@@ -12,12 +12,12 @@ import kotlin.test.assertEquals
 internal class TestAsmConsistencyWithInterpreter {
     @Test
     fun mstSpace() {
-        val res1 = MstSpace.mstInSpace {
+        val res1 = MstGroup.mstInGroup {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    number(3.toByte()) - (number(2.toByte()) + (multiply(
+                    number(3.toByte()) - (number(2.toByte()) + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
                 ),
 
@@ -25,12 +25,12 @@ internal class TestAsmConsistencyWithInterpreter {
             ) + bindSymbol("x") + zero
         }("x" to MST.Numeric(2))
 
-        val res2 = MstSpace.mstInSpace {
+        val res2 = MstGroup.mstInGroup {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    number(3.toByte()) - (number(2.toByte()) + (multiply(
+                    number(3.toByte()) - (number(2.toByte()) + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
                 ),
 
@@ -46,9 +46,9 @@ internal class TestAsmConsistencyWithInterpreter {
         val res1 = ByteRing.mstInRing {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    (bindSymbol("x") - (2.toByte() + (multiply(
+                    (bindSymbol("x") - (2.toByte() + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + 1.toByte()))) * 3.0 - 1.toByte()
                 ),
 
@@ -59,9 +59,9 @@ internal class TestAsmConsistencyWithInterpreter {
         val res2 = ByteRing.mstInRing {
             binaryOperationFunction("+")(
                 unaryOperationFunction("+")(
-                    (bindSymbol("x") - (2.toByte() + (multiply(
+                    (bindSymbol("x") - (2.toByte() + (scale(
                         add(number(1), number(1)),
-                        2
+                        2.0
                     ) + 1.toByte()))) * 3.0 - 1.toByte()
                 ),
                 number(1)
@@ -75,7 +75,7 @@ internal class TestAsmConsistencyWithInterpreter {
     fun realField() {
         val res1 = RealField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
@@ -83,7 +83,7 @@ internal class TestAsmConsistencyWithInterpreter {
 
         val res2 = RealField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
@@ -96,7 +96,7 @@ internal class TestAsmConsistencyWithInterpreter {
     fun complexField() {
         val res1 = ComplexField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
@@ -104,7 +104,7 @@ internal class TestAsmConsistencyWithInterpreter {
 
         val res2 = ComplexField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
-                (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+                (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
                 number(1) / 2 + number(2.0) * one
             ) + zero
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt
index e3adc4629..e99075f07 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt
@@ -2,7 +2,7 @@ package space.kscience.kmath.asm
 
 import space.kscience.kmath.ast.mstInExtendedField
 import space.kscience.kmath.ast.mstInField
-import space.kscience.kmath.ast.mstInSpace
+import space.kscience.kmath.ast.mstInGroup
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.operations.RealField
 import kotlin.random.Random
@@ -12,14 +12,14 @@ import kotlin.test.assertEquals
 internal class TestAsmOperationsSupport {
     @Test
     fun testUnaryOperationInvocation() {
-        val expression = RealField.mstInSpace { -bindSymbol("x") }.compile()
+        val expression = RealField.mstInGroup { -bindSymbol("x") }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-2.0, res)
     }
 
     @Test
     fun testBinaryOperationInvocation() {
-        val expression = RealField.mstInSpace { -bindSymbol("x") + number(1.0) }.compile()
+        val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-1.0, res)
     }
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
index 8342a8071..b74167c3f 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
@@ -4,7 +4,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
 import space.kscience.kmath.expressions.*
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.operations.ExtendedField
-import space.kscience.kmath.operations.RingWithNumbers
+import space.kscience.kmath.operations.NumbersAddOperations
 
 /**
  * A field over commons-math [DerivativeStructure].
@@ -16,7 +16,8 @@ import space.kscience.kmath.operations.RingWithNumbers
 public class DerivativeStructureField(
     public val order: Int,
     bindings: Map<Symbol, Double>,
-) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>, RingWithNumbers<DerivativeStructure> {
+) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>,
+    NumbersAddOperations<DerivativeStructure> {
     public val numberOfVariables: Int = bindings.size
 
     public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
@@ -62,13 +63,11 @@ public class DerivativeStructureField(
 
     public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList())
 
+    override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate()
+
     public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
 
-    public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) {
-        is Double -> a.multiply(k)
-        is Int -> a.multiply(k)
-        else -> a.multiply(k.toDouble())
-    }
+    public override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value)
 
     public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
     public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
index 3638b9808..5f632491c 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
@@ -3,11 +3,13 @@ package space.kscience.kmath.commons.linear
 import org.apache.commons.math3.linear.*
 import space.kscience.kmath.linear.*
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.operations.RealField
 import space.kscience.kmath.structures.RealBuffer
 import kotlin.reflect.KClass
 import kotlin.reflect.cast
 
-public inline class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
+public class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
     public override val rowNum: Int get() = origin.rowDimension
     public override val colNum: Int get() = origin.columnDimension
 
@@ -50,12 +52,17 @@ public inline class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
     }?.let(type::cast)
 
     public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is NDStructure<*>) return false
+        return NDStructure.contentEquals(this, other)
+    }
+
+    override fun hashCode(): Int = origin.hashCode()
 }
 
-
-public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this)
-
-public class CMVector(public val origin: RealVector) : Point<Double> {
+public inline class CMVector(public val origin: RealVector) : Point<Double> {
     public override val size: Int get() = origin.dimension
 
     public override operator fun get(index: Int): Double = origin.getEntry(index)
@@ -63,16 +70,17 @@ public class CMVector(public val origin: RealVector) : Point<Double> {
     public override operator fun iterator(): Iterator<Double> = origin.toArray().iterator()
 }
 
-public fun Point<Double>.toCM(): CMVector = if (this is CMVector) this else {
-    val array = DoubleArray(size) { this[it] }
-    CMVector(ArrayRealVector(array))
-}
-
 public fun RealVector.toPoint(): CMVector = CMVector(this)
 
-public object CMMatrixContext : MatrixContext<Double, CMMatrix> {
-    public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix {
-        val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } }
+public object CMLinearSpace : LinearSpace<Double, RealField> {
+    override val elementAlgebra: RealField get() = RealField
+
+    public override fun buildMatrix(
+        rows: Int,
+        columns: Int,
+        initializer: RealField.(i: Int, j: Int) -> Double,
+    ): CMMatrix {
+        val array = Array(rows) { i -> DoubleArray(columns) { j -> RealField.initializer(i, j) } }
         return CMMatrix(Array2DRowRealMatrix(array))
     }
 
@@ -82,30 +90,50 @@ public object CMMatrixContext : MatrixContext<Double, CMMatrix> {
         else -> {
             //TODO add feature analysis
             val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } }
-            CMMatrix(Array2DRowRealMatrix(array))
+            Array2DRowRealMatrix(array).wrap()
         }
     }
 
+    public fun Point<Double>.toCM(): CMVector = if (this is CMVector) this else {
+        val array = DoubleArray(size) { this[it] }
+        ArrayRealVector(array).wrap()
+    }
+
+    internal fun RealMatrix.wrap(): CMMatrix = CMMatrix(this)
+    internal fun RealVector.wrap(): CMVector = CMVector(this)
+
+    override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point<Double> =
+        ArrayRealVector(DoubleArray(size) { RealField.initializer(it) }).wrap()
+
+    override fun Matrix<Double>.plus(other: Matrix<Double>): CMMatrix =
+        toCM().origin.add(other.toCM().origin).wrap()
+
+    override fun Point<Double>.plus(other: Point<Double>): CMVector =
+        toCM().origin.add(other.toCM().origin).wrap()
+
+    override fun Point<Double>.minus(other: Point<Double>): CMVector =
+        toCM().origin.subtract(other.toCM().origin).wrap()
+
     public override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix =
-        CMMatrix(toCM().origin.multiply(other.toCM().origin))
+        toCM().origin.multiply(other.toCM().origin).wrap()
 
     public override fun Matrix<Double>.dot(vector: Point<Double>): CMVector =
-        CMVector(toCM().origin.preMultiply(vector.toCM().origin))
+        toCM().origin.preMultiply(vector.toCM().origin).wrap()
 
-    public override operator fun Matrix<Double>.unaryMinus(): CMMatrix =
-        produce(rowNum, colNum) { i, j -> -get(i, j) }
-
-    public override fun add(a: Matrix<Double>, b: Matrix<Double>): CMMatrix =
-        CMMatrix(a.toCM().origin.multiply(b.toCM().origin))
-
-    public override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix =
-        CMMatrix(toCM().origin.subtract(b.toCM().origin))
-
-    public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
-        CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble()))
+    public override operator fun Matrix<Double>.minus(other: Matrix<Double>): CMMatrix =
+        toCM().origin.subtract(other.toCM().origin).wrap()
 
     public override operator fun Matrix<Double>.times(value: Double): CMMatrix =
-        produce(rowNum, colNum) { i, j -> get(i, j) * value }
+        toCM().origin.scalarMultiply(value).wrap()
+
+    override fun Double.times(m: Matrix<Double>): CMMatrix =
+        m * this
+
+    override fun Point<Double>.times(value: Double): CMVector =
+        toCM().origin.mapMultiply(value).wrap()
+
+    override fun Double.times(v: Point<Double>): CMVector =
+        v * this
 }
 
 public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix =
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt
index 3ce7ca9e6..b5fd0154e 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt
@@ -12,7 +12,7 @@ public enum class CMDecomposition {
     CHOLESKY
 }
 
-public fun CMMatrixContext.solver(
+public fun CMLinearSpace.solver(
     a: Matrix<Double>,
     decomposition: CMDecomposition = CMDecomposition.LUP
 ): DecompositionSolver = when (decomposition) {
@@ -23,19 +23,19 @@ public fun CMMatrixContext.solver(
     CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver
 }
 
-public fun CMMatrixContext.solve(
+public fun CMLinearSpace.solve(
     a: Matrix<Double>,
     b: Matrix<Double>,
     decomposition: CMDecomposition = CMDecomposition.LUP
-): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).asMatrix()
+): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).wrap()
 
-public fun CMMatrixContext.solve(
+public fun CMLinearSpace.solve(
     a: Matrix<Double>,
     b: Point<Double>,
     decomposition: CMDecomposition = CMDecomposition.LUP
 ): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint()
 
-public fun CMMatrixContext.inverse(
+public fun CMLinearSpace.inverse(
     a: Matrix<Double>,
     decomposition: CMDecomposition = CMDecomposition.LUP
-): CMMatrix = solver(a, decomposition).inverse.asMatrix()
+): CMMatrix = solver(a, decomposition).inverse.wrap()
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
index deadfda5b..a73fb0201 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
@@ -4,10 +4,7 @@ import space.kscience.kmath.memory.MemoryReader
 import space.kscience.kmath.memory.MemorySpec
 import space.kscience.kmath.memory.MemoryWriter
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.operations.ExtendedField
-import space.kscience.kmath.operations.FieldElement
-import space.kscience.kmath.operations.Norm
-import space.kscience.kmath.operations.RingWithNumbers
+import space.kscience.kmath.operations.*
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.MemoryBuffer
 import space.kscience.kmath.structures.MutableBuffer
@@ -47,7 +44,8 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
  * A field of [Complex].
  */
 @OptIn(UnstableKMathAPI::class)
-public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, RingWithNumbers<Complex> {
+public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, NumbersAddOperations<Complex>,
+    ScaleOperations<Complex> {
     public override val zero: Complex = 0.0.toComplex()
     public override val one: Complex = 1.0.toComplex()
 
@@ -56,8 +54,14 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Rin
      */
     public val i: Complex by lazy { Complex(0.0, 1.0) }
 
+    override fun Complex.unaryMinus(): Complex = Complex(-re, -im)
+
+    override fun number(value: Number): Complex = Complex(value.toDouble(), 0.0)
+
+    override fun scale(a: Complex, value: Double): Complex = Complex(a.re * value, a.im * value)
+
     public override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im)
-    public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
+//    public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
 
     public override fun multiply(a: Complex, b: Complex): Complex =
         Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
@@ -86,8 +90,10 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Rin
         }
     }
 
-    public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2
-    public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2
+    override operator fun Complex.div(k: Number): Complex = Complex(re / k.toDouble(), im / k.toDouble())
+
+    public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2.0
+    public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0
 
     public override fun tan(arg: Complex): Complex {
         val e1 = exp(-i * arg)
@@ -159,7 +165,8 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Rin
 
     public override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
 
-    public override fun bindSymbol(value: String): Complex = if (value == "i") i else super<ExtendedField>.bindSymbol(value)
+    public override fun bindSymbol(value: String): Complex =
+        if (value == "i") i else super<ExtendedField>.bindSymbol(value)
 }
 
 /**
@@ -181,7 +188,8 @@ public data class Complex(val re: Double, val im: Double) : FieldElement<Complex
         public override val objectSize: Int
             get() = 16
 
-        public override fun MemoryReader.read(offset: Int): Complex = Complex(readDouble(offset), readDouble(offset + 8))
+        public override fun MemoryReader.read(offset: Int): Complex =
+            Complex(readDouble(offset), readDouble(offset + 8))
 
         public override fun MemoryWriter.write(offset: Int, value: Complex) {
             writeDouble(offset, value.re)
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt
index 11cfea263..382659e10 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt
@@ -6,7 +6,7 @@ import space.kscience.kmath.nd.NDAlgebra
 import space.kscience.kmath.nd.NDBuffer
 import space.kscience.kmath.nd.NDStructure
 import space.kscience.kmath.operations.ExtendedField
-import space.kscience.kmath.operations.RingWithNumbers
+import space.kscience.kmath.operations.NumbersAddOperations
 import space.kscience.kmath.structures.Buffer
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
@@ -19,7 +19,7 @@ import kotlin.contracts.contract
 public class ComplexNDField(
     shape: IntArray,
 ) : BufferedNDField<Complex, ComplexField>(shape, ComplexField, Buffer.Companion::complex),
-    RingWithNumbers<NDStructure<Complex>>,
+    NumbersAddOperations<NDStructure<Complex>>,
     ExtendedField<NDStructure<Complex>> {
 
     override val zero: NDBuffer<Complex> by lazy { produce { zero } }
@@ -29,6 +29,7 @@ public class ComplexNDField(
         val d = value.toComplex() // minimize conversions
         return produce { d }
     }
+
 //
 //    @Suppress("OVERRIDE_BY_INLINE")
 //    override inline fun map(
@@ -75,25 +76,25 @@ public class ComplexNDField(
 //        return BufferedNDFieldElement(this, buffer)
 //    }
 
-    override fun power(arg: NDStructure<Complex>, pow: Number): NDBuffer<Complex> = arg.map() { power(it, pow) }
+    override fun power(arg: NDStructure<Complex>, pow: Number): NDBuffer<Complex> = arg.map { power(it, pow) }
 
-    override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { exp(it) }
+    override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { exp(it) }
 
-    override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { ln(it) }
+    override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { ln(it) }
 
-    override fun sin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { sin(it) }
-    override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cos(it) }
-    override fun tan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { tan(it) }
-    override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asin(it) }
-    override fun acos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { acos(it) }
-    override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atan(it) }
+    override fun sin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { sin(it) }
+    override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { cos(it) }
+    override fun tan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { tan(it) }
+    override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { asin(it) }
+    override fun acos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { acos(it) }
+    override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { atan(it) }
 
-    override fun sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { sinh(it) }
-    override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cosh(it) }
-    override fun tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { tanh(it) }
-    override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asinh(it) }
-    override fun acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { acosh(it) }
-    override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atanh(it) }
+    override fun sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { sinh(it) }
+    override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { cosh(it) }
+    override fun tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { tanh(it) }
+    override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { asinh(it) }
+    override fun acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { acosh(it) }
+    override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { atanh(it) }
 }
 
 
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt
index 4a15e7423..d391aff18 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt
@@ -37,7 +37,7 @@ public val Quaternion.r: Double
  */
 @OptIn(UnstableKMathAPI::class)
 public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>, PowerOperations<Quaternion>,
-    ExponentialOperations<Quaternion>, RingWithNumbers<Quaternion> {
+    ExponentialOperations<Quaternion>, NumbersAddOperations<Quaternion>, ScaleOperations<Quaternion> {
     override val zero: Quaternion = 0.toQuaternion()
     override val one: Quaternion = 1.toQuaternion()
 
@@ -59,10 +59,8 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
     public override fun add(a: Quaternion, b: Quaternion): Quaternion =
         Quaternion(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z)
 
-    public override fun multiply(a: Quaternion, k: Number): Quaternion {
-        val d = k.toDouble()
-        return Quaternion(a.w * d, a.x * d, a.y * d, a.z * d)
-    }
+    public override fun scale(a: Quaternion, value: Double): Quaternion =
+        Quaternion(a.w * value, a.x * value, a.y * value, a.z * value)
 
     public override fun multiply(a: Quaternion, b: Quaternion): Quaternion = Quaternion(
         a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
@@ -173,6 +171,15 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
         "k" -> k
         else -> super<Field>.bindSymbol(value)
     }
+
+    override fun number(value: Number): Quaternion =value.toQuaternion()
+
+    public override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0
+    public override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0
+    public override fun tanh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
+    public override fun asinh(arg: Quaternion): Quaternion = ln(sqrt(arg * arg + one) + arg)
+    public override fun acosh(arg: Quaternion): Quaternion = ln(arg + sqrt((arg - one) * (arg + one)))
+    public override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0
 }
 
 /**
@@ -207,8 +214,7 @@ public data class Quaternion(
         require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
     }
 
-    public override val context: QuaternionField
-        get() = QuaternionField
+    public override val context: QuaternionField get() = QuaternionField
 
     /**
      * Returns a string representation of this quaternion.
diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt
index 43560b35a..81a131318 100644
--- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt
+++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt
@@ -4,7 +4,6 @@ import space.kscience.kmath.expressions.FunctionalExpressionField
 import space.kscience.kmath.expressions.bindSymbol
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.expressions.symbol
-import space.kscience.kmath.operations.invoke
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -13,14 +12,11 @@ internal class ExpressionFieldForComplexTest {
 
     @Test
     fun testComplex() {
-        val context = FunctionalExpressionField(ComplexField)
-
-        val expression = context {
+        val expression = FunctionalExpressionField(ComplexField).run {
             val x = bindSymbol(x)
             x * x + 2 * x + one
         }
 
         assertEquals(expression(x to Complex(1.0, 0.0)), Complex(4.0, 0.0))
-        //assertEquals(expression(), Complex(9.0, 0.0))
     }
 }
diff --git a/kmath-core/README.md b/kmath-core/README.md
deleted file mode 100644
index 54380670d..000000000
--- a/kmath-core/README.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# The Core Module (`kmath-core`)
-
-The core features of KMath:
-
- - [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
- - [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them.
- - [linear](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
- - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
- - [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of 
-objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high 
-performance calculations to code generation.
- - [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains
- - [autodif](src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
-
-
-> #### Artifact:
->
-> This module artifact: `space.kscience:kmath-core:0.2.0`.
->
-> Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
->
-> Bintray development version:    [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
->
-> **Gradle:**
->
-> ```gradle
-> repositories {
->     maven { url 'https://repo.kotlin.link' }
->     maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
->     maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
->//     Uncomment if repo.kotlin.link is unavailable 
->//     maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
->//     maven { url 'https://dl.bintray.com/mipt-npm/dev' }
-> }
-> 
-> dependencies {
->     implementation 'space.kscience:kmath-core:0.2.0'
-> }
-> ```
-> **Gradle Kotlin DSL:**
->
-> ```kotlin
-> repositories {
->     maven("https://repo.kotlin.link")
->     maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
->     maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
->//     Uncomment if repo.kotlin.link is unavailable 
->//     maven("https://dl.bintray.com/mipt-npm/kscience")
->//     maven("https://dl.bintray.com/mipt-npm/dev")
-> }
-> 
-> dependencies {
->     implementation("space.kscience:kmath-core:0.2.0")
-> }
-> ```
diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api
index 4a21a3d7e..2fa9e165b 100644
--- a/kmath-core/api/kmath-core.api
+++ b/kmath-core/api/kmath-core.api
@@ -3,70 +3,6 @@ public abstract interface class space/kscience/kmath/domains/Domain {
 	public abstract fun getDimension ()I
 }
 
-public final class space/kscience/kmath/domains/HyperSquareDomain : space/kscience/kmath/domains/RealDomain {
-	public fun <init> (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)V
-	public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z
-	public fun getDimension ()I
-	public fun getLowerBound (I)Ljava/lang/Double;
-	public fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public fun getUpperBound (I)Ljava/lang/Double;
-	public fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun volume ()D
-}
-
-public abstract interface class space/kscience/kmath/domains/RealDomain : space/kscience/kmath/domains/Domain {
-	public abstract fun getLowerBound (I)Ljava/lang/Double;
-	public abstract fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public abstract fun getUpperBound (I)Ljava/lang/Double;
-	public abstract fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public abstract fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun volume ()D
-}
-
-public final class space/kscience/kmath/domains/UnconstrainedDomain : space/kscience/kmath/domains/RealDomain {
-	public fun <init> (I)V
-	public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z
-	public fun getDimension ()I
-	public fun getLowerBound (I)Ljava/lang/Double;
-	public fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public fun getUpperBound (I)Ljava/lang/Double;
-	public fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun volume ()D
-}
-
-public final class space/kscience/kmath/domains/UnivariateDomain : space/kscience/kmath/domains/RealDomain {
-	public static final synthetic fun box-impl (Lkotlin/ranges/ClosedFloatingPointRange;)Lspace/kscience/kmath/domains/UnivariateDomain;
-	public static fun constructor-impl (Lkotlin/ranges/ClosedFloatingPointRange;)Lkotlin/ranges/ClosedFloatingPointRange;
-	public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static final fun contains-impl (Lkotlin/ranges/ClosedFloatingPointRange;D)Z
-	public static fun contains-impl (Lkotlin/ranges/ClosedFloatingPointRange;Lspace/kscience/kmath/structures/Buffer;)Z
-	public fun equals (Ljava/lang/Object;)Z
-	public static fun equals-impl (Lkotlin/ranges/ClosedFloatingPointRange;Ljava/lang/Object;)Z
-	public static final fun equals-impl0 (Lkotlin/ranges/ClosedFloatingPointRange;Lkotlin/ranges/ClosedFloatingPointRange;)Z
-	public fun getDimension ()I
-	public static fun getDimension-impl (Lkotlin/ranges/ClosedFloatingPointRange;)I
-	public fun getLowerBound (I)Ljava/lang/Double;
-	public fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public static fun getLowerBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;I)Ljava/lang/Double;
-	public static fun getLowerBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public final fun getRange ()Lkotlin/ranges/ClosedFloatingPointRange;
-	public fun getUpperBound (I)Ljava/lang/Double;
-	public fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public static fun getUpperBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;I)Ljava/lang/Double;
-	public static fun getUpperBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double;
-	public fun hashCode ()I
-	public static fun hashCode-impl (Lkotlin/ranges/ClosedFloatingPointRange;)I
-	public fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun nearestInDomain-impl (Lkotlin/ranges/ClosedFloatingPointRange;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun toString ()Ljava/lang/String;
-	public static fun toString-impl (Lkotlin/ranges/ClosedFloatingPointRange;)Ljava/lang/String;
-	public final synthetic fun unbox-impl ()Lkotlin/ranges/ClosedFloatingPointRange;
-	public fun volume ()D
-	public static fun volume-impl (Lkotlin/ranges/ClosedFloatingPointRange;)D
-}
-
 public abstract interface class space/kscience/kmath/expressions/AutoDiffProcessor {
 	public abstract fun process (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/DifferentiableExpression;
 }
@@ -116,7 +52,7 @@ public final class space/kscience/kmath/expressions/ExpressionBuildersKt {
 	public static final fun extendedFieldExpression (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
 	public static final fun fieldExpression (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
 	public static final fun ringExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
-	public static final fun spaceExpression (Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
+	public static final fun spaceExpression (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
 }
 
 public final class space/kscience/kmath/expressions/ExpressionKt {
@@ -155,7 +91,7 @@ public final class space/kscience/kmath/expressions/FunctionalExpressionAlgebraK
 	public static final fun expressionInExtendedField (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
 	public static final fun expressionInField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
 	public static final fun expressionInRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
-	public static final fun expressionInSpace (Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
+	public static final fun expressionInSpace (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
 }
 
 public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField : space/kscience/kmath/expressions/FunctionalExpressionField, space/kscience/kmath/operations/ExtendedField {
@@ -179,9 +115,6 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField
 	public fun cosh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
 	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun exp (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun ln (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
@@ -190,8 +123,6 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField
 	public fun pow (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
 	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun power (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sin (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
@@ -206,21 +137,57 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField
 	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public class space/kscience/kmath/expressions/FunctionalExpressionField : space/kscience/kmath/expressions/FunctionalExpressionRing, space/kscience/kmath/operations/Field {
+public class space/kscience/kmath/expressions/FunctionalExpressionField : space/kscience/kmath/expressions/FunctionalExpressionRing, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations {
 	public fun <init> (Lspace/kscience/kmath/operations/Field;)V
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public final fun div (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
 	public final fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
 	public fun div (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
 	public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun divide (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
+	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
+	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Lspace/kscience/kmath/expressions/Expression;D)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
 	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/kscience/kmath/expressions/FunctionalExpressionSpace, space/kscience/kmath/operations/Ring {
+public class space/kscience/kmath/expressions/FunctionalExpressionGroup : space/kscience/kmath/expressions/FunctionalExpressionAlgebra, space/kscience/kmath/operations/Group {
+	public fun <init> (Lspace/kscience/kmath/operations/Group;)V
+	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun add (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun getZero ()Ljava/lang/Object;
+	public fun getZero ()Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public final fun minus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public final fun minus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
+	public fun minus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public final fun plus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public final fun plus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
+	public fun plus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun unaryMinus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun unaryPlus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
+}
+
+public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/kscience/kmath/expressions/FunctionalExpressionGroup, space/kscience/kmath/operations/Ring {
 	public fun <init> (Lspace/kscience/kmath/operations/Ring;)V
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun getOne ()Ljava/lang/Object;
@@ -234,36 +201,6 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k
 	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public class space/kscience/kmath/expressions/FunctionalExpressionSpace : space/kscience/kmath/expressions/FunctionalExpressionAlgebra, space/kscience/kmath/operations/Space {
-	public fun <init> (Lspace/kscience/kmath/operations/Space;)V
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun getZero ()Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public final fun minus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public final fun minus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
-	public fun minus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public final fun plus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public final fun plus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
-	public fun plus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression;
-	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryMinus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryPlus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression;
-}
-
 public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression {
 	public fun <init> (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V
 	public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
@@ -272,7 +209,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : s
 	public fun invoke (Ljava/util/Map;)Ljava/lang/Object;
 }
 
-public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField : space/kscience/kmath/expressions/SimpleAutoDiffField, space/kscience/kmath/operations/ExtendedField {
+public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField : space/kscience/kmath/expressions/SimpleAutoDiffField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/ScaleOperations {
 	public fun <init> (Lspace/kscience/kmath/operations/ExtendedField;Ljava/util/Map;)V
 	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun acos (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
@@ -294,12 +231,16 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField
 	public fun exp (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun ln (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
+	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
+	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun pow (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public final fun pow (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun power (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sin (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
@@ -314,7 +255,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField
 	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/RingWithNumbers {
+public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumbersAddOperations {
 	public fun <init> (Lspace/kscience/kmath/operations/Field;Ljava/util/Map;)V
 	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun add (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
@@ -329,8 +270,6 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien
 	public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public final fun derive (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
@@ -352,9 +291,7 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public fun minus (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public fun multiply (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
@@ -367,6 +304,8 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue;
 	public final fun setD (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Object;)V
 	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
@@ -493,107 +432,23 @@ public final class space/kscience/kmath/expressions/SymbolIndexerKt {
 	public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
 }
 
-public final class space/kscience/kmath/linear/BufferMatrix : space/kscience/kmath/nd/Structure2D {
-	public fun <init> (IILspace/kscience/kmath/structures/Buffer;)V
-	public fun elements ()Lkotlin/sequences/Sequence;
-	public fun equals (Ljava/lang/Object;)Z
-	public fun get (II)Ljava/lang/Object;
-	public fun get ([I)Ljava/lang/Object;
-	public final fun getBuffer ()Lspace/kscience/kmath/structures/Buffer;
-	public fun getColNum ()I
-	public fun getColumns ()Lspace/kscience/kmath/structures/Buffer;
-	public fun getDimension ()I
-	public fun getRowNum ()I
-	public fun getRows ()Lspace/kscience/kmath/structures/Buffer;
-	public fun getShape ()[I
-	public fun hashCode ()I
-	public fun toString ()Ljava/lang/String;
-}
-
-public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscience/kmath/linear/GenericMatrixContext {
-	public static final field Companion Lspace/kscience/kmath/linear/BufferMatrixContext$Companion;
+public final class space/kscience/kmath/linear/BufferLinearSpace : space/kscience/kmath/linear/LinearSpace {
 	public fun <init> (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D;
+	public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
+	public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 	public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun getElementContext ()Lspace/kscience/kmath/operations/Ring;
-	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public final fun one (II)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
-	public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryPlus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-}
-
-public final class space/kscience/kmath/linear/BufferMatrixContext$Companion {
-}
-
-public final class space/kscience/kmath/linear/BufferVectorSpace : space/kscience/kmath/linear/VectorSpace {
-	public fun <init> (ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;)V
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2;
-	public fun getSize ()I
-	public fun getSpace ()Lspace/kscience/kmath/operations/Space;
-	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun getZero ()Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring;
+	public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 	public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 	public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
+	public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer;
+	public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 	public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
 }
 
 public abstract interface class space/kscience/kmath/linear/CholeskyDecompositionFeature : space/kscience/kmath/linear/MatrixFeature {
@@ -611,39 +466,6 @@ public abstract interface class space/kscience/kmath/linear/DiagonalFeature : sp
 public final class space/kscience/kmath/linear/DiagonalFeature$Companion : space/kscience/kmath/linear/DiagonalFeature {
 }
 
-public abstract interface class space/kscience/kmath/linear/GenericMatrixContext : space/kscience/kmath/linear/MatrixContext {
-	public abstract fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Ring;
-	public abstract fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-}
-
-public final class space/kscience/kmath/linear/GenericMatrixContext$DefaultImpls {
-	public static fun add (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun binaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun div (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun minus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun multiply (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun plus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun point (Lspace/kscience/kmath/linear/GenericMatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun unaryMinus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun unaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-}
-
 public abstract interface class space/kscience/kmath/linear/InverseMatrixFeature : space/kscience/kmath/linear/MatrixFeature {
 	public abstract fun getInverse ()Lspace/kscience/kmath/nd/Structure2D;
 }
@@ -652,11 +474,6 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l
 	public static final field INSTANCE Lspace/kscience/kmath/linear/LFeature;
 }
 
-public final class space/kscience/kmath/linear/LinearAlgebraKt {
-	public static final fun asMatrix (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/linear/VirtualMatrix;
-	public static final fun asPoint (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer;
-}
-
 public abstract interface class space/kscience/kmath/linear/LinearSolver {
 	public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 	public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
@@ -667,9 +484,58 @@ public final class space/kscience/kmath/linear/LinearSolver$DefaultImpls {
 	public static fun solve (Lspace/kscience/kmath/linear/LinearSolver;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
 }
 
+public final class space/kscience/kmath/linear/LinearSolverKt {
+	public static final fun asMatrix (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/linear/VirtualMatrix;
+	public static final fun asVector (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer;
+}
+
+public abstract interface class space/kscience/kmath/linear/LinearSpace {
+	public static final field Companion Lspace/kscience/kmath/linear/LinearSpace$Companion;
+	public abstract fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring;
+	public abstract fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public abstract fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+}
+
+public final class space/kscience/kmath/linear/LinearSpace$Companion {
+	public final fun buffered (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/LinearSpace;
+	public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/LinearSpace$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/LinearSpace;
+	public final fun getReal ()Lspace/kscience/kmath/linear/LinearSpace;
+}
+
+public final class space/kscience/kmath/linear/LinearSpace$DefaultImpls {
+	public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun plus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static fun plus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
+	public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+}
+
+public final class space/kscience/kmath/linear/LinearSpaceKt {
+	public static final fun invoke (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+}
+
 public final class space/kscience/kmath/linear/LupDecomposition : space/kscience/kmath/linear/DeterminantFeature, space/kscience/kmath/linear/LupDecompositionFeature {
-	public fun <init> (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;[IZ)V
-	public final fun getContext ()Lspace/kscience/kmath/linear/MatrixContext;
+	public fun <init> (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;[IZ)V
+	public final fun getContext ()Lspace/kscience/kmath/linear/LinearSpace;
 	public fun getDeterminant ()Ljava/lang/Object;
 	public final fun getElementContext ()Lspace/kscience/kmath/operations/Field;
 	public fun getL ()Lspace/kscience/kmath/nd/Structure2D;
@@ -686,58 +552,27 @@ public abstract interface class space/kscience/kmath/linear/LupDecompositionFeat
 }
 
 public final class space/kscience/kmath/linear/LupDecompositionKt {
-	public static final fun abs (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Comparable;)Ljava/lang/Comparable;
-	public static final fun inverseWithLup (Lspace/kscience/kmath/linear/RealMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static final fun lup (Lspace/kscience/kmath/linear/MatrixContext;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LupDecomposition;
-	public static final fun lup (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/LupDecomposition;
+	public static final fun abs (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Comparable;)Ljava/lang/Comparable;
+	public static final fun inverseWithLup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/nd/Structure2D;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LupDecomposition;
+	public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/LupDecomposition;
+	public static final fun solveWithLup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 	public static final fun solveWithLup (Lspace/kscience/kmath/linear/LupDecomposition;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static final fun solveWithLup (Lspace/kscience/kmath/linear/RealMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
 }
 
 public final class space/kscience/kmath/linear/MatrixBuilder {
-	public fun <init> (II)V
+	public fun <init> (Lspace/kscience/kmath/linear/LinearSpace;II)V
 	public final fun getColumns ()I
+	public final fun getLinearSpace ()Lspace/kscience/kmath/linear/LinearSpace;
 	public final fun getRows ()I
 	public final fun invoke ([Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
 }
 
 public final class space/kscience/kmath/linear/MatrixBuilderKt {
-	public static final fun build (Lspace/kscience/kmath/nd/Structure2D$Companion;II)Lspace/kscience/kmath/linear/MatrixBuilder;
-	public static final fun column (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-	public static final fun row (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-}
-
-public abstract interface class space/kscience/kmath/linear/MatrixContext : space/kscience/kmath/operations/SpaceOperations {
-	public static final field Companion Lspace/kscience/kmath/linear/MatrixContext$Companion;
-	public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-}
-
-public final class space/kscience/kmath/linear/MatrixContext$Companion {
-	public final fun buffered (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/GenericMatrixContext;
-	public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/MatrixContext$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/GenericMatrixContext;
-}
-
-public final class space/kscience/kmath/linear/MatrixContext$DefaultImpls {
-	public static fun binaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun div (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun minus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun plus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun point (Lspace/kscience/kmath/linear/MatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun unaryMinus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun unaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
 }
 
 public abstract interface class space/kscience/kmath/linear/MatrixFeature {
@@ -753,12 +588,12 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km
 	public fun get (II)Ljava/lang/Object;
 	public fun get ([I)Ljava/lang/Object;
 	public fun getColNum ()I
-	public fun getColumns ()Lspace/kscience/kmath/structures/Buffer;
+	public fun getColumns ()Ljava/util/List;
 	public fun getDimension ()I
 	public final fun getFeatures ()Ljava/util/Set;
 	public final fun getOrigin ()Lspace/kscience/kmath/nd/Structure2D;
 	public fun getRowNum ()I
-	public fun getRows ()Lspace/kscience/kmath/structures/Buffer;
+	public fun getRows ()Ljava/util/List;
 	public fun getShape ()[I
 	public fun hashCode ()I
 	public fun toString ()Ljava/lang/String;
@@ -766,12 +601,11 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km
 
 public final class space/kscience/kmath/linear/MatrixWrapperKt {
 	public static final fun getOrigin (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static final fun one (Lspace/kscience/kmath/linear/GenericMatrixContext;II)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun one (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/nd/Structure2D;
 	public static final fun plus (Lspace/kscience/kmath/nd/Structure2D;Ljava/util/Collection;)Lspace/kscience/kmath/linear/MatrixWrapper;
 	public static final fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/linear/MatrixFeature;)Lspace/kscience/kmath/linear/MatrixWrapper;
-	public static final fun square (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
 	public static final fun transpose (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public static final fun zero (Lspace/kscience/kmath/linear/GenericMatrixContext;II)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun zero (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/nd/Structure2D;
 }
 
 public final class space/kscience/kmath/linear/OrthogonalFeature : space/kscience/kmath/linear/MatrixFeature {
@@ -783,52 +617,6 @@ public abstract interface class space/kscience/kmath/linear/QRDecompositionFeatu
 	public abstract fun getR ()Lspace/kscience/kmath/nd/Structure2D;
 }
 
-public final class space/kscience/kmath/linear/RealMatrixContext : space/kscience/kmath/linear/MatrixContext {
-	public static final field INSTANCE Lspace/kscience/kmath/linear/RealMatrixContext;
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public final fun one (II)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
-	public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun times (DLspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun times (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/BufferMatrix;
-	public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
-	public final fun toBufferMatrix (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix;
-	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryPlus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
-}
-
-public final class space/kscience/kmath/linear/RealMatrixContextKt {
-	public static final fun getReal (Lspace/kscience/kmath/linear/MatrixContext$Companion;)Lspace/kscience/kmath/linear/RealMatrixContext;
-}
-
 public abstract interface class space/kscience/kmath/linear/SingularValueDecompositionFeature : space/kscience/kmath/linear/MatrixFeature {
 	public abstract fun getS ()Lspace/kscience/kmath/nd/Structure2D;
 	public abstract fun getSingularValues ()Lspace/kscience/kmath/structures/Buffer;
@@ -849,40 +637,6 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat
 	public static final field INSTANCE Lspace/kscience/kmath/linear/UnitFeature;
 }
 
-public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Space {
-	public static final field Companion Lspace/kscience/kmath/linear/VectorSpace$Companion;
-	public abstract fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun getSize ()I
-	public abstract fun getSpace ()Lspace/kscience/kmath/operations/Space;
-	public abstract fun getZero ()Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun multiply (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
-}
-
-public final class space/kscience/kmath/linear/VectorSpace$Companion {
-	public final fun buffered (ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorSpace;
-	public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorSpace;
-	public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorSpace;
-}
-
-public final class space/kscience/kmath/linear/VectorSpace$DefaultImpls {
-	public static fun add (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun binaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun div (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun getZero (Lspace/kscience/kmath/linear/VectorSpace;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun minus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun multiply (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun plus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun unaryMinus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun unaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-}
-
 public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/kmath/nd/Structure2D {
 	public fun <init> (IILkotlin/jvm/functions/Function2;)V
 	public fun elements ()Lkotlin/sequences/Sequence;
@@ -890,11 +644,11 @@ public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/km
 	public fun get (II)Ljava/lang/Object;
 	public fun get ([I)Ljava/lang/Object;
 	public fun getColNum ()I
-	public fun getColumns ()Lspace/kscience/kmath/structures/Buffer;
+	public fun getColumns ()Ljava/util/List;
 	public fun getDimension ()I
 	public final fun getGenerator ()Lkotlin/jvm/functions/Function2;
 	public fun getRowNum ()I
-	public fun getRows ()Lspace/kscience/kmath/structures/Buffer;
+	public fun getRows ()Ljava/util/List;
 	public fun getShape ()[I
 	public fun hashCode ()I
 }
@@ -908,9 +662,9 @@ public final class space/kscience/kmath/misc/CumulativeKt {
 	public static final fun cumulative (Ljava/util/Iterator;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/Iterator;
 	public static final fun cumulative (Ljava/util/List;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
 	public static final fun cumulative (Lkotlin/sequences/Sequence;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence;
-	public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Iterable;
-	public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Space;)Ljava/util/List;
-	public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Space;)Lkotlin/sequences/Sequence;
+	public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Iterable;
+	public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Group;)Ljava/util/List;
+	public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Lkotlin/sequences/Sequence;
 	public static final fun cumulativeSumOfDouble (Ljava/lang/Iterable;)Ljava/lang/Iterable;
 	public static final fun cumulativeSumOfDouble (Ljava/util/List;)Ljava/util/List;
 	public static final fun cumulativeSumOfDouble (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
@@ -946,41 +700,42 @@ public final class space/kscience/kmath/nd/BufferNDAlgebra$DefaultImpls {
 
 public final class space/kscience/kmath/nd/BufferNDAlgebraKt {
 	public static final fun field (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDField;
+	public static final fun group (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDGroup;
 	public static final fun ndField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun ndGroup (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
 	public static final fun ndRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-	public static final fun ndSpace (Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
 	public static final fun ring (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDRing;
-	public static final fun space (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDSpace;
 }
 
 public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/nd/NDField {
 	public fun <init> ([ILspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun div (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
+	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure;
+	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 }
 
-public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDSpace, space/kscience/kmath/nd/NDRing {
-	public fun <init> ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
-	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun getOne ()Ljava/lang/Object;
-	public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun times (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-}
-
-public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/BufferNDAlgebra, space/kscience/kmath/nd/NDSpace {
-	public fun <init> ([ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;)V
+public class space/kscience/kmath/nd/BufferedNDGroup : space/kscience/kmath/nd/BufferNDAlgebra, space/kscience/kmath/nd/NDGroup {
+	public fun <init> ([ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)V
 	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
@@ -990,12 +745,10 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B
 	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
 	public synthetic fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer;
 	public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2;
-	public synthetic fun getElementContext ()Ljava/lang/Object;
-	public final fun getElementContext ()Lspace/kscience/kmath/operations/Space;
+	public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra;
+	public final fun getElementContext ()Lspace/kscience/kmath/operations/Group;
 	public final fun getShape ()[I
 	public fun getStrides ()Lspace/kscience/kmath/nd/Strides;
 	public synthetic fun getZero ()Ljava/lang/Object;
@@ -1009,18 +762,12 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B
 	public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun minus (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun plus (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
 	public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryMinus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
@@ -1030,6 +777,19 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B
 	public fun unaryPlus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 }
 
+public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDGroup, space/kscience/kmath/nd/NDRing {
+	public fun <init> ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
+	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun getOne ()Ljava/lang/Object;
+	public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer;
+	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun times (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+}
+
 public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath/nd/Strides {
 	public static final field Companion Lspace/kscience/kmath/nd/DefaultStrides$Companion;
 	public synthetic fun <init> ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -1065,7 +825,7 @@ public final class space/kscience/kmath/nd/MutableNDStructure$DefaultImpls {
 public abstract interface class space/kscience/kmath/nd/NDAlgebra {
 	public static final field Companion Lspace/kscience/kmath/nd/NDAlgebra$Companion;
 	public abstract fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun getElementContext ()Ljava/lang/Object;
+	public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Algebra;
 	public abstract fun getShape ()[I
 	public abstract fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public abstract fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
@@ -1093,7 +853,7 @@ public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/NDStruct
 	public fun toString ()Ljava/lang/String;
 }
 
-public abstract interface class space/kscience/kmath/nd/NDField : space/kscience/kmath/nd/NDRing, space/kscience/kmath/operations/Field {
+public abstract interface class space/kscience/kmath/nd/NDField : space/kscience/kmath/nd/NDRing, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations {
 	public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public abstract fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public abstract fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
@@ -1104,33 +864,64 @@ public final class space/kscience/kmath/nd/NDField$DefaultImpls {
 	public static fun binaryOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun div (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun div (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun divide (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun invoke (Lspace/kscience/kmath/nd/NDField;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun leftSideNumberOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun minus (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun minus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun minus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun multiply (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun multiply (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun number (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun plus (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun plus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun plus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun rightSideNumberOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun times (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun unaryMinus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun unaryOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 }
 
-public abstract interface class space/kscience/kmath/nd/NDRing : space/kscience/kmath/nd/NDSpace, space/kscience/kmath/operations/Ring {
+public abstract interface class space/kscience/kmath/nd/NDGroup : space/kscience/kmath/nd/NDAlgebra, space/kscience/kmath/operations/Group {
+	public static final field Companion Lspace/kscience/kmath/nd/NDGroup$Companion;
+	public abstract fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public abstract fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
+	public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public abstract fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
+}
+
+public final class space/kscience/kmath/nd/NDGroup$Companion {
+}
+
+public final class space/kscience/kmath/nd/NDGroup$DefaultImpls {
+	public static fun add (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun binaryOperation (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun invoke (Lspace/kscience/kmath/nd/NDGroup;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun unaryOperation (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+}
+
+public abstract interface class space/kscience/kmath/nd/NDRing : space/kscience/kmath/nd/NDGroup, space/kscience/kmath/operations/Ring {
 	public static final field Companion Lspace/kscience/kmath/nd/NDRing$Companion;
 	public abstract fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
@@ -1145,62 +936,22 @@ public final class space/kscience/kmath/nd/NDRing$DefaultImpls {
 	public static fun binaryOperation (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun div (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun invoke (Lspace/kscience/kmath/nd/NDRing;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun minus (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun minus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun minus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun multiply (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun multiply (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun plus (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun plus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun plus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun times (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun unaryMinus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun unaryOperation (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 }
 
-public abstract interface class space/kscience/kmath/nd/NDSpace : space/kscience/kmath/nd/NDAlgebra, space/kscience/kmath/operations/Space {
-	public static final field Companion Lspace/kscience/kmath/nd/NDSpace$Companion;
-	public abstract fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-}
-
-public final class space/kscience/kmath/nd/NDSpace$Companion {
-}
-
-public final class space/kscience/kmath/nd/NDSpace$DefaultImpls {
-	public static fun add (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun binaryOperation (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun div (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun invoke (Lspace/kscience/kmath/nd/NDSpace;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun multiply (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun times (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun times (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun unaryMinus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun unaryOperation (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-}
-
 public abstract interface class space/kscience/kmath/nd/NDStructure {
 	public static final field Companion Lspace/kscience/kmath/nd/NDStructure$Companion;
 	public abstract fun elements ()Lkotlin/sequences/Sequence;
@@ -1214,10 +965,10 @@ public abstract interface class space/kscience/kmath/nd/NDStructure {
 public final class space/kscience/kmath/nd/NDStructure$Companion {
 	public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer;
 	public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer;
-	public final fun build (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer;
-	public final fun build ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer;
-	public static synthetic fun build$default (Lspace/kscience/kmath/nd/NDStructure$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer;
-	public static synthetic fun build$default (Lspace/kscience/kmath/nd/NDStructure$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer;
+	public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer;
+	public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer;
+	public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/NDStructure$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer;
+	public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/NDStructure$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer;
 	public final fun contentEquals (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Z
 }
 
@@ -1230,7 +981,7 @@ public final class space/kscience/kmath/nd/NDStructureKt {
 	public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableNDStructure;Lkotlin/jvm/functions/Function2;)V
 }
 
-public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd/BufferedNDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/RingWithNumbers {
+public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd/BufferedNDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations {
 	public fun <init> ([I)V
 	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun acos (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
@@ -1258,9 +1009,6 @@ public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd
 	public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer;
 	public synthetic fun getZero ()Ljava/lang/Object;
 	public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer;
-	public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun ln (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
 	public fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
@@ -1273,6 +1021,7 @@ public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd
 	public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer;
+	public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
@@ -1283,9 +1032,9 @@ public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd
 	public fun power (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer;
 	public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
 	public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sin (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
 	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1310,7 +1059,7 @@ public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/Ru
 	public final fun getExpected ()[I
 }
 
-public final class space/kscience/kmath/nd/ShortNDRing : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/operations/RingWithNumbers {
+public final class space/kscience/kmath/nd/ShortNDRing : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/operations/NumbersAddOperations {
 	public fun <init> ([I)V
 	public synthetic fun getOne ()Ljava/lang/Object;
 	public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer;
@@ -1376,22 +1125,21 @@ public abstract interface class space/kscience/kmath/nd/Structure2D : space/ksci
 	public abstract fun get (II)Ljava/lang/Object;
 	public abstract fun get ([I)Ljava/lang/Object;
 	public abstract fun getColNum ()I
-	public abstract fun getColumns ()Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun getColumns ()Ljava/util/List;
 	public abstract fun getRowNum ()I
-	public abstract fun getRows ()Lspace/kscience/kmath/structures/Buffer;
+	public abstract fun getRows ()Ljava/util/List;
 	public abstract fun getShape ()[I
 }
 
 public final class space/kscience/kmath/nd/Structure2D$Companion {
-	public final fun real (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix;
 }
 
 public final class space/kscience/kmath/nd/Structure2D$DefaultImpls {
 	public static fun elements (Lspace/kscience/kmath/nd/Structure2D;)Lkotlin/sequences/Sequence;
 	public static fun get (Lspace/kscience/kmath/nd/Structure2D;[I)Ljava/lang/Object;
-	public static fun getColumns (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun getColumns (Lspace/kscience/kmath/nd/Structure2D;)Ljava/util/List;
 	public static fun getDimension (Lspace/kscience/kmath/nd/Structure2D;)I
-	public static fun getRows (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun getRows (Lspace/kscience/kmath/nd/Structure2D;)Ljava/util/List;
 	public static fun getShape (Lspace/kscience/kmath/nd/Structure2D;)[I
 }
 
@@ -1420,27 +1168,23 @@ public abstract interface class space/kscience/kmath/operations/AlgebraElement {
 }
 
 public final class space/kscience/kmath/operations/AlgebraElementsKt {
-	public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Ljava/lang/Number;)Lspace/kscience/kmath/operations/AlgebraElement;
 	public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
-	public static final fun minus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
 	public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
-	public static final fun times (Ljava/lang/Number;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
-	public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Ljava/lang/Number;)Lspace/kscience/kmath/operations/AlgebraElement;
 	public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
 }
 
 public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
-	public static final fun abs (Lspace/kscience/kmath/operations/Space;Ljava/lang/Comparable;)Ljava/lang/Comparable;
-	public static final fun average (Lspace/kscience/kmath/operations/Space;Ljava/lang/Iterable;)Ljava/lang/Object;
-	public static final fun average (Lspace/kscience/kmath/operations/Space;Lkotlin/sequences/Sequence;)Ljava/lang/Object;
-	public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object;
-	public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object;
+	public static final fun abs (Lspace/kscience/kmath/operations/Group;Ljava/lang/Comparable;)Ljava/lang/Comparable;
+	public static final fun average (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object;
+	public static final fun average (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object;
+	public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object;
+	public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object;
 	public static final fun power (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;I)Ljava/lang/Object;
 	public static final fun power (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object;
-	public static final fun sum (Lspace/kscience/kmath/operations/Space;Ljava/lang/Iterable;)Ljava/lang/Object;
-	public static final fun sum (Lspace/kscience/kmath/operations/Space;Lkotlin/sequences/Sequence;)Ljava/lang/Object;
-	public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object;
-	public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object;
+	public static final fun sum (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object;
+	public static final fun sum (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object;
+	public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object;
+	public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object;
 }
 
 public final class space/kscience/kmath/operations/AlgebraKt {
@@ -1481,7 +1225,7 @@ public final class space/kscience/kmath/operations/BigInt$Companion {
 	public final fun getZERO ()Lspace/kscience/kmath/operations/BigInt;
 }
 
-public final class space/kscience/kmath/operations/BigIntField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/RingWithNumbers {
+public final class space/kscience/kmath/operations/BigIntField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations {
 	public static final field INSTANCE Lspace/kscience/kmath/operations/BigIntField;
 	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun add (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
@@ -1490,8 +1234,6 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
 	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt;
@@ -1511,9 +1253,7 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt;
 	public fun minus (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt;
 	public fun multiply (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt;
@@ -1526,6 +1266,8 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Lspace/kscience/kmath/operations/BigInt;D)Lspace/kscience/kmath/operations/BigInt;
 	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
@@ -1565,8 +1307,6 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Byte;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun div (BLjava/lang/Number;)Ljava/lang/Byte;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun getOne ()Ljava/lang/Byte;
 	public synthetic fun getOne ()Ljava/lang/Object;
 	public fun getZero ()Ljava/lang/Byte;
@@ -1577,8 +1317,6 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma
 	public fun minus (BB)Ljava/lang/Byte;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun multiply (BB)Ljava/lang/Byte;
-	public fun multiply (BLjava/lang/Number;)Ljava/lang/Byte;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun norm (B)Ljava/lang/Byte;
 	public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1590,10 +1328,6 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public fun times (BB)Ljava/lang/Byte;
-	public fun times (BLjava/lang/Number;)Ljava/lang/Byte;
-	public fun times (Ljava/lang/Number;B)Ljava/lang/Byte;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryMinus (B)Ljava/lang/Byte;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1605,16 +1339,34 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma
 }
 
 public abstract interface class space/kscience/kmath/operations/ExponentialOperations : space/kscience/kmath/operations/Algebra {
+	public static final field ACOSH_OPERATION Ljava/lang/String;
+	public static final field ASINH_OPERATION Ljava/lang/String;
+	public static final field ATANH_OPERATION Ljava/lang/String;
+	public static final field COSH_OPERATION Ljava/lang/String;
 	public static final field Companion Lspace/kscience/kmath/operations/ExponentialOperations$Companion;
 	public static final field EXP_OPERATION Ljava/lang/String;
 	public static final field LN_OPERATION Ljava/lang/String;
+	public static final field SINH_OPERATION Ljava/lang/String;
+	public static final field TANH_OPERATION Ljava/lang/String;
+	public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun exp (Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun ln (Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
 }
 
 public final class space/kscience/kmath/operations/ExponentialOperations$Companion {
+	public static final field ACOSH_OPERATION Ljava/lang/String;
+	public static final field ASINH_OPERATION Ljava/lang/String;
+	public static final field ATANH_OPERATION Ljava/lang/String;
+	public static final field COSH_OPERATION Ljava/lang/String;
 	public static final field EXP_OPERATION Ljava/lang/String;
 	public static final field LN_OPERATION Ljava/lang/String;
+	public static final field SINH_OPERATION Ljava/lang/String;
+	public static final field TANH_OPERATION Ljava/lang/String;
 }
 
 public final class space/kscience/kmath/operations/ExponentialOperations$DefaultImpls {
@@ -1625,7 +1377,7 @@ public final class space/kscience/kmath/operations/ExponentialOperations$Default
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOperations, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra {
+public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOperations, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/ScaleOperations {
 	public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1643,12 +1395,12 @@ public final class space/kscience/kmath/operations/ExtendedField$DefaultImpls {
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Ljava/lang/Object;
 	public static fun cosh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun minus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun number (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun plus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun pow (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
@@ -1660,13 +1412,12 @@ public final class space/kscience/kmath/operations/ExtendedField$DefaultImpls {
 	public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public abstract interface class space/kscience/kmath/operations/ExtendedFieldOperations : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/HyperbolicOperations, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/TrigonometricOperations {
+public abstract interface class space/kscience/kmath/operations/ExtendedFieldOperations : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/TrigonometricOperations {
 	public abstract fun tan (Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
@@ -1676,7 +1427,6 @@ public final class space/kscience/kmath/operations/ExtendedFieldOperations$Defau
 	public static fun binaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun div (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun minus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun plus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
@@ -1684,32 +1434,32 @@ public final class space/kscience/kmath/operations/ExtendedFieldOperations$Defau
 	public static fun sqrt (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun tan (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun tanh (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public abstract interface class space/kscience/kmath/operations/Field : space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/Ring {
-	public abstract fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+public abstract interface class space/kscience/kmath/operations/Field : space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations {
+	public abstract fun number (Ljava/lang/Number;)Ljava/lang/Object;
 }
 
 public final class space/kscience/kmath/operations/Field$DefaultImpls {
 	public static fun binaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun minus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun number (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun plus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;)Ljava/lang/Object;
@@ -1731,14 +1481,10 @@ public final class space/kscience/kmath/operations/FieldOperations$DefaultImpls
 	public static fun binaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun div (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun minus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun plus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;)Ljava/lang/Object;
@@ -1771,8 +1517,6 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k
 	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (FF)Ljava/lang/Float;
 	public fun div (FLjava/lang/Number;)Ljava/lang/Float;
-	public fun div (Ljava/lang/Number;F)Ljava/lang/Float;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun divide (FF)Ljava/lang/Float;
@@ -1791,8 +1535,6 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k
 	public fun minus (FF)Ljava/lang/Float;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun multiply (FF)Ljava/lang/Float;
-	public fun multiply (FLjava/lang/Number;)Ljava/lang/Float;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun norm (F)Ljava/lang/Float;
 	public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1807,6 +1549,8 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k
 	public fun rightSideNumberOperation (Ljava/lang/String;FLjava/lang/Number;)Ljava/lang/Float;
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public fun scale (FD)Ljava/lang/Float;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
 	public fun sin (F)Ljava/lang/Float;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sinh (F)Ljava/lang/Float;
@@ -1832,37 +1576,48 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k
 	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public abstract interface class space/kscience/kmath/operations/HyperbolicOperations : space/kscience/kmath/operations/Algebra {
-	public static final field ACOSH_OPERATION Ljava/lang/String;
-	public static final field ASINH_OPERATION Ljava/lang/String;
-	public static final field ATANH_OPERATION Ljava/lang/String;
-	public static final field COSH_OPERATION Ljava/lang/String;
-	public static final field Companion Lspace/kscience/kmath/operations/HyperbolicOperations$Companion;
-	public static final field SINH_OPERATION Ljava/lang/String;
-	public static final field TANH_OPERATION Ljava/lang/String;
-	public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
+public abstract interface class space/kscience/kmath/operations/Group : space/kscience/kmath/operations/GroupOperations {
+	public abstract fun getZero ()Ljava/lang/Object;
 }
 
-public final class space/kscience/kmath/operations/HyperbolicOperations$Companion {
-	public static final field ACOSH_OPERATION Ljava/lang/String;
-	public static final field ASINH_OPERATION Ljava/lang/String;
-	public static final field ATANH_OPERATION Ljava/lang/String;
-	public static final field COSH_OPERATION Ljava/lang/String;
-	public static final field SINH_OPERATION Ljava/lang/String;
-	public static final field TANH_OPERATION Ljava/lang/String;
+public final class space/kscience/kmath/operations/Group$DefaultImpls {
+	public static fun binaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Ljava/lang/Object;
+	public static fun minus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun plus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun unaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public final class space/kscience/kmath/operations/HyperbolicOperations$DefaultImpls {
-	public static fun binaryOperation (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun unaryOperation (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+public abstract interface class space/kscience/kmath/operations/GroupOperations : space/kscience/kmath/operations/Algebra {
+	public static final field Companion Lspace/kscience/kmath/operations/GroupOperations$Companion;
+	public static final field MINUS_OPERATION Ljava/lang/String;
+	public static final field PLUS_OPERATION Ljava/lang/String;
+	public abstract fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public abstract fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public abstract fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
+}
+
+public final class space/kscience/kmath/operations/GroupOperations$Companion {
+	public static final field MINUS_OPERATION Ljava/lang/String;
+	public static final field PLUS_OPERATION Ljava/lang/String;
+}
+
+public final class space/kscience/kmath/operations/GroupOperations$DefaultImpls {
+	public static fun binaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Ljava/lang/Object;
+	public static fun minus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun plus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun unaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;)Ljava/lang/Object;
 }
 
 public final class space/kscience/kmath/operations/IntRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring {
@@ -1874,8 +1629,6 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Integer;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun div (ILjava/lang/Number;)Ljava/lang/Integer;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun getOne ()Ljava/lang/Integer;
 	public synthetic fun getOne ()Ljava/lang/Object;
 	public fun getZero ()Ljava/lang/Integer;
@@ -1886,8 +1639,6 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat
 	public fun minus (II)Ljava/lang/Integer;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun multiply (II)Ljava/lang/Integer;
-	public fun multiply (ILjava/lang/Number;)Ljava/lang/Integer;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun norm (I)Ljava/lang/Integer;
 	public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1899,10 +1650,6 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public fun times (II)Ljava/lang/Integer;
-	public fun times (ILjava/lang/Number;)Ljava/lang/Integer;
-	public fun times (Ljava/lang/Number;I)Ljava/lang/Integer;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryMinus (I)Ljava/lang/Integer;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
@@ -1923,7 +1670,7 @@ public final class space/kscience/kmath/operations/JBigDecimalField : space/ksci
 public final class space/kscience/kmath/operations/JBigDecimalField$Companion : space/kscience/kmath/operations/JBigDecimalFieldBase {
 }
 
-public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/PowerOperations {
+public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/ScaleOperations {
 	public fun <init> ()V
 	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun add (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
@@ -1932,8 +1679,6 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
 	public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigDecimal;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal;
@@ -1949,9 +1694,7 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa
 	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal;
 	public fun multiply (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number (Ljava/lang/Number;)Ljava/math/BigDecimal;
@@ -1964,6 +1707,8 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale (Ljava/math/BigDecimal;D)Ljava/math/BigDecimal;
 	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sqrt (Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
 	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
@@ -1981,7 +1726,7 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa
 	public fun unaryPlus (Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
 }
 
-public final class space/kscience/kmath/operations/JBigIntegerField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra {
+public final class space/kscience/kmath/operations/JBigIntegerField : space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring {
 	public static final field INSTANCE Lspace/kscience/kmath/operations/JBigIntegerField;
 	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun add (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
@@ -1990,14 +1735,6 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
 	public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigInteger;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Ljava/math/BigInteger;)Ljava/math/BigInteger;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger;
-	public fun div (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
-	public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun divide (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
 	public synthetic fun getOne ()Ljava/lang/Object;
 	public fun getOne ()Ljava/math/BigInteger;
 	public synthetic fun getZero ()Ljava/lang/Object;
@@ -2007,9 +1744,7 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci
 	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply (Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger;
 	public fun multiply (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number (Ljava/lang/Number;)Ljava/math/BigInteger;
@@ -2018,11 +1753,7 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Ljava/math/BigInteger;)Ljava/math/BigInteger;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger;
 	public fun times (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryMinus (Ljava/math/BigInteger;)Ljava/math/BigInteger;
@@ -2045,8 +1776,6 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Long;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun div (JLjava/lang/Number;)Ljava/lang/Long;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun getOne ()Ljava/lang/Long;
 	public synthetic fun getOne ()Ljava/lang/Object;
 	public fun getZero ()Ljava/lang/Long;
@@ -2057,8 +1786,6 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma
 	public fun minus (JJ)Ljava/lang/Long;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun multiply (JJ)Ljava/lang/Long;
-	public fun multiply (JLjava/lang/Number;)Ljava/lang/Long;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun norm (J)Ljava/lang/Long;
 	public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
@@ -2070,10 +1797,6 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public fun times (JJ)Ljava/lang/Long;
-	public fun times (JLjava/lang/Number;)Ljava/lang/Long;
-	public fun times (Ljava/lang/Number;J)Ljava/lang/Long;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryMinus (J)Ljava/lang/Long;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
@@ -2088,6 +1811,25 @@ public abstract interface class space/kscience/kmath/operations/Norm {
 	public abstract fun norm (Ljava/lang/Object;)Ljava/lang/Object;
 }
 
+public final class space/kscience/kmath/operations/NumbersAddOperations$DefaultImpls {
+	public static fun binaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Ljava/lang/Object;
+	public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun unaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;)Ljava/lang/Object;
+}
+
 public abstract interface class space/kscience/kmath/operations/NumericAlgebra : space/kscience/kmath/operations/Algebra {
 	public abstract fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public abstract fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
@@ -2135,7 +1877,7 @@ public final class space/kscience/kmath/operations/PowerOperations$DefaultImpls
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public final class space/kscience/kmath/operations/RealField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm {
+public final class space/kscience/kmath/operations/RealField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations {
 	public static final field INSTANCE Lspace/kscience/kmath/operations/RealField;
 	public fun acos (D)Ljava/lang/Double;
 	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
@@ -2162,8 +1904,6 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km
 	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (DD)Ljava/lang/Double;
 	public fun div (DLjava/lang/Number;)Ljava/lang/Double;
-	public fun div (Ljava/lang/Number;D)Ljava/lang/Double;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun divide (DD)Ljava/lang/Double;
@@ -2182,8 +1922,6 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km
 	public fun minus (DD)Ljava/lang/Double;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun multiply (DD)Ljava/lang/Double;
-	public fun multiply (DLjava/lang/Number;)Ljava/lang/Double;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun norm (D)Ljava/lang/Double;
 	public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
@@ -2198,6 +1936,8 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km
 	public fun rightSideNumberOperation (Ljava/lang/String;DLjava/lang/Number;)Ljava/lang/Double;
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public fun scale (DD)Ljava/lang/Double;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
 	public fun sin (D)Ljava/lang/Double;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sinh (D)Ljava/lang/Double;
@@ -2223,7 +1963,7 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km
 	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public abstract interface class space/kscience/kmath/operations/Ring : space/kscience/kmath/operations/RingOperations, space/kscience/kmath/operations/Space {
+public abstract interface class space/kscience/kmath/operations/Ring : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/RingOperations {
 	public abstract fun getOne ()Ljava/lang/Object;
 }
 
@@ -2231,19 +1971,15 @@ public final class space/kscience/kmath/operations/Ring$DefaultImpls {
 	public static fun binaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun minus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun plus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public abstract interface class space/kscience/kmath/operations/RingOperations : space/kscience/kmath/operations/SpaceOperations {
+public abstract interface class space/kscience/kmath/operations/RingOperations : space/kscience/kmath/operations/GroupOperations {
 	public static final field Companion Lspace/kscience/kmath/operations/RingOperations$Companion;
 	public static final field TIMES_OPERATION Ljava/lang/String;
 	public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
@@ -2259,41 +1995,30 @@ public final class space/kscience/kmath/operations/RingOperations$DefaultImpls {
 	public static fun binaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public static fun bindSymbol (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun minus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun plus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 	public static fun unaryPlus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;)Ljava/lang/Object;
 }
 
-public final class space/kscience/kmath/operations/RingWithNumbers$DefaultImpls {
-	public static fun binaryOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun minus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun minus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun minus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun number (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun plus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun plus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun plus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun times (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;)Ljava/lang/Object;
+public abstract interface class space/kscience/kmath/operations/ScaleOperations : space/kscience/kmath/operations/Algebra {
+	public abstract fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public abstract fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public abstract fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public abstract fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+}
+
+public final class space/kscience/kmath/operations/ScaleOperations$DefaultImpls {
+	public static fun binaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Ljava/lang/Object;
+	public static fun div (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public static fun unaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
 public final class space/kscience/kmath/operations/ShortRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring {
@@ -2305,8 +2030,6 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km
 	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
 	public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Short;
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun div (SLjava/lang/Number;)Ljava/lang/Short;
 	public synthetic fun getOne ()Ljava/lang/Object;
 	public fun getOne ()Ljava/lang/Short;
 	public synthetic fun getZero ()Ljava/lang/Object;
@@ -2316,9 +2039,7 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km
 	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (SS)Ljava/lang/Short;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply (SLjava/lang/Number;)Ljava/lang/Short;
 	public fun multiply (SS)Ljava/lang/Short;
 	public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun norm (S)Ljava/lang/Short;
@@ -2329,11 +2050,7 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;SLjava/lang/Number;)Ljava/lang/Short;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;S)Ljava/lang/Short;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (SLjava/lang/Number;)Ljava/lang/Short;
 	public fun times (SS)Ljava/lang/Short;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryMinus (S)Ljava/lang/Short;
@@ -2344,62 +2061,6 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km
 	public fun unaryPlus (S)Ljava/lang/Short;
 }
 
-public abstract interface class space/kscience/kmath/operations/Space : space/kscience/kmath/operations/SpaceOperations {
-	public abstract fun getZero ()Ljava/lang/Object;
-}
-
-public final class space/kscience/kmath/operations/Space$DefaultImpls {
-	public static fun binaryOperation (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun minus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun plus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/Space;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperation (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;)Ljava/lang/Object;
-}
-
-public abstract interface class space/kscience/kmath/operations/SpaceOperations : space/kscience/kmath/operations/Algebra {
-	public static final field Companion Lspace/kscience/kmath/operations/SpaceOperations$Companion;
-	public static final field MINUS_OPERATION Ljava/lang/String;
-	public static final field PLUS_OPERATION Ljava/lang/String;
-	public abstract fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public abstract fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public abstract fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public abstract fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public abstract fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-}
-
-public final class space/kscience/kmath/operations/SpaceOperations$Companion {
-	public static final field MINUS_OPERATION Ljava/lang/String;
-	public static final field PLUS_OPERATION Ljava/lang/String;
-}
-
-public final class space/kscience/kmath/operations/SpaceOperations$DefaultImpls {
-	public static fun binaryOperation (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public static fun bindSymbol (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Ljava/lang/Object;
-	public static fun div (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun minus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun plus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun times (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public static fun unaryMinus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperation (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public static fun unaryPlus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;)Ljava/lang/Object;
-}
-
 public abstract interface class space/kscience/kmath/operations/TrigonometricOperations : space/kscience/kmath/operations/Algebra {
 	public static final field ACOS_OPERATION Ljava/lang/String;
 	public static final field ASIN_OPERATION Ljava/lang/String;
@@ -2470,6 +2131,7 @@ public final class space/kscience/kmath/structures/BufferKt {
 	public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence;
 	public static final fun getIndices (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/ranges/IntRange;
 	public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List;
+	public static final fun toMutableList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List;
 }
 
 public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer {
@@ -2532,7 +2194,7 @@ public final class space/kscience/kmath/structures/FloatBufferKt {
 	public static final fun FloatBuffer (ILkotlin/jvm/functions/Function1;)[F
 	public static final fun FloatBuffer ([F)[F
 	public static final fun asBuffer ([F)[F
-	public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[F
+	public static final fun toFloatArray (Lspace/kscience/kmath/structures/Buffer;)[F
 }
 
 public final class space/kscience/kmath/structures/IntBuffer : space/kscience/kmath/structures/MutableBuffer {
@@ -2568,7 +2230,7 @@ public final class space/kscience/kmath/structures/IntBufferKt {
 	public static final fun IntBuffer (ILkotlin/jvm/functions/Function1;)[I
 	public static final fun IntBuffer ([I)[I
 	public static final fun asBuffer ([I)[I
-	public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[I
+	public static final fun toIntArray (Lspace/kscience/kmath/structures/Buffer;)[I
 }
 
 public final class space/kscience/kmath/structures/ListBuffer : space/kscience/kmath/structures/Buffer {
@@ -2626,7 +2288,7 @@ public final class space/kscience/kmath/structures/LongBufferKt {
 	public static final fun LongBuffer (ILkotlin/jvm/functions/Function1;)[J
 	public static final fun LongBuffer ([J)[J
 	public static final fun asBuffer ([J)[J
-	public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[J
+	public static final fun toLongArray (Lspace/kscience/kmath/structures/Buffer;)[J
 }
 
 public class space/kscience/kmath/structures/MemoryBuffer : space/kscience/kmath/structures/Buffer {
@@ -2776,8 +2438,6 @@ public final class space/kscience/kmath/structures/RealBufferField : space/kscie
 	public fun cos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun cosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
@@ -2798,9 +2458,7 @@ public final class space/kscience/kmath/structures/RealBufferField : space/kscie
 	public fun ln-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D
 	public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
@@ -2813,6 +2471,8 @@ public final class space/kscience/kmath/structures/RealBufferField : space/kscie
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;D)[D
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
@@ -2863,9 +2523,7 @@ public final class space/kscience/kmath/structures/RealBufferFieldOperations : s
 	public fun cos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun cosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
 	public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
 	public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun divide-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
@@ -2875,9 +2533,7 @@ public final class space/kscience/kmath/structures/RealBufferFieldOperations : s
 	public fun ln-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D
 	public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
@@ -2895,14 +2551,10 @@ public final class space/kscience/kmath/structures/RealBufferFieldOperations : s
 	public fun tan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun tanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
 	public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public fun unaryMinus-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
 	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
 	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
 	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
@@ -2915,7 +2567,7 @@ public final class space/kscience/kmath/structures/RealBufferKt {
 	public static final fun RealBuffer ([D)[D
 	public static final fun asBuffer ([D)[D
 	public static final fun contentEquals-2uVC2J0 ([D[D)Z
-	public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[D
+	public static final fun toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D
 }
 
 public final class space/kscience/kmath/structures/ShortBuffer : space/kscience/kmath/structures/MutableBuffer {
@@ -2951,7 +2603,7 @@ public final class space/kscience/kmath/structures/ShortBufferKt {
 	public static final fun ShortBuffer (ILkotlin/jvm/functions/Function1;)[S
 	public static final fun ShortBuffer ([S)[S
 	public static final fun asBuffer ([S)[S
-	public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[S
+	public static final fun toShortArray (Lspace/kscience/kmath/structures/Buffer;)[S
 }
 
 public final class space/kscience/kmath/structures/ValueFlag : java/lang/Enum {
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt
index 3d0c6d3b8..c948f8672 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt
@@ -16,8 +16,8 @@
 package space.kscience.kmath.domains
 
 import space.kscience.kmath.linear.Point
+import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.RealBuffer
 import space.kscience.kmath.structures.indices
 
 /**
@@ -26,6 +26,7 @@ import space.kscience.kmath.structures.indices
  *
  * @author Alexander Nozik
  */
+@UnstableKMathAPI
 public class HyperSquareDomain(private val lower: Buffer<Double>, private val upper: Buffer<Double>) : RealDomain {
     public override val dimension: Int get() = lower.size
 
@@ -33,26 +34,10 @@ public class HyperSquareDomain(private val lower: Buffer<Double>, private val up
         point[i] in lower[i]..upper[i]
     }
 
-    public override fun getLowerBound(num: Int, point: Point<Double>): Double = lower[num]
-
     public override fun getLowerBound(num: Int): Double = lower[num]
 
-    public override fun getUpperBound(num: Int, point: Point<Double>): Double = upper[num]
-
     public override fun getUpperBound(num: Int): Double = upper[num]
 
-    public override fun nearestInDomain(point: Point<Double>): Point<Double> {
-        val res = DoubleArray(point.size) { i ->
-            when {
-                point[i] < lower[i] -> lower[i]
-                point[i] > upper[i] -> upper[i]
-                else -> point[i]
-            }
-        }
-
-        return RealBuffer(*res)
-    }
-
     public override fun volume(): Double {
         var res = 1.0
 
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt
index 13555dad9..c20cbfec1 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt
@@ -15,45 +15,27 @@
  */
 package space.kscience.kmath.domains
 
-import space.kscience.kmath.linear.Point
+import space.kscience.kmath.misc.UnstableKMathAPI
 
 /**
  * n-dimensional volume
  *
  * @author Alexander Nozik
  */
+@UnstableKMathAPI
 public interface RealDomain : Domain<Double> {
-    public fun nearestInDomain(point: Point<Double>): Point<Double>
-
-    /**
-     * The lower edge for the domain going down from point
-     * @param num
-     * @param point
-     * @return
-     */
-    public fun getLowerBound(num: Int, point: Point<Double>): Double?
-
-    /**
-     * The upper edge of the domain going up from point
-     * @param num
-     * @param point
-     * @return
-     */
-    public fun getUpperBound(num: Int, point: Point<Double>): Double?
 
     /**
      * Global lower edge
-     * @param num
-     * @return
+     * @param num axis number
      */
-    public fun getLowerBound(num: Int): Double?
+    public fun getLowerBound(num: Int): Double
 
     /**
      * Global upper edge
-     * @param num
-     * @return
+     * @param num axis number
      */
-    public fun getUpperBound(num: Int): Double?
+    public fun getUpperBound(num: Int): Double
 
     /**
      * Hyper volume
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt
index f1bcc50ad..002caac50 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt
@@ -16,19 +16,15 @@
 package space.kscience.kmath.domains
 
 import space.kscience.kmath.linear.Point
+import space.kscience.kmath.misc.UnstableKMathAPI
 
+@UnstableKMathAPI
 public class UnconstrainedDomain(public override val dimension: Int) : RealDomain {
     public override operator fun contains(point: Point<Double>): Boolean = true
 
-    public override fun getLowerBound(num: Int, point: Point<Double>): Double? = Double.NEGATIVE_INFINITY
+    public override fun getLowerBound(num: Int): Double = Double.NEGATIVE_INFINITY
 
-    public override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY
-
-    public override fun getUpperBound(num: Int, point: Point<Double>): Double? = Double.POSITIVE_INFINITY
-
-    public override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY
-
-    public override fun nearestInDomain(point: Point<Double>): Point<Double> = point
+    public override fun getUpperBound(num: Int): Double = Double.POSITIVE_INFINITY
 
     public override fun volume(): Double = Double.POSITIVE_INFINITY
 }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt
index 36cd4afa7..d20349960 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt
@@ -1,11 +1,11 @@
 package space.kscience.kmath.domains
 
 import space.kscience.kmath.linear.Point
-import space.kscience.kmath.structures.asBuffer
+import space.kscience.kmath.misc.UnstableKMathAPI
 
+@UnstableKMathAPI
 public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<Double>) : RealDomain {
-    public override val dimension: Int
-        get() = 1
+    public override val dimension: Int get() = 1
 
     public operator fun contains(d: Double): Boolean = range.contains(d)
 
@@ -14,33 +14,12 @@ public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<
         return contains(point[0])
     }
 
-    public override fun nearestInDomain(point: Point<Double>): Point<Double> {
-        require(point.size == 1)
-        val value = point[0]
-
-        return when {
-            value in range -> point
-            value >= range.endInclusive -> doubleArrayOf(range.endInclusive).asBuffer()
-            else -> doubleArrayOf(range.start).asBuffer()
-        }
-    }
-
-    public override fun getLowerBound(num: Int, point: Point<Double>): Double? {
+    public override fun getLowerBound(num: Int): Double {
         require(num == 0)
         return range.start
     }
 
-    public override fun getUpperBound(num: Int, point: Point<Double>): Double? {
-        require(num == 0)
-        return range.endInclusive
-    }
-
-    public override fun getLowerBound(num: Int): Double? {
-        require(num == 0)
-        return range.start
-    }
-
-    public override fun getUpperBound(num: Int): Double? {
+    public override fun getUpperBound(num: Int): Double {
         require(num == 0)
         return range.endInclusive
     }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt
index 5177bc868..880f13a3e 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt
@@ -41,25 +41,28 @@ public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(
 }
 
 /**
- * A context class for [Expression] construction for [Space] algebras.
+ * A context class for [Expression] construction for [Group] algebras.
  */
-public open class FunctionalExpressionSpace<T, A : Space<T>>(
+public open class FunctionalExpressionGroup<T, A : Group<T>>(
     algebra: A,
-) : FunctionalExpressionAlgebra<T, A>(algebra), Space<Expression<T>> {
+) : FunctionalExpressionAlgebra<T, A>(algebra), Group<Expression<T>> {
     public override val zero: Expression<T> get() = const(algebra.zero)
 
+    override fun Expression<T>.unaryMinus(): Expression<T> =
+        unaryOperation(GroupOperations.MINUS_OPERATION, this)
+
     /**
      * Builds an Expression of addition of two another expressions.
      */
     public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
-        binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
+        binaryOperation(GroupOperations.PLUS_OPERATION, a, b)
 
-    /**
-     * Builds an Expression of multiplication of expression by number.
-     */
-    public override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments ->
-        algebra.multiply(a.invoke(arguments), k)
-    }
+//    /**
+//     * Builds an Expression of multiplication of expression by number.
+//     */
+//    public override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments ->
+//        algebra.multiply(a.invoke(arguments), k)
+//    }
 
     public operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
     public operator fun Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
@@ -71,13 +74,13 @@ public open class FunctionalExpressionSpace<T, A : Space<T>>(
 
     public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
         super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
+
 }
 
 public open class FunctionalExpressionRing<T, A : Ring<T>>(
     algebra: A,
-) : FunctionalExpressionSpace<T, A>(algebra), Ring<Expression<T>> {
-    public override val one: Expression<T>
-        get() = const(algebra.one)
+) : FunctionalExpressionGroup<T, A>(algebra), Ring<Expression<T>> {
+    public override val one: Expression<T> get() = const(algebra.one)
 
     /**
      * Builds an Expression of multiplication of two expressions.
@@ -89,15 +92,16 @@ public open class FunctionalExpressionRing<T, A : Ring<T>>(
     public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
 
     public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
-        super<FunctionalExpressionSpace>.unaryOperationFunction(operation)
+        super<FunctionalExpressionGroup>.unaryOperationFunction(operation)
 
     public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
-        super<FunctionalExpressionSpace>.binaryOperationFunction(operation)
+        super<FunctionalExpressionGroup>.binaryOperationFunction(operation)
 }
 
-public open class FunctionalExpressionField<T, A : Field<T>>(
+public open class FunctionalExpressionField<T, A:  Field<T>>(
     algebra: A,
-) : FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>> {
+) : FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>>,
+    ScaleOperations<Expression<T>> {
     /**
      * Builds an Expression of division an expression by another one.
      */
@@ -112,6 +116,10 @@ public open class FunctionalExpressionField<T, A : Field<T>>(
 
     public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
         super<FunctionalExpressionRing>.binaryOperationFunction(operation)
+
+    override fun scale(a: Expression<T>, value: Double): Expression<T> = algebra {
+        Expression { args -> a(args) * value }
+    }
 }
 
 public open class FunctionalExpressionExtendedField<T, A : ExtendedField<T>>(
@@ -151,8 +159,8 @@ public open class FunctionalExpressionExtendedField<T, A : ExtendedField<T>>(
         super<FunctionalExpressionField>.binaryOperationFunction(operation)
 }
 
-public inline fun <T, A : Space<T>> A.expressionInSpace(block: FunctionalExpressionSpace<T, A>.() -> Expression<T>): Expression<T> =
-    FunctionalExpressionSpace(this).block()
+public inline fun <T, A : Group<T>> A.expressionInSpace(block: FunctionalExpressionGroup<T, A>.() -> Expression<T>): Expression<T> =
+    FunctionalExpressionGroup(this).block()
 
 public inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressionRing<T, A>.() -> Expression<T>): Expression<T> =
     FunctionalExpressionRing(this).block()
@@ -160,5 +168,6 @@ public inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressio
 public inline fun <T, A : Field<T>> A.expressionInField(block: FunctionalExpressionField<T, A>.() -> Expression<T>): Expression<T> =
     FunctionalExpressionField(this).block()
 
-public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>): Expression<T> =
-    FunctionalExpressionExtendedField(this).block()
+public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(
+    block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>,
+): Expression<T> = FunctionalExpressionExtendedField(this).block()
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt
index c710ba679..4b5b3311e 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt
@@ -47,36 +47,6 @@ public fun <T : Any> DerivationResult<T>.grad(vararg variables: Symbol): Point<T
     return variables.map(::derivative).asBuffer()
 }
 
-/**
- * Runs differentiation and establishes [SimpleAutoDiffField] context inside the block of code.
- *
- * The partial derivatives are placed in argument `d` variable
- *
- * Example:
- * ```
- * val x by symbol // define variable(s) and their values
- * val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context
- * assertEquals(17.0, y.x) // the value of result (y)
- * assertEquals(9.0, x.d)  // dy/dx
- * ```
- *
- * @param body the action in [SimpleAutoDiffField] context returning [AutoDiffVariable] to differentiate with respect to.
- * @return the result of differentiation.
- */
-public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
-    bindings: Map<Symbol, T>,
-    body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
-): DerivationResult<T> {
-    contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) }
-
-    return SimpleAutoDiffField(this, bindings).differentiate(body)
-}
-
-public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
-    vararg bindings: Pair<Symbol, T>,
-    body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
-): DerivationResult<T> = simpleAutoDiff(bindings.toMap(), body)
-
 /**
  * Represents field in context of which functions can be derived.
  */
@@ -84,12 +54,9 @@ public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
 public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
     public val context: F,
     bindings: Map<Symbol, T>,
-) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, RingWithNumbers<AutoDiffValue<T>> {
-    public override val zero: AutoDiffValue<T>
-        get() = const(context.zero)
-
-    public override val one: AutoDiffValue<T>
-        get() = const(context.one)
+) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOperations<AutoDiffValue<T>> {
+    public override val zero: AutoDiffValue<T> get() = const(context.zero)
+    public override val one: AutoDiffValue<T> get() = const(context.one)
 
     // this stack contains pairs of blocks and values to apply them to
     private var stack: Array<Any?> = arrayOfNulls<Any?>(8)
@@ -137,6 +104,8 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
 
     override fun const(value: T): AutoDiffValue<T> = AutoDiffValue(value)
 
+    override fun number(value: Number): AutoDiffValue<T> = const { one * value }
+
     /**
      * A variable accessing inner state of derivatives.
      * Use this value in inner builders to avoid creating additional derivative bindings.
@@ -175,21 +144,24 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
         return DerivationResult(result.value, bindings.mapValues { it.value.d }, context)
     }
 
-    // Overloads for Double constants
+//    // Overloads for Double constants
+//
+//    public override operator fun Number.plus(b: AutoDiffValue<T>): AutoDiffValue<T> =
+//        derive(const { this@plus.toDouble() * one + b.value }) { z ->
+//            b.d += z.d
+//        }
+//
+//    public override operator fun AutoDiffValue<T>.plus(b: Number): AutoDiffValue<T> = b.plus(this)
+//
+//    public override operator fun Number.minus(b: AutoDiffValue<T>): AutoDiffValue<T> =
+//        derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d }
+//
+//    public override operator fun AutoDiffValue<T>.minus(b: Number): AutoDiffValue<T> =
+//        derive(const { this@minus.value - one * b.toDouble() }) { z -> d += z.d }
 
-    public override operator fun Number.plus(b: AutoDiffValue<T>): AutoDiffValue<T> =
-        derive(const { this@plus.toDouble() * one + b.value }) { z ->
-            b.d += z.d
-        }
-
-    public override operator fun AutoDiffValue<T>.plus(b: Number): AutoDiffValue<T> = b.plus(this)
-
-    public override operator fun Number.minus(b: AutoDiffValue<T>): AutoDiffValue<T> =
-        derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d }
-
-    public override operator fun AutoDiffValue<T>.minus(b: Number): AutoDiffValue<T> =
-        derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d }
 
+    override fun AutoDiffValue<T>.unaryMinus(): AutoDiffValue<T> =
+        derive(const { -value }) { z -> d -= z.d }
 
     // Basic math (+, -, *, /)
 
@@ -211,12 +183,44 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
             b.d -= z.d * a.value / (b.value * b.value)
         }
 
-    public override fun multiply(a: AutoDiffValue<T>, k: Number): AutoDiffValue<T> =
-        derive(const { k.toDouble() * a.value }) { z ->
-            a.d += z.d * k.toDouble()
+    public override fun scale(a: AutoDiffValue<T>, value: Double): AutoDiffValue<T> =
+        derive(const { value * a.value }) { z ->
+            a.d += z.d * value
         }
 }
 
+
+/**
+ * Runs differentiation and establishes [SimpleAutoDiffField] context inside the block of code.
+ *
+ * The partial derivatives are placed in argument `d` variable
+ *
+ * Example:
+ * ```
+ * val x by symbol // define variable(s) and their values
+ * val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context
+ * assertEquals(17.0, y.x) // the value of result (y)
+ * assertEquals(9.0, x.d)  // dy/dx
+ * ```
+ *
+ * @param body the action in [SimpleAutoDiffField] context returning [AutoDiffVariable] to differentiate with respect to.
+ * @return the result of differentiation.
+ */
+public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
+    bindings: Map<Symbol, T>,
+    body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
+): DerivationResult<T> {
+    contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) }
+
+    return SimpleAutoDiffField(this, bindings).differentiate(body)
+}
+
+public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
+    vararg bindings: Pair<Symbol, T>,
+    body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
+): DerivationResult<T> = simpleAutoDiff(bindings.toMap(), body)
+
+
 /**
  * A constructs that creates a derivative structure with required order on-demand
  */
@@ -247,19 +251,20 @@ public fun <T : Any, F : Field<T>> simpleAutoDiff(field: F): AutoDiffProcessor<T
 // Extensions for differentiation of various basic mathematical functions
 
 // x ^ 2
-public fun <T : Any, F : Field<T>> SimpleAutoDiffField<T, F>.sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
-    derive(const { x.value * x.value }) { z -> x.d += z.d * 2 * x.value }
+public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
+    derive(const { x.value * x.value }) { z -> x.d += z.d * 2.0 * x.value }
 
 // x ^ 1/2
 public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.sqrt(x: AutoDiffValue<T>): AutoDiffValue<T> =
-    derive(const { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value }
+    derive(const { sqrt(x.value) }) { z -> x.d += z.d / 2.0 / z.value }
 
 // x ^ y (const)
 public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow(
     x: AutoDiffValue<T>,
     y: Double,
-): AutoDiffValue<T> =
-    derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) }
+): AutoDiffValue<T> = derive(const { power(x.value, y) }) { z ->
+    x.d += z.d * y * power(x.value, y - 1)
+}
 
 public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow(
     x: AutoDiffValue<T>,
@@ -328,7 +333,13 @@ public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.atanh(x: Au
 public class SimpleAutoDiffExtendedField<T : Any, F : ExtendedField<T>>(
     context: F,
     bindings: Map<Symbol, T>,
-) : ExtendedField<AutoDiffValue<T>>, SimpleAutoDiffField<T, F>(context, bindings) {
+) : ExtendedField<AutoDiffValue<T>>, ScaleOperations<AutoDiffValue<T>>,
+    SimpleAutoDiffField<T, F>(context, bindings) {
+
+    override fun number(value: Number): AutoDiffValue<T> = const { number(value) }
+
+    override fun scale(a: AutoDiffValue<T>, value: Double): AutoDiffValue<T> = a * number(value)
+
     // x ^ 2
     public fun sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
         (this as SimpleAutoDiffField<T, F>).sqr(x)
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt
index 0ef6803d6..fbf080032 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt
@@ -2,18 +2,18 @@ package space.kscience.kmath.expressions
 
 import space.kscience.kmath.operations.ExtendedField
 import space.kscience.kmath.operations.Field
+import space.kscience.kmath.operations.Group
 import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.operations.Space
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 
 
 /**
- * Creates a functional expression with this [Space].
+ * Creates a functional expression with this [Group].
  */
-public inline fun <T> Space<T>.spaceExpression(block: FunctionalExpressionSpace<T, Space<T>>.() -> Expression<T>): Expression<T> {
+public inline fun <T> Group<T>.spaceExpression(block: FunctionalExpressionGroup<T, Group<T>>.() -> Expression<T>): Expression<T> {
     contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
-    return FunctionalExpressionSpace(this).block()
+    return FunctionalExpressionGroup(this).block()
 }
 
 /**
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt
new file mode 100644
index 000000000..b6c2ea17b
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt
@@ -0,0 +1,83 @@
+package space.kscience.kmath.linear
+
+import space.kscience.kmath.nd.*
+import space.kscience.kmath.operations.Ring
+import space.kscience.kmath.operations.invoke
+import space.kscience.kmath.structures.Buffer
+import space.kscience.kmath.structures.BufferFactory
+import space.kscience.kmath.structures.VirtualBuffer
+import space.kscience.kmath.structures.indices
+
+
+public class BufferLinearSpace<T : Any, A : Ring<T>>(
+    override val elementAlgebra: A,
+    private val bufferFactory: BufferFactory<T>,
+) : LinearSpace<T, A> {
+
+    private fun ndRing(
+        rows: Int,
+        cols: Int,
+    ): BufferedNDRing<T, A> = NDAlgebra.ring(elementAlgebra, bufferFactory, rows, cols)
+
+    override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix<T> =
+        ndRing(rows, columns).produce { (i, j) -> elementAlgebra.initializer(i, j) }.as2D()
+
+    override fun buildVector(size: Int, initializer: A.(Int) -> T): Point<T> =
+        bufferFactory(size) { elementAlgebra.initializer(it) }
+
+    override fun Matrix<T>.unaryMinus(): Matrix<T> = ndRing(rowNum, colNum).run {
+        unwrap().map { -it }.as2D()
+    }
+
+    override fun Matrix<T>.plus(other: Matrix<T>): Matrix<T> = ndRing(rowNum, colNum).run {
+        require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::plus. Expected $shape but found ${other.shape}" }
+        unwrap().plus(other.unwrap()).as2D()
+    }
+
+    override fun Matrix<T>.minus(other: Matrix<T>): Matrix<T> = ndRing(rowNum, colNum).run {
+        require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::minus. Expected $shape but found ${other.shape}" }
+        unwrap().minus(other.unwrap()).as2D()
+    }
+
+    private fun Buffer<T>.linearize() = if (this is VirtualBuffer) {
+        buildVector(size) { get(it) }
+    } else {
+        this
+    }
+
+    override fun Matrix<T>.dot(other: Matrix<T>): Matrix<T> {
+        require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
+        return elementAlgebra {
+            val rows = this@dot.rows.map{it.linearize()}
+            val columns = other.columns.map { it.linearize() }
+            buildMatrix(rowNum, other.colNum) { i, j ->
+                val r = rows[i]
+                val c = columns[j]
+                var res = zero
+                for (l in r.indices) {
+                    res += r[l] * c[l]
+                }
+                res
+            }
+        }
+    }
+
+    override fun Matrix<T>.dot(vector: Point<T>): Point<T> {
+        require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
+        return elementAlgebra {
+            val rows = this@dot.rows.map { it.linearize() }
+            buildVector(rowNum) { i ->
+                val r = rows[i]
+                var res = zero
+                for (j in r.indices) {
+                    res += r[j] * vector[j]
+                }
+                res
+            }
+        }
+    }
+
+    override fun Matrix<T>.times(value: T): Matrix<T> = ndRing(rowNum, colNum).run {
+        unwrap().map { it * value }.as2D()
+    }
+}
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt
deleted file mode 100644
index f8f7f5a05..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package space.kscience.kmath.linear
-
-import space.kscience.kmath.nd.NDStructure
-import space.kscience.kmath.nd.Structure2D
-import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.operations.invoke
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.BufferFactory
-import space.kscience.kmath.structures.asSequence
-
-/**
- * Alias for [Structure2D] with more familiar name.
- *
- * @param T the type of items.
- */
-public typealias Matrix<T> = Structure2D<T>
-
-/**
- * Basic implementation of Matrix space based on [NDStructure]
- */
-public class BufferMatrixContext<T : Any, R : Ring<T>>(
-    public override val elementContext: R,
-    private val bufferFactory: BufferFactory<T>,
-) : GenericMatrixContext<T, R, BufferMatrix<T>> {
-    public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix<T> {
-        val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
-        return BufferMatrix(rows, columns, buffer)
-    }
-
-    public override fun point(size: Int, initializer: (Int) -> T): Point<T> = bufferFactory(size, initializer)
-
-    private fun Matrix<T>.toBufferMatrix(): BufferMatrix<T> = if (this is BufferMatrix) this else {
-        produce(rowNum, colNum) { i, j -> get(i, j) }
-    }
-
-    public fun one(rows: Int, columns: Int): Matrix<Double> = VirtualMatrix(rows, columns) { i, j ->
-        if (i == j) 1.0 else 0.0
-    } + DiagonalFeature
-
-    public override infix fun Matrix<T>.dot(other: Matrix<T>): BufferMatrix<T> {
-        require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
-        val bufferMatrix = toBufferMatrix()
-        val otherBufferMatrix = other.toBufferMatrix()
-        return elementContext {
-            produce(rowNum, other.colNum) { i, j ->
-                var res = one
-                for (l in 0 until colNum) {
-                    res += bufferMatrix[i, l] * otherBufferMatrix[l, j]
-                }
-                res
-            }
-        }
-    }
-
-    public override infix fun Matrix<T>.dot(vector: Point<T>): Point<T> {
-        require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
-        val bufferMatrix = toBufferMatrix()
-        return elementContext {
-            bufferFactory(rowNum) { i ->
-                var res = one
-                for (j in 0 until colNum) {
-                    res += bufferMatrix[i, j] * vector[j]
-                }
-                res
-            }
-        }
-    }
-
-    override fun add(a: Matrix<T>, b: Matrix<T>): BufferMatrix<T> {
-        require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" }
-        require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" }
-        val aBufferMatrix = a.toBufferMatrix()
-        val bBufferMatrix = b.toBufferMatrix()
-        return elementContext {
-            produce(a.rowNum, a.colNum) { i, j ->
-                aBufferMatrix[i, j] + bBufferMatrix[i, j]
-            }
-        }
-    }
-
-    override fun multiply(a: Matrix<T>, k: Number): BufferMatrix<T> {
-        val aBufferMatrix = a.toBufferMatrix()
-        return elementContext {
-            produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
-        }
-    }
-
-    public companion object
-}
-
-public class BufferMatrix<T : Any>(
-    public override val rowNum: Int,
-    public override val colNum: Int,
-    public val buffer: Buffer<T>,
-) : Matrix<T> {
-
-    init {
-        require(buffer.size == rowNum * colNum) { "Dimension mismatch for matrix structure" }
-    }
-
-    override val shape: IntArray get() = intArrayOf(rowNum, colNum)
-
-    public override operator fun get(index: IntArray): T = get(index[0], index[1])
-    public override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j]
-
-    public override fun elements(): Sequence<Pair<IntArray, T>> = sequence {
-        for (i in 0 until rowNum) for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j))
-    }
-
-    public override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-
-        return when (other) {
-            is NDStructure<*> -> NDStructure.contentEquals(this, other)
-            else -> false
-        }
-    }
-
-    override fun hashCode(): Int {
-        var result = rowNum
-        result = 31 * result + colNum
-        result = 31 * result + buffer.hashCode()
-        return result
-    }
-
-    public override fun toString(): String {
-        return if (rowNum <= 5 && colNum <= 5)
-            "Matrix(rowsNum = $rowNum, colNum = $colNum)\n" +
-                    rows.asSequence().joinToString(prefix = "(", postfix = ")", separator = "\n ") { buffer ->
-                        buffer.asSequence().joinToString(separator = "\t") { it.toString() }
-                    }
-        else "Matrix(rowsNum = $rowNum, colNum = $colNum)"
-    }
-
-
-}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt
similarity index 70%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt
index ea871ccba..6cce5a446 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt
@@ -1,25 +1,22 @@
 package space.kscience.kmath.linear
 
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.VirtualBuffer
-
-public typealias Point<T> = Buffer<T>
+import space.kscience.kmath.nd.as1D
 
 /**
  * A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors
  */
 public interface LinearSolver<T : Any> {
     public fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T>
-    public fun solve(a: Matrix<T>, b: Point<T>): Point<T> = solve(a, b.asMatrix()).asPoint()
+    public fun solve(a: Matrix<T>, b: Point<T>): Point<T> = solve(a, b.asMatrix()).asVector()
     public fun inverse(a: Matrix<T>): Matrix<T>
 }
 
 /**
  * Convert matrix to vector if it is possible
  */
-public fun <T : Any> Matrix<T>.asPoint(): Point<T> =
+public fun <T : Any> Matrix<T>.asVector(): Point<T> =
     if (this.colNum == 1)
-        VirtualBuffer(rowNum) { get(it, 0) }
+        as1D()
     else
         error("Can't convert matrix with more than one column to vector")
 
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt
new file mode 100644
index 000000000..1642bfb14
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt
@@ -0,0 +1,204 @@
+package space.kscience.kmath.linear
+
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.*
+import space.kscience.kmath.operations.*
+import space.kscience.kmath.structures.Buffer
+import space.kscience.kmath.structures.BufferFactory
+import kotlin.reflect.KClass
+
+/**
+ * Alias for [Structure2D] with more familiar name.
+ *
+ * @param T the type of items.
+ */
+public typealias Matrix<T> = Structure2D<T>
+
+/**
+ * Alias or using [Buffer] as a point/vector in a many-dimensional space.
+ */
+public typealias Point<T> = Buffer<T>
+
+/**
+ * Basic operations on matrices and vectors. Operates on [Matrix].
+ *
+ * @param T the type of items in the matrices.
+ * @param M the type of operated matrices.
+ */
+public interface LinearSpace<T : Any, out A : Ring<T>> {
+    public val elementAlgebra: A
+
+    /**
+     * Produces a matrix with this context and given dimensions.
+     */
+    public fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix<T>
+
+    /**
+     * Produces a point compatible with matrix space (and possibly optimized for it).
+     */
+    public fun buildVector(size: Int, initializer: A.(Int) -> T): Point<T>
+
+    public operator fun Matrix<T>.unaryMinus(): Matrix<T> = buildMatrix(rowNum, colNum) { i, j ->
+        -get(i, j)
+    }
+
+    public operator fun Point<T>.unaryMinus(): Point<T> = buildVector(size) {
+        -get(it)
+    }
+
+    /**
+     * Matrix sum
+     */
+    public operator fun Matrix<T>.plus(other: Matrix<T>): Matrix<T> = buildMatrix(rowNum, colNum) { i, j ->
+        get(i, j) + other[i, j]
+    }
+
+
+    /**
+     * Vector sum
+     */
+    public operator fun Point<T>.plus(other: Point<T>): Point<T> = buildVector(size) {
+        get(it) + other[it]
+    }
+
+    /**
+     * Matrix subtraction
+     */
+    public operator fun Matrix<T>.minus(other: Matrix<T>): Matrix<T> = buildMatrix(rowNum, colNum) { i, j ->
+        get(i, j) - other[i, j]
+    }
+
+    /**
+     * Vector subtraction
+     */
+    public operator fun Point<T>.minus(other: Point<T>): Point<T> = buildVector(size) {
+        get(it) - other[it]
+    }
+
+
+    /**
+     * Computes the dot product of this matrix and another one.
+     *
+     * @receiver the multiplicand.
+     * @param other the multiplier.
+     * @return the dot product.
+     */
+    public infix fun Matrix<T>.dot(other: Matrix<T>): Matrix<T> {
+        require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
+        return elementAlgebra {
+            buildMatrix(rowNum, other.colNum) { i, j ->
+                var res = zero
+                for (l in 0 until colNum) {
+                    res += this@dot[i, l] * other[l, j]
+                }
+                res
+            }
+        }
+    }
+
+    /**
+     * Computes the dot product of this matrix and a vector.
+     *
+     * @receiver the multiplicand.
+     * @param vector the multiplier.
+     * @return the dot product.
+     */
+    public infix fun Matrix<T>.dot(vector: Point<T>): Point<T> {
+        require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
+        return elementAlgebra {
+            buildVector(rowNum) { i ->
+                var res = one
+                for (j in 0 until colNum) {
+                    res += this@dot[i, j] * vector[j]
+                }
+                res
+            }
+        }
+    }
+
+    /**
+     * Multiplies a matrix by its element.
+     *
+     * @receiver the multiplicand.
+     * @param value the multiplier.
+     * @receiver the product.
+     */
+    public operator fun Matrix<T>.times(value: T): Matrix<T> =
+        buildMatrix(rowNum, colNum) { i, j -> get(i, j) * value }
+
+    /**
+     * Multiplies an element by a matrix of it.
+     *
+     * @receiver the multiplicand.
+     * @param m the multiplier.
+     * @receiver the product.
+     */
+    public operator fun T.times(m: Matrix<T>): Matrix<T> = m * this
+
+    /**
+     * Multiplies a vector by its element.
+     *
+     * @receiver the multiplicand.
+     * @param value the multiplier.
+     * @receiver the product.
+     */
+    public operator fun Point<T>.times(value: T): Point<T> =
+        buildVector(size) { i -> get(i) * value }
+
+    /**
+     * Multiplies an element by a vector of it.
+     *
+     * @receiver the multiplicand.
+     * @param v the multiplier.
+     * @receiver the product.
+     */
+    public operator fun T.times(v: Point<T>): Point<T> = v * this
+
+    /**
+     * Gets a feature from the matrix. This function may return some additional features to
+     * [space.kscience.kmath.nd.NDStructure.getFeature].
+     *
+     * @param F the type of feature.
+     * @param m the matrix.
+     * @param type the [KClass] instance of [F].
+     * @return a feature object or `null` if it isn't present.
+     */
+    @UnstableKMathAPI
+    public fun <F : Any> getFeature(m: Matrix<T>, type: KClass<F>): F? = m.getFeature(type)
+
+    public companion object {
+
+        /**
+         * A structured matrix with custom buffer
+         */
+        public fun <T : Any, A : Ring<T>> buffered(
+            algebra: A,
+            bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
+        ): LinearSpace<T, A> = BufferLinearSpace(algebra,bufferFactory)
+
+        public val real: LinearSpace<Double, RealField> = buffered(RealField, Buffer.Companion::real)
+
+        /**
+         * Automatic buffered matrix, unboxed if it is possible
+         */
+        public inline fun <reified T : Any, A : Ring<T>> auto(ring: A): LinearSpace<T, A> =
+            buffered(ring, Buffer.Companion::auto)
+    }
+}
+
+public operator fun <LS : LinearSpace<*, *>, R> LS.invoke(block: LS.() -> R): R = run(block)
+
+/**
+ * Gets a feature from the matrix. This function may return some additional features to
+ * [space.kscience.kmath.nd.NDStructure.getFeature].
+ *
+ * @param T the type of items in the matrices.
+ * @param M the type of operated matrices.
+ * @param F the type of feature.
+ * @receiver the [LinearSpace] of [T].
+ * @param m the matrix.
+ * @return a feature object or `null` if it isn't present.
+ */
+@UnstableKMathAPI
+public inline fun <T : Any, reified F : Any> LinearSpace<T, *>.getFeature(m: Matrix<T>): F? = getFeature(m, F::class)
+
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt
index a3d4cbc47..0937f1e19 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt
@@ -12,7 +12,7 @@ import space.kscience.kmath.structures.MutableBufferFactory
  * Common implementation of [LupDecompositionFeature].
  */
 public class LupDecomposition<T : Any>(
-    public val context: MatrixContext<T, Matrix<T>>,
+    public val context: LinearSpace<T, *>,
     public val elementContext: Field<T>,
     public val lu: Matrix<T>,
     public val pivot: IntArray,
@@ -62,15 +62,14 @@ public class LupDecomposition<T : Any>(
 }
 
 @PublishedApi
-internal fun <T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F, *>.abs(value: T): T =
-    if (value > elementContext.zero) value else elementContext { -value }
+internal fun <T : Comparable<T>> LinearSpace<T, Ring<T>>.abs(value: T): T =
+    if (value > elementAlgebra.zero) value else elementAlgebra { -value }
 
 /**
  * Create a lup decomposition of generic matrix.
  */
-public fun <T : Comparable<T>> MatrixContext<T, Matrix<T>>.lup(
+public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
     factory: MutableBufferFactory<T>,
-    elementContext: Field<T>,
     matrix: Matrix<T>,
     checkSingular: (T) -> Boolean,
 ): LupDecomposition<T> {
@@ -80,7 +79,7 @@ public fun <T : Comparable<T>> MatrixContext<T, Matrix<T>>.lup(
 
     //TODO just waits for KEEP-176
     BufferAccessor2D(matrix.rowNum, matrix.colNum, factory).run {
-        elementContext {
+        elementAlgebra {
             val lu = create(matrix)
 
             // Initialize permutation array and parity
@@ -142,18 +141,18 @@ public fun <T : Comparable<T>> MatrixContext<T, Matrix<T>>.lup(
                 for (row in col + 1 until m) lu[row, col] /= luDiag
             }
 
-            return LupDecomposition(this@lup, elementContext, lu.collect(), pivot, even)
+            return LupDecomposition(this@lup, elementAlgebra, lu.collect(), pivot, even)
         }
     }
 }
 
-public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F, Matrix<T>>.lup(
+public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
     matrix: Matrix<T>,
     noinline checkSingular: (T) -> Boolean,
-): LupDecomposition<T> = lup(MutableBuffer.Companion::auto, elementContext, matrix, checkSingular)
+): LupDecomposition<T> = lup(MutableBuffer.Companion::auto, matrix, checkSingular)
 
-public fun MatrixContext<Double, Matrix<Double>>.lup(matrix: Matrix<Double>): LupDecomposition<Double> =
-    lup(Buffer.Companion::real, RealField, matrix) { it < 1e-11 }
+public fun LinearSpace<Double, RealField>.lup(matrix: Matrix<Double>): LupDecomposition<Double> =
+    lup(Buffer.Companion::real, matrix) { it < 1e-11 }
 
 public fun <T : Any> LupDecomposition<T>.solveWithLup(
     factory: MutableBufferFactory<T>,
@@ -198,7 +197,7 @@ public fun <T : Any> LupDecomposition<T>.solveWithLup(
                 }
             }
 
-            return context.produce(pivot.size, matrix.colNum) { i, j -> bp[i, j] }
+            return context.buildMatrix(pivot.size, matrix.colNum) { i, j -> bp[i, j] }
         }
     }
 }
@@ -210,18 +209,18 @@ public inline fun <reified T : Any> LupDecomposition<T>.solveWithLup(matrix: Mat
  * Solves a system of linear equations *ax = b** using LUP decomposition.
  */
 @OptIn(UnstableKMathAPI::class)
-public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F, Matrix<T>>.solveWithLup(
+public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.solveWithLup(
     a: Matrix<T>,
     b: Matrix<T>,
     noinline bufferFactory: MutableBufferFactory<T> = MutableBuffer.Companion::auto,
     noinline checkSingular: (T) -> Boolean,
 ): Matrix<T> {
     // Use existing decomposition if it is provided by matrix
-    val decomposition = a.getFeature() ?: lup(bufferFactory, elementContext, a, checkSingular)
+    val decomposition = a.getFeature() ?: lup(bufferFactory, a, checkSingular)
     return decomposition.solveWithLup(bufferFactory, b)
 }
 
-public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F, Matrix<T>>.inverseWithLup(
+public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.inverseWithLup(
     matrix: Matrix<T>,
     noinline bufferFactory: MutableBufferFactory<T> = MutableBuffer.Companion::auto,
     noinline checkSingular: (T) -> Boolean,
@@ -229,15 +228,15 @@ public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext
 
 
 @OptIn(UnstableKMathAPI::class)
-public fun RealMatrixContext.solveWithLup(a: Matrix<Double>, b: Matrix<Double>): Matrix<Double> {
+public fun LinearSpace<Double, RealField>.solveWithLup(a: Matrix<Double>, b: Matrix<Double>): Matrix<Double> {
     // Use existing decomposition if it is provided by matrix
     val bufferFactory: MutableBufferFactory<Double> = MutableBuffer.Companion::real
-    val decomposition: LupDecomposition<Double> = a.getFeature() ?: lup(bufferFactory, RealField, a) { it < 1e-11 }
+    val decomposition: LupDecomposition<Double> = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 }
     return decomposition.solveWithLup(bufferFactory, b)
 }
 
 /**
  * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error.
  */
-public fun RealMatrixContext.inverseWithLup(matrix: Matrix<Double>): Matrix<Double> =
+public fun LinearSpace<Double, RealField>.inverseWithLup(matrix: Matrix<Double>): Matrix<Double> =
     solveWithLup(matrix, one(matrix.rowNum, matrix.colNum))
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt
index c96834360..b30d621fe 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt
@@ -1,46 +1,43 @@
 package space.kscience.kmath.linear
 
-import space.kscience.kmath.nd.Structure2D
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.BufferFactory
-import space.kscience.kmath.structures.asBuffer
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.Ring
 
-public class MatrixBuilder(public val rows: Int, public val columns: Int) {
-    public operator fun <T : Any> invoke(vararg elements: T): Matrix<T> {
+public class MatrixBuilder<T : Any, A : Ring<T>>(
+    public val linearSpace: LinearSpace<T, A>,
+    public val rows: Int,
+    public val columns: Int,
+) {
+    public operator fun invoke(vararg elements: T): Matrix<T> {
         require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" }
-        val buffer = elements.asBuffer()
-        return BufferMatrix(rows, columns, buffer)
+        return linearSpace.buildMatrix(rows, columns) { i, j -> elements[i * columns + j] }
     }
 
     //TODO add specific matrix builder functions like diagonal, etc
 }
 
-public fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns)
+/**
+ * Create a matrix builder with given number of rows and columns
+ */
+@UnstableKMathAPI
+public fun <T : Any, A : Ring<T>> LinearSpace<T, A>.matrix(rows: Int, columns: Int): MatrixBuilder<T, A> =
+    MatrixBuilder(this, rows, columns)
 
-public fun <T : Any> Structure2D.Companion.row(vararg values: T): Matrix<T> {
-    val buffer = values.asBuffer()
-    return BufferMatrix(1, values.size, buffer)
+@UnstableKMathAPI
+public fun <T : Any> LinearSpace<T, Ring<T>>.vector(vararg elements: T): Point<T> {
+    return buildVector(elements.size) { elements[it] }
 }
 
-public inline fun <reified T : Any> Structure2D.Companion.row(
+public inline fun <T : Any> LinearSpace<T, Ring<T>>.row(
     size: Int,
-    factory: BufferFactory<T> = Buffer.Companion::auto,
-    noinline builder: (Int) -> T,
-): Matrix<T> {
-    val buffer = factory(size, builder)
-    return BufferMatrix(1, size, buffer)
-}
+    crossinline builder: (Int) -> T,
+): Matrix<T> = buildMatrix(1, size) { _, j -> builder(j) }
 
-public fun <T : Any> Structure2D.Companion.column(vararg values: T): Matrix<T> {
-    val buffer = values.asBuffer()
-    return BufferMatrix(values.size, 1, buffer)
-}
+public fun <T : Any> LinearSpace<T, Ring<T>>.row(vararg values: T): Matrix<T> = row(values.size, values::get)
 
-public inline fun <reified T : Any> Structure2D.Companion.column(
+public inline fun <T : Any> LinearSpace<T, Ring<T>>.column(
     size: Int,
-    factory: BufferFactory<T> = Buffer.Companion::auto,
-    noinline builder: (Int) -> T,
-): Matrix<T> {
-    val buffer = factory(size, builder)
-    return BufferMatrix(size, 1, buffer)
-}
+    crossinline builder: (Int) -> T,
+): Matrix<T> = buildMatrix(size, 1) { i, _ -> builder(i) }
+
+public fun <T : Any> LinearSpace<T, Ring<T>>.column(vararg values: T): Matrix<T> = column(values.size, values::get)
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt
deleted file mode 100644
index c999a170c..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-package space.kscience.kmath.linear
-
-import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.operations.SpaceOperations
-import space.kscience.kmath.operations.invoke
-import space.kscience.kmath.operations.sum
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.BufferFactory
-import space.kscience.kmath.structures.asSequence
-import kotlin.reflect.KClass
-
-/**
- * Basic operations on matrices. Operates on [Matrix].
- *
- * @param T the type of items in the matrices.
- * @param M the type of operated matrices.
- */
-public interface MatrixContext<T : Any, out M : Matrix<T>> : SpaceOperations<Matrix<T>> {
-    /**
-     * Produces a matrix with this context and given dimensions.
-     */
-    public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): M
-
-    /**
-     * Produces a point compatible with matrix space (and possibly optimized for it).
-     */
-    public fun point(size: Int, initializer: (Int) -> T): Point<T> = Buffer.boxing(size, initializer)
-
-    @Suppress("UNCHECKED_CAST")
-    public override fun binaryOperationFunction(operation: String): (left: Matrix<T>, right: Matrix<T>) -> M =
-        when (operation) {
-            "dot" -> { left, right -> left dot right }
-            else -> super.binaryOperationFunction(operation) as (Matrix<T>, Matrix<T>) -> M
-        }
-
-    /**
-     * Computes the dot product of this matrix and another one.
-     *
-     * @receiver the multiplicand.
-     * @param other the multiplier.
-     * @return the dot product.
-     */
-    public infix fun Matrix<T>.dot(other: Matrix<T>): M
-
-    /**
-     * Computes the dot product of this matrix and a vector.
-     *
-     * @receiver the multiplicand.
-     * @param vector the multiplier.
-     * @return the dot product.
-     */
-    public infix fun Matrix<T>.dot(vector: Point<T>): Point<T>
-
-    /**
-     * Multiplies a matrix by its element.
-     *
-     * @receiver the multiplicand.
-     * @param value the multiplier.
-     * @receiver the product.
-     */
-    public operator fun Matrix<T>.times(value: T): M
-
-    /**
-     * Multiplies an element by a matrix of it.
-     *
-     * @receiver the multiplicand.
-     * @param m the multiplier.
-     * @receiver the product.
-     */
-    public operator fun T.times(m: Matrix<T>): M = m * this
-
-    /**
-     * Gets a feature from the matrix. This function may return some additional features to
-     * [kscience.kmath.nd.NDStructure.getFeature].
-     *
-     * @param F the type of feature.
-     * @param m the matrix.
-     * @param type the [KClass] instance of [F].
-     * @return a feature object or `null` if it isn't present.
-     */
-    @UnstableKMathAPI
-    public fun <F : Any> getFeature(m: Matrix<T>, type: KClass<F>): F? = m.getFeature(type)
-
-    public companion object {
-
-        /**
-         * A structured matrix with custom buffer
-         */
-        public fun <T : Any, R : Ring<T>> buffered(
-            ring: R,
-            bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
-        ): GenericMatrixContext<T, R, BufferMatrix<T>> = BufferMatrixContext(ring, bufferFactory)
-
-        /**
-         * Automatic buffered matrix, unboxed if it is possible
-         */
-        public inline fun <reified T : Any, R : Ring<T>> auto(ring: R): GenericMatrixContext<T, R, BufferMatrix<T>> =
-            buffered(ring, Buffer.Companion::auto)
-    }
-}
-
-/**
- * Gets a feature from the matrix. This function may return some additional features to
- * [kscience.kmath.nd.NDStructure.getFeature].
- *
- * @param T the type of items in the matrices.
- * @param M the type of operated matrices.
- * @param F the type of feature.
- * @receiver the [MatrixContext] of [T].
- * @param m the matrix.
- * @return a feature object or `null` if it isn't present.
- */
-@UnstableKMathAPI
-public inline fun <T : Any, reified F : Any> MatrixContext<T, *>.getFeature(m: Matrix<T>): F? =
-    getFeature(m, F::class)
-
-/**
- * Partial implementation of [MatrixContext] for matrices of [Ring].
- *
- * @param T the type of items in the matrices.
- * @param R the type of ring of matrix elements.
- * @param M the type of operated matrices.
- */
-public interface GenericMatrixContext<T : Any, R : Ring<T>, out M : Matrix<T>> : MatrixContext<T, M> {
-    /**
-     * The ring over matrix elements.
-     */
-    public val elementContext: R
-
-    public override infix fun Matrix<T>.dot(other: Matrix<T>): M {
-        //TODO add typed error
-        require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
-
-        return produce(rowNum, other.colNum) { i, j ->
-            val row = rows[i]
-            val column = other.columns[j]
-            elementContext { sum(row.asSequence().zip(column.asSequence(), ::multiply)) }
-        }
-    }
-
-    public override infix fun Matrix<T>.dot(vector: Point<T>): Point<T> {
-        //TODO add typed error
-        require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
-
-        return point(rowNum) { i ->
-            val row = rows[i]
-            elementContext { sum(row.asSequence().zip(vector.asSequence(), ::multiply)) }
-        }
-    }
-
-    public override operator fun Matrix<T>.unaryMinus(): M =
-        produce(rowNum, colNum) { i, j -> elementContext { -get(i, j) } }
-
-    public override fun add(a: Matrix<T>, b: Matrix<T>): M {
-        require(a.rowNum == b.rowNum && a.colNum == b.colNum) {
-            "Matrix operation dimension mismatch. [${a.rowNum},${a.colNum}] + [${b.rowNum},${b.colNum}]"
-        }
-
-        return produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] + b[i, j] } }
-    }
-
-    public override operator fun Matrix<T>.minus(b: Matrix<T>): M {
-        require(rowNum == b.rowNum && colNum == b.colNum) {
-            "Matrix operation dimension mismatch. [$rowNum,$colNum] - [${b.rowNum},${b.colNum}]"
-        }
-
-        return produce(rowNum, colNum) { i, j -> elementContext { get(i, j) + b[i, j] } }
-    }
-
-    public override fun multiply(a: Matrix<T>, k: Number): M =
-        produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } }
-
-    public override operator fun Matrix<T>.times(value: T): M =
-        produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } }
-}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt
index 86ec0de88..97f0acd61 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt
@@ -1,20 +1,16 @@
 package space.kscience.kmath.linear
 
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.Structure2D
 import space.kscience.kmath.nd.getFeature
 import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.structures.asBuffer
-import kotlin.math.sqrt
 import kotlin.reflect.KClass
-import kotlin.reflect.safeCast
 
 /**
  * A [Matrix] that holds [MatrixFeature] objects.
  *
  * @param T the type of items.
  */
-public class MatrixWrapper<T : Any> internal  constructor(
+public class MatrixWrapper<T : Any> internal constructor(
     public val origin: Matrix<T>,
     public val features: Set<MatrixFeature>,
 ) : Matrix<T> by origin {
@@ -23,7 +19,8 @@ public class MatrixWrapper<T : Any> internal  constructor(
      * Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria
      */
     @UnstableKMathAPI
-    override fun <T : Any> getFeature(type: KClass<T>): T? = type.safeCast(features.find { type.isInstance(it) })
+    @Suppress("UNCHECKED_CAST")
+    override fun <T : Any> getFeature(type: KClass<T>): T? = features.singleOrNull { type.isInstance(it) } as? T
         ?: origin.getFeature(type)
 
     override fun equals(other: Any?): Boolean = origin == other
@@ -60,30 +57,26 @@ public operator fun <T : Any> Matrix<T>.plus(newFeatures: Collection<MatrixFeatu
         MatrixWrapper(this, newFeatures.toSet())
     }
 
-/**
- * Build a square matrix from given elements.
- */
-public fun <T : Any> Structure2D.Companion.square(vararg elements: T): Matrix<T> {
-    val size: Int = sqrt(elements.size.toDouble()).toInt()
-    require(size * size == elements.size) { "The number of elements ${elements.size} is not a full square" }
-    val buffer = elements.asBuffer()
-    return BufferMatrix(size, size, buffer)
-}
-
 /**
  * Diagonal matrix of ones. The matrix is virtual no actual matrix is created
  */
-public fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R, *>.one(rows: Int, columns: Int): Matrix<T> =
-    VirtualMatrix(rows, columns) { i, j ->
-        if (i == j) elementContext.one else elementContext.zero
-    } + UnitFeature
+public fun <T : Any> LinearSpace<T, Ring<T>>.one(
+    rows: Int,
+    columns: Int,
+): Matrix<T> = VirtualMatrix(rows, columns) { i, j ->
+    if (i == j) elementAlgebra.one else elementAlgebra.zero
+} + UnitFeature
 
 
 /**
  * A virtual matrix of zeroes
  */
-public fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R, *>.zero(rows: Int, columns: Int): Matrix<T> =
-    VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } + ZeroFeature
+public fun <T : Any> LinearSpace<T, Ring<T>>.zero(
+    rows: Int,
+    columns: Int,
+): Matrix<T> = VirtualMatrix(rows, columns) { _, _ ->
+    elementAlgebra.zero
+} + ZeroFeature
 
 public class TransposedFeature<T : Any>(public val original: Matrix<T>) : MatrixFeature
 
@@ -91,9 +84,7 @@ public class TransposedFeature<T : Any>(public val original: Matrix<T>) : Matrix
  * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
  */
 @OptIn(UnstableKMathAPI::class)
-public fun <T : Any> Matrix<T>.transpose(): Matrix<T> {
-    return getFeature<TransposedFeature<T>>()?.original ?: VirtualMatrix(
-        colNum,
-        rowNum,
-    ) { i, j -> get(j, i) } + TransposedFeature(this)
-}
\ No newline at end of file
+public fun <T : Any> Matrix<T>.transpose(): Matrix<T> = getFeature<TransposedFeature<T>>()?.original ?: VirtualMatrix(
+    colNum,
+    rowNum,
+) { i, j -> get(j, i) } + TransposedFeature(this)
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt
deleted file mode 100644
index 5f28e6f4c..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package space.kscience.kmath.linear
-
-import space.kscience.kmath.structures.RealBuffer
-
-public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
-
-    public override fun produce(
-        rows: Int,
-        columns: Int,
-        initializer: (i: Int, j: Int) -> Double,
-    ): BufferMatrix<Double> {
-        val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
-        return BufferMatrix(rows, columns, buffer)
-    }
-
-    public fun Matrix<Double>.toBufferMatrix(): BufferMatrix<Double> = if (this is BufferMatrix) this else {
-        produce(rowNum, colNum) { i, j -> get(i, j) }
-    }
-
-    public fun one(rows: Int, columns: Int): Matrix<Double> = VirtualMatrix(rows, columns) { i, j ->
-        if (i == j) 1.0 else 0.0
-    } + DiagonalFeature
-
-    public override infix fun Matrix<Double>.dot(other: Matrix<Double>): BufferMatrix<Double> {
-        require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
-        val bufferMatrix = toBufferMatrix()
-        val otherBufferMatrix = other.toBufferMatrix()
-        return produce(rowNum, other.colNum) { i, j ->
-            var res = 0.0
-            for (l in 0 until colNum) {
-                res += bufferMatrix[i, l] * otherBufferMatrix[l, j]
-            }
-            res
-        }
-    }
-
-    public override infix fun Matrix<Double>.dot(vector: Point<Double>): Point<Double> {
-        require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
-        val bufferMatrix = toBufferMatrix()
-        return RealBuffer(rowNum) { i ->
-            var res = 0.0
-            for (j in 0 until colNum) {
-                res += bufferMatrix[i, j] * vector[j]
-            }
-            res
-        }
-    }
-
-    override fun add(a: Matrix<Double>, b: Matrix<Double>): BufferMatrix<Double> {
-        require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" }
-        require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" }
-        val aBufferMatrix = a.toBufferMatrix()
-        val bBufferMatrix = b.toBufferMatrix()
-        return produce(a.rowNum, a.colNum) { i, j ->
-            aBufferMatrix[i, j] + bBufferMatrix[i, j]
-        }
-    }
-
-    override fun Matrix<Double>.times(value: Double): BufferMatrix<Double> {
-        val bufferMatrix = toBufferMatrix()
-        return produce(rowNum, colNum) { i, j -> bufferMatrix[i, j] * value }
-    }
-
-
-    override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> {
-        val aBufferMatrix = a.toBufferMatrix()
-        return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
-    }
-}
-
-
-/**
- * Partially optimized real-valued matrix
- */
-public val MatrixContext.Companion.real: RealMatrixContext get() = RealMatrixContext
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt
deleted file mode 100644
index 310c1350c..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package space.kscience.kmath.linear
-
-import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.Space
-import space.kscience.kmath.operations.invoke
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.BufferFactory
-
-/**
- * A linear space for vectors.
- * Could be used on any point-like structure
- */
-public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
-    public val size: Int
-    public val space: S
-    override val zero: Point<T> get() = produce { space.zero }
-
-    public fun produce(initializer: S.(Int) -> T): Point<T>
-
-    /**
-     * Produce a space-element of this vector space for expressions
-     */
-    //fun produceElement(initializer: (Int) -> T): Vector<T, S>
-
-    override fun add(a: Point<T>, b: Point<T>): Point<T> = produce { space { a[it] + b[it] } }
-
-    override fun multiply(a: Point<T>, k: Number): Point<T> = produce { space { a[it] * k } }
-
-    //TODO add basis
-
-    public companion object {
-        private val realSpaceCache: MutableMap<Int, BufferVectorSpace<Double, RealField>> = hashMapOf()
-
-        /**
-         * Non-boxing double vector space
-         */
-        public fun real(size: Int): BufferVectorSpace<Double, RealField> = realSpaceCache.getOrPut(size) {
-            BufferVectorSpace(
-                size,
-                RealField,
-                Buffer.Companion::auto
-            )
-        }
-
-        /**
-         * A structured vector space with custom buffer
-         */
-        public fun <T : Any, S : Space<T>> buffered(
-            size: Int,
-            space: S,
-            bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
-        ): BufferVectorSpace<T, S> = BufferVectorSpace(size, space, bufferFactory)
-
-        /**
-         * Automatic buffered vector, unboxed if it is possible
-         */
-        public inline fun <reified T : Any, S : Space<T>> auto(size: Int, space: S): VectorSpace<T, S> =
-            buffered(size, space, Buffer.Companion::auto)
-    }
-}
-
-
-public class BufferVectorSpace<T : Any, S : Space<T>>(
-    override val size: Int,
-    override val space: S,
-    public val bufferFactory: BufferFactory<T>,
-) : VectorSpace<T, S> {
-    override fun produce(initializer: S.(Int) -> T): Buffer<T> = bufferFactory(size) { space.initializer(it) }
-    //override fun produceElement(initializer: (Int) -> T): Vector<T, S> = BufferVector(this, produce(initializer))
-}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt
index 26b1899a1..7f0451946 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt
@@ -1,5 +1,7 @@
 package space.kscience.kmath.linear
 
+import space.kscience.kmath.nd.NDStructure
+
 /**
  * The matrix where each element is evaluated each time when is being accessed.
  *
@@ -17,12 +19,8 @@ public class VirtualMatrix<T : Any>(
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
-        if (other !is Matrix<*>) return false
-
-        if (rowNum != other.rowNum) return false
-        if (colNum != other.colNum) return false
-
-        return elements().all { (index, value) -> value == other[index] }
+        if (other !is NDStructure<*>) return false
+        return NDStructure.contentEquals(this, other)
     }
 
     override fun hashCode(): Int {
@@ -31,6 +29,4 @@ public class VirtualMatrix<T : Any>(
         result = 31 * result + generator.hashCode()
         return result
     }
-
-
 }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt
index 380723095..b50e095cf 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt
@@ -1,6 +1,6 @@
 package space.kscience.kmath.misc
 
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
 import space.kscience.kmath.operations.invoke
 import kotlin.jvm.JvmName
 
@@ -37,7 +37,7 @@ public fun <T, R> List<T>.cumulative(initial: R, operation: (R, T) -> R): List<R
 /**
  * Cumulative sum with custom space
  */
-public fun <T> Iterable<T>.cumulativeSum(space: Space<T>): Iterable<T> =
+public fun <T> Iterable<T>.cumulativeSum(space: Group<T>): Iterable<T> =
     space { cumulative(zero) { element: T, sum: T -> sum + element } }
 
 @JvmName("cumulativeSumOfDouble")
@@ -49,7 +49,7 @@ public fun Iterable<Int>.cumulativeSum(): Iterable<Int> = cumulative(0) { elemen
 @JvmName("cumulativeSumOfLong")
 public fun Iterable<Long>.cumulativeSum(): Iterable<Long> = cumulative(0L) { element, sum -> sum + element }
 
-public fun <T> Sequence<T>.cumulativeSum(space: Space<T>): Sequence<T> =
+public fun <T> Sequence<T>.cumulativeSum(space: Group<T>): Sequence<T> =
     space { cumulative(zero) { element: T, sum: T -> sum + element } }
 
 @JvmName("cumulativeSumOfDouble")
@@ -61,7 +61,7 @@ public fun Sequence<Int>.cumulativeSum(): Sequence<Int> = cumulative(0) { elemen
 @JvmName("cumulativeSumOfLong")
 public fun Sequence<Long>.cumulativeSum(): Sequence<Long> = cumulative(0L) { element, sum -> sum + element }
 
-public fun <T> List<T>.cumulativeSum(space: Space<T>): List<T> =
+public fun <T> List<T>.cumulativeSum(space: Group<T>): List<T> =
     space { cumulative(zero) { element: T, sum: T -> sum + element } }
 
 @JvmName("cumulativeSumOfDouble")
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt
index 71c7d444c..bce3a0830 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt
@@ -1,19 +1,16 @@
 package space.kscience.kmath.nd
 
-import space.kscience.kmath.operations.Field
-import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.*
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.BufferFactory
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 
-public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
+public interface BufferNDAlgebra<T, A : Algebra<T>> : NDAlgebra<T, A> {
     public val strides: Strides
     public val bufferFactory: BufferFactory<T>
 
-    override fun produce(initializer: C.(IntArray) -> T): NDBuffer<T> = NDBuffer(
+    override fun produce(initializer: A.(IntArray) -> T): NDBuffer<T> = NDBuffer(
         strides,
         bufferFactory(strides.linearSize) { offset ->
             elementContext.initializer(strides.index(offset))
@@ -30,14 +27,14 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
             else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) }
         }
 
-    override fun NDStructure<T>.map(transform: C.(T) -> T): NDBuffer<T> {
+    override fun NDStructure<T>.map(transform: A.(T) -> T): NDBuffer<T> {
         val buffer = bufferFactory(strides.linearSize) { offset ->
             elementContext.transform(buffer[offset])
         }
         return NDBuffer(strides, buffer)
     }
 
-    override fun NDStructure<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDBuffer<T> {
+    override fun NDStructure<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer<T> {
         val buffer = bufferFactory(strides.linearSize) { offset ->
             elementContext.transform(
                 strides.index(offset),
@@ -47,7 +44,7 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
         return NDBuffer(strides, buffer)
     }
 
-    override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: C.(T, T) -> T): NDBuffer<T> {
+    override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: A.(T, T) -> T): NDBuffer<T> {
         val buffer = bufferFactory(strides.linearSize) { offset ->
             elementContext.transform(a.buffer[offset], b.buffer[offset])
         }
@@ -55,20 +52,21 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
     }
 }
 
-public open class BufferedNDSpace<T, R : Space<T>>(
+public open class BufferedNDGroup<T, A : Group<T>>(
     final override val shape: IntArray,
-    final override val elementContext: R,
+    final override val elementContext: A,
     final override val bufferFactory: BufferFactory<T>,
-) : NDSpace<T, R>, BufferNDAlgebra<T, R> {
+) : NDGroup<T, A>, BufferNDAlgebra<T, A> {
     override val strides: Strides = DefaultStrides(shape)
     override val zero: NDBuffer<T> by lazy { produce { zero } }
+    override fun NDStructure<T>.unaryMinus(): NDStructure<T> = produce { -get(it) }
 }
 
 public open class BufferedNDRing<T, R : Ring<T>>(
     shape: IntArray,
     elementContext: R,
     bufferFactory: BufferFactory<T>,
-) : BufferedNDSpace<T, R>(shape, elementContext, bufferFactory), NDRing<T, R> {
+) : BufferedNDGroup<T, R>(shape, elementContext, bufferFactory), NDRing<T, R> {
     override val one: NDBuffer<T> by lazy { produce { one } }
 }
 
@@ -76,22 +74,25 @@ public open class BufferedNDField<T, R : Field<T>>(
     shape: IntArray,
     elementContext: R,
     bufferFactory: BufferFactory<T>,
-) : BufferedNDRing<T, R>(shape, elementContext, bufferFactory), NDField<T, R>
+) : BufferedNDRing<T, R>(shape, elementContext, bufferFactory), NDField<T, R> {
 
-// space factories
-public fun <T, A : Space<T>> NDAlgebra.Companion.space(
+    override fun scale(a: NDStructure<T>, value: Double): NDStructure<T> = a.map { it * value }
+}
+
+// group factories
+public fun <T, A : Group<T>> NDAlgebra.Companion.group(
     space: A,
     bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-): BufferedNDSpace<T, A> = BufferedNDSpace(shape, space, bufferFactory)
+): BufferedNDGroup<T, A> = BufferedNDGroup(shape, space, bufferFactory)
 
-public inline fun <T, A : Space<T>, R> A.ndSpace(
+public inline fun <T, A : Group<T>, R> A.ndGroup(
     noinline bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-    action: BufferedNDSpace<T, A>.() -> R,
+    action: BufferedNDGroup<T, A>.() -> R,
 ): R {
     contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return NDAlgebra.space(this, bufferFactory, *shape).run(action)
+    return NDAlgebra.group(this, bufferFactory, *shape).run(action)
 }
 
 //ring factories
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt
index af154d3cd..e3ffae74b 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt
@@ -1,8 +1,6 @@
 package space.kscience.kmath.nd
 
-import space.kscience.kmath.operations.Field
-import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.*
 import space.kscience.kmath.structures.*
 
 /**
@@ -21,7 +19,7 @@ public class ShapeMismatchException(public val expected: IntArray, public val ac
  * @param C the type of the element context.
  * @param N the type of the structure.
  */
-public interface NDAlgebra<T, C> {
+public interface NDAlgebra<T, C: Algebra<T>> {
     /**
      * The shape of ND-structures this algebra operates on.
      */
@@ -33,7 +31,7 @@ public interface NDAlgebra<T, C> {
     public val elementContext: C
 
     /**
-     * Produces a new [N] structure using given initializer function.
+     * Produces a new NDStructure using given initializer function.
      */
     public fun produce(initializer: C.(IntArray) -> T): NDStructure<T>
 
@@ -56,7 +54,7 @@ public interface NDAlgebra<T, C> {
      * Element-wise invocation of function working on [T] on a [NDStructure].
      */
     public operator fun Function1<T, T>.invoke(structure: NDStructure<T>): NDStructure<T> =
-        structure.map() { value -> this@invoke(value) }
+        structure.map { value -> this@invoke(value) }
 
     public companion object
 }
@@ -67,7 +65,7 @@ public interface NDAlgebra<T, C> {
  * @param structures the structures to check.
  * @return the array of valid structures.
  */
-internal fun <T, C> NDAlgebra<T, C>.checkShape(vararg structures: NDStructure<T>): Array<out NDStructure<T>> = structures
+internal fun <T, C: Algebra<T>> NDAlgebra<T, C>.checkShape(vararg structures: NDStructure<T>): Array<out NDStructure<T>> = structures
     .map(NDStructure<T>::shape)
     .singleOrNull { !shape.contentEquals(it) }
     ?.let<IntArray, Array<out NDStructure<T>>> { throw ShapeMismatchException(shape, it) }
@@ -79,7 +77,7 @@ internal fun <T, C> NDAlgebra<T, C>.checkShape(vararg structures: NDStructure<T>
  * @param element the structure to check.
  * @return the valid structure.
  */
-internal fun <T, C> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStructure<T> {
+internal fun <T, C: Algebra<T>> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStructure<T> {
     if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape)
     return element
 }
@@ -91,7 +89,7 @@ internal fun <T, C> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStruc
  * @param N the type of ND structure.
  * @param S the type of space of structure elements.
  */
-public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T, S> {
+public interface NDGroup<T, S : Group<T>> : Group<NDStructure<T>>, NDAlgebra<T, S> {
     /**
      * Element-wise addition.
      *
@@ -102,14 +100,14 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
     public override fun add(a: NDStructure<T>, b: NDStructure<T>): NDStructure<T> =
         combine(a, b) { aValue, bValue -> add(aValue, bValue) }
 
-    /**
-     * Element-wise multiplication by scalar.
-     *
-     * @param a the multiplicand.
-     * @param k the multiplier.
-     * @return the product.
-     */
-    public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = a.map() { multiply(it, k) }
+//    /**
+//     * Element-wise multiplication by scalar.
+//     *
+//     * @param a the multiplicand.
+//     * @param k the multiplier.
+//     * @return the product.
+//     */
+//    public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> =  a.map { multiply(it, k) }
 
     // TODO move to extensions after KEEP-176
 
@@ -120,7 +118,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
      * @param arg the augend.
      * @return the sum.
      */
-    public operator fun NDStructure<T>.plus(arg: T): NDStructure<T> = this.map() { value -> add(arg, value) }
+    public operator fun NDStructure<T>.plus(arg: T): NDStructure<T> = this.map { value -> add(arg, value) }
 
     /**
      * Subtracts an element from ND structure of it.
@@ -129,7 +127,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
      * @param arg the divisor.
      * @return the quotient.
      */
-    public operator fun NDStructure<T>.minus(arg: T): NDStructure<T> = this.map() { value -> add(arg, -value) }
+    public operator fun NDStructure<T>.minus(arg: T): NDStructure<T> = this.map { value -> add(arg, -value) }
 
     /**
      * Adds an element to ND structure of it.
@@ -138,7 +136,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
      * @param arg the augend.
      * @return the sum.
      */
-    public operator fun T.plus(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> add(this@plus, value) }
+    public operator fun T.plus(arg: NDStructure<T>): NDStructure<T> = arg.map { value -> add(this@plus, value) }
 
     /**
      * Subtracts an ND structure from an element of it.
@@ -147,7 +145,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
      * @param arg the divisor.
      * @return the quotient.
      */
-    public operator fun T.minus(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> add(-this@minus, value) }
+    public operator fun T.minus(arg: NDStructure<T>): NDStructure<T> = arg.map { value -> add(-this@minus, value) }
 
     public companion object
 }
@@ -159,7 +157,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
  * @param N the type of ND structure.
  * @param R the type of ring of structure elements.
  */
-public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
+public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDGroup<T, R> {
     /**
      * Element-wise multiplication.
      *
@@ -179,7 +177,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
      * @param arg the multiplier.
      * @return the product.
      */
-    public operator fun NDStructure<T>.times(arg: T): NDStructure<T> = this.map() { value -> multiply(arg, value) }
+    public operator fun NDStructure<T>.times(arg: T): NDStructure<T> = this.map { value -> multiply(arg, value) }
 
     /**
      * Multiplies an element by a ND structure of it.
@@ -188,7 +186,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
      * @param arg the multiplier.
      * @return the product.
      */
-    public operator fun T.times(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> multiply(this@times, value) }
+    public operator fun T.times(arg: NDStructure<T>): NDStructure<T> = arg.map { value -> multiply(this@times, value) }
 
     public companion object
 }
@@ -200,7 +198,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
  * @param N the type of ND structure.
  * @param F the type field of structure elements.
  */
-public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F> {
+public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>, ScaleOperations<NDStructure<T>> {
     /**
      * Element-wise division.
      *
@@ -219,7 +217,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>
      * @param arg the divisor.
      * @return the quotient.
      */
-    public operator fun NDStructure<T>.div(arg: T): NDStructure<T> = this.map() { value -> divide(arg, value) }
+    public operator fun NDStructure<T>.div(arg: T): NDStructure<T> = this.map { value -> divide(arg, value) }
 
     /**
      * Divides an element by an ND structure of it.
@@ -228,7 +226,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>
      * @param arg the divisor.
      * @return the quotient.
      */
-    public operator fun T.div(arg: NDStructure<T>): NDStructure<T> = arg.map() { divide(it, this@div) }
+    public operator fun T.div(arg: NDStructure<T>): NDStructure<T> = arg.map { divide(it, this@div) }
 
 //    @ThreadLocal
 //    public companion object {
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt
index e458d0606..83bf28d14 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt
@@ -52,7 +52,7 @@ public interface NDStructure<T> {
      * optimize operations and performance. If the feature is not present, null is defined.
      */
     @UnstableKMathAPI
-    public fun <T : Any> getFeature(type: KClass<T>): T? = null
+    public fun <F : Any> getFeature(type: KClass<F>): F? = null
 
     public companion object {
         /**
@@ -74,7 +74,7 @@ public interface NDStructure<T> {
          *
          * Strides should be reused if possible.
          */
-        public fun <T> build(
+        public fun <T> buffered(
             strides: Strides,
             bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
             initializer: (IntArray) -> T,
@@ -94,11 +94,11 @@ public interface NDStructure<T> {
             crossinline initializer: (IntArray) -> T,
         ): NDBuffer<T> = NDBuffer(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
 
-        public fun <T> build(
+        public fun <T> buffered(
             shape: IntArray,
             bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
             initializer: (IntArray) -> T,
-        ): NDBuffer<T> = build(DefaultStrides(shape), bufferFactory, initializer)
+        ): NDBuffer<T> = buffered(DefaultStrides(shape), bufferFactory, initializer)
 
         public inline fun <reified T : Any> auto(
             shape: IntArray,
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt
index 73ba337ae..2165aea22 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt
@@ -2,8 +2,9 @@ package space.kscience.kmath.nd
 
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.NumbersAddOperations
 import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.RingWithNumbers
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.RealBuffer
 import kotlin.contracts.InvocationKind
@@ -13,7 +14,8 @@ import kotlin.contracts.contract
 public class RealNDField(
     shape: IntArray,
 ) : BufferedNDField<Double, RealField>(shape, RealField, Buffer.Companion::real),
-    RingWithNumbers<NDStructure<Double>>,
+    NumbersAddOperations<NDStructure<Double>>,
+    ScaleOperations<NDStructure<Double>>,
     ExtendedField<NDStructure<Double>> {
 
     override val zero: NDBuffer<Double> by lazy { produce { zero } }
@@ -75,6 +77,8 @@ public class RealNDField(
         return NDBuffer(strides, buffer)
     }
 
+    override fun scale(a: NDStructure<Double>, value: Double): NDStructure<Double> = a.map { it * value }
+
     override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map { power(it, pow) }
 
     override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(it) }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt
index 30960a090..2085840a4 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt
@@ -1,7 +1,7 @@
 package space.kscience.kmath.nd
 
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.operations.RingWithNumbers
+import space.kscience.kmath.operations.NumbersAddOperations
 import space.kscience.kmath.operations.ShortRing
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.ShortBuffer
@@ -12,7 +12,7 @@ import kotlin.contracts.contract
 public class ShortNDRing(
     shape: IntArray,
 ) : BufferedNDRing<Short, ShortRing>(shape, ShortRing, Buffer.Companion::auto),
-    RingWithNumbers<NDStructure<Short>> {
+    NumbersAddOperations<NDStructure<Short>> {
 
     override val zero: NDBuffer<Short> by lazy { produce { zero } }
     override val one: NDBuffer<Short> by lazy { produce { one } }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt
index e83485ff0..1335a4933 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt
@@ -45,10 +45,12 @@ private inline class Buffer1DWrapper<T>(val buffer: Buffer<T>) : Structure1D<T>
 /**
  * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch
  */
-public fun <T> NDStructure<T>.as1D(): Structure1D<T> = if (shape.size == 1) {
-    if (this is NDBuffer) Buffer1DWrapper(this.buffer) else Structure1DWrapper(this)
-} else
-    error("Can't create 1d-structure from ${shape.size}d-structure")
+public fun <T> NDStructure<T>.as1D(): Structure1D<T> = this as? Structure1D<T> ?: if (shape.size == 1) {
+    when (this) {
+        is NDBuffer -> Buffer1DWrapper(this.buffer)
+        else -> Structure1DWrapper(this)
+    }
+} else error("Can't create 1d-structure from ${shape.size}d-structure")
 
 /**
  * Represent this buffer as 1D structure
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt
index fcc8c0d7e..e9f8234e5 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt
@@ -1,9 +1,9 @@
 package space.kscience.kmath.nd
 
-import space.kscience.kmath.linear.BufferMatrix
-import space.kscience.kmath.linear.RealMatrixContext
+import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.VirtualBuffer
+import kotlin.reflect.KClass
 
 /**
  * A structure that is guaranteed to be two-dimensional.
@@ -26,14 +26,14 @@ public interface Structure2D<T> : NDStructure<T> {
     /**
      * The buffer of rows of this structure. It gets elements from the structure dynamically.
      */
-    public val rows: Buffer<Buffer<T>>
-        get() = VirtualBuffer(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } }
+    public val rows: List<Buffer<T>>
+        get() = List(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } }
 
     /**
      * The buffer of columns of this structure. It gets elements from the structure dynamically.
      */
-    public val columns: Buffer<Buffer<T>>
-        get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } }
+    public val columns: List<Buffer<T>>
+        get() = List(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } }
 
     /**
      * Retrieves an element from the structure by two indices.
@@ -54,21 +54,13 @@ public interface Structure2D<T> : NDStructure<T> {
             for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j))
     }
 
-    public companion object {
-        public inline fun real(
-            rows: Int,
-            columns: Int,
-            crossinline init: (i: Int, j: Int) -> Double,
-        ): BufferMatrix<Double> = RealMatrixContext.produce(rows,columns) { i, j ->
-            init(i, j)
-        }
-    }
+    public companion object
 }
 
 /**
  * A 2D wrapper for nd-structure
  */
-private inline class Structure2DWrapper<T>(val structure: NDStructure<T>) : Structure2D<T> {
+private class Structure2DWrapper<T>(val structure: NDStructure<T>) : Structure2D<T> {
     override val shape: IntArray get() = structure.shape
 
     override val rowNum: Int get() = shape[0]
@@ -76,20 +68,22 @@ private inline class Structure2DWrapper<T>(val structure: NDStructure<T>) : Stru
 
     override operator fun get(i: Int, j: Int): T = structure[i, j]
 
+    @UnstableKMathAPI
+    override fun <F : Any> getFeature(type: KClass<F>): F? = structure.getFeature(type)
+
     override fun elements(): Sequence<Pair<IntArray, T>> = structure.elements()
+
+    override fun equals(other: Any?): Boolean = structure == other
+
+    override fun hashCode(): Int = structure.hashCode()
 }
 
 /**
  * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch
  */
-public fun <T> NDStructure<T>.as2D(): Structure2D<T> = if (shape.size == 2)
-    Structure2DWrapper(this)
-else
-    error("Can't create 2d-structure from ${shape.size}d-structure")
+public fun <T> NDStructure<T>.as2D(): Structure2D<T> = this as? Structure2D<T> ?: when (shape.size) {
+    2 -> Structure2DWrapper(this)
+    else -> error("Can't create 2d-structure from ${shape.size}d-structure")
+}
 
-/**
- * Alias for [Structure2D] with more familiar name.
- *
- * @param T the type of items in the matrix.
- */
-public typealias Matrix<T> = Structure2D<T>
+internal fun <T> Structure2D<T>.unwrap(): NDStructure<T> = if (this is Structure2DWrapper) structure else this
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt
index 572f7089a..9f57bc4c1 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt
@@ -87,10 +87,11 @@ public interface Algebra<T> {
      * @param right the second argument of operation.
      * @return a result of operation.
      */
-    public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right)
+    public fun binaryOperation(operation: String, left: T, right: T): T =
+        binaryOperationFunction(operation)(left, right)
 }
 
-public fun <T: Any> Algebra<T>.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity)
+public fun <T : Any> Algebra<T>.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity)
 
 /**
  * Call a block with an [Algebra] as receiver.
@@ -104,7 +105,7 @@ public inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = r
  *
  * @param T the type of element of this semispace.
  */
-public interface SpaceOperations<T> : Algebra<T> {
+public interface GroupOperations<T> : Algebra<T> {
     /**
      * Addition of two elements.
      *
@@ -114,15 +115,6 @@ public interface SpaceOperations<T> : Algebra<T> {
      */
     public fun add(a: T, b: T): T
 
-    /**
-     * Multiplication of element by scalar.
-     *
-     * @param a the multiplier.
-     * @param k the multiplicand.
-     * @return the produce.
-     */
-    public fun multiply(a: T, k: Number): T
-
     // Operations to be performed in this context. Could be moved to extensions in case of KEEP-176
 
     /**
@@ -131,7 +123,7 @@ public interface SpaceOperations<T> : Algebra<T> {
      * @receiver this value.
      * @return the additive inverse of this value.
      */
-    public operator fun T.unaryMinus(): T = multiply(this, -1.0)
+    public operator fun T.unaryMinus(): T
 
     /**
      * Returns this value.
@@ -159,36 +151,8 @@ public interface SpaceOperations<T> : Algebra<T> {
      */
     public operator fun T.minus(b: T): T = add(this, -b)
 
-    /**
-     * Multiplication of this element by a scalar.
-     *
-     * @receiver the multiplier.
-     * @param k the multiplicand.
-     * @return the product.
-     */
-    public operator fun T.times(k: Number): T = multiply(this, k)
-
-    /**
-     * Division of this element by scalar.
-     *
-     * @receiver the dividend.
-     * @param k the divisor.
-     * @return the quotient.
-     */
-    @Deprecated("Dividing not allowed in a Ring")
-    public operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble())
-
-    /**
-     * Multiplication of this number by element.
-     *
-     * @receiver the multiplier.
-     * @param b the multiplicand.
-     * @return the product.
-     */
-    public operator fun Number.times(b: T): T = b * this
-
     public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
-        PLUS_OPERATION -> { arg -> arg }
+        PLUS_OPERATION -> { arg -> +arg }
         MINUS_OPERATION -> { arg -> -arg }
         else -> super.unaryOperationFunction(operation)
     }
@@ -213,12 +177,11 @@ public interface SpaceOperations<T> : Algebra<T> {
 }
 
 /**
- * Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add] and
- * scalar multiplication [multiply].
+ * Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add].
  *
  * @param T the type of element of this semispace.
  */
-public interface Space<T> : SpaceOperations<T> {
+public interface Group<T> : GroupOperations<T> {
     /**
      * The neutral element of addition.
      */
@@ -231,7 +194,7 @@ public interface Space<T> : SpaceOperations<T> {
  *
  * @param T the type of element of this semiring.
  */
-public interface RingOperations<T> : SpaceOperations<T> {
+public interface RingOperations<T> : GroupOperations<T> {
     /**
      * Multiplies two elements.
      *
@@ -267,7 +230,7 @@ public interface RingOperations<T> : SpaceOperations<T> {
  *
  * @param T the type of element of this ring.
  */
-public interface Ring<T> : Space<T>, RingOperations<T> {
+public interface Ring<T> : Group<T>, RingOperations<T> {
     /**
      * neutral operation for multiplication
      */
@@ -318,13 +281,6 @@ public interface FieldOperations<T> : RingOperations<T> {
  *
  * @param T the type of element of this semifield.
  */
-public interface Field<T> : Ring<T>, FieldOperations<T> {
-    /**
-     * Division of element by scalar.
-     *
-     * @receiver the dividend.
-     * @param b the divisor.
-     * @return the quotient.
-     */
-    public operator fun Number.div(b: T): T = this * divide(one, b)
-}
+public interface Field<T> : Ring<T>, FieldOperations<T>, ScaleOperations<T>, NumericAlgebra<T> {
+    override fun number(value: Number): T = scale(one, value.toDouble())
+}
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt
index 629c4de1b..3e42ac094 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt
@@ -14,24 +14,24 @@ public interface AlgebraElement<T, C : Algebra<T>> {
      */
     public val context: C
 }
-
-/**
- * Divides this element by number.
- *
- * @param k the divisor.
- * @return the quotient.
- */
-public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.div(k: Number): T =
-    context.multiply(this, 1.0 / k.toDouble())
-
-/**
- * Multiplies this element by number.
- *
- * @param k the multiplicand.
- * @return the product.
- */
-public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number): T =
-    context.multiply(this, k.toDouble())
+//
+///**
+// * Divides this element by number.
+// *
+// * @param k the divisor.
+// * @return the quotient.
+// */
+//public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.div(k: Number): T =
+//    context.multiply(this, 1.0 / k.toDouble())
+//
+///**
+// * Multiplies this element by number.
+// *
+// * @param k the multiplicand.
+// * @return the product.
+// */
+//public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number): T =
+//    context.multiply(this, k.toDouble())
 
 /**
  * Subtracts element from this one.
@@ -39,8 +39,9 @@ public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number):
  * @param b the subtrahend.
  * @return the difference.
  */
-public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.minus(b: T): T =
-    context.add(this, context.multiply(b, -1.0))
+@UnstableKMathAPI
+public operator fun <T : AlgebraElement<T, S>, S : NumbersAddOperations<T>> T.minus(b: T): T =
+    context.add(this, context.run { -b})
 
 /**
  * Adds element to this one.
@@ -48,14 +49,14 @@ public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.minus(b: T): T =
  * @param b the augend.
  * @return the sum.
  */
-public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.plus(b: T): T =
+public operator fun <T : AlgebraElement<T, S>, S : Group<T>> T.plus(b: T): T =
     context.add(this, b)
 
-/**
- * Number times element
- */
-public operator fun <T : AlgebraElement<T, S>, S : Space<T>> Number.times(element: T): T =
-    element.times(this)
+///**
+// * Number times element
+// */
+//public operator fun <T : AlgebraElement<T, S>, S : Space<T>> Number.times(element: T): T =
+//    element.times(this)
 
 
 /**
@@ -79,14 +80,14 @@ public operator fun <T : AlgebraElement<T, F>, F : Field<T>> T.div(b: T): T =
 
 
 /**
- * The element of [Space].
+ * The element of [Group].
  *
  * @param T the type of space operation results.
  * @param I self type of the element. Needed for static type checking.
  * @param S the type of space.
  */
 @UnstableKMathAPI
-public interface SpaceElement<T : SpaceElement<T, S>, S : Space<T>> : AlgebraElement<T, S>
+public interface SpaceElement<T : SpaceElement<T, S>, S : Group<T>> : AlgebraElement<T, S>
 
 /**
  * The element of [Ring].
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt
index c21260b82..7e6a2eb81 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt
@@ -21,29 +21,28 @@ public typealias TBase = ULong
  * @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai)
  */
 @OptIn(UnstableKMathAPI::class)
-public object BigIntField : Field<BigInt>, RingWithNumbers<BigInt> {
+public object BigIntField : Field<BigInt>, NumbersAddOperations<BigInt>, ScaleOperations<BigInt> {
     override val zero: BigInt = BigInt.ZERO
     override val one: BigInt = BigInt.ONE
 
-    override fun add(a: BigInt, b: BigInt): BigInt = a.plus(b)
     override fun number(value: Number): BigInt = value.toLong().toBigInt()
 
-    override fun multiply(a: BigInt, k: Number): BigInt = a.times(number(k))
-
+    @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+    override fun BigInt.unaryMinus(): BigInt = -this
+    override fun add(a: BigInt, b: BigInt): BigInt = a.plus(b)
+    override fun scale(a: BigInt, value: Double): BigInt = a.times(number(value))
     override fun multiply(a: BigInt, b: BigInt): BigInt = a.times(b)
+    override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b)
 
     public operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer")
-
     public operator fun String.unaryMinus(): BigInt =
         -(this.parseBigInteger() ?: error("Can't parse $this as big integer"))
-
-    override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b)
 }
 
 public class BigInt internal constructor(
     private val sign: Byte,
-    private val magnitude: Magnitude
-    ) : Comparable<BigInt> {
+    private val magnitude: Magnitude,
+) : Comparable<BigInt> {
     public override fun compareTo(other: BigInt): Int = when {
         (sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0
         sign < other.sign -> -1
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt
index 81f4c1fdf..bd5f5951f 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt
@@ -81,14 +81,53 @@ public interface NumericAlgebra<T> : Algebra<T> {
         rightSideNumberOperationFunction(operation)(left, right)
 }
 
+/**
+ * Scale by scalar operations
+ */
+public interface ScaleOperations<T> : Algebra<T> {
+    /**
+     * Scaling an element by a scalar.
+     *
+     * @param a the multiplier.
+     * @param value the multiplicand.
+     * @return the produce.
+     */
+    public fun scale(a: T, value: Double): T
+
+    /**
+     * Multiplication of this element by a scalar.
+     *
+     * @receiver the multiplier.
+     * @param k the multiplicand.
+     * @return the product.
+     */
+    public operator fun T.times(k: Number): T = scale(this, k.toDouble())
+
+    /**
+     * Division of this element by scalar.
+     *
+     * @receiver the dividend.
+     * @param k the divisor.
+     * @return the quotient.
+     */
+    public operator fun T.div(k: Number): T = scale(this, 1.0 / k.toDouble())
+
+    /**
+     * Multiplication of this number by element.
+     *
+     * @receiver the multiplier.
+     * @param b the multiplicand.
+     * @return the product.
+     */
+    public operator fun Number.times(b: T): T = b * this
+}
+
 /**
  * A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1`
  * TODO to be removed and replaced by extensions after multiple receivers are there
  */
 @UnstableKMathAPI
-public interface RingWithNumbers<T>: Ring<T>, NumericAlgebra<T>{
-    public override fun number(value: Number): T = one * value
-
+public interface NumbersAddOperations<T> : Group<T>, NumericAlgebra<T> {
     /**
      * Addition of element and scalar.
      *
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt
index 6cb329695..6e6249dfe 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt
@@ -107,111 +107,6 @@ public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> acos(arg: T):
 @UnstableKMathAPI
 public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg)
 
-/**
- * A container for hyperbolic trigonometric operations for specific type.
- *
- * @param T the type of element of this structure.
- */
-public interface HyperbolicOperations<T> : Algebra<T> {
-    /**
-     * Computes the hyperbolic sine of [arg].
-     */
-    public fun sinh(arg: T): T
-
-    /**
-     * Computes the hyperbolic cosine of [arg].
-     */
-    public fun cosh(arg: T): T
-
-    /**
-     * Computes the hyperbolic tangent of [arg].
-     */
-    public fun tanh(arg: T): T
-
-    /**
-     * Computes the inverse hyperbolic sine of [arg].
-     */
-    public fun asinh(arg: T): T
-
-    /**
-     * Computes the inverse hyperbolic cosine of [arg].
-     */
-    public fun acosh(arg: T): T
-
-    /**
-     * Computes the inverse hyperbolic tangent of [arg].
-     */
-    public fun atanh(arg: T): T
-
-    public companion object {
-        /**
-         * The identifier of hyperbolic sine.
-         */
-        public const val SINH_OPERATION: String = "sinh"
-
-        /**
-         * The identifier of hyperbolic cosine.
-         */
-        public const val COSH_OPERATION: String = "cosh"
-
-        /**
-         * The identifier of hyperbolic tangent.
-         */
-        public const val TANH_OPERATION: String = "tanh"
-
-        /**
-         * The identifier of inverse hyperbolic sine.
-         */
-        public const val ASINH_OPERATION: String = "asinh"
-
-        /**
-         * The identifier of inverse hyperbolic cosine.
-         */
-        public const val ACOSH_OPERATION: String = "acosh"
-
-        /**
-         * The identifier of inverse hyperbolic tangent.
-         */
-        public const val ATANH_OPERATION: String = "atanh"
-    }
-}
-
-/**
- * Computes the hyperbolic sine of [arg].
- */
-@UnstableKMathAPI
-public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
-
-/**
- * Computes the hyperbolic cosine of [arg].
- */
-@UnstableKMathAPI
-public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
-
-/**
- * Computes the hyperbolic tangent of [arg].
- */
-@UnstableKMathAPI
-public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
-
-/**
- * Computes the inverse hyperbolic sine of [arg].
- */
-@UnstableKMathAPI
-public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
-
-/**
- * Computes the inverse hyperbolic cosine of [arg].
- */
-@UnstableKMathAPI
-public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
-
-/**
- * Computes the inverse hyperbolic tangent of [arg].
- */
-@UnstableKMathAPI
-public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
-
 /**
  * A context extension to include power operations based on exponentiation.
  *
@@ -284,6 +179,36 @@ public interface ExponentialOperations<T> : Algebra<T> {
      */
     public fun ln(arg: T): T
 
+    /**
+     * Computes the hyperbolic sine of [arg].
+     */
+    public fun sinh(arg: T): T
+
+    /**
+     * Computes the hyperbolic cosine of [arg].
+     */
+    public fun cosh(arg: T): T
+
+    /**
+     * Computes the hyperbolic tangent of [arg].
+     */
+    public fun tanh(arg: T): T
+
+    /**
+     * Computes the inverse hyperbolic sine of [arg].
+     */
+    public fun asinh(arg: T): T
+
+    /**
+     * Computes the inverse hyperbolic cosine of [arg].
+     */
+    public fun acosh(arg: T): T
+
+    /**
+     * Computes the inverse hyperbolic tangent of [arg].
+     */
+    public fun atanh(arg: T): T
+
     public companion object {
         /**
          * The identifier of exponential function.
@@ -294,6 +219,36 @@ public interface ExponentialOperations<T> : Algebra<T> {
          * The identifier of natural logarithm.
          */
         public const val LN_OPERATION: String = "ln"
+
+        /**
+         * The identifier of hyperbolic sine.
+         */
+        public const val SINH_OPERATION: String = "sinh"
+
+        /**
+         * The identifier of hyperbolic cosine.
+         */
+        public const val COSH_OPERATION: String = "cosh"
+
+        /**
+         * The identifier of hyperbolic tangent.
+         */
+        public const val TANH_OPERATION: String = "tanh"
+
+        /**
+         * The identifier of inverse hyperbolic sine.
+         */
+        public const val ASINH_OPERATION: String = "asinh"
+
+        /**
+         * The identifier of inverse hyperbolic cosine.
+         */
+        public const val ACOSH_OPERATION: String = "acosh"
+
+        /**
+         * The identifier of inverse hyperbolic tangent.
+         */
+        public const val ATANH_OPERATION: String = "atanh"
     }
 }
 
@@ -309,6 +264,43 @@ public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> exp(arg: T): T
 @UnstableKMathAPI
 public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
 
+
+/**
+ * Computes the hyperbolic sine of [arg].
+ */
+@UnstableKMathAPI
+public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
+
+/**
+ * Computes the hyperbolic cosine of [arg].
+ */
+@UnstableKMathAPI
+public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
+
+/**
+ * Computes the hyperbolic tangent of [arg].
+ */
+@UnstableKMathAPI
+public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
+
+/**
+ * Computes the inverse hyperbolic sine of [arg].
+ */
+@UnstableKMathAPI
+public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
+
+/**
+ * Computes the inverse hyperbolic cosine of [arg].
+ */
+@UnstableKMathAPI
+public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
+
+/**
+ * Computes the inverse hyperbolic tangent of [arg].
+ */
+@UnstableKMathAPI
+public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
+
 /**
  * A container for norm functional on element.
  *
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt
index ae1267d2b..52a0dec6f 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt
@@ -1,47 +1,49 @@
 package space.kscience.kmath.operations
 
 /**
- * Returns the sum of all elements in the iterable in this [Space].
+ * Returns the sum of all elements in the iterable in this [Group].
  *
  * @receiver the algebra that provides addition.
  * @param data the iterable to sum up.
  * @return the sum.
  */
-public fun <T> Space<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> add(left, right) }
+public fun <T> Group<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> add(left, right) }
 
 /**
- * Returns the sum of all elements in the sequence in this [Space].
+ * Returns the sum of all elements in the sequence in this [Group].
  *
  * @receiver the algebra that provides addition.
  * @param data the sequence to sum up.
  * @return the sum.
  */
-public fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> add(left, right) }
+public fun <T> Group<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> add(left, right) }
 
 /**
- * Returns an average value of elements in the iterable in this [Space].
+ * Returns an average value of elements in the iterable in this [Group].
  *
  * @receiver the algebra that provides addition and division.
  * @param data the iterable to find average.
  * @return the average value.
  * @author Iaroslav Postovalov
  */
-public fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
+public fun <T, S> S.average(data: Iterable<T>): T where S : Group<T>, S : ScaleOperations<T> =
+    sum(data) / data.count()
 
 /**
- * Returns an average value of elements in the sequence in this [Space].
+ * Returns an average value of elements in the sequence in this [Group].
  *
  * @receiver the algebra that provides addition and division.
  * @param data the sequence to find average.
  * @return the average value.
  * @author Iaroslav Postovalov
  */
-public fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
+public fun <T, S> S.average(data: Sequence<T>): T where S : Group<T>, S : ScaleOperations<T> =
+    sum(data) / data.count()
 
 /**
  * Absolute of the comparable [value]
  */
-public fun <T : Comparable<T>> Space<T>.abs(value: T): T = if (value > zero) value else -value
+public fun <T : Comparable<T>> Group<T>.abs(value: T): T = if (value > zero) value else -value
 
 /**
  * Returns the sum of all elements in the iterable in provided space.
@@ -50,7 +52,7 @@ public fun <T : Comparable<T>> Space<T>.abs(value: T): T = if (value > zero) val
  * @param space the algebra that provides addition.
  * @return the sum.
  */
-public fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
+public fun <T> Iterable<T>.sumWith(space: Group<T>): T = space.sum(this)
 
 /**
  * Returns the sum of all elements in the sequence in provided space.
@@ -59,27 +61,29 @@ public fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
  * @param space the algebra that provides addition.
  * @return the sum.
  */
-public fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
+public fun <T> Sequence<T>.sumWith(space: Group<T>): T = space.sum(this)
 
 /**
- * Returns an average value of elements in the iterable in this [Space].
+ * Returns an average value of elements in the iterable in this [Group].
  *
  * @receiver the iterable to find average.
  * @param space the algebra that provides addition and division.
  * @return the average value.
  * @author Iaroslav Postovalov
  */
-public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
+public fun <T, S> Iterable<T>.averageWith(space: S): T  where S : Group<T>, S : ScaleOperations<T>  =
+    space.average(this)
 
 /**
- * Returns an average value of elements in the sequence in this [Space].
+ * Returns an average value of elements in the sequence in this [Group].
  *
  * @receiver the sequence to find average.
  * @param space the algebra that provides addition and division.
  * @return the average value.
  * @author Iaroslav Postovalov
  */
-public fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
+public fun <T, S> Sequence<T>.averageWith(space: S): T  where S : Group<T>, S : ScaleOperations<T>  =
+    space.average(this)
 
 //TODO optimized power operation
 
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt
index aa62715d1..4841e78d6 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt
@@ -8,7 +8,6 @@ import kotlin.math.pow as kpow
 public interface ExtendedFieldOperations<T> :
     FieldOperations<T>,
     TrigonometricOperations<T>,
-    HyperbolicOperations<T>,
     PowerOperations<T>,
     ExponentialOperations<T> {
     public override fun tan(arg: T): T = sin(arg) / cos(arg)
@@ -21,15 +20,15 @@ public interface ExtendedFieldOperations<T> :
         TrigonometricOperations.ACOS_OPERATION -> ::acos
         TrigonometricOperations.ASIN_OPERATION -> ::asin
         TrigonometricOperations.ATAN_OPERATION -> ::atan
-        HyperbolicOperations.COSH_OPERATION -> ::cosh
-        HyperbolicOperations.SINH_OPERATION -> ::sinh
-        HyperbolicOperations.TANH_OPERATION -> ::tanh
-        HyperbolicOperations.ACOSH_OPERATION -> ::acosh
-        HyperbolicOperations.ASINH_OPERATION -> ::asinh
-        HyperbolicOperations.ATANH_OPERATION -> ::atanh
         PowerOperations.SQRT_OPERATION -> ::sqrt
         ExponentialOperations.EXP_OPERATION -> ::exp
         ExponentialOperations.LN_OPERATION -> ::ln
+        ExponentialOperations.COSH_OPERATION -> ::cosh
+        ExponentialOperations.SINH_OPERATION -> ::sinh
+        ExponentialOperations.TANH_OPERATION -> ::tanh
+        ExponentialOperations.ACOSH_OPERATION -> ::acosh
+        ExponentialOperations.ASINH_OPERATION -> ::asinh
+        ExponentialOperations.ATANH_OPERATION -> ::atanh
         else -> super<FieldOperations>.unaryOperationFunction(operation)
     }
 }
@@ -37,18 +36,18 @@ public interface ExtendedFieldOperations<T> :
 /**
  * Advanced Number-like field that implements basic operations.
  */
-public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T> {
-    public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
-    public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
+public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T>, ScaleOperations<T> {
+    public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0
+    public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0
     public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
     public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg)
     public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
-    public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
+    public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0
 
     public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
         when (operation) {
             PowerOperations.POW_OPERATION -> ::power
-            else -> super.rightSideNumberOperationFunction(operation)
+            else -> super<Field>.rightSideNumberOperationFunction(operation)
         }
 }
 
@@ -56,28 +55,27 @@ public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, Numeri
  * A field for [Double] without boxing. Does not produce appropriate field element.
  */
 @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
-public object RealField : ExtendedField<Double>, Norm<Double, Double> {
-    public override val zero: Double
-        get() = 0.0
-
-    public override val one: Double
-        get() = 1.0
+public object RealField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
+    public override val zero: Double = 0.0
+    public override val one: Double = 1.0
 
     override fun number(value: Number): Double = value.toDouble()
 
     public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
         when (operation) {
             PowerOperations.POW_OPERATION -> ::power
-            else -> super.binaryOperationFunction(operation)
+            else -> super<ExtendedField>.binaryOperationFunction(operation)
         }
 
     public override inline fun add(a: Double, b: Double): Double = a + b
-    public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble()
+//    public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble()
+//    override fun divide(a: Double, k: Number): Double = a / k.toDouble()
 
     public override inline fun multiply(a: Double, b: Double): Double = a * b
-
     public override inline fun divide(a: Double, b: Double): Double = a / b
 
+    override fun scale(a: Double, value: Double): Double = a * value
+
     public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg)
     public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg)
     public override inline fun tan(arg: Double): Double = kotlin.math.tan(arg)
@@ -110,11 +108,8 @@ public object RealField : ExtendedField<Double>, Norm<Double, Double> {
  */
 @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
 public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
-    public override val zero: Float
-        get() = 0.0f
-
-    public override val one: Float
-        get() = 1.0f
+    public override val zero: Float = 0.0f
+    public override val one: Float = 1.0f
 
     override fun number(value: Number): Float = value.toFloat()
 
@@ -125,7 +120,7 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
         }
 
     public override inline fun add(a: Float, b: Float): Float = a + b
-    public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat()
+    override fun scale(a: Float, value: Double): Float = a * value.toFloat()
 
     public override inline fun multiply(a: Float, b: Float): Float = a * b
 
@@ -170,12 +165,8 @@ public object IntRing : Ring<Int>, Norm<Int, Int>, NumericAlgebra<Int> {
         get() = 1
 
     override fun number(value: Number): Int = value.toInt()
-
     public override inline fun add(a: Int, b: Int): Int = a + b
-    public override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a
-
     public override inline fun multiply(a: Int, b: Int): Int = a * b
-
     public override inline fun norm(arg: Int): Int = abs(arg)
 
     public override inline fun Int.unaryMinus(): Int = -this
@@ -196,12 +187,8 @@ public object ShortRing : Ring<Short>, Norm<Short, Short>, NumericAlgebra<Short>
         get() = 1
 
     override fun number(value: Number): Short = value.toShort()
-
     public override inline fun add(a: Short, b: Short): Short = (a + b).toShort()
-    public override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort()
-
     public override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort()
-
     public override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
 
     public override inline fun Short.unaryMinus(): Short = (-this).toShort()
@@ -222,12 +209,8 @@ public object ByteRing : Ring<Byte>, Norm<Byte, Byte>, NumericAlgebra<Byte> {
         get() = 1
 
     override fun number(value: Number): Byte = value.toByte()
-
     public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte()
-    public override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte()
-
     public override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte()
-
     public override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
 
     public override inline fun Byte.unaryMinus(): Byte = (-this).toByte()
@@ -248,12 +231,8 @@ public object LongRing : Ring<Long>, Norm<Long, Long>, NumericAlgebra<Long> {
         get() = 1L
 
     override fun number(value: Number): Long = value.toLong()
-
     public override inline fun add(a: Long, b: Long): Long = a + b
-    public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong()
-
     public override inline fun multiply(a: Long, b: Long): Long = a * b
-
     public override fun norm(arg: Long): Long = abs(arg)
 
     public override inline fun Long.unaryMinus(): Long = (-this)
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt
index 2fccd2eeb..2bde18fce 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt
@@ -100,9 +100,29 @@ public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
 public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
 
 /**
- * Converts this [Buffer] to a new [List]
+ * Returns a new [List] containing all elements of this buffer.
  */
-public fun <T> Buffer<T>.toList(): List<T> = asSequence().toList()
+public fun <T> Buffer<T>.toList(): List<T> = when (this) {
+    is ArrayBuffer<T> -> array.toList()
+    is ListBuffer<T> -> list.toList()
+    is MutableListBuffer<T> -> list.toList()
+    else -> asSequence().toList()
+}
+
+/**
+ * Returns a new [MutableList] filled with all elements of this buffer.
+ */
+public fun <T> Buffer<T>.toMutableList(): MutableList<T> = when (this) {
+    is ArrayBuffer<T> -> array.toMutableList()
+    is ListBuffer<T> -> list.toMutableList()
+    is MutableListBuffer<T> -> list.toMutableList()
+    else -> asSequence().toMutableList()
+}
+
+/**
+ * Returns a new [Array] containing all elements of this buffer.
+ */
+public inline fun <reified T> Buffer<T>.toTypedArray(): Array<T> = asSequence().toList().toTypedArray()
 
 /**
  * Returns an [IntRange] of the valid indices for this [Buffer].
@@ -222,7 +242,7 @@ public inline class MutableListBuffer<T>(public val list: MutableList<T>) : Muta
  * @param T the type of elements contained in the buffer.
  * @property array The underlying array.
  */
-public class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
+public class ArrayBuffer<T>(internal val array: Array<T>) : MutableBuffer<T> {
     // Can't inline because array is invariant
     override val size: Int
         get() = array.size
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt
index fd440a344..0910b2034 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt
@@ -13,10 +13,10 @@ internal class BufferAccessor2D<T : Any>(
     public val colNum: Int,
     val factory: MutableBufferFactory<T>,
 ) {
-    public operator fun Buffer<T>.get(i: Int, j: Int): T = get(i + colNum * j)
+    public operator fun Buffer<T>.get(i: Int, j: Int): T = get(i*colNum + j)
 
     public operator fun MutableBuffer<T>.set(i: Int, j: Int, value: T) {
-        set(i + colNum * j, value)
+        set(i*colNum + j, value)
     }
 
     public inline fun create(crossinline init: (i: Int, j: Int) -> T): MutableBuffer<T> =
@@ -25,7 +25,7 @@ internal class BufferAccessor2D<T : Any>(
     public fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] }
 
     //TODO optimize wrapper
-    public fun MutableBuffer<T>.collect(): Structure2D<T> = NDStructure.build(
+    public fun MutableBuffer<T>.collect(): Structure2D<T> = NDStructure.buffered(
         DefaultStrides(intArrayOf(rowNum, colNum)),
         factory
     ) { (i, j) ->
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt
index 3839be8e1..9fc7d55f3 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt
@@ -36,10 +36,12 @@ public inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer = Fl
 public fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats)
 
 /**
- * Returns a [FloatArray] containing all of the elements of this [MutableBuffer].
+ * Returns a new [FloatArray] containing all of the elements of this [Buffer].
  */
-public val MutableBuffer<out Float>.array: FloatArray
-    get() = (if (this is FloatBuffer) array else FloatArray(size) { get(it) })
+public fun Buffer<Float>.toFloatArray(): FloatArray = when(this) {
+    is FloatBuffer -> array.copyOf()
+    else -> FloatArray(size, ::get)
+}
 
 /**
  * Returns [FloatBuffer] over this array.
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt
index df3289a3e..d3d0f79a5 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt
@@ -35,10 +35,12 @@ public inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer = IntBuffe
 public fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints)
 
 /**
- * Returns a [IntArray] containing all of the elements of this [MutableBuffer].
+ * Returns a new [IntArray] containing all of the elements of this [Buffer].
  */
-public val MutableBuffer<out Int>.array: IntArray
-    get() = (if (this is IntBuffer) array else IntArray(size) { get(it) })
+public fun Buffer<Int>.toIntArray(): IntArray = when(this) {
+    is IntBuffer -> array.copyOf()
+    else -> IntArray(size, ::get)
+}
 
 /**
  * Returns [IntBuffer] over this array.
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt
index d07d44799..fec358421 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt
@@ -35,10 +35,12 @@ public inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer = LongB
 public fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs)
 
 /**
- * Returns a [IntArray] containing all of the elements of this [MutableBuffer].
+ * Returns a new [LongArray] containing all of the elements of this [Buffer].
  */
-public val MutableBuffer<out Long>.array: LongArray
-    get() = (if (this is LongBuffer) array else LongArray(size) { get(it) })
+public fun Buffer<Long>.toLongArray(): LongArray = when(this) {
+    is LongBuffer -> array.copyOf()
+    else -> LongArray(size, ::get)
+}
 
 /**
  * Returns [LongBuffer] over this array.
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt
index e53ed85c7..01b533138 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt
@@ -40,10 +40,12 @@ public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
 public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles)
 
 /**
- * Returns a [DoubleArray] containing all of the elements of this [MutableBuffer].
+ * Returns a new [DoubleArray] containing all of the elements of this [Buffer].
  */
-public val MutableBuffer<out Double>.array: DoubleArray
-    get() = (if (this is RealBuffer) array else DoubleArray(size) { get(it) })
+public fun Buffer<Double>.toDoubleArray(): DoubleArray = when(this) {
+    is RealBuffer -> array.copyOf()
+    else -> DoubleArray(size, ::get)
+}
 
 /**
  * Returns [RealBuffer] over this array.
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt
index 7351881ee..2a03a36e3 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt
@@ -8,6 +8,12 @@ import kotlin.math.*
  * [ExtendedFieldOperations] over [RealBuffer].
  */
 public object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
+    override fun Buffer<Double>.unaryMinus(): RealBuffer = if (this is RealBuffer) {
+        RealBuffer(size) { -array[it] }
+    } else {
+        RealBuffer(size) { -get(it) }
+    }
+
     public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
         require(b.size == a.size) {
             "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
@@ -19,15 +25,24 @@ public object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>
             RealBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] })
         } else RealBuffer(DoubleArray(a.size) { a[it] + b[it] })
     }
-
-    public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
-        val kValue = k.toDouble()
-
-        return if (a is RealBuffer) {
-            val aArray = a.array
-            RealBuffer(DoubleArray(a.size) { aArray[it] * kValue })
-        } else RealBuffer(DoubleArray(a.size) { a[it] * kValue })
-    }
+//
+//    public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
+//        val kValue = k.toDouble()
+//
+//        return if (a is RealBuffer) {
+//            val aArray = a.array
+//            RealBuffer(DoubleArray(a.size) { aArray[it] * kValue })
+//        } else RealBuffer(DoubleArray(a.size) { a[it] * kValue })
+//    }
+//
+//    public override fun divide(a: Buffer<Double>, k: Number): RealBuffer {
+//        val kValue = k.toDouble()
+//
+//        return if (a is RealBuffer) {
+//            val aArray = a.array
+//            RealBuffer(DoubleArray(a.size) { aArray[it] / kValue })
+//        } else RealBuffer(DoubleArray(a.size) { a[it] / kValue })
+//    }
 
     public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
         require(b.size == a.size) {
@@ -152,14 +167,22 @@ public class RealBufferField(public val size: Int) : ExtendedField<Buffer<Double
 
     override fun number(value: Number): Buffer<Double> = RealBuffer(size) { value.toDouble() }
 
+    override fun Buffer<Double>.unaryMinus(): Buffer<Double> = RealBufferFieldOperations.run {
+        -this@unaryMinus
+    }
+
     public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
         require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
         return RealBufferFieldOperations.add(a, b)
     }
 
-    public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
+    public override fun scale(a: Buffer<Double>, value: Double): RealBuffer {
         require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
-        return RealBufferFieldOperations.multiply(a, k)
+
+        return if (a is RealBuffer) {
+            val aArray = a.array
+            RealBuffer(DoubleArray(a.size) { aArray[it] * value })
+        } else RealBuffer(DoubleArray(a.size) { a[it] * value })
     }
 
     public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt
index afc472b72..77f128403 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt
@@ -33,10 +33,12 @@ public inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer = Sh
 public fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts)
 
 /**
- * Returns a [ShortArray] containing all of the elements of this [MutableBuffer].
+ * Returns a new [ShortArray] containing all of the elements of this [Buffer].
  */
-public val MutableBuffer<out Short>.array: ShortArray
-    get() = (if (this is ShortBuffer) array else ShortArray(size) { get(it) })
+public fun Buffer<Short>.toShortArray(): ShortArray = when(this) {
+    is ShortBuffer -> array.copyOf()
+    else -> ShortArray(size, ::get)
+}
 
 /**
  * Returns [ShortBuffer] over this array.
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt
new file mode 100644
index 000000000..459136631
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt
@@ -0,0 +1,7 @@
+package space.kscience.kmath.structures
+
+
+public inline fun <T : Any, reified R : Any> Buffer<T>.map(
+    bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
+    crossinline block: (T) -> R,
+): Buffer<R> = bufferFactory(size) { block(get(it)) }
\ No newline at end of file
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt
index c13850193..cf75eba3e 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt
@@ -11,9 +11,7 @@ class ExpressionFieldTest {
 
     @Test
     fun testExpression() {
-        val context = FunctionalExpressionField(RealField)
-
-        val expression = context {
+        val expression = FunctionalExpressionField(RealField).invoke {
             val x by binding()
             x * x + 2 * x + one
         }
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt
index 75967f024..097703f49 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt
@@ -1,23 +1,24 @@
 package space.kscience.kmath.linear
 
+import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.nd.NDStructure
 import space.kscience.kmath.nd.as2D
-import space.kscience.kmath.operations.invoke
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
+@UnstableKMathAPI
 @Suppress("UNUSED_VARIABLE")
 class MatrixTest {
     @Test
     fun testTranspose() {
-        val matrix = MatrixContext.real.one(3, 3)
+        val matrix = LinearSpace.real.one(3, 3)
         val transposed = matrix.transpose()
         assertEquals(matrix, transposed)
     }
 
     @Test
     fun testBuilder() {
-        val matrix = Matrix.build(2, 3)(
+        val matrix = LinearSpace.real.matrix(2, 3)(
             1.0, 0.0, 0.0,
             0.0, 1.0, 2.0
         )
@@ -39,7 +40,7 @@ class MatrixTest {
         infix fun Matrix<Double>.pow(power: Int): Matrix<Double> {
             var res = this
             repeat(power - 1) {
-                res = RealMatrixContext.invoke { res dot this@pow }
+                res = LinearSpace.real.run { res dot this@pow }
             }
             return res
         }
@@ -52,7 +53,7 @@ class MatrixTest {
         val firstMatrix = NDStructure.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D()
         val secondMatrix = NDStructure.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D()
 
-        MatrixContext.real.run {
+        LinearSpace.real.run {
 //            val firstMatrix = produce(2, 3) { i, j -> (i + j).toDouble() }
 //            val secondMatrix = produce(3, 2) { i, j -> (i + j).toDouble() }
             val result = firstMatrix dot secondMatrix
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt
index f1289801a..fb90b5e11 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt
@@ -1,29 +1,31 @@
 package space.kscience.kmath.linear
 
+import space.kscience.kmath.misc.UnstableKMathAPI
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
+@UnstableKMathAPI
 class RealLUSolverTest {
 
     @Test
     fun testInvertOne() {
-        val matrix = MatrixContext.real.one(2, 2)
-        val inverted = MatrixContext.real.inverseWithLup(matrix)
+        val matrix = LinearSpace.real.one(2, 2)
+        val inverted = LinearSpace.real.inverseWithLup(matrix)
         assertEquals(matrix, inverted)
     }
 
     @Test
     fun testDecomposition() {
-        val matrix = Matrix.square(
-            3.0, 1.0,
-            1.0, 3.0
-        )
+        LinearSpace.real.run {
+            val matrix = matrix(2,2)(
+                3.0, 1.0,
+                2.0, 3.0
+            )
 
-        MatrixContext.real.run {
             val lup = lup(matrix)
 
             //Check determinant
-            assertEquals(8.0, lup.determinant)
+            assertEquals(7.0, lup.determinant)
 
             assertEquals(lup.p dot matrix, lup.l dot lup.u)
         }
@@ -31,14 +33,14 @@ class RealLUSolverTest {
 
     @Test
     fun testInvert() {
-        val matrix = Matrix.square(
+        val matrix = LinearSpace.real.matrix(2,2)(
             3.0, 1.0,
             1.0, 3.0
         )
 
-        val inverted = MatrixContext.real.inverseWithLup(matrix)
+        val inverted = LinearSpace.real.inverseWithLup(matrix)
 
-        val expected = Matrix.square(
+        val expected = LinearSpace.real.matrix(2,2)(
             0.375, -0.125,
             -0.125, 0.375
         )
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt
index 23b0e7348..dd7871f9a 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt
@@ -1,5 +1,6 @@
 package space.kscience.kmath.structures
 
+import space.kscience.kmath.linear.LinearSpace
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.operations.Norm
 import space.kscience.kmath.operations.invoke
@@ -33,7 +34,9 @@ class NumberNDFieldTest {
     @Test
     fun testGeneration() {
 
-        val array = Structure2D.real(3, 3) { i, j -> (i * 10 + j).toDouble() }
+        val array = LinearSpace.real.buildMatrix(3, 3) { i, j ->
+            (i * 10 + j).toDouble()
+        }
 
         for (i in 0..2) {
             for (j in 0..2) {
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt
index 2aef6b27f..cdb0a7c5d 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt
@@ -5,8 +5,9 @@ import space.kscience.kmath.operations.invoke
 import kotlin.test.assertEquals
 import kotlin.test.assertNotEquals
 
-internal class FieldVerifier<T>(override val algebra: Field<T>, a: T, b: T, c: T, x: Number) :
-    RingVerifier<T>(algebra, a, b, c, x) {
+internal class FieldVerifier<T, A : Field<T>>(
+    algebra: A, a: T, b: T, c: T, x: Number,
+) : RingVerifier<T, A>(algebra, a, b, c, x) {
 
     override fun verify() {
         super.verify()
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt
index dd8841806..6970c8ac7 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt
@@ -1,11 +1,13 @@
 package space.kscience.kmath.testutils
 
 import space.kscience.kmath.operations.Ring
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.invoke
 import kotlin.test.assertEquals
 
-internal open class RingVerifier<T>(override val algebra: Ring<T>, a: T, b: T, c: T, x: Number) :
-    SpaceVerifier<T>(algebra, a, b, c, x) {
+internal open class RingVerifier<T, A>(algebra: A, a: T, b: T, c: T, x: Number) :
+    SpaceVerifier<T, A>(algebra, a, b, c, x) where A : Ring<T>, A : ScaleOperations<T> {
+
     override fun verify() {
         super.verify()
 
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt
index f7a25b593..a9cd4454c 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt
@@ -1,18 +1,18 @@
 package space.kscience.kmath.testutils
 
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.invoke
 import kotlin.test.assertEquals
 import kotlin.test.assertNotEquals
 
-internal open class SpaceVerifier<T>(
-    override val algebra: Space<T>,
+internal open class SpaceVerifier<T, out S>(
+    override val algebra: S,
     val a: T,
     val b: T,
     val c: T,
-    val x: Number
-) :
-    AlgebraicVerifier<T, Space<T>> {
+    val x: Number,
+) : AlgebraicVerifier<T, Group<T>> where S : Group<T>, S : ScaleOperations<T> {
     override fun verify() {
         algebra {
             assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.")
diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt
index 8f8b31ed9..0ac0ba1c5 100644
--- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt
+++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt
@@ -7,19 +7,16 @@ import java.math.MathContext
 /**
  * A field over [BigInteger].
  */
-public object JBigIntegerField : Field<BigInteger>, NumericAlgebra<BigInteger> {
-    public override val zero: BigInteger
-        get() = BigInteger.ZERO
+public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
+    public override val zero: BigInteger get() = BigInteger.ZERO
 
-    public override val one: BigInteger
-        get() = BigInteger.ONE
+    public override val one: BigInteger get() = BigInteger.ONE
 
     public override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
-    public override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b)
     public override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b)
     public override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b)
-    public override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger())
     public override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b)
+
     public override operator fun BigInteger.unaryMinus(): BigInteger = negate()
 }
 
@@ -30,7 +27,7 @@ public object JBigIntegerField : Field<BigInteger>, NumericAlgebra<BigInteger> {
  */
 public abstract class JBigDecimalFieldBase internal constructor(
     private val mathContext: MathContext = MathContext.DECIMAL64,
-) : Field<BigDecimal>, PowerOperations<BigDecimal>, NumericAlgebra<BigDecimal> {
+) : Field<BigDecimal>, PowerOperations<BigDecimal>, NumericAlgebra<BigDecimal>, ScaleOperations<BigDecimal> {
     public override val zero: BigDecimal
         get() = BigDecimal.ZERO
 
@@ -41,8 +38,8 @@ public abstract class JBigDecimalFieldBase internal constructor(
     public override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b)
     public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
 
-    public override fun multiply(a: BigDecimal, k: Number): BigDecimal =
-        a.multiply(k.toDouble().toBigDecimal(mathContext), mathContext)
+    public override fun scale(a: BigDecimal, value: Double): BigDecimal =
+        a.multiply(value.toBigDecimal(mathContext), mathContext)
 
     public override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext)
     public override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext)
diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt
index 489cca8c1..81b4327fc 100644
--- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt
+++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt
@@ -5,16 +5,16 @@ import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.runningReduce
 import kotlinx.coroutines.flow.scan
-import space.kscience.kmath.operations.Space
-import space.kscience.kmath.operations.SpaceOperations
+import space.kscience.kmath.operations.Group
+import space.kscience.kmath.operations.GroupOperations
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.invoke
 
-@ExperimentalCoroutinesApi
-public fun <T> Flow<T>.cumulativeSum(space: SpaceOperations<T>): Flow<T> =
-    space { runningReduce { sum, element -> sum + element } }
+public fun <T> Flow<T>.cumulativeSum(group: GroupOperations<T>): Flow<T> =
+    group { runningReduce { sum, element -> sum + element } }
 
 @ExperimentalCoroutinesApi
-public fun <T> Flow<T>.mean(space: Space<T>): Flow<T> = space {
+public fun <T, S> Flow<T>.mean(algebra: S): Flow<T> where S : Group<T>, S : ScaleOperations<T> = algebra {
     data class Accumulator(var sum: T, var num: Int)
 
     scan(Accumulator(zero, 0)) { sum, element ->
diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt
index 237824a39..f7e14b29f 100644
--- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt
+++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt
@@ -2,7 +2,8 @@ package space.kscience.kmath.dimensions
 
 import space.kscience.kmath.linear.*
 import space.kscience.kmath.nd.Structure2D
-import space.kscience.kmath.operations.invoke
+import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.Ring
 
 /**
  * A matrix with compile-time controlled dimension
@@ -77,7 +78,7 @@ public inline class DPointWrapper<T, D : Dimension>(public val point: Point<T>)
 /**
  * Basic operations on dimension-safe matrices. Operates on [Matrix]
  */
-public inline class DMatrixContext<T : Any>(public val context: MatrixContext<T, Matrix<T>>) {
+public inline class DMatrixContext<T : Any, out A : Ring<T>>(public val context: LinearSpace<T, A>) {
     public inline fun <reified R : Dimension, reified C : Dimension> Matrix<T>.coerce(): DMatrix<T, R, C> {
         require(rowNum == Dimension.dim<R>().toInt()) {
             "Row number mismatch: expected ${Dimension.dim<R>()} but found $rowNum"
@@ -93,17 +94,19 @@ public inline class DMatrixContext<T : Any>(public val context: MatrixContext<T,
     /**
      * Produce a matrix with this context and given dimensions
      */
-    public inline fun <reified R : Dimension, reified C : Dimension> produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix<T, R, C> {
+    public inline fun <reified R : Dimension, reified C : Dimension> produce(
+        noinline initializer: A.(i: Int, j: Int) -> T
+    ): DMatrix<T, R, C> {
         val rows = Dimension.dim<R>()
         val cols = Dimension.dim<C>()
-        return context.produce(rows.toInt(), cols.toInt(), initializer).coerce<R, C>()
+        return context.buildMatrix(rows.toInt(), cols.toInt(), initializer).coerce<R, C>()
     }
 
-    public inline fun <reified D : Dimension> point(noinline initializer: (Int) -> T): DPoint<T, D> {
+    public inline fun <reified D : Dimension> point(noinline initializer: A.(Int) -> T): DPoint<T, D> {
         val size = Dimension.dim<D>()
 
         return DPoint.coerceUnsafe(
-            context.point(
+            context.buildVector(
                 size.toInt(),
                 initializer
             )
@@ -112,31 +115,31 @@ public inline class DMatrixContext<T : Any>(public val context: MatrixContext<T,
 
     public inline infix fun <reified R1 : Dimension, reified C1 : Dimension, reified C2 : Dimension> DMatrix<T, R1, C1>.dot(
         other: DMatrix<T, C1, C2>,
-    ): DMatrix<T, R1, C2> = context { this@dot dot other }.coerce()
+    ): DMatrix<T, R1, C2> = context.run { this@dot dot other }.coerce()
 
     public inline infix fun <reified R : Dimension, reified C : Dimension> DMatrix<T, R, C>.dot(vector: DPoint<T, C>): DPoint<T, R> =
-        DPoint.coerceUnsafe(context { this@dot dot vector })
+        DPoint.coerceUnsafe(context.run { this@dot dot vector })
 
     public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, R, C>.times(value: T): DMatrix<T, R, C> =
-        context { this@times.times(value) }.coerce()
+        context.run { this@times.times(value) }.coerce()
 
     public inline operator fun <reified R : Dimension, reified C : Dimension> T.times(m: DMatrix<T, R, C>): DMatrix<T, R, C> =
         m * this
 
     public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.plus(other: DMatrix<T, C, R>): DMatrix<T, C, R> =
-        context { this@plus + other }.coerce()
+        context.run { this@plus + other }.coerce()
 
     public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.minus(other: DMatrix<T, C, R>): DMatrix<T, C, R> =
-        context { this@minus + other }.coerce()
+        context.run { this@minus + other }.coerce()
 
     public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.unaryMinus(): DMatrix<T, C, R> =
-        context { this@unaryMinus.unaryMinus() }.coerce()
+        context.run { this@unaryMinus.unaryMinus() }.coerce()
 
     public inline fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.transpose(): DMatrix<T, R, C> =
-        context { (this@transpose as Matrix<T>).transpose() }.coerce()
+        context.run { (this@transpose as Matrix<T>).transpose() }.coerce()
 
     public companion object {
-        public val real: DMatrixContext<Double> = DMatrixContext(MatrixContext.real)
+        public val real: DMatrixContext<Double, RealField> = DMatrixContext(LinearSpace.real)
     }
 }
 
@@ -144,11 +147,11 @@ public inline class DMatrixContext<T : Any>(public val context: MatrixContext<T,
 /**
  * A square unit matrix
  */
-public inline fun <reified D : Dimension> DMatrixContext<Double>.one(): DMatrix<Double, D, D> = produce { i, j ->
+public inline fun <reified D : Dimension> DMatrixContext<Double, RealField>.one(): DMatrix<Double, D, D> = produce { i, j ->
     if (i == j) 1.0 else 0.0
 }
 
-public inline fun <reified R : Dimension, reified C : Dimension> DMatrixContext<Double>.zero(): DMatrix<Double, R, C> =
+public inline fun <reified R : Dimension, reified C : Dimension> DMatrixContext<Double, RealField>.zero(): DMatrix<Double, R, C> =
     produce { _, _ ->
         0.0
     }
\ No newline at end of file
diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt
new file mode 100644
index 000000000..eecd88681
--- /dev/null
+++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt
@@ -0,0 +1,113 @@
+package space.kscience.kmath.ejml
+
+import org.ejml.simple.SimpleMatrix
+import space.kscience.kmath.linear.*
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.getFeature
+import space.kscience.kmath.operations.RealField
+
+/**
+ * Represents context of basic operations operating with [EjmlMatrix].
+ *
+ * @author Iaroslav Postovalov
+ */
+public object EjmlLinearSpace : LinearSpace<Double, RealField> {
+
+    override val elementAlgebra: RealField get() = RealField
+
+    /**
+     * Converts this matrix to EJML one.
+     */
+    @OptIn(UnstableKMathAPI::class)
+    public fun Matrix<Double>.toEjml(): EjmlMatrix = when (val matrix = origin) {
+        is EjmlMatrix -> matrix
+        else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) }
+    }
+
+    /**
+     * Converts this vector to EJML one.
+     */
+    public fun Point<Double>.toEjml(): EjmlVector = when (this) {
+        is EjmlVector -> this
+        else -> EjmlVector(SimpleMatrix(size, 1).also {
+            (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) }
+        })
+    }
+
+    override fun buildMatrix(rows: Int, columns: Int, initializer: RealField.(i: Int, j: Int) -> Double): EjmlMatrix =
+        EjmlMatrix(SimpleMatrix(rows, columns).also {
+            (0 until rows).forEach { row ->
+                (0 until columns).forEach { col -> it[row, col] = RealField.initializer(row, col) }
+            }
+        })
+
+    override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point<Double> =
+        EjmlVector(SimpleMatrix(size, 1).also {
+            (0 until it.numRows()).forEach { row -> it[row, 0] = RealField.initializer(row) }
+        })
+
+    private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this)
+    private fun SimpleMatrix.wrapVector() = EjmlVector(this)
+
+    override fun Matrix<Double>.unaryMinus(): Matrix<Double> = this * (-1.0)
+
+    public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlMatrix =
+        EjmlMatrix(toEjml().origin.mult(other.toEjml().origin))
+
+    public override fun Matrix<Double>.dot(vector: Point<Double>): EjmlVector =
+        EjmlVector(toEjml().origin.mult(vector.toEjml().origin))
+
+    public override operator fun Matrix<Double>.minus(other: Matrix<Double>): EjmlMatrix =
+        (toEjml().origin - other.toEjml().origin).wrapMatrix()
+
+    public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix =
+        toEjml().origin.scale(value).wrapMatrix()
+
+    override fun Point<Double>.unaryMinus(): EjmlVector =
+        toEjml().origin.negative().wrapVector()
+
+    override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlMatrix =
+        (toEjml().origin + other.toEjml().origin).wrapMatrix()
+
+    override fun Point<Double>.plus(other: Point<Double>): EjmlVector =
+        (toEjml().origin + other.toEjml().origin).wrapVector()
+
+    override fun Point<Double>.minus(other: Point<Double>): EjmlVector =
+        (toEjml().origin - other.toEjml().origin).wrapVector()
+
+    override fun Double.times(m: Matrix<Double>): EjmlMatrix =
+        m.toEjml().origin.scale(this).wrapMatrix()
+
+    override fun Point<Double>.times(value: Double): EjmlVector =
+        toEjml().origin.scale(value).wrapVector()
+
+    override fun Double.times(v: Point<Double>): EjmlVector =
+        v.toEjml().origin.scale(this).wrapVector()
+}
+
+/**
+ * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix.
+ *
+ * @param a the base matrix.
+ * @param b n by p matrix.
+ * @return the solution for 'x' that is n by p.
+ * @author Iaroslav Postovalov
+ */
+public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Matrix<Double>): EjmlMatrix =
+    EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin))
+
+/**
+ * Solves for X in the following equation: x = a^(-1)*b, where 'a' is base matrix and 'b' is an n by p matrix.
+ *
+ * @param a the base matrix.
+ * @param b n by p vector.
+ * @return the solution for 'x' that is n by p.
+ * @author Iaroslav Postovalov
+ */
+public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Point<Double>): EjmlVector =
+    EjmlVector(a.toEjml().origin.solve(b.toEjml().origin))
+
+@OptIn(UnstableKMathAPI::class)
+public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature<InverseMatrixFeature<Double>>()!!.inverse as EjmlMatrix
+
+public fun EjmlLinearSpace.inverse(matrix: Matrix<Double>): Matrix<Double> = matrix.toEjml().inverted()
\ No newline at end of file
diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt
index d23e613e4..a1984fa31 100644
--- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt
+++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt
@@ -85,7 +85,7 @@ public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix<Double> {
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
-        if (other !is Matrix<*>) return false
+        if (other !is NDStructure<*>) return false
         return NDStructure.contentEquals(this, other)
     }
 
diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt
deleted file mode 100644
index d67f80409..000000000
--- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-package space.kscience.kmath.ejml
-
-import org.ejml.simple.SimpleMatrix
-import space.kscience.kmath.linear.*
-import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.getFeature
-
-/**
- * Represents context of basic operations operating with [EjmlMatrix].
- *
- * @author Iaroslav Postovalov
- */
-public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix> {
-
-    /**
-     * Converts this matrix to EJML one.
-     */
-    @OptIn(UnstableKMathAPI::class)
-    public fun Matrix<Double>.toEjml(): EjmlMatrix = when (val matrix = origin) {
-        is EjmlMatrix -> matrix
-        else -> produce(rowNum, colNum) { i, j -> get(i, j) }
-    }
-
-    /**
-     * Converts this vector to EJML one.
-     */
-    public fun Point<Double>.toEjml(): EjmlVector =
-        if (this is EjmlVector) this else EjmlVector(SimpleMatrix(size, 1).also {
-            (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) }
-        })
-
-    override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix =
-        EjmlMatrix(SimpleMatrix(rows, columns).also {
-            (0 until rows).forEach { row ->
-                (0 until columns).forEach { col -> it[row, col] = initializer(row, col) }
-            }
-        })
-
-    override fun point(size: Int, initializer: (Int) -> Double): Point<Double> =
-        EjmlVector(SimpleMatrix(size, 1).also {
-            (0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) }
-        })
-
-    public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlMatrix =
-        EjmlMatrix(toEjml().origin.mult(other.toEjml().origin))
-
-    public override fun Matrix<Double>.dot(vector: Point<Double>): EjmlVector =
-        EjmlVector(toEjml().origin.mult(vector.toEjml().origin))
-
-    public override fun add(a: Matrix<Double>, b: Matrix<Double>): EjmlMatrix =
-        EjmlMatrix(a.toEjml().origin + b.toEjml().origin)
-
-    public override operator fun Matrix<Double>.minus(b: Matrix<Double>): EjmlMatrix =
-        EjmlMatrix(toEjml().origin - b.toEjml().origin)
-
-    public override fun multiply(a: Matrix<Double>, k: Number): EjmlMatrix =
-        produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() }
-
-    public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix =
-        EjmlMatrix(toEjml().origin.scale(value))
-}
-
-/**
- * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix.
- *
- * @param a the base matrix.
- * @param b n by p matrix.
- * @return the solution for 'x' that is n by p.
- * @author Iaroslav Postovalov
- */
-public fun EjmlMatrixContext.solve(a: Matrix<Double>, b: Matrix<Double>): EjmlMatrix =
-    EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin))
-
-/**
- * Solves for X in the following equation: x = a^(-1)*b, where 'a' is base matrix and 'b' is an n by p matrix.
- *
- * @param a the base matrix.
- * @param b n by p vector.
- * @return the solution for 'x' that is n by p.
- * @author Iaroslav Postovalov
- */
-public fun EjmlMatrixContext.solve(a: Matrix<Double>, b: Point<Double>): EjmlVector =
-    EjmlVector(a.toEjml().origin.solve(b.toEjml().origin))
-
-@OptIn(UnstableKMathAPI::class)
-public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature<InverseMatrixFeature<Double>>()!!.inverse as EjmlMatrix
-
-public fun EjmlMatrixContext.inverse(matrix: Matrix<Double>): Matrix<Double> = matrix.toEjml().inverted()
\ No newline at end of file
diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt
index 30d002498..76c73ab16 100644
--- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt
+++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt
@@ -2,6 +2,7 @@ package space.kscience.kmath.real
 
 import space.kscience.kmath.linear.*
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.RealField
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.RealBuffer
 import space.kscience.kmath.structures.asIterable
@@ -21,15 +22,19 @@ import kotlin.math.pow
 
 public typealias RealMatrix = Matrix<Double>
 
-public fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum, initializer)
+public fun realMatrix(rowNum: Int, colNum: Int, initializer: RealField.(i: Int, j: Int) -> Double): RealMatrix =
+    LinearSpace.real.buildMatrix(rowNum, colNum, initializer)
+
+@OptIn(UnstableKMathAPI::class)
+public fun realMatrix(rowNum: Int, colNum: Int): MatrixBuilder<Double, RealField> =
+    LinearSpace.real.matrix(rowNum, colNum)
 
 public fun Array<DoubleArray>.toMatrix(): RealMatrix {
-    return MatrixContext.real.produce(size, this[0].size) { row, col -> this[row][col] }
+    return LinearSpace.real.buildMatrix(size, this[0].size) { row, col -> this@toMatrix[row][col] }
 }
 
 public fun Sequence<DoubleArray>.toMatrix(): RealMatrix = toList().let {
-    MatrixContext.real.produce(it.size, it[0].size) { row, col -> it[row][col] }
+    LinearSpace.real.buildMatrix(it.size, it[0].size) { row, col -> it[row][col] }
 }
 
 public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix =
@@ -42,38 +47,38 @@ public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix =
  */
 
 public operator fun RealMatrix.times(double: Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { row, col ->
-        this[row, col] * double
+    LinearSpace.real.buildMatrix(rowNum, colNum) { row, col ->
+        get(row, col) * double
     }
 
 public operator fun RealMatrix.plus(double: Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { row, col ->
-        this[row, col] + double
+    LinearSpace.real.buildMatrix(rowNum, colNum) { row, col ->
+        get(row, col) + double
     }
 
 public operator fun RealMatrix.minus(double: Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { row, col ->
-        this[row, col] - double
+    LinearSpace.real.buildMatrix(rowNum, colNum) { row, col ->
+        get(row, col) - double
     }
 
 public operator fun RealMatrix.div(double: Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { row, col ->
-        this[row, col] / double
+    LinearSpace.real.buildMatrix(rowNum, colNum) { row, col ->
+        get(row, col) / double
     }
 
 public operator fun Double.times(matrix: RealMatrix): RealMatrix =
-    MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col ->
-        this * matrix[row, col]
+    LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col ->
+        this@times * matrix[row, col]
     }
 
 public operator fun Double.plus(matrix: RealMatrix): RealMatrix =
-    MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col ->
-        this + matrix[row, col]
+    LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col ->
+        this@plus + matrix[row, col]
     }
 
 public operator fun Double.minus(matrix: RealMatrix): RealMatrix =
-    MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col ->
-        this - matrix[row, col]
+    LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col ->
+        this@minus - matrix[row, col]
     }
 
 // TODO: does this operation make sense? Should it be 'this/matrix[row, col]'?
@@ -87,29 +92,29 @@ public operator fun Double.minus(matrix: RealMatrix): RealMatrix =
 
 @UnstableKMathAPI
 public operator fun RealMatrix.times(other: RealMatrix): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * other[row, col] }
+    LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this@times[row, col] * other[row, col] }
 
 public operator fun RealMatrix.plus(other: RealMatrix): RealMatrix =
-    MatrixContext.real.add(this, other)
+    LinearSpace.real.run { this@plus + other }
 
 public operator fun RealMatrix.minus(other: RealMatrix): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - other[row, col] }
+    LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this@minus[row, col] - other[row, col] }
 
 /*
  *  Operations on columns
  */
 
 public inline fun RealMatrix.appendColumn(crossinline mapper: (Buffer<Double>) -> Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum + 1) { row, col ->
+    LinearSpace.real.buildMatrix(rowNum, colNum + 1) { row, col ->
         if (col < colNum)
-            this[row, col]
+            get(row, col)
         else
             mapper(rows[row])
     }
 
 public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix =
-    MatrixContext.real.produce(rowNum, columnRange.count()) { row, col ->
-        this[row, columnRange.first + col]
+    LinearSpace.real.buildMatrix(rowNum, columnRange.count()) { row, col ->
+        this@extractColumns[row, columnRange.first + col]
     }
 
 public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix =
@@ -141,14 +146,14 @@ public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.ma
 public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average()
 
 public inline fun RealMatrix.map(crossinline transform: (Double) -> Double): RealMatrix =
-    MatrixContext.real.produce(rowNum, colNum) { i, j ->
+    LinearSpace.real.buildMatrix(rowNum, colNum) { i, j ->
         transform(get(i, j))
     }
 
 /**
  * Inverse a square real matrix using LUP decomposition
  */
-public fun RealMatrix.inverseWithLup(): RealMatrix = MatrixContext.real.inverseWithLup(this)
+public fun RealMatrix.inverseWithLup(): RealMatrix = LinearSpace.real.inverseWithLup(this)
 
 //extended operations
 
diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt
index ca892fa7e..ee42fe404 100644
--- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt
+++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt
@@ -5,6 +5,7 @@ import space.kscience.kmath.operations.Norm
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.asBuffer
 import space.kscience.kmath.structures.asIterable
+import space.kscience.kmath.structures.indices
 import kotlin.math.pow
 import kotlin.math.sqrt
 
@@ -30,7 +31,7 @@ public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -
     Buffer.real(size) { transform(it, get(it)) }
 
 public operator fun RealVector.plus(other: RealVector): RealVector {
-    require(size == other.size){"Vector size $size expected but ${other.size} found"}
+    require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value + other[index] }
 }
 
@@ -41,7 +42,7 @@ public operator fun Number.plus(vector: RealVector): RealVector = vector + this
 public operator fun RealVector.unaryMinus(): Buffer<Double> = map { -it }
 
 public operator fun RealVector.minus(other: RealVector): RealVector {
-    require(size == other.size){"Vector size $size expected but ${other.size} found"}
+    require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value - other[index] }
 }
 
@@ -50,7 +51,7 @@ public operator fun RealVector.minus(number: Number): RealVector = map { it - nu
 public operator fun Number.minus(vector: RealVector): RealVector = vector.map { toDouble() - it }
 
 public operator fun RealVector.times(other: RealVector): RealVector {
-    require(size == other.size){"Vector size $size expected but ${other.size} found"}
+    require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value * other[index] }
 }
 
@@ -59,7 +60,7 @@ public operator fun RealVector.times(number: Number): RealVector = map { it * nu
 public operator fun Number.times(vector: RealVector): RealVector = vector * this
 
 public operator fun RealVector.div(other: RealVector): RealVector {
-    require(size == other.size){"Vector size $size expected but ${other.size} found"}
+    require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value / other[index] }
 }
 
@@ -88,3 +89,13 @@ public fun tan(vector: RealVector): RealVector = vector.map { kotlin.math.tan(it
 public fun ln(vector: RealVector): RealVector = vector.map { kotlin.math.ln(it) }
 
 public fun log10(vector: RealVector): RealVector = vector.map { kotlin.math.log10(it) }
+
+// reductions methods
+
+public fun RealVector.sum(): Double {
+    var res = 0.0
+    for (i in indices) {
+        res += get(i)
+    }
+    return res
+}
\ No newline at end of file
diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt
index cbfb364c1..0bc5c111b 100644
--- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt
+++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt
@@ -1,31 +1,12 @@
 package space.kscience.kmath.real
 
-import space.kscience.kmath.linear.BufferMatrix
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.RealBuffer
+import space.kscience.kmath.linear.LinearSpace
+import space.kscience.kmath.linear.Matrix
 
 
 /**
  * Optimized dot product for real matrices
  */
-public infix fun BufferMatrix<Double>.dot(other: BufferMatrix<Double>): BufferMatrix<Double> {
-    require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
-    val resultArray = DoubleArray(this.rowNum * other.colNum)
-
-    //convert to array to insure there is no memory indirection
-    fun Buffer<Double>.unsafeArray() = if (this is RealBuffer)
-        this.array
-    else
-        DoubleArray(size) { get(it) }
-
-    val a = this.buffer.unsafeArray()
-    val b = other.buffer.unsafeArray()
-
-    for (i in (0 until rowNum))
-        for (j in (0 until other.colNum))
-            for (k in (0 until colNum))
-                resultArray[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j]
-
-    val buffer = RealBuffer(resultArray)
-    return BufferMatrix(rowNum, other.colNum, buffer)
+public infix fun Matrix<Double>.dot(other: Matrix<Double>): Matrix<Double> = LinearSpace.real.run{
+    this@dot dot other
 }
\ No newline at end of file
diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt
index 9e2778be9..06135598e 100644
--- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt
+++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt
@@ -1,7 +1,7 @@
 package kaceince.kmath.real
 
-import space.kscience.kmath.linear.Matrix
-import space.kscience.kmath.linear.build
+import space.kscience.kmath.linear.LinearSpace
+import space.kscience.kmath.linear.matrix
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.real.*
 import space.kscience.kmath.structures.contentEquals
@@ -9,6 +9,7 @@ import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
 
+@UnstableKMathAPI
 internal class RealMatrixTest {
     @Test
     fun testSum() {
@@ -30,11 +31,11 @@ internal class RealMatrixTest {
 
     @Test
     fun testRepeatStackVertical() {
-        val matrix1 = Matrix.build(2, 3)(
+        val matrix1 = realMatrix(2, 3)(
             1.0, 0.0, 0.0,
             0.0, 1.0, 2.0
         )
-        val matrix2 = Matrix.build(6, 3)(
+        val matrix2 = realMatrix(6, 3)(
             1.0, 0.0, 0.0,
             0.0, 1.0, 2.0,
             1.0, 0.0, 0.0,
@@ -47,12 +48,12 @@ internal class RealMatrixTest {
 
     @Test
     fun testMatrixAndDouble() {
-        val matrix1 = Matrix.build(2, 3)(
+        val matrix1 = realMatrix(2, 3)(
             1.0, 0.0, 3.0,
             4.0, 6.0, 2.0
         )
         val matrix2 = (matrix1 * 2.5 + 1.0 - 2.0) / 2.0
-        val expectedResult = Matrix.build(2, 3)(
+        val expectedResult = LinearSpace.real.matrix(2, 3)(
             0.75, -0.5, 3.25,
             4.5, 7.0, 2.0
         )
@@ -61,13 +62,13 @@ internal class RealMatrixTest {
 
     @Test
     fun testDoubleAndMatrix() {
-        val matrix1 = Matrix.build(2, 3)(
+        val matrix1 = realMatrix(2, 3)(
             1.0, 0.0, 3.0,
             4.0, 6.0, 2.0
         )
         val matrix2 = 20.0 - (10.0 + (5.0 * matrix1))
         //val matrix2 = 10.0 + (5.0 * matrix1)
-        val expectedResult = Matrix.build(2, 3)(
+        val expectedResult = realMatrix(2, 3)(
             5.0, 10.0, -5.0,
             -10.0, -20.0, 0.0
         )
@@ -76,15 +77,15 @@ internal class RealMatrixTest {
 
     @Test
     fun testSquareAndPower() {
-        val matrix1 = Matrix.build(2, 3)(
+        val matrix1 = realMatrix(2, 3)(
             -1.0, 0.0, 3.0,
             4.0, -6.0, -2.0
         )
-        val matrix2 = Matrix.build(2, 3)(
+        val matrix2 = realMatrix(2, 3)(
             1.0, 0.0, 9.0,
             16.0, 36.0, 4.0
         )
-        val matrix3 = Matrix.build(2, 3)(
+        val matrix3 = realMatrix(2, 3)(
             -1.0, 0.0, 27.0,
             64.0, -216.0, -8.0
         )
@@ -95,16 +96,16 @@ internal class RealMatrixTest {
     @OptIn(UnstableKMathAPI::class)
     @Test
     fun testTwoMatrixOperations() {
-        val matrix1 = Matrix.build(2, 3)(
+        val matrix1 = realMatrix(2, 3)(
             -1.0, 0.0, 3.0,
             4.0, -6.0, 7.0
         )
-        val matrix2 = Matrix.build(2, 3)(
+        val matrix2 = realMatrix(2, 3)(
             1.0, 0.0, 3.0,
             4.0, 6.0, -2.0
         )
         val result = matrix1 * matrix2 + matrix1 - matrix2
-        val expectedResult = Matrix.build(2, 3)(
+        val expectedResult = realMatrix(2, 3)(
             -3.0, 0.0, 9.0,
             16.0, -48.0, -5.0
         )
@@ -113,16 +114,16 @@ internal class RealMatrixTest {
 
     @Test
     fun testColumnOperations() {
-        val matrix1 = Matrix.build(2, 4)(
+        val matrix1 = realMatrix(2, 4)(
             -1.0, 0.0, 3.0, 15.0,
             4.0, -6.0, 7.0, -11.0
         )
-        val matrix2 = Matrix.build(2, 5)(
+        val matrix2 = realMatrix(2, 5)(
             -1.0, 0.0, 3.0, 15.0, -1.0,
             4.0, -6.0, 7.0, -11.0, 4.0
         )
-        val col1 = Matrix.build(2, 1)(0.0, -6.0)
-        val cols1to2 = Matrix.build(2, 2)(
+        val col1 = realMatrix(2, 1)(0.0, -6.0)
+        val cols1to2 = realMatrix(2, 2)(
             0.0, 3.0,
             -6.0, 7.0
         )
@@ -147,7 +148,7 @@ internal class RealMatrixTest {
 
     @Test
     fun testAllElementOperations() {
-        val matrix1 = Matrix.build(2, 4)(
+        val matrix1 = LinearSpace.real.matrix(2, 4)(
             -1.0, 0.0, 3.0, 15.0,
             4.0, -6.0, 7.0, -11.0
         )
diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt
index 463c68681..59d55110f 100644
--- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt
+++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt
@@ -1,10 +1,8 @@
 package kaceince.kmath.real
 
-import space.kscience.kmath.linear.MatrixContext
+import space.kscience.kmath.linear.LinearSpace
 import space.kscience.kmath.linear.asMatrix
-import space.kscience.kmath.linear.real
 import space.kscience.kmath.linear.transpose
-import space.kscience.kmath.operations.invoke
 import space.kscience.kmath.real.plus
 import space.kscience.kmath.structures.Buffer
 import kotlin.test.Test
@@ -32,7 +30,7 @@ internal class RealVectorTest {
         val vector2 =  Buffer.real(5) { 5 - it.toDouble() }
         val matrix1 = vector1.asMatrix()
         val matrix2 = vector2.asMatrix().transpose()
-        val product = MatrixContext.real { matrix1 dot matrix2 }
+        val product = LinearSpace.real.run { matrix1 dot matrix2 }
         assertEquals(5.0, product[1, 0])
         assertEquals(6.0, product[2, 2])
     }
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
index b1e47f34c..049909fe1 100644
--- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
@@ -1,7 +1,8 @@
 package space.kscience.kmath.functions
 
+import space.kscience.kmath.operations.Group
 import space.kscience.kmath.operations.Ring
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.invoke
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
@@ -41,9 +42,15 @@ public fun <T : Any, C : Ring<T>> Polynomial<T>.asFunction(ring: C): (T) -> T =
 /**
  * An algebra for polynomials
  */
-public class PolynomialSpace<T : Any, C : Ring<T>>(private val ring: C) : Space<Polynomial<T>> {
+public class PolynomialSpace<T : Any, C>(
+    private val ring: C,
+) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> {
     public override val zero: Polynomial<T> = Polynomial(emptyList())
 
+    override fun Polynomial<T>.unaryMinus(): Polynomial<T> = with(ring) {
+        Polynomial(coefficients.map { -it })
+    }
+
     public override fun add(a: Polynomial<T>, b: Polynomial<T>): Polynomial<T> {
         val dim = max(a.coefficients.size, b.coefficients.size)
 
@@ -54,13 +61,13 @@ public class PolynomialSpace<T : Any, C : Ring<T>>(private val ring: C) : Space<
         }
     }
 
-    public override fun multiply(a: Polynomial<T>, k: Number): Polynomial<T> =
-        ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * k }) }
+    public override fun scale(a: Polynomial<T>, value: Double): Polynomial<T> =
+        ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) }
 
     public operator fun Polynomial<T>.invoke(arg: T): T = value(ring, arg)
 }
 
-public inline fun <T : Any, C : Ring<T>, R> C.polynomial(block: PolynomialSpace<T, C>.() -> R): R {
+public inline fun <T : Any, C, R> C.polynomial(block: PolynomialSpace<T, C>.() -> R): R where C : Ring<T>, C : ScaleOperations<T> {
     contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
     return PolynomialSpace(this).block()
 }
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
index 34fd25ad4..ddbe743f0 100644
--- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
@@ -13,7 +13,7 @@ import space.kscience.kmath.structures.MutableBufferFactory
  */
 public class SplineInterpolator<T : Comparable<T>>(
     public override val algebra: Field<T>,
-    public val bufferFactory: MutableBufferFactory<T>
+    public val bufferFactory: MutableBufferFactory<T>,
 ) : PolynomialInterpolator<T> {
     //TODO possibly optimize zeroed buffers
 
diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt
index 609274d7d..54a1e032c 100644
--- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt
+++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt
@@ -2,6 +2,7 @@ package space.kscience.kmath.geometry
 
 import space.kscience.kmath.linear.Point
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.SpaceElement
 import space.kscience.kmath.operations.invoke
 import kotlin.math.sqrt
@@ -30,18 +31,20 @@ public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y)
 
 private data class Vector2DImpl(
     override val x: Double,
-    override val y: Double
+    override val y: Double,
 ) : Vector2D
 
 /**
  * 2D Euclidean space
  */
-public object Euclidean2DSpace : GeometrySpace<Vector2D> {
+public object Euclidean2DSpace : GeometrySpace<Vector2D>, ScaleOperations<Vector2D> {
     public override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) }
 
     public fun Vector2D.norm(): Double = sqrt(x * x + y * y)
+    override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y)
+
     public override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm()
     public override fun add(a: Vector2D, b: Vector2D): Vector2D = Vector2D(a.x + b.x, a.y + b.y)
-    public override fun multiply(a: Vector2D, k: Number): Vector2D = Vector2D(a.x * k.toDouble(), a.y * k.toDouble())
+    public override fun scale(a: Vector2D, value: Double): Vector2D = Vector2D(a.x * value, a.y * value)
     public override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y
 }
diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt
index 906f5df03..ed110e383 100644
--- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt
+++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt
@@ -2,6 +2,7 @@ package space.kscience.kmath.geometry
 
 import space.kscience.kmath.linear.Point
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.SpaceElement
 import space.kscience.kmath.operations.invoke
 import kotlin.math.sqrt
@@ -32,21 +33,22 @@ public val Vector3D.r: Double get() = Euclidean3DSpace { sqrt(norm()) }
 private data class Vector3DImpl(
     override val x: Double,
     override val y: Double,
-    override val z: Double
+    override val z: Double,
 ) : Vector3D
 
-public object Euclidean3DSpace : GeometrySpace<Vector3D> {
+public object Euclidean3DSpace : GeometrySpace<Vector3D>, ScaleOperations<Vector3D> {
     public override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) }
 
     public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z)
+    override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z)
 
     public override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm()
 
     public override fun add(a: Vector3D, b: Vector3D): Vector3D =
         Vector3D(a.x + b.x, a.y + b.y, a.z + b.z)
 
-    public override fun multiply(a: Vector3D, k: Number): Vector3D =
-        Vector3D(a.x * k.toDouble(), a.y * k.toDouble(), a.z * k.toDouble())
+    public override fun scale(a: Vector3D, value: Double): Vector3D =
+        Vector3D(a.x * value, a.y * value, a.z * value)
 
     public override fun Vector3D.dot(other: Vector3D): Double =
         x * other.x + y * other.y + z * other.z
diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt
index 392156e9f..9552c1320 100644
--- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt
+++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt
@@ -1,10 +1,11 @@
 package space.kscience.kmath.geometry
 
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
+import space.kscience.kmath.operations.ScaleOperations
 
 public interface Vector
 
-public interface GeometrySpace<V : Vector> : Space<V> {
+public interface GeometrySpace<V : Vector> : Group<V>, ScaleOperations<V> {
     /**
      * L2 distance
      */
diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt
index 55e8c0631..d5f3965d9 100644
--- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt
+++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt
@@ -2,8 +2,8 @@ package space.kscience.kmath.histogram
 
 import kotlinx.atomicfu.atomic
 import kotlinx.atomicfu.getAndUpdate
+import space.kscience.kmath.operations.Group
 import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.Space
 
 /**
  * Common representation for atomic counters
@@ -36,7 +36,7 @@ public class LongCounter : Counter<Long> {
     override val value: Long get() = innerValue.value
 }
 
-public class ObjectCounter<T : Any>(public val space: Space<T>) : Counter<T> {
+public class ObjectCounter<T : Any>(public val space: Group<T>) : Counter<T> {
     private val innerValue = atomic(space.zero)
 
     override fun add(delta: T) {
diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt
index 85262abeb..19128b2ac 100644
--- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt
+++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt
@@ -3,10 +3,11 @@ package space.kscience.kmath.histogram
 import space.kscience.kmath.domains.Domain
 import space.kscience.kmath.linear.Point
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.NDSpace
+import space.kscience.kmath.nd.NDField
 import space.kscience.kmath.nd.NDStructure
 import space.kscience.kmath.nd.Strides
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.SpaceElement
 import space.kscience.kmath.operations.invoke
 
@@ -41,10 +42,11 @@ public class IndexedHistogram<T : Comparable<T>, V : Any>(
 /**
  * A space for producing histograms with values in a NDStructure
  */
-public interface IndexedHistogramSpace<T : Comparable<T>, V : Any> : Space<IndexedHistogram<T, V>> {
+public interface IndexedHistogramSpace<T : Comparable<T>, V : Any>
+    : Group<IndexedHistogram<T, V>>, ScaleOperations<IndexedHistogram<T, V>> {
     //public val valueSpace: Space<V>
     public val strides: Strides
-    public val histogramValueSpace: NDSpace<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
+    public val histogramValueSpace: NDField<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
 
     /**
      * Resolve index of the bin including given [point]
@@ -63,12 +65,12 @@ public interface IndexedHistogramSpace<T : Comparable<T>, V : Any> : Space<Index
     override fun add(a: IndexedHistogram<T, V>, b: IndexedHistogram<T, V>): IndexedHistogram<T, V> {
         require(a.context == this) { "Can't operate on a histogram produced by external space" }
         require(b.context == this) { "Can't operate on a histogram produced by external space" }
-        return IndexedHistogram(this, histogramValueSpace.invoke { a.values + b.values })
+        return IndexedHistogram(this, histogramValueSpace { a.values + b.values })
     }
 
-    override fun multiply(a: IndexedHistogram<T, V>, k: Number): IndexedHistogram<T, V> {
+    override fun scale(a: IndexedHistogram<T, V>, value: Double): IndexedHistogram<T, V> {
         require(a.context == this) { "Can't operate on a histogram produced by external space" }
-        return IndexedHistogram(this, histogramValueSpace.invoke { a.values * k })
+        return IndexedHistogram(this, histogramValueSpace { a.values * value })
     }
 
     override val zero: IndexedHistogram<T, V> get() = produce { }
diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt
index 26efdf1fe..3df0b1626 100644
--- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt
+++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt
@@ -2,6 +2,7 @@ package space.kscience.kmath.histogram
 
 import space.kscience.kmath.domains.Domain
 import space.kscience.kmath.domains.HyperSquareDomain
+import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.structures.*
 import kotlin.math.floor
@@ -40,6 +41,7 @@ public class RealHistogramSpace(
         getIndex(it, point[it])
     }
 
+    @OptIn(UnstableKMathAPI::class)
     override fun getDomain(index: IntArray): Domain<Double> {
         val lowerBoundary = index.mapIndexed { axis, i ->
             when (i) {
@@ -77,6 +79,8 @@ public class RealHistogramSpace(
         return IndexedHistogram(this, values)
     }
 
+    override fun IndexedHistogram<Double, Double>.unaryMinus(): IndexedHistogram<Double, Double> = this * (-1)
+
     public companion object {
         /**
          * Use it like
diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt
index ddecc4332..b2071fa02 100644
--- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt
+++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt
@@ -2,7 +2,8 @@ package space.kscience.kmath.histogram
 
 import space.kscience.kmath.domains.UnivariateDomain
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.structures.Buffer
 import java.util.*
 import kotlin.math.abs
@@ -36,7 +37,7 @@ public class TreeHistogram(
 @UnstableKMathAPI
 public class TreeHistogramSpace(
     public val binFactory: (Double) -> UnivariateDomain,
-) : Space<UnivariateHistogram> {
+) : Group<UnivariateHistogram>, ScaleOperations<UnivariateHistogram> {
 
     private class BinCounter(val domain: UnivariateDomain, val counter: Counter<Double> = Counter.real()) :
         ClosedFloatingPointRange<Double> by domain.range
@@ -97,14 +98,14 @@ public class TreeHistogramSpace(
         return TreeHistogram(this, bins)
     }
 
-    override fun multiply(a: UnivariateHistogram, k: Number): UnivariateHistogram {
+    override fun scale(a: UnivariateHistogram, value: Double): UnivariateHistogram {
         val bins = TreeMap<Double, UnivariateBin>().apply {
             a.bins.forEach { bin ->
                 put(bin.domain.center,
                     UnivariateBin(
                         bin.domain,
-                        value = bin.value * k.toDouble(),
-                        standardDeviation = abs(bin.standardDeviation * k.toDouble())
+                        value = bin.value * value.toDouble(),
+                        standardDeviation = abs(bin.standardDeviation * value.toDouble())
                     )
                 )
             }
@@ -113,6 +114,8 @@ public class TreeHistogramSpace(
         return TreeHistogram(this, bins)
     }
 
+    override fun UnivariateHistogram.unaryMinus(): UnivariateHistogram = this * (-1)
+
     override val zero: UnivariateHistogram = produce { }
 
     public companion object {
diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt
index 8c4f9e434..03bd096d9 100644
--- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt
+++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt
@@ -2,12 +2,13 @@ package space.kscience.kmath.histogram
 
 import space.kscience.kmath.domains.UnivariateDomain
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
 import space.kscience.kmath.operations.SpaceElement
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.asSequence
 
 
+@UnstableKMathAPI
 public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2
 
 /**
@@ -15,6 +16,7 @@ public val UnivariateDomain.center: Double get() = (range.endInclusive - range.s
  * @param value The value of histogram including weighting
  * @param standardDeviation Standard deviation of the bin value. Zero or negative if not applicable
  */
+@UnstableKMathAPI
 public class UnivariateBin(
     public val domain: UnivariateDomain,
     override val value: Double,
@@ -28,7 +30,7 @@ public class UnivariateBin(
 
 @OptIn(UnstableKMathAPI::class)
 public interface UnivariateHistogram : Histogram<Double, UnivariateBin>,
-    SpaceElement<UnivariateHistogram, Space<UnivariateHistogram>> {
+    SpaceElement<UnivariateHistogram, Group<UnivariateHistogram>> {
     public operator fun get(value: Double): UnivariateBin?
     public override operator fun get(point: Buffer<Double>): UnivariateBin? = get(point[0])
 
diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt
index 6ca6bc113..82b801f91 100644
--- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt
+++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt
@@ -102,8 +102,8 @@ public fun <X : SFun<X>> MST.toSFun(): SFun<X> = when (this) {
     is MST.Symbolic -> toSVar()
 
     is MST.Unary -> when (operation) {
-        SpaceOperations.PLUS_OPERATION -> +value.toSFun<X>()
-        SpaceOperations.MINUS_OPERATION -> -value.toSFun<X>()
+        GroupOperations.PLUS_OPERATION -> +value.toSFun<X>()
+        GroupOperations.MINUS_OPERATION -> -value.toSFun<X>()
         TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun())
         TrigonometricOperations.COS_OPERATION -> cos(value.toSFun())
         TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun())
@@ -114,8 +114,8 @@ public fun <X : SFun<X>> MST.toSFun(): SFun<X> = when (this) {
     }
 
     is MST.Binary -> when (operation) {
-        SpaceOperations.PLUS_OPERATION -> left.toSFun<X>() + right.toSFun()
-        SpaceOperations.MINUS_OPERATION -> left.toSFun<X>() - right.toSFun()
+        GroupOperations.PLUS_OPERATION -> left.toSFun<X>() + right.toSFun()
+        GroupOperations.MINUS_OPERATION -> left.toSFun<X>() - right.toSFun()
         RingOperations.TIMES_OPERATION -> left.toSFun<X>() * right.toSFun()
         FieldOperations.DIV_OPERATION -> left.toSFun<X>() / right.toSFun()
         PowerOperations.POW_OPERATION -> left.toSFun<X>() pow (right as MST.Numeric).toSConst()
diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt
index c50174b95..d8ce1052a 100644
--- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt
+++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt
@@ -20,7 +20,7 @@ internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray {
  * @param T the type of ND-structure element.
  * @param C the type of the element context.
  */
-public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C> {
+public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : NDAlgebra<T, C> {
     /**
      * Wraps [INDArray] to [N].
      */
@@ -70,40 +70,27 @@ public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C> {
 }
 
 /**
- * Represents [NDSpace] over [Nd4jArrayStructure].
+ * Represents [NDGroup] over [Nd4jArrayStructure].
  *
  * @param T the type of the element contained in ND structure.
  * @param S the type of space of structure elements.
  */
-public interface Nd4jArraySpace<T, S : Space<T>> : NDSpace<T, S>, Nd4jArrayAlgebra<T, S> {
+public interface Nd4JArrayGroup<T, S : Group<T>> : NDGroup<T, S>, Nd4jArrayAlgebra<T, S> {
 
     public override val zero: Nd4jArrayStructure<T>
         get() = Nd4j.zeros(*shape).wrap()
 
-    public override fun add(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> {
-        return a.ndArray.add(b.ndArray).wrap()
-    }
+    public override fun add(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
+        a.ndArray.add(b.ndArray).wrap()
 
-    public override operator fun NDStructure<T>.minus(b: NDStructure<T>): Nd4jArrayStructure<T> {
-        return ndArray.sub(b.ndArray).wrap()
-    }
+    public override operator fun NDStructure<T>.minus(b: NDStructure<T>): Nd4jArrayStructure<T> =
+        ndArray.sub(b.ndArray).wrap()
 
-    public override operator fun NDStructure<T>.unaryMinus(): Nd4jArrayStructure<T> {
-        return ndArray.neg().wrap()
-    }
+    public override operator fun NDStructure<T>.unaryMinus(): Nd4jArrayStructure<T> =
+        ndArray.neg().wrap()
 
-    public override fun multiply(a: NDStructure<T>, k: Number): Nd4jArrayStructure<T> {
-        return a.ndArray.mul(k).wrap()
-    }
-
-    @Deprecated("Avoid using this method, underlying array get casted to Doubles")
-    public override operator fun NDStructure<T>.div(k: Number): Nd4jArrayStructure<T> {
-        return ndArray.div(k).wrap()
-    }
-
-    public override operator fun NDStructure<T>.times(k: Number): Nd4jArrayStructure<T> {
-        return ndArray.mul(k).wrap()
-    }
+    public fun multiply(a: NDStructure<T>, k: Number): Nd4jArrayStructure<T> =
+        a.ndArray.mul(k).wrap()
 }
 
 /**
@@ -113,14 +100,13 @@ public interface Nd4jArraySpace<T, S : Space<T>> : NDSpace<T, S>, Nd4jArrayAlgeb
  * @param R the type of ring of structure elements.
  */
 @OptIn(UnstableKMathAPI::class)
-public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4jArraySpace<T, R> {
+public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4JArrayGroup<T, R> {
 
     public override val one: Nd4jArrayStructure<T>
         get() = Nd4j.ones(*shape).wrap()
 
-    public override fun multiply(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> {
-        return a.ndArray.mul(b.ndArray).wrap()
-    }
+    public override fun multiply(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
+        a.ndArray.mul(b.ndArray).wrap()
 //
 //    public override operator fun Nd4jArrayStructure<T>.minus(b: Number): Nd4jArrayStructure<T> {
 //        check(this)
@@ -180,8 +166,7 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
     public override fun divide(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
         a.ndArray.div(b.ndArray).wrap()
 
-    public override operator fun Number.div(b: NDStructure<T>): Nd4jArrayStructure<T> = b.ndArray.rdiv(this).wrap()
-
+    public operator fun Number.div(b: NDStructure<T>): Nd4jArrayStructure<T> = b.ndArray.rdiv(this).wrap()
 
     public companion object {
         private val floatNd4jArrayFieldCache: ThreadLocal<MutableMap<IntArray, FloatNd4jArrayField>> =
@@ -218,11 +203,14 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
  * Represents [NDField] over [Nd4jArrayRealStructure].
  */
 public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Double, RealField> {
-    public override val elementContext: RealField
-        get() = RealField
+    public override val elementContext: RealField get() = RealField
 
     public override fun INDArray.wrap(): Nd4jArrayStructure<Double> = checkShape(this).asRealStructure()
 
+    override fun scale(a: NDStructure<Double>, value: Double): Nd4jArrayStructure<Double> {
+        return a.ndArray.mul(value).wrap()
+    }
+
     public override operator fun NDStructure<Double>.div(arg: Double): Nd4jArrayStructure<Double> {
         return ndArray.div(arg).wrap()
     }
@@ -257,29 +245,26 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra
 
     public override fun INDArray.wrap(): Nd4jArrayStructure<Float> = checkShape(this).asFloatStructure()
 
-    public override operator fun NDStructure<Float>.div(arg: Float): Nd4jArrayStructure<Float> {
-        return ndArray.div(arg).wrap()
-    }
+    override fun scale(a: NDStructure<Float>, value: Double): NDStructure<Float> =
+        a.ndArray.mul(value).wrap()
 
-    public override operator fun NDStructure<Float>.plus(arg: Float): Nd4jArrayStructure<Float> {
-        return ndArray.add(arg).wrap()
-    }
+    public override operator fun NDStructure<Float>.div(arg: Float): Nd4jArrayStructure<Float> =
+        ndArray.div(arg).wrap()
 
-    public override operator fun NDStructure<Float>.minus(arg: Float): Nd4jArrayStructure<Float> {
-        return ndArray.sub(arg).wrap()
-    }
+    public override operator fun NDStructure<Float>.plus(arg: Float): Nd4jArrayStructure<Float> =
+        ndArray.add(arg).wrap()
 
-    public override operator fun NDStructure<Float>.times(arg: Float): Nd4jArrayStructure<Float> {
-        return ndArray.mul(arg).wrap()
-    }
+    public override operator fun NDStructure<Float>.minus(arg: Float): Nd4jArrayStructure<Float> =
+        ndArray.sub(arg).wrap()
 
-    public override operator fun Float.div(arg: NDStructure<Float>): Nd4jArrayStructure<Float> {
-        return arg.ndArray.rdiv(this).wrap()
-    }
+    public override operator fun NDStructure<Float>.times(arg: Float): Nd4jArrayStructure<Float> =
+        ndArray.mul(arg).wrap()
 
-    public override operator fun Float.minus(arg: NDStructure<Float>): Nd4jArrayStructure<Float> {
-        return arg.ndArray.rsub(this).wrap()
-    }
+    public override operator fun Float.div(arg: NDStructure<Float>): Nd4jArrayStructure<Float> =
+        arg.ndArray.rdiv(this).wrap()
+
+    public override operator fun Float.minus(arg: NDStructure<Float>): Nd4jArrayStructure<Float> =
+        arg.ndArray.rsub(this).wrap()
 }
 
 /**
@@ -291,21 +276,17 @@ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRi
 
     public override fun INDArray.wrap(): Nd4jArrayStructure<Int> = checkShape(this).asIntStructure()
 
-    public override operator fun NDStructure<Int>.plus(arg: Int): Nd4jArrayStructure<Int> {
-        return ndArray.add(arg).wrap()
-    }
+    public override operator fun NDStructure<Int>.plus(arg: Int): Nd4jArrayStructure<Int> =
+        ndArray.add(arg).wrap()
 
-    public override operator fun NDStructure<Int>.minus(arg: Int): Nd4jArrayStructure<Int> {
-        return ndArray.sub(arg).wrap()
-    }
+    public override operator fun NDStructure<Int>.minus(arg: Int): Nd4jArrayStructure<Int> =
+        ndArray.sub(arg).wrap()
 
-    public override operator fun NDStructure<Int>.times(arg: Int): Nd4jArrayStructure<Int> {
-        return ndArray.mul(arg).wrap()
-    }
+    public override operator fun NDStructure<Int>.times(arg: Int): Nd4jArrayStructure<Int> =
+        ndArray.mul(arg).wrap()
 
-    public override operator fun Int.minus(arg: NDStructure<Int>): Nd4jArrayStructure<Int> {
-        return arg.ndArray.rsub(this).wrap()
-    }
+    public override operator fun Int.minus(arg: NDStructure<Int>): Nd4jArrayStructure<Int> =
+        arg.ndArray.rsub(this).wrap()
 }
 
 /**
@@ -317,19 +298,15 @@ public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayR
 
     public override fun INDArray.wrap(): Nd4jArrayStructure<Long> = checkShape(this).asLongStructure()
 
-    public override operator fun NDStructure<Long>.plus(arg: Long): Nd4jArrayStructure<Long> {
-        return ndArray.add(arg).wrap()
-    }
+    public override operator fun NDStructure<Long>.plus(arg: Long): Nd4jArrayStructure<Long> =
+        ndArray.add(arg).wrap()
 
-    public override operator fun NDStructure<Long>.minus(arg: Long): Nd4jArrayStructure<Long> {
-        return ndArray.sub(arg).wrap()
-    }
+    public override operator fun NDStructure<Long>.minus(arg: Long): Nd4jArrayStructure<Long> =
+        ndArray.sub(arg).wrap()
 
-    public override operator fun NDStructure<Long>.times(arg: Long): Nd4jArrayStructure<Long> {
-        return ndArray.mul(arg).wrap()
-    }
+    public override operator fun NDStructure<Long>.times(arg: Long): Nd4jArrayStructure<Long> =
+        ndArray.mul(arg).wrap()
 
-    public override operator fun Long.minus(arg: NDStructure<Long>): Nd4jArrayStructure<Long> {
-        return arg.ndArray.rsub(this).wrap()
-    }
+    public override operator fun Long.minus(arg: NDStructure<Long>): Nd4jArrayStructure<Long> =
+        arg.ndArray.rsub(this).wrap()
 }
diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt
index 9fed91e1f..c5ec99dae 100644
--- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt
+++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt
@@ -4,7 +4,8 @@ import space.kscience.kmath.chains.Chain
 import space.kscience.kmath.chains.ConstantChain
 import space.kscience.kmath.chains.map
 import space.kscience.kmath.chains.zip
-import space.kscience.kmath.operations.Space
+import space.kscience.kmath.operations.Group
+import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.invoke
 
 public class BasicSampler<T : Any>(public val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> {
@@ -18,14 +19,18 @@ public class ConstantSampler<T : Any>(public val value: T) : Sampler<T> {
 /**
  * A space for samplers. Allows to perform simple operations on distributions
  */
-public class SamplerSpace<T : Any>(public val space: Space<T>) : Space<Sampler<T>> {
-    public override val zero: Sampler<T> = ConstantSampler(space.zero)
+public class SamplerSpace<T : Any, S>(public val algebra: S) : Group<Sampler<T>>,
+    ScaleOperations<Sampler<T>> where S : Group<T>, S : ScaleOperations<T> {
+
+    public override val zero: Sampler<T> = ConstantSampler(algebra.zero)
 
     public override fun add(a: Sampler<T>, b: Sampler<T>): Sampler<T> = BasicSampler { generator ->
-        a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } }
+        a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> algebra { aValue + bValue } }
     }
 
-    public override fun multiply(a: Sampler<T>, k: Number): Sampler<T> = BasicSampler { generator ->
-        a.sample(generator).map { space { it * k.toDouble() } }
+    public override fun scale(a: Sampler<T>, value: Double): Sampler<T> = BasicSampler { generator ->
+        a.sample(generator).map { algebra { it * value } }
     }
+
+    override fun Sampler<T>.unaryMinus(): Sampler<T> = scale(this, -1.0)
 }
diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt
index 29ded2b88..a9f7cd3e4 100644
--- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt
+++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt
@@ -43,7 +43,7 @@ public interface ComposableStatistic<T, I, R> : Statistic<T, R> {
 @ExperimentalCoroutinesApi
 private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
     flow: Flow<Buffer<T>>,
-    dispatcher: CoroutineDispatcher = Dispatchers.Default
+    dispatcher: CoroutineDispatcher = Dispatchers.Default,
 ): Flow<I> = flow
     .mapParallel(dispatcher) { computeIntermediate(it) }
     .runningReduce(::composeIntermediate)
@@ -59,27 +59,31 @@ private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
 @ExperimentalCoroutinesApi
 public fun <T, I, R> ComposableStatistic<T, I, R>.flow(
     flow: Flow<Buffer<T>>,
-    dispatcher: CoroutineDispatcher = Dispatchers.Default
+    dispatcher: CoroutineDispatcher = Dispatchers.Default,
 ): Flow<R> = flowIntermediate(flow, dispatcher).map(::toResult)
 
 /**
  * Arithmetic mean
  */
-public class Mean<T>(public val space: Space<T>) : ComposableStatistic<T, Pair<T, Int>, T> {
+public class Mean<T>(
+    private val space: Group<T>,
+    private val division: (sum: T, count: Int) -> T,
+) : ComposableStatistic<T, Pair<T, Int>, T> {
     public override suspend fun computeIntermediate(data: Buffer<T>): Pair<T, Int> =
         space { sum(data.asIterable()) } to data.size
 
     public override suspend fun composeIntermediate(first: Pair<T, Int>, second: Pair<T, Int>): Pair<T, Int> =
         space { first.first + second.first } to (first.second + second.second)
 
-    public override suspend fun toResult(intermediate: Pair<T, Int>): T =
-        space { intermediate.first / intermediate.second }
+    public override suspend fun toResult(intermediate: Pair<T, Int>): T = space {
+        division(intermediate.first, intermediate.second)
+    }
 
     public companion object {
         //TODO replace with optimized version which respects overflow
-        public val real: Mean<Double> = Mean(RealField)
-        public val int: Mean<Int> = Mean(IntRing)
-        public val long: Mean<Long> = Mean(LongRing)
+        public val real: Mean<Double> = Mean(RealField) { sum, count -> sum / count }
+        public val int: Mean<Int> = Mean(IntRing) { sum, count -> sum / count }
+        public val long: Mean<Long> = Mean(LongRing) { sum, count -> sum / count }
     }
 }
 
diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api
index 462e065bf..ebb97b150 100644
--- a/kmath-viktor/api/kmath-viktor.api
+++ b/kmath-viktor/api/kmath-viktor.api
@@ -26,7 +26,7 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kma
 	public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64FlatArray;
 }
 
-public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/RingWithNumbers {
+public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations {
 	public fun <init> ([I)V
 	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun acos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
@@ -55,8 +55,6 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
 	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun div (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun div (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 	public synthetic fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
@@ -68,7 +66,7 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
 	public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun exp-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
-	public synthetic fun getElementContext ()Ljava/lang/Object;
+	public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra;
 	public fun getElementContext ()Lspace/kscience/kmath/operations/RealField;
 	public final fun getF64Buffer (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun getOne ()Ljava/lang/Object;
@@ -96,11 +94,8 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
 	public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public synthetic fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun minus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
-	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun multiply-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
 	public fun number-Q7Xurp0 (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
 	public fun plus (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
@@ -122,6 +117,8 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
 	public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
+	public fun scale-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;D)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
 	public fun sin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt
index 8deda2544..d791ed675 100644
--- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt
+++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt
@@ -4,8 +4,9 @@ import org.jetbrains.bio.viktor.F64Array
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.NumbersAddOperations
 import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.operations.RingWithNumbers
+import space.kscience.kmath.operations.ScaleOperations
 
 @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
 public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure<Double> {
@@ -26,7 +27,8 @@ public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this)
 @OptIn(UnstableKMathAPI::class)
 @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
 public class ViktorNDField(public override val shape: IntArray) : NDField<Double, RealField>,
-    RingWithNumbers<NDStructure<Double>>, ExtendedField<NDStructure<Double>> {
+    NumbersAddOperations<NDStructure<Double>>, ExtendedField<NDStructure<Double>>,
+    ScaleOperations<NDStructure<Double>> {
 
     public val NDStructure<Double>.f64Buffer: F64Array
         get() = when {
@@ -38,11 +40,9 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
             else -> produce { this@f64Buffer[it] }.f64Buffer
         }
 
-    public override val zero: ViktorNDStructure
-        get() = F64Array.full(init = 0.0, shape = shape).asStructure()
+    public override val zero: ViktorNDStructure by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() }
 
-    public override val one: ViktorNDStructure
-        get() = F64Array.full(init = 1.0, shape = shape).asStructure()
+    public override val one: ViktorNDStructure by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() }
 
     private val strides: Strides = DefaultStrides(shape)
 
@@ -55,6 +55,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
             }
         }.asStructure()
 
+    override fun NDStructure<Double>.unaryMinus(): NDStructure<Double> = -1 * this
+
     public override fun NDStructure<Double>.map(transform: RealField.(Double) -> Double): ViktorNDStructure =
         F64Array(*this@ViktorNDField.shape).apply {
             this@ViktorNDField.strides.indices().forEach { index ->
@@ -83,8 +85,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
     public override fun add(a: NDStructure<Double>, b: NDStructure<Double>): ViktorNDStructure =
         (a.f64Buffer + b.f64Buffer).asStructure()
 
-    public override fun multiply(a: NDStructure<Double>, k: Number): ViktorNDStructure =
-        (a.f64Buffer * k.toDouble()).asStructure()
+    public override fun scale(a: NDStructure<Double>, value: Double): ViktorNDStructure =
+        (a.f64Buffer * value.toDouble()).asStructure()
 
     public override inline fun NDStructure<Double>.plus(b: NDStructure<Double>): ViktorNDStructure =
         (f64Buffer + b.f64Buffer).asStructure()
diff --git a/settings.gradle.kts b/settings.gradle.kts
index cadbfd7ba..b4d7b3049 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,14 +1,15 @@
 pluginManagement {
     repositories {
+        maven("https://repo.kotlin.link")
+        mavenLocal()
         gradlePluginPortal()
         jcenter()
-        maven("https://repo.kotlin.link")
         maven("https://dl.bintray.com/kotlin/kotlin-eap")
         maven("https://dl.bintray.com/kotlin/kotlinx")
     }
 
-    val toolsVersion = "0.8.1"
-    val kotlinVersion = "1.4.30"
+    val toolsVersion = "0.9.1"
+    val kotlinVersion = "1.4.31"
 
     plugins {
         id("kotlinx.benchmark") version "0.2.0-dev-20"