diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 29a2ed649..82b0fb303 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -22,10 +22,19 @@ jobs:
           key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }}
           restore-keys: |
             ubuntu-20.04-gradle-
+      - name: Cache konan
+        uses: actions/cache@v2
+        with:
+          path: ~/.konan
+          key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
+          restore-keys: |
+            ${{ runner.os }}-gradle-
       - name: Build
-        run: ./gradlew build --no-daemon --stacktrace
+        run: |
+          ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
+          mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html
       - name: Deploy to GitHub Pages
         uses: JamesIves/github-pages-deploy-action@4.1.0
         with:
-            branch: gh-pages
-            folder: build/dokka/htmlMultiModule
+          branch: gh-pages
+          folder: build/dokka/htmlMultiModule
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 42fa6d3b6..ca374574e 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,7 +12,7 @@ jobs:
       name: publish
     strategy:
       matrix:
-        os: [macOS-latest, windows-latest]
+        os: [ macOS-latest, windows-latest ]
     runs-on: ${{matrix.os}}
     steps:
       - name: Checkout the repo
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 47690e36a..8b4dddf81 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,18 +4,22 @@
 ### Added
 - ScaleOperations interface
 - Field extends ScaleOperations
+- Basic integration API
 
 ### Changed
 - Exponential operations merged with hyperbolic functions
 - Space is replaced by Group. Space is reserved for vector spaces.
 - VectorSpace is now a vector space
-- 
+- Buffer factories for primitives moved to MutableBuffer.Companion
+- NDStructure and NDAlgebra to StructureND and AlgebraND respectively
+- Real -> Double
 
 ### Deprecated
 
 ### Removed
 - Nearest in Domain. To be implemented in geometry package.
 - Number multiplication and division in main Algebra chain
+- `contentEquals` from Buffer. It moved to the companion.
 
 ### Fixed
 
@@ -73,6 +77,7 @@
 - `toGrid` method.
 - Public visibility of `BufferAccessor2D`
 - `Real` class
+- StructureND identity and equals
 
 ### Fixed
 - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)
diff --git a/README.md b/README.md
index e9cf64ea0..cc9439d27 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,7 @@
 
 ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
 
-Bintray:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
-
-Bintray-dev:    [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
+[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22)
 
 # KMath
 
@@ -89,12 +87,12 @@ KMath is a modular library. Different modules provide different features with di
 > **Maturity**: PROTOTYPE
 >
 > **Features:**
-> - [expression-language](kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser
-> - [mst](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
-> - [mst-building](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
-> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter
-> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
-> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
+> - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
+> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
+> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
+> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter
+> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
+> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
 
 <hr/>
 
@@ -110,8 +108,8 @@ KMath is a modular library. Different modules provide different features with di
 > **Maturity**: PROTOTYPE
 >
 > **Features:**
-> - [complex](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Complex.kt) : Complex Numbers
-> - [quaternion](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt) : Quaternions
+> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers
+> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions
 
 <hr/>
 
@@ -121,15 +119,15 @@ KMath is a modular library. Different modules provide different features with di
 > **Maturity**: DEVELOPMENT
 >
 > **Features:**
-> - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
-> - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them.
-> - [linear](kmath-core/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](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
-> - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of 
+> - [algebras](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
+> - [nd](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them.
+> - [linear](kmath-core/src/commonMain/kotlin/space/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](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
+> - [expressions](kmath-core/src/commonMain/kotlin/space/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](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains
-> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
+> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
+> - [autodif](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
 
 <hr/>
 
@@ -159,9 +157,9 @@ One can still use generic algebras though.
 > **Maturity**: EXPERIMENTAL
 >
 > **Features:**
-> - [RealVector](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points
-> - [RealMatrix](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures
-> - [grids](kmath-for-real/src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators
+> - [DoubleVector](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points
+> - [DoubleMatrix](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures
+> - [grids](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
 
 <hr/>
 
@@ -171,10 +169,10 @@ One can still use generic algebras though.
 > **Maturity**: PROTOTYPE
 >
 > **Features:**
-> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt
-> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt
-> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt
-> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt
+> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt
+> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
+> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt
+> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
 
 <hr/>
 
@@ -208,9 +206,9 @@ One can still use generic algebras though.
 > **Maturity**: EXPERIMENTAL
 >
 > **Features:**
-> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
-> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long
-> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double
+> - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray
+> - [nd4jarrayrings](kmath-nd4j/#) : Rings over Nd4jArrayStructure of Int and Long
+> - [nd4jarrayfields](kmath-nd4j/#) : Fields over Nd4jArrayStructure of Float and Double
 
 <hr/>
 
@@ -256,8 +254,8 @@ repositories {
 }
 
 dependencies {
-    api("kscience.kmath:kmath-core:() -> kotlin.Any")
-    // api("kscience.kmath:kmath-core-jvm:() -> kotlin.Any") for jvm-specific version
+    api("space.kscience:kmath-core:0.3.0-dev-3")
+    // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-3") for jvm-specific version
 }
 ```
 
diff --git a/build.gradle.kts b/build.gradle.kts
index 113107f69..5f1a8b88a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -20,7 +20,7 @@ allprojects {
     }
 
     group = "space.kscience"
-    version = "0.3.0"
+    version = "0.3.0-dev-3"
 }
 
 subprojects {
diff --git a/docs/algebra.md b/docs/algebra.md
index 6bfcde043..84693bb81 100644
--- a/docs/algebra.md
+++ b/docs/algebra.md
@@ -31,7 +31,7 @@ multiplication;
 - [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1);
 - [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
 
-A typical implementation of `Field<T>` is the `RealField` which works on doubles, and `VectorSpace` for `Space<T>`.
+A typical implementation of `Field<T>` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space<T>`.
 
 In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate
 interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot` 
diff --git a/docs/images/KM.svg b/docs/images/KM.svg
index 50126cbc5..83af21f35 100644
--- a/docs/images/KM.svg
+++ b/docs/images/KM.svg
@@ -13,27 +13,30 @@
         version="1.1"><metadata
      id="metadata8"><rdf:RDF><cc:Work
          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
-     id="defs6"><clipPath
+        rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
+    <defs
+            id="defs6"><clipPath
        id="clipPath24"
        clipPathUnits="userSpaceOnUse"><path
          id="path22"
-         d="M 0,1590 H 6720 V 4400 H 0 Z" /></clipPath><clipPath
-       id="clipPath36"
-       clipPathUnits="userSpaceOnUse"><path
+         d="M 0,1590 H 6720 V 4400 H 0 Z" /></clipPath>
+        <clipPath
+                id="clipPath36"
+                clipPathUnits="userSpaceOnUse"><path
          id="path34"
-         d="M 3410,0 H 6720 V 1590 H 3410 Z" /></clipPath></defs><g
-     transform="matrix(1.3333333,0,0,-1.3333333,0,586.66667)"
-     id="g10"><g
+         d="M 3410,0 H 6720 V 1590 H 3410 Z" /></clipPath></defs>
+    <g
+            transform="matrix(1.3333333,0,0,-1.3333333,0,586.66667)"
+            id="g10"><g
        transform="scale(0.1)"
        id="g12"><path
          id="path14"
          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
          d="m 1299.34,651.602 h 4653.75 v 3208.87 H 1299.34 Z" /><path
-         id="path16"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 1651.48,1093.71 h 4076.99 v 114.609 H 1651.48 Z" /><g
-         id="g18"><g
+            id="path16"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 1651.48,1093.71 h 4076.99 v 114.609 H 1651.48 Z"/><g
+            id="g18"><g
            clip-path="url(#clipPath24)"
            id="g20"><g
              transform="matrix(6720,0,0,2810.4,0,1589.6)"
@@ -45,7 +48,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g30"><g
+            id="g30"><g
            clip-path="url(#clipPath36)"
            id="g32"><g
              transform="matrix(3312,0,0,1591.2,3410,-1.19998)"
diff --git a/docs/images/KM_mono.svg b/docs/images/KM_mono.svg
index 3b6890b6b..90566b87b 100644
--- a/docs/images/KM_mono.svg
+++ b/docs/images/KM_mono.svg
@@ -13,35 +13,37 @@
         version="1.1"><metadata
      id="metadata8"><rdf:RDF><cc:Work
          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
-     id="defs6"><clipPath
+        rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
+    <defs
+            id="defs6"><clipPath
        id="clipPath32"
        clipPathUnits="userSpaceOnUse"><path
          id="path30"
-         d="M 1780,1750 H 3830 V 3800 H 1780 Z" /></clipPath></defs><g
-     transform="matrix(1.3333333,0,0,-1.3333333,0,633.33333)"
-     id="g10"><g
+         d="M 1780,1750 H 3830 V 3800 H 1780 Z" /></clipPath></defs>
+    <g
+            transform="matrix(1.3333333,0,0,-1.3333333,0,633.33333)"
+            id="g10"><g
        transform="scale(0.1)"
        id="g12"><path
          id="path14"
          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
          d="M 318.789,2616.17 6643.05,4723.79 c 239.45,79.76 496.44,-48.75 576.29,-288.17 79.8,-239.41 -48.72,-496.4 -288.13,-576.21 L 606.949,1751.84 c -239.449,-79.81 -496.437,48.71 -576.2888,288.12 -79.8008,239.45 48.7187,496.45 288.1288,576.21 z" /><path
-         id="path16"
-         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="M 3751.56,538.199 6636.91,4443.95 c 109.22,147.89 316.21,178.98 464.11,69.76 147.89,-109.22 178.98,-316.21 69.76,-464.06 L 4285.43,143.91 C 4176.17,-3.98047 3969.18,-35.0781 3821.29,74.1406 3673.44,183.359 3642.3,390.309 3751.56,538.199 Z" /><path
-         id="path18"
-         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="M 1400.43,708.48 H 6418.24 V 4168.4 H 1400.43 Z" /><path
-         id="path20"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 6145.16,1753.83 h -358.6 V 3271.02 L 5158.28,1753.83 H 5005 L 4379.69,3271.02 V 1753.83 h -358.6 v 2044.53 h 505.79 l 554.68,-1345.63 557.97,1345.63 h 505.63 z" /><path
-         id="path22"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 1780.12,1185.24 h 4395.94 v 123.551 H 1780.12 Z" /><path
-         id="path24"
-         style="fill:none;stroke:#000000;stroke-width:22.00740051;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-         d="m 1780.12,3798.09 c 0,-2044.73 0,-2044.73 0,-2044.73 H 3824.84 L 2806.17,2778.24 3824.84,3798.09" /><g
-         id="g26"><g
+            id="path16"
+            style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="M 3751.56,538.199 6636.91,4443.95 c 109.22,147.89 316.21,178.98 464.11,69.76 147.89,-109.22 178.98,-316.21 69.76,-464.06 L 4285.43,143.91 C 4176.17,-3.98047 3969.18,-35.0781 3821.29,74.1406 3673.44,183.359 3642.3,390.309 3751.56,538.199 Z"/><path
+            id="path18"
+            style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="M 1400.43,708.48 H 6418.24 V 4168.4 H 1400.43 Z"/><path
+            id="path20"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 6145.16,1753.83 h -358.6 V 3271.02 L 5158.28,1753.83 H 5005 L 4379.69,3271.02 V 1753.83 h -358.6 v 2044.53 h 505.79 l 554.68,-1345.63 557.97,1345.63 h 505.63 z"/><path
+            id="path22"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 1780.12,1185.24 h 4395.94 v 123.551 H 1780.12 Z"/><path
+            id="path24"
+            style="fill:none;stroke:#000000;stroke-width:22.00740051;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+            d="m 1780.12,3798.09 c 0,-2044.73 0,-2044.73 0,-2044.73 H 3824.84 L 2806.17,2778.24 3824.84,3798.09"/><g
+            id="g26"><g
            clip-path="url(#clipPath32)"
            id="g28"><g
              transform="matrix(2052,0,0,2052,1780,1748)"
diff --git a/docs/images/KMath.svg b/docs/images/KMath.svg
index d88cfe7b0..4ee4b87d0 100644
--- a/docs/images/KMath.svg
+++ b/docs/images/KMath.svg
@@ -13,35 +13,40 @@
         version="1.1"><metadata
      id="metadata8"><rdf:RDF><cc:Work
          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
-     id="defs6"><clipPath
+        rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
+    <defs
+            id="defs6"><clipPath
        id="clipPath24"
        clipPathUnits="userSpaceOnUse"><path
          id="path22"
-         d="M 0,3010 H 6470 V 4280 H 0 Z" /></clipPath><clipPath
-       id="clipPath36"
-       clipPathUnits="userSpaceOnUse"><path
+         d="M 0,3010 H 6470 V 4280 H 0 Z" /></clipPath>
+        <clipPath
+                id="clipPath36"
+                clipPathUnits="userSpaceOnUse"><path
          id="path34"
-         d="M 0,1590 H 7000 V 3010 H 0 Z" /></clipPath><clipPath
-       id="clipPath48"
-       clipPathUnits="userSpaceOnUse"><path
+         d="M 0,1590 H 7000 V 3010 H 0 Z" /></clipPath>
+        <clipPath
+                id="clipPath48"
+                clipPathUnits="userSpaceOnUse"><path
          id="path46"
-         d="m 0,1580 h 6470 v 10 H 0 Z" /></clipPath><clipPath
-       id="clipPath60"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 0,1580 h 6470 v 10 H 0 Z" /></clipPath>
+        <clipPath
+                id="clipPath60"
+                clipPathUnits="userSpaceOnUse"><path
          id="path58"
-         d="M 3280,0 H 6460 V 1580 H 3280 Z" /></clipPath></defs><g
-     transform="matrix(1.3333333,0,0,-1.3333333,0,570.66667)"
-     id="g10"><g
+         d="M 3280,0 H 6460 V 1580 H 3280 Z" /></clipPath></defs>
+    <g
+            transform="matrix(1.3333333,0,0,-1.3333333,0,570.66667)"
+            id="g10"><g
        transform="scale(0.1)"
        id="g12"><path
          id="path14"
          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
          d="m 791.328,957.73 h 6401.56 V 3245.31 H 791.328 Z" /><path
-         id="path16"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 1049.45,1214.42 h 2988.24 v 86.9883 H 1049.45 Z" /><g
-         id="g18"><g
+            id="path16"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 1049.45,1214.42 h 2988.24 v 86.9883 H 1049.45 Z"/><g
+            id="g18"><g
            clip-path="url(#clipPath24)"
            id="g20"><g
              transform="matrix(6470.4,0,0,1272,0,3008)"
@@ -53,7 +58,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g30"><g
+            id="g30"><g
            clip-path="url(#clipPath36)"
            id="g32"><g
              transform="matrix(7000.8,0,0,1420.8,0,1589.2)"
@@ -65,7 +70,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g42"><g
+            id="g42"><g
            clip-path="url(#clipPath48)"
            id="g44"><g
              transform="matrix(6470.4,0,0,12,0,1578)"
@@ -77,7 +82,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g54"><g
+            id="g54"><g
            clip-path="url(#clipPath60)"
            id="g56"><g
              transform="matrix(3180,0,0,1581.6,3280,-1.59972)"
diff --git a/docs/images/KMath_mono.svg b/docs/images/KMath_mono.svg
index 3a62ac383..dfcff9ec9 100644
--- a/docs/images/KMath_mono.svg
+++ b/docs/images/KMath_mono.svg
@@ -13,123 +13,144 @@
         version="1.1"><metadata
      id="metadata8"><rdf:RDF><cc:Work
          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
-     id="defs6"><clipPath
+        rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
+    <defs
+            id="defs6"><clipPath
        id="clipPath40"
        clipPathUnits="userSpaceOnUse"><path
          id="path38"
-         d="m 2370,2780 h 1370 v 10 H 2370 Z" /></clipPath><clipPath
-       id="clipPath52"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 2370,2780 h 1370 v 10 H 2370 Z" /></clipPath>
+        <clipPath
+                id="clipPath52"
+                clipPathUnits="userSpaceOnUse"><path
          id="path50"
-         d="m 5630,2780 h 860 v 10 h -860 z" /></clipPath><clipPath
-       id="clipPath64"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 5630,2780 h 860 v 10 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath64"
+                clipPathUnits="userSpaceOnUse"><path
          id="path62"
-         d="m 970,2690 h 1300 v 90 H 970 Z" /></clipPath><clipPath
-       id="clipPath76"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 970,2690 h 1300 v 90 H 970 Z" /></clipPath>
+        <clipPath
+                id="clipPath76"
+                clipPathUnits="userSpaceOnUse"><path
          id="path74"
-         d="m 2370,2690 h 1370 v 90 H 2370 Z" /></clipPath><clipPath
-       id="clipPath88"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 2370,2690 h 1370 v 90 H 2370 Z" /></clipPath>
+        <clipPath
+                id="clipPath88"
+                clipPathUnits="userSpaceOnUse"><path
          id="path86"
-         d="m 5630,2690 h 860 v 90 h -860 z" /></clipPath><clipPath
-       id="clipPath100"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 5630,2690 h 860 v 90 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath100"
+                clipPathUnits="userSpaceOnUse"><path
          id="path98"
-         d="m 970,2460 h 1300 v 230 H 970 Z" /></clipPath><clipPath
-       id="clipPath112"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 970,2460 h 1300 v 230 H 970 Z" /></clipPath>
+        <clipPath
+                id="clipPath112"
+                clipPathUnits="userSpaceOnUse"><path
          id="path110"
-         d="m 2370,2460 h 1370 v 230 H 2370 Z" /></clipPath><clipPath
-       id="clipPath124"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 2370,2460 h 1370 v 230 H 2370 Z" /></clipPath>
+        <clipPath
+                id="clipPath124"
+                clipPathUnits="userSpaceOnUse"><path
          id="path122"
-         d="m 4900,2460 h 620 v 230 h -620 z" /></clipPath><clipPath
-       id="clipPath136"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 4900,2460 h 620 v 230 h -620 z" /></clipPath>
+        <clipPath
+                id="clipPath136"
+                clipPathUnits="userSpaceOnUse"><path
          id="path134"
-         d="m 5630,2460 h 860 v 230 h -860 z" /></clipPath><clipPath
-       id="clipPath148"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 5630,2460 h 860 v 230 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath148"
+                clipPathUnits="userSpaceOnUse"><path
          id="path146"
-         d="m 970,1480 h 1300 v 980 H 970 Z" /></clipPath><clipPath
-       id="clipPath160"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 970,1480 h 1300 v 980 H 970 Z" /></clipPath>
+        <clipPath
+                id="clipPath160"
+                clipPathUnits="userSpaceOnUse"><path
          id="path158"
-         d="m 2370,1480 h 1370 v 980 H 2370 Z" /></clipPath><clipPath
-       id="clipPath172"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 2370,1480 h 1370 v 980 H 2370 Z" /></clipPath>
+        <clipPath
+                id="clipPath172"
+                clipPathUnits="userSpaceOnUse"><path
          id="path170"
-         d="m 3920,1480 h 860 v 980 h -860 z" /></clipPath><clipPath
-       id="clipPath184"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 3920,1480 h 860 v 980 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath184"
+                clipPathUnits="userSpaceOnUse"><path
          id="path182"
-         d="m 4900,1480 h 620 v 980 h -620 z" /></clipPath><clipPath
-       id="clipPath196"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 4900,1480 h 620 v 980 h -620 z" /></clipPath>
+        <clipPath
+                id="clipPath196"
+                clipPathUnits="userSpaceOnUse"><path
          id="path194"
-         d="m 5630,1480 h 860 v 980 h -860 z" /></clipPath><clipPath
-       id="clipPath208"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 5630,1480 h 860 v 980 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath208"
+                clipPathUnits="userSpaceOnUse"><path
          id="path206"
-         d="m 2370,1470 h 1370 v 10 H 2370 Z" /></clipPath><clipPath
-       id="clipPath220"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 2370,1470 h 1370 v 10 H 2370 Z" /></clipPath>
+        <clipPath
+                id="clipPath220"
+                clipPathUnits="userSpaceOnUse"><path
          id="path218"
-         d="m 3920,1470 h 860 v 10 h -860 z" /></clipPath><clipPath
-       id="clipPath232"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 3920,1470 h 860 v 10 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath232"
+                clipPathUnits="userSpaceOnUse"><path
          id="path230"
-         d="m 4900,1470 h 620 v 10 h -620 z" /></clipPath><clipPath
-       id="clipPath244"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 4900,1470 h 620 v 10 h -620 z" /></clipPath>
+        <clipPath
+                id="clipPath244"
+                clipPathUnits="userSpaceOnUse"><path
          id="path242"
-         d="m 5630,1470 h 860 v 10 h -860 z" /></clipPath><clipPath
-       id="clipPath256"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 5630,1470 h 860 v 10 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath256"
+                clipPathUnits="userSpaceOnUse"><path
          id="path254"
-         d="m 3920,1450 h 860 v 20 h -860 z" /></clipPath><clipPath
-       id="clipPath268"
-       clipPathUnits="userSpaceOnUse"><path
+         d="m 3920,1450 h 860 v 20 h -860 z" /></clipPath>
+        <clipPath
+                id="clipPath268"
+                clipPathUnits="userSpaceOnUse"><path
          id="path266"
-         d="m 4900,1450 h 620 v 20 h -620 z" /></clipPath></defs><g
-     transform="matrix(1.3333333,0,0,-1.3333333,0,529.33333)"
-     id="g10"><g
+         d="m 4900,1450 h 620 v 20 h -620 z" /></clipPath></defs>
+    <g
+            transform="matrix(1.3333333,0,0,-1.3333333,0,529.33333)"
+            id="g10"><g
        transform="scale(0.1)"
        id="g12"><path
          id="path14"
          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
          d="M 265.859,2205.39 5500.51,3949.84 c 198.16,66.06 410.9,-40.31 476.99,-238.51 66.05,-198.17 -40.31,-410.86 -238.48,-476.92 L 504.379,1489.96 c -198.168,-66.05 -410.8985,40.31 -476.9571,238.48 -66.0938,198.16 40.2773,410.9 238.4371,476.95 z" /><path
-         id="path16"
-         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 3096.33,444.379 2388.2,3232.811 c 90.43,122.38 261.76,148.12 384.18,57.73 122.38,-90.39 148.13,-261.72 57.74,-384.1 L 3538.2,117.969 C 3447.77,-4.41016 3276.45,-30.1602 3154.06,60.2305 3031.64,150.66 3005.9,321.949 3096.33,444.379 Z" /><path
-         id="path18"
-         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 734.691,901.211 h 5982.5 v 2109.69 h -5982.5 z" /><path
-         id="path20"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 3724.45,1489.53 h -225.93 v 956.09 l -395.94,-956.09 h -96.56 l -394.07,956.09 v -956.09 h -225.93 v 1288.28 h 318.59 l 349.69,-847.97 351.4,847.97 h 318.75 z" /><path
-         id="path22"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="M 4767.23,1489.53 H 4564.41 V 1590 c -72.11,-82.42 -172.5,-123.59 -301.25,-123.59 -85,0 -160.39,27.34 -226.09,82.03 -65.62,54.68 -98.44,130.31 -98.44,226.87 0,99.14 32.5,174.46 97.5,225.94 65.08,51.56 140.78,77.34 227.03,77.34 132.58,0 233.01,-39.92 301.25,-119.68 v 139.06 c 0,54.06 -19.96,96.48 -59.84,127.34 -39.92,30.94 -92.73,46.41 -158.44,46.41 -104.29,0 -196.33,-39.3 -276.09,-117.81 L 3986.91,2295 c 105.63,100.39 236.29,150.62 392.04,150.62 114.68,0 208.04,-27.1 280.15,-81.24 72.07,-54.07 108.13,-139.65 108.13,-256.72 z m -424.85,115.94 c 101.64,0 175.67,32.19 222.03,96.56 v 140.94 c -46.36,64.37 -120.39,96.56 -222.03,96.56 -58.04,0 -105.74,-15.47 -143.12,-46.41 -37.31,-30.85 -55.94,-71.36 -55.94,-121.56 0,-50.23 18.63,-90.47 55.94,-120.78 37.38,-30.23 85.08,-45.31 143.12,-45.31 z" /><path
-         id="path24"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 5308.32,1466.41 c -78.55,0 -138.12,20.58 -178.75,61.71 -40.55,41.26 -60.78,100.47 -60.78,177.66 v 538.91 h -154.53 v 177.65 h 154.53 v 255 h 202.81 v -255 h 189.22 V 2244.69 H 5271.6 v -488.6 c 0,-33.55 7.7,-60.31 23.13,-80.31 15.5,-19.92 37.42,-29.84 65.78,-29.84 41.13,0 71.4,10.94 90.78,32.81 l 48.28,-152.5 c -42.5,-39.88 -106.25,-59.84 -191.25,-59.84 z" /><path
-         id="path26"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 6477.38,1489.53 h -202.65 v 587.19 c 0,68.2 -16.49,116.8 -49.38,145.78 -32.81,28.95 -79.49,43.44 -140,43.44 -47.62,0 -92.65,-12.27 -135.15,-36.72 -42.5,-24.49 -77.31,-54.06 -104.38,-88.75 v -650.94 h -202.66 v 1288.28 h 202.66 V 2295 c 34.77,41.13 81.45,76.48 140,106.09 58.63,29.69 122.07,44.53 190.31,44.53 200.82,0 301.25,-98.55 301.25,-295.62 z" /><path
-         id="path28"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         d="m 973.949,1128.48 h 2769.84 v 80.6211 H 973.949 Z" /><path
-         id="path30"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
-         d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65" /><path
-         id="path32"
-         style="fill:none;stroke:#000000;stroke-width:13.86260033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-         d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65" /><g
-         id="g34"><g
+            id="path16"
+            style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 3096.33,444.379 2388.2,3232.811 c 90.43,122.38 261.76,148.12 384.18,57.73 122.38,-90.39 148.13,-261.72 57.74,-384.1 L 3538.2,117.969 C 3447.77,-4.41016 3276.45,-30.1602 3154.06,60.2305 3031.64,150.66 3005.9,321.949 3096.33,444.379 Z"/><path
+            id="path18"
+            style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 734.691,901.211 h 5982.5 v 2109.69 h -5982.5 z"/><path
+            id="path20"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 3724.45,1489.53 h -225.93 v 956.09 l -395.94,-956.09 h -96.56 l -394.07,956.09 v -956.09 h -225.93 v 1288.28 h 318.59 l 349.69,-847.97 351.4,847.97 h 318.75 z"/><path
+            id="path22"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="M 4767.23,1489.53 H 4564.41 V 1590 c -72.11,-82.42 -172.5,-123.59 -301.25,-123.59 -85,0 -160.39,27.34 -226.09,82.03 -65.62,54.68 -98.44,130.31 -98.44,226.87 0,99.14 32.5,174.46 97.5,225.94 65.08,51.56 140.78,77.34 227.03,77.34 132.58,0 233.01,-39.92 301.25,-119.68 v 139.06 c 0,54.06 -19.96,96.48 -59.84,127.34 -39.92,30.94 -92.73,46.41 -158.44,46.41 -104.29,0 -196.33,-39.3 -276.09,-117.81 L 3986.91,2295 c 105.63,100.39 236.29,150.62 392.04,150.62 114.68,0 208.04,-27.1 280.15,-81.24 72.07,-54.07 108.13,-139.65 108.13,-256.72 z m -424.85,115.94 c 101.64,0 175.67,32.19 222.03,96.56 v 140.94 c -46.36,64.37 -120.39,96.56 -222.03,96.56 -58.04,0 -105.74,-15.47 -143.12,-46.41 -37.31,-30.85 -55.94,-71.36 -55.94,-121.56 0,-50.23 18.63,-90.47 55.94,-120.78 37.38,-30.23 85.08,-45.31 143.12,-45.31 z"/><path
+            id="path24"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 5308.32,1466.41 c -78.55,0 -138.12,20.58 -178.75,61.71 -40.55,41.26 -60.78,100.47 -60.78,177.66 v 538.91 h -154.53 v 177.65 h 154.53 v 255 h 202.81 v -255 h 189.22 V 2244.69 H 5271.6 v -488.6 c 0,-33.55 7.7,-60.31 23.13,-80.31 15.5,-19.92 37.42,-29.84 65.78,-29.84 41.13,0 71.4,10.94 90.78,32.81 l 48.28,-152.5 c -42.5,-39.88 -106.25,-59.84 -191.25,-59.84 z"/><path
+            id="path26"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 6477.38,1489.53 h -202.65 v 587.19 c 0,68.2 -16.49,116.8 -49.38,145.78 -32.81,28.95 -79.49,43.44 -140,43.44 -47.62,0 -92.65,-12.27 -135.15,-36.72 -42.5,-24.49 -77.31,-54.06 -104.38,-88.75 v -650.94 h -202.66 v 1288.28 h 202.66 V 2295 c 34.77,41.13 81.45,76.48 140,106.09 58.63,29.69 122.07,44.53 190.31,44.53 200.82,0 301.25,-98.55 301.25,-295.62 z"/><path
+            id="path28"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+            d="m 973.949,1128.48 h 2769.84 v 80.6211 H 973.949 Z"/><path
+            id="path30"
+            style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+            d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65"/><path
+            id="path32"
+            style="fill:none;stroke:#000000;stroke-width:13.86260033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+            d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65"/><g
+            id="g34"><g
            clip-path="url(#clipPath40)"
            id="g36"><g
              transform="matrix(1370.4,0,0,12,2370,2778)"
@@ -141,7 +162,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g46"><g
+            id="g46"><g
            clip-path="url(#clipPath52)"
            id="g48"><g
              transform="matrix(861.6,0,0,12,5630,2778)"
@@ -153,7 +174,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g58"><g
+            id="g58"><g
            clip-path="url(#clipPath64)"
            id="g60"><g
              transform="matrix(1300.8,0,0,91.2,970,2688.8)"
@@ -165,7 +186,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g70"><g
+            id="g70"><g
            clip-path="url(#clipPath76)"
            id="g72"><g
              transform="matrix(1370.4,0,0,91.2,2370,2688.8)"
@@ -177,7 +198,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g82"><g
+            id="g82"><g
            clip-path="url(#clipPath88)"
            id="g84"><g
              transform="matrix(861.6,0,0,91.2,5630,2688.8)"
@@ -189,7 +210,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g94"><g
+            id="g94"><g
            clip-path="url(#clipPath100)"
            id="g96"><g
              transform="matrix(1300.8,0,0,230.4,970,2459.6)"
@@ -201,7 +222,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g106"><g
+            id="g106"><g
            clip-path="url(#clipPath112)"
            id="g108"><g
              transform="matrix(1370.4,0,0,230.4,2370,2459.6)"
@@ -213,7 +234,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g118"><g
+            id="g118"><g
            clip-path="url(#clipPath124)"
            id="g120"><g
              transform="matrix(621.6,0,0,230.4,4900,2459.6)"
@@ -225,7 +246,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g130"><g
+            id="g130"><g
            clip-path="url(#clipPath136)"
            id="g132"><g
              transform="matrix(861.6,0,0,230.4,5630,2459.6)"
@@ -237,7 +258,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g142"><g
+            id="g142"><g
            clip-path="url(#clipPath148)"
            id="g144"><g
              transform="matrix(1300.8,0,0,981.6,970,1478.4)"
@@ -249,7 +270,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g154"><g
+            id="g154"><g
            clip-path="url(#clipPath160)"
            id="g156"><g
              transform="matrix(1370.4,0,0,981.6,2370,1478.4)"
@@ -261,7 +282,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g166"><g
+            id="g166"><g
            clip-path="url(#clipPath172)"
            id="g168"><g
              transform="matrix(861.6,0,0,981.6,3920,1478.4)"
@@ -273,7 +294,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g178"><g
+            id="g178"><g
            clip-path="url(#clipPath184)"
            id="g180"><g
              transform="matrix(621.6,0,0,981.6,4900,1478.4)"
@@ -285,7 +306,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g190"><g
+            id="g190"><g
            clip-path="url(#clipPath196)"
            id="g192"><g
              transform="matrix(861.6,0,0,981.6,5630,1478.4)"
@@ -297,7 +318,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g202"><g
+            id="g202"><g
            clip-path="url(#clipPath208)"
            id="g204"><g
              transform="matrix(1370.4,0,0,12,2370,1468)"
@@ -309,7 +330,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g214"><g
+            id="g214"><g
            clip-path="url(#clipPath220)"
            id="g216"><g
              transform="matrix(861.6,0,0,12,3920,1468)"
@@ -321,7 +342,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g226"><g
+            id="g226"><g
            clip-path="url(#clipPath232)"
            id="g228"><g
              transform="matrix(621.6,0,0,12,4900,1468)"
@@ -333,7 +354,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g238"><g
+            id="g238"><g
            clip-path="url(#clipPath244)"
            id="g240"><g
              transform="matrix(861.6,0,0,12,5630,1468)"
@@ -345,7 +366,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g250"><g
+            id="g250"><g
            clip-path="url(#clipPath256)"
            id="g252"><g
              transform="matrix(861.6,0,0,21.6,3920,1448.4)"
@@ -357,7 +378,7 @@
                style="image-rendering:optimizeSpeed"
                height="1"
                width="1" /></g></g></g><g
-         id="g262"><g
+            id="g262"><g
            clip-path="url(#clipPath268)"
            id="g264"><g
              transform="matrix(621.6,0,0,21.6,4900,1448.4)"
diff --git a/docs/nd-structure.md b/docs/nd-structure.md
index 835304b9f..ec9b4d521 100644
--- a/docs/nd-structure.md
+++ b/docs/nd-structure.md
@@ -10,11 +10,11 @@ structures. In `kmath` performance depends on which particular context was used
 Let us consider following contexts:
 ```kotlin
     // automatically build context most suited for given type.
-    val autoField = NDField.auto(RealField, dim, dim)
+    val autoField = NDField.auto(DoubleField, dim, dim)
     // specialized nd-field for Double. It works as generic Double field as well
     val specializedField = NDField.real(dim, dim)
     //A generic boxing field. It should be used for objects, not primitives.
-    val genericField = NDField.buffered(RealField, dim, dim)
+    val genericField = NDField.buffered(DoubleField, dim, dim)
 ```
 Now let us perform several tests and see which implementation is best suited for each case:
 
diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md
index 8ac71193f..cb741bc6f 100644
--- a/docs/templates/ARTIFACT-TEMPLATE.md
+++ b/docs/templates/ARTIFACT-TEMPLATE.md
@@ -13,9 +13,6 @@
 >     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 {
@@ -29,9 +26,6 @@
 >     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 {
diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md
index 10bc7aab1..4366c8fcd 100644
--- a/docs/templates/README-TEMPLATE.md
+++ b/docs/templates/README-TEMPLATE.md
@@ -3,9 +3,7 @@
 
 ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
 
-Bintray:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
-
-Bintray-dev:    [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
+[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22)
 
 # KMath
 
@@ -106,7 +104,7 @@ repositories {
 }
 
 dependencies {
-    api("kscience.kmath:kmath-core:$version")
+    api("${group}:kmath-core:$version")
     // api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version
 }
 ```
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index 0301e4d67..5dd40b609 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -113,6 +113,6 @@ tasks.withType<KotlinCompile> {
     kotlinOptions.jvmTarget = "11"
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
 }
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 1c3bbab75..1db1d77dc 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
@@ -5,14 +5,14 @@ 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.DoubleBuffer
 import space.kscience.kmath.structures.MutableBuffer
-import space.kscience.kmath.structures.RealBuffer
 
 @State(Scope.Benchmark)
 internal class BufferBenchmark {
     @Benchmark
-    fun genericRealBufferReadWrite() {
-        val buffer = RealBuffer(size) { it.toDouble() }
+    fun genericDoubleBufferReadWrite() {
+        val buffer = DoubleBuffer(size) { it.toDouble() }
 
         (0 until size).forEach {
             buffer[it]
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 dbf373929..6a2126dc1 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
@@ -8,7 +8,7 @@ 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.DoubleField
 import kotlin.random.Random
 
 @State(Scope.Benchmark)
@@ -51,7 +51,7 @@ internal class DotBenchmark {
 
     @Benchmark
     fun bufferedDot(blackhole: Blackhole) {
-        LinearSpace.auto(RealField).invoke {
+        LinearSpace.auto(DoubleField).invoke {
             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 e5cfbf9f6..0899241f9 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
@@ -10,7 +10,7 @@ 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.RealField
+import space.kscience.kmath.operations.DoubleField
 import space.kscience.kmath.operations.bindSymbol
 import kotlin.random.Random
 
@@ -68,7 +68,7 @@ internal class ExpressionsInterpretersBenchmark {
     }
 
     private companion object {
-        private val algebra = RealField
+        private val algebra = DoubleField
         private val x by symbol
     }
 }
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 aeee0dafe..09c415d9a 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
@@ -5,7 +5,7 @@ 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.operations.DoubleField
 import space.kscience.kmath.structures.Buffer
 
 @State(Scope.Benchmark)
@@ -13,7 +13,7 @@ internal class NDFieldBenchmark {
     @Benchmark
     fun autoFieldAdd(blackhole: Blackhole) {
         with(autoField) {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += one }
             blackhole.consume(res)
         }
@@ -22,7 +22,7 @@ internal class NDFieldBenchmark {
     @Benchmark
     fun specializedFieldAdd(blackhole: Blackhole) {
         with(specializedField) {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
             blackhole.consume(res)
         }
@@ -32,7 +32,7 @@ internal class NDFieldBenchmark {
     @Benchmark
     fun boxingFieldAdd(blackhole: Blackhole) {
         with(genericField) {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
             blackhole.consume(res)
         }
@@ -41,8 +41,8 @@ internal class NDFieldBenchmark {
     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)
+        private val autoField = AlgebraND.auto(DoubleField, dim, dim)
+        private val specializedField = AlgebraND.real(dim, dim)
+        private val genericField = AlgebraND.field(DoubleField, 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 c511173a9..fd0188bd6 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
@@ -5,11 +5,11 @@ import kotlinx.benchmark.Blackhole
 import kotlinx.benchmark.Scope
 import kotlinx.benchmark.State
 import org.jetbrains.bio.viktor.F64Array
-import space.kscience.kmath.nd.NDAlgebra
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.AlgebraND
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.nd.auto
 import space.kscience.kmath.nd.real
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import space.kscience.kmath.viktor.ViktorNDField
 
 @State(Scope.Benchmark)
@@ -17,7 +17,7 @@ internal class ViktorBenchmark {
     @Benchmark
     fun automaticFieldAddition(blackhole: Blackhole) {
         with(autoField) {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
             blackhole.consume(res)
         }
@@ -26,7 +26,7 @@ internal class ViktorBenchmark {
     @Benchmark
     fun realFieldAddition(blackhole: Blackhole) {
         with(realField) {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
             blackhole.consume(res)
         }
@@ -54,8 +54,8 @@ internal class ViktorBenchmark {
         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 autoField = AlgebraND.auto(DoubleField, dim, dim)
+        private val realField = AlgebraND.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 0036b615c..b6bd036ba 100644
--- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
+++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
@@ -5,11 +5,11 @@ import kotlinx.benchmark.Blackhole
 import kotlinx.benchmark.Scope
 import kotlinx.benchmark.State
 import org.jetbrains.bio.viktor.F64Array
-import space.kscience.kmath.nd.NDAlgebra
+import space.kscience.kmath.nd.AlgebraND
 import space.kscience.kmath.nd.auto
 import space.kscience.kmath.nd.real
-import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.viktor.ViktorNDField
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.viktor.ViktorFieldND
 
 @State(Scope.Benchmark)
 internal class ViktorLogBenchmark {
@@ -46,8 +46,8 @@ internal class ViktorLogBenchmark {
         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))
+        private val autoField = AlgebraND.auto(DoubleField, dim, dim)
+        private val realNdField = AlgebraND.real(dim, dim)
+        private val viktorField = ViktorFieldND(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 c342fc3ef..17c85eea5 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
@@ -1,10 +1,10 @@
 package space.kscience.kmath.ast
 
 import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 
 fun main() {
-    val expr = RealField.mstInField {
+    val expr = DoubleField.mstInField {
         val x = bindSymbol("x")
         x * 2.0 + number(2.0) / x - 16.0
     }
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
index 16304a458..23c9d5b41 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
@@ -5,7 +5,7 @@ import space.kscience.kmath.expressions.derivative
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.expressions.symbol
 import space.kscience.kmath.kotlingrad.differentiable
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 
 /**
  * In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with
@@ -14,11 +14,11 @@ import space.kscience.kmath.operations.RealField
 fun main() {
     val x by symbol
 
-    val actualDerivative = MstExpression(RealField, "x^2-4*x-44".parseMath())
+    val actualDerivative = MstExpression(DoubleField, "x^2-4*x-44".parseMath())
         .differentiable()
         .derivative(x)
         .compile()
 
-    val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile()
+    val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile()
     assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0))
 }
diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
index 63b819dc9..ef0c29a2d 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
@@ -8,7 +8,7 @@ import kscience.plotly.models.TraceValues
 import space.kscience.kmath.commons.optimization.chiSquared
 import space.kscience.kmath.commons.optimization.minimize
 import space.kscience.kmath.expressions.symbol
-import space.kscience.kmath.real.RealVector
+import space.kscience.kmath.real.DoubleVector
 import space.kscience.kmath.real.map
 import space.kscience.kmath.real.step
 import space.kscience.kmath.stat.*
@@ -26,7 +26,7 @@ private val c by symbol
 /**
  * Shortcut to use buffers in plotly
  */
-operator fun TraceValues.invoke(vector: RealVector) {
+operator fun TraceValues.invoke(vector: DoubleVector) {
     numbers = vector.asIterable()
 }
 
@@ -90,10 +90,10 @@ fun main() {
             }
         }
         br()
-        h3{
+        h3 {
             +"Fit result: $result"
         }
-        h3{
+        h3 {
             +"Chi2/dof = ${result.value / (x.size - 3)}"
         }
     }
diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
index 8dd3d7f6b..8940aeac9 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
@@ -1,11 +1,11 @@
 package space.kscience.kmath.linear
 
 import space.kscience.kmath.real.*
-import space.kscience.kmath.structures.RealBuffer
+import space.kscience.kmath.structures.DoubleBuffer
 
 fun main() {
-    val x0 = Point(0.0, 0.0, 0.0)
-    val sigma = Point(1.0, 1.0, 1.0)
+    val x0 = DoubleVector(0.0, 0.0, 0.0)
+    val sigma = DoubleVector(1.0, 1.0, 1.0)
 
     val gaussian: (Point<Double>) -> Double = { x ->
         require(x.size == x0.size)
@@ -14,9 +14,9 @@ fun main() {
 
     fun ((Point<Double>) -> Double).grad(x: Point<Double>): Point<Double> {
         require(x.size == x0.size)
-        return RealBuffer(x.size) { i ->
+        return DoubleBuffer(x.size) { i ->
             val h = sigma[i] / 5
-            val dVector = RealBuffer(x.size) { if (it == i) h else 0.0 }
+            val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 }
             val f1 = invoke(x + dVector / 2)
             val f0 = invoke(x - dVector / 2)
             (f1 - f0) / h
diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt
index 5330d9e40..105fb108e 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt
@@ -2,17 +2,17 @@ package space.kscience.kmath.operations
 
 import space.kscience.kmath.complex.Complex
 import space.kscience.kmath.complex.complex
-import space.kscience.kmath.nd.NDAlgebra
+import space.kscience.kmath.nd.AlgebraND
 
 fun main() {
     // 2d element
-    val element = NDAlgebra.complex(2, 2).produce { (i, j) ->
+    val element = AlgebraND.complex(2, 2).produce { (i, j) ->
         Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble())
     }
     println(element)
 
     // 1d element operation
-    val result = with(NDAlgebra.complex(8)) {
+    val result = with(AlgebraND.complex(8)) {
         val a = produce { (it) -> i * it - it.toDouble() }
         val b = 3
         val c = Complex(1.0, 1.0)
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt
index b8cbc9a57..68af2560b 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt
@@ -4,8 +4,8 @@ package space.kscience.kmath.structures
 
 import space.kscience.kmath.complex.*
 import space.kscience.kmath.linear.transpose
-import space.kscience.kmath.nd.NDAlgebra
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.AlgebraND
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.nd.as2D
 import space.kscience.kmath.nd.real
 import space.kscience.kmath.operations.invoke
@@ -15,12 +15,12 @@ fun main() {
     val dim = 1000
     val n = 1000
 
-    val realField = NDAlgebra.real(dim, dim)
-    val complexField: ComplexNDField = NDAlgebra.complex(dim, dim)
+    val realField = AlgebraND.real(dim, dim)
+    val complexField: ComplexFieldND = AlgebraND.complex(dim, dim)
 
     val realTime = measureTimeMillis {
         realField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) {
                 res += 1.0
             }
@@ -31,7 +31,7 @@ fun main() {
 
     val complexTime = measureTimeMillis {
         complexField {
-            var res: NDStructure<Complex> = one
+            var res: StructureND<Complex> = one
             repeat(n) {
                 res += 1.0
             }
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
index 10fb3cb3d..f7dc3280a 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
@@ -4,7 +4,7 @@ import kotlinx.coroutines.GlobalScope
 import org.nd4j.linalg.factory.Nd4j
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.nd4j.Nd4jArrayField
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import space.kscience.kmath.operations.invoke
 import space.kscience.kmath.viktor.ViktorNDField
 import kotlin.contracts.InvocationKind
@@ -24,56 +24,56 @@ fun main() {
     val n = 1000
 
     // automatically build context most suited for given type.
-    val autoField = NDAlgebra.auto(RealField, dim, dim)
+    val autoField = AlgebraND.auto(DoubleField, dim, dim)
     // specialized nd-field for Double. It works as generic Double field as well
-    val realField = NDAlgebra.real(dim, dim)
+    val realField = AlgebraND.real(dim, dim)
     //A generic boxing field. It should be used for objects, not primitives.
-    val boxingField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
+    val boxingField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
     // Nd4j specialized field.
     val nd4jField = Nd4jArrayField.real(dim, dim)
     //viktor field
-    val viktorField = ViktorNDField(dim,dim)
+    val viktorField = ViktorNDField(dim, dim)
     //parallel processing based on Java Streams
-    val parallelField = NDAlgebra.realWithStream(dim,dim)
+    val parallelField = AlgebraND.realWithStream(dim, dim)
 
     measureAndPrint("Boxing addition") {
         boxingField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
         }
     }
 
     measureAndPrint("Specialized addition") {
         realField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
         }
     }
 
     measureAndPrint("Nd4j specialized addition") {
         nd4jField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
         }
     }
 
     measureAndPrint("Viktor addition") {
         viktorField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
         }
     }
 
     measureAndPrint("Parallel stream addition") {
         parallelField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
         }
     }
 
     measureAndPrint("Automatic field addition") {
         autoField {
-            var res: NDStructure<Double> = one
+            var res: StructureND<Double> = one
             repeat(n) { res += 1.0 }
         }
     }
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt
deleted file mode 100644
index 0c914468d..000000000
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-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 java.util.*
-import java.util.stream.IntStream
-
-/**
- * A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution
- */
-@OptIn(UnstableKMathAPI::class)
-class StreamRealNDField(
-    override val shape: IntArray,
-) : NDField<Double, RealField>,
-    NumbersAddOperations<NDStructure<Double>>,
-    ExtendedField<NDStructure<Double>> {
-
-    private val strides = DefaultStrides(shape)
-    override val elementContext: RealField get() = RealField
-    override val zero: NDBuffer<Double> by lazy { produce { zero } }
-    override val one: NDBuffer<Double> by lazy { produce { one } }
-
-    override fun number(value: Number): NDBuffer<Double> {
-        val d = value.toDouble() // minimize conversions
-        return produce { d }
-    }
-
-    private val NDStructure<Double>.buffer: RealBuffer
-        get() = when {
-            !shape.contentEquals(this@StreamRealNDField.shape) -> throw ShapeMismatchException(
-                this@StreamRealNDField.shape,
-                shape
-            )
-            this is NDBuffer && this.strides == this@StreamRealNDField.strides -> this.buffer as RealBuffer
-            else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
-        }
-
-
-    override fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer<Double> {
-        val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
-            val index = strides.index(offset)
-            RealField.initializer(index)
-        }.toArray()
-
-        return NDBuffer(strides, array.asBuffer())
-    }
-
-    override fun NDStructure<Double>.map(
-        transform: RealField.(Double) -> Double,
-    ): NDBuffer<Double> {
-        val array = Arrays.stream(buffer.array).parallel().map { RealField.transform(it) }.toArray()
-        return NDBuffer(strides, array.asBuffer())
-    }
-
-    override fun NDStructure<Double>.mapIndexed(
-        transform: RealField.(index: IntArray, Double) -> Double,
-    ): NDBuffer<Double> {
-        val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
-            RealField.transform(
-                strides.index(offset),
-                buffer.array[offset]
-            )
-        }.toArray()
-
-        return NDBuffer(strides, array.asBuffer())
-    }
-
-    override fun combine(
-        a: NDStructure<Double>,
-        b: NDStructure<Double>,
-        transform: RealField.(Double, Double) -> Double,
-    ): NDBuffer<Double> {
-        val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
-            RealField.transform(a.buffer.array[offset], b.buffer.array[offset])
-        }.toArray()
-        return NDBuffer(strides, array.asBuffer())
-    }
-
-    override fun NDStructure<Double>.unaryMinus(): NDStructure<Double> = map { -it }
-
-    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) }
-
-    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/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt
new file mode 100644
index 000000000..6741209fc
--- /dev/null
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt
@@ -0,0 +1,107 @@
+package space.kscience.kmath.structures
+
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.*
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.NumbersAddOperations
+import java.util.*
+import java.util.stream.IntStream
+
+/**
+ * A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution
+ */
+@OptIn(UnstableKMathAPI::class)
+class StreamDoubleFieldND(
+    override val shape: IntArray,
+) : FieldND<Double, DoubleField>,
+    NumbersAddOperations<StructureND<Double>>,
+    ExtendedField<StructureND<Double>> {
+
+    private val strides = DefaultStrides(shape)
+    override val elementContext: DoubleField get() = DoubleField
+    override val zero: BufferND<Double> by lazy { produce { zero } }
+    override val one: BufferND<Double> by lazy { produce { one } }
+
+    override fun number(value: Number): BufferND<Double> {
+        val d = value.toDouble() // minimize conversions
+        return produce { d }
+    }
+
+    private val StructureND<Double>.buffer: DoubleBuffer
+        get() = when {
+            !shape.contentEquals(this@StreamDoubleFieldND.shape) -> throw ShapeMismatchException(
+                this@StreamDoubleFieldND.shape,
+                shape
+            )
+            this is BufferND && this.strides == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer
+            else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
+        }
+
+
+    override fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
+        val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
+            val index = strides.index(offset)
+            DoubleField.initializer(index)
+        }.toArray()
+
+        return BufferND(strides, array.asBuffer())
+    }
+
+    override fun StructureND<Double>.map(
+        transform: DoubleField.(Double) -> Double,
+    ): BufferND<Double> {
+        val array = Arrays.stream(buffer.array).parallel().map { DoubleField.transform(it) }.toArray()
+        return BufferND(strides, array.asBuffer())
+    }
+
+    override fun StructureND<Double>.mapIndexed(
+        transform: DoubleField.(index: IntArray, Double) -> Double,
+    ): BufferND<Double> {
+        val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
+            DoubleField.transform(
+                strides.index(offset),
+                buffer.array[offset]
+            )
+        }.toArray()
+
+        return BufferND(strides, array.asBuffer())
+    }
+
+    override fun combine(
+        a: StructureND<Double>,
+        b: StructureND<Double>,
+        transform: DoubleField.(Double, Double) -> Double,
+    ): BufferND<Double> {
+        val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
+            DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset])
+        }.toArray()
+        return BufferND(strides, array.asBuffer())
+    }
+
+    override fun StructureND<Double>.unaryMinus(): StructureND<Double> = map { -it }
+
+    override fun scale(a: StructureND<Double>, value: Double): StructureND<Double> = a.map { it * value }
+
+    override fun power(arg: StructureND<Double>, pow: Number): BufferND<Double> = arg.map { power(it, pow) }
+
+    override fun exp(arg: StructureND<Double>): BufferND<Double> = arg.map { exp(it) }
+
+    override fun ln(arg: StructureND<Double>): BufferND<Double> = arg.map { ln(it) }
+
+    override fun sin(arg: StructureND<Double>): BufferND<Double> = arg.map { sin(it) }
+    override fun cos(arg: StructureND<Double>): BufferND<Double> = arg.map { cos(it) }
+    override fun tan(arg: StructureND<Double>): BufferND<Double> = arg.map { tan(it) }
+    override fun asin(arg: StructureND<Double>): BufferND<Double> = arg.map { asin(it) }
+    override fun acos(arg: StructureND<Double>): BufferND<Double> = arg.map { acos(it) }
+    override fun atan(arg: StructureND<Double>): BufferND<Double> = arg.map { atan(it) }
+
+    override fun sinh(arg: StructureND<Double>): BufferND<Double> = arg.map { sinh(it) }
+    override fun cosh(arg: StructureND<Double>): BufferND<Double> = arg.map { cosh(it) }
+    override fun tanh(arg: StructureND<Double>): BufferND<Double> = arg.map { tanh(it) }
+    override fun asinh(arg: StructureND<Double>): BufferND<Double> = arg.map { asinh(it) }
+    override fun acosh(arg: StructureND<Double>): BufferND<Double> = arg.map { acosh(it) }
+    override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
+}
+
+fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape)
\ No newline at end of file
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt
index 7f6d73394..1c8a923c7 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt
@@ -1,16 +1,16 @@
 package space.kscience.kmath.structures
 
+import space.kscience.kmath.nd.BufferND
 import space.kscience.kmath.nd.DefaultStrides
-import space.kscience.kmath.nd.NDBuffer
 import kotlin.system.measureTimeMillis
 
 @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
 fun main() {
     val n = 6000
     val array = DoubleArray(n * n) { 1.0 }
-    val buffer = RealBuffer(array)
+    val buffer = DoubleBuffer(array)
     val strides = DefaultStrides(intArrayOf(n, n))
-    val structure = NDBuffer(strides, buffer)
+    val structure = BufferND(strides, buffer)
 
     measureTimeMillis {
         var res = 0.0
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 66d85edff..27741be61 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
@@ -1,13 +1,13 @@
 package space.kscience.kmath.structures
 
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.nd.mapToBuffer
 import kotlin.system.measureTimeMillis
 
 @Suppress("UNUSED_VARIABLE")
 fun main() {
     val n = 6000
-    val structure = NDStructure.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 }
+    val structure = StructureND.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")
@@ -20,10 +20,10 @@ fun main() {
 
     println("Array mapping finished in $time2 millis")
 
-    val buffer = RealBuffer(DoubleArray(n * n) { 1.0 })
+    val buffer = DoubleBuffer(DoubleArray(n * n) { 1.0 })
 
     val time3 = measureTimeMillis {
-        val target = RealBuffer(DoubleArray(n * n))
+        val target = DoubleBuffer(DoubleArray(n * n))
         val res = array.forEachIndexed { index, value ->
             target[index] = value + 1
         }
diff --git a/gradle.properties b/gradle.properties
index e28e22e8e..7ff50a435 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,10 +1,8 @@
 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=1G
+org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
 org.gradle.parallel=true
-
-kotlin.mpp.enableGranularSourceSetsMetadata=true
-kotlin.native.enableDependencyPropagation=false
-
diff --git a/kmath-ast/README.md b/kmath-ast/README.md
index e52f0fa96..ee14604d2 100644
--- a/kmath-ast/README.md
+++ b/kmath-ast/README.md
@@ -2,17 +2,17 @@
 
 This subproject implements the following features:
 
- - [expression-language](src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser
- - [mst](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
- - [mst-building](src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
- - [mst-interpreter](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter
- - [mst-jvm-codegen](src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
- - [mst-js-codegen](src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
+ - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
+ - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
+ - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
+ - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter
+ - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
+ - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
 
 
 > #### Artifact:
 >
-> This module artifact: `space.kscience:kmath-ast:0.2.0`.
+> This module artifact: `space.kscience:kmath-ast:0.3.0-dev-3`.
 >
 > Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion)
 >
@@ -25,13 +25,10 @@ This subproject implements the following features:
 >     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-ast:0.2.0'
+>     implementation 'space.kscience:kmath-ast:0.3.0-dev-3'
 > }
 > ```
 > **Gradle Kotlin DSL:**
@@ -41,13 +38,10 @@ This subproject implements the following features:
 >     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-ast:0.2.0")
+>     implementation("space.kscience:kmath-ast:0.3.0-dev-3")
 > }
 > ```
 
@@ -61,10 +55,10 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
 For example, the following builder:
 
 ```kotlin
-RealField.mstInField { symbol("x") + 2 }.compile()
+DoubleField.mstInField { symbol("x") + 2 }.compile()
 ``` 
 
-… leads to generation of bytecode, which can be decompiled to the following Java class:
+… leads to generation of bytecode, which can be decompiled to the following Java class:
 
 ```java
 package space.kscience.kmath.asm.generated;
@@ -94,8 +88,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
 This API extends MST and MstExpression, so you may optimize as both of them:
 
 ```kotlin
-RealField.mstInField { symbol("x") + 2 }.compile()
-RealField.expression("x+2".parseMath())
+DoubleField.mstInField { symbol("x") + 2 }.compile()
+DoubleField.expression("x+2".parseMath())
 ```
 
 #### Known issues
@@ -109,7 +103,7 @@ RealField.expression("x+2".parseMath())
 A similar feature is also available on JS.
 
 ```kotlin
-RealField.mstInField { symbol("x") + 2 }.compile()
+DoubleField.mstInField { symbol("x") + 2 }.compile()
 ``` 
 
 The code above returns expression implemented with such a JS function:
diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts
index 5b764459c..e3a7faf0a 100644
--- a/kmath-ast/build.gradle.kts
+++ b/kmath-ast/build.gradle.kts
@@ -58,36 +58,36 @@ readme {
     feature(
         id = "expression-language",
         description = "Expression language and its parser",
-        ref = "src/jvmMain/kotlin/kscience/kmath/ast/parser.kt"
+        ref = "src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt"
     )
 
     feature(
         id = "mst",
         description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation",
-        ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt"
     )
 
     feature(
         id = "mst-building",
         description = "MST building algebraic structure",
-        ref = "src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt"
     )
 
     feature(
         id = "mst-interpreter",
         description = "MST interpreter",
-        ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt"
     )
 
     feature(
         id = "mst-jvm-codegen",
         description = "Dynamic MST to JVM bytecode compiler",
-        ref = "src/jvmMain/kotlin/kscience/kmath/asm/asm.kt"
+        ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt"
     )
 
     feature(
         id = "mst-js-codegen",
         description = "Dynamic MST to JS compiler",
-        ref = "src/jsMain/kotlin/kscience/kmath/estree/estree.kt"
+        ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
     )
 }
diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md
index 2712cba75..80e48008b 100644
--- a/kmath-ast/docs/README-TEMPLATE.md
+++ b/kmath-ast/docs/README-TEMPLATE.md
@@ -16,7 +16,7 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
 For example, the following builder:
 
 ```kotlin
-RealField.mstInField { symbol("x") + 2 }.compile()
+DoubleField.mstInField { symbol("x") + 2 }.compile()
 ``` 
 
 … leads to generation of bytecode, which can be decompiled to the following Java class:
@@ -49,8 +49,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
 This API extends MST and MstExpression, so you may optimize as both of them:
 
 ```kotlin
-RealField.mstInField { symbol("x") + 2 }.compile()
-RealField.expression("x+2".parseMath())
+DoubleField.mstInField { symbol("x") + 2 }.compile()
+DoubleField.expression("x+2".parseMath())
 ```
 
 #### Known issues
@@ -64,7 +64,7 @@ RealField.expression("x+2".parseMath())
 A similar feature is also available on JS.
 
 ```kotlin
-RealField.mstInField { symbol("x") + 2 }.compile()
+DoubleField.mstInField { symbol("x") + 2 }.compile()
 ``` 
 
 The code above returns expression implemented with such a JS function:
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 5ed39687b..c1aeae90e 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
@@ -50,7 +50,7 @@ public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
  */
 @OptIn(UnstableKMathAPI::class)
 public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
-    public override val zero: MST.Numeric  get() = MstGroup.zero
+    public override val zero: MST.Numeric get() = MstGroup.zero
     public override val one: MST.Numeric = number(1.0)
 
     public override fun number(value: Number): MST.Numeric = MstGroup.number(value)
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 bb34254b1..683c0337c 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
@@ -5,7 +5,7 @@ import space.kscience.kmath.complex.ComplexField
 import space.kscience.kmath.complex.toComplex
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.operations.ByteRing
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -73,7 +73,7 @@ internal class TestESTreeConsistencyWithInterpreter {
 
     @Test
     fun realField() {
-        val res1 = RealField.mstInField {
+        val res1 = DoubleField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
                 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
@@ -81,7 +81,7 @@ internal class TestESTreeConsistencyWithInterpreter {
             ) + zero
         }("x" to 2.0)
 
-        val res2 = RealField.mstInField {
+        val res2 = DoubleField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
                 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
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 27bf2f167..d59c048b6 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
@@ -4,7 +4,7 @@ import space.kscience.kmath.ast.mstInExtendedField
 import space.kscience.kmath.ast.mstInField
 import space.kscience.kmath.ast.mstInGroup
 import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.random.Random
 import kotlin.test.Test
 import kotlin.test.assertEquals
@@ -12,27 +12,29 @@ import kotlin.test.assertEquals
 internal class TestESTreeOperationsSupport {
     @Test
     fun testUnaryOperationInvocation() {
-        val expression = RealField.mstInGroup { -bindSymbol("x") }.compile()
+        val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-2.0, res)
     }
 
     @Test
     fun testBinaryOperationInvocation() {
-        val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
+        val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-1.0, res)
     }
 
     @Test
     fun testConstProductInvocation() {
-        val res = RealField.mstInField { bindSymbol("x") * 2 }("x" to 2.0)
+        val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0)
         assertEquals(4.0, res)
     }
 
     @Test
     fun testMultipleCalls() {
-        val e = RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }.compile()
+        val e =
+            DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
+                .compile()
         val r = Random(0)
         var s = 0.0
         repeat(1000000) { s += e("x" to r.nextDouble()) }
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt
index c5e43241a..6be963175 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt
@@ -2,50 +2,50 @@ package space.kscience.kmath.estree
 
 import space.kscience.kmath.ast.mstInField
 import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 internal class TestESTreeSpecialization {
     @Test
     fun testUnaryPlus() {
-        val expr = RealField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile()
         assertEquals(2.0, expr("x" to 2.0))
     }
 
     @Test
     fun testUnaryMinus() {
-        val expr = RealField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile()
         assertEquals(-2.0, expr("x" to 2.0))
     }
 
     @Test
     fun testAdd() {
-        val expr = RealField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile()
         assertEquals(4.0, expr("x" to 2.0))
     }
 
     @Test
     fun testSine() {
-        val expr = RealField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile()
         assertEquals(0.0, expr("x" to 0.0))
     }
 
     @Test
     fun testMinus() {
-        val expr = RealField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile()
         assertEquals(0.0, expr("x" to 2.0))
     }
 
     @Test
     fun testDivide() {
-        val expr = RealField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile()
         assertEquals(1.0, expr("x" to 2.0))
     }
 
     @Test
     fun testPower() {
-        val expr = RealField
+        val expr = DoubleField
             .mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) }
             .compile()
 
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
index 1124a860f..4522c966f 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
@@ -86,7 +86,7 @@ internal inline fun ClassWriter.visitField(
     descriptor: String,
     signature: String?,
     value: Any?,
-    block: FieldVisitor.() -> Unit
+    block: FieldVisitor.() -> Unit,
 ): FieldVisitor {
     contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
     return visitField(access, name, descriptor, signature, value).apply(block)
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 7cc1497d0..abc320360 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
@@ -5,7 +5,7 @@ import space.kscience.kmath.complex.ComplexField
 import space.kscience.kmath.complex.toComplex
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.operations.ByteRing
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -73,7 +73,7 @@ internal class TestAsmConsistencyWithInterpreter {
 
     @Test
     fun realField() {
-        val res1 = RealField.mstInField {
+        val res1 = DoubleField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
                 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
@@ -81,7 +81,7 @@ internal class TestAsmConsistencyWithInterpreter {
             ) + zero
         }("x" to 2.0)
 
-        val res2 = RealField.mstInField {
+        val res2 = DoubleField.mstInField {
             +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
                 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
                         + number(1),
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 e99075f07..5d70cb76b 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
@@ -4,7 +4,7 @@ import space.kscience.kmath.ast.mstInExtendedField
 import space.kscience.kmath.ast.mstInField
 import space.kscience.kmath.ast.mstInGroup
 import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.random.Random
 import kotlin.test.Test
 import kotlin.test.assertEquals
@@ -12,27 +12,29 @@ import kotlin.test.assertEquals
 internal class TestAsmOperationsSupport {
     @Test
     fun testUnaryOperationInvocation() {
-        val expression = RealField.mstInGroup { -bindSymbol("x") }.compile()
+        val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-2.0, res)
     }
 
     @Test
     fun testBinaryOperationInvocation() {
-        val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
+        val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
         val res = expression("x" to 2.0)
         assertEquals(-1.0, res)
     }
 
     @Test
     fun testConstProductInvocation() {
-        val res = RealField.mstInField { bindSymbol("x") * 2 }("x" to 2.0)
+        val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0)
         assertEquals(4.0, res)
     }
 
     @Test
     fun testMultipleCalls() {
-        val e = RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }.compile()
+        val e =
+            DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
+                .compile()
         val r = Random(0)
         var s = 0.0
         repeat(1000000) { s += e("x" to r.nextDouble()) }
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt
index a214ca4ad..f485260c9 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt
@@ -2,50 +2,50 @@ package space.kscience.kmath.asm
 
 import space.kscience.kmath.ast.mstInField
 import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 internal class TestAsmSpecialization {
     @Test
     fun testUnaryPlus() {
-        val expr = RealField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile()
         assertEquals(2.0, expr("x" to 2.0))
     }
 
     @Test
     fun testUnaryMinus() {
-        val expr = RealField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile()
         assertEquals(-2.0, expr("x" to 2.0))
     }
 
     @Test
     fun testAdd() {
-        val expr = RealField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile()
         assertEquals(4.0, expr("x" to 2.0))
     }
 
     @Test
     fun testSine() {
-        val expr = RealField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile()
         assertEquals(0.0, expr("x" to 0.0))
     }
 
     @Test
     fun testMinus() {
-        val expr = RealField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile()
         assertEquals(0.0, expr("x" to 2.0))
     }
 
     @Test
     fun testDivide() {
-        val expr = RealField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile()
+        val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile()
         assertEquals(1.0, expr("x" to 2.0))
     }
 
     @Test
     fun testPower() {
-        val expr = RealField
+        val expr = DoubleField
             .mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) }
             .compile()
 
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt
index 7153f4bfc..1450cab84 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt
@@ -1,12 +1,12 @@
 package space.kscience.kmath.ast
 
+import space.kscience.kmath.operations.DoubleField
 import space.kscience.kmath.operations.Field
-import space.kscience.kmath.operations.RealField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 internal class ParserPrecedenceTest {
-    private val f: Field<Double> = RealField
+    private val f: Field<Double> = DoubleField
 
     @Test
     fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt
index 6807d5c5d..3d5449043 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt
@@ -4,7 +4,7 @@ import space.kscience.kmath.complex.Complex
 import space.kscience.kmath.complex.ComplexField
 import space.kscience.kmath.expressions.invoke
 import space.kscience.kmath.operations.Algebra
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -33,7 +33,7 @@ internal class ParserTest {
     @Test
     fun `evaluate MST with unary function`() {
         val mst = "sin(0)".parseMath()
-        val res = RealField.evaluate(mst)
+        val res = DoubleField.evaluate(mst)
         assertEquals(0.0, res)
     }
 
diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts
index 4fe16605a..56dcef29a 100644
--- a/kmath-commons/build.gradle.kts
+++ b/kmath-commons/build.gradle.kts
@@ -12,6 +12,6 @@ dependencies {
     api("org.apache.commons:commons-math3:3.6.1")
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
 }
\ No newline at end of file
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt
new file mode 100644
index 000000000..e1ba7d777
--- /dev/null
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt
@@ -0,0 +1,92 @@
+package space.kscience.kmath.commons.integration
+
+import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator
+import org.apache.commons.math3.analysis.integration.SimpsonIntegrator
+import space.kscience.kmath.integration.*
+import space.kscience.kmath.misc.UnstableKMathAPI
+
+/**
+ * Integration wrapper for Common-maths UnivariateIntegrator
+ */
+public class CMIntegrator(
+    private val defaultMaxCalls: Int = 200,
+    public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator,
+) : UnivariateIntegrator<Double> {
+
+    public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature
+    public class TargetAbsoluteAccuracy(public val value: Double) : IntegrandFeature
+
+    public class MinIterations(public val value: Int) : IntegrandFeature
+    public class MaxIterations(public val value: Int) : IntegrandFeature
+
+    override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
+        val integrator = integratorBuilder(integrand)
+        val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
+        val remainingCalls = maxCalls - integrand.calls
+        val range = integrand.getFeature<IntegrationRange<Double>>()?.range
+            ?: error("Integration range is not provided")
+        val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
+
+        return integrand +
+                IntegrandValue(res) +
+                IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) +
+                IntegrandRelativeAccuracy(integrator.relativeAccuracy) +
+                IntegrandCalls(integrator.evaluations + integrand.calls)
+    }
+
+
+    public companion object {
+        /**
+         * Create a Simpson integrator based on [SimpsonIntegrator]
+         */
+        public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand ->
+            val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value
+                ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
+            val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value
+                ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
+            val minIterations = integrand.getFeature<MinIterations>()?.value
+                ?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT
+            val maxIterations = integrand.getFeature<MaxIterations>()?.value
+                ?: SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
+
+            SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, minIterations, maxIterations)
+        }
+
+        /**
+         * Create a Gauss-Legandre integrator based on [IterativeLegendreGaussIntegrator]
+         */
+        public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator =
+            CMIntegrator(defaultMaxCalls) { integrand ->
+                val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value
+                    ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
+                val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value
+                    ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
+                val minIterations = integrand.getFeature<MinIterations>()?.value
+                    ?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT
+                val maxIterations = integrand.getFeature<MaxIterations>()?.value
+                    ?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
+
+                IterativeLegendreGaussIntegrator(
+                    numPoints,
+                    relativeAccuracy,
+                    absoluteAccuracy,
+                    minIterations,
+                    maxIterations
+                )
+            }
+    }
+}
+
+@UnstableKMathAPI
+public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double?
+    get() = filterIsInstance<CMIntegrator.TargetAbsoluteAccuracy>().lastOrNull()?.value
+    set(value) {
+        value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) }
+    }
+
+@UnstableKMathAPI
+public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double?
+    get() = filterIsInstance<CMIntegrator.TargetRelativeAccuracy>().lastOrNull()?.value
+    set(value) {
+        value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) }
+    }
\ No newline at end of file
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt
new file mode 100644
index 000000000..5a18756ac
--- /dev/null
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt
@@ -0,0 +1,94 @@
+/* 
+ * Copyright 2015 Alexander Nozik.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package space.kscience.kmath.commons.integration
+
+import org.apache.commons.math3.analysis.integration.gauss.GaussIntegrator
+import org.apache.commons.math3.analysis.integration.gauss.GaussIntegratorFactory
+import space.kscience.kmath.integration.*
+
+/**
+ * A simple one-pass integrator based on Gauss rule
+ */
+public class GaussRuleIntegrator(
+    private val numpoints: Int,
+    private var type: GaussRule = GaussRule.LEGANDRE,
+) : UnivariateIntegrator<Double> {
+
+    override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
+        val range = integrand.getFeature<IntegrationRange<Double>>()?.range
+            ?: error("Integration range is not provided")
+        val integrator: GaussIntegrator = getIntegrator(range)
+        //TODO check performance
+        val res: Double = integrator.integrate(integrand.function)
+        return integrand + IntegrandValue(res) + IntegrandCalls(integrand.calls + numpoints)
+    }
+
+    private fun getIntegrator(range: ClosedRange<Double>): GaussIntegrator {
+        return when (type) {
+            GaussRule.LEGANDRE -> factory.legendre(
+                numpoints,
+                range.start,
+                range.endInclusive
+            )
+            GaussRule.LEGANDREHP -> factory.legendreHighPrecision(
+                numpoints,
+                range.start,
+                range.endInclusive
+            )
+            GaussRule.UNIFORM -> GaussIntegrator(
+                getUniformRule(
+                    range.start,
+                    range.endInclusive,
+                    numpoints
+                )
+            )
+        }
+    }
+
+    private fun getUniformRule(
+        min: Double,
+        max: Double,
+        numPoints: Int,
+    ): org.apache.commons.math3.util.Pair<DoubleArray, DoubleArray> {
+        assert(numPoints > 2)
+        val points = DoubleArray(numPoints)
+        val weights = DoubleArray(numPoints)
+        val step = (max - min) / (numPoints - 1)
+        points[0] = min
+        for (i in 1 until numPoints) {
+            points[i] = points[i - 1] + step
+            weights[i] = step
+        }
+        return org.apache.commons.math3.util.Pair<DoubleArray, DoubleArray>(points, weights)
+    }
+
+    public enum class GaussRule {
+        UNIFORM, LEGANDRE, LEGANDREHP
+    }
+
+    public companion object {
+        private val factory: GaussIntegratorFactory = GaussIntegratorFactory()
+
+        public fun integrate(
+            range: ClosedRange<Double>,
+            numPoints: Int = 100,
+            type: GaussRule = GaussRule.LEGANDRE,
+            function: (Double) -> Double,
+        ): Double = GaussRuleIntegrator(numPoints, type).integrate(
+            UnivariateIntegrand(function, IntegrationRange(range))
+        ).value!!
+    }
+}
\ No newline at end of file
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 5f632491c..89e9649e9 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,63 +3,16 @@ 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 space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.structures.DoubleBuffer
 import kotlin.reflect.KClass
 import kotlin.reflect.cast
 
-public class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
+public inline class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
     public override val rowNum: Int get() = origin.rowDimension
     public override val colNum: Int get() = origin.columnDimension
 
-    @UnstableKMathAPI
-    override fun <T : Any> getFeature(type: KClass<T>): T? = when (type) {
-        DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null
-
-        DeterminantFeature::class, LupDecompositionFeature::class -> object :
-            DeterminantFeature<Double>,
-            LupDecompositionFeature<Double> {
-            private val lup by lazy { LUDecomposition(origin) }
-            override val determinant: Double by lazy { lup.determinant }
-            override val l: Matrix<Double> by lazy { CMMatrix(lup.l) + LFeature }
-            override val u: Matrix<Double> by lazy { CMMatrix(lup.u) + UFeature }
-            override val p: Matrix<Double> by lazy { CMMatrix(lup.p) }
-        }
-
-        CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
-            override val l: Matrix<Double> by lazy {
-                val cholesky = CholeskyDecomposition(origin)
-                CMMatrix(cholesky.l) + LFeature
-            }
-        }
-
-        QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
-            private val qr by lazy { QRDecomposition(origin) }
-            override val q: Matrix<Double> by lazy { CMMatrix(qr.q) + OrthogonalFeature }
-            override val r: Matrix<Double> by lazy { CMMatrix(qr.r) + UFeature }
-        }
-
-        SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
-            private val sv by lazy { SingularValueDecomposition(origin) }
-            override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
-            override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
-            override val v: Matrix<Double> by lazy { CMMatrix(sv.v) }
-            override val singularValues: Point<Double> by lazy { RealBuffer(sv.singularValues) }
-        }
-
-        else -> null
-    }?.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 inline class CMVector(public val origin: RealVector) : Point<Double> {
@@ -72,15 +25,15 @@ public inline class CMVector(public val origin: RealVector) : Point<Double> {
 
 public fun RealVector.toPoint(): CMVector = CMVector(this)
 
-public object CMLinearSpace : LinearSpace<Double, RealField> {
-    override val elementAlgebra: RealField get() = RealField
+public object CMLinearSpace : LinearSpace<Double, DoubleField> {
+    override val elementAlgebra: DoubleField get() = DoubleField
 
     public override fun buildMatrix(
         rows: Int,
         columns: Int,
-        initializer: RealField.(i: Int, j: Int) -> Double,
+        initializer: DoubleField.(i: Int, j: Int) -> Double,
     ): CMMatrix {
-        val array = Array(rows) { i -> DoubleArray(columns) { j -> RealField.initializer(i, j) } }
+        val array = Array(rows) { i -> DoubleArray(columns) { j -> DoubleField.initializer(i, j) } }
         return CMMatrix(Array2DRowRealMatrix(array))
     }
 
@@ -102,8 +55,8 @@ public object CMLinearSpace : LinearSpace<Double, RealField> {
     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 buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point<Double> =
+        ArrayRealVector(DoubleArray(size) { DoubleField.initializer(it) }).wrap()
 
     override fun Matrix<Double>.plus(other: Matrix<Double>): CMMatrix =
         toCM().origin.add(other.toCM().origin).wrap()
@@ -134,13 +87,54 @@ public object CMLinearSpace : LinearSpace<Double, RealField> {
 
     override fun Double.times(v: Point<Double>): CMVector =
         v * this
+
+    @UnstableKMathAPI
+    override fun <F : Any> getFeature(structure: Matrix<Double>, type: KClass<F>): F? {
+        //Return the feature if it is intrinsic to the structure
+        structure.getFeature(type)?.let { return it }
+
+        val origin = structure.toCM().origin
+
+        return when (type) {
+            DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null
+
+            DeterminantFeature::class, LupDecompositionFeature::class -> object :
+                DeterminantFeature<Double>,
+                LupDecompositionFeature<Double> {
+                private val lup by lazy { LUDecomposition(origin) }
+                override val determinant: Double by lazy { lup.determinant }
+                override val l: Matrix<Double> by lazy { CMMatrix(lup.l) + LFeature }
+                override val u: Matrix<Double> by lazy { CMMatrix(lup.u) + UFeature }
+                override val p: Matrix<Double> by lazy { CMMatrix(lup.p) }
+            }
+
+            CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
+                override val l: Matrix<Double> by lazy {
+                    val cholesky = CholeskyDecomposition(origin)
+                    CMMatrix(cholesky.l) + LFeature
+                }
+            }
+
+            QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
+                private val qr by lazy { QRDecomposition(origin) }
+                override val q: Matrix<Double> by lazy { CMMatrix(qr.q) + OrthogonalFeature }
+                override val r: Matrix<Double> by lazy { CMMatrix(qr.r) + UFeature }
+            }
+
+            SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
+                private val sv by lazy { SingularValueDecomposition(origin) }
+                override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
+                override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
+                override val v: Matrix<Double> by lazy { CMMatrix(sv.v) }
+                override val singularValues: Point<Double> by lazy { DoubleBuffer(sv.singularValues) }
+            }
+            else -> null
+        }?.let(type::cast)
+    }
 }
 
-public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix =
-    CMMatrix(origin.add(other.origin))
+public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = CMMatrix(origin.add(other.origin))
 
-public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix =
-    CMMatrix(origin.subtract(other.origin))
+public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix = CMMatrix(origin.subtract(other.origin))
 
-public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix =
-    CMMatrix(origin.multiply(other.origin))
+public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix = CMMatrix(origin.multiply(other.origin))
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 b5fd0154e..b4706473a 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
@@ -14,7 +14,7 @@ public enum class CMDecomposition {
 
 public fun CMLinearSpace.solver(
     a: Matrix<Double>,
-    decomposition: CMDecomposition = CMDecomposition.LUP
+    decomposition: CMDecomposition = CMDecomposition.LUP,
 ): DecompositionSolver = when (decomposition) {
     CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver
     CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver
@@ -26,16 +26,16 @@ public fun CMLinearSpace.solver(
 public fun CMLinearSpace.solve(
     a: Matrix<Double>,
     b: Matrix<Double>,
-    decomposition: CMDecomposition = CMDecomposition.LUP
+    decomposition: CMDecomposition = CMDecomposition.LUP,
 ): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).wrap()
 
 public fun CMLinearSpace.solve(
     a: Matrix<Double>,
     b: Point<Double>,
-    decomposition: CMDecomposition = CMDecomposition.LUP
+    decomposition: CMDecomposition = CMDecomposition.LUP,
 ): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint()
 
 public fun CMLinearSpace.inverse(
     a: Matrix<Double>,
-    decomposition: CMDecomposition = CMDecomposition.LUP
+    decomposition: CMDecomposition = CMDecomposition.LUP,
 ): CMMatrix = solver(a, decomposition).inverse.wrap()
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt
index d655b4f61..13a10475f 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt
@@ -19,7 +19,7 @@ import kotlin.reflect.KClass
 public operator fun PointValuePair.component1(): DoubleArray = point
 public operator fun PointValuePair.component2(): Double = value
 
-public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
+public class CMOptimizationProblem(override val symbols: List<Symbol>) :
     OptimizationProblem<Double>, SymbolIndexer, OptimizationFeature {
     private val optimizationData: HashMap<KClass<out OptimizationData>, OptimizationData> = HashMap()
     private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
index e174a237f..010ea7e9f 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
@@ -10,6 +10,7 @@ import space.kscience.kmath.streaming.spread
 import space.kscience.kmath.structures.*
 
 
+
 /**
  * Streaming and buffer transformations
  */
@@ -17,7 +18,7 @@ public object Transformations {
     private fun Buffer<Complex>.toArray(): Array<org.apache.commons.math3.complex.Complex> =
         Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) }
 
-    private fun Buffer<Double>.asArray() = if (this is RealBuffer) {
+    private fun Buffer<Double>.asArray() = if (this is DoubleBuffer) {
         array
     } else {
         DoubleArray(size) { i -> get(i) }
@@ -33,34 +34,34 @@ public object Transformations {
 
     public fun fourier(
         normalization: DftNormalization = DftNormalization.STANDARD,
-        direction: TransformType = TransformType.FORWARD
+        direction: TransformType = TransformType.FORWARD,
     ): SuspendBufferTransform<Complex, Complex> = {
         FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer()
     }
 
     public fun realFourier(
         normalization: DftNormalization = DftNormalization.STANDARD,
-        direction: TransformType = TransformType.FORWARD
+        direction: TransformType = TransformType.FORWARD,
     ): SuspendBufferTransform<Double, Complex> = {
         FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer()
     }
 
     public fun sine(
         normalization: DstNormalization = DstNormalization.STANDARD_DST_I,
-        direction: TransformType = TransformType.FORWARD
+        direction: TransformType = TransformType.FORWARD,
     ): SuspendBufferTransform<Double, Double> = {
         FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer()
     }
 
     public fun cosine(
         normalization: DctNormalization = DctNormalization.STANDARD_DCT_I,
-        direction: TransformType = TransformType.FORWARD
+        direction: TransformType = TransformType.FORWARD,
     ): SuspendBufferTransform<Double, Double> = {
         FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer()
     }
 
     public fun hadamard(
-        direction: TransformType = TransformType.FORWARD
+        direction: TransformType = TransformType.FORWARD,
     ): SuspendBufferTransform<Double, Double> = {
         FastHadamardTransformer().transform(it.asArray(), direction).asBuffer()
     }
@@ -72,7 +73,7 @@ public object Transformations {
 @FlowPreview
 public fun Flow<Buffer<Complex>>.FFT(
     normalization: DftNormalization = DftNormalization.STANDARD,
-    direction: TransformType = TransformType.FORWARD
+    direction: TransformType = TransformType.FORWARD,
 ): Flow<Buffer<Complex>> {
     val transform = Transformations.fourier(normalization, direction)
     return map { transform(it) }
@@ -82,7 +83,7 @@ public fun Flow<Buffer<Complex>>.FFT(
 @JvmName("realFFT")
 public fun Flow<Buffer<Double>>.FFT(
     normalization: DftNormalization = DftNormalization.STANDARD,
-    direction: TransformType = TransformType.FORWARD
+    direction: TransformType = TransformType.FORWARD,
 ): Flow<Buffer<Complex>> {
     val transform = Transformations.realFourier(normalization, direction)
     return map(transform)
@@ -96,7 +97,7 @@ public fun Flow<Buffer<Double>>.FFT(
 public fun Flow<Double>.FFT(
     bufferSize: Int = Int.MAX_VALUE,
     normalization: DftNormalization = DftNormalization.STANDARD,
-    direction: TransformType = TransformType.FORWARD
+    direction: TransformType = TransformType.FORWARD,
 ): Flow<Complex> = chunked(bufferSize).FFT(normalization, direction).spread()
 
 /**
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
index 19b6e28da..8d9bab652 100644
--- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
@@ -27,10 +27,10 @@ internal class AutoDiffTest {
             val y = bindSymbol("y")
             val z = x * (-sin(x * y) + y) + 2.0
             println(z.derivative(x))
-            println(z.derivative(y,x))
+            println(z.derivative(y, x))
             assertEquals(z.derivative(x, y), z.derivative(y, x))
             //check that improper order cause failure
-            assertFails { z.derivative(x,x,y) }
+            assertFails { z.derivative(x, x, y) }
         }
     }
 
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt
new file mode 100644
index 000000000..d163203f7
--- /dev/null
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt
@@ -0,0 +1,30 @@
+package space.kscience.kmath.commons.integration
+
+import org.junit.jupiter.api.Test
+import space.kscience.kmath.integration.integrate
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.DoubleField.sin
+import kotlin.math.PI
+import kotlin.math.abs
+import kotlin.test.assertTrue
+
+@UnstableKMathAPI
+internal class IntegrationTest {
+    private val function: (Double) -> Double = { sin(it) }
+
+    @Test
+    fun simpson() {
+        val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function)
+        assertTrue { abs(res) < 1e-3 }
+    }
+
+    @Test
+    fun customSimpson() {
+        val res = CMIntegrator.simpson().integrate(0.0..PI, function) {
+            targetRelativeAccuracy = 1e-4
+            targetAbsoluteAccuracy = 1e-4
+        }
+        assertTrue { abs(res - 2) < 1e-3 }
+        assertTrue { abs(res - 2) > 1e-12 }
+    }
+}
\ No newline at end of file
diff --git a/kmath-complex/README.md b/kmath-complex/README.md
index 71a75bd3e..9e9cd5b6f 100644
--- a/kmath-complex/README.md
+++ b/kmath-complex/README.md
@@ -2,13 +2,13 @@
 
 Complex and hypercomplex number systems in KMath:
 
- - [complex](src/commonMain/kotlin/kscience/kmath/complex/Complex.kt) : Complex Numbers
- - [quaternion](src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt) : Quaternions
+ - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers
+ - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions
 
 
 > #### Artifact:
 >
-> This module artifact: `space.kscience:kmath-complex:0.2.0`.
+> This module artifact: `space.kscience:kmath-complex:0.3.0-dev-3`.
 >
 > Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-complex/_latestVersion)
 >
@@ -21,13 +21,10 @@ Complex and hypercomplex number systems in KMath:
 >     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-complex:0.2.0'
+>     implementation 'space.kscience:kmath-complex:0.3.0-dev-3'
 > }
 > ```
 > **Gradle Kotlin DSL:**
@@ -37,12 +34,9 @@ Complex and hypercomplex number systems in KMath:
 >     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-complex:0.2.0")
+>     implementation("space.kscience:kmath-complex:0.3.0-dev-3")
 > }
 > ```
diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts
index 4cd43c70c..5b9dc3ba0 100644
--- a/kmath-complex/build.gradle.kts
+++ b/kmath-complex/build.gradle.kts
@@ -25,12 +25,12 @@ readme {
     feature(
         id = "complex",
         description = "Complex Numbers",
-        ref = "src/commonMain/kotlin/kscience/kmath/complex/Complex.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt"
     )
 
     feature(
         id = "quaternion",
         description = "Quaternions",
-        ref = "src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt"
     )
 }
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
similarity index 55%
rename from kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt
rename to kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
index 382659e10..d11f2b7db 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
@@ -1,10 +1,10 @@
 package space.kscience.kmath.complex
 
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.BufferedNDField
-import space.kscience.kmath.nd.NDAlgebra
-import space.kscience.kmath.nd.NDBuffer
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.AlgebraND
+import space.kscience.kmath.nd.BufferND
+import space.kscience.kmath.nd.BufferedFieldND
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.operations.ExtendedField
 import space.kscience.kmath.operations.NumbersAddOperations
 import space.kscience.kmath.structures.Buffer
@@ -16,16 +16,16 @@ import kotlin.contracts.contract
  * An optimized nd-field for complex numbers
  */
 @OptIn(UnstableKMathAPI::class)
-public class ComplexNDField(
+public class ComplexFieldND(
     shape: IntArray,
-) : BufferedNDField<Complex, ComplexField>(shape, ComplexField, Buffer.Companion::complex),
-    NumbersAddOperations<NDStructure<Complex>>,
-    ExtendedField<NDStructure<Complex>> {
+) : BufferedFieldND<Complex, ComplexField>(shape, ComplexField, Buffer.Companion::complex),
+    NumbersAddOperations<StructureND<Complex>>,
+    ExtendedField<StructureND<Complex>> {
 
-    override val zero: NDBuffer<Complex> by lazy { produce { zero } }
-    override val one: NDBuffer<Complex> by lazy { produce { one } }
+    override val zero: BufferND<Complex> by lazy { produce { zero } }
+    override val one: BufferND<Complex> by lazy { produce { one } }
 
-    override fun number(value: Number): NDBuffer<Complex> {
+    override fun number(value: Number): BufferND<Complex> {
         val d = value.toComplex() // minimize conversions
         return produce { d }
     }
@@ -34,15 +34,15 @@ public class ComplexNDField(
 //    @Suppress("OVERRIDE_BY_INLINE")
 //    override inline fun map(
 //        arg: AbstractNDBuffer<Double>,
-//        transform: RealField.(Double) -> Double,
+//        transform: DoubleField.(Double) -> Double,
 //    ): RealNDElement {
 //        check(arg)
-//        val array = RealBuffer(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) }
+//        val array = RealBuffer(arg.strides.linearSize) { offset -> DoubleField.transform(arg.buffer[offset]) }
 //        return BufferedNDFieldElement(this, array)
 //    }
 //
 //    @Suppress("OVERRIDE_BY_INLINE")
-//    override inline fun produce(initializer: RealField.(IntArray) -> Double): RealNDElement {
+//    override inline fun produce(initializer: DoubleField.(IntArray) -> Double): RealNDElement {
 //        val array = RealBuffer(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) }
 //        return BufferedNDFieldElement(this, array)
 //    }
@@ -50,7 +50,7 @@ public class ComplexNDField(
 //    @Suppress("OVERRIDE_BY_INLINE")
 //    override inline fun mapIndexed(
 //        arg: AbstractNDBuffer<Double>,
-//        transform: RealField.(index: IntArray, Double) -> Double,
+//        transform: DoubleField.(index: IntArray, Double) -> Double,
 //    ): RealNDElement {
 //        check(arg)
 //        return BufferedNDFieldElement(
@@ -67,7 +67,7 @@ public class ComplexNDField(
 //    override inline fun combine(
 //        a: AbstractNDBuffer<Double>,
 //        b: AbstractNDBuffer<Double>,
-//        transform: RealField.(Double, Double) -> Double,
+//        transform: DoubleField.(Double, Double) -> Double,
 //    ): RealNDElement {
 //        check(a, b)
 //        val buffer = RealBuffer(strides.linearSize) { offset ->
@@ -76,44 +76,44 @@ 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: StructureND<Complex>, pow: Number): BufferND<Complex> = arg.map { power(it, pow) }
 
-    override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { exp(it) }
+    override fun exp(arg: StructureND<Complex>): BufferND<Complex> = arg.map { exp(it) }
 
-    override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { ln(it) }
+    override fun ln(arg: StructureND<Complex>): BufferND<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: StructureND<Complex>): BufferND<Complex> = arg.map { sin(it) }
+    override fun cos(arg: StructureND<Complex>): BufferND<Complex> = arg.map { cos(it) }
+    override fun tan(arg: StructureND<Complex>): BufferND<Complex> = arg.map { tan(it) }
+    override fun asin(arg: StructureND<Complex>): BufferND<Complex> = arg.map { asin(it) }
+    override fun acos(arg: StructureND<Complex>): BufferND<Complex> = arg.map { acos(it) }
+    override fun atan(arg: StructureND<Complex>): BufferND<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: StructureND<Complex>): BufferND<Complex> = arg.map { sinh(it) }
+    override fun cosh(arg: StructureND<Complex>): BufferND<Complex> = arg.map { cosh(it) }
+    override fun tanh(arg: StructureND<Complex>): BufferND<Complex> = arg.map { tanh(it) }
+    override fun asinh(arg: StructureND<Complex>): BufferND<Complex> = arg.map { asinh(it) }
+    override fun acosh(arg: StructureND<Complex>): BufferND<Complex> = arg.map { acosh(it) }
+    override fun atanh(arg: StructureND<Complex>): BufferND<Complex> = arg.map { atanh(it) }
 }
 
 
 /**
  * Fast element production using function inlining
  */
-public inline fun BufferedNDField<Complex, ComplexField>.produceInline(initializer: ComplexField.(Int) -> Complex): NDBuffer<Complex> {
+public inline fun BufferedFieldND<Complex, ComplexField>.produceInline(initializer: ComplexField.(Int) -> Complex): BufferND<Complex> {
     contract { callsInPlace(initializer, InvocationKind.EXACTLY_ONCE) }
     val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.initializer(offset) }
-    return NDBuffer(strides, buffer)
+    return BufferND(strides, buffer)
 }
 
 
-public fun NDAlgebra.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape)
+public fun AlgebraND.Companion.complex(vararg shape: Int): ComplexFieldND = ComplexFieldND(shape)
 
 /**
  * Produce a context for n-dimensional operations inside this real field
  */
-public inline fun <R> ComplexField.nd(vararg shape: Int, action: ComplexNDField.() -> R): R {
+public inline fun <R> ComplexField.nd(vararg shape: Int, action: ComplexFieldND.() -> R): R {
     contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return ComplexNDField(shape).action()
+    return ComplexFieldND(shape).action()
 }
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 d391aff18..9a0346ca7 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
@@ -172,7 +172,7 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
         else -> super<Field>.bindSymbol(value)
     }
 
-    override fun number(value: Number): Quaternion =value.toQuaternion()
+    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
diff --git a/kmath-core/README.md b/kmath-core/README.md
new file mode 100644
index 000000000..4e4b5273d
--- /dev/null
+++ b/kmath-core/README.md
@@ -0,0 +1,49 @@
+# The Core Module (`kmath-core`)
+
+The core features of KMath:
+
+ - [algebras](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
+ - [nd](src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them.
+ - [linear](src/commonMain/kotlin/space/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/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
+ - [expressions](src/commonMain/kotlin/space/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/space/kscience/kmath/domains) : Domains
+ - [autodif](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
+
+
+> #### Artifact:
+>
+> This module artifact: `space.kscience:kmath-core:0.3.0-dev-3`.
+>
+> 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
+> }
+> 
+> dependencies {
+>     implementation 'space.kscience:kmath-core:0.3.0-dev-3'
+> }
+> ```
+> **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
+> }
+> 
+> dependencies {
+>     implementation("space.kscience:kmath-core:0.3.0-dev-3")
+> }
+> ```
diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api
index 2fa9e165b..04325379e 100644
--- a/kmath-core/api/kmath-core.api
+++ b/kmath-core/api/kmath-core.api
@@ -432,7 +432,7 @@ 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/BufferLinearSpace : space/kscience/kmath/linear/LinearSpace {
+public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace {
 	public fun <init> (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
 	public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D;
 	public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
@@ -584,7 +584,6 @@ public final class space/kscience/kmath/linear/MatrixFeaturesKt {
 
 public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/kmath/nd/Structure2D {
 	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 fun getColNum ()I
@@ -595,7 +594,6 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km
 	public fun getRowNum ()I
 	public fun getRows ()Ljava/util/List;
 	public fun getShape ()[I
-	public fun hashCode ()I
 	public fun toString ()Ljava/lang/String;
 }
 
@@ -640,7 +638,6 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat
 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;
-	public fun equals (Ljava/lang/Object;)Z
 	public fun get (II)Ljava/lang/Object;
 	public fun get ([I)Ljava/lang/Object;
 	public fun getColNum ()I
@@ -650,7 +647,6 @@ public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/km
 	public fun getRowNum ()I
 	public fun getRows ()Ljava/util/List;
 	public fun getShape ()[I
-	public fun hashCode ()I
 }
 
 public final class space/kscience/kmath/linear/ZeroFeature : space/kscience/kmath/linear/DiagonalFeature {
@@ -679,115 +675,144 @@ public final class space/kscience/kmath/misc/CumulativeKt {
 public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
 }
 
-public abstract interface class space/kscience/kmath/nd/BufferNDAlgebra : space/kscience/kmath/nd/NDAlgebra {
-	public abstract fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
-	public abstract fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer;
+public abstract interface class space/kscience/kmath/nd/AlgebraND {
+	public static final field Companion Lspace/kscience/kmath/nd/AlgebraND$Companion;
+	public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
+	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/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public final class space/kscience/kmath/nd/AlgebraND$Companion {
+}
+
+public final class space/kscience/kmath/nd/AlgebraND$DefaultImpls {
+	public static fun invoke (Lspace/kscience/kmath/nd/AlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public abstract interface class space/kscience/kmath/nd/BufferAlgebraND : space/kscience/kmath/nd/AlgebraND {
+	public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public abstract fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer;
 	public abstract fun getBufferFactory ()Lkotlin/jvm/functions/Function2;
 	public abstract fun getStrides ()Lspace/kscience/kmath/nd/Strides;
-	public abstract fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
-	public abstract fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
-	public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
+	public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
+	public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
 }
 
-public final class space/kscience/kmath/nd/BufferNDAlgebra$DefaultImpls {
-	public static fun combine (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
-	public static fun getBuffer (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer;
-	public static fun invoke (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public static fun map (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
-	public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
-	public static fun produce (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
+public final class space/kscience/kmath/nd/BufferAlgebraND$DefaultImpls {
+	public static fun combine (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public static fun getBuffer (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer;
+	public static fun invoke (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun map (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
+	public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public static fun produce (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
 }
 
-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 final class space/kscience/kmath/nd/BufferAlgebraNDKt {
+	public static final fun field (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedFieldND;
+	public static final fun group (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedGroupND;
 	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 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 ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND;
 }
 
-public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/nd/NDField {
+public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND {
+	public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V
+	public fun elements ()Lkotlin/sequences/Sequence;
+	public fun get ([I)Ljava/lang/Object;
+	public final fun getBuffer ()Lspace/kscience/kmath/structures/Buffer;
+	public fun getDimension ()I
+	public fun getShape ()[I
+	public final fun getStrides ()Lspace/kscience/kmath/nd/Strides;
+	public fun toString ()Ljava/lang/String;
+}
+
+public class space/kscience/kmath/nd/BufferedFieldND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/nd/FieldND {
 	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/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 fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	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 rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND;
 	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 fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 }
 
-public class space/kscience/kmath/nd/BufferedNDGroup : space/kscience/kmath/nd/BufferNDAlgebra, space/kscience/kmath/nd/NDGroup {
+public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/BufferAlgebraND, space/kscience/kmath/nd/GroupND {
 	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 fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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/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 fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer;
+	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND;
+	public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
+	public fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer;
 	public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2;
 	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;
-	public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer;
-	public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
-	public synthetic fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
-	public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun getZero ()Lspace/kscience/kmath/nd/BufferND;
+	public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
+	public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	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 fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun minus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun plus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryMinus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 }
 
-public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDGroup, space/kscience/kmath/nd/NDRing {
+public class space/kscience/kmath/nd/BufferedRingND : space/kscience/kmath/nd/BufferedGroupND, space/kscience/kmath/nd/RingND {
 	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 fun getOne ()Lspace/kscience/kmath/nd/BufferND;
 	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 fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun times (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 }
 
 public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath/nd/Strides {
@@ -807,250 +832,183 @@ public final class space/kscience/kmath/nd/DefaultStrides$Companion {
 	public final fun invoke ([I)Lspace/kscience/kmath/nd/Strides;
 }
 
-public final class space/kscience/kmath/nd/MutableNDBuffer : space/kscience/kmath/nd/NDBuffer, space/kscience/kmath/nd/MutableNDStructure {
-	public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V
-	public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer;
-	public fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer;
-	public fun set ([ILjava/lang/Object;)V
-}
-
-public abstract interface class space/kscience/kmath/nd/MutableNDStructure : space/kscience/kmath/nd/NDStructure {
-	public abstract fun set ([ILjava/lang/Object;)V
-}
-
-public final class space/kscience/kmath/nd/MutableNDStructure$DefaultImpls {
-	public static fun getDimension (Lspace/kscience/kmath/nd/MutableNDStructure;)I
-}
-
-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 ()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;
-	public abstract fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
-	public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-}
-
-public final class space/kscience/kmath/nd/NDAlgebra$Companion {
-}
-
-public final class space/kscience/kmath/nd/NDAlgebra$DefaultImpls {
-	public static fun invoke (Lspace/kscience/kmath/nd/NDAlgebra;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-}
-
-public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/NDStructure {
-	public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V
-	public fun elements ()Lkotlin/sequences/Sequence;
-	public fun equals (Ljava/lang/Object;)Z
-	public fun get ([I)Ljava/lang/Object;
-	public fun getBuffer ()Lspace/kscience/kmath/structures/Buffer;
-	public fun getDimension ()I
-	public fun getShape ()[I
-	public final fun getStrides ()Lspace/kscience/kmath/nd/Strides;
-	public fun hashCode ()I
-	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, 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;
-}
-
-public final class space/kscience/kmath/nd/NDField$DefaultImpls {
-	public static fun add (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	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/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;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 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/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;
-	public abstract fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-}
-
-public final class space/kscience/kmath/nd/NDRing$Companion {
-}
-
-public final class space/kscience/kmath/nd/NDRing$DefaultImpls {
-	public static fun add (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	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 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;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/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/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 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/NDStructure {
-	public static final field Companion Lspace/kscience/kmath/nd/NDStructure$Companion;
-	public abstract fun elements ()Lkotlin/sequences/Sequence;
-	public abstract fun equals (Ljava/lang/Object;)Z
-	public abstract fun get ([I)Ljava/lang/Object;
-	public abstract fun getDimension ()I
-	public abstract fun getShape ()[I
-	public abstract fun hashCode ()I
-}
-
-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 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
-}
-
-public final class space/kscience/kmath/nd/NDStructure$DefaultImpls {
-	public static fun getDimension (Lspace/kscience/kmath/nd/NDStructure;)I
-}
-
-public final class space/kscience/kmath/nd/NDStructureKt {
-	public static final fun get (Lspace/kscience/kmath/nd/NDStructure;[I)Ljava/lang/Object;
-	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/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations {
+public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/nd/BufferedFieldND, 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;
+	public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun acosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asin (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atan (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
-	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 fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
+	public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun cos (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun exp (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
-	public synthetic fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer;
-	public fun getBuffer-LGjt3BI (Lspace/kscience/kmath/nd/NDStructure;)[D
+	public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer;
+	public fun getBuffer-Udx-57Q (Lspace/kscience/kmath/nd/StructureND;)[D
 	public synthetic fun getOne ()Ljava/lang/Object;
-	public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer;
+	public fun getOne ()Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer;
+	public fun getZero ()Lspace/kscience/kmath/nd/BufferND;
 	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;
-	public synthetic fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer;
-	public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
+	public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
+	public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun pow (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	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 fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND;
+	public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
+	public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sin (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sqrt (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun tan (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun tanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND;
 	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
 }
 
-public final class space/kscience/kmath/nd/RealNDFieldKt {
-	public static final fun nd (Lspace/kscience/kmath/operations/RealField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-	public static final fun real (Lspace/kscience/kmath/nd/NDAlgebra$Companion;[I)Lspace/kscience/kmath/nd/RealNDField;
+public final class space/kscience/kmath/nd/DoubleFieldNDKt {
+	public static final fun nd (Lspace/kscience/kmath/operations/DoubleField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun real (Lspace/kscience/kmath/nd/AlgebraND$Companion;[I)Lspace/kscience/kmath/nd/DoubleFieldND;
+}
+
+public abstract interface class space/kscience/kmath/nd/FieldND : space/kscience/kmath/nd/RingND, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations {
+	public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public final class space/kscience/kmath/nd/FieldND$DefaultImpls {
+	public static fun add (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun binaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun div (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun divide (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun invoke (Lspace/kscience/kmath/nd/FieldND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun leftSideNumberOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun minus (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun multiply (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun number (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun rightSideNumberOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun times (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun unaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public abstract interface class space/kscience/kmath/nd/GroupND : space/kscience/kmath/nd/AlgebraND, space/kscience/kmath/operations/Group {
+	public static final field Companion Lspace/kscience/kmath/nd/GroupND$Companion;
+	public abstract fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public final class space/kscience/kmath/nd/GroupND$Companion {
+}
+
+public final class space/kscience/kmath/nd/GroupND$DefaultImpls {
+	public static fun add (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun binaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun invoke (Lspace/kscience/kmath/nd/GroupND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun unaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND {
+	public abstract fun set ([ILjava/lang/Object;)V
+}
+
+public final class space/kscience/kmath/nd/MutableStructureND$DefaultImpls {
+	public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructureND;)I
+}
+
+public abstract interface class space/kscience/kmath/nd/RingND : space/kscience/kmath/nd/GroupND, space/kscience/kmath/operations/Ring {
+	public static final field Companion Lspace/kscience/kmath/nd/RingND$Companion;
+	public abstract fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public abstract fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+}
+
+public final class space/kscience/kmath/nd/RingND$Companion {
+}
+
+public final class space/kscience/kmath/nd/RingND$DefaultImpls {
+	public static fun add (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun binaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public static fun bindSymbol (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun invoke (Lspace/kscience/kmath/nd/RingND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun multiply (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun plus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun times (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun unaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public static fun unaryPlus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 }
 
 public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/RuntimeException {
@@ -1059,33 +1017,33 @@ 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/NumbersAddOperations {
+public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd/BufferedRingND, 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;
+	public fun getOne ()Lspace/kscience/kmath/nd/BufferND;
 	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer;
+	public fun getZero ()Lspace/kscience/kmath/nd/BufferND;
 	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 leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
-	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer;
+	public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND;
 	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 fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	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 rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 }
 
-public final class space/kscience/kmath/nd/ShortNDRingKt {
+public final class space/kscience/kmath/nd/ShortRingNDKt {
 	public static final fun nd (Lspace/kscience/kmath/operations/ShortRing;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-	public static final fun produceInline (Lspace/kscience/kmath/nd/BufferedNDRing;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer;
+	public static final fun produceInline (Lspace/kscience/kmath/nd/BufferedRingND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND;
 }
 
 public abstract interface class space/kscience/kmath/nd/Strides {
@@ -1101,25 +1059,24 @@ public final class space/kscience/kmath/nd/Strides$DefaultImpls {
 	public static fun indices (Lspace/kscience/kmath/nd/Strides;)Lkotlin/sequences/Sequence;
 }
 
-public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/NDStructure, space/kscience/kmath/structures/Buffer {
+public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer {
 	public abstract fun get ([I)Ljava/lang/Object;
 	public abstract fun getDimension ()I
 	public abstract fun iterator ()Ljava/util/Iterator;
 }
 
 public final class space/kscience/kmath/nd/Structure1D$DefaultImpls {
-	public static fun contentEquals (Lspace/kscience/kmath/nd/Structure1D;Lspace/kscience/kmath/structures/Buffer;)Z
 	public static fun get (Lspace/kscience/kmath/nd/Structure1D;[I)Ljava/lang/Object;
 	public static fun getDimension (Lspace/kscience/kmath/nd/Structure1D;)I
 	public static fun iterator (Lspace/kscience/kmath/nd/Structure1D;)Ljava/util/Iterator;
 }
 
 public final class space/kscience/kmath/nd/Structure1DKt {
-	public static final fun as1D (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/Structure1D;
+	public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D;
 	public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D;
 }
 
-public abstract interface class space/kscience/kmath/nd/Structure2D : space/kscience/kmath/nd/NDStructure {
+public abstract interface class space/kscience/kmath/nd/Structure2D : space/kscience/kmath/nd/StructureND {
 	public static final field Companion Lspace/kscience/kmath/nd/Structure2D$Companion;
 	public abstract fun elements ()Lkotlin/sequences/Sequence;
 	public abstract fun get (II)Ljava/lang/Object;
@@ -1144,7 +1101,35 @@ public final class space/kscience/kmath/nd/Structure2D$DefaultImpls {
 }
 
 public final class space/kscience/kmath/nd/Structure2DKt {
-	public static final fun as2D (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/Structure2D;
+	public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D;
+}
+
+public abstract interface class space/kscience/kmath/nd/StructureND {
+	public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion;
+	public abstract fun elements ()Lkotlin/sequences/Sequence;
+	public abstract fun get ([I)Ljava/lang/Object;
+	public abstract fun getDimension ()I
+	public abstract fun getShape ()[I
+}
+
+public final class space/kscience/kmath/nd/StructureND$Companion {
+	public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND;
+	public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND;
+	public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND;
+	public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND;
+	public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND;
+	public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND;
+	public final fun contentEquals (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Z
+	public final fun toString (Lspace/kscience/kmath/nd/StructureND;)Ljava/lang/String;
+}
+
+public final class space/kscience/kmath/nd/StructureND$DefaultImpls {
+	public static fun getDimension (Lspace/kscience/kmath/nd/StructureND;)I
+}
+
+public final class space/kscience/kmath/nd/StructureNDKt {
+	public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)Ljava/lang/Object;
+	public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableStructureND;Lkotlin/jvm/functions/Function2;)V
 }
 
 public abstract interface class space/kscience/kmath/operations/Algebra {
@@ -1287,7 +1272,7 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/
 
 public final class space/kscience/kmath/operations/BigIntKt {
 	public static final fun abs (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
-	public static final fun bigInt (Lspace/kscience/kmath/nd/NDAlgebra$Companion;[I)Lspace/kscience/kmath/nd/BufferedNDRing;
+	public static final fun bigInt (Lspace/kscience/kmath/nd/AlgebraND$Companion;[I)Lspace/kscience/kmath/nd/BufferedRingND;
 	public static final fun bigInt (Lspace/kscience/kmath/structures/Buffer$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
 	public static final fun bigInt (Lspace/kscience/kmath/structures/MutableBuffer$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer;
 	public static final fun parseBigInteger (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt;
@@ -1338,6 +1323,92 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma
 	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
 }
 
+public final class space/kscience/kmath/operations/DoubleField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations {
+	public static final field INSTANCE Lspace/kscience/kmath/operations/DoubleField;
+	public fun acos (D)Ljava/lang/Double;
+	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun acosh (D)Ljava/lang/Double;
+	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun add (DD)Ljava/lang/Double;
+	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun asin (D)Ljava/lang/Double;
+	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun asinh (D)Ljava/lang/Double;
+	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun atan (D)Ljava/lang/Double;
+	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun atanh (D)Ljava/lang/Double;
+	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun binaryOperation (Ljava/lang/String;DD)Ljava/lang/Double;
+	public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Double;
+	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
+	public fun cos (D)Ljava/lang/Double;
+	public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun cosh (D)Ljava/lang/Double;
+	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 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;
+	public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun exp (D)Ljava/lang/Double;
+	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun getOne ()Ljava/lang/Double;
+	public synthetic fun getOne ()Ljava/lang/Object;
+	public fun getZero ()Ljava/lang/Double;
+	public synthetic fun getZero ()Ljava/lang/Object;
+	public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;D)Ljava/lang/Double;
+	public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public fun ln (D)Ljava/lang/Double;
+	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
+	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 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;
+	public fun number (Ljava/lang/Number;)Ljava/lang/Double;
+	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
+	public fun plus (DD)Ljava/lang/Double;
+	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun pow (DLjava/lang/Number;)Ljava/lang/Double;
+	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun power (DLjava/lang/Number;)Ljava/lang/Double;
+	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	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;
+	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sqrt (D)Ljava/lang/Double;
+	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun tan (D)Ljava/lang/Double;
+	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun tanh (D)Ljava/lang/Double;
+	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun times (DD)Ljava/lang/Double;
+	public fun times (DLjava/lang/Number;)Ljava/lang/Double;
+	public fun times (Ljava/lang/Number;D)Ljava/lang/Double;
+	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 (D)Ljava/lang/Double;
+	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun unaryOperation (Ljava/lang/String;D)Ljava/lang/Double;
+	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
+	public fun unaryPlus (D)Ljava/lang/Double;
+	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
+}
+
 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;
@@ -1877,92 +1948,6 @@ 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, 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;
-	public fun acosh (D)Ljava/lang/Double;
-	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add (DD)Ljava/lang/Double;
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asin (D)Ljava/lang/Double;
-	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asinh (D)Ljava/lang/Double;
-	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atan (D)Ljava/lang/Double;
-	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atanh (D)Ljava/lang/Double;
-	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun binaryOperation (Ljava/lang/String;DD)Ljava/lang/Double;
-	public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Double;
-	public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
-	public fun cos (D)Ljava/lang/Double;
-	public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun cosh (D)Ljava/lang/Double;
-	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 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;
-	public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun exp (D)Ljava/lang/Double;
-	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun getOne ()Ljava/lang/Double;
-	public synthetic fun getOne ()Ljava/lang/Object;
-	public fun getZero ()Ljava/lang/Double;
-	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;D)Ljava/lang/Double;
-	public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public fun ln (D)Ljava/lang/Double;
-	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
-	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 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;
-	public fun number (Ljava/lang/Number;)Ljava/lang/Double;
-	public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
-	public fun plus (DD)Ljava/lang/Double;
-	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun pow (DLjava/lang/Number;)Ljava/lang/Double;
-	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun power (DLjava/lang/Number;)Ljava/lang/Double;
-	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	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;
-	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sqrt (D)Ljava/lang/Double;
-	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun tan (D)Ljava/lang/Double;
-	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun tanh (D)Ljava/lang/Double;
-	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun times (DD)Ljava/lang/Double;
-	public fun times (DLjava/lang/Number;)Ljava/lang/Double;
-	public fun times (Ljava/lang/Number;D)Ljava/lang/Double;
-	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 (D)Ljava/lang/Double;
-	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperation (Ljava/lang/String;D)Ljava/lang/Double;
-	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
-	public fun unaryPlus (D)Ljava/lang/Double;
-	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-}
-
 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;
 }
@@ -2096,7 +2081,6 @@ public final class space/kscience/kmath/operations/TrigonometricOperations$Defau
 
 public final class space/kscience/kmath/structures/ArrayBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public fun <init> ([Ljava/lang/Object;)V
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun get (I)Ljava/lang/Object;
 	public fun getSize ()I
@@ -2106,7 +2090,6 @@ public final class space/kscience/kmath/structures/ArrayBuffer : space/kscience/
 
 public abstract interface class space/kscience/kmath/structures/Buffer {
 	public static final field Companion Lspace/kscience/kmath/structures/Buffer$Companion;
-	public abstract fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
 	public abstract fun get (I)Ljava/lang/Object;
 	public abstract fun getSize ()I
 	public abstract fun iterator ()Ljava/util/Iterator;
@@ -2115,43 +2098,221 @@ public abstract interface class space/kscience/kmath/structures/Buffer {
 public final class space/kscience/kmath/structures/Buffer$Companion {
 	public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
 	public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
-	public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D
-}
-
-public final class space/kscience/kmath/structures/Buffer$DefaultImpls {
-	public static fun contentEquals (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Z
+	public final fun contentEquals (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Z
 }
 
 public final class space/kscience/kmath/structures/BufferKt {
-	public static final fun ListBuffer (ILkotlin/jvm/functions/Function1;)Ljava/util/List;
 	public static final fun asBuffer (Ljava/util/List;)Ljava/util/List;
 	public static final fun asBuffer ([Ljava/lang/Object;)Lspace/kscience/kmath/structures/ArrayBuffer;
-	public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable;
+	public static final fun asMutableBuffer (Ljava/util/List;)Ljava/util/List;
 	public static final fun asReadOnly (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	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 final class space/kscience/kmath/structures/BufferOperationKt {
+	public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable;
+	public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence;
 	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 final class space/kscience/kmath/structures/DoubleBuffer : space/kscience/kmath/structures/MutableBuffer {
+	public static final synthetic fun box-impl ([D)Lspace/kscience/kmath/structures/DoubleBuffer;
+	public static fun constructor-impl ([D)[D
+	public synthetic fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
+	public fun copy-Dv3HvWU ()[D
+	public static fun copy-Dv3HvWU ([D)[D
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl ([DLjava/lang/Object;)Z
+	public static final fun equals-impl0 ([D[D)Z
+	public fun get (I)Ljava/lang/Double;
+	public synthetic fun get (I)Ljava/lang/Object;
+	public static fun get-impl ([DI)Ljava/lang/Double;
+	public final fun getArray ()[D
+	public fun getSize ()I
+	public static fun getSize-impl ([D)I
+	public fun hashCode ()I
+	public static fun hashCode-impl ([D)I
+	public synthetic fun iterator ()Ljava/util/Iterator;
+	public fun iterator ()Lkotlin/collections/DoubleIterator;
+	public static fun iterator-impl ([D)Lkotlin/collections/DoubleIterator;
+	public fun set (ID)V
+	public synthetic fun set (ILjava/lang/Object;)V
+	public static fun set-impl ([DID)V
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl ([D)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()[D
+}
+
+public final class space/kscience/kmath/structures/DoubleBufferField : space/kscience/kmath/operations/ExtendedField {
+	public fun <init> (I)V
+	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun acos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun acosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun add-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun asin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun asinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun atan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun atanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	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 cos (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun cosh-Udx-57Q (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-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun exp-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun getOne ()Ljava/lang/Object;
+	public fun getOne ()Lspace/kscience/kmath/structures/Buffer;
+	public final fun getSize ()I
+	public synthetic fun getZero ()Ljava/lang/Object;
+	public fun getZero ()Lspace/kscience/kmath/structures/Buffer;
+	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/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
+	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun ln-Udx-57Q (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/Object;)Ljava/lang/Object;
+	public fun multiply-CZ9oacQ (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;
+	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;
+	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
+	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D
+	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-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;D)[D
+	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun tan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun tanh-Udx-57Q (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 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 final class space/kscience/kmath/structures/DoubleBufferFieldOperations : space/kscience/kmath/operations/ExtendedFieldOperations {
+	public static final field INSTANCE Lspace/kscience/kmath/structures/DoubleBufferFieldOperations;
+	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun acos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun acosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	public fun add-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun asin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun asinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun atan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun atanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	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 cos (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun cosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	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-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun exp-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun ln-Udx-57Q (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/Object;)Ljava/lang/Object;
+	public fun multiply-CZ9oacQ (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;
+	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
+	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
+	public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D
+	public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun tan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun tanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D
+	public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+	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-Udx-57Q (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;
+	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
+	public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
+}
+
+public final class space/kscience/kmath/structures/DoubleBufferKt {
+	public static final fun DoubleBuffer (ILkotlin/jvm/functions/Function1;)[D
+	public static final fun DoubleBuffer ([D)[D
+	public static final fun asBuffer ([D)[D
+	public static final fun contentEquals-2c9zdjM ([D[D)Z
+	public static final fun toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D
 }
 
 public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer {
 	public abstract fun getFlag (I)B
 }
 
-public final class space/kscience/kmath/structures/FlaggedBuffer$DefaultImpls {
-	public static fun contentEquals (Lspace/kscience/kmath/structures/FlaggedBuffer;Lspace/kscience/kmath/structures/Buffer;)Z
-}
-
 public final class space/kscience/kmath/structures/FlaggedBufferKt {
-	public static final fun forEachValid (Lspace/kscience/kmath/structures/FlaggedRealBuffer;Lkotlin/jvm/functions/Function1;)V
+	public static final fun forEachValid (Lspace/kscience/kmath/structures/FlaggedDoubleBuffer;Lkotlin/jvm/functions/Function1;)V
 	public static final fun hasFlag (Lspace/kscience/kmath/structures/FlaggedBuffer;ILspace/kscience/kmath/structures/ValueFlag;)Z
 	public static final fun isMissing (Lspace/kscience/kmath/structures/FlaggedBuffer;I)Z
 	public static final fun isValid (Lspace/kscience/kmath/structures/FlaggedBuffer;I)Z
 }
 
-public final class space/kscience/kmath/structures/FlaggedRealBuffer : space/kscience/kmath/structures/Buffer, space/kscience/kmath/structures/FlaggedBuffer {
+public final class space/kscience/kmath/structures/FlaggedDoubleBuffer : space/kscience/kmath/structures/Buffer, space/kscience/kmath/structures/FlaggedBuffer {
 	public fun <init> ([D[B)V
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun get (I)Ljava/lang/Double;
 	public synthetic fun get (I)Ljava/lang/Object;
 	public fun getFlag (I)B
@@ -2164,8 +2325,6 @@ public final class space/kscience/kmath/structures/FlaggedRealBuffer : space/ksc
 public final class space/kscience/kmath/structures/FloatBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public static final synthetic fun box-impl ([F)Lspace/kscience/kmath/structures/FloatBuffer;
 	public static fun constructor-impl ([F)[F
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl ([FLspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public static fun copy-impl ([F)Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun equals (Ljava/lang/Object;)Z
@@ -2200,8 +2359,6 @@ public final class space/kscience/kmath/structures/FloatBufferKt {
 public final class space/kscience/kmath/structures/IntBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public static final synthetic fun box-impl ([I)Lspace/kscience/kmath/structures/IntBuffer;
 	public static fun constructor-impl ([I)[I
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl ([ILspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public static fun copy-impl ([I)Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun equals (Ljava/lang/Object;)Z
@@ -2236,8 +2393,6 @@ public final class space/kscience/kmath/structures/IntBufferKt {
 public final class space/kscience/kmath/structures/ListBuffer : space/kscience/kmath/structures/Buffer {
 	public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/ListBuffer;
 	public static fun constructor-impl (Ljava/util/List;)Ljava/util/List;
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl (Ljava/util/List;Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun equals (Ljava/lang/Object;)Z
 	public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z
 	public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z
@@ -2258,8 +2413,6 @@ public final class space/kscience/kmath/structures/ListBuffer : space/kscience/k
 public final class space/kscience/kmath/structures/LongBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public static final synthetic fun box-impl ([J)Lspace/kscience/kmath/structures/LongBuffer;
 	public static fun constructor-impl ([J)[J
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl ([JLspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public static fun copy-impl ([J)Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun equals (Ljava/lang/Object;)Z
@@ -2294,7 +2447,6 @@ public final class space/kscience/kmath/structures/LongBufferKt {
 public class space/kscience/kmath/structures/MemoryBuffer : space/kscience/kmath/structures/Buffer {
 	public static final field Companion Lspace/kscience/kmath/structures/MemoryBuffer$Companion;
 	public fun <init> (Lspace/kscience/kmath/memory/Memory;Lspace/kscience/kmath/memory/MemorySpec;)V
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun get (I)Ljava/lang/Object;
 	protected final fun getMemory ()Lspace/kscience/kmath/memory/Memory;
 	public fun getSize ()I
@@ -2316,18 +2468,16 @@ public abstract interface class space/kscience/kmath/structures/MutableBuffer :
 public final class space/kscience/kmath/structures/MutableBuffer$Companion {
 	public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer;
 	public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer;
-	public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D
-}
-
-public final class space/kscience/kmath/structures/MutableBuffer$DefaultImpls {
-	public static fun contentEquals (Lspace/kscience/kmath/structures/MutableBuffer;Lspace/kscience/kmath/structures/Buffer;)Z
+	public final fun double-CZ9oacQ (ILkotlin/jvm/functions/Function1;)[D
+	public final fun float-YxruXGw (ILkotlin/jvm/functions/Function1;)[F
+	public final fun int-Ye6GY2U (ILkotlin/jvm/functions/Function1;)[I
+	public final fun long-BuQOeTY (ILkotlin/jvm/functions/Function1;)[J
+	public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S
 }
 
 public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer;
 	public static fun constructor-impl (Ljava/util/List;)Ljava/util/List;
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl (Ljava/util/List;Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public static fun copy-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun equals (Ljava/lang/Object;)Z
@@ -2364,8 +2514,6 @@ public final class space/kscience/kmath/structures/MutableMemoryBuffer$Companion
 public final class space/kscience/kmath/structures/ReadOnlyBuffer : space/kscience/kmath/structures/Buffer {
 	public static final synthetic fun box-impl (Lspace/kscience/kmath/structures/MutableBuffer;)Lspace/kscience/kmath/structures/ReadOnlyBuffer;
 	public static fun constructor-impl (Lspace/kscience/kmath/structures/MutableBuffer;)Lspace/kscience/kmath/structures/MutableBuffer;
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl (Lspace/kscience/kmath/structures/MutableBuffer;Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun equals (Ljava/lang/Object;)Z
 	public static fun equals-impl (Lspace/kscience/kmath/structures/MutableBuffer;Ljava/lang/Object;)Z
 	public static final fun equals-impl0 (Lspace/kscience/kmath/structures/MutableBuffer;Lspace/kscience/kmath/structures/MutableBuffer;)Z
@@ -2383,198 +2531,9 @@ public final class space/kscience/kmath/structures/ReadOnlyBuffer : space/kscien
 	public final synthetic fun unbox-impl ()Lspace/kscience/kmath/structures/MutableBuffer;
 }
 
-public final class space/kscience/kmath/structures/RealBuffer : space/kscience/kmath/structures/MutableBuffer {
-	public static final synthetic fun box-impl ([D)Lspace/kscience/kmath/structures/RealBuffer;
-	public static fun constructor-impl ([D)[D
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl ([DLspace/kscience/kmath/structures/Buffer;)Z
-	public synthetic fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
-	public fun copy-88GwAag ()[D
-	public static fun copy-88GwAag ([D)[D
-	public fun equals (Ljava/lang/Object;)Z
-	public static fun equals-impl ([DLjava/lang/Object;)Z
-	public static final fun equals-impl0 ([D[D)Z
-	public fun get (I)Ljava/lang/Double;
-	public synthetic fun get (I)Ljava/lang/Object;
-	public static fun get-impl ([DI)Ljava/lang/Double;
-	public final fun getArray ()[D
-	public fun getSize ()I
-	public static fun getSize-impl ([D)I
-	public fun hashCode ()I
-	public static fun hashCode-impl ([D)I
-	public synthetic fun iterator ()Ljava/util/Iterator;
-	public fun iterator ()Lkotlin/collections/DoubleIterator;
-	public static fun iterator-impl ([D)Lkotlin/collections/DoubleIterator;
-	public fun set (ID)V
-	public synthetic fun set (ILjava/lang/Object;)V
-	public static fun set-impl ([DID)V
-	public fun toString ()Ljava/lang/String;
-	public static fun toString-impl ([D)Ljava/lang/String;
-	public final synthetic fun unbox-impl ()[D
-}
-
-public final class space/kscience/kmath/structures/RealBufferField : space/kscience/kmath/operations/ExtendedField {
-	public fun <init> (I)V
-	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun acos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun acosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	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 cos (Ljava/lang/Object;)Ljava/lang/Object;
-	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
-	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun exp-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun getOne ()Ljava/lang/Object;
-	public fun getOne ()Lspace/kscience/kmath/structures/Buffer;
-	public final fun getSize ()I
-	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun getZero ()Lspace/kscience/kmath/structures/Buffer;
-	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/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
-	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
-	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/Object;)Ljava/lang/Object;
-	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;
-	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;
-	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun power-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D
-	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;
-	public fun sinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
-	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 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 final class space/kscience/kmath/structures/RealBufferFieldOperations : space/kscience/kmath/operations/ExtendedFieldOperations {
-	public static final field INSTANCE Lspace/kscience/kmath/structures/RealBufferFieldOperations;
-	public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun acos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun acosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun add-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	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 cos (Ljava/lang/Object;)Ljava/lang/Object;
-	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/Object;)Ljava/lang/Object;
-	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
-	public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun exp-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
-	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/Object;)Ljava/lang/Object;
-	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;
-	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun power-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[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;
-	public fun sinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D
-	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
-	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/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	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-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;
-	public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
-}
-
-public final class space/kscience/kmath/structures/RealBufferKt {
-	public static final fun RealBuffer (ILkotlin/jvm/functions/Function1;)[D
-	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 toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D
-}
-
 public final class space/kscience/kmath/structures/ShortBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public static final synthetic fun box-impl ([S)Lspace/kscience/kmath/structures/ShortBuffer;
 	public static fun constructor-impl ([S)[S
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl ([SLspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public static fun copy-impl ([S)Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun equals (Ljava/lang/Object;)Z
@@ -2618,7 +2577,6 @@ public final class space/kscience/kmath/structures/ValueFlag : java/lang/Enum {
 
 public final class space/kscience/kmath/structures/VirtualBuffer : space/kscience/kmath/structures/Buffer {
 	public fun <init> (ILkotlin/jvm/functions/Function1;)V
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun get (I)Ljava/lang/Object;
 	public fun getSize ()I
 	public fun iterator ()Ljava/util/Iterator;
diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts
index 8d30f1d6e..2fed3eb2f 100644
--- a/kmath-core/build.gradle.kts
+++ b/kmath-core/build.gradle.kts
@@ -23,13 +23,13 @@ readme {
         description = """
             Algebraic structures like rings, spaces and fields.
         """.trimIndent(),
-        ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt"
     )
 
     feature(
         id = "nd",
         description = "Many-dimensional structures and operations on them.",
-        ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt"
     )
 
     feature(
@@ -37,13 +37,13 @@ readme {
         description = """
             Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
         """.trimIndent(),
-        ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt"
     )
 
     feature(
         id = "buffers",
         description = "One-dimensional structure",
-        ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt"
     )
 
     feature(
@@ -53,18 +53,18 @@ readme {
             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.
         """.trimIndent(),
-        ref = "src/commonMain/kotlin/kscience/kmath/expressions"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/expressions"
     )
 
     feature(
         id = "domains",
         description = "Domains",
-        ref = "src/commonMain/kotlin/kscience/kmath/domains"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/domains"
     )
 
     feature(
         id = "autodif",
         description = "Automatic differentiation",
-        ref = "src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt"
     )
 }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt
similarity index 95%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt
index c20cbfec1..057a4a344 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt
@@ -23,7 +23,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
  * @author Alexander Nozik
  */
 @UnstableKMathAPI
-public interface RealDomain : Domain<Double> {
+public interface DoubleDomain : Domain<Double> {
 
     /**
      * Global lower edge
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 c948f8672..a15d04b4c 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
@@ -27,7 +27,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 class HyperSquareDomain(private val lower: Buffer<Double>, private val upper: Buffer<Double>) : DoubleDomain {
     public override val dimension: Int get() = lower.size
 
     public override operator fun contains(point: Point<Double>): Boolean = point.indices.all { i ->
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 002caac50..79f33fe05 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
@@ -19,7 +19,7 @@ import space.kscience.kmath.linear.Point
 import space.kscience.kmath.misc.UnstableKMathAPI
 
 @UnstableKMathAPI
-public class UnconstrainedDomain(public override val dimension: Int) : RealDomain {
+public class UnconstrainedDomain(public override val dimension: Int) : DoubleDomain {
     public override operator fun contains(point: Point<Double>): Boolean = true
 
     public override fun getLowerBound(num: Int): Double = Double.NEGATIVE_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 d20349960..6f737bd38 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
@@ -4,7 +4,7 @@ import space.kscience.kmath.linear.Point
 import space.kscience.kmath.misc.UnstableKMathAPI
 
 @UnstableKMathAPI
-public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<Double>) : RealDomain {
+public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<Double>) : DoubleDomain {
     public override val dimension: Int get() = 1
 
     public operator fun contains(d: Double): Boolean = range.contains(d)
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt
index 508a62aca..5cbc4dbf4 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt
@@ -28,7 +28,7 @@ public fun <T, R : Expression<T>> DifferentiableExpression<T, R>.derivative(name
 /**
  * A [DifferentiableExpression] that defines only first derivatives
  */
-public abstract class FirstDerivativeExpression<T, R : Expression<T>> : DifferentiableExpression<T,R> {
+public abstract class FirstDerivativeExpression<T, R : Expression<T>> : DifferentiableExpression<T, R> {
     /**
      * Returns first derivative of this expression by given [symbol].
      */
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt
index 231bbdab1..5ba24aa62 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt
@@ -95,7 +95,7 @@ public fun <T, E> ExpressionAlgebra<T, E>.bindSymbol(symbol: Symbol): E =
 /**
  * A delegate to create a symbol with a string identity in this scope
  */
-public val symbol: ReadOnlyProperty<Any?, Symbol>  = ReadOnlyProperty { _, property ->
+public val symbol: ReadOnlyProperty<Any?, Symbol> = ReadOnlyProperty { _, property ->
     StringSymbol(property.name)
 }
 
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 880f13a3e..cca75754f 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
@@ -98,7 +98,7 @@ public open class FunctionalExpressionRing<T, A : Ring<T>>(
         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>>,
     ScaleOperations<Expression<T>> {
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 4b5b3311e..4b0d402ed 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
@@ -198,7 +198,7 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
  * 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
+ * val y = DoubleField.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
  * ```
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt
similarity index 94%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt
index b6c2ea17b..662cd6409 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt
@@ -9,7 +9,7 @@ import space.kscience.kmath.structures.VirtualBuffer
 import space.kscience.kmath.structures.indices
 
 
-public class BufferLinearSpace<T : Any, A : Ring<T>>(
+public class BufferedLinearSpace<T : Any, A : Ring<T>>(
     override val elementAlgebra: A,
     private val bufferFactory: BufferFactory<T>,
 ) : LinearSpace<T, A> {
@@ -17,7 +17,7 @@ public class BufferLinearSpace<T : Any, A : Ring<T>>(
     private fun ndRing(
         rows: Int,
         cols: Int,
-    ): BufferedNDRing<T, A> = NDAlgebra.ring(elementAlgebra, bufferFactory, rows, cols)
+    ): BufferedRingND<T, A> = AlgebraND.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()
@@ -48,7 +48,7 @@ public class BufferLinearSpace<T : Any, A : Ring<T>>(
     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 rows = this@dot.rows.map { it.linearize() }
             val columns = other.columns.map { it.linearize() }
             buildMatrix(rowNum, other.colNum) { i, j ->
                 val r = rows[i]
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt
index 6cce5a446..af136c552 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt
@@ -6,9 +6,20 @@ 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> {
+    /**
+     * Solve a dot x = b matrix equation and return x
+     */
     public fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T>
+
+    /**
+     * Solve a dot x = b vector equation and return b
+     */
     public fun solve(a: Matrix<T>, b: Point<T>): Point<T> = solve(a, b.asMatrix()).asVector()
-    public fun inverse(a: Matrix<T>): Matrix<T>
+
+    /**
+     * Get inverse of a matrix
+     */
+    public fun inverse(matrix: Matrix<T>): Matrix<T>
 }
 
 /**
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
index 1642bfb14..6a587270b 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt
@@ -5,6 +5,7 @@ import space.kscience.kmath.nd.*
 import space.kscience.kmath.operations.*
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.BufferFactory
+import space.kscience.kmath.structures.DoubleBuffer
 import kotlin.reflect.KClass
 
 /**
@@ -155,16 +156,15 @@ public interface LinearSpace<T : Any, out A : Ring<T>> {
     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].
+     * Get a feature of the structure in this scope. Structure features take precedence other context features
      *
      * @param F the type of feature.
-     * @param m the matrix.
+     * @param structure the structure.
      * @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 fun <F : Any> getFeature(structure: Matrix<T>, type: KClass<F>): F? = structure.getFeature(type)
 
     public companion object {
 
@@ -174,9 +174,9 @@ public interface LinearSpace<T : Any, out A : Ring<T>> {
         public fun <T : Any, A : Ring<T>> buffered(
             algebra: A,
             bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
-        ): LinearSpace<T, A> = BufferLinearSpace(algebra,bufferFactory)
+        ): LinearSpace<T, A> = BufferedLinearSpace(algebra, bufferFactory)
 
-        public val real: LinearSpace<Double, RealField> = buffered(RealField, Buffer.Companion::real)
+        public val real: LinearSpace<Double, DoubleField> = buffered(DoubleField, ::DoubleBuffer)
 
         /**
          * Automatic buffered matrix, unboxed if it is possible
@@ -186,19 +186,17 @@ public interface LinearSpace<T : Any, out A : Ring<T>> {
     }
 }
 
-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].
+ * Get a feature of the structure in this scope. Structure features take precedence other context features
  *
  * @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)
+public inline fun <T : Any, reified F : Any> LinearSpace<T, *>.getFeature(structure: Matrix<T>): F? =
+    getFeature(structure, F::class)
+
+
+public operator fun <LS : LinearSpace<*, *>, R> LS.invoke(block: LS.() -> R): R = run(block)
 
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 0937f1e19..7a6495638 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
@@ -3,8 +3,8 @@ package space.kscience.kmath.linear
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.nd.getFeature
 import space.kscience.kmath.operations.*
-import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.BufferAccessor2D
+import space.kscience.kmath.structures.DoubleBuffer
 import space.kscience.kmath.structures.MutableBuffer
 import space.kscience.kmath.structures.MutableBufferFactory
 
@@ -151,8 +151,8 @@ public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
     noinline checkSingular: (T) -> Boolean,
 ): LupDecomposition<T> = lup(MutableBuffer.Companion::auto, matrix, checkSingular)
 
-public fun LinearSpace<Double, RealField>.lup(matrix: Matrix<Double>): LupDecomposition<Double> =
-    lup(Buffer.Companion::real, matrix) { it < 1e-11 }
+public fun LinearSpace<Double, DoubleField>.lup(matrix: Matrix<Double>): LupDecomposition<Double> =
+    lup(::DoubleBuffer, matrix) { it < 1e-11 }
 
 public fun <T : Any> LupDecomposition<T>.solveWithLup(
     factory: MutableBufferFactory<T>,
@@ -228,9 +228,9 @@ public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.inverseWi
 
 
 @OptIn(UnstableKMathAPI::class)
-public fun LinearSpace<Double, RealField>.solveWithLup(a: Matrix<Double>, b: Matrix<Double>): Matrix<Double> {
+public fun LinearSpace<Double, DoubleField>.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 bufferFactory: MutableBufferFactory<Double> = ::DoubleBuffer
     val decomposition: LupDecomposition<Double> = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 }
     return decomposition.solveWithLup(bufferFactory, b)
 }
@@ -238,5 +238,5 @@ public fun LinearSpace<Double, RealField>.solveWithLup(a: Matrix<Double>, b: Mat
 /**
  * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error.
  */
-public fun LinearSpace<Double, RealField>.inverseWithLup(matrix: Matrix<Double>): Matrix<Double> =
+public fun LinearSpace<Double, DoubleField>.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/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt
index 97f0acd61..868f74cc6 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
@@ -23,8 +23,6 @@ public class MatrixWrapper<T : Any> internal constructor(
     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
-    override fun hashCode(): Int = origin.hashCode()
     override fun toString(): String {
         return "MatrixWrapper(matrix=$origin, features=$features)"
     }
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 7f0451946..e80ee5ebd 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,7 +1,5 @@
 package space.kscience.kmath.linear
 
-import space.kscience.kmath.nd.NDStructure
-
 /**
  * The matrix where each element is evaluated each time when is being accessed.
  *
@@ -10,23 +8,10 @@ import space.kscience.kmath.nd.NDStructure
 public class VirtualMatrix<T : Any>(
     override val rowNum: Int,
     override val colNum: Int,
-    public val generator: (i: Int, j: Int) -> T
+    public val generator: (i: Int, j: Int) -> T,
 ) : Matrix<T> {
 
     override val shape: IntArray get() = intArrayOf(rowNum, colNum)
 
     override operator fun get(i: Int, j: Int): T = generator(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 {
-        var result = rowNum
-        result = 31 * result + colNum
-        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 b50e095cf..6466695a6 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
@@ -37,8 +37,8 @@ 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: Group<T>): Iterable<T> =
-    space { cumulative(zero) { element: T, sum: T -> sum + element } }
+public fun <T> Iterable<T>.cumulativeSum(group: Group<T>): Iterable<T> =
+    group { cumulative(zero) { element: T, sum: T -> sum + element } }
 
 @JvmName("cumulativeSumOfDouble")
 public fun Iterable<Double>.cumulativeSum(): Iterable<Double> = cumulative(0.0) { element, sum -> sum + element }
@@ -49,8 +49,8 @@ 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: Group<T>): Sequence<T> =
-    space { cumulative(zero) { element: T, sum: T -> sum + element } }
+public fun <T> Sequence<T>.cumulativeSum(group: Group<T>): Sequence<T> =
+    group { cumulative(zero) { element: T, sum: T -> sum + element } }
 
 @JvmName("cumulativeSumOfDouble")
 public fun Sequence<Double>.cumulativeSum(): Sequence<Double> = cumulative(0.0) { element, sum -> sum + element }
@@ -61,8 +61,8 @@ 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: Group<T>): List<T> =
-    space { cumulative(zero) { element: T, sum: T -> sum + element } }
+public fun <T> List<T>.cumulativeSum(group: Group<T>): List<T> =
+    group { cumulative(zero) { element: T, sum: T -> sum + element } }
 
 @JvmName("cumulativeSumOfDouble")
 public fun List<Double>.cumulativeSum(): List<Double> = cumulative(0.0) { element, sum -> sum + element }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt
similarity index 66%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt
index e3ffae74b..b23ce947d 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt
@@ -1,7 +1,9 @@
 package space.kscience.kmath.nd
 
+import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.operations.*
 import space.kscience.kmath.structures.*
+import kotlin.reflect.KClass
 
 /**
  * An exception is thrown when the expected ans actual shape of NDArray differs.
@@ -19,7 +21,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: Algebra<T>> {
+public interface AlgebraND<T, C : Algebra<T>> {
     /**
      * The shape of ND-structures this algebra operates on.
      */
@@ -33,43 +35,67 @@ public interface NDAlgebra<T, C: Algebra<T>> {
     /**
      * Produces a new NDStructure using given initializer function.
      */
-    public fun produce(initializer: C.(IntArray) -> T): NDStructure<T>
+    public fun produce(initializer: C.(IntArray) -> T): StructureND<T>
 
     /**
      * Maps elements from one structure to another one by applying [transform] to them.
      */
-    public fun NDStructure<T>.map(transform: C.(T) -> T): NDStructure<T>
+    public fun StructureND<T>.map(transform: C.(T) -> T): StructureND<T>
 
     /**
      * Maps elements from one structure to another one by applying [transform] to them alongside with their indices.
      */
-    public fun NDStructure<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDStructure<T>
+    public fun StructureND<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): StructureND<T>
 
     /**
      * Combines two structures into one.
      */
-    public fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: C.(T, T) -> T): NDStructure<T>
+    public fun combine(a: StructureND<T>, b: StructureND<T>, transform: C.(T, T) -> T): StructureND<T>
 
     /**
-     * Element-wise invocation of function working on [T] on a [NDStructure].
+     * Element-wise invocation of function working on [T] on a [StructureND].
      */
-    public operator fun Function1<T, T>.invoke(structure: NDStructure<T>): NDStructure<T> =
+    public operator fun Function1<T, T>.invoke(structure: StructureND<T>): StructureND<T> =
         structure.map { value -> this@invoke(value) }
 
+    /**
+     * Get a feature of the structure in this scope. Structure features take precedence other context features
+     *
+     * @param F the type of feature.
+     * @param structure the structure.
+     * @param type the [KClass] instance of [F].
+     * @return a feature object or `null` if it isn't present.
+     */
+    @UnstableKMathAPI
+    public fun <F : Any> getFeature(structure: StructureND<T>, type: KClass<F>): F? = structure.getFeature(type)
+
     public companion object
 }
 
+
+/**
+ * Get a feature of the structure in this scope. Structure features take precedence other context features
+ *
+ * @param T the type of items in the matrices.
+ * @param F the type of feature.
+ * @return a feature object or `null` if it isn't present.
+ */
+@UnstableKMathAPI
+public inline fun <T : Any, reified F : Any> AlgebraND<T, *>.getFeature(structure: StructureND<T>): F? =
+    getFeature(structure, F::class)
+
 /**
  * Checks if given elements are consistent with this context.
  *
  * @param structures the structures to check.
  * @return the array of valid 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) }
-    ?: structures
+internal fun <T, C : Algebra<T>> AlgebraND<T, C>.checkShape(vararg structures: StructureND<T>): Array<out StructureND<T>> =
+    structures
+        .map(StructureND<T>::shape)
+        .singleOrNull { !shape.contentEquals(it) }
+        ?.let<IntArray, Array<out StructureND<T>>> { throw ShapeMismatchException(shape, it) }
+        ?: structures
 
 /**
  * Checks if given element is consistent with this context.
@@ -77,19 +103,19 @@ internal fun <T, C: Algebra<T>> NDAlgebra<T, C>.checkShape(vararg structures: ND
  * @param element the structure to check.
  * @return the valid structure.
  */
-internal fun <T, C: Algebra<T>> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStructure<T> {
+internal fun <T, C : Algebra<T>> AlgebraND<T, C>.checkShape(element: StructureND<T>): StructureND<T> {
     if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape)
     return element
 }
 
 /**
- * Space of [NDStructure].
+ * Space of [StructureND].
  *
  * @param T the type of the element contained in ND structure.
  * @param N the type of ND structure.
  * @param S the type of space of structure elements.
  */
-public interface NDGroup<T, S : Group<T>> : Group<NDStructure<T>>, NDAlgebra<T, S> {
+public interface GroupND<T, S : Group<T>> : Group<StructureND<T>>, AlgebraND<T, S> {
     /**
      * Element-wise addition.
      *
@@ -97,7 +123,7 @@ public interface NDGroup<T, S : Group<T>> : Group<NDStructure<T>>, NDAlgebra<T,
      * @param b the augend.
      * @return the sum.
      */
-    public override fun add(a: NDStructure<T>, b: NDStructure<T>): NDStructure<T> =
+    public override fun add(a: StructureND<T>, b: StructureND<T>): StructureND<T> =
         combine(a, b) { aValue, bValue -> add(aValue, bValue) }
 
 //    /**
@@ -118,7 +144,7 @@ public interface NDGroup<T, S : Group<T>> : Group<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 StructureND<T>.plus(arg: T): StructureND<T> = this.map { value -> add(arg, value) }
 
     /**
      * Subtracts an element from ND structure of it.
@@ -127,7 +153,7 @@ public interface NDGroup<T, S : Group<T>> : Group<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 StructureND<T>.minus(arg: T): StructureND<T> = this.map { value -> add(arg, -value) }
 
     /**
      * Adds an element to ND structure of it.
@@ -136,7 +162,7 @@ public interface NDGroup<T, S : Group<T>> : Group<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: StructureND<T>): StructureND<T> = arg.map { value -> add(this@plus, value) }
 
     /**
      * Subtracts an ND structure from an element of it.
@@ -145,19 +171,19 @@ public interface NDGroup<T, S : Group<T>> : Group<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: StructureND<T>): StructureND<T> = arg.map { value -> add(-this@minus, value) }
 
     public companion object
 }
 
 /**
- * Ring of [NDStructure].
+ * Ring of [StructureND].
  *
  * @param T the type of the element contained in ND structure.
  * @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>>, NDGroup<T, R> {
+public interface RingND<T, R : Ring<T>> : Ring<StructureND<T>>, GroupND<T, R> {
     /**
      * Element-wise multiplication.
      *
@@ -165,7 +191,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDGroup<T, R> {
      * @param b the multiplier.
      * @return the product.
      */
-    public override fun multiply(a: NDStructure<T>, b: NDStructure<T>): NDStructure<T> =
+    public override fun multiply(a: StructureND<T>, b: StructureND<T>): StructureND<T> =
         combine(a, b) { aValue, bValue -> multiply(aValue, bValue) }
 
     //TODO move to extensions after KEEP-176
@@ -177,7 +203,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDGroup<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 StructureND<T>.times(arg: T): StructureND<T> = this.map { value -> multiply(arg, value) }
 
     /**
      * Multiplies an element by a ND structure of it.
@@ -186,19 +212,19 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDGroup<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: StructureND<T>): StructureND<T> = arg.map { value -> multiply(this@times, value) }
 
     public companion object
 }
 
 /**
- * Field of [NDStructure].
+ * Field of [StructureND].
  *
  * @param T the type of the element contained in ND structure.
  * @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>, ScaleOperations<NDStructure<T>> {
+public interface FieldND<T, F : Field<T>> : Field<StructureND<T>>, RingND<T, F>, ScaleOperations<StructureND<T>> {
     /**
      * Element-wise division.
      *
@@ -206,7 +232,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>,
      * @param b the divisor.
      * @return the quotient.
      */
-    public override fun divide(a: NDStructure<T>, b: NDStructure<T>): NDStructure<T> =
+    public override fun divide(a: StructureND<T>, b: StructureND<T>): StructureND<T> =
         combine(a, b) { aValue, bValue -> divide(aValue, bValue) }
 
     //TODO move to extensions after KEEP-176
@@ -217,7 +243,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 StructureND<T>.div(arg: T): StructureND<T> = this.map { value -> divide(arg, value) }
 
     /**
      * Divides an element by an ND structure of it.
@@ -226,7 +252,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: StructureND<T>): StructureND<T> = arg.map { divide(it, this@div) }
 
 //    @ThreadLocal
 //    public companion object {
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt
similarity index 52%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt
index bce3a0830..67e94df74 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt
@@ -6,132 +6,132 @@ import space.kscience.kmath.structures.BufferFactory
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 
-public interface BufferNDAlgebra<T, A : Algebra<T>> : NDAlgebra<T, A> {
+public interface BufferAlgebraND<T, A : Algebra<T>> : AlgebraND<T, A> {
     public val strides: Strides
     public val bufferFactory: BufferFactory<T>
 
-    override fun produce(initializer: A.(IntArray) -> T): NDBuffer<T> = NDBuffer(
+    override fun produce(initializer: A.(IntArray) -> T): BufferND<T> = BufferND(
         strides,
         bufferFactory(strides.linearSize) { offset ->
             elementContext.initializer(strides.index(offset))
         }
     )
 
-    public val NDStructure<T>.buffer: Buffer<T>
+    public val StructureND<T>.buffer: Buffer<T>
         get() = when {
-            !shape.contentEquals(this@BufferNDAlgebra.shape) -> throw ShapeMismatchException(
-                this@BufferNDAlgebra.shape,
+            !shape.contentEquals(this@BufferAlgebraND.shape) -> throw ShapeMismatchException(
+                this@BufferAlgebraND.shape,
                 shape
             )
-            this is NDBuffer && this.strides == this@BufferNDAlgebra.strides -> this.buffer
+            this is BufferND && this.strides == this@BufferAlgebraND.strides -> this.buffer
             else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) }
         }
 
-    override fun NDStructure<T>.map(transform: A.(T) -> T): NDBuffer<T> {
+    override fun StructureND<T>.map(transform: A.(T) -> T): BufferND<T> {
         val buffer = bufferFactory(strides.linearSize) { offset ->
             elementContext.transform(buffer[offset])
         }
-        return NDBuffer(strides, buffer)
+        return BufferND(strides, buffer)
     }
 
-    override fun NDStructure<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer<T> {
+    override fun StructureND<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): BufferND<T> {
         val buffer = bufferFactory(strides.linearSize) { offset ->
             elementContext.transform(
                 strides.index(offset),
                 buffer[offset]
             )
         }
-        return NDBuffer(strides, buffer)
+        return BufferND(strides, buffer)
     }
 
-    override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: A.(T, T) -> T): NDBuffer<T> {
+    override fun combine(a: StructureND<T>, b: StructureND<T>, transform: A.(T, T) -> T): BufferND<T> {
         val buffer = bufferFactory(strides.linearSize) { offset ->
             elementContext.transform(a.buffer[offset], b.buffer[offset])
         }
-        return NDBuffer(strides, buffer)
+        return BufferND(strides, buffer)
     }
 }
 
-public open class BufferedNDGroup<T, A : Group<T>>(
+public open class BufferedGroupND<T, A : Group<T>>(
     final override val shape: IntArray,
     final override val elementContext: A,
     final override val bufferFactory: BufferFactory<T>,
-) : NDGroup<T, A>, BufferNDAlgebra<T, A> {
+) : GroupND<T, A>, BufferAlgebraND<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) }
+    override val zero: BufferND<T> by lazy { produce { zero } }
+    override fun StructureND<T>.unaryMinus(): StructureND<T> = produce { -get(it) }
 }
 
-public open class BufferedNDRing<T, R : Ring<T>>(
+public open class BufferedRingND<T, R : Ring<T>>(
     shape: IntArray,
     elementContext: R,
     bufferFactory: BufferFactory<T>,
-) : BufferedNDGroup<T, R>(shape, elementContext, bufferFactory), NDRing<T, R> {
-    override val one: NDBuffer<T> by lazy { produce { one } }
+) : BufferedGroupND<T, R>(shape, elementContext, bufferFactory), RingND<T, R> {
+    override val one: BufferND<T> by lazy { produce { one } }
 }
 
-public open class BufferedNDField<T, R : Field<T>>(
+public open class BufferedFieldND<T, R : Field<T>>(
     shape: IntArray,
     elementContext: R,
     bufferFactory: BufferFactory<T>,
-) : BufferedNDRing<T, R>(shape, elementContext, bufferFactory), NDField<T, R> {
+) : BufferedRingND<T, R>(shape, elementContext, bufferFactory), FieldND<T, R> {
 
-    override fun scale(a: NDStructure<T>, value: Double): NDStructure<T> = a.map { it * value }
+    override fun scale(a: StructureND<T>, value: Double): StructureND<T> = a.map { it * value }
 }
 
 // group factories
-public fun <T, A : Group<T>> NDAlgebra.Companion.group(
+public fun <T, A : Group<T>> AlgebraND.Companion.group(
     space: A,
     bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-): BufferedNDGroup<T, A> = BufferedNDGroup(shape, space, bufferFactory)
+): BufferedGroupND<T, A> = BufferedGroupND(shape, space, bufferFactory)
 
 public inline fun <T, A : Group<T>, R> A.ndGroup(
     noinline bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-    action: BufferedNDGroup<T, A>.() -> R,
+    action: BufferedGroupND<T, A>.() -> R,
 ): R {
     contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return NDAlgebra.group(this, bufferFactory, *shape).run(action)
+    return AlgebraND.group(this, bufferFactory, *shape).run(action)
 }
 
 //ring factories
-public fun <T, A : Ring<T>> NDAlgebra.Companion.ring(
+public fun <T, A : Ring<T>> AlgebraND.Companion.ring(
     ring: A,
     bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-): BufferedNDRing<T, A> = BufferedNDRing(shape, ring, bufferFactory)
+): BufferedRingND<T, A> = BufferedRingND(shape, ring, bufferFactory)
 
 public inline fun <T, A : Ring<T>, R> A.ndRing(
     noinline bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-    action: BufferedNDRing<T, A>.() -> R,
+    action: BufferedRingND<T, A>.() -> R,
 ): R {
     contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return NDAlgebra.ring(this, bufferFactory, *shape).run(action)
+    return AlgebraND.ring(this, bufferFactory, *shape).run(action)
 }
 
 //field factories
-public fun <T, A : Field<T>> NDAlgebra.Companion.field(
+public fun <T, A : Field<T>> AlgebraND.Companion.field(
     field: A,
     bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-): BufferedNDField<T, A> = BufferedNDField(shape, field, bufferFactory)
+): BufferedFieldND<T, A> = BufferedFieldND(shape, field, bufferFactory)
 
 @Suppress("UNCHECKED_CAST")
-public inline fun <reified T : Any, A : Field<T>> NDAlgebra.Companion.auto(
+public inline fun <reified T : Any, A : Field<T>> AlgebraND.Companion.auto(
     field: A,
     vararg shape: Int,
-): NDField<T, A> = when (field) {
-    RealField -> RealNDField(shape) as NDField<T, A>
-    else -> BufferedNDField(shape, field, Buffer.Companion::auto)
+): FieldND<T, A> = when (field) {
+    DoubleField -> DoubleFieldND(shape) as FieldND<T, A>
+    else -> BufferedFieldND(shape, field, Buffer.Companion::auto)
 }
 
 public inline fun <T, A : Field<T>, R> A.ndField(
     noinline bufferFactory: BufferFactory<T>,
     vararg shape: Int,
-    action: BufferedNDField<T, A>.() -> R,
+    action: BufferedFieldND<T, A>.() -> R,
 ): R {
     contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return NDAlgebra.field(this, bufferFactory, *shape).run(action)
+    return AlgebraND.field(this, bufferFactory, *shape).run(action)
 }
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt
new file mode 100644
index 000000000..c7f8d222d
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt
@@ -0,0 +1,48 @@
+package space.kscience.kmath.nd
+
+import space.kscience.kmath.structures.Buffer
+import space.kscience.kmath.structures.BufferFactory
+
+/**
+ * Represents [StructureND] over [Buffer].
+ *
+ * @param T the type of items.
+ * @param strides The strides to access elements of [Buffer] by linear indices.
+ * @param buffer The underlying buffer.
+ */
+public class BufferND<T>(
+    public val strides: Strides,
+    public val buffer: Buffer<T>,
+) : StructureND<T> {
+
+    init {
+        if (strides.linearSize != buffer.size) {
+            error("Expected buffer side of ${strides.linearSize}, but found ${buffer.size}")
+        }
+    }
+
+    override operator fun get(index: IntArray): T = buffer[strides.offset(index)]
+
+    override val shape: IntArray get() = strides.shape
+
+    override fun elements(): Sequence<Pair<IntArray, T>> = strides.indices().map {
+        it to this[it]
+    }
+
+    override fun toString(): String = StructureND.toString(this)
+}
+
+/**
+ * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND]
+ */
+public inline fun <T, reified R : Any> StructureND<T>.mapToBuffer(
+    factory: BufferFactory<R> = Buffer.Companion::auto,
+    crossinline transform: (T) -> R,
+): BufferND<R> {
+    return if (this is BufferND<T>)
+        BufferND(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) })
+    else {
+        val strides = DefaultStrides(shape)
+        BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) })
+    }
+}
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt
new file mode 100644
index 000000000..d38ed02da
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt
@@ -0,0 +1,110 @@
+package space.kscience.kmath.nd
+
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.NumbersAddOperations
+import space.kscience.kmath.operations.ScaleOperations
+import space.kscience.kmath.structures.DoubleBuffer
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
+
+@OptIn(UnstableKMathAPI::class)
+public class DoubleFieldND(
+    shape: IntArray,
+) : BufferedFieldND<Double, DoubleField>(shape, DoubleField, ::DoubleBuffer),
+    NumbersAddOperations<StructureND<Double>>,
+    ScaleOperations<StructureND<Double>>,
+    ExtendedField<StructureND<Double>> {
+
+    override val zero: BufferND<Double> by lazy { produce { zero } }
+    override val one: BufferND<Double> by lazy { produce { one } }
+
+    override fun number(value: Number): BufferND<Double> {
+        val d = value.toDouble() // minimize conversions
+        return produce { d }
+    }
+
+    override val StructureND<Double>.buffer: DoubleBuffer
+        get() = when {
+            !shape.contentEquals(this@DoubleFieldND.shape) -> throw ShapeMismatchException(
+                this@DoubleFieldND.shape,
+                shape
+            )
+            this is BufferND && this.strides == this@DoubleFieldND.strides -> this.buffer as DoubleBuffer
+            else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
+        }
+
+    @Suppress("OVERRIDE_BY_INLINE")
+    override inline fun StructureND<Double>.map(
+        transform: DoubleField.(Double) -> Double,
+    ): BufferND<Double> {
+        val buffer = DoubleBuffer(strides.linearSize) { offset -> DoubleField.transform(buffer.array[offset]) }
+        return BufferND(strides, buffer)
+    }
+
+    @Suppress("OVERRIDE_BY_INLINE")
+    override inline fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
+        val array = DoubleArray(strides.linearSize) { offset ->
+            val index = strides.index(offset)
+            DoubleField.initializer(index)
+        }
+        return BufferND(strides, DoubleBuffer(array))
+    }
+
+    @Suppress("OVERRIDE_BY_INLINE")
+    override inline fun StructureND<Double>.mapIndexed(
+        transform: DoubleField.(index: IntArray, Double) -> Double,
+    ): BufferND<Double> = BufferND(
+        strides,
+        buffer = DoubleBuffer(strides.linearSize) { offset ->
+            DoubleField.transform(
+                strides.index(offset),
+                buffer.array[offset]
+            )
+        })
+
+    @Suppress("OVERRIDE_BY_INLINE")
+    override inline fun combine(
+        a: StructureND<Double>,
+        b: StructureND<Double>,
+        transform: DoubleField.(Double, Double) -> Double,
+    ): BufferND<Double> {
+        val buffer = DoubleBuffer(strides.linearSize) { offset ->
+            DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset])
+        }
+        return BufferND(strides, buffer)
+    }
+
+    override fun scale(a: StructureND<Double>, value: Double): StructureND<Double> = a.map { it * value }
+
+    override fun power(arg: StructureND<Double>, pow: Number): BufferND<Double> = arg.map { power(it, pow) }
+
+    override fun exp(arg: StructureND<Double>): BufferND<Double> = arg.map { exp(it) }
+
+    override fun ln(arg: StructureND<Double>): BufferND<Double> = arg.map { ln(it) }
+
+    override fun sin(arg: StructureND<Double>): BufferND<Double> = arg.map { sin(it) }
+    override fun cos(arg: StructureND<Double>): BufferND<Double> = arg.map { cos(it) }
+    override fun tan(arg: StructureND<Double>): BufferND<Double> = arg.map { tan(it) }
+    override fun asin(arg: StructureND<Double>): BufferND<Double> = arg.map { asin(it) }
+    override fun acos(arg: StructureND<Double>): BufferND<Double> = arg.map { acos(it) }
+    override fun atan(arg: StructureND<Double>): BufferND<Double> = arg.map { atan(it) }
+
+    override fun sinh(arg: StructureND<Double>): BufferND<Double> = arg.map { sinh(it) }
+    override fun cosh(arg: StructureND<Double>): BufferND<Double> = arg.map { cosh(it) }
+    override fun tanh(arg: StructureND<Double>): BufferND<Double> = arg.map { tanh(it) }
+    override fun asinh(arg: StructureND<Double>): BufferND<Double> = arg.map { asinh(it) }
+    override fun acosh(arg: StructureND<Double>): BufferND<Double> = arg.map { acosh(it) }
+    override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
+}
+
+public fun AlgebraND.Companion.real(vararg shape: Int): DoubleFieldND = DoubleFieldND(shape)
+
+/**
+ * Produce a context for n-dimensional operations inside this real field
+ */
+public inline fun <R> DoubleField.nd(vararg shape: Int, action: DoubleFieldND.() -> R): R {
+    contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
+    return DoubleFieldND(shape).run(action)
+}
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
deleted file mode 100644
index 2165aea22..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-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.ScaleOperations
-import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.RealBuffer
-import kotlin.contracts.InvocationKind
-import kotlin.contracts.contract
-
-@OptIn(UnstableKMathAPI::class)
-public class RealNDField(
-    shape: IntArray,
-) : BufferedNDField<Double, RealField>(shape, RealField, Buffer.Companion::real),
-    NumbersAddOperations<NDStructure<Double>>,
-    ScaleOperations<NDStructure<Double>>,
-    ExtendedField<NDStructure<Double>> {
-
-    override val zero: NDBuffer<Double> by lazy { produce { zero } }
-    override val one: NDBuffer<Double> by lazy { produce { one } }
-
-    override fun number(value: Number): NDBuffer<Double> {
-        val d = value.toDouble() // minimize conversions
-        return produce { d }
-    }
-
-    override val NDStructure<Double>.buffer: RealBuffer
-        get() = when {
-            !shape.contentEquals(this@RealNDField.shape) -> throw ShapeMismatchException(
-                this@RealNDField.shape,
-                shape
-            )
-            this is NDBuffer && this.strides == this@RealNDField.strides -> this.buffer as RealBuffer
-            else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
-        }
-
-    @Suppress("OVERRIDE_BY_INLINE")
-    override inline fun NDStructure<Double>.map(
-        transform: RealField.(Double) -> Double,
-    ): NDBuffer<Double> {
-        val buffer = RealBuffer(strides.linearSize) { offset -> RealField.transform(buffer.array[offset]) }
-        return NDBuffer(strides, buffer)
-    }
-
-    @Suppress("OVERRIDE_BY_INLINE")
-    override inline fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer<Double> {
-        val array = DoubleArray(strides.linearSize) { offset ->
-            val index = strides.index(offset)
-            RealField.initializer(index)
-        }
-        return NDBuffer(strides, RealBuffer(array))
-    }
-
-    @Suppress("OVERRIDE_BY_INLINE")
-    override inline fun NDStructure<Double>.mapIndexed(
-        transform: RealField.(index: IntArray, Double) -> Double,
-    ): NDBuffer<Double> = NDBuffer(
-        strides,
-        buffer = RealBuffer(strides.linearSize) { offset ->
-            RealField.transform(
-                strides.index(offset),
-                buffer.array[offset]
-            )
-        })
-
-    @Suppress("OVERRIDE_BY_INLINE")
-    override inline fun combine(
-        a: NDStructure<Double>,
-        b: NDStructure<Double>,
-        transform: RealField.(Double, Double) -> Double,
-    ): NDBuffer<Double> {
-        val buffer = RealBuffer(strides.linearSize) { offset ->
-            RealField.transform(a.buffer.array[offset], b.buffer.array[offset])
-        }
-        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) }
-
-    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) }
-}
-
-public fun NDAlgebra.Companion.real(vararg shape: Int): RealNDField = RealNDField(shape)
-
-/**
- * Produce a context for n-dimensional operations inside this real field
- */
-public inline fun <R> RealField.nd(vararg shape: Int, action: RealNDField.() -> R): R {
-    contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return RealNDField(shape).run(action)
-}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt
similarity index 57%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt
index 2085840a4..f1056d0ff 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt
@@ -9,15 +9,15 @@ import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 
 @OptIn(UnstableKMathAPI::class)
-public class ShortNDRing(
+public class ShortRingND(
     shape: IntArray,
-) : BufferedNDRing<Short, ShortRing>(shape, ShortRing, Buffer.Companion::auto),
-    NumbersAddOperations<NDStructure<Short>> {
+) : BufferedRingND<Short, ShortRing>(shape, ShortRing, Buffer.Companion::auto),
+    NumbersAddOperations<StructureND<Short>> {
 
-    override val zero: NDBuffer<Short> by lazy { produce { zero } }
-    override val one: NDBuffer<Short> by lazy { produce { one } }
+    override val zero: BufferND<Short> by lazy { produce { zero } }
+    override val one: BufferND<Short> by lazy { produce { one } }
 
-    override fun number(value: Number): NDBuffer<Short> {
+    override fun number(value: Number): BufferND<Short> {
         val d = value.toShort() // minimize conversions
         return produce { d }
     }
@@ -26,11 +26,11 @@ public class ShortNDRing(
 /**
  * Fast element production using function inlining.
  */
-public inline fun BufferedNDRing<Short, ShortRing>.produceInline(crossinline initializer: ShortRing.(Int) -> Short): NDBuffer<Short> {
-    return NDBuffer(strides, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) }))
+public inline fun BufferedRingND<Short, ShortRing>.produceInline(crossinline initializer: ShortRing.(Int) -> Short): BufferND<Short> {
+    return BufferND(strides, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) }))
 }
 
-public inline fun <R> ShortRing.nd(vararg shape: Int, action: ShortNDRing.() -> R): R {
+public inline fun <R> ShortRing.nd(vararg shape: Int, action: ShortRingND.() -> R): R {
     contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
-    return ShortNDRing(shape).run(action)
+    return ShortRingND(shape).run(action)
 }
\ No newline at end of file
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 fd965a668..c157f9a2f 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
@@ -8,7 +8,7 @@ import space.kscience.kmath.structures.asSequence
 /**
  * A structure that is guaranteed to be one-dimensional
  */
-public interface Structure1D<T> : NDStructure<T>, Buffer<T> {
+public interface Structure1D<T> : StructureND<T>, Buffer<T> {
     public override val dimension: Int get() = 1
 
     public override operator fun get(index: IntArray): T {
@@ -22,7 +22,7 @@ public interface Structure1D<T> : NDStructure<T>, Buffer<T> {
 /**
  * A mutable structure that is guaranteed to be one-dimensional
  */
-public interface MutableStructure1D<T> : Structure1D<T>, MutableNDStructure<T>, MutableBuffer<T> {
+public interface MutableStructure1D<T> : Structure1D<T>, MutableStructureND<T>, MutableBuffer<T> {
     public override operator fun set(index: IntArray, value: T) {
         require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" }
         set(index[0], value)
@@ -32,7 +32,7 @@ public interface MutableStructure1D<T> : Structure1D<T>, MutableNDStructure<T>,
 /**
  * A 1D wrapper for nd-structure
  */
-private inline class Structure1DWrapper<T>(val structure: NDStructure<T>) : Structure1D<T> {
+private inline class Structure1DWrapper<T>(val structure: StructureND<T>) : Structure1D<T> {
     override val shape: IntArray get() = structure.shape
     override val size: Int get() = structure.shape[0]
 
@@ -43,12 +43,10 @@ private inline class Structure1DWrapper<T>(val structure: NDStructure<T>) : Stru
 /**
  * A 1D wrapper for a mutable nd-structure
  */
-private inline class MutableStructure1DWrapper<T>(val structure: MutableNDStructure<T>) : MutableStructure1D<T> {
+private inline class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure1D<T> {
     override val shape: IntArray get() = structure.shape
     override val size: Int get() = structure.shape[0]
-    override fun elements(): Sequence<Pair<IntArray, T>> {
-        TODO("Not yet implemented")
-    }
+    override fun elements(): Sequence<Pair<IntArray, T>> = structure.elements()
 
     override fun get(index: Int): T = structure[index]
     override fun set(index: Int, value: T) {
@@ -73,37 +71,19 @@ private inline class Buffer1DWrapper<T>(val buffer: Buffer<T>) : Structure1D<T>
     override operator fun get(index: Int): T = buffer[index]
 }
 
-private inline class MutableBuffer1DWrapper<T>(val buffer: MutableBuffer<T>) : MutableStructure1D<T> {
-    override val shape: IntArray get() = intArrayOf(buffer.size)
-    override val size: Int get() = buffer.size
-
-    override fun elements(): Sequence<Pair<IntArray, T>> =
-        buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value }
-
-    override operator fun get(index: Int): T = buffer[index]
-    override fun set(index: Int, value: T) {
-        buffer[index] = value
-    }
-
-    override fun copy(): MutableBuffer<T> = buffer.copy()
-}
-
 /**
- * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch
+ * Represent a [StructureND] as [Structure1D]. Throw error in case of dimension mismatch
  */
-public fun <T> NDStructure<T>.as1D(): Structure1D<T> = this as? Structure1D<T> ?: if (shape.size == 1) {
+public fun <T> StructureND<T>.as1D(): Structure1D<T> = this as? Structure1D<T> ?: if (shape.size == 1) {
     when (this) {
-        is NDBuffer -> Buffer1DWrapper(this.buffer)
+        is BufferND -> Buffer1DWrapper(this.buffer)
         else -> Structure1DWrapper(this)
     }
 } else error("Can't create 1d-structure from ${shape.size}d-structure")
 
-public fun <T> MutableNDStructure<T>.as1D(): MutableStructure1D<T> =
+public fun <T> MutableStructureND<T>.as1D(): MutableStructure1D<T> =
     this as? MutableStructure1D<T> ?: if (shape.size == 1) {
-        when (this) {
-            is MutableNDBuffer -> MutableBuffer1DWrapper(this.buffer)
-            else -> MutableStructure1DWrapper(this)
-        }
+        MutableStructure1DWrapper(this)
     } else error("Can't create 1d-structure from ${shape.size}d-structure")
 
 /**
@@ -111,4 +91,12 @@ public fun <T> MutableNDStructure<T>.as1D(): MutableStructure1D<T> =
  */
 public fun <T> Buffer<T>.asND(): Structure1D<T> = Buffer1DWrapper(this)
 
-public fun <T> MutableBuffer<T>.asND(): MutableStructure1D<T> = MutableBuffer1DWrapper(this)
+/**
+ * Expose inner buffer of this [Structure1D] if possible
+ */
+internal fun <T : Any> Structure1D<T>.unwrap(): Buffer<T> = when {
+    this is Buffer1DWrapper<T> -> buffer
+    this is Structure1DWrapper && structure is BufferND<T> -> structure.buffer
+    else -> this
+}
+
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 2f2fd653e..d49438b2c 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
@@ -10,7 +10,7 @@ import kotlin.reflect.KClass
  *
  * @param T the type of items.
  */
-public interface Structure2D<T> : NDStructure<T> {
+public interface Structure2D<T> : StructureND<T> {
     /**
      * The number of rows in this structure.
      */
@@ -60,7 +60,7 @@ public interface Structure2D<T> : NDStructure<T> {
 /**
  * Represents mutable [Structure2D].
  */
-public interface MutableStructure2D<T> : Structure2D<T>, MutableNDStructure<T> {
+public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
     /**
      * Inserts an item at the specified indices.
      *
@@ -74,7 +74,7 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableNDStructure<T> {
 /**
  * A 2D wrapper for nd-structure
  */
-private class Structure2DWrapper<T>(val structure: NDStructure<T>) : Structure2D<T> {
+private inline class Structure2DWrapper<T>(val structure: StructureND<T>) : Structure2D<T> {
     override val shape: IntArray get() = structure.shape
 
     override val rowNum: Int get() = shape[0]
@@ -86,16 +86,12 @@ private class Structure2DWrapper<T>(val structure: NDStructure<T>) : Structure2D
     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()
 }
 
 /**
  * A 2D wrapper for a mutable nd-structure
  */
-private class MutableStructure2DWrapper<T>(val structure: MutableNDStructure<T>): MutableStructure2D<T>
+private class MutableStructure2DWrapper<T>(val structure: MutableStructureND<T>): MutableStructure2D<T>
 {
     override val shape: IntArray get() = structure.shape
 
@@ -120,19 +116,25 @@ private class MutableStructure2DWrapper<T>(val structure: MutableNDStructure<T>)
 }
 
 /**
- * Represent a [NDStructure] as [Structure2D]. Throw error in case of dimension mismatch
+ * Represent a [StructureND] as [Structure1D]. Throw error in case of dimension mismatch
  */
-public fun <T> NDStructure<T>.as2D(): Structure2D<T> = this as? Structure2D<T> ?: when (shape.size) {
+public fun <T> StructureND<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")
 }
 
-internal fun <T> Structure2D<T>.unwrap(): NDStructure<T> = if (this is Structure2DWrapper) structure else this
-
-public fun <T> MutableNDStructure<T>.as2D(): MutableStructure2D<T> = this as? MutableStructure2D<T> ?: when (shape.size) {
+public fun <T> MutableStructureND<T>.as2D(): MutableStructure2D<T> = this as? MutableStructure2D<T> ?: when (shape.size) {
     2 -> MutableStructure2DWrapper(this)
     else -> error("Can't create 2d-structure from ${shape.size}d-structure")
 }
 
-internal fun <T> MutableStructure2D<T>.unwrap(): MutableNDStructure<T> =
+/**
+ * Expose inner [StructureND] if possible
+ */
+internal fun <T> Structure2D<T>.unwrap(): StructureND<T> =
+    if (this is Structure2DWrapper) structure
+    else this
+
+internal fun <T> MutableStructure2D<T>.unwrap(): MutableStructureND<T> =
     if (this is MutableStructure2DWrapper) structure else this
+
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt
similarity index 55%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt
index 83bf28d14..78eac1809 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt
@@ -3,8 +3,6 @@ package space.kscience.kmath.nd
 import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.BufferFactory
-import space.kscience.kmath.structures.MutableBuffer
-import space.kscience.kmath.structures.asSequence
 import kotlin.jvm.JvmName
 import kotlin.native.concurrent.ThreadLocal
 import kotlin.reflect.KClass
@@ -14,9 +12,11 @@ import kotlin.reflect.KClass
  * of dimensions and items in an array is defined by its shape, which is a sequence of non-negative integers that
  * specify the sizes of each dimension.
  *
+ * StructureND is in general identity-free. [StructureND.contentEquals] should be used in tests to compare contents.
+ *
  * @param T the type of items.
  */
-public interface NDStructure<T> {
+public interface StructureND<T> {
     /**
      * The shape of structure, i.e. non-empty sequence of non-negative integers that specify sizes of dimensions of
      * this structure.
@@ -43,32 +43,47 @@ public interface NDStructure<T> {
      */
     public fun elements(): Sequence<Pair<IntArray, T>>
 
-    //force override equality and hash code
-    public override fun equals(other: Any?): Boolean
-    public override fun hashCode(): Int
-
     /**
-     * Feature is additional property or hint that does not directly affect the structure, but could in some cases help
-     * optimize operations and performance. If the feature is not present, null is defined.
+     * Feature is some additional strucure information which allows to access it special properties or hints.
+     * If the feature is not present, null is returned.
      */
     @UnstableKMathAPI
     public fun <F : Any> getFeature(type: KClass<F>): F? = null
 
     public companion object {
         /**
-         * Indicates whether some [NDStructure] is equal to another one.
+         * Indicates whether some [StructureND] is equal to another one.
          */
-        public fun contentEquals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean {
+        public fun <T : Any> contentEquals(st1: StructureND<T>, st2: StructureND<T>): Boolean {
             if (st1 === st2) return true
 
             // fast comparison of buffers if possible
-            if (st1 is NDBuffer && st2 is NDBuffer && st1.strides == st2.strides)
-                return st1.buffer.contentEquals(st2.buffer)
+            if (st1 is BufferND && st2 is BufferND && st1.strides == st2.strides)
+                return Buffer.contentEquals(st1.buffer, st2.buffer)
 
             //element by element comparison if it could not be avoided
             return st1.elements().all { (index, value) -> value == st2[index] }
         }
 
+        /**
+         * Debug output to string
+         */
+        public fun toString(structure: StructureND<*>): String {
+            val bufferRepr: String = when (structure.shape.size) {
+                1 -> (0 until structure.shape[0]).map { structure[it] }
+                    .joinToString(prefix = "[", postfix = "]", separator = ", ")
+                2 -> (0 until structure.shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i ->
+                    (0 until structure.shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j ->
+                        structure[i, j].toString()
+                    }
+                }
+                else -> "..."
+            }
+            val className = structure::class.simpleName ?: "StructureND"
+
+            return "$className(shape=${structure.shape.contentToString()}, buffer=$bufferRepr)"
+        }
+
         /**
          * Creates a NDStructure with explicit buffer factory.
          *
@@ -78,7 +93,7 @@ public interface NDStructure<T> {
             strides: Strides,
             bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
             initializer: (IntArray) -> T,
-        ): NDBuffer<T> = NDBuffer(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) })
+        ): BufferND<T> = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) })
 
         /**
          * Inline create NDStructure with non-boxing buffer implementation if it is possible
@@ -86,37 +101,37 @@ public interface NDStructure<T> {
         public inline fun <reified T : Any> auto(
             strides: Strides,
             crossinline initializer: (IntArray) -> T,
-        ): NDBuffer<T> = NDBuffer(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) })
+        ): BufferND<T> = BufferND(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) })
 
         public inline fun <T : Any> auto(
             type: KClass<T>,
             strides: Strides,
             crossinline initializer: (IntArray) -> T,
-        ): NDBuffer<T> = NDBuffer(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
+        ): BufferND<T> = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
 
         public fun <T> buffered(
             shape: IntArray,
             bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
             initializer: (IntArray) -> T,
-        ): NDBuffer<T> = buffered(DefaultStrides(shape), bufferFactory, initializer)
+        ): BufferND<T> = buffered(DefaultStrides(shape), bufferFactory, initializer)
 
         public inline fun <reified T : Any> auto(
             shape: IntArray,
             crossinline initializer: (IntArray) -> T,
-        ): NDBuffer<T> = auto(DefaultStrides(shape), initializer)
+        ): BufferND<T> = auto(DefaultStrides(shape), initializer)
 
         @JvmName("autoVarArg")
         public inline fun <reified T : Any> auto(
             vararg shape: Int,
             crossinline initializer: (IntArray) -> T,
-        ): NDBuffer<T> =
+        ): BufferND<T> =
             auto(DefaultStrides(shape), initializer)
 
         public inline fun <T : Any> auto(
             type: KClass<T>,
             vararg shape: Int,
             crossinline initializer: (IntArray) -> T,
-        ): NDBuffer<T> = auto(type, DefaultStrides(shape), initializer)
+        ): BufferND<T> = auto(type, DefaultStrides(shape), initializer)
     }
 }
 
@@ -126,15 +141,15 @@ public interface NDStructure<T> {
  * @param index the indices.
  * @return the value.
  */
-public operator fun <T> NDStructure<T>.get(vararg index: Int): T = get(index)
+public operator fun <T> StructureND<T>.get(vararg index: Int): T = get(index)
 
 @UnstableKMathAPI
-public inline fun <reified T : Any> NDStructure<*>.getFeature(): T? = getFeature(T::class)
+public inline fun <reified T : Any> StructureND<*>.getFeature(): T? = getFeature(T::class)
 
 /**
- * Represents mutable [NDStructure].
+ * Represents mutable [StructureND].
  */
-public interface MutableNDStructure<T> : NDStructure<T> {
+public interface MutableStructureND<T> : StructureND<T> {
     /**
      * Inserts an item at the specified indices.
      *
@@ -147,7 +162,7 @@ public interface MutableNDStructure<T> : NDStructure<T> {
 /**
  * Transform a structure element-by element in place.
  */
-public inline fun <T> MutableNDStructure<T>.mapInPlace(action: (IntArray, T) -> T): Unit =
+public inline fun <T> MutableStructureND<T>.mapInPlace(action: (IntArray, T) -> T): Unit =
     elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) }
 
 /**
@@ -162,7 +177,7 @@ public interface Strides {
     /**
      * Array strides
      */
-    public val strides: IntArray
+    public val strides: List<Int>
 
     /**
      * Get linear index from multidimensional index
@@ -174,11 +189,6 @@ public interface Strides {
      */
     public fun index(offset: Int): IntArray
 
-    /**
-     * Get next multidimensional index from the current multidimensional index
-     */
-    public fun nextIndex(index: IntArray): IntArray
-
     /**
      * The size of linear buffer to accommodate all elements of ND-structure corresponding to strides
      */
@@ -194,11 +204,6 @@ public interface Strides {
     }
 }
 
-internal inline fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = index.mapIndexed { i, value ->
-    if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})")
-    value * strides[i]
-}.sum()
-
 /**
  * Simple implementation of [Strides].
  */
@@ -209,7 +214,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) :
     /**
      * Strides for memory access
      */
-    override val strides: IntArray by lazy {
+    override val strides: List<Int> by lazy {
         sequence {
             var current = 1
             yield(1)
@@ -218,10 +223,13 @@ public class DefaultStrides private constructor(override val shape: IntArray) :
                 current *= it
                 yield(current)
             }
-        }.toList().toIntArray()
+        }.toList()
     }
 
-    override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides)
+    override fun offset(index: IntArray): Int = index.mapIndexed { i, value ->
+        if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})")
+        value * strides[i]
+    }.sum()
 
     override fun index(offset: Int): IntArray {
         val res = IntArray(shape.size)
@@ -237,10 +245,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) :
         return res
     }
 
-    override fun nextIndex(index: IntArray): IntArray {
-        TODO("Not yet implemented")
-    }
-
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is DefaultStrides) return false
@@ -262,97 +266,10 @@ public class DefaultStrides private constructor(override val shape: IntArray) :
     }
 }
 
-/**
- * Represents [NDStructure] over [Buffer].
- *
- * @param T the type of items.
- * @param strides The strides to access elements of [Buffer] by linear indices.
- * @param buffer The underlying buffer.
- */
-public open class NDBuffer<T>(
-    public val strides: Strides,
-    buffer: Buffer<T>,
-) : NDStructure<T> {
-
-    init {
-        if (strides.linearSize != buffer.size) {
-            error("Expected buffer side of ${strides.linearSize}, but found ${buffer.size}")
-        }
-    }
-
-    public open val buffer: Buffer<T> = buffer
-
-    override operator fun get(index: IntArray): T = buffer[strides.offset(index)]
-
-    override val shape: IntArray get() = strides.shape
-
-    override fun elements(): Sequence<Pair<IntArray, T>> = strides.indices().map {
-        it to this[it]
-    }
-
-    override fun equals(other: Any?): Boolean {
-        return NDStructure.contentEquals(this, other as? NDStructure<*> ?: return false)
-    }
-
-    override fun hashCode(): Int {
-        var result = strides.hashCode()
-        result = 31 * result + buffer.hashCode()
-        return result
-    }
-
-    override fun toString(): String {
-        val bufferRepr: String = when (shape.size) {
-            1 -> buffer.asSequence().joinToString(prefix = "[", postfix = "]", separator = ", ")
-            2 -> (0 until shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i ->
-                (0 until shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j ->
-                    val offset = strides.offset(intArrayOf(i, j))
-                    buffer[offset].toString()
-                }
-            }
-            else -> "..."
-        }
-        return "NDBuffer(shape=${shape.contentToString()}, buffer=$bufferRepr)"
-    }
-}
-
-/**
- * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [NDBuffer]
- */
-public inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer(
-    factory: BufferFactory<R> = Buffer.Companion::auto,
-    crossinline transform: (T) -> R,
-): NDBuffer<R> {
-    return if (this is NDBuffer<T>)
-        NDBuffer(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) })
-    else {
-        val strides = DefaultStrides(shape)
-        NDBuffer(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) })
-    }
-}
-
-/**
- * Mutable ND buffer based on linear [MutableBuffer].
- */
-public open class MutableNDBuffer<T>(
-    strides: Strides,
-    buffer: MutableBuffer<T>,
-) : NDBuffer<T>(strides, buffer), MutableNDStructure<T> {
-
-    init {
-        require(strides.linearSize == buffer.size) {
-            "Expected buffer side of ${strides.linearSize}, but found ${buffer.size}"
-        }
-    }
-
-    override val buffer: MutableBuffer<T> = super.buffer as MutableBuffer<T>
-
-    override operator fun set(index: IntArray, value: T): Unit = buffer.set(strides.offset(index), value)
-}
-
-public inline fun <reified T : Any> NDStructure<T>.combine(
-    struct: NDStructure<T>,
+public inline fun <reified T : Any> StructureND<T>.combine(
+    struct: StructureND<T>,
     crossinline block: (T, T) -> T,
-): NDStructure<T> {
+): StructureND<T> {
     require(shape.contentEquals(struct.shape)) { "Shape mismatch in structure combination" }
-    return NDStructure.auto(shape) { block(this[it], struct[it]) }
+    return StructureND.auto(shape) { block(this[it], struct[it]) }
 }
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 3e42ac094..b2b5911df 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
@@ -41,7 +41,7 @@ public interface AlgebraElement<T, C : Algebra<T>> {
  */
 @UnstableKMathAPI
 public operator fun <T : AlgebraElement<T, S>, S : NumbersAddOperations<T>> T.minus(b: T): T =
-    context.add(this, context.run { -b})
+    context.add(this, context.run { -b })
 
 /**
  * Adds element to this one.
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 7e6a2eb81..55bb68850 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
@@ -1,8 +1,8 @@
 package space.kscience.kmath.operations
 
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.BufferedNDRing
-import space.kscience.kmath.nd.NDAlgebra
+import space.kscience.kmath.nd.AlgebraND
+import space.kscience.kmath.nd.BufferedRingND
 import space.kscience.kmath.operations.BigInt.Companion.BASE
 import space.kscience.kmath.operations.BigInt.Companion.BASE_SIZE
 import space.kscience.kmath.structures.Buffer
@@ -464,5 +464,5 @@ public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigIn
 public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer<BigInt> =
     boxing(size, initializer)
 
-public fun NDAlgebra.Companion.bigInt(vararg shape: Int): BufferedNDRing<BigInt, BigIntField> =
-    BufferedNDRing(shape, BigIntField, Buffer.Companion::bigInt)
+public fun AlgebraND.Companion.bigInt(vararg shape: Int): BufferedRingND<BigInt, BigIntField> =
+    BufferedRingND(shape, BigIntField, Buffer.Companion::bigInt)
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 52a0dec6f..b927655e3 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
@@ -49,19 +49,19 @@ public fun <T : Comparable<T>> Group<T>.abs(value: T): T = if (value > zero) val
  * Returns the sum of all elements in the iterable in provided space.
  *
  * @receiver the collection to sum up.
- * @param space the algebra that provides addition.
+ * @param group the algebra that provides addition.
  * @return the sum.
  */
-public fun <T> Iterable<T>.sumWith(space: Group<T>): T = space.sum(this)
+public fun <T> Iterable<T>.sumWith(group: Group<T>): T = group.sum(this)
 
 /**
  * Returns the sum of all elements in the sequence in provided space.
  *
  * @receiver the collection to sum up.
- * @param space the algebra that provides addition.
+ * @param group the algebra that provides addition.
  * @return the sum.
  */
-public fun <T> Sequence<T>.sumWith(space: Group<T>): T = space.sum(this)
+public fun <T> Sequence<T>.sumWith(group: Group<T>): T = group.sum(this)
 
 /**
  * Returns an average value of elements in the iterable in this [Group].
@@ -71,7 +71,7 @@ public fun <T> Sequence<T>.sumWith(space: Group<T>): T = space.sum(this)
  * @return the average value.
  * @author Iaroslav Postovalov
  */
-public fun <T, S> Iterable<T>.averageWith(space: S): T  where S : Group<T>, S : ScaleOperations<T>  =
+public fun <T, S> Iterable<T>.averageWith(space: S): T where S : Group<T>, S : ScaleOperations<T> =
     space.average(this)
 
 /**
@@ -82,7 +82,7 @@ public fun <T, S> Iterable<T>.averageWith(space: S): T  where S : Group<T>, S :
  * @return the average value.
  * @author Iaroslav Postovalov
  */
-public fun <T, S> Sequence<T>.averageWith(space: S): T  where S : Group<T>, S : ScaleOperations<T>  =
+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 4841e78d6..0101b058a 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
@@ -55,7 +55,7 @@ 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>, ScaleOperations<Double> {
+public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
     public override val zero: Double = 0.0
     public override val one: Double = 1.0
 
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 c62fa30ba..c85c6c5e3 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
@@ -17,7 +17,9 @@ public typealias BufferFactory<T> = (Int, (Int) -> T) -> Buffer<T>
 public typealias MutableBufferFactory<T> = (Int, (Int) -> T) -> MutableBuffer<T>
 
 /**
- * A generic immutable random-access structure for both primitives and objects.
+ * A generic read-only random-access structure for both primitives and objects.
+ *
+ * [Buffer] is in general identity-free. [Buffer.contentEquals] should be used for content equality checks.
  *
  * @param T the type of elements contained in the buffer.
  */
@@ -37,49 +39,46 @@ public interface Buffer<out T> {
      */
     public operator fun iterator(): Iterator<T>
 
-    /**
-     * Checks content equality with another buffer.
-     */
-    public fun contentEquals(other: Buffer<*>): Boolean =
-        asSequence().mapIndexed { index, value -> value == other[index] }.all { it }
-
     public companion object {
+
         /**
-         * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified
-         * [initializer] function.
+         * Check the element-by-element match of content of two buffers.
          */
-        public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer =
-            RealBuffer(size) { initializer(it) }
+        public fun <T: Any> contentEquals(first: Buffer<T>, second: Buffer<T>): Boolean{
+            if (first.size != second.size) return false
+            for (i in first.indices) {
+                if (first[i] != second[i]) return false
+            }
+            return true
+        }
 
         /**
          * Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the
          * specified [initializer] function.
          */
         public inline fun <T> boxing(size: Int, initializer: (Int) -> T): Buffer<T> =
-            ListBuffer(List(size, initializer))
-
-        // TODO add resolution based on Annotation or companion resolution
+            List(size, initializer).asBuffer()
 
         /**
          * Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([IntBuffer],
-         * [RealBuffer], etc.), [ListBuffer] is returned otherwise.
+         * [DoubleBuffer], etc.), [ListBuffer] is returned otherwise.
          *
          * The [size] is specified, and each element is calculated by calling the specified [initializer] function.
          */
         @Suppress("UNCHECKED_CAST")
         public inline fun <T : Any> auto(type: KClass<T>, size: Int, initializer: (Int) -> T): Buffer<T> =
             when (type) {
-                Double::class -> RealBuffer(size) { initializer(it) as Double } as Buffer<T>
-                Short::class -> ShortBuffer(size) { initializer(it) as Short } as Buffer<T>
-                Int::class -> IntBuffer(size) { initializer(it) as Int } as Buffer<T>
-                Long::class -> LongBuffer(size) { initializer(it) as Long } as Buffer<T>
-                Float::class -> FloatBuffer(size) { initializer(it) as Float } as Buffer<T>
+                Double::class -> MutableBuffer.double(size) { initializer(it) as Double } as Buffer<T>
+                Short::class -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer<T>
+                Int::class -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer<T>
+                Long::class -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer<T>
+                Float::class -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer<T>
                 else -> boxing(size, initializer)
             }
 
         /**
          * Creates a [Buffer] of given type [T]. If the type is primitive, specialized buffers are used ([IntBuffer],
-         * [RealBuffer], etc.), [ListBuffer] is returned otherwise.
+         * [DoubleBuffer], etc.), [ListBuffer] is returned otherwise.
          *
          * The [size] is specified, and each element is calculated by calling the specified [initializer] function.
          */
@@ -89,41 +88,6 @@ public interface Buffer<out T> {
     }
 }
 
-/**
- * Creates a sequence that returns all elements from this [Buffer].
- */
-public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
-
-/**
- * Creates an iterable that returns all elements from this [Buffer].
- */
-public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
-
-/**
- * Returns a new [List] containing all elements of this buffer.
- */
-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].
  */
@@ -146,6 +110,44 @@ public interface MutableBuffer<T> : Buffer<T> {
     public fun copy(): MutableBuffer<T>
 
     public companion object {
+
+        /**
+         * Creates a [DoubleBuffer] with the specified [size], where each element is calculated by calling the specified
+         * [initializer] function.
+         */
+        public inline fun double(size: Int, initializer: (Int) -> Double): DoubleBuffer =
+            DoubleBuffer(size, initializer)
+
+        /**
+         * Creates a [ShortBuffer] with the specified [size], where each element is calculated by calling the specified
+         * [initializer] function.
+         */
+        public inline fun short(size: Int, initializer: (Int) -> Short): ShortBuffer =
+            ShortBuffer(size, initializer)
+
+        /**
+         * Creates a [IntBuffer] with the specified [size], where each element is calculated by calling the specified
+         * [initializer] function.
+         */
+        public inline fun int(size: Int, initializer: (Int) -> Int): IntBuffer =
+            IntBuffer(size, initializer)
+
+        /**
+         * Creates a [LongBuffer] with the specified [size], where each element is calculated by calling the specified
+         * [initializer] function.
+         */
+        public inline fun long(size: Int, initializer: (Int) -> Long): LongBuffer =
+            LongBuffer(size, initializer)
+
+
+        /**
+         * Creates a [FloatBuffer] with the specified [size], where each element is calculated by calling the specified
+         * [initializer] function.
+         */
+        public inline fun float(size: Int, initializer: (Int) -> Float): FloatBuffer =
+            FloatBuffer(size, initializer)
+
+
         /**
          * Create a boxing mutable buffer of given type
          */
@@ -154,37 +156,30 @@ public interface MutableBuffer<T> : Buffer<T> {
 
         /**
          * Creates a [MutableBuffer] of given [type]. If the type is primitive, specialized buffers are used
-         * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise.
+         * ([IntBuffer], [DoubleBuffer], etc.), [ListBuffer] is returned otherwise.
          *
          * The [size] is specified, and each element is calculated by calling the specified [initializer] function.
          */
         @Suppress("UNCHECKED_CAST")
         public inline fun <T : Any> auto(type: KClass<out T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
             when (type) {
-                Double::class -> RealBuffer(size) { initializer(it) as Double } as MutableBuffer<T>
-                Short::class -> ShortBuffer(size) { initializer(it) as Short } as MutableBuffer<T>
-                Int::class -> IntBuffer(size) { initializer(it) as Int } as MutableBuffer<T>
-                Float::class -> FloatBuffer(size) { initializer(it) as Float } as MutableBuffer<T>
-                Long::class -> LongBuffer(size) { initializer(it) as Long } as MutableBuffer<T>
+                Double::class -> double(size) { initializer(it) as Double } as MutableBuffer<T>
+                Short::class -> short(size) { initializer(it) as Short } as MutableBuffer<T>
+                Int::class -> int(size) { initializer(it) as Int } as MutableBuffer<T>
+                Float::class -> float(size) { initializer(it) as Float } as MutableBuffer<T>
+                Long::class -> long(size) { initializer(it) as Long } as MutableBuffer<T>
                 else -> boxing(size, initializer)
             }
 
         /**
          * Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used
-         * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise.
+         * ([IntBuffer], [DoubleBuffer], etc.), [ListBuffer] is returned otherwise.
          *
          * The [size] is specified, and each element is calculated by calling the specified [initializer] function.
          */
         @Suppress("UNCHECKED_CAST")
         public inline fun <reified T : Any> auto(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
             auto(T::class, size, initializer)
-
-        /**
-         * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified
-         * [initializer] function.
-         */
-        public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer =
-            RealBuffer(size) { initializer(it) }
     }
 }
 
@@ -207,15 +202,6 @@ public inline class ListBuffer<T>(public val list: List<T>) : Buffer<T> {
  */
 public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
 
-/**
- * Creates a new [ListBuffer] with the specified [size], where each element is calculated by calling the specified
- * [init] function.
- *
- * The function [init] is called for each array element sequentially starting from the first one.
- * It should return the value for an array element given its index.
- */
-public inline fun <T> ListBuffer(size: Int, init: (Int) -> T): ListBuffer<T> = List(size, init).asBuffer()
-
 /**
  * [MutableBuffer] implementation over [MutableList].
  *
@@ -237,7 +223,11 @@ public inline class MutableListBuffer<T>(public val list: MutableList<T>) : Muta
 }
 
 /**
+<<<<<<< HEAD
  * Returns an [MutableListBuffer] that wraps the original list.
+=======
+ * Returns an [ListBuffer] that wraps the original list.
+>>>>>>> dev
  */
 public fun <T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(this)
 
@@ -249,8 +239,7 @@ public fun <T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableL
  */
 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
+    override val size: Int get() = array.size
 
     override operator fun get(index: Int): T = array[index]
 
@@ -268,16 +257,6 @@ public class ArrayBuffer<T>(internal val array: Array<T>) : MutableBuffer<T> {
  */
 public fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
 
-/**
- * Creates a new [ArrayBuffer] with the specified [size], where each element is calculated by calling the specified
- * [init] function.
- *
- * The function [init] is called for each array element sequentially starting from the first one.
- * It should return the value for an array element given its index.
- */
-public inline fun <reified T> ArrayBuffer(size: Int, init: (Int) -> T): ArrayBuffer<T> =
-    Array(size) { i -> init(i) }.asBuffer()
-
 /**
  * Immutable wrapper for [MutableBuffer].
  *
@@ -305,27 +284,9 @@ public class VirtualBuffer<T>(override val size: Int, private val generator: (In
     }
 
     override operator fun iterator(): Iterator<T> = (0 until size).asSequence().map(generator).iterator()
-
-    override fun contentEquals(other: Buffer<*>): Boolean {
-        return if (other is VirtualBuffer) {
-            this.size == other.size && this.generator == other.generator
-        } else {
-            super.contentEquals(other)
-        }
-    }
 }
 
 /**
  * Convert this buffer to read-only buffer.
  */
-public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
-
-/**
- * Typealias for buffer transformations.
- */
-public typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
-
-/**
- * Typealias for buffer transformations with suspend function.
- */
-public typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>
+public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
\ No newline at end of file
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 0910b2034..6666c88b4 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
@@ -1,8 +1,8 @@
 package space.kscience.kmath.structures
 
 import space.kscience.kmath.nd.DefaultStrides
-import space.kscience.kmath.nd.NDStructure
 import space.kscience.kmath.nd.Structure2D
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.nd.as2D
 
 /**
@@ -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.buffered(
+    public fun MutableBuffer<T>.collect(): Structure2D<T> = StructureND.buffered(
         DefaultStrides(intArrayOf(rowNum, colNum)),
         factory
     ) { (i, j) ->
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt
new file mode 100644
index 000000000..0a23d31fe
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt
@@ -0,0 +1,56 @@
+package space.kscience.kmath.structures
+
+/**
+ * Specialized [MutableBuffer] implementation over [DoubleArray].
+ *
+ * @property array the underlying array.
+ */
+@Suppress("OVERRIDE_BY_INLINE")
+public inline class DoubleBuffer(public val array: DoubleArray) : MutableBuffer<Double> {
+    override val size: Int get() = array.size
+
+    override operator fun get(index: Int): Double = array[index]
+
+    override operator fun set(index: Int, value: Double) {
+        array[index] = value
+    }
+
+    override operator fun iterator(): DoubleIterator = array.iterator()
+
+    override fun copy(): DoubleBuffer = DoubleBuffer(array.copyOf())
+}
+
+/**
+ * Creates a new [DoubleBuffer] with the specified [size], where each element is calculated by calling the specified
+ * [init] function.
+ *
+ * The function [init] is called for each array element sequentially starting from the first one.
+ * It should return the value for an buffer element given its index.
+ */
+public inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer = DoubleBuffer(DoubleArray(size) { init(it) })
+
+/**
+ * Returns a new [DoubleBuffer] of given elements.
+ */
+public fun DoubleBuffer(vararg doubles: Double): DoubleBuffer = DoubleBuffer(doubles)
+
+/**
+ * Simplified [DoubleBuffer] to array comparison
+ */
+public fun DoubleBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles)
+
+/**
+ * Returns a new [DoubleArray] containing all of the elements of this [Buffer].
+ */
+public fun Buffer<Double>.toDoubleArray(): DoubleArray = when (this) {
+    is DoubleBuffer -> array.copyOf()
+    else -> DoubleArray(size, ::get)
+}
+
+/**
+ * Returns [DoubleBuffer] over this array.
+ *
+ * @receiver the array.
+ * @return the new buffer.
+ */
+public fun DoubleArray.asBuffer(): DoubleBuffer = DoubleBuffer(this)
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt
new file mode 100644
index 000000000..4a85219ac
--- /dev/null
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt
@@ -0,0 +1,272 @@
+package space.kscience.kmath.structures
+
+import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.ExtendedFieldOperations
+import kotlin.math.*
+
+/**
+ * [ExtendedFieldOperations] over [DoubleBuffer].
+ */
+public object DoubleBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
+    override fun Buffer<Double>.unaryMinus(): DoubleBuffer = if (this is DoubleBuffer) {
+        DoubleBuffer(size) { -array[it] }
+    } else {
+        DoubleBuffer(size) { -get(it) }
+    }
+
+    public override fun add(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
+        require(b.size == a.size) {
+            "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
+        }
+
+        return if (a is DoubleBuffer && b is DoubleBuffer) {
+            val aArray = a.array
+            val bArray = b.array
+            DoubleBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] })
+        } else DoubleBuffer(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 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>): DoubleBuffer {
+        require(b.size == a.size) {
+            "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
+        }
+
+        return if (a is DoubleBuffer && b is DoubleBuffer) {
+            val aArray = a.array
+            val bArray = b.array
+            DoubleBuffer(DoubleArray(a.size) { aArray[it] * bArray[it] })
+        } else
+            DoubleBuffer(DoubleArray(a.size) { a[it] * b[it] })
+    }
+
+    public override fun divide(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
+        require(b.size == a.size) {
+            "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
+        }
+
+        return if (a is DoubleBuffer && b is DoubleBuffer) {
+            val aArray = a.array
+            val bArray = b.array
+            DoubleBuffer(DoubleArray(a.size) { aArray[it] / bArray[it] })
+        } else DoubleBuffer(DoubleArray(a.size) { a[it] / b[it] })
+    }
+
+    public override fun sin(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { sin(array[it]) })
+    } else DoubleBuffer(DoubleArray(arg.size) { sin(arg[it]) })
+
+    public override fun cos(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { cos(array[it]) })
+    } else DoubleBuffer(DoubleArray(arg.size) { cos(arg[it]) })
+
+    public override fun tan(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { tan(array[it]) })
+    } else DoubleBuffer(DoubleArray(arg.size) { tan(arg[it]) })
+
+    public override fun asin(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { asin(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { asin(arg[it]) })
+
+    public override fun acos(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { acos(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { acos(arg[it]) })
+
+    public override fun atan(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { atan(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { atan(arg[it]) })
+
+    public override fun sinh(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { sinh(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { sinh(arg[it]) })
+
+    public override fun cosh(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { cosh(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { cosh(arg[it]) })
+
+    public override fun tanh(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { tanh(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { tanh(arg[it]) })
+
+    public override fun asinh(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { asinh(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { asinh(arg[it]) })
+
+    public override fun acosh(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { acosh(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { acosh(arg[it]) })
+
+    public override fun atanh(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { atanh(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { atanh(arg[it]) })
+
+    public override fun power(arg: Buffer<Double>, pow: Number): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) })
+
+    public override fun exp(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { exp(array[it]) })
+    } else DoubleBuffer(DoubleArray(arg.size) { exp(arg[it]) })
+
+    public override fun ln(arg: Buffer<Double>): DoubleBuffer = if (arg is DoubleBuffer) {
+        val array = arg.array
+        DoubleBuffer(DoubleArray(arg.size) { ln(array[it]) })
+    } else
+        DoubleBuffer(DoubleArray(arg.size) { ln(arg[it]) })
+}
+
+/**
+ * [ExtendedField] over [DoubleBuffer].
+ *
+ * @property size the size of buffers to operate on.
+ */
+public class DoubleBufferField(public val size: Int) : ExtendedField<Buffer<Double>> {
+    public override val zero: Buffer<Double> by lazy { DoubleBuffer(size) { 0.0 } }
+    public override val one: Buffer<Double> by lazy { DoubleBuffer(size) { 1.0 } }
+
+    override fun number(value: Number): Buffer<Double> = DoubleBuffer(size) { value.toDouble() }
+
+    override fun Buffer<Double>.unaryMinus(): Buffer<Double> = DoubleBufferFieldOperations.run {
+        -this@unaryMinus
+    }
+
+    public override fun add(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
+        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.add(a, b)
+    }
+
+    public override fun scale(a: Buffer<Double>, value: Double): DoubleBuffer {
+        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
+
+        return if (a is DoubleBuffer) {
+            val aArray = a.array
+            DoubleBuffer(DoubleArray(a.size) { aArray[it] * value })
+        } else DoubleBuffer(DoubleArray(a.size) { a[it] * value })
+    }
+
+    public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
+        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.multiply(a, b)
+    }
+
+    public override fun divide(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
+        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.divide(a, b)
+    }
+
+    public override fun sin(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.sin(arg)
+    }
+
+    public override fun cos(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.cos(arg)
+    }
+
+    public override fun tan(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.tan(arg)
+    }
+
+    public override fun asin(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.asin(arg)
+    }
+
+    public override fun acos(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.acos(arg)
+    }
+
+    public override fun atan(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.atan(arg)
+    }
+
+    public override fun sinh(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.sinh(arg)
+    }
+
+    public override fun cosh(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.cosh(arg)
+    }
+
+    public override fun tanh(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.tanh(arg)
+    }
+
+    public override fun asinh(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.asinh(arg)
+    }
+
+    public override fun acosh(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.acosh(arg)
+    }
+
+    public override fun atanh(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.atanh(arg)
+    }
+
+    public override fun power(arg: Buffer<Double>, pow: Number): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.power(arg, pow)
+    }
+
+    public override fun exp(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.exp(arg)
+    }
+
+    public override fun ln(arg: Buffer<Double>): DoubleBuffer {
+        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
+        return DoubleBufferFieldOperations.ln(arg)
+    }
+}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt
index 3326c1491..670a0c175 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt
@@ -48,7 +48,7 @@ public fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, Valu
 /**
  * A real buffer which supports flags for each value like NaN or Missing
  */
-public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer<Double?>,
+public class FlaggedDoubleBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer<Double?>,
     Buffer<Double?> {
     init {
         require(values.size == flags.size) { "Values and flags must have the same dimensions" }
@@ -65,7 +65,7 @@ public class FlaggedRealBuffer(public val values: DoubleArray, public val flags:
     }.iterator()
 }
 
-public inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) {
+public inline fun FlaggedDoubleBuffer.forEachValid(block: (Double) -> Unit) {
     indices
         .asSequence()
         .filter(::isValid)
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 9fc7d55f3..5c4ec3b05 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
@@ -38,7 +38,7 @@ public fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats)
 /**
  * Returns a new [FloatArray] containing all of the elements of this [Buffer].
  */
-public fun Buffer<Float>.toFloatArray(): FloatArray = when(this) {
+public fun Buffer<Float>.toFloatArray(): FloatArray = when (this) {
     is FloatBuffer -> array.copyOf()
     else -> FloatArray(size, ::get)
 }
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 d3d0f79a5..32dfcf9aa 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
@@ -37,7 +37,7 @@ public fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints)
 /**
  * Returns a new [IntArray] containing all of the elements of this [Buffer].
  */
-public fun Buffer<Int>.toIntArray(): IntArray = when(this) {
+public fun Buffer<Int>.toIntArray(): IntArray = when (this) {
     is IntBuffer -> array.copyOf()
     else -> IntArray(size, ::get)
 }
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 fec358421..48b1d7a7b 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
@@ -37,7 +37,7 @@ public fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs)
 /**
  * Returns a new [LongArray] containing all of the elements of this [Buffer].
  */
-public fun Buffer<Long>.toLongArray(): LongArray = when(this) {
+public fun Buffer<Long>.toLongArray(): LongArray = when (this) {
     is LongBuffer -> array.copyOf()
     else -> LongArray(size, ::get)
 }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt
index 418adb537..50a2db590 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt
@@ -24,7 +24,7 @@ public open class MemoryBuffer<T : Any>(protected val memory: Memory, protected
         public inline fun <T : Any> create(
             spec: MemorySpec<T>,
             size: Int,
-            initializer: (Int) -> T
+            initializer: (Int) -> T,
         ): MemoryBuffer<T> = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer ->
             (0 until size).forEach { buffer[it] = initializer(it) }
         }
@@ -53,7 +53,7 @@ public class MutableMemoryBuffer<T : Any>(memory: Memory, spec: MemorySpec<T>) :
         public inline fun <T : Any> create(
             spec: MemorySpec<T>,
             size: Int,
-            initializer: (Int) -> T
+            initializer: (Int) -> T,
         ): MutableMemoryBuffer<T> = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer ->
             (0 until size).forEach { buffer[it] = initializer(it) }
         }
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
deleted file mode 100644
index 01b533138..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package space.kscience.kmath.structures
-
-/**
- * Specialized [MutableBuffer] implementation over [DoubleArray].
- *
- * @property array the underlying array.
- */
-@Suppress("OVERRIDE_BY_INLINE")
-public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer<Double> {
-    override val size: Int get() = array.size
-
-    override operator fun get(index: Int): Double = array[index]
-
-    override operator fun set(index: Int, value: Double) {
-        array[index] = value
-    }
-
-    override operator fun iterator(): DoubleIterator = array.iterator()
-
-    override fun copy(): RealBuffer = RealBuffer(array.copyOf())
-}
-
-/**
- * Creates a new [RealBuffer] with the specified [size], where each element is calculated by calling the specified
- * [init] function.
- *
- * The function [init] is called for each array element sequentially starting from the first one.
- * It should return the value for an buffer element given its index.
- */
-public inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = RealBuffer(DoubleArray(size) { init(it) })
-
-/**
- * Returns a new [RealBuffer] of given elements.
- */
-public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
-
-/**
- * Simplified [RealBuffer] to array comparison
- */
-public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles)
-
-/**
- * Returns a new [DoubleArray] containing all of the elements of this [Buffer].
- */
-public fun Buffer<Double>.toDoubleArray(): DoubleArray = when(this) {
-    is RealBuffer -> array.copyOf()
-    else -> DoubleArray(size, ::get)
-}
-
-/**
- * Returns [RealBuffer] over this array.
- *
- * @receiver the array.
- * @return the new buffer.
- */
-public fun DoubleArray.asBuffer(): RealBuffer = RealBuffer(this)
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
deleted file mode 100644
index 2a03a36e3..000000000
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt
+++ /dev/null
@@ -1,272 +0,0 @@
-package space.kscience.kmath.structures
-
-import space.kscience.kmath.operations.ExtendedField
-import space.kscience.kmath.operations.ExtendedFieldOperations
-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} "
-        }
-
-        return if (a is RealBuffer && b is RealBuffer) {
-            val aArray = a.array
-            val bArray = b.array
-            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 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) {
-            "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
-        }
-
-        return if (a is RealBuffer && b is RealBuffer) {
-            val aArray = a.array
-            val bArray = b.array
-            RealBuffer(DoubleArray(a.size) { aArray[it] * bArray[it] })
-        } else
-            RealBuffer(DoubleArray(a.size) { a[it] * b[it] })
-    }
-
-    public override fun divide(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} "
-        }
-
-        return if (a is RealBuffer && b is RealBuffer) {
-            val aArray = a.array
-            val bArray = b.array
-            RealBuffer(DoubleArray(a.size) { aArray[it] / bArray[it] })
-        } else RealBuffer(DoubleArray(a.size) { a[it] / b[it] })
-    }
-
-    public override fun sin(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { sin(array[it]) })
-    } else RealBuffer(DoubleArray(arg.size) { sin(arg[it]) })
-
-    public override fun cos(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { cos(array[it]) })
-    } else RealBuffer(DoubleArray(arg.size) { cos(arg[it]) })
-
-    public override fun tan(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { tan(array[it]) })
-    } else RealBuffer(DoubleArray(arg.size) { tan(arg[it]) })
-
-    public override fun asin(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { asin(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { asin(arg[it]) })
-
-    public override fun acos(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { acos(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { acos(arg[it]) })
-
-    public override fun atan(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { atan(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { atan(arg[it]) })
-
-    public override fun sinh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { sinh(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) })
-
-    public override fun cosh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { cosh(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) })
-
-    public override fun tanh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { tanh(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) })
-
-    public override fun asinh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { asinh(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) })
-
-    public override fun acosh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { acosh(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) })
-
-    public override fun atanh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { atanh(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) })
-
-    public override fun power(arg: Buffer<Double>, pow: Number): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) })
-
-    public override fun exp(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { exp(array[it]) })
-    } else RealBuffer(DoubleArray(arg.size) { exp(arg[it]) })
-
-    public override fun ln(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
-        val array = arg.array
-        RealBuffer(DoubleArray(arg.size) { ln(array[it]) })
-    } else
-        RealBuffer(DoubleArray(arg.size) { ln(arg[it]) })
-}
-
-/**
- * [ExtendedField] over [RealBuffer].
- *
- * @property size the size of buffers to operate on.
- */
-public class RealBufferField(public val size: Int) : ExtendedField<Buffer<Double>> {
-    public override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
-    public override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
-
-    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 scale(a: Buffer<Double>, value: Double): RealBuffer {
-        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
-
-        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 {
-        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
-        return RealBufferFieldOperations.multiply(a, b)
-    }
-
-    public override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
-        require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
-        return RealBufferFieldOperations.divide(a, b)
-    }
-
-    public override fun sin(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.sin(arg)
-    }
-
-    public override fun cos(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.cos(arg)
-    }
-
-    public override fun tan(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.tan(arg)
-    }
-
-    public override fun asin(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.asin(arg)
-    }
-
-    public override fun acos(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.acos(arg)
-    }
-
-    public override fun atan(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.atan(arg)
-    }
-
-    public override fun sinh(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.sinh(arg)
-    }
-
-    public override fun cosh(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.cosh(arg)
-    }
-
-    public override fun tanh(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.tanh(arg)
-    }
-
-    public override fun asinh(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.asinh(arg)
-    }
-
-    public override fun acosh(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.acosh(arg)
-    }
-
-    public override fun atanh(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.atanh(arg)
-    }
-
-    public override fun power(arg: Buffer<Double>, pow: Number): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.power(arg, pow)
-    }
-
-    public override fun exp(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.exp(arg)
-    }
-
-    public override fun ln(arg: Buffer<Double>): RealBuffer {
-        require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
-        return RealBufferFieldOperations.ln(arg)
-    }
-}
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 77f128403..7832bb863 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
@@ -35,7 +35,7 @@ public fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts)
 /**
  * Returns a new [ShortArray] containing all of the elements of this [Buffer].
  */
-public fun Buffer<Short>.toShortArray(): ShortArray = when(this) {
+public fun Buffer<Short>.toShortArray(): ShortArray = when (this) {
     is ShortBuffer -> array.copyOf()
     else -> ShortArray(size, ::get)
 }
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
index 459136631..4355ba17f 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt
@@ -1,7 +1,84 @@
 package space.kscience.kmath.structures
 
+import space.kscience.kmath.misc.UnstableKMathAPI
 
+/**
+ * Typealias for buffer transformations.
+ */
+public typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
+
+/**
+ * Typealias for buffer transformations with suspend function.
+ */
+public typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>
+
+
+/**
+ * Creates a sequence that returns all elements from this [Buffer].
+ */
+public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
+
+/**
+ * Creates an iterable that returns all elements from this [Buffer].
+ */
+public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
+
+/**
+ * Returns a new [List] containing all elements of this buffer.
+ */
+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.
+ * **NOTE:** this method uses a protective copy, so it should not be used in performance-critical code.
+ */
+@UnstableKMathAPI
+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 -> MutableList(size, ::get)
+}
+
+/**
+ * Returns a new [Array] containing all elements of this buffer.
+ * **NOTE:** this method uses a protective copy, so it should not be used in performance-critical code.
+ */
+@UnstableKMathAPI
+public inline fun <reified T> Buffer<T>.toTypedArray(): Array<T> = Array(size, ::get)
+
+/**
+ * Create a new buffer from this one with the given mapping function.
+ * Provided [BufferFactory] is used to construct the new buffer.
+ */
 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
+): Buffer<R> = bufferFactory(size) { block(get(it)) }
+
+/**
+ * Create a new buffer from this one with the given indexed mapping function.
+ * Provided [BufferFactory] is used to construct the new buffer.
+ */
+public inline fun <T : Any, reified R : Any> Buffer<T>.mapIndexed(
+    bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
+    crossinline block: (index: Int, value: T) -> R,
+): Buffer<R> = bufferFactory(size) { block(it, get(it)) }
+
+/**
+ * Zip two buffers using given [transform].
+ */
+@UnstableKMathAPI
+public inline fun <T1 : Any, T2 : Any, reified R : Any> Buffer<T1>.zip(
+    other: Buffer<T2>,
+    bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
+    crossinline transform: (T1, T2) -> R,
+): Buffer<R> {
+    require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" }
+    return bufferFactory(size) { transform(get(it), other[it]) }
+}
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt
index f5ea39d1b..64c4d98b8 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt
@@ -1,5 +1,5 @@
 package space.kscience.kmath.tensors
 
-import space.kscience.kmath.nd.MutableNDStructure
+import space.kscience.kmath.nd.MutableStructureND
 
-public typealias TensorStructure<T> = MutableNDStructure<T>
+public typealias TensorStructure<T> = MutableStructureND<T>
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt
index 20f64f469..4bfbe5863 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt
@@ -8,7 +8,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
         val broadcast = broadcastTensors(this, other)
         val newThis = broadcast[0]
         val newOther = broadcast[1]
-        val resBuffer = DoubleArray(newThis.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
             newThis.buffer.array()[i] + newOther.buffer.array()[i]
         }
         return DoubleTensor(newThis.shape, resBuffer)
@@ -16,7 +16,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
 
     override fun DoubleTensor.plusAssign(other: DoubleTensor) {
         val newOther = broadcastTo(other, this.shape)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] +=
                 newOther.buffer.array()[this.bufferStart + i]
         }
@@ -26,7 +26,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
         val broadcast = broadcastTensors(this, other)
         val newThis = broadcast[0]
         val newOther = broadcast[1]
-        val resBuffer = DoubleArray(newThis.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
             newThis.buffer.array()[i] - newOther.buffer.array()[i]
         }
         return DoubleTensor(newThis.shape, resBuffer)
@@ -34,7 +34,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
 
     override fun DoubleTensor.minusAssign(other: DoubleTensor) {
         val newOther = broadcastTo(other, this.shape)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] -=
                 newOther.buffer.array()[this.bufferStart + i]
         }
@@ -44,7 +44,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
         val broadcast = broadcastTensors(this, other)
         val newThis = broadcast[0]
         val newOther = broadcast[1]
-        val resBuffer = DoubleArray(newThis.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
             newThis.buffer.array()[newOther.bufferStart + i] *
                     newOther.buffer.array()[newOther.bufferStart + i]
         }
@@ -53,7 +53,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
 
     override fun DoubleTensor.timesAssign(other: DoubleTensor) {
         val newOther = broadcastTo(other, this.shape)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] *=
                 newOther.buffer.array()[this.bufferStart + i]
         }
@@ -63,7 +63,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
         val broadcast = broadcastTensors(this, other)
         val newThis = broadcast[0]
         val newOther = broadcast[1]
-        val resBuffer = DoubleArray(newThis.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
             newThis.buffer.array()[newOther.bufferStart + i] /
                     newOther.buffer.array()[newOther.bufferStart + i]
         }
@@ -72,7 +72,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
 
     override fun DoubleTensor.divAssign(other: DoubleTensor) {
         val newOther = broadcastTo(other, this.shape)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] /=
                 newOther.buffer.array()[this.bufferStart + i]
         }
@@ -130,7 +130,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl
     }
 
     for (linearIndex in 0 until n) {
-        val totalMultiIndex = resTensor.strides.index(linearIndex)
+        val totalMultiIndex = resTensor.linearStructure.index(linearIndex)
         val curMultiIndex = tensor.shape.copyOf()
 
         val offset = totalMultiIndex.size - curMultiIndex.size
@@ -143,7 +143,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl
             }
         }
 
-        val curLinearIndex = tensor.strides.offset(curMultiIndex)
+        val curLinearIndex = tensor.linearStructure.offset(curMultiIndex)
         resTensor.buffer.array()[linearIndex] =
             tensor.buffer.array()[tensor.bufferStart + curLinearIndex]
     }
@@ -159,7 +159,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List<DoubleT
         val resTensor = DoubleTensor(totalShape, DoubleArray(n))
 
         for (linearIndex in 0 until n) {
-            val totalMultiIndex = resTensor.strides.index(linearIndex)
+            val totalMultiIndex = resTensor.linearStructure.index(linearIndex)
             val curMultiIndex = tensor.shape.copyOf()
 
             val offset = totalMultiIndex.size - curMultiIndex.size
@@ -172,7 +172,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List<DoubleT
                 }
             }
 
-            val curLinearIndex = tensor.strides.offset(curMultiIndex)
+            val curLinearIndex = tensor.linearStructure.offset(curMultiIndex)
             resTensor.buffer.array()[linearIndex] =
                 tensor.buffer.array()[tensor.bufferStart + curLinearIndex]
         }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt
index ca9168c91..4f5e1f9f0 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt
@@ -1,9 +1,7 @@
 package space.kscience.kmath.tensors.core
 
-import space.kscience.kmath.linear.Matrix
 import space.kscience.kmath.nd.*
 import space.kscience.kmath.structures.*
-import space.kscience.kmath.tensors.TensorStrides
 import space.kscience.kmath.tensors.TensorStructure
 import kotlin.math.atanh
 
@@ -14,19 +12,19 @@ public open class BufferedTensor<T>(
     internal val bufferStart: Int
 ) : TensorStructure<T>
 {
-    public val strides: TensorStrides
-        get() = TensorStrides(shape)
+    public val linearStructure: TensorLinearStructure
+        get() = TensorLinearStructure(shape)
 
     public val numel: Int
-        get() = strides.linearSize
+        get() = linearStructure.size
 
-    override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)]
+    override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)]
 
     override fun set(index: IntArray, value: T) {
-        buffer[bufferStart + strides.offset(index)] = value
+        buffer[bufferStart + linearStructure.offset(index)] = value
     }
 
-    override fun elements(): Sequence<Pair<IntArray, T>> = strides.indices().map {
+    override fun elements(): Sequence<Pair<IntArray, T>> = linearStructure.indices().map {
         it to this[it]
     }
 
@@ -36,7 +34,7 @@ public open class BufferedTensor<T>(
 
     public fun vectorSequence(): Sequence<MutableStructure1D<T>> = sequence {
         check(shape.size >= 1) {"todo"}
-        val vectorOffset = strides.strides[0]
+        val vectorOffset = linearStructure.strides[0]
         val vectorShape = intArrayOf(shape.last())
         for (offset in 0 until numel step vectorOffset) {
             val vector = BufferedTensor<T>(vectorShape, buffer, offset).as1D()
@@ -46,7 +44,7 @@ public open class BufferedTensor<T>(
 
     public fun matrixSequence(): Sequence<MutableStructure2D<T>> = sequence {
         check(shape.size >= 2) {"todo"}
-        val matrixOffset = strides.strides[1]
+        val matrixOffset = linearStructure.strides[1]
         val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way?
         for (offset in 0 until numel step matrixOffset) {
             val matrix = BufferedTensor<T>(matrixShape, buffer, offset).as2D()
@@ -91,4 +89,4 @@ public class DoubleTensor internal constructor(
     shape: IntArray,
     buffer: DoubleArray,
     offset: Int = 0
-) : BufferedTensor<Double>(shape, RealBuffer(buffer), offset)
\ No newline at end of file
+) : BufferedTensor<Double>(shape, DoubleBuffer(buffer), offset)
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt
index daa8b6d74..57339adfa 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt
@@ -27,7 +27,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
 
     override fun DoubleTensor.fullLike(value: Double): DoubleTensor {
         val shape = this.shape
-        val buffer = DoubleArray(this.strides.linearSize) { value }
+        val buffer = DoubleArray(this.linearStructure.size) { value }
         return DoubleTensor(shape, buffer)
     }
 
@@ -54,7 +54,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
     }
 
     override fun Double.plus(other: DoubleTensor): DoubleTensor {
-        val resBuffer = DoubleArray(other.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(other.linearStructure.size) { i ->
             other.buffer.array()[other.bufferStart + i] + this
         }
         return DoubleTensor(other.shape, resBuffer)
@@ -64,35 +64,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
 
     override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor {
         checkShapesCompatible(this, other)
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[i] + other.buffer.array()[i]
         }
         return DoubleTensor(this.shape, resBuffer)
     }
 
     override fun DoubleTensor.plusAssign(value: Double) {
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] += value
         }
     }
 
     override fun DoubleTensor.plusAssign(other: DoubleTensor) {
         checkShapesCompatible(this, other)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] +=
                 other.buffer.array()[this.bufferStart + i]
         }
     }
 
     override fun Double.minus(other: DoubleTensor): DoubleTensor {
-        val resBuffer = DoubleArray(other.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(other.linearStructure.size) { i ->
             this - other.buffer.array()[other.bufferStart + i]
         }
         return DoubleTensor(other.shape, resBuffer)
     }
 
     override fun DoubleTensor.minus(value: Double): DoubleTensor {
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[this.bufferStart + i] - value
         }
         return DoubleTensor(this.shape, resBuffer)
@@ -100,28 +100,28 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
 
     override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor {
         checkShapesCompatible(this, other)
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[i] - other.buffer.array()[i]
         }
         return DoubleTensor(this.shape, resBuffer)
     }
 
     override fun DoubleTensor.minusAssign(value: Double) {
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] -= value
         }
     }
 
     override fun DoubleTensor.minusAssign(other: DoubleTensor) {
         checkShapesCompatible(this, other)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] -=
                 other.buffer.array()[this.bufferStart + i]
         }
     }
 
     override fun Double.times(other: DoubleTensor): DoubleTensor {
-        val resBuffer = DoubleArray(other.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(other.linearStructure.size) { i ->
             other.buffer.array()[other.bufferStart + i] * this
         }
         return DoubleTensor(other.shape, resBuffer)
@@ -131,7 +131,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
 
     override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor {
         checkShapesCompatible(this, other)
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[other.bufferStart + i] *
                     other.buffer.array()[other.bufferStart + i]
         }
@@ -139,21 +139,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
     }
 
     override fun DoubleTensor.timesAssign(value: Double) {
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] *= value
         }
     }
 
     override fun DoubleTensor.timesAssign(other: DoubleTensor) {
         checkShapesCompatible(this, other)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] *=
                 other.buffer.array()[this.bufferStart + i]
         }
     }
 
     override fun DoubleTensor.div(value: Double): DoubleTensor {
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[this.bufferStart + i] / value
         }
         return DoubleTensor(this.shape, resBuffer)
@@ -161,7 +161,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
 
     override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor {
         checkShapesCompatible(this, other)
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[other.bufferStart + i] /
                     other.buffer.array()[other.bufferStart + i]
         }
@@ -169,21 +169,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
     }
 
     override fun DoubleTensor.divAssign(value: Double) {
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] /= value
         }
     }
 
     override fun DoubleTensor.divAssign(other: DoubleTensor) {
         checkShapesCompatible(this, other)
-        for (i in 0 until this.strides.linearSize) {
+        for (i in 0 until this.linearStructure.size) {
             this.buffer.array()[this.bufferStart + i] /=
                 other.buffer.array()[this.bufferStart + i]
         }
     }
 
     override fun DoubleTensor.unaryMinus(): DoubleTensor {
-        val resBuffer = DoubleArray(this.strides.linearSize) { i ->
+        val resBuffer = DoubleArray(this.linearStructure.size) { i ->
             this.buffer.array()[this.bufferStart + i].unaryMinus()
         }
         return DoubleTensor(this.shape, resBuffer)
@@ -191,7 +191,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
 
     override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor {
         checkTranspose(this.dimension, i, j)
-        val n = this.strides.linearSize
+        val n = this.linearStructure.size
         val resBuffer = DoubleArray(n)
 
         val resShape = this.shape.copyOf()
@@ -200,11 +200,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double, Dou
         val resTensor = DoubleTensor(resShape, resBuffer)
 
         for (offset in 0 until n) {
-            val oldMultiIndex = this.strides.index(offset)
+            val oldMultiIndex = this.linearStructure.index(offset)
             val newMultiIndex = oldMultiIndex.copyOf()
             newMultiIndex[i] = newMultiIndex[j].also { newMultiIndex[j] = newMultiIndex[i] }
 
-            val linearIndex = resTensor.strides.offset(newMultiIndex)
+            val linearIndex = resTensor.linearStructure.offset(newMultiIndex)
             resTensor.buffer.array()[linearIndex] =
                 this.buffer.array()[this.bufferStart + offset]
         }
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt
similarity index 55%
rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt
rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt
index d1d1204b4..97ce29657 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt
@@ -1,10 +1,14 @@
-package space.kscience.kmath.tensors
+package space.kscience.kmath.tensors.core
 
-import space.kscience.kmath.nd.Strides
-import space.kscience.kmath.nd.offsetFromIndex
 import kotlin.math.max
 
 
+internal inline fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int =
+    index.mapIndexed { i, value ->
+        if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})")
+        value * strides[i]
+    }.sum()
+
 internal inline fun stridesFromShape(shape: IntArray): IntArray {
     val nDim = shape.size
     val res = IntArray(nDim)
@@ -35,7 +39,7 @@ internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int):
     return res
 }
 
-internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray {
+internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray {
     val res = index.copyOf()
     var current = nDim - 1
     var carry = 0
@@ -47,26 +51,29 @@ internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntA
             res[current] = 0
         }
         current--
-    } while(carry != 0 && current >= 0)
+    } while (carry != 0 && current >= 0)
 
     return res
 }
 
 
-
-public class TensorStrides(override val shape: IntArray): Strides
+public class TensorLinearStructure(public val shape: IntArray)
 {
-    override val strides: IntArray
+    public val strides: IntArray
         get() = stridesFromShape(shape)
 
-    override fun offset(index: IntArray): Int  = offsetFromIndex(index, shape, strides)
+    public fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides)
 
-    override fun index(offset: Int): IntArray =
+    public fun index(offset: Int): IntArray =
         indexFromOffset(offset, strides, shape.size)
 
-    override fun nextIndex(index: IntArray): IntArray =
-        nextIndex(index, shape, shape.size)
+    public fun stepIndex(index: IntArray): IntArray =
+        stepIndex(index, shape, shape.size)
 
-    override val linearSize: Int
+    public val size: Int
         get() = shape.reduce(Int::times)
+
+    public fun indices(): Sequence<IntArray> = (0 until size).asSequence().map {
+        index(it)
+    }
 }
\ No newline at end of file
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt
index 69c8afde5..591ebb89c 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt
@@ -31,6 +31,6 @@ internal fun Buffer<Float>.array(): FloatArray = when (this) {
  * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer].
  */
 internal fun Buffer<Double>.array(): DoubleArray = when (this) {
-    is RealBuffer -> array
+    is DoubleBuffer -> array
     else -> throw RuntimeException("Failed to cast Buffer to DoubleArray")
 }
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 cf75eba3e..b1be0c392 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
@@ -1,6 +1,6 @@
 package space.kscience.kmath.expressions
 
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import space.kscience.kmath.operations.invoke
 import kotlin.test.Test
 import kotlin.test.assertEquals
@@ -11,7 +11,7 @@ class ExpressionFieldTest {
 
     @Test
     fun testExpression() {
-        val expression = FunctionalExpressionField(RealField).invoke {
+        val expression = FunctionalExpressionField(DoubleField).invoke {
             val x by binding()
             x * x + 2 * x + one
         }
@@ -27,7 +27,7 @@ class ExpressionFieldTest {
             return x * x + 2 * x + one
         }
 
-        val expression = FunctionalExpressionField(RealField).expression()
+        val expression = FunctionalExpressionField(DoubleField).expression()
         assertEquals(expression(x to 1.0), 4.0)
     }
 
@@ -38,7 +38,7 @@ class ExpressionFieldTest {
             x * x + 2 * x + one
         }
 
-        val expression = FunctionalExpressionField(RealField).expressionBuilder()
+        val expression = FunctionalExpressionField(DoubleField).expressionBuilder()
         assertEquals(expression(x to 1.0), 4.0)
     }
 }
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt
index ee7fffa4c..ca7aca905 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt
@@ -1,6 +1,7 @@
 package space.kscience.kmath.expressions
 
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.asBuffer
 import kotlin.math.E
 import kotlin.math.PI
@@ -14,19 +15,19 @@ class SimpleAutoDiffTest {
 
     fun dx(
         xBinding: Pair<Symbol, Double>,
-        body: SimpleAutoDiffField<Double, RealField>.(x: AutoDiffValue<Double>) -> AutoDiffValue<Double>,
-    ): DerivationResult<Double> = RealField.simpleAutoDiff(xBinding) { body(bindSymbol(xBinding.first)) }
+        body: SimpleAutoDiffField<Double, DoubleField>.(x: AutoDiffValue<Double>) -> AutoDiffValue<Double>,
+    ): DerivationResult<Double> = DoubleField.simpleAutoDiff(xBinding) { body(bindSymbol(xBinding.first)) }
 
     fun dxy(
         xBinding: Pair<Symbol, Double>,
         yBinding: Pair<Symbol, Double>,
-        body: SimpleAutoDiffField<Double, RealField>.(x: AutoDiffValue<Double>, y: AutoDiffValue<Double>) -> AutoDiffValue<Double>,
-    ): DerivationResult<Double> = RealField.simpleAutoDiff(xBinding, yBinding) {
+        body: SimpleAutoDiffField<Double, DoubleField>.(x: AutoDiffValue<Double>, y: AutoDiffValue<Double>) -> AutoDiffValue<Double>,
+    ): DerivationResult<Double> = DoubleField.simpleAutoDiff(xBinding, yBinding) {
         body(bindSymbol(xBinding.first), bindSymbol(yBinding.first))
     }
 
-    fun diff(block: SimpleAutoDiffField<Double, RealField>.() -> AutoDiffValue<Double>): SimpleAutoDiffExpression<Double, RealField> {
-        return SimpleAutoDiffExpression(RealField, block)
+    fun diff(block: SimpleAutoDiffField<Double, DoubleField>.() -> AutoDiffValue<Double>): SimpleAutoDiffExpression<Double, DoubleField> {
+        return SimpleAutoDiffExpression(DoubleField, block)
     }
 
     val x by symbol
@@ -35,7 +36,7 @@ class SimpleAutoDiffTest {
 
     @Test
     fun testPlusX2() {
-        val y = RealField.simpleAutoDiff(x to 3.0) {
+        val y = DoubleField.simpleAutoDiff(x to 3.0) {
             // diff w.r.t this x at 3
             val x = bindSymbol(x)
             x + x
@@ -58,7 +59,7 @@ class SimpleAutoDiffTest {
     @Test
     fun testPlus() {
         // two variables
-        val z = RealField.simpleAutoDiff(x to 2.0, y to 3.0) {
+        val z = DoubleField.simpleAutoDiff(x to 2.0, y to 3.0) {
             val x = bindSymbol(x)
             val y = bindSymbol(y)
             x + y
@@ -71,7 +72,7 @@ class SimpleAutoDiffTest {
     @Test
     fun testMinus() {
         // two variables
-        val z = RealField.simpleAutoDiff(x to 7.0, y to 3.0) {
+        val z = DoubleField.simpleAutoDiff(x to 7.0, y to 3.0) {
             val x = bindSymbol(x)
             val y = bindSymbol(y)
 
@@ -276,7 +277,7 @@ class SimpleAutoDiffTest {
     fun testDivGrad() {
         val res = dxy(x to 1.0, y to 2.0) { x, y -> x * x + y * y }
         assertEquals(6.0, res.div())
-        assertTrue(res.grad(x, y).contentEquals(doubleArrayOf(2.0, 4.0).asBuffer()))
+        assertTrue(Buffer.contentEquals(res.grad(x, y), doubleArrayOf(2.0, 4.0).asBuffer()))
     }
 
     private fun assertApprox(a: Double, b: Double) {
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt
similarity index 59%
rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt
rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt
index fb90b5e11..445aadd97 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt
@@ -1,23 +1,29 @@
 package space.kscience.kmath.linear
 
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.StructureND
 import kotlin.test.Test
 import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+fun <T : Any> assertMatrixEquals(expected: StructureND<T>, actual: StructureND<T>) {
+    assertTrue { StructureND.contentEquals(expected, actual) }
+}
 
 @UnstableKMathAPI
-class RealLUSolverTest {
+class DoubleLUSolverTest {
 
     @Test
     fun testInvertOne() {
         val matrix = LinearSpace.real.one(2, 2)
         val inverted = LinearSpace.real.inverseWithLup(matrix)
-        assertEquals(matrix, inverted)
+        assertMatrixEquals(matrix, inverted)
     }
 
     @Test
     fun testDecomposition() {
         LinearSpace.real.run {
-            val matrix = matrix(2,2)(
+            val matrix = matrix(2, 2)(
                 3.0, 1.0,
                 2.0, 3.0
             )
@@ -27,24 +33,24 @@ class RealLUSolverTest {
             //Check determinant
             assertEquals(7.0, lup.determinant)
 
-            assertEquals(lup.p dot matrix, lup.l dot lup.u)
+            assertMatrixEquals(lup.p dot matrix, lup.l dot lup.u)
         }
     }
 
     @Test
     fun testInvert() {
-        val matrix = LinearSpace.real.matrix(2,2)(
+        val matrix = LinearSpace.real.matrix(2, 2)(
             3.0, 1.0,
             1.0, 3.0
         )
 
         val inverted = LinearSpace.real.inverseWithLup(matrix)
 
-        val expected = LinearSpace.real.matrix(2,2)(
+        val expected = LinearSpace.real.matrix(2, 2)(
             0.375, -0.125,
             -0.125, 0.375
         )
 
-        assertEquals(expected, inverted)
+        assertMatrixEquals(expected, inverted)
     }
 }
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 097703f49..fd6fb320b 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,10 +1,11 @@
 package space.kscience.kmath.linear
 
 import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.nd.as2D
 import kotlin.test.Test
 import kotlin.test.assertEquals
+import kotlin.test.assertTrue
 
 @UnstableKMathAPI
 @Suppress("UNUSED_VARIABLE")
@@ -13,7 +14,7 @@ class MatrixTest {
     fun testTranspose() {
         val matrix = LinearSpace.real.one(3, 3)
         val transposed = matrix.transpose()
-        assertEquals(matrix, transposed)
+        assertTrue { StructureND.contentEquals(matrix, transposed) }
     }
 
     @Test
@@ -50,8 +51,8 @@ class MatrixTest {
 
     @Test
     fun test2DDot() {
-        val firstMatrix = NDStructure.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D()
-        val secondMatrix = NDStructure.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D()
+        val firstMatrix = StructureND.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D()
+        val secondMatrix = StructureND.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D()
 
         LinearSpace.real.run {
 //            val firstMatrix = produce(2, 3) { i, j -> (i + j).toDouble() }
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt
similarity index 59%
rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt
rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt
index bba612d12..fde4f4a9e 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt
@@ -4,13 +4,13 @@ import space.kscience.kmath.testutils.FieldVerifier
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
-internal class RealFieldTest {
+internal class DoubleFieldTest {
     @Test
-    fun verify() = FieldVerifier(RealField, 42.0, 66.0, 2.0, 5).verify()
+    fun verify() = FieldVerifier(DoubleField, 42.0, 66.0, 2.0, 5).verify()
 
     @Test
     fun testSqrt() {
-        val sqrt = RealField { sqrt(25 * one) }
+        val sqrt = DoubleField { sqrt(25 * one) }
         assertEquals(5.0, sqrt)
     }
 }
diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt
index 3c84d7b4b..b282ee9f5 100644
--- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt
+++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt
@@ -1,6 +1,6 @@
 package space.kscience.kmath.structures
 
-import space.kscience.kmath.nd.NDAlgebra
+import space.kscience.kmath.nd.AlgebraND
 import space.kscience.kmath.nd.get
 import space.kscience.kmath.nd.real
 import space.kscience.kmath.operations.invoke
@@ -11,12 +11,12 @@ import kotlin.test.assertEquals
 internal class NDFieldTest {
     @Test
     fun verify() {
-        (NDAlgebra.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) }
+        (AlgebraND.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) }
     }
 
     @Test
     fun testStrides() {
-        val ndArray = NDAlgebra.real(10, 10).produce { (it[0] + it[1]).toDouble() }
+        val ndArray = AlgebraND.real(10, 10).produce { (it[0] + it[1]).toDouble() }
         assertEquals(ndArray[5, 5], 10.0)
     }
 }
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 dd7871f9a..fb67f0308 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
@@ -11,7 +11,7 @@ import kotlin.test.assertEquals
 
 @Suppress("UNUSED_VARIABLE")
 class NumberNDFieldTest {
-    val algebra = NDAlgebra.real(3,3)
+    val algebra = AlgebraND.real(3, 3)
     val array1 = algebra.produce { (i, j) -> (i + j).toDouble() }
     val array2 = algebra.produce { (i, j) -> (i - j).toDouble() }
 
@@ -69,15 +69,15 @@ class NumberNDFieldTest {
         val division = array1.combine(array2, Double::div)
     }
 
-    object L2Norm : Norm<NDStructure<out Number>, Double> {
-        override fun norm(arg: NDStructure<out Number>): Double =
+    object L2Norm : Norm<StructureND<out Number>, Double> {
+        override fun norm(arg: StructureND<out Number>): Double =
             kotlin.math.sqrt(arg.elements().sumByDouble { it.second.toDouble() })
     }
 
     @Test
     fun testInternalContext() {
         algebra {
-            (NDAlgebra.real(*array1.shape)) { with(L2Norm) { 1 + norm(array1) + exp(array2) } }
+            (AlgebraND.real(*array1.shape)) { with(L2Norm) { 1 + norm(array1) + exp(array2) } }
         }
     }
 }
diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts
index 4a9ca5244..b68dd2e8d 100644
--- a/kmath-coroutines/build.gradle.kts
+++ b/kmath-coroutines/build.gradle.kts
@@ -18,6 +18,6 @@ kotlin.sourceSets {
     }
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
 }
\ No newline at end of file
diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt
similarity index 82%
rename from kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt
rename to kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt
index ac6b117dc..bc4508994 100644
--- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt
+++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt
@@ -3,7 +3,7 @@ package space.kscience.kmath.chains
 /**
  * Performance optimized chain for real values
  */
-public abstract class BlockingRealChain : Chain<Double> {
+public abstract class BlockingDoubleChain : Chain<Double> {
     public abstract fun nextDouble(): Double
 
     override suspend fun next(): Double = nextDouble()
diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt
index 5375113fe..26d078fcb 100644
--- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt
+++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt
@@ -83,7 +83,7 @@ public class StatefulChain<S, out R>(
     private val state: S,
     private val seed: S.() -> R,
     private val forkState: ((S) -> S),
-    private val gen: suspend S.(R) -> R
+    private val gen: suspend S.(R) -> R,
 ) : Chain<R> {
     private val mutex: Mutex = Mutex()
     private var value: R? = null
@@ -145,7 +145,7 @@ public fun <T, R> Chain<T>.collect(mapper: suspend (Chain<T>) -> R): Chain<R> =
 public fun <T, S, R> Chain<T>.collectWithState(
     state: S,
     stateFork: (S) -> S,
-    mapper: suspend S.(Chain<T>) -> R
+    mapper: suspend S.(Chain<T>) -> R,
 ): Chain<R> = object : Chain<R> {
     override suspend fun next(): R = state.mapper(this@collectWithState)
 
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 81b4327fc..7d4914a01 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
@@ -14,7 +14,7 @@ public fun <T> Flow<T>.cumulativeSum(group: GroupOperations<T>): Flow<T> =
     group { runningReduce { sum, element -> sum + element } }
 
 @ExperimentalCoroutinesApi
-public fun <T, S> Flow<T>.mean(algebra: S): Flow<T> where S : Group<T>, S : ScaleOperations<T> = algebra {
+public fun <T, S> Flow<T>.mean(space: S): Flow<T> where S : Group<T>, S : ScaleOperations<T> = space {
     data class Accumulator(var sum: T, var num: Int)
 
     scan(Accumulator(zero, 0)) { sum, element ->
diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt
index 6578af0e9..7a3a52657 100644
--- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt
+++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt
@@ -27,7 +27,7 @@ public class AsyncFlow<T> internal constructor(internal val deferredFlow: Flow<L
 
 public fun <T, R> Flow<T>.async(
     dispatcher: CoroutineDispatcher = Dispatchers.Default,
-    block: suspend CoroutineScope.(T) -> R
+    block: suspend CoroutineScope.(T) -> R,
 ): AsyncFlow<R> {
     val flow = map { LazyDeferred(dispatcher) { block(it) } }
     return AsyncFlow(flow)
@@ -72,12 +72,12 @@ public suspend fun <T> AsyncFlow<T>.collect(concurrency: Int, collector: FlowCol
 
 public suspend inline fun <T> AsyncFlow<T>.collect(
     concurrency: Int,
-    crossinline action: suspend (value: T) -> Unit
+    crossinline action: suspend (value: T) -> Unit,
 ): Unit = collect(concurrency, object : FlowCollector<T> {
     override suspend fun emit(value: T): Unit = action(value)
 })
 
 public inline fun <T, R> Flow<T>.mapParallel(
     dispatcher: CoroutineDispatcher = Dispatchers.Default,
-    crossinline transform: suspend (T) -> R
+    crossinline transform: suspend (T) -> R,
 ): Flow<R> = flatMapMerge { value -> flow { emit(transform(value)) } }.flowOn(dispatcher)
diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt
index 4df22c2ad..c271f8889 100644
--- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt
+++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt
@@ -2,10 +2,10 @@ package space.kscience.kmath.streaming
 
 import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.flow.*
-import space.kscience.kmath.chains.BlockingRealChain
+import space.kscience.kmath.chains.BlockingDoubleChain
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.BufferFactory
-import space.kscience.kmath.structures.RealBuffer
+import space.kscience.kmath.structures.DoubleBuffer
 import space.kscience.kmath.structures.asBuffer
 
 /**
@@ -45,10 +45,10 @@ public fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>)
 /**
  * Specialized flow chunker for real buffer
  */
-public fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
+public fun Flow<Double>.chunked(bufferSize: Int): Flow<DoubleBuffer> = flow {
     require(bufferSize > 0) { "Resulting chunk size must be more than zero" }
 
-    if (this@chunked is BlockingRealChain) {
+    if (this@chunked is BlockingDoubleChain) {
         // performance optimization for blocking primitive chain
         while (true) emit(nextBlock(bufferSize).asBuffer())
     } else {
@@ -60,13 +60,13 @@ public fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
             counter++
 
             if (counter == bufferSize) {
-                val buffer = RealBuffer(array)
+                val buffer = DoubleBuffer(array)
                 emit(buffer)
                 counter = 0
             }
         }
 
-        if (counter > 0) emit(RealBuffer(counter) { array[it] })
+        if (counter > 0) emit(DoubleBuffer(counter) { array[it] })
     }
 }
 
diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt
index efed41112..f81ad2f0d 100644
--- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt
+++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt
@@ -13,7 +13,7 @@ import space.kscience.kmath.structures.VirtualBuffer
 public class RingBuffer<T>(
     private val buffer: MutableBuffer<T?>,
     private var startIndex: Int = 0,
-    size: Int = 0
+    size: Int = 0,
 ) : Buffer<T> {
     private val mutex: Mutex = Mutex()
 
diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt
deleted file mode 100644
index 51a79f44a..000000000
--- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package space.kscience.kmath.structures
-
-import kotlinx.coroutines.*
-import space.kscience.kmath.coroutines.Math
-import space.kscience.kmath.nd.DefaultStrides
-import space.kscience.kmath.nd.NDStructure
-
-public class LazyNDStructure<T>(
-    public val scope: CoroutineScope,
-    public override val shape: IntArray,
-    public val function: suspend (IntArray) -> T
-) : NDStructure<T> {
-    private val cache: MutableMap<IntArray, Deferred<T>> = hashMapOf()
-
-    public fun deferred(index: IntArray): Deferred<T> = cache.getOrPut(index) {
-        scope.async(context = Dispatchers.Math) { function(index) }
-    }
-
-    public suspend fun await(index: IntArray): T = deferred(index).await()
-    public override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() }
-
-    public override fun elements(): Sequence<Pair<IntArray, T>> {
-        val strides = DefaultStrides(shape)
-        val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } }
-        return res.asSequence()
-    }
-
-    public override fun equals(other: Any?): Boolean {
-        return NDStructure.contentEquals(this, other as? NDStructure<*> ?: return false)
-    }
-
-    public override fun hashCode(): Int {
-        var result = scope.hashCode()
-        result = 31 * result + shape.contentHashCode()
-        result = 31 * result + function.hashCode()
-        result = 31 * result + cache.hashCode()
-        return result
-    }
-}
-
-public fun <T> NDStructure<T>.deferred(index: IntArray): Deferred<T> =
-    if (this is LazyNDStructure<T>) deferred(index) else CompletableDeferred(get(index))
-
-public suspend fun <T> NDStructure<T>.await(index: IntArray): T =
-    if (this is LazyNDStructure<T>) await(index) else get(index)
-
-/**
- * PENDING would benefit from KEEP-176
- */
-public inline fun <T, R> NDStructure<T>.mapAsyncIndexed(
-    scope: CoroutineScope,
-    crossinline function: suspend (T, index: IntArray) -> R
-): LazyNDStructure<R> = LazyNDStructure(scope, shape) { index -> function(get(index), index) }
-
-public inline fun <T, R> NDStructure<T>.mapAsync(
-    scope: CoroutineScope,
-    crossinline function: suspend (T) -> R
-): LazyNDStructure<R> = LazyNDStructure(scope, shape) { index -> function(get(index)) }
diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt
new file mode 100644
index 000000000..6b0938c54
--- /dev/null
+++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt
@@ -0,0 +1,46 @@
+package space.kscience.kmath.structures
+
+import kotlinx.coroutines.*
+import space.kscience.kmath.coroutines.Math
+import space.kscience.kmath.nd.DefaultStrides
+import space.kscience.kmath.nd.StructureND
+
+public class LazyStructureND<T>(
+    public val scope: CoroutineScope,
+    public override val shape: IntArray,
+    public val function: suspend (IntArray) -> T,
+) : StructureND<T> {
+    private val cache: MutableMap<IntArray, Deferred<T>> = HashMap()
+
+    public fun deferred(index: IntArray): Deferred<T> = cache.getOrPut(index) {
+        scope.async(context = Dispatchers.Math) { function(index) }
+    }
+
+    public suspend fun await(index: IntArray): T = deferred(index).await()
+    public override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() }
+
+    public override fun elements(): Sequence<Pair<IntArray, T>> {
+        val strides = DefaultStrides(shape)
+        val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } }
+        return res.asSequence()
+    }
+}
+
+public fun <T> StructureND<T>.deferred(index: IntArray): Deferred<T> =
+    if (this is LazyStructureND<T>) deferred(index) else CompletableDeferred(get(index))
+
+public suspend fun <T> StructureND<T>.await(index: IntArray): T =
+    if (this is LazyStructureND<T>) await(index) else get(index)
+
+/**
+ * PENDING would benefit from KEEP-176
+ */
+public inline fun <T, R> StructureND<T>.mapAsyncIndexed(
+    scope: CoroutineScope,
+    crossinline function: suspend (T, index: IntArray) -> R,
+): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index), index) }
+
+public inline fun <T, R> StructureND<T>.mapAsync(
+    scope: CoroutineScope,
+    crossinline function: suspend (T) -> R,
+): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index)) }
diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts
index 3355eda42..3c73f34e6 100644
--- a/kmath-dimensions/build.gradle.kts
+++ b/kmath-dimensions/build.gradle.kts
@@ -19,6 +19,6 @@ kotlin.sourceSets {
     }
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
 }
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 f7e14b29f..dd85a97cb 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
@@ -1,8 +1,11 @@
 package space.kscience.kmath.dimensions
 
-import space.kscience.kmath.linear.*
+import space.kscience.kmath.linear.LinearSpace
+import space.kscience.kmath.linear.Matrix
+import space.kscience.kmath.linear.Point
+import space.kscience.kmath.linear.transpose
 import space.kscience.kmath.nd.Structure2D
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import space.kscience.kmath.operations.Ring
 
 /**
@@ -95,7 +98,7 @@ public inline class DMatrixContext<T : Any, out A : Ring<T>>(public val context:
      * Produce a matrix with this context and given dimensions
      */
     public inline fun <reified R : Dimension, reified C : Dimension> produce(
-        noinline initializer: A.(i: Int, j: Int) -> T
+        noinline initializer: A.(i: Int, j: Int) -> T,
     ): DMatrix<T, R, C> {
         val rows = Dimension.dim<R>()
         val cols = Dimension.dim<C>()
@@ -139,7 +142,7 @@ public inline class DMatrixContext<T : Any, out A : Ring<T>>(public val context:
         context.run { (this@transpose as Matrix<T>).transpose() }.coerce()
 
     public companion object {
-        public val real: DMatrixContext<Double, RealField> = DMatrixContext(LinearSpace.real)
+        public val real: DMatrixContext<Double, DoubleField> = DMatrixContext(LinearSpace.real)
     }
 }
 
@@ -147,11 +150,12 @@ public inline class DMatrixContext<T : Any, out A : Ring<T>>(public val context:
 /**
  * A square unit matrix
  */
-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 D : Dimension> DMatrixContext<Double, DoubleField>.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, RealField>.zero(): DMatrix<Double, R, C> =
+public inline fun <reified R : Dimension, reified C : Dimension> DMatrixContext<Double, DoubleField>.zero(): DMatrix<Double, R, C> =
     produce { _, _ ->
         0.0
     }
\ No newline at end of file
diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md
new file mode 100644
index 000000000..1081b2b7f
--- /dev/null
+++ b/kmath-ejml/README.md
@@ -0,0 +1,43 @@
+# ejml-simple support (`kmath-ejml`)
+
+This subproject implements the following features:
+
+ - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
+ - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
+ - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix.
+
+
+> #### Artifact:
+>
+> This module artifact: `space.kscience:kmath-ejml:0.3.0-dev-3`.
+>
+> Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ejml/_latestVersion)
+>
+> Bintray development version:    [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ejml/_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
+> }
+> 
+> dependencies {
+>     implementation 'space.kscience:kmath-ejml:0.3.0-dev-3'
+> }
+> ```
+> **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
+> }
+> 
+> dependencies {
+>     implementation("space.kscience:kmath-ejml:0.3.0-dev-3")
+> }
+> ```
diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts
index 07f95b13f..5091139ac 100644
--- a/kmath-ejml/build.gradle.kts
+++ b/kmath-ejml/build.gradle.kts
@@ -1,12 +1,33 @@
+import ru.mipt.npm.gradle.Maturity
+
 plugins {
     id("ru.mipt.npm.gradle.jvm")
 }
 
 dependencies {
-    implementation("org.ejml:ejml-simple:0.39")
-    implementation(project(":kmath-core"))
+    api("org.ejml:ejml-simple:0.40")
+    api(project(":kmath-core"))
 }
 
-readme{
-    maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
-}
\ No newline at end of file
+readme {
+    maturity = Maturity.PROTOTYPE
+    propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
+
+    feature(
+        id = "ejml-vector",
+        description = "The Point implementation using SimpleMatrix.",
+        ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt"
+    )
+
+    feature(
+        id = "ejml-matrix",
+        description = "The Matrix implementation using SimpleMatrix.",
+        ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt"
+    )
+
+    feature(
+        id = "ejml-linear-space",
+        description = "The LinearSpace implementation using SimpleMatrix.",
+        ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt"
+    )
+}
diff --git a/kmath-ejml/docs/README-TEMPLATE.md b/kmath-ejml/docs/README-TEMPLATE.md
new file mode 100644
index 000000000..c53f4a81c
--- /dev/null
+++ b/kmath-ejml/docs/README-TEMPLATE.md
@@ -0,0 +1,7 @@
+# ejml-simple support (`kmath-ejml`)
+
+This subproject implements the following features:
+
+${features}
+
+${artifact}
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
index eecd88681..6fc0a049c 100644
--- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt
+++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt
@@ -1,19 +1,26 @@
 package space.kscience.kmath.ejml
 
+import org.ejml.dense.row.factory.DecompositionFactory_DDRM
 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
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.structures.DoubleBuffer
+import kotlin.reflect.KClass
+import kotlin.reflect.cast
 
 /**
  * Represents context of basic operations operating with [EjmlMatrix].
  *
  * @author Iaroslav Postovalov
+ * @author Alexander Nozik
  */
-public object EjmlLinearSpace : LinearSpace<Double, RealField> {
-
-    override val elementAlgebra: RealField get() = RealField
+public object EjmlLinearSpace : LinearSpace<Double, DoubleField> {
+    /**
+     * The [DoubleField] reference.
+     */
+    public override val elementAlgebra: DoubleField get() = DoubleField
 
     /**
      * Converts this matrix to EJML one.
@@ -34,22 +41,25 @@ public object EjmlLinearSpace : LinearSpace<Double, RealField> {
         })
     }
 
-    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) }
-            }
-        })
+    public override fun buildMatrix(
+        rows: Int,
+        columns: Int,
+        initializer: DoubleField.(i: Int, j: Int) -> Double,
+    ): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also {
+        (0 until rows).forEach { row ->
+            (0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) }
+        }
+    })
 
-    override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point<Double> =
+    public override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point<Double> =
         EjmlVector(SimpleMatrix(size, 1).also {
-            (0 until it.numRows()).forEach { row -> it[row, 0] = RealField.initializer(row) }
+            (0 until it.numRows()).forEach { row -> it[row, 0] = DoubleField.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>.unaryMinus(): Matrix<Double> = this * (-1.0)
 
     public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlMatrix =
         EjmlMatrix(toEjml().origin.mult(other.toEjml().origin))
@@ -63,30 +73,100 @@ public object EjmlLinearSpace : LinearSpace<Double, RealField> {
     public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix =
         toEjml().origin.scale(value).wrapMatrix()
 
-    override fun Point<Double>.unaryMinus(): EjmlVector =
+    public override fun Point<Double>.unaryMinus(): EjmlVector =
         toEjml().origin.negative().wrapVector()
 
-    override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlMatrix =
+    public override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlMatrix =
         (toEjml().origin + other.toEjml().origin).wrapMatrix()
 
-    override fun Point<Double>.plus(other: Point<Double>): EjmlVector =
+    public override fun Point<Double>.plus(other: Point<Double>): EjmlVector =
         (toEjml().origin + other.toEjml().origin).wrapVector()
 
-    override fun Point<Double>.minus(other: Point<Double>): EjmlVector =
+    public override fun Point<Double>.minus(other: Point<Double>): EjmlVector =
         (toEjml().origin - other.toEjml().origin).wrapVector()
 
-    override fun Double.times(m: Matrix<Double>): EjmlMatrix =
+    public override fun Double.times(m: Matrix<Double>): EjmlMatrix =
         m.toEjml().origin.scale(this).wrapMatrix()
 
-    override fun Point<Double>.times(value: Double): EjmlVector =
+    public override fun Point<Double>.times(value: Double): EjmlVector =
         toEjml().origin.scale(value).wrapVector()
 
-    override fun Double.times(v: Point<Double>): EjmlVector =
+    public override fun Double.times(v: Point<Double>): EjmlVector =
         v.toEjml().origin.scale(this).wrapVector()
+
+    @UnstableKMathAPI
+    public override fun <F : Any> getFeature(structure: Matrix<Double>, type: KClass<F>): F? {
+        //Return the feature if it is intrinsic to the structure
+        structure.getFeature(type)?.let { return it }
+
+        val origin = structure.toEjml().origin
+
+        return when (type) {
+            InverseMatrixFeature::class -> object : InverseMatrixFeature<Double> {
+                override val inverse: Matrix<Double> by lazy { EjmlMatrix(origin.invert()) }
+            }
+
+            DeterminantFeature::class -> object : DeterminantFeature<Double> {
+                override val determinant: Double by lazy(origin::determinant)
+            }
+
+            SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
+                private val svd by lazy {
+                    DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false)
+                        .apply { decompose(origin.ddrm.copy()) }
+                }
+
+                override val u: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) }
+                override val s: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) }
+                override val v: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) }
+                override val singularValues: Point<Double> by lazy { DoubleBuffer(svd.singularValues) }
+            }
+
+            QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
+                private val qr by lazy {
+                    DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) }
+                }
+
+                override val q: Matrix<Double> by lazy {
+                    EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature
+                }
+
+                override val r: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature }
+            }
+
+            CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
+                override val l: Matrix<Double> by lazy {
+                    val cholesky =
+                        DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.ddrm.copy()) }
+
+                    EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature
+                }
+            }
+
+            LupDecompositionFeature::class -> object : LupDecompositionFeature<Double> {
+                private val lup by lazy {
+                    DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols())
+                        .apply { decompose(origin.ddrm.copy()) }
+                }
+
+                override val l: Matrix<Double> by lazy {
+                    EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature
+                }
+
+                override val u: Matrix<Double> by lazy {
+                    EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature
+                }
+
+                override val p: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) }
+            }
+
+            else -> null
+        }?.let(type::cast)
+    }
 }
 
 /**
- * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix.
+ * Solves for *x* in the following equation: *x = [a] <sup>-1</sup> &middot; [b]*.
  *
  * @param a the base matrix.
  * @param b n by p matrix.
@@ -97,7 +177,7 @@ public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Matrix<Double>): EjmlMatr
     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.
+ * Solves for *x* in the following equation: *x = [a] <sup>-1</sup> &middot; [b]*.
  *
  * @param a the base matrix.
  * @param b n by p vector.
@@ -107,7 +187,17 @@ public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Matrix<Double>): EjmlMatr
 public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Point<Double>): EjmlVector =
     EjmlVector(a.toEjml().origin.solve(b.toEjml().origin))
 
+/**
+ * Inverts this matrix.
+ *
+ * @author Alexander Nozik
+ */
 @OptIn(UnstableKMathAPI::class)
 public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature<InverseMatrixFeature<Double>>()!!.inverse as EjmlMatrix
 
+/**
+ * Inverts the given matrix.
+ *
+ * @author Alexander Nozik
+ */
 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 a1984fa31..10afd6ec2 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
@@ -1,95 +1,17 @@
 package space.kscience.kmath.ejml
 
-import org.ejml.dense.row.factory.DecompositionFactory_DDRM
 import org.ejml.simple.SimpleMatrix
-import space.kscience.kmath.linear.*
-import space.kscience.kmath.misc.UnstableKMathAPI
-import space.kscience.kmath.nd.NDStructure
-import space.kscience.kmath.structures.RealBuffer
-import kotlin.reflect.KClass
-import kotlin.reflect.cast
+import space.kscience.kmath.linear.Matrix
 
 /**
- * Represents featured matrix over EJML [SimpleMatrix].
+ * The matrix implementation over EJML [SimpleMatrix].
  *
  * @property origin the underlying [SimpleMatrix].
  * @author Iaroslav Postovalov
  */
-public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix<Double> {
+public inline class EjmlMatrix(public val origin: SimpleMatrix) : Matrix<Double> {
     public override val rowNum: Int get() = origin.numRows()
     public override val colNum: Int get() = origin.numCols()
 
-    @UnstableKMathAPI
-    public override fun <T : Any> getFeature(type: KClass<T>): T? = when (type) {
-        InverseMatrixFeature::class -> object : InverseMatrixFeature<Double> {
-            override val inverse: Matrix<Double> by lazy { EjmlMatrix(origin.invert()) }
-        }
-
-        DeterminantFeature::class -> object : DeterminantFeature<Double> {
-            override val determinant: Double by lazy(origin::determinant)
-        }
-
-        SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
-            private val svd by lazy {
-                DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false)
-                    .apply { decompose(origin.ddrm.copy()) }
-            }
-
-            override val u: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) }
-            override val s: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) }
-            override val v: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) }
-            override val singularValues: Point<Double> by lazy { RealBuffer(svd.singularValues) }
-        }
-
-        QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
-            private val qr by lazy {
-                DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) }
-            }
-
-            override val q: Matrix<Double> by lazy {
-                EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature
-            }
-
-            override val r: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature }
-        }
-
-        CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
-            override val l: Matrix<Double> by lazy {
-                val cholesky =
-                    DecompositionFactory_DDRM.chol(rowNum, true).apply { decompose(origin.ddrm.copy()) }
-
-                EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature
-            }
-        }
-
-        LupDecompositionFeature::class -> object : LupDecompositionFeature<Double> {
-            private val lup by lazy {
-                DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()).apply { decompose(origin.ddrm.copy()) }
-            }
-
-            override val l: Matrix<Double> by lazy {
-                EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature
-            }
-
-            override val u: Matrix<Double> by lazy {
-                EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature
-            }
-
-            override val p: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) }
-        }
-
-        else -> null
-    }?.let(type::cast)
-
     public override operator fun get(i: Int, j: Int): Double = origin[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()
-
-
 }
diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt
index efa1f6128..2c8d2edd4 100644
--- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt
+++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt
@@ -2,7 +2,6 @@ package space.kscience.kmath.ejml
 
 import org.ejml.simple.SimpleMatrix
 import space.kscience.kmath.linear.Point
-import space.kscience.kmath.structures.Buffer
 
 /**
  * Represents point over EJML [SimpleMatrix].
@@ -10,7 +9,7 @@ import space.kscience.kmath.structures.Buffer
  * @property origin the underlying [SimpleMatrix].
  * @author Iaroslav Postovalov
  */
-public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point<Double> {
+public inline class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point<Double> {
     public override val size: Int
         get() = origin.numRows()
 
@@ -31,10 +30,5 @@ public class EjmlVector internal constructor(public val origin: SimpleMatrix) :
         override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows()
     }
 
-    public override fun contentEquals(other: Buffer<*>): Boolean {
-        if (other is EjmlVector) return origin.isIdentical(other.origin, 0.0)
-        return super.contentEquals(other)
-    }
-
     public override fun toString(): String = "EjmlVector(origin=$origin)"
 }
diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt
index 7f31d2f93..5fb526f40 100644
--- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt
+++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt
@@ -2,16 +2,18 @@ package space.kscience.kmath.ejml
 
 import org.ejml.dense.row.factory.DecompositionFactory_DDRM
 import org.ejml.simple.SimpleMatrix
-import space.kscience.kmath.linear.DeterminantFeature
-import space.kscience.kmath.linear.LupDecompositionFeature
-import space.kscience.kmath.linear.MatrixFeature
-import space.kscience.kmath.linear.plus
+import space.kscience.kmath.linear.*
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.nd.getFeature
 import kotlin.random.Random
 import kotlin.random.asJavaRandom
 import kotlin.test.*
 
+fun <T : Any> assertMatrixEquals(expected: StructureND<T>, actual: StructureND<T>) {
+    assertTrue { StructureND.contentEquals(expected, actual) }
+}
+
 internal class EjmlMatrixTest {
     private val random = Random(0)
 
@@ -45,16 +47,16 @@ internal class EjmlMatrixTest {
     fun features() {
         val m = randomMatrix
         val w = EjmlMatrix(m)
-        val det = w.getFeature<DeterminantFeature<Double>>() ?: fail()
+        val det: DeterminantFeature<Double> = EjmlLinearSpace.getFeature(w) ?: fail()
         assertEquals(m.determinant(), det.determinant)
-        val lup = w.getFeature<LupDecompositionFeature<Double>>() ?: fail()
+        val lup: LupDecompositionFeature<Double> = EjmlLinearSpace.getFeature(w) ?: fail()
 
         val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols())
             .also { it.decompose(m.ddrm.copy()) }
 
-        assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l)
-        assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u)
-        assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p)
+        assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l)
+        assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u)
+        assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p)
     }
 
     private object SomeFeature : MatrixFeature {}
diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md
index 94b9eb59a..139cd3cef 100644
--- a/kmath-for-real/README.md
+++ b/kmath-for-real/README.md
@@ -1,13 +1,13 @@
 # Real number specialization module (`kmath-for-real`)
 
- - [RealVector](src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points
- - [RealMatrix](src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures
- - [grids](src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators
+ - [DoubleVector](src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points
+ - [DoubleMatrix](src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures
+ - [grids](src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
 
 
 > #### Artifact:
 >
-> This module artifact: `space.kscience:kmath-for-real:0.2.0`.
+> This module artifact: `space.kscience:kmath-for-real:0.3.0-dev-3`.
 >
 > Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-for-real/_latestVersion)
 >
@@ -20,13 +20,10 @@
 >     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-for-real:0.2.0'
+>     implementation 'space.kscience:kmath-for-real:0.3.0-dev-3'
 > }
 > ```
 > **Gradle Kotlin DSL:**
@@ -36,12 +33,9 @@
 >     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-for-real:0.2.0")
+>     implementation("space.kscience:kmath-for-real:0.3.0-dev-3")
 > }
 > ```
diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts
index d095cac04..0dcaf330a 100644
--- a/kmath-for-real/build.gradle.kts
+++ b/kmath-for-real/build.gradle.kts
@@ -18,20 +18,20 @@ readme {
     propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
 
     feature(
-        id = "RealVector",
+        id = "DoubleVector",
         description = "Numpy-like operations for Buffers/Points",
-        ref = "src/commonMain/kotlin/kscience/kmath/real/RealVector.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt"
     )
 
     feature(
-        id = "RealMatrix",
+        id = "DoubleMatrix",
         description = "Numpy-like operations for 2d real structures",
-        ref = "src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt"
     )
 
     feature(
         id = "grids",
         description = "Uniform grid generators",
-        ref = "src/commonMain/kotlin/kscience/kmath/structures/grids.kt"
+        ref = "src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt"
     )
 }
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 76c73ab16..a16d64234 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,9 +2,9 @@ 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.operations.DoubleField
 import space.kscience.kmath.structures.Buffer
-import space.kscience.kmath.structures.RealBuffer
+import space.kscience.kmath.structures.DoubleBuffer
 import space.kscience.kmath.structures.asIterable
 import kotlin.math.pow
 
@@ -22,11 +22,11 @@ import kotlin.math.pow
 
 public typealias RealMatrix = Matrix<Double>
 
-public fun realMatrix(rowNum: Int, colNum: Int, initializer: RealField.(i: Int, j: Int) -> Double): RealMatrix =
+public fun realMatrix(rowNum: Int, colNum: Int, initializer: DoubleField.(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> =
+public fun realMatrix(rowNum: Int, colNum: Int): MatrixBuilder<Double, DoubleField> =
     LinearSpace.real.matrix(rowNum, colNum)
 
 public fun Array<DoubleArray>.toMatrix(): RealMatrix {
@@ -120,19 +120,19 @@ public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix =
 public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix =
     extractColumns(columnIndex..columnIndex)
 
-public fun RealMatrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j ->
+public fun RealMatrix.sumByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
     columns[j].asIterable().sum()
 }
 
-public fun RealMatrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j ->
+public fun RealMatrix.minByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
     columns[j].asIterable().minOrNull() ?: error("Cannot produce min on empty column")
 }
 
-public fun RealMatrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j ->
+public fun RealMatrix.maxByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
     columns[j].asIterable().maxOrNull() ?: error("Cannot produce min on empty column")
 }
 
-public fun RealMatrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j ->
+public fun RealMatrix.averageByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
     columns[j].asIterable().average()
 }
 
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 ee42fe404..433e3c756 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
@@ -1,98 +1,102 @@
 package space.kscience.kmath.real
 
 import space.kscience.kmath.linear.Point
+import space.kscience.kmath.misc.UnstableKMathAPI
 import space.kscience.kmath.operations.Norm
 import space.kscience.kmath.structures.Buffer
+import space.kscience.kmath.structures.MutableBuffer.Companion.double
 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
 
-public typealias RealVector = Point<Double>
+public typealias DoubleVector = Point<Double>
 
 public object VectorL2Norm : Norm<Point<out Number>, Double> {
     override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble))
 }
 
-public operator fun Buffer.Companion.invoke(vararg doubles: Double): RealVector = doubles.asBuffer()
+@Suppress("FunctionName")
+public fun DoubleVector(vararg doubles: Double): DoubleVector = doubles.asBuffer()
 
 /**
  * Fill the vector of given [size] with given [value]
  */
-public fun Buffer.Companion.same(size: Int, value: Number): RealVector = real(size) { value.toDouble() }
+@UnstableKMathAPI
+public fun Buffer.Companion.same(size: Int, value: Number): DoubleVector = double(size) { value.toDouble() }
 
 // Transformation methods
 
-public inline fun RealVector.map(transform: (Double) -> Double): RealVector =
-    Buffer.real(size) { transform(get(it)) }
+public inline fun DoubleVector.map(transform: (Double) -> Double): DoubleVector =
+    double(size) { transform(get(it)) }
 
-public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector =
-    Buffer.real(size) { transform(it, get(it)) }
+public inline fun DoubleVector.mapIndexed(transform: (index: Int, value: Double) -> Double): DoubleVector =
+    double(size) { transform(it, get(it)) }
 
-public operator fun RealVector.plus(other: RealVector): RealVector {
+public operator fun DoubleVector.plus(other: DoubleVector): DoubleVector {
     require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value + other[index] }
 }
 
-public operator fun RealVector.plus(number: Number): RealVector = map { it + number.toDouble() }
+public operator fun DoubleVector.plus(number: Number): DoubleVector = map { it + number.toDouble() }
 
-public operator fun Number.plus(vector: RealVector): RealVector = vector + this
+public operator fun Number.plus(vector: DoubleVector): DoubleVector = vector + this
 
-public operator fun RealVector.unaryMinus(): Buffer<Double> = map { -it }
+public operator fun DoubleVector.unaryMinus(): Buffer<Double> = map { -it }
 
-public operator fun RealVector.minus(other: RealVector): RealVector {
+public operator fun DoubleVector.minus(other: DoubleVector): DoubleVector {
     require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value - other[index] }
 }
 
-public operator fun RealVector.minus(number: Number): RealVector = map { it - number.toDouble() }
+public operator fun DoubleVector.minus(number: Number): DoubleVector = map { it - number.toDouble() }
 
-public operator fun Number.minus(vector: RealVector): RealVector = vector.map { toDouble() - it }
+public operator fun Number.minus(vector: DoubleVector): DoubleVector = vector.map { toDouble() - it }
 
-public operator fun RealVector.times(other: RealVector): RealVector {
+public operator fun DoubleVector.times(other: DoubleVector): DoubleVector {
     require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value * other[index] }
 }
 
-public operator fun RealVector.times(number: Number): RealVector = map { it * number.toDouble() }
+public operator fun DoubleVector.times(number: Number): DoubleVector = map { it * number.toDouble() }
 
-public operator fun Number.times(vector: RealVector): RealVector = vector * this
+public operator fun Number.times(vector: DoubleVector): DoubleVector = vector * this
 
-public operator fun RealVector.div(other: RealVector): RealVector {
+public operator fun DoubleVector.div(other: DoubleVector): DoubleVector {
     require(size == other.size) { "Vector size $size expected but ${other.size} found" }
     return mapIndexed { index, value -> value / other[index] }
 }
 
-public operator fun RealVector.div(number: Number): RealVector = map { it / number.toDouble() }
+public operator fun DoubleVector.div(number: Number): DoubleVector = map { it / number.toDouble() }
 
-public operator fun Number.div(vector: RealVector): RealVector = vector.map { toDouble() / it }
+public operator fun Number.div(vector: DoubleVector): DoubleVector = vector.map { toDouble() / it }
 
 //extended operations
 
-public fun RealVector.pow(p: Double): RealVector = map { it.pow(p) }
+public fun DoubleVector.pow(p: Double): DoubleVector = map { it.pow(p) }
 
-public fun RealVector.pow(p: Int): RealVector = map { it.pow(p) }
+public fun DoubleVector.pow(p: Int): DoubleVector = map { it.pow(p) }
 
-public fun exp(vector: RealVector): RealVector = vector.map { kotlin.math.exp(it) }
+public fun exp(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.exp(it) }
 
-public fun sqrt(vector: RealVector): RealVector = vector.map { kotlin.math.sqrt(it) }
+public fun sqrt(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.sqrt(it) }
 
-public fun RealVector.square(): RealVector = map { it.pow(2) }
+public fun DoubleVector.square(): DoubleVector = map { it.pow(2) }
 
-public fun sin(vector: RealVector): RealVector = vector.map { kotlin.math.sin(it) }
+public fun sin(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.sin(it) }
 
-public fun cos(vector: RealVector): RealVector = vector.map { kotlin.math.cos(it) }
+public fun cos(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.cos(it) }
 
-public fun tan(vector: RealVector): RealVector = vector.map { kotlin.math.tan(it) }
+public fun tan(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.tan(it) }
 
-public fun ln(vector: RealVector): RealVector = vector.map { kotlin.math.ln(it) }
+public fun ln(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.ln(it) }
 
-public fun log10(vector: RealVector): RealVector = vector.map { kotlin.math.log10(it) }
+public fun log10(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.log10(it) }
 
 // reductions methods
 
-public fun RealVector.sum(): Double {
+public fun DoubleVector.sum(): Double {
     var res = 0.0
     for (i in indices) {
         res += get(i)
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 0bc5c111b..d5f093d63 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
@@ -7,6 +7,6 @@ import space.kscience.kmath.linear.Matrix
 /**
  * Optimized dot product for real matrices
  */
-public infix fun Matrix<Double>.dot(other: Matrix<Double>): Matrix<Double> = LinearSpace.real.run{
+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/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt
index 8b4f1cd96..35297a3ac 100644
--- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt
+++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt
@@ -33,7 +33,7 @@ public fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Se
     }
 }
 
-public infix fun ClosedFloatingPointRange<Double>.step(step: Double): RealVector =
+public infix fun ClosedFloatingPointRange<Double>.step(step: Double): DoubleVector =
     toSequenceWithStep(step).toList().asBuffer()
 
 /**
diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt
index 492e40922..95faec4b3 100644
--- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt
+++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt
@@ -1,31 +1,31 @@
 package space.kscience.kmath.real
 
-import space.kscience.kmath.nd.NDBuffer
-import space.kscience.kmath.operations.RealField
-import space.kscience.kmath.structures.RealBuffer
+import space.kscience.kmath.nd.BufferND
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.structures.DoubleBuffer
 
 /**
- * Map one [NDBuffer] using function without indices.
+ * Map one [BufferND] using function without indices.
  */
-public inline fun NDBuffer<Double>.mapInline(crossinline transform: RealField.(Double) -> Double): NDBuffer<Double> {
-    val array = DoubleArray(strides.linearSize) { offset -> RealField.transform(buffer[offset]) }
-    return NDBuffer(strides, RealBuffer(array))
+public inline fun BufferND<Double>.mapInline(crossinline transform: DoubleField.(Double) -> Double): BufferND<Double> {
+    val array = DoubleArray(strides.linearSize) { offset -> DoubleField.transform(buffer[offset]) }
+    return BufferND(strides, DoubleBuffer(array))
 }
 
 /**
  * Element by element application of any operation on elements to the whole array. Just like in numpy.
  */
-public operator fun Function1<Double, Double>.invoke(ndElement: NDBuffer<Double>): NDBuffer<Double> =
-    ndElement.mapInline { this@invoke(it) }
+public operator fun Function1<Double, Double>.invoke(elementND: BufferND<Double>): BufferND<Double> =
+    elementND.mapInline { this@invoke(it) }
 
 /* plus and minus */
 
 /**
- * Summation operation for [NDBuffer] and single element
+ * Summation operation for [BufferND] and single element
  */
-public operator fun NDBuffer<Double>.plus(arg: Double): NDBuffer<Double> = mapInline { it + arg }
+public operator fun BufferND<Double>.plus(arg: Double): BufferND<Double> = mapInline { it + arg }
 
 /**
- * Subtraction operation between [NDBuffer] and single element
+ * Subtraction operation between [BufferND] and single element
  */
-public operator fun NDBuffer<Double>.minus(arg: Double): NDBuffer<Double> = mapInline { it - arg }
\ No newline at end of file
+public operator fun BufferND<Double>.minus(arg: Double): BufferND<Double> = mapInline { it - arg }
\ 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/DoubleMatrixTest.kt
similarity index 85%
rename from kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt
rename to kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt
index 06135598e..1c47d803a 100644
--- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt
+++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt
@@ -3,14 +3,19 @@ package kaceince.kmath.real
 import space.kscience.kmath.linear.LinearSpace
 import space.kscience.kmath.linear.matrix
 import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.real.*
 import space.kscience.kmath.structures.contentEquals
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
 
+fun <T : Any> assertMatrixEquals(expected: StructureND<T>, actual: StructureND<T>) {
+    assertTrue { StructureND.contentEquals(expected, actual) }
+}
+
 @UnstableKMathAPI
-internal class RealMatrixTest {
+internal class DoubleMatrixTest {
     @Test
     fun testSum() {
         val m = realMatrix(10, 10) { i, j -> (i + j).toDouble() }
@@ -43,7 +48,7 @@ internal class RealMatrixTest {
             1.0, 0.0, 0.0,
             0.0, 1.0, 2.0
         )
-        assertEquals(matrix2, matrix1.repeatStackVertical(3))
+        assertMatrixEquals(matrix2, matrix1.repeatStackVertical(3))
     }
 
     @Test
@@ -57,7 +62,7 @@ internal class RealMatrixTest {
             0.75, -0.5, 3.25,
             4.5, 7.0, 2.0
         )
-        assertEquals(matrix2, expectedResult)
+        assertMatrixEquals(matrix2, expectedResult)
     }
 
     @Test
@@ -72,7 +77,7 @@ internal class RealMatrixTest {
             5.0, 10.0, -5.0,
             -10.0, -20.0, 0.0
         )
-        assertEquals(matrix2, expectedResult)
+        assertMatrixEquals(matrix2, expectedResult)
     }
 
     @Test
@@ -89,8 +94,8 @@ internal class RealMatrixTest {
             -1.0, 0.0, 27.0,
             64.0, -216.0, -8.0
         )
-        assertEquals(matrix1.square(), matrix2)
-        assertEquals(matrix1.pow(3), matrix3)
+        assertMatrixEquals(matrix1.square(), matrix2)
+        assertMatrixEquals(matrix1.pow(3), matrix3)
     }
 
     @OptIn(UnstableKMathAPI::class)
@@ -109,7 +114,7 @@ internal class RealMatrixTest {
             -3.0, 0.0, 9.0,
             16.0, -48.0, -5.0
         )
-        assertEquals(result, expectedResult)
+        assertMatrixEquals(result, expectedResult)
     }
 
     @Test
@@ -128,9 +133,9 @@ internal class RealMatrixTest {
             -6.0, 7.0
         )
 
-        assertEquals(matrix1.appendColumn { it[0] }, matrix2)
-        assertEquals(matrix1.extractColumn(1), col1)
-        assertEquals(matrix1.extractColumns(1..2), cols1to2)
+        assertMatrixEquals(matrix1.appendColumn { it[0] }, matrix2)
+        assertMatrixEquals(matrix1.extractColumn(1), col1)
+        assertMatrixEquals(matrix1.extractColumns(1..2), cols1to2)
         //equals should never be called on buffers
         assertTrue {
             matrix1.sumByColumn().contentEquals(3.0, -6.0, 10.0, 4.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/DoubleVectorTest.kt
similarity index 67%
rename from kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt
rename to kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleVectorTest.kt
index 59d55110f..669f88186 100644
--- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt
+++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleVectorTest.kt
@@ -4,30 +4,30 @@ import space.kscience.kmath.linear.LinearSpace
 import space.kscience.kmath.linear.asMatrix
 import space.kscience.kmath.linear.transpose
 import space.kscience.kmath.real.plus
-import space.kscience.kmath.structures.Buffer
+import space.kscience.kmath.structures.DoubleBuffer
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
-internal class RealVectorTest {
+internal class DoubleVectorTest {
     @Test
     fun testSum() {
-        val vector1 = Buffer.real(5) { it.toDouble() }
-        val vector2 =  Buffer.real(5) { 5 - it.toDouble() }
+        val vector1 = DoubleBuffer(5) { it.toDouble() }
+        val vector2 = DoubleBuffer(5) { 5 - it.toDouble() }
         val sum = vector1 + vector2
         assertEquals(5.0, sum[2])
     }
 
     @Test
     fun testVectorToMatrix() {
-        val vector =  Buffer.real(5) { it.toDouble() }
+        val vector = DoubleBuffer(5) { it.toDouble() }
         val matrix = vector.asMatrix()
         assertEquals(4.0, matrix[4, 0])
     }
 
     @Test
     fun testDot() {
-        val vector1 =  Buffer.real(5) { it.toDouble() }
-        val vector2 =  Buffer.real(5) { 5 - it.toDouble() }
+        val vector1 = DoubleBuffer(5) { it.toDouble() }
+        val vector2 = DoubleBuffer(5) { 5 - it.toDouble() }
         val matrix1 = vector1.asMatrix()
         val matrix2 = vector2.asMatrix().transpose()
         val product = LinearSpace.real.run { matrix1 dot matrix2 }
diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt
index c538a2d99..5a644c8f9 100644
--- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt
+++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt
@@ -6,7 +6,7 @@ import kotlin.test.assertEquals
 
 class GridTest {
     @Test
-    fun testStepGrid(){
+    fun testStepGrid() {
         val grid = 0.0..1.0 step 0.2
         assertEquals(6, grid.size)
     }
diff --git a/kmath-functions/README.md b/kmath-functions/README.md
index 0eae4e3c0..d13c4c107 100644
--- a/kmath-functions/README.md
+++ b/kmath-functions/README.md
@@ -2,15 +2,15 @@
 
 Functions and interpolations:
 
- - [piecewise](Piecewise functions.) : src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt
- - [polynomials](Polynomial functions.) : src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt
- - [linear interpolation](Linear XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt
- - [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt
+ - [piecewise](Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt
+ - [polynomials](Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
+ - [linear interpolation](Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt
+ - [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
 
 
 > #### Artifact:
 >
-> This module artifact: `space.kscience:kmath-functions:0.2.0`.
+> This module artifact: `space.kscience:kmath-functions:0.3.0-dev-3`.
 >
 > Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-functions/_latestVersion)
 >
@@ -23,13 +23,10 @@ Functions and interpolations:
 >     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-functions:0.2.0'
+>     implementation 'space.kscience:kmath-functions:0.3.0-dev-3'
 > }
 > ```
 > **Gradle Kotlin DSL:**
@@ -39,12 +36,9 @@ Functions and interpolations:
 >     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-functions:0.2.0")
+>     implementation("space.kscience:kmath-functions:0.3.0-dev-3")
 > }
 > ```
diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts
index fc52c4981..51fc75501 100644
--- a/kmath-functions/build.gradle.kts
+++ b/kmath-functions/build.gradle.kts
@@ -13,8 +13,12 @@ readme {
     maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
     propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
 
-    feature("piecewise", "src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt", "Piecewise functions.")
-    feature("polynomials", "src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt", "Polynomial functions.")
-    feature("linear interpolation", "src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt", "Linear XY interpolator.")
-    feature("spline interpolation", "src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt", "Cubic spline XY interpolator.")
+    feature("piecewise", "src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt", "Piecewise functions.")
+    feature("polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt", "Polynomial functions.")
+    feature("linear interpolation",
+        "src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt",
+        "Linear XY interpolator.")
+    feature("spline interpolation",
+        "src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt",
+        "Cubic spline XY interpolator.")
 }
\ No newline at end of file
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt
new file mode 100644
index 000000000..336a3ef3a
--- /dev/null
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt
@@ -0,0 +1,23 @@
+package space.kscience.kmath.integration
+
+import kotlin.reflect.KClass
+
+public interface IntegrandFeature
+
+public interface Integrand {
+    public fun <T : IntegrandFeature> getFeature(type: KClass<T>): T?
+}
+
+public inline fun <reified T : IntegrandFeature> Integrand.getFeature(): T? = getFeature(T::class)
+
+public class IntegrandValue<T : Any>(public val value: T) : IntegrandFeature
+
+public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature
+
+public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature
+
+public class IntegrandCalls(public val calls: Int) : IntegrandFeature
+
+public val Integrand.calls: Int get() = getFeature<IntegrandCalls>()?.calls ?: 0
+
+public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt
new file mode 100644
index 000000000..ebc53ad2e
--- /dev/null
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt
@@ -0,0 +1,11 @@
+package space.kscience.kmath.integration
+
+/**
+ * A general interface for all integrators
+ */
+public interface Integrator<I : Integrand> {
+    /**
+     * Run one integration pass and return a new [Integrand] with a new set of features
+     */
+    public fun integrate(integrand: I): I
+}
\ No newline at end of file
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt
new file mode 100644
index 000000000..4b3a6deb4
--- /dev/null
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt
@@ -0,0 +1,27 @@
+package space.kscience.kmath.integration
+
+import space.kscience.kmath.linear.Point
+import kotlin.reflect.KClass
+
+public class MultivariateIntegrand<T : Any> internal constructor(
+    private val features: Map<KClass<*>, IntegrandFeature>,
+    public val function: (Point<T>) -> T,
+) : Integrand {
+
+    @Suppress("UNCHECKED_CAST")
+    override fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? = features[type] as? T
+
+    public operator fun <F : IntegrandFeature> plus(pair: Pair<KClass<out F>, F>): MultivariateIntegrand<T> =
+        MultivariateIntegrand(features + pair, function)
+
+    public operator fun <F : IntegrandFeature> plus(feature: F): MultivariateIntegrand<T> =
+        plus(feature::class to feature)
+}
+
+@Suppress("FunctionName")
+public fun <T : Any> MultivariateIntegrand(
+    vararg features: IntegrandFeature,
+    function: (Point<T>) -> T,
+): MultivariateIntegrand<T> = MultivariateIntegrand(features.associateBy { it::class }, function)
+
+public val <T : Any> MultivariateIntegrand<T>.value: T? get() = getFeature<IntegrandValue<T>>()?.value
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt
new file mode 100644
index 000000000..9389318e8
--- /dev/null
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt
@@ -0,0 +1,64 @@
+package space.kscience.kmath.integration
+
+import space.kscience.kmath.misc.UnstableKMathAPI
+import kotlin.reflect.KClass
+
+public class UnivariateIntegrand<T : Any> internal constructor(
+    private val features: Map<KClass<*>, IntegrandFeature>,
+    public val function: (T) -> T,
+) : Integrand {
+
+    @Suppress("UNCHECKED_CAST")
+    override fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? = features[type] as? T
+
+    public operator fun <F : IntegrandFeature> plus(pair: Pair<KClass<out F>, F>): UnivariateIntegrand<T> =
+        UnivariateIntegrand(features + pair, function)
+
+    public operator fun <F : IntegrandFeature> plus(feature: F): UnivariateIntegrand<T> =
+        plus(feature::class to feature)
+}
+
+@Suppress("FunctionName")
+public fun <T : Any> UnivariateIntegrand(
+    function: (T) -> T,
+    vararg features: IntegrandFeature,
+): UnivariateIntegrand<T> = UnivariateIntegrand(features.associateBy { it::class }, function)
+
+public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
+
+public inline class IntegrationRange<T : Comparable<T>>(public val range: ClosedRange<T>) : IntegrandFeature
+
+public val <T : Any> UnivariateIntegrand<T>.value: T? get() = getFeature<IntegrandValue<T>>()?.value
+
+/**
+ * A shortcut method to integrate a [function] in [range] with additional [features].
+ * The [function] is placed in the end position to allow passing a lambda.
+ */
+@UnstableKMathAPI
+public fun UnivariateIntegrator<Double>.integrate(
+    range: ClosedRange<Double>,
+    vararg features: IntegrandFeature,
+    function: (Double) -> Double,
+): Double = integrate(
+    UnivariateIntegrand(function, IntegrationRange(range), *features)
+).value ?: error("Unexpected: no value after integration.")
+
+/**
+ * A shortcut method to integrate a [function] in [range] with additional [features].
+ * The [function] is placed in the end position to allow passing a lambda.
+ */
+@UnstableKMathAPI
+public fun UnivariateIntegrator<Double>.integrate(
+    range: ClosedRange<Double>,
+    function: (Double) -> Double,
+    featureBuilder: (MutableList<IntegrandFeature>.() -> Unit) = {},
+): Double {
+    //TODO use dedicated feature builder class instead or add extensions to MutableList<IntegrandFeature>
+    val features = buildList {
+        featureBuilder()
+        add(IntegrationRange(range))
+    }
+    return integrate(
+        UnivariateIntegrand(function, *features.toTypedArray())
+    ).value ?: error("Unexpected: no value after integration.")
+}
\ No newline at end of file
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt
index dc5227f8b..fa978a9bc 100644
--- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt
@@ -24,21 +24,21 @@ public interface PolynomialInterpolator<T : Comparable<T>> : Interpolator<T, T>
 
 public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
     x: Buffer<T>,
-    y: Buffer<T>
+    y: Buffer<T>,
 ): PiecewisePolynomial<T> {
     val pointSet = BufferXYPointSet(x, y)
     return interpolatePolynomials(pointSet)
 }
 
 public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
-    data: Map<T, T>
+    data: Map<T, T>,
 ): PiecewisePolynomial<T> {
     val pointSet = BufferXYPointSet(data.keys.toList().asBuffer(), data.values.toList().asBuffer())
     return interpolatePolynomials(pointSet)
 }
 
 public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
-    data: List<Pair<T, T>>
+    data: List<Pair<T, T>>,
 ): PiecewisePolynomial<T> {
     val pointSet = BufferXYPointSet(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer())
     return interpolatePolynomials(pointSet)
diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt
index c3bcad846..1ff7b6351 100644
--- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt
+++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt
@@ -32,7 +32,7 @@ public class NDStructureColumn<T>(public val structure: Structure2D<T>, public v
 
 public class BufferXYPointSet<X, Y>(
     public override val x: Buffer<X>,
-    public override val y: Buffer<Y>
+    public override val y: Buffer<Y>,
 ) : XYPointSet<X, Y> {
     public override val size: Int
         get() = x.size
diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt
index 0b7b62147..476c035e9 100644
--- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt
+++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt
@@ -2,7 +2,7 @@ package space.kscience.kmath.interpolation
 
 import space.kscience.kmath.functions.PiecewisePolynomial
 import space.kscience.kmath.functions.asFunction
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -16,8 +16,8 @@ internal class LinearInterpolatorTest {
             3.0 to 4.0
         )
 
-        val polynomial: PiecewisePolynomial<Double> = LinearInterpolator(RealField).interpolatePolynomials(data)
-        val function = polynomial.asFunction(RealField)
+        val polynomial: PiecewisePolynomial<Double> = LinearInterpolator(DoubleField).interpolatePolynomials(data)
+        val function = polynomial.asFunction(DoubleField)
         assertEquals(null, function(-1.0))
         assertEquals(0.5, function(0.5))
         assertEquals(2.0, function(1.5))
diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts
index e99eee38b..9d1b2d4d6 100644
--- a/kmath-geometry/build.gradle.kts
+++ b/kmath-geometry/build.gradle.kts
@@ -6,6 +6,6 @@ kotlin.sourceSets.commonMain {
     }
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
 }
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 d5f3965d9..764ff116c 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.DoubleField
 import space.kscience.kmath.operations.Group
-import space.kscience.kmath.operations.RealField
 
 /**
  * Common representation for atomic counters
@@ -11,8 +11,9 @@ import space.kscience.kmath.operations.RealField
 public interface Counter<T : Any> {
     public fun add(delta: T)
     public val value: T
-    public companion object{
-        public fun real(): ObjectCounter<Double> = ObjectCounter(RealField)
+
+    public companion object {
+        public fun real(): ObjectCounter<Double> = ObjectCounter(DoubleField)
     }
 }
 
@@ -36,11 +37,11 @@ public class LongCounter : Counter<Long> {
     override val value: Long get() = innerValue.value
 }
 
-public class ObjectCounter<T : Any>(public val space: Group<T>) : Counter<T> {
-    private val innerValue = atomic(space.zero)
+public class ObjectCounter<T : Any>(public val group: Group<T>) : Counter<T> {
+    private val innerValue = atomic(group.zero)
 
     override fun add(delta: T) {
-        innerValue.getAndUpdate { space.run { it + delta } }
+        innerValue.getAndUpdate { group.run { it + delta } }
     }
 
     override val value: T get() = innerValue.value
diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt
similarity index 88%
rename from kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt
rename to kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt
index 3df0b1626..384ce6159 100644
--- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt
+++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt
@@ -7,7 +7,7 @@ import space.kscience.kmath.nd.*
 import space.kscience.kmath.structures.*
 import kotlin.math.floor
 
-public class RealHistogramSpace(
+public class DoubleHistogramSpace(
     private val lower: Buffer<Double>,
     private val upper: Buffer<Double>,
     private val binNums: IntArray = IntArray(lower.size) { 20 },
@@ -23,13 +23,13 @@ public class RealHistogramSpace(
     public val dimension: Int get() = lower.size
 
     private val shape = IntArray(binNums.size) { binNums[it] + 2 }
-    override val histogramValueSpace: RealNDField = NDAlgebra.real(*shape)
+    override val histogramValueSpace: DoubleFieldND = AlgebraND.real(*shape)
 
     override val strides: Strides get() = histogramValueSpace.strides
-    private val binSize = RealBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] }
+    private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] }
 
     /**
-     * Get internal [NDStructure] bin index for given axis
+     * Get internal [StructureND] bin index for given axis
      */
     private fun getIndex(axis: Int, value: Double): Int = when {
         value >= upper[axis] -> binNums[axis] + 1 // overflow
@@ -69,13 +69,13 @@ public class RealHistogramSpace(
     }
 
     override fun produce(builder: HistogramBuilder<Double>.() -> Unit): IndexedHistogram<Double, Double> {
-        val ndCounter = NDStructure.auto(strides) { Counter.real() }
+        val ndCounter = StructureND.auto(strides) { Counter.real() }
         val hBuilder = HistogramBuilder<Double> { point, value ->
             val index = getIndex(point)
             ndCounter[index].add(value.toDouble())
         }
         hBuilder.apply(builder)
-        val values: NDBuffer<Double> = ndCounter.mapToBuffer { it.value }
+        val values: BufferND<Double> = ndCounter.mapToBuffer { it.value }
         return IndexedHistogram(this, values)
     }
 
@@ -91,7 +91,7 @@ public class RealHistogramSpace(
          *)
          *```
          */
-        public fun fromRanges(vararg ranges: ClosedFloatingPointRange<Double>): RealHistogramSpace = RealHistogramSpace(
+        public fun fromRanges(vararg ranges: ClosedFloatingPointRange<Double>): DoubleHistogramSpace = DoubleHistogramSpace(
             ranges.map(ClosedFloatingPointRange<Double>::start).asBuffer(),
             ranges.map(ClosedFloatingPointRange<Double>::endInclusive).asBuffer()
         )
@@ -105,8 +105,8 @@ public class RealHistogramSpace(
          *)
          *```
          */
-        public fun fromRanges(vararg ranges: Pair<ClosedFloatingPointRange<Double>, Int>): RealHistogramSpace =
-            RealHistogramSpace(
+        public fun fromRanges(vararg ranges: Pair<ClosedFloatingPointRange<Double>, Int>): DoubleHistogramSpace =
+            DoubleHistogramSpace(
                 ListBuffer(
                     ranges
                         .map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt
index 73b34783c..d680a9ad0 100644
--- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt
+++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt
@@ -2,8 +2,8 @@ package space.kscience.kmath.histogram
 
 import space.kscience.kmath.domains.Domain
 import space.kscience.kmath.linear.Point
-import space.kscience.kmath.structures.ArrayBuffer
-import space.kscience.kmath.structures.RealBuffer
+import space.kscience.kmath.structures.DoubleBuffer
+import space.kscience.kmath.structures.asBuffer
 
 /**
  * The binned data element. Could be a histogram bin with a number of counts or an artificial construct
@@ -29,7 +29,7 @@ public interface Histogram<T : Any, out B : Bin<T>> {
     public val bins: Iterable<B>
 }
 
-public fun interface HistogramBuilder<T : Any>  {
+public fun interface HistogramBuilder<T : Any> {
 
     /**
      * Increment appropriate bin
@@ -40,12 +40,12 @@ public fun interface HistogramBuilder<T : Any>  {
 
 public fun <T : Any, B : Bin<T>> HistogramBuilder<T>.put(point: Point<out T>): Unit = putValue(point, 1.0)
 
-public fun <T : Any> HistogramBuilder<T>.put(vararg point: T): Unit = put(ArrayBuffer(point))
+public fun <T : Any> HistogramBuilder<T>.put(vararg point: T): Unit = put(point.asBuffer())
 
 public fun HistogramBuilder<Double>.put(vararg point: Number): Unit =
-    put(RealBuffer(point.map { it.toDouble() }.toDoubleArray()))
+    put(DoubleBuffer(point.map { it.toDouble() }.toDoubleArray()))
 
-public fun HistogramBuilder<Double>.put(vararg point: Double): Unit = put(RealBuffer(point))
+public fun HistogramBuilder<Double>.put(vararg point: Double): Unit = put(DoubleBuffer(point))
 public fun <T : Any> HistogramBuilder<T>.fill(sequence: Iterable<Point<T>>): Unit = sequence.forEach { put(it) }
 
 /**
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 19128b2ac..f55080b09 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,9 +3,9 @@ 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.NDField
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.FieldND
 import space.kscience.kmath.nd.Strides
+import space.kscience.kmath.nd.StructureND
 import space.kscience.kmath.operations.Group
 import space.kscience.kmath.operations.ScaleOperations
 import space.kscience.kmath.operations.SpaceElement
@@ -22,7 +22,7 @@ public data class DomainBin<T : Comparable<T>>(
 @OptIn(UnstableKMathAPI::class)
 public class IndexedHistogram<T : Comparable<T>, V : Any>(
     override val context: IndexedHistogramSpace<T, V>,
-    public val values: NDStructure<V>,
+    public val values: StructureND<V>,
 ) : Histogram<T, Bin<T>>, SpaceElement<IndexedHistogram<T, V>, IndexedHistogramSpace<T, V>> {
 
     override fun get(point: Point<T>): Bin<T>? {
@@ -46,7 +46,7 @@ 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: NDField<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
+    public val histogramValueSpace: FieldND<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
 
     /**
      * Resolve index of the bin including given [point]
diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt
index e83f42b4b..feb87a7a7 100644
--- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt
+++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt
@@ -1,15 +1,14 @@
 package space.kscience.kmath.histogram
 
 import space.kscience.kmath.operations.invoke
-import space.kscience.kmath.real.RealVector
-import space.kscience.kmath.real.invoke
+import space.kscience.kmath.real.DoubleVector
 import kotlin.random.Random
 import kotlin.test.*
 
 internal class MultivariateHistogramTest {
     @Test
     fun testSinglePutHistogram() {
-        val hSpace = RealHistogramSpace.fromRanges(
+        val hSpace = DoubleHistogramSpace.fromRanges(
             (-1.0..1.0),
             (-1.0..1.0)
         )
@@ -17,14 +16,14 @@ internal class MultivariateHistogramTest {
             put(0.55, 0.55)
         }
         val bin = histogram.bins.find { it.value.toInt() > 0 } ?: fail()
-        assertTrue { bin.contains(RealVector(0.55, 0.55)) }
-        assertTrue { bin.contains(RealVector(0.6, 0.5)) }
-        assertFalse { bin.contains(RealVector(-0.55, 0.55)) }
+        assertTrue { bin.contains(DoubleVector(0.55, 0.55)) }
+        assertTrue { bin.contains(DoubleVector(0.6, 0.5)) }
+        assertFalse { bin.contains(DoubleVector(-0.55, 0.55)) }
     }
 
     @Test
     fun testSequentialPut() {
-        val hSpace = RealHistogramSpace.fromRanges(
+        val hSpace = DoubleHistogramSpace.fromRanges(
             (-1.0..1.0),
             (-1.0..1.0),
             (-1.0..1.0)
@@ -44,7 +43,7 @@ internal class MultivariateHistogramTest {
 
     @Test
     fun testHistogramAlgebra() {
-       RealHistogramSpace.fromRanges(
+        DoubleHistogramSpace.fromRanges(
             (-1.0..1.0),
             (-1.0..1.0),
             (-1.0..1.0)
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 03bd096d9..b1b2a10c2 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
@@ -9,7 +9,8 @@ import space.kscience.kmath.structures.asSequence
 
 
 @UnstableKMathAPI
-public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2
+public val UnivariateDomain.center: Double
+    get() = (range.endInclusive - range.start) / 2
 
 /**
  * A univariate bin based an a range
diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts
index 51292cbfb..a7c0c7e01 100644
--- a/kmath-kotlingrad/build.gradle.kts
+++ b/kmath-kotlingrad/build.gradle.kts
@@ -8,6 +8,6 @@ dependencies {
     api(project(":kmath-ast"))
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
 }
\ No newline at end of file
diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt
index ffdabaffb..7cd3276b8 100644
--- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt
+++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt
@@ -6,7 +6,7 @@ import space.kscience.kmath.ast.MstAlgebra
 import space.kscience.kmath.ast.MstExpression
 import space.kscience.kmath.ast.parseMath
 import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.operations.RealField
+import space.kscience.kmath.operations.DoubleField
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
@@ -16,8 +16,8 @@ internal class AdaptingTests {
     @Test
     fun symbol() {
         val c1 = MstAlgebra.bindSymbol("x")
-        assertTrue(c1.toSVar<KMathNumber<Double, RealField>>().name == "x")
-        val c2 = "kitten".parseMath().toSFun<KMathNumber<Double, RealField>>()
+        assertTrue(c1.toSVar<KMathNumber<Double, DoubleField>>().name == "x")
+        val c2 = "kitten".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
         if (c2 is SVar) assertTrue(c2.name == "kitten") else fail()
     }
 
@@ -25,15 +25,15 @@ internal class AdaptingTests {
     fun number() {
         val c1 = MstAlgebra.number(12354324)
         assertTrue(c1.toSConst<DReal>().doubleValue == 12354324.0)
-        val c2 = "0.234".parseMath().toSFun<KMathNumber<Double, RealField>>()
+        val c2 = "0.234".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
         if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail()
-        val c3 = "1e-3".parseMath().toSFun<KMathNumber<Double, RealField>>()
+        val c3 = "1e-3".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
         if (c3 is SConst) assertEquals(0.001, c3.value) else fail()
     }
 
     @Test
     fun simpleFunctionShape() {
-        val linear = "2*x+16".parseMath().toSFun<KMathNumber<Double, RealField>>()
+        val linear = "2*x+16".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
         if (linear !is Sum) fail()
         if (linear.left !is Prod) fail()
         if (linear.right !is SConst) fail()
@@ -41,21 +41,21 @@ internal class AdaptingTests {
 
     @Test
     fun simpleFunctionDerivative() {
-        val x = MstAlgebra.bindSymbol("x").toSVar<KMathNumber<Double, RealField>>()
-        val quadratic = "x^2-4*x-44".parseMath().toSFun<KMathNumber<Double, RealField>>()
-        val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile()
-        val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile()
+        val x = MstAlgebra.bindSymbol("x").toSVar<KMathNumber<Double, DoubleField>>()
+        val quadratic = "x^2-4*x-44".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
+        val actualDerivative = MstExpression(DoubleField, quadratic.d(x).toMst()).compile()
+        val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile()
         assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0))
     }
 
     @Test
     fun moreComplexDerivative() {
-        val x = MstAlgebra.bindSymbol("x").toSVar<KMathNumber<Double, RealField>>()
-        val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun<KMathNumber<Double, RealField>>()
-        val actualDerivative = MstExpression(RealField, composition.d(x).toMst()).compile()
+        val x = MstAlgebra.bindSymbol("x").toSVar<KMathNumber<Double, DoubleField>>()
+        val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
+        val actualDerivative = MstExpression(DoubleField, composition.d(x).toMst()).compile()
 
         val expectedDerivative = MstExpression(
-            RealField,
+            DoubleField,
             "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath()
         ).compile()
 
diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts
index dbd68b042..1ccd1bed8 100644
--- a/kmath-memory/build.gradle.kts
+++ b/kmath-memory/build.gradle.kts
@@ -3,7 +3,7 @@ plugins {
     id("ru.mipt.npm.gradle.native")
 }
 
-readme{
+readme {
     description = """
         An API and basic implementation for arranging objects in a continous memory block.
     """.trimIndent()
diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt
index 7c68e3abb..5ed3c3c9e 100644
--- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt
+++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt
@@ -32,7 +32,8 @@ public fun <T : Any> MemoryReader.read(spec: MemorySpec<T>, offset: Int): T = wi
 /**
  * Writes the object [value] with [spec] starting from [offset].
  */
-public fun <T : Any> MemoryWriter.write(spec: MemorySpec<T>, offset: Int, value: T): Unit = with(spec) { write(offset, value) }
+public fun <T : Any> MemoryWriter.write(spec: MemorySpec<T>, offset: Int, value: T): Unit =
+    with(spec) { write(offset, value) }
 
 /**
  * Reads array of [size] objects mapped by [spec] at certain [offset].
diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt
index 5145b1ed4..fe15cce49 100644
--- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt
+++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt
@@ -13,7 +13,7 @@ import kotlin.contracts.contract
 internal class ByteBufferMemory(
     val buffer: ByteBuffer,
     val startOffset: Int = 0,
-    override val size: Int = buffer.limit()
+    override val size: Int = buffer.limit(),
 ) : Memory {
     @Suppress("NOTHING_TO_INLINE")
     private inline fun position(o: Int): Int = startOffset + o
@@ -100,7 +100,8 @@ public actual fun Memory.Companion.allocate(length: Int): Memory =
  * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied
  * and could be mutated independently from the resulting [Memory].
  */
-public actual fun Memory.Companion.wrap(array: ByteArray): Memory = ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array)))
+public actual fun Memory.Companion.wrap(array: ByteArray): Memory =
+    ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array)))
 
 /**
  * Wraps this [ByteBuffer] to [Memory] object.
diff --git a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt
index 3afb6c7a2..1274959ad 100644
--- a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt
+++ b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt
@@ -4,7 +4,7 @@ package space.kscience.kmath.memory
 internal class NativeMemory(
     val array: ByteArray,
     val startOffset: Int = 0,
-    override val size: Int = array.size
+    override val size: Int = array.size,
 ) : Memory {
     @Suppress("NOTHING_TO_INLINE")
     private inline fun position(o: Int): Int = startOffset + o
diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md
index 046c8127f..2771722eb 100644
--- a/kmath-nd4j/README.md
+++ b/kmath-nd4j/README.md
@@ -2,14 +2,14 @@
 
 This subproject implements the following features:
 
- - [nd4jarraystructure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
- - [nd4jarrayrings](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long
- - [nd4jarrayfields](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double
+ - [nd4jarraystructure](#) : NDStructure wrapper for INDArray
+ - [nd4jarrayrings](#) : Rings over Nd4jArrayStructure of Int and Long
+ - [nd4jarrayfields](#) : Fields over Nd4jArrayStructure of Float and Double
 
 
 > #### Artifact:
 >
-> This module artifact: `space.kscience:kmath-nd4j:0.2.0`.
+> This module artifact: `space.kscience:kmath-nd4j:0.3.0-dev-3`.
 >
 > Bintray release version:        [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion)
 >
@@ -22,13 +22,10 @@ This subproject implements the following features:
 >     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-nd4j:0.2.0'
+>     implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3'
 > }
 > ```
 > **Gradle Kotlin DSL:**
@@ -38,13 +35,10 @@ This subproject implements the following features:
 >     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-nd4j:0.2.0")
+>     implementation("space.kscience:kmath-nd4j:0.3.0-dev-3")
 > }
 > ```
 
@@ -57,7 +51,7 @@ import org.nd4j.linalg.factory.*
 import scientifik.kmath.nd4j.*
 import scientifik.kmath.structures.*
 
-val array = Nd4j.ones(2, 2).asRealStructure()
+val array = Nd4j.ones(2, 2).asDoubleStructure()
 println(array[0, 0]) // 1.0
 array[intArrayOf(0, 0)] = 24.0
 println(array[0, 0]) // 24.0
@@ -70,8 +64,8 @@ import org.nd4j.linalg.factory.*
 import scientifik.kmath.nd4j.*
 import scientifik.kmath.operations.*
 
-val field = RealNd4jArrayField(intArrayOf(2, 2))
-val array = Nd4j.rand(2, 2).asRealStructure()
+val field = DoubleNd4jArrayField(intArrayOf(2, 2))
+val array = Nd4j.rand(2, 2).asDoubleStructure()
 
 val res = field {
     (25.0 / array + 20) * 4
diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts
index c801f8e51..2954a1e65 100644
--- a/kmath-nd4j/build.gradle.kts
+++ b/kmath-nd4j/build.gradle.kts
@@ -19,19 +19,16 @@ readme {
 
     feature(
         id = "nd4jarraystructure",
-        description = "NDStructure wrapper for INDArray",
-        ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt"
+        description = "NDStructure wrapper for INDArray"
     )
 
     feature(
         id = "nd4jarrayrings",
-        description = "Rings over Nd4jArrayStructure of Int and Long",
-        ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt"
+        description = "Rings over Nd4jArrayStructure of Int and Long"
     )
 
     feature(
         id = "nd4jarrayfields",
-        description = "Fields over Nd4jArrayStructure of Float and Double",
-        ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt"
+        description = "Fields over Nd4jArrayStructure of Float and Double"
     )
 }
diff --git a/kmath-nd4j/docs/README-TEMPLATE.md b/kmath-nd4j/docs/README-TEMPLATE.md
index 76ce8c9a7..9783e74be 100644
--- a/kmath-nd4j/docs/README-TEMPLATE.md
+++ b/kmath-nd4j/docs/README-TEMPLATE.md
@@ -15,7 +15,7 @@ import org.nd4j.linalg.factory.*
 import scientifik.kmath.nd4j.*
 import scientifik.kmath.structures.*
 
-val array = Nd4j.ones(2, 2).asRealStructure()
+val array = Nd4j.ones(2, 2).asDoubleStructure()
 println(array[0, 0]) // 1.0
 array[intArrayOf(0, 0)] = 24.0
 println(array[0, 0]) // 24.0
@@ -28,8 +28,8 @@ import org.nd4j.linalg.factory.*
 import scientifik.kmath.nd4j.*
 import scientifik.kmath.operations.*
 
-val field = RealNd4jArrayField(intArrayOf(2, 2))
-val array = Nd4j.rand(2, 2).asRealStructure()
+val field = DoubleNd4jArrayField(intArrayOf(2, 2))
+val array = Nd4j.rand(2, 2).asDoubleStructure()
 
 val res = field {
     (25.0 / array + 20) * 4
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 d8ce1052a..8ea992bcb 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
@@ -7,7 +7,7 @@ import space.kscience.kmath.nd.*
 import space.kscience.kmath.operations.*
 import space.kscience.kmath.structures.*
 
-internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray {
+internal fun AlgebraND<*, *>.checkShape(array: INDArray): INDArray {
     val arrayShape = array.shape().toIntArray()
     if (!shape.contentEquals(arrayShape)) throw ShapeMismatchException(shape, arrayShape)
     return array
@@ -15,18 +15,18 @@ internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray {
 
 
 /**
- * Represents [NDAlgebra] over [Nd4jArrayAlgebra].
+ * Represents [AlgebraND] over [Nd4jArrayAlgebra].
  *
  * @param T the type of ND-structure element.
  * @param C the type of the element context.
  */
-public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : NDAlgebra<T, C> {
+public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : AlgebraND<T, C> {
     /**
      * Wraps [INDArray] to [N].
      */
     public fun INDArray.wrap(): Nd4jArrayStructure<T>
 
-    public val NDStructure<T>.ndArray: INDArray
+    public val StructureND<T>.ndArray: INDArray
         get() = when {
             !shape.contentEquals(this@Nd4jArrayAlgebra.shape) -> throw ShapeMismatchException(
                 this@Nd4jArrayAlgebra.shape,
@@ -44,13 +44,13 @@ public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : NDAlgebra<T, C> {
         return struct
     }
 
-    public override fun NDStructure<T>.map(transform: C.(T) -> T): Nd4jArrayStructure<T> {
+    public override fun StructureND<T>.map(transform: C.(T) -> T): Nd4jArrayStructure<T> {
         val newStruct = ndArray.dup().wrap()
         newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) }
         return newStruct
     }
 
-    public override fun NDStructure<T>.mapIndexed(
+    public override fun StructureND<T>.mapIndexed(
         transform: C.(index: IntArray, T) -> T,
     ): Nd4jArrayStructure<T> {
         val new = Nd4j.create(*this@Nd4jArrayAlgebra.shape).wrap()
@@ -59,8 +59,8 @@ public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : NDAlgebra<T, C> {
     }
 
     public override fun combine(
-        a: NDStructure<T>,
-        b: NDStructure<T>,
+        a: StructureND<T>,
+        b: StructureND<T>,
         transform: C.(T, T) -> T,
     ): Nd4jArrayStructure<T> {
         val new = Nd4j.create(*shape).wrap()
@@ -70,42 +70,42 @@ public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : NDAlgebra<T, C> {
 }
 
 /**
- * Represents [NDGroup] over [Nd4jArrayStructure].
+ * Represents [GroupND] over [Nd4jArrayStructure].
  *
  * @param T the type of the element contained in ND structure.
  * @param S the type of space of structure elements.
  */
-public interface Nd4JArrayGroup<T, S : Group<T>> : NDGroup<T, S>, Nd4jArrayAlgebra<T, S> {
+public interface Nd4JArrayGroup<T, S : Group<T>> : GroupND<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> =
+    public override fun add(a: StructureND<T>, b: StructureND<T>): Nd4jArrayStructure<T> =
         a.ndArray.add(b.ndArray).wrap()
 
-    public override operator fun NDStructure<T>.minus(b: NDStructure<T>): Nd4jArrayStructure<T> =
+    public override operator fun StructureND<T>.minus(b: StructureND<T>): Nd4jArrayStructure<T> =
         ndArray.sub(b.ndArray).wrap()
 
-    public override operator fun NDStructure<T>.unaryMinus(): Nd4jArrayStructure<T> =
+    public override operator fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> =
         ndArray.neg().wrap()
 
-    public fun multiply(a: NDStructure<T>, k: Number): Nd4jArrayStructure<T> =
+    public fun multiply(a: StructureND<T>, k: Number): Nd4jArrayStructure<T> =
         a.ndArray.mul(k).wrap()
 }
 
 /**
- * Represents [NDRing] over [Nd4jArrayStructure].
+ * Represents [RingND] over [Nd4jArrayStructure].
  *
  * @param T the type of the element contained in ND structure.
  * @param R the type of ring of structure elements.
  */
 @OptIn(UnstableKMathAPI::class)
-public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4JArrayGroup<T, R> {
+public interface Nd4jArrayRing<T, R : Ring<T>> : RingND<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> =
+    public override fun multiply(a: StructureND<T>, b: StructureND<T>): Nd4jArrayStructure<T> =
         a.ndArray.mul(b.ndArray).wrap()
 //
 //    public override operator fun Nd4jArrayStructure<T>.minus(b: Number): Nd4jArrayStructure<T> {
@@ -131,19 +131,19 @@ public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4JArrayGroup<T,
             ThreadLocal.withInitial { hashMapOf() }
 
         /**
-         * Creates an [NDRing] for [Int] values or pull it from cache if it was created previously.
+         * Creates an [RingND] for [Int] values or pull it from cache if it was created previously.
          */
         public fun int(vararg shape: Int): Nd4jArrayRing<Int, IntRing> =
             intNd4jArrayRingCache.get().getOrPut(shape) { IntNd4jArrayRing(shape) }
 
         /**
-         * Creates an [NDRing] for [Long] values or pull it from cache if it was created previously.
+         * Creates an [RingND] for [Long] values or pull it from cache if it was created previously.
          */
         public fun long(vararg shape: Int): Nd4jArrayRing<Long, LongRing> =
             longNd4jArrayRingCache.get().getOrPut(shape) { LongNd4jArrayRing(shape) }
 
         /**
-         * Creates a most suitable implementation of [NDRing] using reified class.
+         * Creates a most suitable implementation of [RingND] using reified class.
          */
         @Suppress("UNCHECKED_CAST")
         public inline fun <reified T : Any> auto(vararg shape: Int): Nd4jArrayRing<T, out Ring<T>> = when {
@@ -155,40 +155,40 @@ public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4JArrayGroup<T,
 }
 
 /**
- * Represents [NDField] over [Nd4jArrayStructure].
+ * Represents [FieldND] over [Nd4jArrayStructure].
  *
  * @param T the type of the element contained in ND structure.
  * @param N the type of ND structure.
  * @param F the type field of structure elements.
  */
-public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<T, F> {
+public interface Nd4jArrayField<T, F : Field<T>> : FieldND<T, F>, Nd4jArrayRing<T, F> {
 
-    public override fun divide(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
+    public override fun divide(a: StructureND<T>, b: StructureND<T>): Nd4jArrayStructure<T> =
         a.ndArray.div(b.ndArray).wrap()
 
-    public operator fun Number.div(b: NDStructure<T>): Nd4jArrayStructure<T> = b.ndArray.rdiv(this).wrap()
+    public operator fun Number.div(b: StructureND<T>): Nd4jArrayStructure<T> = b.ndArray.rdiv(this).wrap()
 
     public companion object {
         private val floatNd4jArrayFieldCache: ThreadLocal<MutableMap<IntArray, FloatNd4jArrayField>> =
             ThreadLocal.withInitial { hashMapOf() }
 
-        private val realNd4jArrayFieldCache: ThreadLocal<MutableMap<IntArray, RealNd4jArrayField>> =
+        private val doubleNd4JArrayFieldCache: ThreadLocal<MutableMap<IntArray, DoubleNd4jArrayField>> =
             ThreadLocal.withInitial { hashMapOf() }
 
         /**
-         * Creates an [NDField] for [Float] values or pull it from cache if it was created previously.
+         * Creates an [FieldND] for [Float] values or pull it from cache if it was created previously.
          */
         public fun float(vararg shape: Int): Nd4jArrayRing<Float, FloatField> =
             floatNd4jArrayFieldCache.get().getOrPut(shape) { FloatNd4jArrayField(shape) }
 
         /**
-         * Creates an [NDField] for [Double] values or pull it from cache if it was created previously.
+         * Creates an [FieldND] for [Double] values or pull it from cache if it was created previously.
          */
-        public fun real(vararg shape: Int): Nd4jArrayRing<Double, RealField> =
-            realNd4jArrayFieldCache.get().getOrPut(shape) { RealNd4jArrayField(shape) }
+        public fun real(vararg shape: Int): Nd4jArrayRing<Double, DoubleField> =
+            doubleNd4JArrayFieldCache.get().getOrPut(shape) { DoubleNd4jArrayField(shape) }
 
         /**
-         * Creates a most suitable implementation of [NDRing] using reified class.
+         * Creates a most suitable implementation of [RingND] using reified class.
          */
         @Suppress("UNCHECKED_CAST")
         public inline fun <reified T : Any> auto(vararg shape: Int): Nd4jArrayField<T, out Field<T>> = when {
@@ -200,44 +200,44 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
 }
 
 /**
- * Represents [NDField] over [Nd4jArrayRealStructure].
+ * Represents [FieldND] over [Nd4jArrayDoubleStructure].
  */
-public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Double, RealField> {
-    public override val elementContext: RealField get() = RealField
+public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Double, DoubleField> {
+    public override val elementContext: DoubleField get() = DoubleField
 
-    public override fun INDArray.wrap(): Nd4jArrayStructure<Double> = checkShape(this).asRealStructure()
+    public override fun INDArray.wrap(): Nd4jArrayStructure<Double> = checkShape(this).asDoubleStructure()
 
-    override fun scale(a: NDStructure<Double>, value: Double): Nd4jArrayStructure<Double> {
+    override fun scale(a: StructureND<Double>, value: Double): Nd4jArrayStructure<Double> {
         return a.ndArray.mul(value).wrap()
     }
 
-    public override operator fun NDStructure<Double>.div(arg: Double): Nd4jArrayStructure<Double> {
+    public override operator fun StructureND<Double>.div(arg: Double): Nd4jArrayStructure<Double> {
         return ndArray.div(arg).wrap()
     }
 
-    public override operator fun NDStructure<Double>.plus(arg: Double): Nd4jArrayStructure<Double> {
+    public override operator fun StructureND<Double>.plus(arg: Double): Nd4jArrayStructure<Double> {
         return ndArray.add(arg).wrap()
     }
 
-    public override operator fun NDStructure<Double>.minus(arg: Double): Nd4jArrayStructure<Double> {
+    public override operator fun StructureND<Double>.minus(arg: Double): Nd4jArrayStructure<Double> {
         return ndArray.sub(arg).wrap()
     }
 
-    public override operator fun NDStructure<Double>.times(arg: Double): Nd4jArrayStructure<Double> {
+    public override operator fun StructureND<Double>.times(arg: Double): Nd4jArrayStructure<Double> {
         return ndArray.mul(arg).wrap()
     }
 
-    public override operator fun Double.div(arg: NDStructure<Double>): Nd4jArrayStructure<Double> {
+    public override operator fun Double.div(arg: StructureND<Double>): Nd4jArrayStructure<Double> {
         return arg.ndArray.rdiv(this).wrap()
     }
 
-    public override operator fun Double.minus(arg: NDStructure<Double>): Nd4jArrayStructure<Double> {
+    public override operator fun Double.minus(arg: StructureND<Double>): Nd4jArrayStructure<Double> {
         return arg.ndArray.rsub(this).wrap()
     }
 }
 
 /**
- * Represents [NDField] over [Nd4jArrayStructure] of [Float].
+ * Represents [FieldND] over [Nd4jArrayStructure] of [Float].
  */
 public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Float, FloatField> {
     public override val elementContext: FloatField
@@ -245,30 +245,30 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra
 
     public override fun INDArray.wrap(): Nd4jArrayStructure<Float> = checkShape(this).asFloatStructure()
 
-    override fun scale(a: NDStructure<Float>, value: Double): NDStructure<Float> =
+    override fun scale(a: StructureND<Float>, value: Double): StructureND<Float> =
         a.ndArray.mul(value).wrap()
 
-    public override operator fun NDStructure<Float>.div(arg: Float): Nd4jArrayStructure<Float> =
+    public override operator fun StructureND<Float>.div(arg: Float): Nd4jArrayStructure<Float> =
         ndArray.div(arg).wrap()
 
-    public override operator fun NDStructure<Float>.plus(arg: Float): Nd4jArrayStructure<Float> =
+    public override operator fun StructureND<Float>.plus(arg: Float): Nd4jArrayStructure<Float> =
         ndArray.add(arg).wrap()
 
-    public override operator fun NDStructure<Float>.minus(arg: Float): Nd4jArrayStructure<Float> =
+    public override operator fun StructureND<Float>.minus(arg: Float): Nd4jArrayStructure<Float> =
         ndArray.sub(arg).wrap()
 
-    public override operator fun NDStructure<Float>.times(arg: Float): Nd4jArrayStructure<Float> =
+    public override operator fun StructureND<Float>.times(arg: Float): Nd4jArrayStructure<Float> =
         ndArray.mul(arg).wrap()
 
-    public override operator fun Float.div(arg: NDStructure<Float>): Nd4jArrayStructure<Float> =
+    public override operator fun Float.div(arg: StructureND<Float>): Nd4jArrayStructure<Float> =
         arg.ndArray.rdiv(this).wrap()
 
-    public override operator fun Float.minus(arg: NDStructure<Float>): Nd4jArrayStructure<Float> =
+    public override operator fun Float.minus(arg: StructureND<Float>): Nd4jArrayStructure<Float> =
         arg.ndArray.rsub(this).wrap()
 }
 
 /**
- * Represents [NDRing] over [Nd4jArrayIntStructure].
+ * Represents [RingND] over [Nd4jArrayIntStructure].
  */
 public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing<Int, IntRing> {
     public override val elementContext: IntRing
@@ -276,21 +276,21 @@ 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> =
+    public override operator fun StructureND<Int>.plus(arg: Int): Nd4jArrayStructure<Int> =
         ndArray.add(arg).wrap()
 
-    public override operator fun NDStructure<Int>.minus(arg: Int): Nd4jArrayStructure<Int> =
+    public override operator fun StructureND<Int>.minus(arg: Int): Nd4jArrayStructure<Int> =
         ndArray.sub(arg).wrap()
 
-    public override operator fun NDStructure<Int>.times(arg: Int): Nd4jArrayStructure<Int> =
+    public override operator fun StructureND<Int>.times(arg: Int): Nd4jArrayStructure<Int> =
         ndArray.mul(arg).wrap()
 
-    public override operator fun Int.minus(arg: NDStructure<Int>): Nd4jArrayStructure<Int> =
+    public override operator fun Int.minus(arg: StructureND<Int>): Nd4jArrayStructure<Int> =
         arg.ndArray.rsub(this).wrap()
 }
 
 /**
- * Represents [NDRing] over [Nd4jArrayStructure] of [Long].
+ * Represents [RingND] over [Nd4jArrayStructure] of [Long].
  */
 public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing<Long, LongRing> {
     public override val elementContext: LongRing
@@ -298,15 +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> =
+    public override operator fun StructureND<Long>.plus(arg: Long): Nd4jArrayStructure<Long> =
         ndArray.add(arg).wrap()
 
-    public override operator fun NDStructure<Long>.minus(arg: Long): Nd4jArrayStructure<Long> =
+    public override operator fun StructureND<Long>.minus(arg: Long): Nd4jArrayStructure<Long> =
         ndArray.sub(arg).wrap()
 
-    public override operator fun NDStructure<Long>.times(arg: Long): Nd4jArrayStructure<Long> =
+    public override operator fun StructureND<Long>.times(arg: Long): Nd4jArrayStructure<Long> =
         ndArray.mul(arg).wrap()
 
-    public override operator fun Long.minus(arg: NDStructure<Long>): Nd4jArrayStructure<Long> =
+    public override operator fun Long.minus(arg: StructureND<Long>): Nd4jArrayStructure<Long> =
         arg.ndArray.rsub(this).wrap()
 }
diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt
index 521c8cab3..cfb900277 100644
--- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt
+++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt
@@ -37,11 +37,11 @@ private sealed class Nd4jArrayIteratorBase<T>(protected val iterateOver: INDArra
     }
 }
 
-private class Nd4jArrayRealIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase<Double>(iterateOver) {
+private class Nd4jArrayDoubleIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase<Double>(iterateOver) {
     override fun getSingle(indices: LongArray): Double = iterateOver.getDouble(*indices)
 }
 
-internal fun INDArray.realIterator(): Iterator<Pair<IntArray, Double>> = Nd4jArrayRealIterator(this)
+internal fun INDArray.realIterator(): Iterator<Pair<IntArray, Double>> = Nd4jArrayDoubleIterator(this)
 
 private class Nd4jArrayLongIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase<Long>(iterateOver) {
     override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices)
diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt
index 415c908a8..6a3ae37a7 100644
--- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt
+++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt
@@ -1,15 +1,15 @@
 package space.kscience.kmath.nd4j
 
 import org.nd4j.linalg.api.ndarray.INDArray
-import space.kscience.kmath.nd.MutableNDStructure
-import space.kscience.kmath.nd.NDStructure
+import space.kscience.kmath.nd.MutableStructureND
+import space.kscience.kmath.nd.StructureND
 
 /**
- * Represents a [NDStructure] wrapping an [INDArray] object.
+ * Represents a [StructureND] wrapping an [INDArray] object.
  *
  * @param T the type of items.
  */
-public sealed class Nd4jArrayStructure<T> : MutableNDStructure<T> {
+public sealed class Nd4jArrayStructure<T> : MutableStructureND<T> {
     /**
      * The wrapped [INDArray].
      */
@@ -45,7 +45,7 @@ private data class Nd4jArrayLongStructure(override val ndArray: INDArray) : Nd4j
  */
 public fun INDArray.asLongStructure(): Nd4jArrayStructure<Long> = Nd4jArrayLongStructure(this)
 
-private data class Nd4jArrayRealStructure(override val ndArray: INDArray) : Nd4jArrayStructure<Double>() {
+private data class Nd4jArrayDoubleStructure(override val ndArray: INDArray) : Nd4jArrayStructure<Double>() {
     override fun elementsIterator(): Iterator<Pair<IntArray, Double>> = ndArray.realIterator()
     override fun get(index: IntArray): Double = ndArray.getDouble(*index)
     override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) }
@@ -54,7 +54,7 @@ private data class Nd4jArrayRealStructure(override val ndArray: INDArray) : Nd4j
 /**
  * Wraps this [INDArray] to [Nd4jArrayStructure].
  */
-public fun INDArray.asRealStructure(): Nd4jArrayStructure<Double> = Nd4jArrayRealStructure(this)
+public fun INDArray.asDoubleStructure(): Nd4jArrayStructure<Double> = Nd4jArrayDoubleStructure(this)
 
 private data class Nd4jArrayFloatStructure(override val ndArray: INDArray) : Nd4jArrayStructure<Float>() {
     override fun elementsIterator(): Iterator<Pair<IntArray, Float>> = ndArray.floatIterator()
diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt
index 9a067aa29..e658275f5 100644
--- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt
+++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt
@@ -8,8 +8,8 @@ import kotlin.test.fail
 internal class Nd4jArrayAlgebraTest {
     @Test
     fun testProduce() {
-        val res = with(RealNd4jArrayField(intArrayOf(2, 2))){ produce { it.sum().toDouble() } }
-        val expected = (Nd4j.create(2, 2) ?: fail()).asRealStructure()
+        val res = with(DoubleNd4jArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } }
+        val expected = (Nd4j.create(2, 2) ?: fail()).asDoubleStructure()
         expected[intArrayOf(0, 0)] = 0.0
         expected[intArrayOf(0, 1)] = 1.0
         expected[intArrayOf(1, 0)] = 1.0
diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt
index 03369127d..0c03270dd 100644
--- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt
+++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt
@@ -11,7 +11,7 @@ internal class Nd4jArrayStructureTest {
     @Test
     fun testElements() {
         val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!!
-        val struct = nd.asRealStructure()
+        val struct = nd.asDoubleStructure()
         val res = struct.elements().map(Pair<IntArray, Double>::second).toList()
         assertEquals(listOf(1.0, 2.0, 3.0), res)
     }
@@ -19,32 +19,32 @@ internal class Nd4jArrayStructureTest {
     @Test
     fun testShape() {
         val nd = Nd4j.rand(10, 2, 3, 6) ?: fail()
-        val struct = nd.asRealStructure()
+        val struct = nd.asDoubleStructure()
         assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.toList())
     }
 
     @Test
     fun testEquals() {
         val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail()
-        val struct1 = nd1.asRealStructure()
+        val struct1 = nd1.asDoubleStructure()
         assertEquals(struct1, struct1)
         assertNotEquals(struct1 as Any?, null)
         val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail()
-        val struct2 = nd2.asRealStructure()
+        val struct2 = nd2.asDoubleStructure()
         assertEquals(struct1, struct2)
         assertEquals(struct2, struct1)
         val nd3 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail()
-        val struct3 = nd3.asRealStructure()
+        val struct3 = nd3.asDoubleStructure()
         assertEquals(struct2, struct3)
         assertEquals(struct1, struct3)
     }
 
     @Test
     fun testHashCode() {
-        val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))?:fail()
-        val struct1 = nd1.asRealStructure()
-        val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))?:fail()
-        val struct2 = nd2.asRealStructure()
+        val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail()
+        val struct1 = nd1.asDoubleStructure()
+        val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail()
+        val struct2 = nd2.asDoubleStructure()
         assertEquals(struct1.hashCode(), struct2.hashCode())
     }
 
@@ -57,7 +57,7 @@ internal class Nd4jArrayStructureTest {
 
     @Test
     fun testGet() {
-        val nd = Nd4j.rand(10, 2, 3, 6)?:fail()
+        val nd = Nd4j.rand(10, 2, 3, 6) ?: fail()
         val struct = nd.asIntStructure()
         assertEquals(nd.getInt(0, 0, 0, 0), struct[0, 0, 0, 0])
     }
diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts
index 67a96937c..5b29a9e64 100644
--- a/kmath-stat/build.gradle.kts
+++ b/kmath-stat/build.gradle.kts
@@ -25,6 +25,6 @@ kotlin.sourceSets {
     }
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
 }
\ No newline at end of file
diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt
index fa38dd9e4..25f6a87b5 100644
--- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt
+++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt
@@ -4,6 +4,7 @@ import space.kscience.kmath.chains.Chain
 import space.kscience.kmath.chains.collect
 import space.kscience.kmath.structures.Buffer
 import space.kscience.kmath.structures.BufferFactory
+import space.kscience.kmath.structures.DoubleBuffer
 
 public interface Sampler<T : Any> {
     public fun sample(generator: RandomGenerator): Chain<T>
@@ -52,7 +53,7 @@ public fun <T : Comparable<T>> UnivariateDistribution<T>.integral(from: T, to: T
 public fun <T : Any> Sampler<T>.sampleBuffer(
     generator: RandomGenerator,
     size: Int,
-    bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
+    bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
 ): Chain<Buffer<T>> {
     require(size > 1)
     //creating temporary storage once
@@ -74,4 +75,4 @@ public fun <T : Any> Sampler<T>.sampleBuffer(
  * Generate a bunch of samples from real distributions
  */
 public fun Sampler<Double>.sampleBuffer(generator: RandomGenerator, size: Int): Chain<Buffer<Double>> =
-    sampleBuffer(generator, size, Buffer.Companion::real)
+    sampleBuffer(generator, size, ::DoubleBuffer)
diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt
index 71f3096de..ffa24fa98 100644
--- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt
+++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt
@@ -68,7 +68,7 @@ public fun <T : Any, F : OptimizationProblem<T>> Expression<T>.optimizeWith(
     configuration: F.() -> Unit,
 ): OptimizationResult<T> {
     require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" }
-    val problem = factory(symbols.toList(),configuration)
+    val problem = factory(symbols.toList(), configuration)
     problem.expression(this)
     return problem.optimize()
 }
@@ -76,7 +76,7 @@ public fun <T : Any, F : OptimizationProblem<T>> Expression<T>.optimizeWith(
 /**
  * Optimize differentiable expression using specific [OptimizationProblemFactory]
  */
-public fun <T : Any, F : OptimizationProblem<T>>  DifferentiableExpression<T, Expression<T>>.optimizeWith(
+public fun <T : Any, F : OptimizationProblem<T>> DifferentiableExpression<T, Expression<T>>.optimizeWith(
     factory: OptimizationProblemFactory<T, F>,
     vararg symbols: Symbol,
     configuration: F.() -> Unit,
diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt
index 881eabdac..6e1f36c8a 100644
--- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt
+++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt
@@ -7,7 +7,7 @@ import space.kscience.kmath.chains.Chain
  */
 public class RandomChain<out R>(
     public val generator: RandomGenerator,
-    private val gen: suspend RandomGenerator.() -> R
+    private val gen: suspend RandomGenerator.() -> R,
 ) : Chain<R> {
     override suspend fun next(): R = generator.gen()
 
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 a9f7cd3e4..689182115 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
@@ -66,22 +66,22 @@ public fun <T, I, R> ComposableStatistic<T, I, R>.flow(
  * Arithmetic mean
  */
 public class Mean<T>(
-    private val space: Group<T>,
+    private val group: 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
+        group { 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)
+        group { first.first + second.first } to (first.second + second.second)
 
-    public override suspend fun toResult(intermediate: Pair<T, Int>): T = space {
+    public override suspend fun toResult(intermediate: Pair<T, Int>): T = group {
         division(intermediate.first, intermediate.second)
     }
 
     public companion object {
         //TODO replace with optimized version which respects overflow
-        public val real: Mean<Double> = Mean(RealField) { sum, count -> sum / count }
+        public val real: Mean<Double> = Mean(DoubleField) { 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-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt
index d33b54818..8b5551a16 100644
--- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt
+++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt
@@ -2,8 +2,8 @@ package space.kscience.kmath.stat
 
 import org.apache.commons.rng.UniformRandomProvider
 import org.apache.commons.rng.sampling.distribution.*
+import space.kscience.kmath.chains.BlockingDoubleChain
 import space.kscience.kmath.chains.BlockingIntChain
-import space.kscience.kmath.chains.BlockingRealChain
 import space.kscience.kmath.chains.Chain
 import kotlin.math.PI
 import kotlin.math.exp
@@ -11,7 +11,7 @@ import kotlin.math.pow
 import kotlin.math.sqrt
 
 public abstract class ContinuousSamplerDistribution : Distribution<Double> {
-    private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() {
+    private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingDoubleChain() {
         private val sampler = buildCMSampler(generator)
 
         override fun nextDouble(): Double = sampler.sample()
@@ -20,7 +20,7 @@ public abstract class ContinuousSamplerDistribution : Distribution<Double> {
 
     protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler
 
-    public override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator)
+    public override fun sample(generator: RandomGenerator): BlockingDoubleChain = ContinuousSamplerChain(generator)
 }
 
 public abstract class DiscreteSamplerDistribution : Distribution<Int> {
@@ -50,7 +50,7 @@ private fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomPr
     }
 
 public fun Distribution.Companion.normal(
-    method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat
+    method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat,
 ): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() {
     override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler {
         val provider = generator.asUniformRandomProvider()
@@ -66,7 +66,7 @@ public fun Distribution.Companion.normal(
 public fun Distribution.Companion.normal(
     mean: Double,
     sigma: Double,
-    method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat
+    method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat,
 ): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() {
     private val sigma2 = sigma.pow(2)
     private val norm = sigma * sqrt(PI * 2)
diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api
index ebb97b150..0b9ea1b48 100644
--- a/kmath-viktor/api/kmath-viktor.api
+++ b/kmath-viktor/api/kmath-viktor.api
@@ -1,8 +1,6 @@
 public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kmath/structures/MutableBuffer {
 	public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lspace/kscience/kmath/viktor/ViktorBuffer;
 	public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lorg/jetbrains/bio/viktor/F64FlatArray;
-	public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z
-	public static fun contentEquals-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;Lspace/kscience/kmath/structures/Buffer;)Z
 	public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer;
 	public static fun copy-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lspace/kscience/kmath/structures/MutableBuffer;
 	public fun equals (Ljava/lang/Object;)Z
@@ -26,130 +24,130 @@ 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/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations {
+public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/kmath/nd/FieldND, 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;
+	public fun acos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun acosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun add-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
+	public synthetic fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun add-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun asin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun asinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atan-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun atan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun atanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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/NDStructure;
-	public synthetic fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun combine-ZQYDhZg (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND;
+	public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
+	public fun combine-WKhNzhk (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun cos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun cos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	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 fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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;
-	public fun div (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure;
-	public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic 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 div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public synthetic fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun div (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun exp-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	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 fun getElementContext ()Lspace/kscience/kmath/operations/DoubleField;
+	public final fun getF64Buffer (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun getOne ()Ljava/lang/Object;
-	public fun getOne-MSOxzaI ()Lorg/jetbrains/bio/viktor/F64Array;
+	public fun getOne-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array;
 	public fun getShape ()[I
 	public synthetic fun getZero ()Ljava/lang/Object;
-	public fun getZero-MSOxzaI ()Lorg/jetbrains/bio/viktor/F64Array;
-	public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun getZero-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array;
+	public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
 	public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun ln-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
-	public synthetic fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun map-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array;
-	public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun mapIndexed-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array;
-	public fun minus (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun ln-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
+	public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
+	public fun map-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array;
+	public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND;
+	public fun mapIndexed-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun minus (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun minus (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure;
-	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 minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun minus (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND;
+	public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public synthetic fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun minus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	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 fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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;
+	public fun number-8UOKELU (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun plus (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
 	public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-	public synthetic 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/Number;)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun plus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;D)Lorg/jetbrains/bio/viktor/F64Array;
-	public fun plus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
+	public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
+	public synthetic fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun pow (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
-	public fun power-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
-	public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun produce-Q7Xurp0 (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array;
+	public fun power-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
+	public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND;
+	public fun produce-8UOKELU (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array;
 	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 rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun scale-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;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 fun sin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun sqrt (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun tan (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun tanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun times (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun times (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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 synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
-	public fun times (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure;
-	public synthetic 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 fun times-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
+	public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun times (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND;
+	public synthetic fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND;
+	public fun times (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
+	public fun times-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
 	public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryMinus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 	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/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
+	public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND;
 }
 
-public final class space/kscience/kmath/viktor/ViktorNDStructure : space/kscience/kmath/nd/MutableNDStructure {
-	public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorNDStructure;
+public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscience/kmath/nd/MutableStructureND {
+	public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorStructureND;
 	public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array;
 	public fun elements ()Lkotlin/sequences/Sequence;
 	public static fun elements-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lkotlin/sequences/Sequence;
@@ -174,8 +172,8 @@ public final class space/kscience/kmath/viktor/ViktorNDStructure : space/kscienc
 	public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64Array;
 }
 
-public final class space/kscience/kmath/viktor/ViktorNDStructureKt {
-	public static final fun ViktorNDField ([I)Lspace/kscience/kmath/viktor/ViktorNDField;
+public final class space/kscience/kmath/viktor/ViktorStructureNDKt {
+	public static final fun ViktorNDField ([I)Lspace/kscience/kmath/viktor/ViktorFieldND;
 	public static final fun asStructure (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array;
 }
 
diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts
index b79a25ea1..94744f528 100644
--- a/kmath-viktor/build.gradle.kts
+++ b/kmath-viktor/build.gradle.kts
@@ -9,6 +9,6 @@ dependencies {
     api("org.jetbrains.bio:viktor:1.0.1")
 }
 
-readme{
+readme {
     maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
 }
\ No newline at end of file
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
deleted file mode 100644
index d791ed675..000000000
--- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-package space.kscience.kmath.viktor
-
-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.ScaleOperations
-
-@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
-public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure<Double> {
-    public override val shape: IntArray get() = f64Buffer.shape
-
-    public override inline fun get(index: IntArray): Double = f64Buffer.get(*index)
-
-    public override inline fun set(index: IntArray, value: Double) {
-        f64Buffer.set(*index, value = value)
-    }
-
-    public override fun elements(): Sequence<Pair<IntArray, Double>> =
-        DefaultStrides(shape).indices().map { it to get(it) }
-}
-
-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>,
-    NumbersAddOperations<NDStructure<Double>>, ExtendedField<NDStructure<Double>>,
-    ScaleOperations<NDStructure<Double>> {
-
-    public val NDStructure<Double>.f64Buffer: F64Array
-        get() = when {
-            !shape.contentEquals(this@ViktorNDField.shape) -> throw ShapeMismatchException(
-                this@ViktorNDField.shape,
-                shape
-            )
-            this is ViktorNDStructure && this.f64Buffer.shape.contentEquals(this@ViktorNDField.shape) -> this.f64Buffer
-            else -> produce { this@f64Buffer[it] }.f64Buffer
-        }
-
-    public override val zero: ViktorNDStructure by lazy { F64Array.full(init = 0.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)
-
-    public override val elementContext: RealField get() = RealField
-
-    public override fun produce(initializer: RealField.(IntArray) -> Double): ViktorNDStructure =
-        F64Array(*shape).apply {
-            this@ViktorNDField.strides.indices().forEach { index ->
-                set(value = RealField.initializer(index), indices = index)
-            }
-        }.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 ->
-                set(value = RealField.transform(this@map[index]), indices = index)
-            }
-        }.asStructure()
-
-    public override fun NDStructure<Double>.mapIndexed(
-        transform: RealField.(index: IntArray, Double) -> Double,
-    ): ViktorNDStructure = F64Array(*this@ViktorNDField.shape).apply {
-        this@ViktorNDField.strides.indices().forEach { index ->
-            set(value = RealField.transform(index, this@mapIndexed[index]), indices = index)
-        }
-    }.asStructure()
-
-    public override fun combine(
-        a: NDStructure<Double>,
-        b: NDStructure<Double>,
-        transform: RealField.(Double, Double) -> Double,
-    ): ViktorNDStructure = F64Array(*shape).apply {
-        this@ViktorNDField.strides.indices().forEach { index ->
-            set(value = RealField.transform(a[index], b[index]), indices = index)
-        }
-    }.asStructure()
-
-    public override fun add(a: NDStructure<Double>, b: NDStructure<Double>): ViktorNDStructure =
-        (a.f64Buffer + b.f64Buffer).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()
-
-    public override inline fun NDStructure<Double>.minus(b: NDStructure<Double>): ViktorNDStructure =
-        (f64Buffer - b.f64Buffer).asStructure()
-
-    public override inline fun NDStructure<Double>.times(k: Number): ViktorNDStructure =
-        (f64Buffer * k.toDouble()).asStructure()
-
-    public override inline fun NDStructure<Double>.plus(arg: Double): ViktorNDStructure =
-        (f64Buffer.plus(arg)).asStructure()
-
-    override fun number(value: Number): ViktorNDStructure =
-        F64Array.full(init = value.toDouble(), shape = shape).asStructure()
-
-    override fun sin(arg: NDStructure<Double>): ViktorNDStructure = arg.map { sin(it) }
-
-    override fun cos(arg: NDStructure<Double>): ViktorNDStructure = arg.map { cos(it) }
-
-    override fun asin(arg: NDStructure<Double>): ViktorNDStructure = arg.map { asin(it) }
-
-    override fun acos(arg: NDStructure<Double>): ViktorNDStructure = arg.map { acos(it) }
-
-    override fun atan(arg: NDStructure<Double>): ViktorNDStructure = arg.map { atan(it) }
-
-    override fun power(arg: NDStructure<Double>, pow: Number): ViktorNDStructure = arg.map { it.pow(pow) }
-
-    override fun exp(arg: NDStructure<Double>): ViktorNDStructure = arg.f64Buffer.exp().asStructure()
-
-    override fun ln(arg: NDStructure<Double>): ViktorNDStructure = arg.f64Buffer.log().asStructure()
-}
-
-public fun ViktorNDField(vararg shape: Int): ViktorNDField = ViktorNDField(shape)
\ No newline at end of file
diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt
new file mode 100644
index 000000000..420bcac90
--- /dev/null
+++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt
@@ -0,0 +1,123 @@
+package space.kscience.kmath.viktor
+
+import org.jetbrains.bio.viktor.F64Array
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.nd.*
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.ExtendedField
+import space.kscience.kmath.operations.NumbersAddOperations
+import space.kscience.kmath.operations.ScaleOperations
+
+@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
+public inline class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND<Double> {
+    public override val shape: IntArray get() = f64Buffer.shape
+
+    public override inline fun get(index: IntArray): Double = f64Buffer.get(*index)
+
+    public override inline fun set(index: IntArray, value: Double) {
+        f64Buffer.set(*index, value = value)
+    }
+
+    public override fun elements(): Sequence<Pair<IntArray, Double>> =
+        DefaultStrides(shape).indices().map { it to get(it) }
+}
+
+public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this)
+
+@OptIn(UnstableKMathAPI::class)
+@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
+public class ViktorFieldND(public override val shape: IntArray) : FieldND<Double, DoubleField>,
+    NumbersAddOperations<StructureND<Double>>, ExtendedField<StructureND<Double>>,
+    ScaleOperations<StructureND<Double>> {
+
+    public val StructureND<Double>.f64Buffer: F64Array
+        get() = when {
+            !shape.contentEquals(this@ViktorFieldND.shape) -> throw ShapeMismatchException(
+                this@ViktorFieldND.shape,
+                shape
+            )
+            this is ViktorStructureND && this.f64Buffer.shape.contentEquals(this@ViktorFieldND.shape) -> this.f64Buffer
+            else -> produce { this@f64Buffer[it] }.f64Buffer
+        }
+
+    public override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() }
+
+    public override val one: ViktorStructureND by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() }
+
+    private val strides: Strides = DefaultStrides(shape)
+
+    public override val elementContext: DoubleField get() = DoubleField
+
+    public override fun produce(initializer: DoubleField.(IntArray) -> Double): ViktorStructureND =
+        F64Array(*shape).apply {
+            this@ViktorFieldND.strides.indices().forEach { index ->
+                set(value = DoubleField.initializer(index), indices = index)
+            }
+        }.asStructure()
+
+    override fun StructureND<Double>.unaryMinus(): StructureND<Double> = -1 * this
+
+    public override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): ViktorStructureND =
+        F64Array(*this@ViktorFieldND.shape).apply {
+            this@ViktorFieldND.strides.indices().forEach { index ->
+                set(value = DoubleField.transform(this@map[index]), indices = index)
+            }
+        }.asStructure()
+
+    public override fun StructureND<Double>.mapIndexed(
+        transform: DoubleField.(index: IntArray, Double) -> Double,
+    ): ViktorStructureND = F64Array(*this@ViktorFieldND.shape).apply {
+        this@ViktorFieldND.strides.indices().forEach { index ->
+            set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index)
+        }
+    }.asStructure()
+
+    public override fun combine(
+        a: StructureND<Double>,
+        b: StructureND<Double>,
+        transform: DoubleField.(Double, Double) -> Double,
+    ): ViktorStructureND = F64Array(*shape).apply {
+        this@ViktorFieldND.strides.indices().forEach { index ->
+            set(value = DoubleField.transform(a[index], b[index]), indices = index)
+        }
+    }.asStructure()
+
+    public override fun add(a: StructureND<Double>, b: StructureND<Double>): ViktorStructureND =
+        (a.f64Buffer + b.f64Buffer).asStructure()
+
+    public override fun scale(a: StructureND<Double>, value: Double): ViktorStructureND =
+        (a.f64Buffer * value.toDouble()).asStructure()
+
+    public override inline fun StructureND<Double>.plus(b: StructureND<Double>): ViktorStructureND =
+        (f64Buffer + b.f64Buffer).asStructure()
+
+    public override inline fun StructureND<Double>.minus(b: StructureND<Double>): ViktorStructureND =
+        (f64Buffer - b.f64Buffer).asStructure()
+
+    public override inline fun StructureND<Double>.times(k: Number): ViktorStructureND =
+        (f64Buffer * k.toDouble()).asStructure()
+
+    public override inline fun StructureND<Double>.plus(arg: Double): ViktorStructureND =
+        (f64Buffer.plus(arg)).asStructure()
+
+    override fun number(value: Number): ViktorStructureND =
+        F64Array.full(init = value.toDouble(), shape = shape).asStructure()
+
+    override fun sin(arg: StructureND<Double>): ViktorStructureND = arg.map { sin(it) }
+
+    override fun cos(arg: StructureND<Double>): ViktorStructureND = arg.map { cos(it) }
+
+    override fun asin(arg: StructureND<Double>): ViktorStructureND = arg.map { asin(it) }
+
+    override fun acos(arg: StructureND<Double>): ViktorStructureND = arg.map { acos(it) }
+
+    override fun atan(arg: StructureND<Double>): ViktorStructureND = arg.map { atan(it) }
+
+    override fun power(arg: StructureND<Double>, pow: Number): ViktorStructureND = arg.map { it.pow(pow) }
+
+    override fun exp(arg: StructureND<Double>): ViktorStructureND = arg.f64Buffer.exp().asStructure()
+
+    override fun ln(arg: StructureND<Double>): ViktorStructureND = arg.f64Buffer.log().asStructure()
+}
+
+public fun ViktorNDField(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape)
\ No newline at end of file