diff --git a/.gitignore b/.gitignore
index a1fc39c07..1e4a58980 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,9 @@
.gradle
/build/
-
-# Ignore Gradle GUI config
-gradle-app.setting
+.idea/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
-
-# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
-# gradle/wrapper/gradle-wrapper.properties
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 000000000..188aca7b9
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 000000000..9870be164
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/common/common_main.iml b/.idea/modules/common/common_main.iml
new file mode 100644
index 000000000..0e9be6f8b
--- /dev/null
+++ b/.idea/modules/common/common_main.iml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/common/common_test.iml b/.idea/modules/common/common_test.iml
new file mode 100644
index 000000000..672412fbd
--- /dev/null
+++ b/.idea/modules/common/common_test.iml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..94a25f7f4
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 000000000..fe07b921e
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,3 @@
+group = 'scientifik'
+version = '0.1-SNAPSHOT'
+
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644
index 000000000..bae2e09d7
--- /dev/null
+++ b/common/build.gradle
@@ -0,0 +1,25 @@
+buildscript {
+ ext.kotlin_version = '1.2.40'
+
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+description = "Platform-independent interfaces for kotlin maths"
+
+apply plugin: 'kotlin-platform-common'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
+ testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
+ testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
+}
+
diff --git a/common/src/main/kotlin/scientifik/kmath/operations/Algebra.kt b/common/src/main/kotlin/scientifik/kmath/operations/Algebra.kt
new file mode 100644
index 000000000..4b74cbc7a
--- /dev/null
+++ b/common/src/main/kotlin/scientifik/kmath/operations/Algebra.kt
@@ -0,0 +1,103 @@
+package scientifik.kmath.operations
+
+/**
+ * A general interface representing linear context of some kind.
+ * The context defines sum operation for its elements and multiplication by real value.
+ * One must note that in some cases context is a singleton class, but in some cases it
+ * works as a context for operations inside it.
+ *
+ * TODO do we need commutative context?
+ */
+interface Space {
+ /**
+ * Neutral element for sum operation
+ */
+ val zero: T
+
+ /**
+ * Addition operation for two context elements
+ */
+ fun add(a: T, b: T): T
+
+ /**
+ * Multiplication operation for context element and real number
+ */
+ fun multiply(a: T, k: Double): T
+
+ //Operation to be performed in this context
+ operator fun T.unaryMinus(): T = multiply(this, -1.0)
+
+ operator fun T.plus(b: T): T = add(this, b)
+ operator fun T.minus(b: T): T = add(this, -b)
+ operator fun T.times(k: Number) = multiply(this, k.toDouble())
+ operator fun T.div(k: Number) = multiply(this, 1.0 / k.toDouble())
+ operator fun Number.times(b: T) = b * this
+
+}
+
+/**
+ * The element of linear context
+ * @param S self type of the element. Needed for static type checking
+ */
+interface SpaceElement> {
+ /**
+ * The context this element belongs to
+ */
+ val context: Space
+
+ /**
+ * Self value. Needed for static type checking. Needed to avoid type erasure on JVM.
+ */
+ val self: S
+
+ operator fun plus(b: S): S = with(context) { self + b }
+ operator fun minus(b: S): S = with(context) { self - b }
+ operator fun times(k: Number): S = with(context) { self * k }
+ operator fun div(k: Number): S = with(context) { self / k }
+}
+
+/**
+ * The same as {@link Space} but with additional multiplication operation
+ */
+interface Ring : Space {
+ /**
+ * neutral operation for multiplication
+ */
+ val one: T
+
+ /**
+ * Multiplication for two field elements
+ */
+ fun multiply(a: T, b: T): T
+
+ operator fun T.times(b: T): T = multiply(this, b)
+
+}
+
+/**
+ * Ring element
+ */
+interface RingElement> : SpaceElement {
+ override val context: Ring
+
+ operator fun times(b: S): S = with(context) { self * b }
+}
+
+/**
+ * Four operations algebra
+ */
+interface Field : Ring {
+ fun divide(a: T, b: T): T
+
+ operator fun T.div(b: T): T = divide(this, b)
+ operator fun Double.div(b: T) = this * divide(one, b)
+}
+
+/**
+ * Field element
+ */
+interface FieldElement> : RingElement {
+ override val context: Field
+
+ operator fun div(b: S): S = with(context) { self / b }
+}
\ No newline at end of file
diff --git a/common/src/main/kotlin/scientifik/kmath/operations/Fields.kt b/common/src/main/kotlin/scientifik/kmath/operations/Fields.kt
new file mode 100644
index 000000000..40414879b
--- /dev/null
+++ b/common/src/main/kotlin/scientifik/kmath/operations/Fields.kt
@@ -0,0 +1,78 @@
+package scientifik.kmath.operations
+
+import kotlin.math.sqrt
+
+/**
+ * Field for real values
+ */
+object RealField : Field {
+ override val zero: Real = Real(0.0)
+ override fun add(a: Real, b: Real): Real = Real(a.value + b.value)
+ override val one: Real = Real(1.0)
+ override fun multiply(a: Real, b: Real): Real = Real(a.value * b.value)
+ override fun multiply(a: Real, k: Double): Real = Real(a.value * k)
+ override fun divide(a: Real, b: Real): Real = Real(a.value / b.value)
+}
+
+/**
+ * Real field element wrapping double
+ */
+class Real(val value: Double) : FieldElement, Number() {
+ override fun toByte(): Byte = value.toByte()
+ override fun toChar(): Char = value.toChar()
+ override fun toDouble(): Double = value
+ override fun toFloat(): Float = value.toFloat()
+ override fun toInt(): Int = value.toInt()
+ override fun toLong(): Long = value.toLong()
+ override fun toShort(): Short = value.toShort()
+
+ //values are dynamically calculated to save memory
+ override val self
+ get() = this
+ override val context
+ get() = RealField
+}
+
+/**
+ * A field for complex numbers
+ */
+object ComplexField : Field {
+ override val zero: Complex = Complex(0.0, 0.0)
+
+ override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im)
+
+ override fun multiply(a: Complex, k: Double): Complex = Complex(a.re * k, a.im * k)
+
+ override val one: Complex = Complex(1.0, 0.0)
+
+ override fun multiply(a: Complex, b: Complex): Complex = Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
+
+ override fun divide(a: Complex, b: Complex): Complex = Complex(a.re * b.re + a.im * b.im, a.re * b.im - a.im * b.re) / b.square
+
+}
+
+/**
+ * Complex number class
+ */
+data class Complex(val re: Double, val im: Double) : FieldElement {
+ override val self: Complex
+ get() = this
+ override val context: Field
+ get() = ComplexField
+
+ /**
+ * A complex conjugate
+ */
+ val conjugate: Complex
+ get() = Complex(re, -im)
+
+ val square: Double
+ get() = re * re + im * im
+
+ val module: Double
+ get() = sqrt(square)
+
+
+ //TODO is it convenient?
+ operator fun not() = conjugate
+}
\ No newline at end of file
diff --git a/common/src/main/kotlin/scientifik/kmath/structures/NDArray.kt b/common/src/main/kotlin/scientifik/kmath/structures/NDArray.kt
new file mode 100644
index 000000000..4ab01da56
--- /dev/null
+++ b/common/src/main/kotlin/scientifik/kmath/structures/NDArray.kt
@@ -0,0 +1,120 @@
+package scientifik.kmath.structures
+
+import scientifik.kmath.operations.Field
+import scientifik.kmath.operations.FieldElement
+import scientifik.kmath.operations.Real
+
+class ShapeMismatchException(val expected: List, val actual: List) : RuntimeException()
+
+/**
+ * Field for n-dimensional arrays.
+ * @param shape - the list of dimensions of the array
+ * @param elementField - operations field defined on individual array element
+ */
+abstract class NDField>(val shape: List, val elementField: Field) : Field> {
+ /**
+ * Create new instance of NDArray using field shape and given initializer
+ */
+ abstract fun produce(initializer: (List) -> T): NDArray
+
+ override val zero: NDArray
+ get() = produce { elementField.zero }
+
+ private fun checkShape(vararg arrays: NDArray) {
+ arrays.forEach {
+ if (shape != it.shape) {
+ throw ShapeMismatchException(shape, it.shape)
+ }
+ }
+ }
+
+ /**
+ * Element-by-element addition
+ */
+ override fun add(a: NDArray, b: NDArray): NDArray {
+ checkShape(a, b)
+ return produce { a[it] + b[it] }
+ }
+
+ /**
+ * Multiply all elements by cinstant
+ */
+ override fun multiply(a: NDArray, k: Double): NDArray {
+ checkShape(a)
+ return produce { a[it] * k }
+ }
+
+ override val one: NDArray
+ get() = produce { elementField.one }
+
+ /**
+ * Element-by-element multiplication
+ */
+ override fun multiply(a: NDArray, b: NDArray): NDArray {
+ checkShape(a)
+ return produce { a[it] * b[it] }
+ }
+
+ /**
+ * Element-by-element division
+ */
+ override fun divide(a: NDArray, b: NDArray): NDArray {
+ checkShape(a)
+ return produce { a[it] / b[it] }
+ }
+}
+
+
+interface NDArray> : FieldElement>, Iterable, T>> {
+
+ /**
+ * The list of dimensions of this NDArray
+ */
+ val shape: List
+ get() = (context as NDField).shape
+
+ /**
+ * The number of dimentsions for this array
+ */
+ val dimension: Int
+ get() = shape.size
+
+ /**
+ * Get the element with given indexes. If number of indexes is different from {@link dimension}, throws exception.
+ */
+ operator fun get(vararg index: Int): T
+
+ operator fun get(index: List): T {
+ return get(*index.toIntArray())
+ }
+
+ override operator fun iterator(): Iterator, T>> {
+ return iterateIndexes(shape).map { Pair(it, this[it]) }.iterator()
+ }
+
+ /**
+ * Generate new NDArray, using given transformation for each element
+ */
+ fun transform(action: (List, T) -> T): NDArray = (context as NDField).produce { action(it, this[it]) }
+
+ companion object {
+ /**
+ * Iterate over all indexes in the nd-shape
+ */
+ fun iterateIndexes(shape: List): Sequence> {
+ return if (shape.size == 1) {
+ (0 until shape[0]).asSequence().map { listOf(it) }
+ } else {
+ val tailShape = ArrayList(shape).apply { remove(0) }
+ val tailSequence: List> = iterateIndexes(tailShape).toList()
+ (0 until shape[0]).asSequence().map { firstIndex ->
+ //adding first element to each of provided index lists
+ tailSequence.map { listOf(firstIndex) + it }.asSequence()
+ }.flatten()
+ }
+ }
+ }
+}
+
+
+expect fun RealNDArray(shape: List, initializer: (List) -> Double): NDArray
\ No newline at end of file
diff --git a/jvm/build.gradle b/jvm/build.gradle
new file mode 100644
index 000000000..a8402b75c
--- /dev/null
+++ b/jvm/build.gradle
@@ -0,0 +1,33 @@
+buildscript {
+ ext.kotlin_version = '1.2.40'
+
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+
+apply plugin: 'kotlin-platform-jvm'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ expectedBy project(":common")
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+ testCompile "junit:junit:4.12"
+ testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
+ testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
+}
+
+compileKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+}
+compileTestKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+}
+sourceCompatibility = "1.8"
\ No newline at end of file
diff --git a/jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt b/jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt
new file mode 100644
index 000000000..3d00b79d5
--- /dev/null
+++ b/jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt
@@ -0,0 +1,64 @@
+package scientifik.kmath.structures
+
+import scientifik.kmath.operations.Field
+import scientifik.kmath.operations.Real
+import scientifik.kmath.operations.RealField
+import java.nio.DoubleBuffer
+
+private class RealNDField(shape: List) : NDField(shape, RealField) {
+
+ /**
+ * Strides for memory access
+ */
+ private val strides: List by lazy {
+ ArrayList(shape.size).apply {
+ var current = 1
+ shape.forEach{
+ current *=it
+ add(current)
+ }
+ }
+ }
+
+ fun offset(index: List): Int {
+ return index.mapIndexed { i, value ->
+ if (value < 0 || value >= shape[i]) {
+ throw RuntimeException("Index out of shape bounds: ($i,$value)")
+ }
+ value * strides[i]
+ }.sum()
+ }
+
+ val capacity: Int
+ get() = strides[shape.size - 1]
+
+
+ override fun produce(initializer: (List) -> Real): NDArray {
+ //TODO use sparse arrays for large capacities
+ val buffer = DoubleBuffer.allocate(capacity)
+ NDArray.iterateIndexes(shape).forEach {
+ buffer.put(offset(it), initializer(it).value)
+ }
+ return RealNDArray(buffer)
+ }
+
+ inner class RealNDArray(val data: DoubleBuffer) : NDArray {
+
+ override val context: Field>
+ get() = this@RealNDField
+
+ override fun get(vararg index: Int): Real {
+ return Real(data.get(offset(index.asList())))
+ }
+
+ override val self: NDArray
+ get() = this
+ }
+
+}
+
+
+actual fun RealNDArray(shape: List, initializer: (List) -> Double): NDArray {
+ //TODO cache fields?
+ return RealNDField(shape).produce { Real(initializer(it)) }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 000000000..a60b00349
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,4 @@
+rootProject.name = 'kmath'
+include 'common'
+include 'jvm'
+