diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for rc
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Bogdan Penkovsky (c) 2018
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Bogdan Penkovsky nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# Reservoir Computing
+
+Facilitating RC research
+
+## Features
+
+* [Nonlinear transient computing (NTC)](https://github.com/masterdezign/rc/tree/master/examples/NTC)
+
+
+## Getting Started
+
+Use [Stack](http://haskellstack.org).
+
+     $ git clone https://github.com/masterdezign/rc.git && cd rc
+     $ stack build --install-ghc
+
+### [Example 1](https://github.com/masterdezign/rc/tree/master/examples/NTC). NTC
+
+
+     $ stack exec ntc
+
+     Error: 3.1103181863915367e-3
+
+[Here](https://raw.githubusercontent.com/masterdezign/rc/master/examples/NTC/mg-prediction.png) is visualized prediction result.
+
+
+
+Great!
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/examples/NTC/Main.hs b/examples/NTC/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/NTC/Main.hs
@@ -0,0 +1,59 @@
+import           Numeric.LinearAlgebra
+import           System.Random ( mkStdGen )
+import           Learning ( nrmse )
+
+import           RC.NTC as RC
+
+-- Get training data
+takePast :: Int -> Matrix Double -> Matrix Double
+takePast horizon xs = xs ?? (All, Take (len - horizon))
+  where
+    len = cols xs
+
+-- Get teacher data
+takeFuture :: Int -> Matrix Double -> Matrix Double
+takeFuture horizon = (?? (All, Drop horizon))
+
+main = do
+  -- Load and transpose time series to predict
+  dta <- tr <$> loadMatrix "examples/data/mg.txt"
+
+  let splitRatio = 0.50  -- Train on 50% of data
+      total = cols dta
+      spl = round $ splitRatio * fromIntegral total
+      -- Split the data
+      train = dta ?? (All, Take spl)
+      validate = dta ?? (All, Drop spl)
+
+  -- Configure new NTC network
+  let p = RC.par0 { RC._inputWeightsRange = (0.1, 0.3) }
+      g = mkStdGen 1111
+      ntc = RC.new g p (1, 1000, 1)
+
+  -- 20 steps ahead prediction horizon
+  let horizon = 20
+
+  let train' = takePast horizon train  -- Past series
+      trainTeacher = takeFuture horizon train  -- Predicted series
+
+  let forgetPts = 300  -- Washout
+
+  -- Train
+  case RC.learn ntc forgetPts train' trainTeacher of
+    Left s -> error s
+    Right ntc' -> do
+      let target = (takeFuture horizon validate) ?? (All, Drop forgetPts)
+
+      -- Predict
+      case RC.predict ntc' forgetPts (takePast horizon validate) of
+        Left s -> error s
+        Right prediction -> do
+          let tgt' = flatten target
+              predic' = flatten prediction
+              err = nrmse tgt' predic'
+
+          putStrLn $ "Error: " ++ show err
+
+          let result = (tr target) ||| (tr prediction)
+
+          saveMatrix "examples/NTC/result.txt" "%g" result
diff --git a/rc.cabal b/rc.cabal
new file mode 100644
--- /dev/null
+++ b/rc.cabal
@@ -0,0 +1,79 @@
+-- This file has been generated from package.yaml by hpack version 0.20.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 32b8af1a3f4db71e5262f476ae36f22cd703e7dfd8e047f0c0d7b61b9ee1f3e8
+
+name:           rc
+version:        0.1.0.0
+synopsis:       Reservoir Computing, fast RNNs
+description:    Please see the README on Github at <https://github.com/masterdezign/rc#readme>
+category:       Machine Learning
+homepage:       https://github.com/masterdezign/rc#readme
+bug-reports:    https://github.com/masterdezign/rc/issues
+author:         Bogdan Penkovsky
+maintainer:     dev () penkovsky dot com
+copyright:      Bogdan Penkovsky
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    ChangeLog.md
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/masterdezign/rc
+
+library
+  hs-source-dirs:
+      rc
+  build-depends:
+      Learning
+    , base >=4.7 && <5
+    , dde ==0.0.0
+    , hmatrix >=0.18.0.0
+    , random
+    , vector
+  exposed-modules:
+      RC.Helpers
+      RC.NTC
+  other-modules:
+      Paths_rc
+  default-language: Haskell2010
+
+executable ntc
+  main-is: Main.hs
+  hs-source-dirs:
+      examples/NTC
+  build-depends:
+      Learning
+    , base >=4.7 && <5
+    , dde ==0.0.0
+    , hmatrix >=0.18.0.0
+    , random
+    , rc
+    , vector
+  other-modules:
+      Paths_rc
+  default-language: Haskell2010
+
+test-suite rc-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      Learning
+    , base >=4.7 && <5
+    , dde ==0.0.0
+    , hmatrix >=0.18.0.0
+    , random
+    , rc
+    , vector
+  other-modules:
+      Paths_rc
+  default-language: Haskell2010
diff --git a/rc/RC/Helpers.hs b/rc/RC/Helpers.hs
new file mode 100644
--- /dev/null
+++ b/rc/RC/Helpers.hs
@@ -0,0 +1,65 @@
+module RC.Helpers
+  ( addBiases
+  , randList
+  , randMatrix
+  , randSparse
+  , hsigmoid
+  ) where
+
+import           System.Random
+import           Data.List ( unfoldr )
+import qualified Numeric.LinearAlgebra as LA
+
+-- | Hard sigmoid
+hsigmoid :: (Fractional a, Ord a)
+         => (a, a, a)
+         -- ^ Vertical scaling, width, offset
+         -> a
+         -> a
+hsigmoid (β, width, offset) x = f
+  where
+    f | x < offset = 0.0
+      | x < width = β * (x - offset)
+      | otherwise = β * (width - offset)
+
+-- | Prepend a row of ones
+-- >>> addBiases $ (2><3) [20..26]
+-- (3><3)
+--  [  1.0,  1.0,  1.0
+--  , 20.0, 21.0, 22.0
+--  , 23.0, 24.0, 25.0 ]
+addBiases :: LA.Matrix Double -> LA.Matrix Double
+addBiases m = let no = LA.cols m
+                  m' = LA.konst 1.0 (1, no)
+              in m' LA.=== m
+
+-- | Random matrix with elements in the range of [minVal; maxVal]
+randMatrix
+  :: StdGen
+     -> (Int, Int)
+     -- ^ Number of rows and columns
+     -> (Double, Double)
+     -- ^ Minimal and maximal values
+     -> LA.Matrix Double
+randMatrix seed (rows', cols') (minVal, maxVal) = (LA.reshape cols'. LA.vector) xs
+  where
+    xs = f <$> randList (rows' * cols') seed
+    f x = (maxVal - minVal) * x + minVal
+
+-- | Random sparse matrix
+--
+-- NB: at the moment, the matrix is stored in memory as
+-- an ordinary (dense) matrix.
+randSparse g (rows', cols') (minVal, maxVal) connectivity =
+    LA.reshape cols' $ LA.vector xs
+  where
+    (g1, g2) = split g
+    rlist = randList (rows' * cols')
+    xs = zipWith f (rlist g1) (rlist g2)
+    f lv rv | lv < connectivity = (maxVal - minVal) * rv + minVal
+            | otherwise = 0.0
+
+randList :: (Random a, Floating a) => Int -> StdGen -> [a]
+randList n = take n. unfoldr (Just. random)
+{-# SPECIALISE randList :: Int -> StdGen -> [Float] #-}
+{-# SPECIALISE randList :: Int -> StdGen -> [Double] #-}
diff --git a/rc/RC/NTC.hs b/rc/RC/NTC.hs
new file mode 100644
--- /dev/null
+++ b/rc/RC/NTC.hs
@@ -0,0 +1,146 @@
+-- = Nonlinear transient computing
+--
+-- This module was developed as a part of author's PhD project:
+-- https://www.researchgate.net/project/Theory-and-Modeling-of-Complex-Nonlinear-Delay-Dynamics-Applied-to-Neuromorphic-Computing
+--
+
+{-# LANGUAGE BangPatterns #-}
+
+module RC.NTC
+  ( new
+  , learn
+  , predict
+  , par0
+  , NTCParameters (..)
+  , DDEModel.Par (..)
+  , DDEModel.BandpassFiltering (..)
+  ) where
+
+import           Numeric.LinearAlgebra
+import           System.Random ( StdGen
+                               , split
+                               )
+import qualified Data.Vector.Storable as V
+import qualified Learning
+import qualified Numeric.DDE as DDE
+import qualified Numeric.DDE.Model as DDEModel
+
+import qualified RC.Helpers as H
+
+-- | DDE reservoir abstraction
+newtype Reservoir = Reservoir { _transform :: Matrix Double -> Matrix Double }
+
+data NTCParameters = Par
+  { _preprocess :: Matrix Double -> Matrix Double
+    -- ^ Modify data before masking (e.g. compression)
+  , _inputWeightsRange :: (Double, Double)  -- ^ Input weights (mask) range
+  , _inputWeightsGenerator :: StdGen -> (Int, Int) -> (Double, Double) -> Matrix Double
+  , _postprocess :: Matrix Double -> Matrix Double
+  -- ^ Modify data before training or prediction (e.g. add biases)
+  , _reservoirModel :: DDEModel.Par
+  }
+
+data NTC = NTC
+  { _inputWeights :: Matrix Double
+  , _reservoir :: Reservoir
+  , _outputWeights :: Maybe (Matrix Double)
+  -- ^ Trainable part of NTC
+  , _par :: NTCParameters
+  }
+
+new
+  :: StdGen
+  -> NTCParameters
+  -> (Int, Int, Int)
+  -- ^ Input dimension, network nodes, and output dimension
+  -> NTC
+new g par (ind, nodes, out) =
+  let iwgen = _inputWeightsGenerator par
+      iw = iwgen g (nodes, ind) (_inputWeightsRange par)
+      ntc = NTC { _inputWeights = iw
+                , _reservoir = genReservoir (_reservoirModel par)
+                , _outputWeights = Nothing
+                , _par = par
+                }
+  in ntc
+
+-- | Default NTC parameters
+par0 :: NTCParameters
+par0 = Par
+  { _preprocess = id
+  , _inputWeightsGenerator = H.randMatrix
+  , _postprocess = H.addBiases  -- Usually `id` will work
+  , _inputWeightsRange = undefined  -- To be manually set, e.g. (-1, 1)
+  , _reservoirModel = DDEModel.RC { DDEModel._filt = filt'
+                                  , DDEModel._rho = 3.25
+                                  , DDEModel._fnl = H.hsigmoid (1.09375, 1.5, 0.0)
+                                  }
+  }
+  where
+    filt' = DDEModel.BandpassFiltering {
+              DDEModel._tau = 7.8125e-3
+            , DDEModel._theta = recip 0.34375
+            }
+
+genReservoir :: DDEModel.Par -> Reservoir
+genReservoir par = Reservoir _r
+  where
+    _r sample = unflatten response
+      where
+        flatten' = flatten. tr
+        unflatten = tr. reshape nodes
+
+        oversampling = 1 :: Int  -- No oversampling
+        detuning = 1.0 :: Double  -- Delay detuning factor, 1 = no detuning
+        nodes = rows sample
+        delaySamples = round $ detuning * fromIntegral (oversampling * nodes)
+
+        -- Matrix to timetrace
+        trace1 = flatten' sample
+
+        -- Duplicate the last element (DDE.integHeun2_2D consumes one extra input)
+        trace = trace1 V.++ V.singleton (V.last trace1)
+
+        tau = DDEModel._tau $ DDEModel._filt par
+        hStep = tau / 2
+
+        !(_, !response) = DDE.integHeun2_2D delaySamples hStep (DDEModel.rhs par) (DDE.Input trace)
+
+forwardPass :: NTC -> Matrix Double -> Matrix Double
+forwardPass NTC { _par = Par { _preprocess = prep, _postprocess = post }
+                , _inputWeights = iw
+                , _reservoir = Reservoir res
+                } sample =
+  let pipeline = post. res. (iw <>). prep
+  in pipeline sample
+
+-- | Offline NTC training
+learn
+  :: NTC
+  -> Int
+  -- ^ Discard the first N points
+  -> Matrix Double
+  -- ^ Input matrix of features rows and observations columns
+  -> Matrix Double
+  -- ^ Desired output matrix of observations columns
+  -> Either String NTC
+learn ntc forgetPts inp out = ntc'
+  where
+    state' = (forwardPass ntc inp) ?? (All, Drop forgetPts)
+    teacher' = out ?? (All, Drop forgetPts)
+    ntc' = case Learning.learn' state' teacher' of
+      Nothing -> Left "Cannot create a readout matrix"
+      w -> Right $ ntc { _outputWeights = w }
+
+predict :: NTC
+        -> Int
+        -> Matrix Double
+        -> Either String (Matrix Double)
+predict ntc@NTC { _outputWeights = ow
+                } forgetPts inp =
+  case ow of
+    Nothing -> Left "Please train the NTC first"
+    Just w -> let y = forwardPass ntc inp
+                  y2 = y ?? (All, Drop forgetPts)
+                  prediction = w <> y2
+              in Right prediction
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
