packages feed

hasktorch-indef (empty) → 0.0.1.0

raw patch · 76 files changed

+15152/−0 lines, 76 filesdep +QuickCheckdep +backpropdep +base

Dependencies added: QuickCheck, backprop, base, containers, cuda, deepseq, dimensions, ghc-typelits-natnormalise, hasktorch-ffi-th, hasktorch-indef, hasktorch-signatures, hasktorch-signatures-partial, hasktorch-signatures-support, hasktorch-types-th, hasktorch-types-thc, hspec, managed, mtl, safe-exceptions, singletons, text, transformers, vector

Files

+ hasktorch-indef.cabal view
@@ -0,0 +1,243 @@+cabal-version: 2.2+-- * * * * * * * * * * * * WARNING * * * * * * * * * * * *+-- This file has been AUTO-GENERATED by dhall-to-cabal.+--+-- Do not edit it by hand, because your changes will be over-written!+--+-- Instead, edit the source Dhall file, namely+-- 'indef/hasktorch-indef.dhall', and re-generate this file by running+-- 'dhall-to-cabal -- indef/hasktorch-indef.dhall > hasktorch-indef.cabal'.+-- * * * * * * * * * * * * WARNING * * * * * * * * * * * *+name: hasktorch-indef+version: 0.0.1.0+license: BSD-3-Clause+maintainer: Sam Stites <fnz@fgvgrf.vb>, Austin Huang <nhfgvau@nyhz.zvg.rqh> - cipher:ROT13+author: Hasktorch dev team+homepage: https://github.com/hasktorch/hasktorch#readme+bug-reports: https://github.com/hasktorch/hasktorch/issues+synopsis: Core Hasktorch abstractions wrapping FFI bindings+description:+    The hasktorch-indef package constitutes the main user API for hasktorch. It uses backpack signatures to generically glue low-level FFI bindings to a high-level interface.+category: Tensors, Machine Learning, AI+build-type: Simple++source-repository head+    type: git+    location: https://github.com/hasktorch/hasktorch++flag cuda+    description:+        build with THC support+    default: False++library+    exposed-modules:+        Torch.Indef.Index+        Torch.Indef.Mask+        Torch.Indef.Types+        Torch.Indef.Storage+        Torch.Indef.Storage.Copy+        Torch.Indef.Dynamic.Print+        Torch.Indef.Dynamic.Tensor+        Torch.Indef.Dynamic.Tensor.Copy+        Torch.Indef.Dynamic.Tensor.Index+        Torch.Indef.Dynamic.Tensor.Masked+        Torch.Indef.Dynamic.Tensor.Math+        Torch.Indef.Dynamic.Tensor.Math.Compare+        Torch.Indef.Dynamic.Tensor.Math.CompareT+        Torch.Indef.Dynamic.Tensor.Math.Pairwise+        Torch.Indef.Dynamic.Tensor.Math.Pointwise+        Torch.Indef.Dynamic.Tensor.Math.Reduce+        Torch.Indef.Dynamic.Tensor.Math.Scan+        Torch.Indef.Dynamic.Tensor.Mode+        Torch.Indef.Dynamic.Tensor.ScatterGather+        Torch.Indef.Dynamic.Tensor.Sort+        Torch.Indef.Dynamic.Tensor.TopK+        Torch.Indef.Static.Tensor+        Torch.Indef.Static.Tensor.Copy+        Torch.Indef.Static.Tensor.Index+        Torch.Indef.Static.Tensor.Masked+        Torch.Indef.Static.Tensor.Math+        Torch.Indef.Static.Tensor.Math.Compare+        Torch.Indef.Static.Tensor.Math.CompareT+        Torch.Indef.Static.Tensor.Math.Pairwise+        Torch.Indef.Static.Tensor.Math.Pointwise+        Torch.Indef.Static.Tensor.Math.Reduce+        Torch.Indef.Static.Tensor.Math.Scan+        Torch.Indef.Static.Tensor.Mode+        Torch.Indef.Static.Tensor.ScatterGather+        Torch.Indef.Static.Tensor.Sort+        Torch.Indef.Static.Tensor.TopK+        Torch.Indef.Static.Tensor.Math.Pointwise.Signed+        Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed+        Torch.Indef.Dynamic.Tensor.Math.Blas+        Torch.Indef.Dynamic.Tensor.Math.Floating+        Torch.Indef.Dynamic.Tensor.Math.Lapack+        Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating+        Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating+        Torch.Indef.Dynamic.Tensor.Random.TH+        Torch.Indef.Dynamic.Tensor.Random.THC+        Torch.Indef.Dynamic.Tensor.Math.Random.TH+        Torch.Indef.Static.Tensor.Math.Blas+        Torch.Indef.Static.Tensor.Math.Floating+        Torch.Indef.Static.Tensor.Math.Lapack+        Torch.Indef.Static.Tensor.Math.Pointwise.Floating+        Torch.Indef.Static.Tensor.Math.Reduce.Floating+        Torch.Indef.Static.Tensor.Random.TH+        Torch.Indef.Static.Tensor.Random.THC+        Torch.Indef.Static.Tensor.Math.Random.TH+        Torch.Indef.Dynamic.NN+        Torch.Indef.Dynamic.NN.Activation+        Torch.Indef.Dynamic.NN.Pooling+        Torch.Indef.Dynamic.NN.Criterion+        Torch.Indef.Static.NN+        Torch.Indef.Static.NN.Activation+        Torch.Indef.Static.NN.Backprop+        Torch.Indef.Static.NN.Conv1d+        Torch.Indef.Static.NN.Conv2d+        Torch.Indef.Static.NN.Criterion+        Torch.Indef.Static.NN.Layers+        Torch.Indef.Static.NN.Linear+        Torch.Indef.Static.NN.Math+        Torch.Indef.Static.NN.Padding+        Torch.Indef.Static.NN.Pooling+        Torch.Indef.Static.NN.Sampling+    hs-source-dirs: src+    other-modules:+        Torch.Indef.Internal+    default-language: Haskell2010+    default-extensions: LambdaCase DataKinds TypeFamilies+                        TypeSynonymInstances ScopedTypeVariables FlexibleContexts CPP+    build-depends:+        base (==4.7 || >4.7) && <5,+        backprop ==0.2.5 || >0.2.5,+        containers ==0.5.10 || >0.5.10,+        deepseq ==1.3.0 || >1.3.0,+        dimensions ==1.0 || >1.0,+        hasktorch-signatures (==0.0.1 || >0.0.1) && <0.0.2,+        hasktorch-signatures-support (==0.0.1 || >0.0.1) && <0.0.2,+        hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,+        hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,+        managed (==1.0.0 || >1.0.0) && <1.1,+        mtl ==2.2.2 || >2.2.2,+        safe-exceptions ==0.1.0 || >0.1.0,+        singletons ==2.2 || >2.2,+        ghc-typelits-natnormalise -any,+        transformers ==0.5.5 || >0.5.5,+        text ==1.2.2 || >1.2.2,+        vector ==0.12.0 || >0.12.0+    +    if flag(cuda)+        cpp-options: -DCUDA -DHASKTORCH_INTERNAL_CUDA+        build-depends:+            hasktorch-types-thc (==0.0.1 || >0.0.1) && <0.0.2,+            cuda -any+    else++library hasktorch-indef-floating+    reexported-modules: Torch.Indef.Index,+                        Torch.Indef.Mask,+                        Torch.Indef.Types,+                        Torch.Indef.Storage,+                        Torch.Indef.Storage.Copy,+                        Torch.Indef.Dynamic.Print,+                        Torch.Indef.Dynamic.Tensor,+                        Torch.Indef.Dynamic.Tensor.Copy,+                        Torch.Indef.Dynamic.Tensor.Index,+                        Torch.Indef.Dynamic.Tensor.Masked,+                        Torch.Indef.Dynamic.Tensor.Math,+                        Torch.Indef.Dynamic.Tensor.Math.Compare,+                        Torch.Indef.Dynamic.Tensor.Math.CompareT,+                        Torch.Indef.Dynamic.Tensor.Math.Pairwise,+                        Torch.Indef.Dynamic.Tensor.Math.Pointwise,+                        Torch.Indef.Dynamic.Tensor.Math.Reduce,+                        Torch.Indef.Dynamic.Tensor.Math.Scan,+                        Torch.Indef.Dynamic.Tensor.Mode,+                        Torch.Indef.Dynamic.Tensor.ScatterGather,+                        Torch.Indef.Dynamic.Tensor.Sort,+                        Torch.Indef.Dynamic.Tensor.TopK,+                        Torch.Indef.Static.Tensor,+                        Torch.Indef.Static.Tensor.Copy,+                        Torch.Indef.Static.Tensor.Index,+                        Torch.Indef.Static.Tensor.Masked,+                        Torch.Indef.Static.Tensor.Math,+                        Torch.Indef.Static.Tensor.Math.Compare,+                        Torch.Indef.Static.Tensor.Math.CompareT,+                        Torch.Indef.Static.Tensor.Math.Pairwise,+                        Torch.Indef.Static.Tensor.Math.Pointwise,+                        Torch.Indef.Static.Tensor.Math.Reduce,+                        Torch.Indef.Static.Tensor.Math.Scan,+                        Torch.Indef.Static.Tensor.Mode,+                        Torch.Indef.Static.Tensor.ScatterGather,+                        Torch.Indef.Static.Tensor.Sort,+                        Torch.Indef.Static.Tensor.TopK,+                        Torch.Indef.Static.Tensor.Math.Pointwise.Signed,+                        Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed,+                        Torch.Indef.Dynamic.Tensor.Math.Blas,+                        Torch.Indef.Dynamic.Tensor.Math.Floating,+                        Torch.Indef.Dynamic.Tensor.Math.Lapack,+                        Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating,+                        Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating,+                        Torch.Indef.Dynamic.Tensor.Random.TH,+                        Torch.Indef.Dynamic.Tensor.Random.THC,+                        Torch.Indef.Dynamic.Tensor.Math.Random.TH,+                        Torch.Indef.Static.Tensor.Math.Blas,+                        Torch.Indef.Static.Tensor.Math.Floating,+                        Torch.Indef.Static.Tensor.Math.Lapack,+                        Torch.Indef.Static.Tensor.Math.Pointwise.Floating,+                        Torch.Indef.Static.Tensor.Math.Reduce.Floating,+                        Torch.Indef.Static.Tensor.Random.TH,+                        Torch.Indef.Static.Tensor.Random.THC,+                        Torch.Indef.Static.Tensor.Math.Random.TH,+                        Torch.Indef.Dynamic.NN,+                        Torch.Indef.Dynamic.NN.Activation,+                        Torch.Indef.Dynamic.NN.Pooling,+                        Torch.Indef.Dynamic.NN.Criterion,+                        Torch.Indef.Static.NN,+                        Torch.Indef.Static.NN.Activation,+                        Torch.Indef.Static.NN.Backprop,+                        Torch.Indef.Static.NN.Conv1d,+                        Torch.Indef.Static.NN.Conv2d,+                        Torch.Indef.Static.NN.Criterion,+                        Torch.Indef.Static.NN.Layers,+                        Torch.Indef.Static.NN.Linear,+                        Torch.Indef.Static.NN.Math,+                        Torch.Indef.Static.NN.Padding,+                        Torch.Indef.Static.NN.Pooling,+                        Torch.Indef.Static.NN.Sampling,+                        Torch.Undefined.Tensor.Math.Random.TH,+                        Torch.Undefined.Tensor.Random.TH,+                        Torch.Undefined.Tensor.Random.THC+    default-language: Haskell2010+    build-depends:+        base (==4.7 || >4.7) && <5,+        hasktorch-indef -any,+        hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2++test-suite spec-double-th+    type: exitcode-stdio-1.0+    main-is: Spec.hs+    hs-source-dirs: tests+    other-modules:+        Torch.Indef.StorageSpec+        Torch.Indef.Dynamic.TensorSpec+        Torch.Indef.Static.TensorSpec+    default-language: Haskell2010+    default-extensions: LambdaCase DataKinds TypeFamilies+                        TypeSynonymInstances ScopedTypeVariables FlexibleContexts CPP+    build-depends:+        QuickCheck ==2.11 || >2.11,+        backprop ==0.2.5 || >0.2.5,+        base (==4.7 || >4.7) && <5,+        dimensions ==1.0 || >1.0,+        ghc-typelits-natnormalise -any,+        hasktorch-indef-floating -any,+        hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,+        hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,+        hspec ==2.4.4 || >2.4.4,+        mtl ==2.2.2 || >2.2.2,+        singletons ==2.2 || >2.2,+        text ==1.2.2 || >1.2.2,+        transformers ==0.5.5 || >0.5.5+    mixins: hasktorch-indef-floating requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Double, Torch.Sig.Storage as Torch.FFI.TH.Double.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Double.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Double.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Double.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Double.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Double.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.TH.Double.TensorLapack, Torch.Sig.NN as Torch.FFI.TH.NN.Double, Torch.Sig.Types.NN as Torch.Types.TH, Torch.Sig.Tensor.Math.Random.TH as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Random.TH as Torch.FFI.TH.Double.TensorRandom, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Tensor.Random.THC)+
+ src/Torch/Indef/Dynamic/NN.hs view
@@ -0,0 +1,1253 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.NN+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- NN backpack API which is _not recommended to be used directly_. This package+-- is just a wrapper around the backpack signatures of Torch's C-based NN+-- library.+--+-- Instead, use 'Torch.Indef.Static.NN' which includes an AD abstraction,+-- simple forward- and backward- functions, and staticly-typed dimension-level+-- checking.+--+-- This library will, over time, iterate into type-safe code -- but for the+-- moment we hoist the safety into the dependent types, which is faster to+-- iterate with and is semantically clearer for development (the errors take a+-- bit of getting used to).+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.NN+  ( module X+  , _abs_updateOutput+  , _abs_updateGradInput+  , _gatedLinear_updateOutput+  , _gatedLinear_updateGradInput+  , _hardTanh_updateOutput+  , _hardTanh_updateGradInput+  , _im2Col_updateOutput+  , _im2Col_updateGradInput+  , _col2Im_updateOutput+  , _col2Im_updateGradInput+  , _gRUFused_updateOutput+  , _gRUFused_updateGradInput+  , _lSTMFused_updateOutput+  , _lSTMFused_updateGradInput+  , _logSigmoid_updateOutput+  , _logSigmoid_updateGradInput+  , _logSoftMax_updateOutput+  , _logSoftMax_updateGradInput+  , _sigmoid_updateOutput+  , _sigmoid_updateGradInput+  , _softMax_updateOutput+  , _softMax_updateGradInput+  , _softPlus_updateOutput+  , _softPlus_updateGradInput+  , _softShrink_updateOutput+  , _softShrink_updateGradInput+  , _sparseLinear_updateOutput+  , _sparseLinear_accGradParameters+  , _sparseLinear_zeroGradParameters+  , _sparseLinear_updateParameters+  , _sparseLinear_legacyUpdateOutput+  , _sparseLinear_legacyAccGradParameters+  , _sqrt_updateOutput+  , _sqrt_updateGradInput+  , _square_updateOutput+  , _square_updateGradInput+  , _tanh_updateOutput+  , _tanh_updateGradInput+  , _temporalConvolution_updateOutput+  , _temporalConvolution_updateGradInput+  , _temporalConvolution_accGradParameters+  , _temporalRowConvolution_updateOutput+  , _temporalRowConvolution_updateGradInput+  , _temporalRowConvolution_accGradParameters+  , _temporalUpSamplingNearest_updateOutput+  , _temporalUpSamplingNearest_updateGradInput+  , _temporalUpSamplingLinear_updateOutput+  , _temporalUpSamplingLinear_updateGradInput+  , _batchNormalization_updateOutput+  , _batchNormalization_backward++  -- start to clean up conv2d+  , spatialConvolutionMM_updateOutput+  , _spatialConvolutionMM_updateOutput++  , _spatialConvolutionMM_updateGradInput+  , _spatialConvolutionMM_accGradParameters+  , _spatialConvolutionLocal_updateOutput+  , _spatialConvolutionLocal_updateGradInput+  , _spatialConvolutionLocal_accGradParameters+  , _spatialFullConvolution_updateOutput+  , _spatialFullConvolution_updateGradInput+  , _spatialFullConvolution_accGradParameters+  , _spatialDilatedConvolution_updateOutput+  , _spatialDilatedConvolution_updateGradInput+  , _spatialDilatedConvolution_accGradParameters+  , _spatialFullDilatedConvolution_updateOutput+  , _spatialFullDilatedConvolution_updateGradInput+  , _spatialFullDilatedConvolution_accGradParameters+  , _spatialSubSampling_updateOutput+  , _spatialSubSampling_updateGradInput+  , _spatialSubSampling_accGradParameters+  , _spatialUpSamplingNearest_updateOutput+  , _spatialUpSamplingNearest_updateGradInput+  , _spatialUpSamplingBilinear_updateOutput+  , _spatialUpSamplingBilinear_updateGradInput+  , _spatialGridSamplerBilinear_updateOutput+  , _spatialGridSamplerBilinear_updateGradInput+  , _volumetricGridSamplerBilinear_updateOutput+  , _volumetricGridSamplerBilinear_updateGradInput+  , _volumetricConvolution_updateOutput+  , _volumetricConvolution_updateGradInput+  , _volumetricConvolution_accGradParameters+  , _volumetricFullConvolution_updateOutput+  , _volumetricFullConvolution_updateGradInput+  , _volumetricFullConvolution_accGradParameters+  , _volumetricDilatedConvolution_updateOutput+  , _volumetricDilatedConvolution_updateGradInput+  , _volumetricDilatedConvolution_accGradParameters+  , _volumetricFullDilatedConvolution_updateOutput+  , _volumetricFullDilatedConvolution_updateGradInput+  , _volumetricFullDilatedConvolution_accGradParameters+  , _spatialReflectionPadding_updateOutput+  , _spatialReflectionPadding_updateGradInput+  , _spatialReplicationPadding_updateOutput+  , _spatialReplicationPadding_updateGradInput+  , _volumetricReplicationPadding_updateOutput+  , _volumetricReplicationPadding_updateGradInput+  , _volumetricUpSamplingNearest_updateOutput+  , _volumetricUpSamplingNearest_updateGradInput+  , _volumetricUpSamplingTrilinear_updateOutput+  , _volumetricUpSamplingTrilinear_updateGradInput+  , _temporalReflectionPadding_updateOutput+  , _temporalReflectionPadding_updateGradInput+  , _temporalReplicationPadding_updateOutput+  , _temporalReplicationPadding_updateGradInput+  ) where+++import Foreign.C.Types+import Control.Monad.Managed+import Torch.Sig.Types.NN+import Torch.Indef.Dynamic.Tensor -- (empty, new)+import Torch.Indef.Dynamic.NN.Activation as X+import Torch.Indef.Dynamic.NN.Pooling as X+import qualified Torch.Sig.NN as Sig++import Torch.Indef.Types++-- -- | indexLinear forward pass+-- --+-- -- FIXME: reintroduce these+-- _indexLinear_updateOutput+--   :: IndexDynamic+--   -> Integer+--   -> Dynamic+--   -> IndexDynamic+--   -> IndexDynamic+--   -> Dynamic+--   -> Dynamic+--   -> Dynamic+--   -> Dynamic+--   -> Int+--   -> IO ()+-- _indexLinear_updateOutput i0 l t0 i1 i2 t1 t2 t3 t4 i = undefined+  -- Sig.c_IndexLinear_updateOutput++-- c_IndexLinear_accGradParameters :: IndexDynamic -> CLLong -> Dynamic -> IndexDynamic -> IndexDynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> CDouble -> CDouble -> IO ()+-- c_IndexLinear_accUpdateGradParameters :: IndexDynamic -> CLLong -> Dynamic -> IndexDynamic -> IndexDynamic -> Dynamic -> Dynamic -> Dynamic -> CDouble -> CDouble -> IO ()+-- c_IndexLinear_updateParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> IndexDynamic -> CLLong -> CDouble -> CDouble -> IO ()++-- c_LookupTable_accGradParameters :: Ptr CIndexTensor -> Ptr CDoubleTensor -> Ptr CDoubleTensor -> Ptr CIndexTensor -> Ptr CIndexTensor -> Ptr CIndexTensor -> CBool -> CInt -> CDouble -> IO ()+-- c_LookupTable_renorm :: Ptr CIndexTensor -> Ptr CDoubleTensor -> CDouble -> CDouble -> IO ()++-- | abs forward+_abs_updateOutput :: Dynamic -> Dynamic -> IO ()+_abs_updateOutput t0 t1 = with2DynamicState t0 t1 $ \s' t0' t1' ->+  Sig.c_Abs_updateOutput s' t0' t1'++-- | abs backward+_abs_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IO ()+_abs_updateGradInput t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_Abs_updateGradInput s' t0' t1' t2'++_gatedLinear_updateOutput     :: Dynamic -> Dynamic -> Int -> IO ()+-- | gatedLinear backward-update (updates the layer and bias tensors)+_gatedLinear_updateGradInput  :: Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | hardTanh forward pass (updates the output tensor)+_hardTanh_updateOutput        :: Dynamic -> Dynamic -> Double -> Double -> Bool -> IO ()+-- | hardTanh backward-update (updates the layer and bias tensors)+_hardTanh_updateGradInput     :: Dynamic -> Dynamic -> Dynamic -> Double -> Double -> Bool -> IO ()+-- | im2Col forward pass (updates the output tensor)+_im2Col_updateOutput          :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | im2Col backward-update (updates the layer and bias tensors)+_im2Col_updateGradInput       :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()++-- | col2Im forward pass (updates the output tensor)+_col2Im_updateOutput+  :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_col2Im_updateOutput t0 t1 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Sig.c_Col2Im_updateOutput s' t0' t1'+      (fromIntegral a0)+      (fromIntegral a1)+      (fromIntegral a2)+      (fromIntegral a3)+      (fromIntegral a4)+      (fromIntegral a5)+      (fromIntegral a6)+      (fromIntegral a7)+      (fromIntegral a8)+      (fromIntegral a9)+++-- | col2Im backward-update (updates the layer and bias tensors)+_col2Im_updateGradInput :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_col2Im_updateGradInput t0 t1 a0 a1 a2 a3 a4 a5 a6 a7 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Sig.c_Col2Im_updateGradInput s' t0' t1'+      (fromIntegral a0)+      (fromIntegral a1)+      (fromIntegral a2)+      (fromIntegral a3)+      (fromIntegral a4)+      (fromIntegral a5)+      (fromIntegral a6)+      (fromIntegral a7)+++-- | gRUFused forward pass (updates the output tensor)+_gRUFused_updateOutput        :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | gRUFused backward-update (updates the layer and bias tensors)+_gRUFused_updateGradInput     :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | lSTMFused forward pass (updates the output tensor)+_lSTMFused_updateOutput       :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | lSTMFused backward-update (updates the layer and bias tensors)+_lSTMFused_updateGradInput    :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | logSigmoid forward pass (updates the output tensor)+_logSigmoid_updateOutput      :: Dynamic -> Dynamic -> Dynamic -> IO ()+-- | logSigmoid backward-update (updates the layer and bias tensors)+_logSigmoid_updateGradInput   :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | logSoftMax forward pass (updates the output tensor)+_logSoftMax_updateOutput      :: Dynamic -> Dynamic -> Integer -> IO ()+-- | logSoftMax backward-update (updates the layer and bias tensors)+_logSoftMax_updateGradInput   :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Integer -> IO ()++_sigmoid_updateOutput     :: Dynamic -> Dynamic -> IO ()+-- | sigmoid backward-update (updates the layer and bias tensors)+_sigmoid_updateGradInput  :: Dynamic -> Dynamic -> Dynamic -> IO ()++-- | softMax forward pass (updates the output tensor)+_softMax_updateOutput       :: Dynamic -> Dynamic -> Integer -> IO ()+-- | softMax backward-update (updates the layer and bias tensors)+_softMax_updateGradInput    :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Integer -> IO ()++-- | softPlus forward pass (updates the output tensor)+_softPlus_updateOutput      :: Dynamic -> Dynamic -> Double -> Double -> IO ()+-- | softPlus backward-update (updates the layer and bias tensors)+_softPlus_updateGradInput   :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> Double -> IO ()+-- | softShrink forward pass (updates the output tensor)+_softShrink_updateOutput    :: Dynamic -> Dynamic -> Double -> IO ()+-- | softShrink backward-update (updates the layer and bias tensors)+_softShrink_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Double -> IO ()+-- | sparseLinear forward pass (updates the output tensor)+_sparseLinear_updateOutput             :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | sparseLinear backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_sparseLinear_accGradParameters        :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> Double -> IO ()+-- | sparseLinear zeroGradParameters+_sparseLinear_zeroGradParameters       :: Dynamic -> Dynamic -> Dynamic -> IO ()+-- | sparseLinear updateParameters+_sparseLinear_updateParameters         :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> IO ()+-- | sparseLinear legacyUpdateOutput+_sparseLinear_legacyUpdateOutput       :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | sparseLinear legacyAccGradParameters+_sparseLinear_legacyAccGradParameters  :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> Double -> IO ()+-- | sqrt forward pass (updates the output tensor)+_sqrt_updateOutput         :: Dynamic -> Dynamic -> Double -> IO ()+-- | sqrt backward-update (updates the layer and bias tensors)+_sqrt_updateGradInput      :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- | square forward pass (updates the output tensor)+_square_updateOutput       :: Dynamic -> Dynamic -> IO ()+-- | square backward-update (updates the layer and bias tensors)+_square_updateGradInput    :: Dynamic -> Dynamic -> Dynamic -> IO ()+-- | tanh forward pass (updates the output tensor)+_tanh_updateOutput         :: Dynamic -> Dynamic -> IO ()+-- | tanh backward-update (updates the layer and bias tensors)+_tanh_updateGradInput      :: Dynamic -> Dynamic -> Dynamic -> IO ()++-- | temporalConvolution forward pass (updates the output tensor)+_temporalConvolution_updateOutput+  :: Dynamic     -- ^ input+  -> Dynamic     -- ^ output -- this is the mutated return value+  -> Dynamic     -- ^ 2d weight tensor+  -> Dynamic     -- ^ 1d bias tensor+  -> Int         -- ^ kernel width+  -> Int         -- ^ step size+  -> Int         -- ^ feature size+  -> Int         -- ^ output size+  -> IO ()+_temporalConvolution_updateOutput t0 t1 t2 t3 i0 i1 i2 i3 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_  t2' t3' ->+      Sig.c_TemporalConvolution_updateOutput s' t0' t1' t2' t3'+        (fromIntegral i0) (fromIntegral i1)+        (fromIntegral i2) (fromIntegral i3)++-- | temporalConvolution backward-update (updates the layer and bias tensors)+_temporalConvolution_updateGradInput+  :: Dynamic     -- ^ input+  -> Dynamic     -- ^ grad output+  -> Dynamic     -- ^ grad input -- this is the mutated return value+  -> Dynamic     -- ^ weights+  -> Int         -- ^ kernel width+  -> Int         -- ^ step size+  -> IO ()+_temporalConvolution_updateGradInput t0 t1 t2 t3 i0 i1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_  t2' t3' ->+      Sig.c_TemporalConvolution_updateGradInput s' t0' t1' t2' t3'+        (fromIntegral i0) (fromIntegral i1)+++-- | temporalConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_temporalConvolution_accGradParameters+  :: Dynamic   -- ^ input+  -> Dynamic   -- ^ grad output+  -> Dynamic   -- ^ grad weight -- this is a mutated argument and torch will accumulate this gradient+  -> Dynamic   -- ^ grad bias -- this is a mutated argument and torch will accumulate this gradient+  -> Int       -- ^ kernel width+  -> Int       -- ^ step size+  -> Double    -- ^ scale+  -> IO ()+_temporalConvolution_accGradParameters t0 t1 t2 t3 i0 i1 scale =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_  t2' t3' ->+      Sig.c_TemporalConvolution_accGradParameters s' t0' t1' t2' t3'+        (fromIntegral i0) (fromIntegral i1)+        (realToFrac scale)++-- | temporalRowConvolution forward pass (updates the output tensor)+_temporalRowConvolution_updateOutput                :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Bool -> IO ()+-- | temporalRowConvolution backward-update (updates the layer and bias tensors)+_temporalRowConvolution_updateGradInput             :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Bool -> IO ()+-- | temporalRowConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_temporalRowConvolution_accGradParameters           :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Bool -> Double -> IO ()+-- | temporalUpSamplingNearest forward pass (updates the output tensor)+_temporalUpSamplingNearest_updateOutput             :: Dynamic -> Dynamic -> Int -> IO ()+-- | temporalUpSamplingNearest backward-update (updates the layer and bias tensors)+_temporalUpSamplingNearest_updateGradInput          :: Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | temporalUpSamplingLinear forward pass (updates the output tensor)+_temporalUpSamplingLinear_updateOutput              :: Dynamic -> Dynamic -> Int -> IO ()+-- | temporalUpSamplingLinear backward-update (updates the layer and bias tensors)+_temporalUpSamplingLinear_updateGradInput           :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | batchNormalization forward pass (updates the output tensor)+_batchNormalization_updateOutput                    :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Double -> Double -> IO ()+-- | batchNormalization backward+_batchNormalization_backward                        :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Double -> Double -> IO ()++-- | spatialConvolutionMM forward pass+spatialConvolutionMM_updateOutput+  :: Dynamic    -- ^ input+  -> Dynamic    -- ^ 3D weight tensor (connTable:size(1) x kH x kW)+  -> Dynamic    -- ^ 1D bias tensor (nOutputPlane)+  -> (Int, Int) -- ^ (kW, kH) kernel height and width+  -> (Int, Int) -- ^ (dW, dH) step of the convolution in width and height dimensions. C-default is 1 for both.+  -> (Int, Int) -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used. C-default is 0 for both.+  -> IO Dynamic -- ^ output+spatialConvolutionMM_updateOutput inp weight bias (kW, kH) (dW, dH) (pW, pH) = do+  -- these are temporary placeholders and do not require dimensions as internal torch code will resize and fill them. See:+  -- https://github.com/zdevito/ATen/blob/682cb389db5a318539ff03f031bf896a43a71b13/aten/src/THCUNN/generic/SpatialConvolutionMM.cu#L141+  --+  -- TODO: someone needs to verify that this is all above-board and we aren't missing out on some optimization tricks.+  let columns = empty   -- temporary columns+  let ones    = empty   -- buffer of ones for bias accumulation++  -- This one as well:+  let out     = empty   -- output+  _spatialConvolutionMM_updateOutput inp out weight bias columns ones (kW, kH) (dW, dH) (pW, pH)++  pure out++-- | spatialConvolutionMM forward pass+_spatialConvolutionMM_updateOutput+  :: Dynamic    -- ^ input++  -> Dynamic    -- ^ output++  -> Dynamic    -- ^ 3D weight tensor (connTable:size(1) x kH x kW)+  -> Dynamic    -- ^ 1D bias tensor (nOutputPlane)++  -> Dynamic    -- ^ BUFFER: temporary columns+  -> Dynamic    -- ^ BUFFER: buffer of ones for bias accumulation++  -> (Int, Int) -- ^ (kW, kH) kernel height and width+  -> (Int, Int) -- ^ (dW, dH) step of the convolution in width and height dimensions. C-default is 1 for both.+  -> (Int, Int) -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used. C-default is 0 for both.+  -> IO ()+_spatialConvolutionMM_updateOutput inp out weight bias columns ones (kW, kH) (dW, dH) (pW, pH) = do+  with3DynamicState inp out weight $ \s' inp' out' weight' ->+   with3DynamicState bias columns ones $ \_ bias' columns' ones' ->+    Sig.c_SpatialConvolutionMM_updateOutput s' inp' out' weight' bias' columns' ones'+      (fromIntegral kW) (fromIntegral kH)+      (fromIntegral dW) (fromIntegral dH)+      (fromIntegral pW) (fromIntegral pH)++-- | spatialConvolutionMM backward-update (updates the layer and bias tensors)+_spatialConvolutionMM_updateGradInput+  :: Dynamic    -- ^ input+  -> Dynamic    -- ^ gradOutput+  -> Dynamic    -- ^ gradInput+  -> Dynamic    -- ^ weight+  -> Dynamic    -- ^ columns+  -> Dynamic    -- ^ ones+  -> (Int, Int) -- ^ (kW, kH) kernel height and width+  -> (Int, Int) -- ^ (dW, dH) step of the convolution in width and height dimensions+  -> (Int, Int) -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used.+  -> IO ()+_spatialConvolutionMM_updateGradInput inp gout gin w columns ones (kW, kH) (dW, dH) (pW, pH) = do+  -- columns and ones are reshaped (and I'm not even sure ones is used):+  -- https://github.com/zdevito/ATen/blob/682cb389db5a318539ff03f031bf896a43a71b13/aten/src/THCUNN/generic/SpatialConvolutionMM.cu#L294+  -- shape inp >>= print+  -- (gin, columns, ones) <- (,,) <$> new (dim :: Dim '[2,2]) <*> newWithTensor inp <*> new (dim :: Dim '[1,1])+  with3DynamicState inp gout gin $ \s' inp' gout' gin' ->+   with3DynamicState w columns ones $ \_ w' columns' ones' ->+    Sig.c_SpatialConvolutionMM_updateGradInput s' inp' gout' gin' w' columns' ones'+      (fromIntegral kW) (fromIntegral kH)+      (fromIntegral dW) (fromIntegral dH)+      (fromIntegral pW) (fromIntegral pH)+  -- pure gin+  -- asStatic <$> Dynamic.spatialConvolutionMM_updateGradInput+  --   (asDynamic inp) (asDynamic gout)+  --   (asDynamic (weights conv))+  --   (kernel2d conv)+  --   (param2d step)+  --   (param2d pad)+++-- | spatialConvolutionMM backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialConvolutionMM_accGradParameters+  :: Dynamic    -- ^ input+  -> Dynamic    -- ^ gradOutput+  -> Dynamic    -- ^ gradWeight+  -> Dynamic    -- ^ gradBias+  -> Dynamic    -- ^ finput/columns <<- required. This can be NULL in C if gradWeight is NULL.+  -> Dynamic    -- ^ ones+  -> (Int, Int) -- ^ (kW, kH) kernel height and width+  -> (Int, Int) -- ^ (dW, dH) step of the convolution in width and height dimensions+  -> (Int, Int) -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used.+  -> Double+  -> IO ()+_spatialConvolutionMM_accGradParameters inp gout gweight gbias finput fgradInput (kW, kH) (dW, dH) (pW, pH) scale = do+  with3DynamicState inp gout gweight $ \s' inp' gout' gweight' ->+   with3DynamicState gbias finput fgradInput $ \_ gbias' finput' fgradInput' ->+    Sig.c_SpatialConvolutionMM_accGradParameters s' inp' gout' gweight' gbias' finput' fgradInput'+      (fromIntegral kW) (fromIntegral kH)+      (fromIntegral dW) (fromIntegral dH)+      (fromIntegral pW) (fromIntegral pH)+      (realToFrac scale)+++-- | spatialConvolutionLocal forward pass (updates the output tensor)+_spatialConvolutionLocal_updateOutput               :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> CLLong -> CLLong -> CLLong -> CLLong -> IO ()+-- | spatialConvolutionLocal backward-update (updates the layer and bias tensors)+_spatialConvolutionLocal_updateGradInput            :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> CLLong -> CLLong -> CLLong -> CLLong -> IO ()+-- | spatialConvolutionLocal backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialConvolutionLocal_accGradParameters          :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> CLLong -> CLLong -> CLLong -> CLLong -> Double -> IO ()+-- | spatialFullConvolution forward pass (updates the output tensor)+_spatialFullConvolution_updateOutput                :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialFullConvolution backward-update (updates the layer and bias tensors)+_spatialFullConvolution_updateGradInput             :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialFullConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialFullConvolution_accGradParameters           :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | spatialDilatedConvolution forward pass (updates the output tensor)+_spatialDilatedConvolution_updateOutput             :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialDilatedConvolution backward-update (updates the layer and bias tensors)+_spatialDilatedConvolution_updateGradInput          :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialDilatedConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialDilatedConvolution_accGradParameters        :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | spatialFullDilatedConvolution forward pass (updates the output tensor)+_spatialFullDilatedConvolution_updateOutput         :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialFullDilatedConvolution backward-update (updates the layer and bias tensors)+_spatialFullDilatedConvolution_updateGradInput      :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialFullDilatedConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialFullDilatedConvolution_accGradParameters    :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | spatialSubSampling forward pass (updates the output tensor)+_spatialSubSampling_updateOutput                    :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | spatialSubSampling backward-update (updates the layer and bias tensors)+_spatialSubSampling_updateGradInput                 :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | spatialSubSampling backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialSubSampling_accGradParameters               :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | spatialUpSamplingNearest forward pass (updates the output tensor)+_spatialUpSamplingNearest_updateOutput              :: Dynamic -> Dynamic -> Int -> IO ()+-- | spatialUpSamplingNearest backward-update (updates the layer and bias tensors)+_spatialUpSamplingNearest_updateGradInput           :: Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | spatialUpSamplingBilinear forward pass (updates the output tensor)+_spatialUpSamplingBilinear_updateOutput             :: Dynamic -> Dynamic -> Int -> Int -> IO ()+-- | spatialUpSamplingBilinear backward-update (updates the layer and bias tensors)+_spatialUpSamplingBilinear_updateGradInput          :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | spatialGridSamplerBilinear forward pass (updates the output tensor)+_spatialGridSamplerBilinear_updateOutput            :: Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | spatialGridSamplerBilinear backward-update (updates the layer and bias tensors)+_spatialGridSamplerBilinear_updateGradInput         :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | volumetricGridSamplerBilinear forward pass (updates the output tensor)+_volumetricGridSamplerBilinear_updateOutput         :: Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | volumetricGridSamplerBilinear backward-update (updates the layer and bias tensors)+_volumetricGridSamplerBilinear_updateGradInput      :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | volumetricConvolution forward pass (updates the output tensor)+_volumetricConvolution_updateOutput                 :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricConvolution backward-update (updates the layer and bias tensors)+_volumetricConvolution_updateGradInput              :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_volumetricConvolution_accGradParameters            :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | volumetricFullConvolution forward pass (updates the output tensor)+_volumetricFullConvolution_updateOutput             :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricFullConvolution backward-update (updates the layer and bias tensors)+_volumetricFullConvolution_updateGradInput          :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricFullConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_volumetricFullConvolution_accGradParameters        :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | volumetricDilatedConvolution forward pass (updates the output tensor)+_volumetricDilatedConvolution_updateOutput          :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricDilatedConvolution backward-update (updates the layer and bias tensors)+_volumetricDilatedConvolution_updateGradInput       :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricDilatedConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_volumetricDilatedConvolution_accGradParameters     :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | volumetricFullDilatedConvolution forward pass (updates the output tensor)+_volumetricFullDilatedConvolution_updateOutput      :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricFullDilatedConvolution backward-update (updates the layer and bias tensors)+_volumetricFullDilatedConvolution_updateGradInput   :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricFullDilatedConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_volumetricFullDilatedConvolution_accGradParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- | spatialReflectionPadding forward pass (updates the output tensor)+_spatialReflectionPadding_updateOutput              :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | spatialReflectionPadding backward-update (updates the layer and bias tensors)+_spatialReflectionPadding_updateGradInput           :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | spatialReplicationPadding forward pass (updates the output tensor)+_spatialReplicationPadding_updateOutput             :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | spatialReplicationPadding backward-update (updates the layer and bias tensors)+_spatialReplicationPadding_updateGradInput          :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricReplicationPadding forward pass (updates the output tensor)+_volumetricReplicationPadding_updateOutput          :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricReplicationPadding backward-update (updates the layer and bias tensors)+_volumetricReplicationPadding_updateGradInput       :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | volumetricUpSamplingNearest forward pass (updates the output tensor)+_volumetricUpSamplingNearest_updateOutput           :: Dynamic -> Dynamic -> Int -> IO ()+-- | volumetricUpSamplingNearest backward-update (updates the layer and bias tensors)+_volumetricUpSamplingNearest_updateGradInput        :: Dynamic -> Dynamic -> Dynamic -> Int -> IO ()+-- | volumetricUpSamplingTrilinear forward pass (updates the output tensor)+_volumetricUpSamplingTrilinear_updateOutput         :: Dynamic -> Dynamic -> Int -> Int -> Int -> IO ()+-- | volumetricUpSamplingTrilinear backward-update (updates the layer and bias tensors)+_volumetricUpSamplingTrilinear_updateGradInput      :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- | temporalReflectionPadding forward pass (updates the output tensor)+_temporalReflectionPadding_updateOutput             :: Dynamic -> Dynamic -> Int -> Int -> IO ()+-- | temporalReflectionPadding backward-update (updates the layer and bias tensors)+_temporalReflectionPadding_updateGradInput          :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> IO ()+-- | temporalReplicationPadding forward pass (updates the output tensor)+_temporalReplicationPadding_updateOutput            :: Dynamic -> Dynamic -> Int -> Int -> IO ()+-- | temporalReplicationPadding backward-update (updates the layer and bias tensors)+_temporalReplicationPadding_updateGradInput         :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> IO ()++_sqrt_updateGradInput = ten4 Sig.c_Sqrt_updateGradInput+_square_updateOutput = ten2 Sig.c_Square_updateOutput++_square_updateGradInput t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_Square_updateGradInput s' t0' t1' t2'++_tanh_updateOutput = ten2 Sig.c_Tanh_updateOutput+_tanh_updateGradInput t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_Tanh_updateGradInput s' t0' t1' t2'+++_logSigmoid_updateOutput t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_LogSigmoid_updateOutput s' t0' t1' t2'++_logSigmoid_updateGradInput = ten4 Sig.c_LogSigmoid_updateGradInput+_sigmoid_updateOutput = ten2 Sig.c_Sigmoid_updateOutput+_sigmoid_updateGradInput t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_Sigmoid_updateGradInput s' t0' t1' t2'++_logSoftMax_updateOutput = ten2dim1 Sig.c_LogSoftMax_updateOutput+_im2Col_updateOutput = ten2int8 Sig.c_Im2Col_updateOutput+_im2Col_updateGradInput = ten2int10 Sig.c_Im2Col_updateGradInput+_gRUFused_updateGradInput = ten5 Sig.c_GRUFused_updateGradInput+_softMax_updateOutput = ten2dim1 Sig.c_SoftMax_updateOutput++_sqrt_updateOutput = ten2double1 Sig.c_Sqrt_updateOutput+_softShrink_updateOutput = ten2double1 Sig.c_SoftShrink_updateOutput+_softPlus_updateOutput = ten2double2 Sig.c_SoftPlus_updateOutput+_hardTanh_updateOutput = ten2double2bool1 Sig.c_HardTanh_updateOutput+_hardTanh_updateGradInput t0 t1 t2 d0 d1 b0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_HardTanh_updateGradInput s' t0' t1' t2' (realToFrac d0) (realToFrac d0) (toEnum $ fromEnum b0)++_softShrink_updateGradInput t0 t1 t2 d0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SoftShrink_updateGradInput s' t0' t1' t2' (realToFrac d0)++_softPlus_updateGradInput = ten4double2 Sig.c_SoftPlus_updateGradInput+_logSoftMax_updateGradInput = ten4dim1 Sig.c_LogSoftMax_updateGradInput+_softMax_updateGradInput = ten4dim1 Sig.c_SoftMax_updateGradInput+_spatialSubSampling_updateOutput = ten4int4 Sig.c_SpatialSubSampling_updateOutput+_spatialSubSampling_updateGradInput = ten4int4 Sig.c_SpatialSubSampling_updateGradInput+_spatialSubSampling_accGradParameters = ten4int4double1 Sig.c_SpatialSubSampling_accGradParameters+_spatialGridSamplerBilinear_updateGradInput = ten5int1 Sig.c_SpatialGridSamplerBilinear_updateGradInput+_sparseLinear_updateParameters = ten5double1 Sig.c_SparseLinear_updateParameters+_volumetricGridSamplerBilinear_updateGradInput = ten5int1 Sig.c_VolumetricGridSamplerBilinear_updateGradInput+_spatialGridSamplerBilinear_updateOutput t0 t1 t2 i0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SpatialGridSamplerBilinear_updateOutput s' t0' t1' t2' (fromIntegral i0)++_volumetricGridSamplerBilinear_updateOutput t0 t1 t2 i0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_VolumetricGridSamplerBilinear_updateOutput s' t0' t1' t2' (fromIntegral i0)++_spatialUpSamplingNearest_updateGradInput t0 t1 t2 i0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SpatialUpSamplingNearest_updateGradInput s' t0' t1' t2' (fromIntegral i0)++_temporalUpSamplingNearest_updateGradInput t0 t1 t2 i0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_TemporalUpSamplingNearest_updateGradInput s' t0' t1' t2' (fromIntegral i0)++_gatedLinear_updateGradInput t0 t1 t2 i0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_GatedLinear_updateGradInput s' t0' t1' t2' (fromIntegral i0)++_temporalUpSamplingNearest_updateOutput = ten2int1 Sig.c_TemporalUpSamplingNearest_updateOutput+_temporalUpSamplingLinear_updateOutput = ten2int1 Sig.c_TemporalUpSamplingLinear_updateOutput+_gatedLinear_updateOutput = ten2int1 Sig.c_GatedLinear_updateOutput+_spatialUpSamplingNearest_updateOutput = ten2int1 Sig.c_SpatialUpSamplingNearest_updateOutput+_spatialUpSamplingBilinear_updateOutput = ten2int2 Sig.c_SpatialUpSamplingBilinear_updateOutput+_temporalUpSamplingLinear_updateGradInput = ten2int4 Sig.c_TemporalUpSamplingLinear_updateGradInput+_spatialUpSamplingBilinear_updateGradInput = ten2int6 Sig.c_SpatialUpSamplingBilinear_updateGradInput+_volumetricConvolution_updateGradInput = ten5int6 Sig.c_VolumetricConvolution_updateGradInput+_spatialDilatedConvolution_updateGradInput = ten5int8 Sig.c_SpatialDilatedConvolution_updateGradInput+_spatialFullConvolution_updateGradInput = ten5int8 Sig.c_SpatialFullConvolution_updateGradInput+_spatialFullDilatedConvolution_updateGradInput = ten5int10 Sig.c_SpatialFullDilatedConvolution_updateGradInput+_temporalRowConvolution_updateOutput = ten6int3bool1 Sig.c_TemporalRowConvolution_updateOutput+_temporalRowConvolution_updateGradInput = ten6int3bool1 Sig.c_TemporalRowConvolution_updateGradInput+_temporalRowConvolution_accGradParameters = ten6int3bool1double1 Sig.c_TemporalRowConvolution_accGradParameters+_sparseLinear_legacyAccGradParameters = ten6double2 Sig.c_SparseLinear_legacyAccGradParameters+_sparseLinear_accGradParameters = ten6double2 Sig.c_SparseLinear_accGradParameters+_spatialConvolutionLocal_updateOutput = ten6int6long4 Sig.c_SpatialConvolutionLocal_updateOutput+_spatialConvolutionLocal_updateGradInput = ten6int6long4 Sig.c_SpatialConvolutionLocal_updateGradInput+_spatialConvolutionLocal_accGradParameters = ten6int6long4double1 Sig.c_SpatialConvolutionLocal_accGradParameters+_volumetricConvolution_updateOutput = ten6int6 Sig.c_VolumetricConvolution_updateOutput+_spatialFullConvolution_updateOutput = ten6int8 Sig.c_SpatialFullConvolution_updateOutput+_spatialFullConvolution_accGradParameters = ten6int8double1 Sig.c_SpatialFullConvolution_accGradParameters+_spatialDilatedConvolution_updateOutput = ten6int8 Sig.c_SpatialDilatedConvolution_updateOutput+_spatialDilatedConvolution_accGradParameters = ten6int8double1 Sig.c_SpatialDilatedConvolution_accGradParameters+_spatialFullDilatedConvolution_updateOutput = ten6int10 Sig.c_SpatialFullDilatedConvolution_updateOutput+_spatialFullDilatedConvolution_accGradParameters = ten6int10double1 Sig.c_SpatialFullDilatedConvolution_accGradParameters+_gRUFused_updateOutput = ten7 Sig.c_GRUFused_updateOutput+_lSTMFused_updateOutput = ten7 Sig.c_LSTMFused_updateOutput+_lSTMFused_updateGradInput = ten7 Sig.c_LSTMFused_updateGradInput+_batchNormalization_updateOutput = ten8bool1double2 Sig.c_BatchNormalization_updateOutput+_batchNormalization_backward = ten10bool1double2 Sig.c_BatchNormalization_backward+_volumetricConvolution_accGradParameters = ten6int6double1 Sig.c_VolumetricConvolution_accGradParameters+_volumetricFullConvolution_updateOutput = ten6int12 Sig.c_VolumetricFullConvolution_updateOutput+_volumetricFullConvolution_updateGradInput = ten6int12 Sig.c_VolumetricFullConvolution_updateGradInput+_volumetricFullConvolution_accGradParameters = ten6int12double1 Sig.c_VolumetricFullConvolution_accGradParameters+_volumetricDilatedConvolution_updateOutput = ten6int12 Sig.c_VolumetricDilatedConvolution_updateOutput+_volumetricDilatedConvolution_updateGradInput = ten5int12 Sig.c_VolumetricDilatedConvolution_updateGradInput++_sparseLinear_updateOutput = ten4 Sig.c_SparseLinear_updateOutput+_sparseLinear_zeroGradParameters t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SparseLinear_zeroGradParameters s' t0' t1' t2'++_sparseLinear_legacyUpdateOutput = ten4 Sig.c_SparseLinear_legacyUpdateOutput+_volumetricDilatedConvolution_accGradParameters = ten6int12double1 Sig.c_VolumetricDilatedConvolution_accGradParameters+_volumetricFullDilatedConvolution_updateOutput = ten6int15 Sig.c_VolumetricFullDilatedConvolution_updateOutput+_volumetricFullDilatedConvolution_updateGradInput = ten6int15 Sig.c_VolumetricFullDilatedConvolution_updateGradInput+_volumetricFullDilatedConvolution_accGradParameters = ten6int15double1 Sig.c_VolumetricFullDilatedConvolution_accGradParameters+++_spatialReflectionPadding_updateOutput     = ten2int4 Sig.c_SpatialReflectionPadding_updateOutput+_spatialReflectionPadding_updateGradInput  t0 t1 t2 i0 i1 i2 i3 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SpatialReflectionPadding_updateGradInput s' t0' t1' t2' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)++_spatialReplicationPadding_updateOutput    = ten2int4 Sig.c_SpatialReplicationPadding_updateOutput++_spatialReplicationPadding_updateGradInput t0 t1 t2 i0 i1 i2 i3 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SpatialReplicationPadding_updateGradInput s' t0' t1' t2' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)++++_volumetricReplicationPadding_updateOutput =+  ten2int6 Sig.c_VolumetricReplicationPadding_updateOutput++_volumetricReplicationPadding_updateGradInput =+  ten3int6 Sig.c_VolumetricReplicationPadding_updateGradInput++_volumetricUpSamplingNearest_updateOutput =+  ten2int1 Sig.c_VolumetricUpSamplingNearest_updateOutput++_volumetricUpSamplingNearest_updateGradInput =+  ten3int1 Sig.c_VolumetricUpSamplingNearest_updateGradInput++_volumetricUpSamplingTrilinear_updateOutput =+  ten2int3 Sig.c_VolumetricUpSamplingTrilinear_updateOutput++_volumetricUpSamplingTrilinear_updateGradInput =+  ten2int8 Sig.c_VolumetricUpSamplingTrilinear_updateGradInput++_temporalReflectionPadding_updateOutput =+  ten2int2 Sig.c_TemporalReflectionPadding_updateOutput++_temporalReflectionPadding_updateGradInput =+  ten3int2 Sig.c_TemporalReflectionPadding_updateGradInput++_temporalReplicationPadding_updateOutput =+  ten2int2 Sig.c_TemporalReplicationPadding_updateOutput++_temporalReplicationPadding_updateGradInput =+  ten3int2 Sig.c_TemporalReplicationPadding_updateGradInput++-------------------------------------------------------------------------------+-- Deal love of god...+--+ten1 fn t0 d0 = runManaged $ do+  s' <- managedState+  t0' <- managedTensor t0+  liftIO $ fn s' t0' (fromIntegral d0)++ten2dim1 fn t0 t1 d0 = runManaged $ do+  s' <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  liftIO $ fn s' t0' t1' (fromIntegral d0)++ten2 fn t0 t1 = runManaged $ do+  s' <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  liftIO $ fn s' t0' t1'++ten3 fn t0 t1 t2 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2'++ten4 fn t0 t1 t2 t3 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \_  t2' t3' ->+    fn s' t0' t1' t2' t3'++ten4dim1 fn t0 t1 t2 t3 d0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \_  t2' t3' ->+    fn s' t0' t1' t2' t3'+      (fromIntegral d0)++ten5 fn t0 t1 t2 t3 t4 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with3DynamicState t2 t3 t4 $ \_  t2' t3' t4' ->+    fn s' t0' t1' t2' t3' t4'++ten3bool2 fn t0 t1 t2 b0 b1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++ten4bool2 fn t0 t1 t2 t3 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \_ t2' t3' ->+    fn s' t0' t1' t2' t3' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++ten3bool1ten1bool1 fn t0 t1 t2 b0 t3 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \_ t2' t3' ->+    fn s' t0' t1' t2' (toEnum $ fromEnum b0) t3' (toEnum $ fromEnum b1)+++ten3int1 fn t0 t1 t2 i0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (fromIntegral i0)++ten3int2 fn t0 t1 t2 i0 i1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (fromIntegral i0) (fromIntegral i1)++ten3int3 fn t0 t1 t2 i0 i1 i2 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2)++ten3int4 fn t0 t1 t2 i0 i1 i2 i3 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)++ten4int2 fn t0 t1 t2 t3 i0 i1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \_  t2' t3' ->+    fn s' t0' t1' t2' t3'+      (fromIntegral i0) (fromIntegral i1)++ten4int4 fn t0 t1 t2 t3 i0 i1 i2 i3 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \_  t2' t3' ->+    fn s' t0' t1' t2' t3'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)++ten3int6bool2 fn t0 t1 t2 i0 i1 i2 i3 i4 i5 b0 b1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (toEnum $ fromEnum b0)+      (toEnum $ fromEnum b1)++ten2int6bool2 fn t0 t1 i0 i1 i2 i3 i4 i5 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (toEnum $ fromEnum b0)+      (toEnum $ fromEnum b1)++ten2int9bool2 fn t0 t1 i0 i1 i2 i3 i4 i5 i6 i7 i8 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8)+      (toEnum $ fromEnum b0)+      (toEnum $ fromEnum b1)++++ten3int9bool2 fn t0 t1 t2 i0 i1 i2 i3 i4 i5 i6 i7 i8 b0 b1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8)+      (toEnum $ fromEnum b0)+      (toEnum $ fromEnum b1)+++ten3int6 fn t0 t1 t2 i0 i1 i2 i3 i4 i5 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)++ten6int16 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (fromIntegral i10) (fromIntegral i11)+      (fromIntegral i12) (fromIntegral i13)+      (fromIntegral i14) (fromIntegral i15)++ten6int15 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (fromIntegral i10) (fromIntegral i11)+      (fromIntegral i12) (fromIntegral i13)+      (fromIntegral i14)++ten6int15double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (fromIntegral i10) (fromIntegral i11)+      (fromIntegral i12) (fromIntegral i13)+      (fromIntegral i14)+      (realToFrac d0)++ten4int2double1 fn t0 t1 t2 t3 i0 i1 d0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+   with2DynamicState t2 t3 $ \ _ t2' t3' ->+    fn s' t0' t1' t2' t3'+      (fromIntegral i0) (fromIntegral i1)+      (realToFrac d0)++ten4int4double1 fn t0 t1 t2 t3 i0 i1 i2 i3 d0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+   with2DynamicState t2 t3 $ \ _ t2' t3' ->+    fn s' t0' t1' t2' t3'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (realToFrac d0)++ten6int4double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (realToFrac d0)++ten6int6double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (realToFrac d0)+++ten6int10 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)++ten6int6 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)++ten6int6long4 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 l0 l1 l2 l3 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral l0) (fromIntegral l1)+      (fromIntegral l2) (fromIntegral l3)++ten6double2 fn t0 t1 t2 t3 t4 t5 d0 d1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (realToFrac d0)+      (realToFrac d1)++ten6int6long4double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 l0 l1 l2 l3 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral l0) (fromIntegral l1)+      (fromIntegral l2) (fromIntegral l3)+      (realToFrac d0)++ten6int6long6double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 l0 l1 l2 l3 l4 l5 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral l0) (fromIntegral l1)+      (fromIntegral l2) (fromIntegral l3)+      (fromIntegral l4) (fromIntegral l5)+      (realToFrac d0)++ten6int8 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)++ten6int8double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (realToFrac d0)++ten6int10double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (realToFrac d0)+++ten6int12double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \s' t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (fromIntegral i10) (fromIntegral i11)+      (realToFrac d0)++ten5double1 fn t0 t1 t2 t3 t4 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    fn s' t0' t1' t2' t3' t4' (realToFrac d0)+++ten5int1 fn t0 t1 t2 t3 t4 i0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    fn s' t0' t1' t2' t3' t4' (fromIntegral i0)++ten5int6 fn t0 t1 t2 t3 t4 i0 i1 i2 i3 i4 i5 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    fn s' t0' t1' t2' t3' t4'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)++ten5int8 fn t0 t1 t2 t3 t4 i0 i1 i2 i3 i4 i5 i6 i7 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    fn s' t0' t1' t2' t3' t4'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+++ten5int10 fn t0 t1 t2 t3 t4 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    fn s' t0' t1' t2' t3' t4'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)++ten2int10 fn t0 t1 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)++++ten5int12 fn t0 t1 t2 t3 t4 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    fn s' t0' t1' t2' t3' t4'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (fromIntegral i10) (fromIntegral i11)+++ten3double1 fn t0 t1 t2 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (realToFrac d0)++ten3double1bool1 fn t0 t1 t2 d0 b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (realToFrac d0) (toEnum $ fromEnum b0)++ten3double2 fn t0 t1 t2 d0 d1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (realToFrac d0) (realToFrac d1)++ten4double2 fn t0 t1 t2 t3 d0 d1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \ _ t2' t3' ->+    fn s' t0' t1' t2' t3' (realToFrac d0) (realToFrac d1)++++ten4double2bool2 fn t0 t1 t2 t3 d0 d1 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with2DynamicState t2 t3 $ \ _ t2' t3' ->+    fn s' t0' t1' t2' t3'+      (realToFrac d0)        (realToFrac d1)+      (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++ten4bool1ten1bool1 fn t0 t1 t2 t3 b0 t4 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+  with3DynamicState t2 t3 t4 $ \ _ t2' t3' t4' ->+    fn s' t0' t1' t2' t3' (toEnum $ fromEnum b0) t4' (toEnum $ fromEnum b1)++ten2double1 fn t0 t1 d0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (realToFrac d0)++ten2double2 fn t0 t1 d0 d1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (realToFrac d0)+      (realToFrac d1)++ten2double1bool1 fn t0 t1 d0 b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (realToFrac d0)+      (toEnum $ fromEnum b0)++ten2double2bool1 fn t0 t1 d0 d1 b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (realToFrac d0)+      (realToFrac d1)+      (toEnum $ fromEnum b0)++ten3double2bool1 fn t0 t1 t2 d0 d1 b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2'+      (realToFrac d0)+      (realToFrac d1)+      (toEnum $ fromEnum b0)++ten6int3bool1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \_ t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0)+      (fromIntegral i1)+      (fromIntegral i2)+      (toEnum $ fromEnum b0)++ten6int3bool1double1 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 b0 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \_ t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0)+      (fromIntegral i1)+      (fromIntegral i2)+      (toEnum $ fromEnum b0)+      (realToFrac d0)++ten3bool1double1 fn t0 t1 t2 b0 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    fn s' t0' t1' t2' (toEnum $ fromEnum b0) (realToFrac d0)++ten10bool1double2 fn t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 b0 d0 d1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \_ t3' t4' ->+    with3DynamicState t5 t6 t7 $ \_ t5' t6' t7' ->+     with2DynamicState t8 t9 $ \_ t8' t9' ->+      fn s' t0' t1' t2' t3' t4' t5' t6' t7' t8' t9'+        (toEnum $ fromEnum b0)+        (realToFrac d0)+        (realToFrac d1)++ten8bool1double2 fn t0 t1 t2 t3 t4 t5 t6 t7 b0 d0 d1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \_ t3' t4' ->+    with3DynamicState t5 t6 t7 $ \_ t5' t6' t7' ->+      fn s' t0' t1' t2' t3' t4' t5' t6' t7'+        (toEnum $ fromEnum b0)+        (realToFrac d0)+        (realToFrac d1)++ten7 fn t0 t1 t2 t3 t4 t5 t6 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \_ t3' t4' ->+    with2DynamicState t5 t6 $ \_ t5' t6' ->+      fn s' t0' t1' t2' t3' t4' t5' t6'+++ten6int12 fn t0 t1 t2 t3 t4 t5 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with3DynamicState t3 t4 t5 $ \_ t3' t4' t5' ->+    fn s' t0' t1' t2' t3' t4' t5'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)+      (fromIntegral i8) (fromIntegral i9)+      (fromIntegral i10) (fromIntegral i11)+++++-------------------------------------------------------------------------------++ten2int1 fn t0 t1 i0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1' (fromIntegral i0)++ten2int2 fn t0 t1 i0 i1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1' (fromIntegral i0) (fromIntegral i1)++ten2int3 fn t0 t1 i0 i1 i2 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2)+ten2int4 fn t0 t1 i0 i1 i2 i3 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+++ten2int6 fn t0 t1 i0 i1 i2 i3 i4 i5 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)++ten2int8 fn t0 t1 i0 i1 i2 i3 i4 i5 i6 i7 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    fn s' t0' t1'+      (fromIntegral i0) (fromIntegral i1)+      (fromIntegral i2) (fromIntegral i3)+      (fromIntegral i4) (fromIntegral i5)+      (fromIntegral i6) (fromIntegral i7)++-- ========================================================================= --+++-- CPU TENSORS ONLY+-- unfolded_acc  :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- unfolded_copy :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- volumetricConvolutionMM_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- volumetricConvolutionMM_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- volumetricConvolutionMM_accGradParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+-- temporalSubSampling_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> IO ()+-- temporalSubSampling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> IO ()+-- temporalSubSampling_accGradParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Double -> IO ()+-- spatialFullConvolutionMap_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- spatialFullConvolutionMap_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IO ()+-- spatialFullConvolutionMap_accGradParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Double -> IO ()+-- hardShrink_updateOutput      :: Dynamic -> Dynamic -> Double -> IO ()+-- hardShrink_updateGradInput   :: Dynamic -> Dynamic -> Dynamic -> Double -> IO ()+-- col2Im_updateGradInput       :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- linear_updateOutput      :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- linear_updateGradInput   :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+-- linear_accGradParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> IO ()+-- sparseLinear_legacyZeroGradParameters :: Dynamic -> Dynamic -> Dynamic -> IO ()+-- sparseLinear_legacyUpdateParameters   :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> IO ()
+ src/Torch/Indef/Dynamic/NN/Activation.hs view
@@ -0,0 +1,104 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.NN.Activation+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- DYNAMIC-NN MODULE WARNING: this module is mostly unfinished and+-- undocumented. It provides, in essence, direct calls to the torch neural+-- network libraries: THNN and THCUNN. Because the dynamic tensor code requires+-- a lot of runtime checks which requires a lot of thought regarding a good+-- API, the recommended route is to use Static tensors, which have a much more+-- natural API and is inherently safer.+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.NN.Activation where++import Torch.Indef.Types+import qualified Torch.Sig.NN as Sig++-- | threshold forward pass (updates the output tensor)+_threshold_updateOutput :: Dynamic -> Dynamic -> Double -> Double -> Bool -> IO ()+_threshold_updateOutput inp out threshold val inplace = with2DynamicState inp out $ \s' inp' out' ->+  Sig.c_Threshold_updateOutput s' inp' out' (realToFrac threshold) (realToFrac val) (toEnum $ fromEnum inplace)++-- | threshold backward-update (updates the layer and bias tensors)+_threshold_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Double -> Double -> Bool -> IO ()+_threshold_updateGradInput inp gout gin threshold val inplace =  with3DynamicState inp gout gin $ \s' inp' gout' gin' ->+  Sig.c_Threshold_updateGradInput s' inp' gout' gin' (realToFrac threshold) (realToFrac val) (toEnum $ fromEnum inplace)+++-- | pReLU forward pass (updates the output tensor)+_pReLU_updateOutput :: Dynamic -> Dynamic -> Dynamic -> IO ()+_pReLU_updateOutput inp gout gin =+  with3DynamicState inp gout gin $ \s' inp' gout' gin' ->+    Sig.c_PReLU_updateOutput s' inp' gout' gin'++-- | pReLU backward-update (updates the layer and bias tensors)+_pReLU_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> IO ()+_pReLU_updateGradInput t0 t1 t2 t3 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \ _ t2' t3' ->+      Sig.c_PReLU_updateGradInput s' t0' t1' t2' t3'+++-- | pReLU backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_pReLU_accGradParameters :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> IO ()+_pReLU_accGradParameters t0 t1 t2 t3 t4 d0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+   with2DynamicState t3 t4 $ \s' t3' t4' ->+    Sig.c_PReLU_accGradParameters s' t0' t1' t2' t3' t4' (realToFrac d0)+++-- | rReLU forward pass (updates the output tensor)+_rReLU_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Double -> Double -> Bool -> Bool -> Generator -> IO ()+_rReLU_updateOutput t0 t1 t2 d0 d1 b0 b1 g =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    -- withGen g $ \g' ->+      Sig.c_RReLU_updateOutput s' t0' t1' t2'+        (realToFrac d0) (realToFrac d1)+        (toEnum $ fromEnum b0) (toEnum $ fromEnum b1) undefined -- g'++-- | rReLU backward-update (updates the layer and bias tensors)+_rReLU_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> Double -> Bool -> Bool -> IO ()+_rReLU_updateGradInput t0 t1 t2 t3 d0 d1 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_  t2' t3' ->+      Sig.c_RReLU_updateGradInput s' t0' t1' t2' t3'+        (realToFrac d0) (realToFrac d1)+        (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)+++-- | leakyReLU forward pass (updates the output tensor)+_leakyReLU_updateOutput :: Dynamic -> Dynamic -> Double -> Bool -> IO ()+_leakyReLU_updateOutput t0 t1 d0 b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+      Sig.c_LeakyReLU_updateOutput s' t0' t1'+        (realToFrac d0) (toEnum $ fromEnum b0)+++-- | leakyReLU backward-update (updates the layer and bias tensors)+_leakyReLU_updateGradInput    :: Dynamic -> Dynamic -> Dynamic -> Double -> Bool -> IO ()+_leakyReLU_updateGradInput t0 t1 t2 d0 b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+      Sig.c_LeakyReLU_updateGradInput s' t0' t1' t1'+        (realToFrac d0) (toEnum $ fromEnum b0)++-- | eLU forward pass (updates the output tensor)+_eLU_updateOutput :: Dynamic -> Dynamic -> Double -> Double -> Bool -> IO ()+_eLU_updateOutput t0 t1 d0 d1 b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+      Sig.c_ELU_updateOutput s' t0' t1'+        (realToFrac d0) (realToFrac d1)+        (toEnum $ fromEnum b0) ++-- | eLU backward-update (updates the layer and bias tensors)+_eLU_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Double -> Double -> IO ()+_eLU_updateGradInput t0 t1 t2 d0 d1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+      Sig.c_ELU_updateGradInput s' t0' t1' t2'+        (realToFrac d0) (realToFrac d1)++
+ src/Torch/Indef/Dynamic/NN/Criterion.hs view
@@ -0,0 +1,188 @@+module Torch.Indef.Dynamic.NN.Criterion where++import Foreign hiding (with, new)+import Foreign.C.Types+import Foreign.Ptr+import Control.Monad.Managed+import Torch.Sig.Types.NN+import Torch.Indef.Dynamic.Tensor+import qualified Torch.Sig.NN as Sig+import qualified Torch.Indef.Index as Ix++import Torch.Indef.Types++-- | ClassNLLCriterion_updateOutput forward pass (updates the output tensor)+_ClassNLLCriterion_updateOutput+  :: Dynamic                -- THTensor *input,+  -> IndexDynamic           -- THIndexTensor *target,+  -> Dynamic                -- THTensor *output,+  -> Bool                   -- bool sizeAverage,+  -> Maybe Dynamic          -- THTensor *weights,+  -> Dynamic                -- THTensor *total_weight,+  -> Integer                -- int64_t ignore_index,+  -> Bool                   -- bool reduce+  -> IO ()+_ClassNLLCriterion_updateOutput t0 it0 t1 b0 mt2 t3 i b1 = runManaged $ do+  s' <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  t3' <- managedTensor t3+  liftIO $ do+    t2' <- case mt2 of+      Just t2 -> withForeignPtr (ctensor t2) pure+      Nothing -> pure nullPtr+    Ix.withDynamicState it0 $ \ _ it0' ->+      Sig.c_ClassNLLCriterion_updateOutput s' t0' it0' t1'+          (toEnum $ fromEnum b0)+          t2'+          t3'+          (fromIntegral i)+          (toEnum $ fromEnum b1)+++-- | ClassNLLCriterion_updateOutput forward pass (updates the output tensor)+_ClassNLLCriterion_updateGradInput+  :: Dynamic         -- THTensor *input,+  -> IndexDynamic    -- THIndexTensor *target,+  -> Dynamic         -- THTensor *gradOutput,+  -> Dynamic         -- THTensor *gradInput,+  -> Bool            -- bool sizeAverage,+  -> Maybe Dynamic   -- THTensor *weights,+  -> Dynamic         -- THTensor *total_weight,+  -> Integer         -- int64_t ignore_index,+  -> Bool            -- bool reduce)+  -> IO ()+_ClassNLLCriterion_updateGradInput t0 it0 t1 t2 b0 mt3 t4 i b1 = runManaged $ do+  s' <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  t2' <- managedTensor t2+  t4' <- managedTensor t4+  liftIO $ do+    t3' <- case mt3 of+      Just t3 -> withForeignPtr (ctensor t3) pure+      Nothing -> pure nullPtr+    Ix.withDynamicState it0 $ \_ it0' ->+      Sig.c_ClassNLLCriterion_updateGradInput s' t0' it0' t1' t2' (toEnum $ fromEnum b0) t3' t4' (fromIntegral i) (toEnum $ fromEnum b1)++++-- c_SpatialClassNLLCriterion_updateOutput :: Ptr CNNState -> Ptr CTensor -> IndexDynamic -> Ptr CTensor -> Bool -> Ptr CTensor -> Ptr CTensor -> Integer -> Bool -> IO ()+-- c_SpatialClassNLLCriterion_updateGradInput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Bool -> Ptr CTensor -> Ptr CTensor -> Integer -> Bool -> IO ()+--+-- c_MultiLabelMarginCriterion_updateOutput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Bool -> Bool -> IO ()+-- c_MultiLabelMarginCriterion_updateGradInput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Bool -> Bool -> IO ()+-- c_MultiMarginCriterion_updateOutput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Bool -> CInt -> Ptr CTensor -> CDouble -> Bool -> IO ()+-- c_MultiMarginCriterion_updateGradInput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Bool -> CInt -> Ptr CTensor -> CDouble -> Bool -> IO ()++-- | l1Cost forward pass (updates the output tensor)+_l1Cost_updateOutput :: Dynamic -> Dynamic -> IO ()+_l1Cost_updateOutput t0 t1 = with2DynamicState t0 t1 $ \s' t0' t1' ->+  Sig.c_L1Cost_updateOutput s' t0' t1'++-- | l1Cost backward-update (updates the layer and bias tensors)+_l1Cost_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IO ()+_l1Cost_updateGradInput t0 t1 t2 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_L1Cost_updateGradInput s' t0' t1' t2'++-- | smoothL1Criterion forward pass (updates the output tensor)+_smoothL1Criterion_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_smoothL1Criterion_updateOutput t0 t1 t2 b0 b1 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SmoothL1Criterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | smoothL1Criterion backward-update (updates the layer and bias tensors)+_smoothL1Criterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_smoothL1Criterion_updateGradInput t0 t1 t2 t3 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_ t2' t3' ->+      Sig.c_SmoothL1Criterion_updateGradInput s' t0' t1' t2' t3' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | absCriterion forward pass (updates the output tensor)+_absCriterion_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_absCriterion_updateOutput t0 t1 t2 b0 b1 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_AbsCriterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | absCriterion backward-update (updates the layer and bias tensors)+_absCriterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_absCriterion_updateGradInput t0 t1 t2 t3 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_ t2' t3' ->+      Sig.c_AbsCriterion_updateGradInput s' t0' t1' t2' t3' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | bCECriterion forward pass (updates the output tensor)+_bCECriterion_updateOutput    :: Dynamic -> Dynamic -> Dynamic -> Bool -> Maybe Dynamic -> Bool -> IO ()+_bCECriterion_updateOutput t0 t1 t2 b0 mt3 b1 = runManaged $ do+  s'  <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  t2' <- managedTensor t2+  liftIO $ do+    t3' <- case mt3 of+      Nothing -> pure nullPtr+      Just t3 -> withForeignPtr (ctensor t3) pure+    Sig.c_BCECriterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) t3' (toEnum $ fromEnum b1)++-- | bCECriterion backward-update (updates the layer and bias tensors)+_bCECriterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Maybe Dynamic -> Bool -> IO ()+_bCECriterion_updateGradInput t0 t1 t2 t3 b0 mt4 b1 = runManaged $ do+  s'  <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  t2' <- managedTensor t2+  t3' <- managedTensor t3+  liftIO $ do+    t4' <- case mt4 of+      Nothing -> pure nullPtr+      Just t4 -> withForeignPtr (ctensor t4) pure+    Sig.c_BCECriterion_updateGradInput s' t0' t1' t2' t3' (toEnum $ fromEnum b0) t4' (toEnum $ fromEnum b1)+++-- | distKLDivCriterion forward pass (updates the output tensor)+_distKLDivCriterion_updateOutput    :: Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_distKLDivCriterion_updateOutput t0 t1 t2 b0 b1 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_DistKLDivCriterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | distKLDivCriterion backward-update (updates the layer and bias tensors)+_distKLDivCriterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_distKLDivCriterion_updateGradInput t0 t1 t2 t3 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_ t2' t3' ->+      Sig.c_DistKLDivCriterion_updateGradInput s' t0' t1' t2' t3' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | marginCriterion forward pass (updates the output tensor)+_marginCriterion_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Bool -> Double -> IO ()+_marginCriterion_updateOutput t0 t1 t2 b0 d0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_MarginCriterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) (realToFrac d0)++-- | marginCriterion backward-update (updates the layer and bias tensors)+_marginCriterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Bool -> Double -> IO ()+_marginCriterion_updateGradInput t0 t1 t2 b0 d0 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_MarginCriterion_updateGradInput s' t0' t1' t2' (toEnum $ fromEnum b0) (realToFrac d0)++-- | softMarginCriterion forward pass (updates the output tensor)+_softMarginCriterion_updateOutput :: Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_softMarginCriterion_updateOutput t0 t1 t2 b0 b1 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_SoftMarginCriterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | softMarginCriterion backward-update (updates the layer and bias tensors)+_softMarginCriterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_softMarginCriterion_updateGradInput t0 t1 t2 t3 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_ t2' t3' ->+      Sig.c_SoftMarginCriterion_updateGradInput s' t0' t1' t2' t3' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | mSECriterion forward pass (updates the output tensor)+_mSECriterion_updateOutput    :: Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_mSECriterion_updateOutput t0 t1 t2 b0 b1 = with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+  Sig.c_MSECriterion_updateOutput s' t0' t1' t2' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | mSECriterion backward-update (updates the layer and bias tensors)+_mSECriterion_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Bool -> Bool -> IO ()+_mSECriterion_updateGradInput t0 t1 t2 t3 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_ t2' t3' ->+      Sig.c_MSECriterion_updateGradInput s' t0' t1' t2' t3' (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++++
+ src/Torch/Indef/Dynamic/NN/Pooling.hs view
@@ -0,0 +1,337 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.NN.Pooling+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- DYNAMIC-NN MODULE WARNING: this module is mostly unfinished and+-- undocumented. It provides, in essence, direct calls to the torch neural+-- network libraries: THNN and THCUNN. Because the dynamic tensor code requires+-- a lot of runtime checks which requires a lot of thought regarding a good+-- API, the recommended route is to use Static tensors, which have a much more+-- natural API and is inherently safer.+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.NN.Pooling where++import Torch.Sig.Types.NN+import Torch.Indef.Dynamic.Tensor+import qualified Torch.Sig.NN as Sig+import qualified Torch.Indef.Index as Ix++import Torch.Indef.Types++-- | spatialAdaptiveAveragePooling forward pass (updates the output tensor)+_spatialAdaptiveAveragePooling_updateOutput :: Dynamic -> Dynamic -> Int -> Int -> IO ()+_spatialAdaptiveAveragePooling_updateOutput t0 t1 a0 a1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Sig.c_SpatialAdaptiveAveragePooling_updateOutput s' t0' t1' (fromIntegral a0) (fromIntegral a1)++-- | spatialAdaptiveAveragePooling backward pass (updates the gradInput tensor)+_spatialAdaptiveAveragePooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IO ()+_spatialAdaptiveAveragePooling_updateGradInput t0 t1 t2 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Sig.c_SpatialAdaptiveAveragePooling_updateGradInput s' t0' t1' t2'++-- | spatialAveragePooling forward pass (updates the output tensor)+_spatialAveragePooling_updateOutput :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> IO ()+_spatialAveragePooling_updateOutput t0 t1 a0 a1 a2 a3 a4 a5 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Sig.c_SpatialAveragePooling_updateOutput s' t0' t1'+      (fromIntegral a0) (fromIntegral a1) (fromIntegral a2) (fromIntegral a3)+      (fromIntegral a4) (fromIntegral a5) (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)+++-- | spatialAveragePooling backward pass (updates the gradInput tensor)+_spatialAveragePooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> IO ()+_spatialAveragePooling_updateGradInput t0 t1 t2 a0 a1 a2 a3 a4 a5 b0 b1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Sig.c_SpatialAveragePooling_updateGradInput s' t0' t1' t2'+      (fromIntegral a0) (fromIntegral a1) (fromIntegral a2) (fromIntegral a3)+      (fromIntegral a4) (fromIntegral a5) (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)+++-- | volumetricAveragePooling forward pass (updates the output tensor)+_volumetricAveragePooling_updateOutput :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> IO ()+_volumetricAveragePooling_updateOutput t0 t1 a0 a1 a2 a3 a4 a5 a6 a7 a8 b0 b1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Sig.c_VolumetricAveragePooling_updateOutput s' t0' t1'+      (fromIntegral a0) (fromIntegral a1) (fromIntegral a2) (fromIntegral a3)+      (fromIntegral a4) (fromIntegral a5) (fromIntegral a6) (fromIntegral a7)+      (fromIntegral a8) (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)+++-- | volumetricAveragePooling backward pass (updates the gradInput tensor)+_volumetricAveragePooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> IO ()+_volumetricAveragePooling_updateGradInput t0 t1 t2 a0 a1 a2 a3 a4 a5 a6 a7 a8 b0 b1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Sig.c_VolumetricAveragePooling_updateGradInput s' t0' t1' t2'+      (fromIntegral a0) (fromIntegral a1) (fromIntegral a2) (fromIntegral a3)+      (fromIntegral a4) (fromIntegral a5) (fromIntegral a6) (fromIntegral a7)+      (fromIntegral a8) (toEnum $ fromEnum b0) (toEnum $ fromEnum b1)++-- | volumetricAdaptiveAveragePooling forward pass (updates the output tensor)+_volumetricAdaptiveAveragePooling_updateOutput :: Dynamic -> Dynamic -> Int -> Int -> Int -> IO ()+_volumetricAdaptiveAveragePooling_updateOutput t0 t1 a0 a1 a2 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Sig.c_VolumetricAdaptiveAveragePooling_updateOutput s' t0' t1'+      (fromIntegral a0) (fromIntegral a1) (fromIntegral a2)++-- | volumetricAdaptiveAveragePooling backward pass (updates the gradInput tensor)+_volumetricAdaptiveAveragePooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IO ()+_volumetricAdaptiveAveragePooling_updateGradInput t0 t1 t2 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+      Sig.c_VolumetricAdaptiveAveragePooling_updateGradInput s' t0' t1' t2'++-- | featureLPPooling forward pass (updates the output tensor)+_featureLPPooling_updateOutput                      :: Dynamic -> Dynamic -> Double -> Int -> Int -> Bool -> IO ()+_featureLPPooling_updateOutput r t0 v0 v1 v2 b =+  with2DynamicState r t0 $ \s' r' t0' ->+    Sig.c_FeatureLPPooling_updateOutput s' r' t0' (realToFrac v0) (fromIntegral v1) (fromIntegral v2) (toEnum $ fromEnum b)++-- | featureLPPooling backward pass (updates the gradInput tensor)+_featureLPPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Dynamic -> Double -> Int -> Int -> Bool -> IO ()+_featureLPPooling_updateGradInput t0 t1 t2 t3 v0 v1 v2 b =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    with2DynamicState t2 t3 $ \_ t2' t3' ->+      Sig.c_FeatureLPPooling_updateGradInput s' t0' t1' t2' t3'+        (realToFrac v0) (fromIntegral v1) (fromIntegral v2) (toEnum $ fromEnum b)++-- | temporalMaxPooling forward pass (updates the output tensor)+_temporalMaxPooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> IO ()+_temporalMaxPooling_updateOutput t0 t1 ix0 i0 i1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_TemporalMaxPooling_updateOutput s' t0' t1' ix0' (fromIntegral i0) (fromIntegral i1)++-- | temporalMaxPooling backward pass (updates the gradInput tensor)+_temporalMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> IO ()+_temporalMaxPooling_updateGradInput t0 t1 t2 ix0 i0 i1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_TemporalMaxPooling_updateGradInput s' t0' t1' t2' ix0' (fromIntegral i0) (fromIntegral i1)++-- | spatialAdaptiveMaxPooling forward pass (updates the output tensor)+_spatialAdaptiveMaxPooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> IO ()+_spatialAdaptiveMaxPooling_updateOutput t0 t1 ix0 i0 i1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialAdaptiveMaxPooling_updateOutput s' t0' t1' ix0' (fromIntegral i0) (fromIntegral i1)++-- | spatialAdaptiveMaxPooling backward pass (updates the gradInput tensor)+_spatialAdaptiveMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> IO ()+_spatialAdaptiveMaxPooling_updateGradInput t0 t1 t2 ix0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialAdaptiveMaxPooling_updateGradInput s' t0' t1' t2' ix0'+++-- | spatialFractionalMaxPooling forward pass (updates the output tensor)+_spatialFractionalMaxPooling_updateOutput :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IndexDynamic -> Dynamic -> IO ()+_spatialFractionalMaxPooling_updateOutput t0 t1 a0 a1 a2 a3 ix0 t2 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialFractionalMaxPooling_updateOutput s' t0' t1'+        (fromIntegral a0) (fromIntegral a1) (fromIntegral a2) (fromIntegral a3)+        ix0' t2'++-- | spatialFractionalMaxPooling backward pass (updates the gradInput tensor)+_spatialFractionalMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> IndexDynamic -> IO ()+_spatialFractionalMaxPooling_updateGradInput t0 t1 t2 a0 a1 a2 a3 ix0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialFractionalMaxPooling_updateGradInput s' t0' t1' t2'+        (fromIntegral a0) (fromIntegral a1) (fromIntegral a2) (fromIntegral a3) ix0'+++-- | spatialMaxPooling forward pass (updates the output tensor)+_spatialMaxPooling_updateOutput+  :: Dynamic         -- ^ input+  -> Dynamic         -- ^ output+  -> IndexDynamic    -- ^ indices+  -> (Int, Int)      -- ^ kernel size+  -> (Int, Int)      -- ^ step size+  -> (Int, Int)      -- ^ padding size+  -> Bool            -- ^ ceil mode+  -> IO ()+_spatialMaxPooling_updateOutput t0 t1 ix0 (i0,i1) (i2,i3) (i4,i5) b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialMaxPooling_updateOutput s' t0' t1' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (toEnum $ fromEnum b0)+++-- | spatialMaxPooling backward pass (updates the gradInput tensor)+_spatialMaxPooling_updateGradInput+  :: Dynamic         -- ^ input+  -> Dynamic         -- ^ grad output+  -> Dynamic         -- ^ grad input+  -> IndexDynamic    -- ^ indices+  -> (Int, Int)      -- ^ kernel size+  -> (Int, Int)      -- ^ step size+  -> (Int, Int)      -- ^ padding size+  -> Bool            -- ^ ceil mode+  -> IO ()+_spatialMaxPooling_updateGradInput t0 t1 t2 ix0 (i0,i1) (i2,i3) (i4,i5) b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialMaxPooling_updateGradInput s' t0' t1' t2' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (toEnum $ fromEnum b0)++-- | spatialDilatedMaxPooling forward pass (updates the output tensor)+_spatialDilatedMaxPooling_updateOutput+  :: Dynamic         -- ^ input+  -> Dynamic         -- ^ output+  -> IndexDynamic    -- ^ indices+  -> (Int, Int)      -- ^ kernel size+  -> (Int, Int)      -- ^ step size+  -> (Int, Int)      -- ^ padding size+  -> (Int, Int)      -- ^ dilation size+  -> Bool            -- ^ ceil mode+  -> IO ()+_spatialDilatedMaxPooling_updateOutput t0 t1 ix0 (i0,i1) (i2,i3) (i4,i5) (i6,i7) b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialDilatedMaxPooling_updateOutput s' t0' t1' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (toEnum $ fromEnum b0)++-- | spatialDilatedMaxPooling backward pass (updates the gradInput tensor)+_spatialDilatedMaxPooling_updateGradInput+  :: Dynamic         -- ^ input+  -> Dynamic         -- ^ grad output+  -> Dynamic         -- ^ grad input+  -> IndexDynamic    -- ^ indices+  -> (Int, Int)      -- ^ kernel size+  -> (Int, Int)      -- ^ step size+  -> (Int, Int)      -- ^ padding size+  -> (Int, Int)      -- ^ dilation size+  -> Bool            -- ^ ceil mode+  -> IO ()+_spatialDilatedMaxPooling_updateGradInput t0 t1 t2 ix0 (i0,i1) (i2,i3) (i4,i5) (i6,i7) b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialDilatedMaxPooling_updateGradInput s' t0' t1' t2' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (toEnum $ fromEnum b0)++-- | spatialMaxUnpooling forward pass (updates the output tensor)+_spatialMaxUnpooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> IO ()+_spatialMaxUnpooling_updateOutput t0 t1 ix0 i0 i1 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialMaxUnpooling_updateOutput s' t0' t1' ix0' (fromIntegral i0) (fromIntegral i1)+++-- | spatialMaxUnpooling backward pass (updates the gradInput tensor)+_spatialMaxUnpooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> IO ()+_spatialMaxUnpooling_updateGradInput t0 t1 t2 ix0 i0 i1 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_SpatialMaxUnpooling_updateGradInput s' t0' t1' t2' ix0'+        (fromIntegral i0) (fromIntegral i1)+++-- | volumetricFractionalMaxPooling forward pass (updates the output tensor)+_volumetricFractionalMaxPooling_updateOutput :: Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IndexDynamic -> Dynamic -> IO ()+_volumetricFractionalMaxPooling_updateOutput t0 t1 i0 i1 i2 i3 i4 i5 ix0 t2 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricFractionalMaxPooling_updateOutput s' t0' t1'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) ix0' t2'+++-- | volumetricFractionalMaxPooling backward pass (updates the gradInput tensor)+_volumetricFractionalMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> Int -> Int -> Int -> Int -> Int -> Int -> IndexDynamic -> IO ()+_volumetricFractionalMaxPooling_updateGradInput t0 t1 t2 i0 i1 i2 i3 i4 i5 ix0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricFractionalMaxPooling_updateGradInput s' t0' t1' t2'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) ix0'++-- | volumetricMaxPooling forward pass (updates the output tensor)+_volumetricMaxPooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricMaxPooling_updateOutput t0 t1 ix0 i0 i1 i2 i3 i4 i5 i6 i7 i8 b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricMaxPooling_updateOutput s' t0' t1' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (fromIntegral i8) (toEnum $ fromEnum b0)++-- | volumetricMaxPooling backward pass (updates the gradInput tensor)+_volumetricMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricMaxPooling_updateGradInput t0 t1 t2 ix0 i0 i1 i2 i3 i4 i5 i6 i7 i8 b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricMaxPooling_updateGradInput s' t0' t1' t2' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (fromIntegral i8) (toEnum $ fromEnum b0)++++-- | volumetricDilatedMaxPooling forward pass (updates the output tensor)+_volumetricDilatedMaxPooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricDilatedMaxPooling_updateOutput t0 t1 ix0 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 b0 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricDilatedMaxPooling_updateOutput s' t0' t1' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (fromIntegral i8) (fromIntegral i9) (fromIntegral i10) (fromIntegral i11)+        (toEnum $ fromEnum b0)++-- | volumetricDilatedMaxPooling backward pass (updates the gradInput tensor)+_volumetricDilatedMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricDilatedMaxPooling_updateGradInput t0 t1 t2 ix0 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 b0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricDilatedMaxPooling_updateGradInput s' t0' t1' t2' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (fromIntegral i8) (fromIntegral i9) (fromIntegral i10) (fromIntegral i11)+        (toEnum $ fromEnum b0)++-- | volumetricMaxUnpooling forward pass (updates the output tensor)+_volumetricMaxUnpooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricMaxUnpooling_updateOutput t0 t1 ix0 i0 i1 i2 i3 i4 i5 i6 i7 i8 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricMaxUnpooling_updateOutput s' t0' t1' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (fromIntegral i8)++-- | volumetricMaxUnpooling backward pass (updates the gradInput tensor)+_volumetricMaxUnpooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricMaxUnpooling_updateGradInput t0 t1 t2 ix0 i0 i1 i2 i3 i4 i5 i6 i7 i8 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricMaxUnpooling_updateGradInput s' t0' t1' t2' ix0'+        (fromIntegral i0) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)+        (fromIntegral i4) (fromIntegral i5) (fromIntegral i6) (fromIntegral i7)+        (fromIntegral i8)++-- | volumetricAdaptiveMaxPooling forward pass (updates the output tensor)+_volumetricAdaptiveMaxPooling_updateOutput :: Dynamic -> Dynamic -> IndexDynamic -> Int -> Int -> Int -> IO ()+_volumetricAdaptiveMaxPooling_updateOutput t0 t1 ix0 i0 i1 i2 =+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricAdaptiveMaxPooling_updateOutput s' t0' t1' ix0' (fromIntegral i0) (fromIntegral i1) (fromIntegral i2)++-- | volumetricAdaptiveMaxPooling backward pass (updates the gradInput tensor)+_volumetricAdaptiveMaxPooling_updateGradInput :: Dynamic -> Dynamic -> Dynamic -> IndexDynamic -> IO ()+_volumetricAdaptiveMaxPooling_updateGradInput t0 t1 t2 ix0 =+  with3DynamicState t0 t1 t2 $ \s' t0' t1' t2' ->+    Ix.withDynamicState ix0 $ \_ ix0' ->+      Sig.c_VolumetricAdaptiveMaxPooling_updateGradInput s' t0' t1' t2' ix0'+
+ src/Torch/Indef/Dynamic/Print.hs view
@@ -0,0 +1,184 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Print+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Helper functions to render n-rank tensors+-------------------------------------------------------------------------------+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+module Torch.Indef.Dynamic.Print+  ( showTensor+  , describeTensor+  ) where++import Control.Applicative+import Control.Exception.Safe+import Control.Monad+import Data.List (intercalate)+import Data.List.NonEmpty (NonEmpty(..))+import Data.Maybe+import Data.Typeable+import GHC.Int+import GHC.Word+import Text.Printf++import qualified Data.List.NonEmpty as NE++import Torch.Indef.Types++-- | Generic way of showing the internal data of a tensor in a tabular format.+-- This makes no assumptions about the type of representation to show and can be+-- used for 'Storage', 'Dynamic', and 'Tensor' types.+showTensor+  :: forall a ix . (Typeable a, Ord a, Num a, Show a, Integral ix, Show ix)+  => (ix -> a)+  -> (ix -> ix -> a)+  -> (ix -> ix -> ix -> a)+  -> (ix -> ix -> ix -> ix -> a)+  -> [ix]+  -> String+showTensor get'1d get'2d get'3d get'4d ds =+  case ds of+    []  -> ""+    [x] -> brackets . intercalate "" $ fmap (valWithSpace . get'1d) (mkIx x)+    [x,y] -> go "" get'2d x y++    [z,x,y]   -> concat . flip fmap (mkIx z) $ \z' -> gt2IxHeader [z'] ++ (go "  " (get'3d z') x y)+    -- [x,y,z]   -> mat3dGo x y z+    [w,q,x,y] -> concat . flip fmap (mkXY w q) $ \(w', q') -> gt2IxHeader [w', q'] ++ (go "  " (get'4d w' q') x y)+    -- [x,y,z,q] -> mat4dGo x y z q++    _ -> error "Can't print this yet"+ where+  go :: String -> (ix -> ix -> a) -> ix -> ix -> String+  go fill getter x y = mat2dGo fill y "" $ fmap (valWithSpace . uncurry getter) (mkXY x y)++  mat2dGo :: String -> ix -> String -> [String] -> String+  mat2dGo    _ _ acc []  = acc+  mat2dGo fill y acc rcs = mat2dGo fill y acc' rest+    where+      (row, rest) = splitAt (fromIntegral y) rcs+      fullrow = fill ++ brackets (intercalate "" row)+      acc' = if null acc then fullrow else acc ++ "\n" ++ fullrow++  mat3dGo :: ix -> ix -> ix -> String+  mat3dGo x y z = concat $ flip fmap (mkIx x) $ \x' ->+    let mat = go "  " (get'3d x') y z+    in gt2IxHeader [x'] ++ mat++  mat4dGo :: ix -> ix -> ix -> ix -> String+  mat4dGo w q x y = concat $ flip fmap (mkXY w q) $ \(w', q') ->+    let mat = go "  " (get'4d w' q') x y+    in gt2IxHeader [w', q'] ++ mat+++  mkIx :: ix -> [ix]+  mkIx x = [0..x - 1]++  mkXY :: ix -> ix -> [(ix, ix)]+  mkXY x y = [ (r, c) | r <- mkIx x, c <- mkIx y ]++  brackets :: String -> String+  brackets s = "[" ++ s ++ "]"++  valWithSpace :: (Typeable a, Ord a, Num a, Show a) => a -> String+  valWithSpace v = spacing ++ value ++ ""+   where+     truncTo :: (RealFrac x, Fractional x) => Int -> x -> x+     truncTo n f = fromInteger (round $ f * (10^n)) / (10.0^^n)++     value :: String+     value = fromMaybe (show v) $+           (printf "%.8f" <$> (cast v :: Maybe Double))+       <|> (printf "%.4f" <$> (cast v :: Maybe Float))++     spacing = magspacing ++ signspacing+     magspacing = ""+     -- magspacing = case compare (v `mod` 10) 4 of+     --   LT -> replicate (v `mod` 10)+     signspacing = case compare (signum v) 0 of+        LT -> " "+        _  -> "  "++  gt2IxHeader :: Show ix => [ix] -> String+  gt2IxHeader is = "\n(" ++ intercalate "," (fmap show is) ++ ",.,.):\n"++-- | show the shape of a tensor+describeTensor+  :: forall t dims+  . (Typeable t, Show dims)+  => [dims]+  -> Proxy t+  -> String+describeTensor ds t =+  "[" ++ show (typeRep t) ++ " tensor with shape: " ++ intercalate "x" (fmap show ds) ++ "]"++data TenSlices+  = TenNone+  | TenVector (NonEmpty HsReal)+  | TenMatricies (NonEmpty (NonEmpty [HsReal]))++-- | Helper function to show the matrix slices from a tensor.+tensorSlices+  :: Dynamic+  -> (Int64 -> IO HsReal)+  -> (Int64 -> Int64 -> IO HsReal)+  -- -> (Int64 -> Int64 -> Int64 -> IO HsReal)+  -- -> (Int64 -> Int64 -> Int64 -> Int64 -> IO HsReal)+  -> [Word64]+  -> IO TenSlices+tensorSlices t get'1d get'2d -- get'3d get'4d+  = \case+    []  -> pure TenNone+    [x] -> TenVector <$> go1d get'1d x+    [x,y] -> (TenMatricies . (:|[])) <$> go2d get'2d x y+    _ -> throwString "Can't slice this yet"+ where+  go1d :: (Int64 -> IO HsReal) -> Word64 -> IO (NonEmpty HsReal)+  go1d getter x+    = forM (mkIx x) getter++  go2d :: (Int64 -> Int64 -> IO HsReal) -> Word64 -> Word64 -> IO (NonEmpty [HsReal])+  go2d getter x y =+    forM (mkIx x) $ \ix ->+      forM (mkVIx y) $ \iy ->+        getter ix iy++  go3d :: (Int64 -> Int64 -> Int64 -> IO HsReal) -> Word64 -> Word64 -> Word64 -> IO (NonEmpty (NonEmpty [HsReal]))+  go3d getter x y z =+    forM (mkIx x) $ \ix ->+      forM (mkIx y) $ \iy ->+        -- forM [0..z - 1] $ \iz ->+          traverse (getter ix iy) (mkVIx z)++  -- mat2dGo :: Int64 -> String -> [HsReal] -> String+  -- mat2dGo _ acc []  = acc+  -- mat2dGo y acc rcs = mat2dGo y acc' rest+  --   where+  --     (row, rest) = splitAt (fromIntegral y) rcs+  --     acc' = if null acc then row else acc ++ "\n" ++ row++  -- mat3dGo :: Int64 -> Int64 -> Int64 -> IO String+  -- mat3dGo x y z = fmap (intercalate "") $ forM (mkIx x) $ \x' -> do+  --   mat <- go "  " (get'3d x') y z+  --   pure $ gt2IxHeader [x'] ++ mat++  -- mat4dGo :: Int64 -> Int64 -> Int64 -> Int64 -> IO String+  -- mat4dGo w q x y = fmap (intercalate "") $ forM (mkXY w q) $ \(w', q') -> do+  --   mat <- go "  " (get'4d w' q') x y+  --   pure $ gt2IxHeader [w', q'] ++ mat++  mkIx :: Word64 -> NonEmpty Int64+  mkIx 0 = 0 :| []+  mkIx x = 0 :| [1..fromIntegral x - 1]++  mkVIx :: Word64 -> [Int64]+  mkVIx 0 = []+  mkVIx x = [0..fromIntegral x - 1]++
+ src/Torch/Indef/Dynamic/Tensor.hs view
@@ -0,0 +1,1228 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- This package is the class for handling numeric data in dynamic tensors.+--+-- A 'Dynamic' is a multi-dimensional matrix without static type-level+-- dimensions. The number of dimensions is unlimited (up to what can be created+-- using LongStorage).+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -fno-cse -Wno-deprecations #-} -- no deprications because we still bundle up all mutable functions+module Torch.Indef.Dynamic.Tensor where++import Foreign hiding (with, new)+import Foreign.Ptr+import Control.Applicative ((<|>))+import Control.Monad+import Control.Monad.Trans.Class+import Control.Monad.Managed+import Control.Exception.Safe+import Control.DeepSeq+import Data.Coerce (coerce)+import Data.Typeable+import Data.Maybe (fromMaybe, fromJust)+import Data.List (intercalate, genericLength)+import Data.List.NonEmpty (NonEmpty(..))+import Foreign.C.Types+import GHC.ForeignPtr (ForeignPtr)+import GHC.Int+import GHC.Exts (IsList(..))+import Numeric.Dimensions+import System.IO.Unsafe+import Control.Concurrent+import Control.Monad.Trans.Except+import Text.Printf++import qualified Data.List                 as List ((!!))+import qualified Data.List.NonEmpty        as NE+import qualified Torch.Types.TH            as TH+import qualified Foreign.Marshal.Array     as FM+import qualified Torch.Sig.State           as Sig+import qualified Torch.Sig.Types           as Sig+import qualified Torch.Sig.Types.Global    as Sig+import qualified Torch.Sig.Tensor          as Sig+import qualified Torch.Sig.Tensor.Memory   as Sig+import qualified Torch.Sig.Storage         as StorageSig (c_size)++import Torch.Indef.Dynamic.Print (showTensor, describeTensor)+import Torch.Indef.Types+import Torch.Indef.Internal+import Torch.Indef.Index hiding (withDynamicState)+import qualified Torch.Indef.Storage as Storage++-- | Clears the internal flags on a tensor. Uses bitwise operators for flags.+_clearFlag :: Dynamic -> Int8 -> IO ()+_clearFlag t cc = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_clearFlag s' t' (CChar cc)++-- | Get the underlying data as a haskell list from the tensor+--+-- NOTE: This _cannot_ use a Tensor's storage size because ATen's Storage+-- allocates up to the next 64-byte line on the CPU (needs reference, this+-- is the unofficial response from \@soumith in slack).+tensordata :: Dynamic -> [HsReal]+tensordata t =+  case shape t of+    [] -> []+    ds ->+      unsafeDupablePerformIO . flip with (pure . fmap c2hsReal) $ do+        st <- managedState+        t' <- managedTensor t+        liftIO $ do+          let sz = fromIntegral (product ds)+          -- a strong dose of paranoia+          tmp <- FM.mallocArray sz+          creals <- Sig.c_data st t'+          FM.copyArray tmp creals sz+          FM.peekArray sz tmp+{-# NOINLINE tensordata #-}++-- | get a value from dimension 1+get1d :: Dynamic -> Word -> Maybe HsReal+get1d t d1+  | nDimension t /= 1 || size t 0 < d1 = Nothing+  | otherwise = unsafeDupablePerformIO . flip with (pure . Just . c2hsReal) . (liftIO =<<) $ Sig.c_get1d+    <$> managedState+    <*> managedTensor t+    <*> pure (fromIntegral d1)+{-# NOINLINE get1d #-}++unsafeGet1d :: Dynamic -> Word -> HsReal+unsafeGet1d t d1 = fromJust $ get1d t d1++-- | get a value from dimension 2+get2d :: Dynamic -> Word -> Word -> Maybe HsReal+get2d t d1 d2+  | nDimension t /= 2 = Nothing+  | otherwise = unsafeDupablePerformIO . flip with (pure . Just . c2hsReal) . (liftIO =<<) $ Sig.c_get2d+    <$> managedState+    <*> managedTensor t+    <*> pure (fromIntegral d1)+    <*> pure (fromIntegral d2)+{-# NOINLINE get2d #-}++unsafeGet2d :: Dynamic -> Word -> Word -> HsReal+unsafeGet2d t d1 d2 = fromJust $ get2d t d1 d2++-- | get a value from dimension 3+get3d :: Dynamic -> Word -> Word -> Word -> Maybe HsReal+get3d t d1 d2 d3+  | nDimension t /= 3 = Nothing+  | otherwise = unsafeDupablePerformIO . flip with (pure . Just . c2hsReal) . (liftIO =<<) $ Sig.c_get3d+    <$> managedState+    <*> managedTensor t+    <*> pure (fromIntegral d1)+    <*> pure (fromIntegral d2)+    <*> pure (fromIntegral d3)+{-# NOINLINE get3d #-}++unsafeGet3d :: Dynamic -> Word -> Word -> Word -> HsReal+unsafeGet3d t d1 d2 d3 = fromJust $ get3d t d1 d2 d3++-- | get a value from dimension 4+get4d :: Dynamic -> Word -> Word -> Word -> Word -> Maybe HsReal+get4d t d1 d2 d3 d4+  | nDimension t /= 4 = Nothing+  | otherwise = unsafeDupablePerformIO . flip with (pure . Just . c2hsReal) . (liftIO =<<) $ Sig.c_get4d+    <$> managedState+    <*> managedTensor t+    <*> pure (fromIntegral d1)+    <*> pure (fromIntegral d2)+    <*> pure (fromIntegral d3)+    <*> pure (fromIntegral d4)+{-# NOINLINE get4d #-}++unsafeGet4d :: Dynamic -> Word -> Word -> Word -> Word -> HsReal+unsafeGet4d t d1 d2 d3 d4 = fromJust $ get4d t d1 d2 d3 d4++-- | get a value from a dynamic tensor at a given index, @Dims d@.+getDim :: Dynamic -> Dims ((i:+ds)::[Nat]) -> Maybe HsReal+getDim t d = case fromIntegral <$> listDims d of+  []           -> error "[impossible] pattern match fail, `Dims ((i:+ds)::[Nat])` prevents this"+  [x]          -> get1d t x+  [x, y]       -> get2d t x y+  [x, y, z]    -> get3d t x y z+  [x, y, z, q] -> get4d t x y z q+  _            -> error "[incomplete] getDim doen't have support for dimensions > 4"++-- | whether or not the tensor is contiguous in memory.+isContiguous :: Dynamic -> Bool+isContiguous t = unsafeDupablePerformIO . flip with (pure . (1 ==)) . (liftIO =<<) $ Sig.c_isContiguous+  <$> managedState+  <*> managedTensor t+{-# NOINLINE isContiguous #-}++-- | check to see if to tensors are the same size as eachother.+isSameSizeAs :: Dynamic -> Dynamic -> Bool+isSameSizeAs t0 t1 = unsafeDupablePerformIO . flip with (pure . (1 ==)) . (liftIO =<<) $ Sig.c_isSameSizeAs+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+{-# NOINLINE isSameSizeAs #-}++-- | Returns true iff the Tensor is set to the argument Tensor.+--+-- Note: this is only true if the tensors are the same size, have+-- the same strides and share the same storage and offset.+isSetTo :: Dynamic -> Dynamic -> Bool+isSetTo t0 t1 = unsafeDupablePerformIO . flip with (pure . (1 ==)) . (liftIO =<<) $ Sig.c_isSetTo+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+{-# NOINLINE isSetTo #-}++-- | check to see if the tensor is the same size as the LongStorage.+isSize :: Dynamic -> TH.LongStorage -> Bool+isSize t ls = unsafeDupablePerformIO . flip with (pure . (1 ==)) . (liftIO =<<) $ Sig.c_isSize+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (snd $ TH.longStorageState ls))+{-# NOINLINE isSize #-}++-- | Returns the number of dimensions in a Tensor.+nDimension :: Dynamic -> Word+nDimension t = unsafeDupablePerformIO . flip with (pure . fromIntegral) . (liftIO =<<) $ Sig.c_nDimension+  <$> managedState+  <*> managedTensor t+{-# NOINLINE nDimension #-}++-- | Returns the number of elements in a Tensor.+nElement :: Dynamic -> Word64+nElement t = unsafeDupablePerformIO . flip with (pure . fromIntegral) . (liftIO =<<) $ Sig.c_nElement+  <$> managedState+  <*> managedTensor t+{-# NOINLINE nElement #-}++-- | returns a tensor which /shares the same 'Storage'/ as the original. Hence, any modification in+-- the memory of the sub-tensor will have an impact on the primary tensor, and vice-versa.+-- These methods are very fast, as they do not involve any memory copy.+_narrow+  :: Dynamic -- ^ return tensor to mutate (C-style)+  -> Dynamic -- ^ source tensor used for data+  -> Word    -- ^ dimension to operate on+  -> Int64+  -> Size+  -> IO ()+_narrow t0 t1 a b c = withLift $ Sig.c_narrow+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+  <*> pure (fromIntegral c)+{-# WARNING _narrow "hasktorch devs have not yet made this safe. You are warned." #-}++-- | Returns an empty tensor.+empty :: Dynamic+empty = unsafeDupablePerformIO . withDynamic $ Sig.c_new <$> managedState+{-# NOINLINE empty #-}++-- | pure version of '_expand'+newExpand :: Dynamic -> TH.IndexStorage -> Dynamic+newExpand r ix = unsafeDupablePerformIO . withDynamic $ Sig.c_newExpand+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . snd $ TH.longStorageState ix)+{-# NOINLINE newExpand #-}++-- | Expanding a tensor does not allocate new memory, but only creates a new view on the+-- existing tensor where singleton dimensions can be expanded to multiple ones by setting+-- the stride to 0. Any dimension that has size 1 can be expanded to arbitrary value+-- without any new memory allocation. Attempting to expand along a dimension that does+-- not have size 1 will result in an error which we do not currently handle in hasktorch.+_expand+  :: Dynamic          -- ^ return tensor to mutate inplace.+  -> Dynamic          -- ^ source tensor to expand+  -> TH.IndexStorage  -- ^ how to expand the tensor.+  -> IO ()+_expand r t ix = withLift $ Sig.c_expand+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> managed (withForeignPtr . snd $ TH.longStorageState ix)++-- | FIXME: doublecheck what this does.+_expandNd  :: NonEmpty Dynamic -> NonEmpty Dynamic -> Int -> IO ()+_expandNd (rets@(s:|_)) ops i = runManaged $ do+  st    <- managedState+  rets' <- mngNonEmpty rets+  ops'  <- mngNonEmpty ops+  liftIO $ Sig.c_expandNd st rets' ops' (fromIntegral i)+ where+  mngNonEmpty :: NonEmpty Dynamic -> Managed (Ptr (Ptr CTensor))+  mngNonEmpty = mapM toMPtr . NE.toList >=> mWithArray++  mWithArray :: [Ptr a] -> Managed (Ptr (Ptr a))+  mWithArray as = managed (FM.withArray as)++  toMPtr :: Dynamic -> Managed (Ptr CTensor)+  toMPtr d = managed (withForeignPtr (Sig.ctensor d))++-- | purely clone a tensor+newClone :: Dynamic -> Dynamic+newClone t = unsafeDupablePerformIO . withDynamic $ Sig.c_newClone+  <$> managedState+  <*> managedTensor t+{-# NOINLINE newClone #-}++-- | purely clone a tensor to have a contiguous memory layout.+newContiguous :: Dynamic -> Dynamic+newContiguous t = unsafeDupablePerformIO . withDynamic $ Sig.c_newContiguous+  <$> managedState+  <*> managedTensor t+{-# NOINLINE newContiguous #-}++-- | returns a tensor which /shares the same 'Storage'/ as the original. Hence, any modification in+-- the memory of the sub-tensor will have an impact on the primary tensor, and vice-versa.+-- These methods are very fast, as they do not involve any memory copy.+newNarrow+  :: Dynamic    -- ^ source tensor+  -> Word       -- ^ dimenion to operate over+  -> Int64+  -> Size+  -> IO Dynamic -- ^ return tensor, linked by storage to source tensor+newNarrow t a b c = withDynamic $ Sig.c_newNarrow+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+  <*> pure (fromIntegral c)+{-# WARNING newNarrow "hasktorch devs have not yet made this safe. You are warned." #-}++-- | returns a tensor which /shares the same 'Storage'/ as the original. Hence, any modification in+-- the memory of the sub-tensor will have an impact on the primary tensor, and vice-versa.+-- These methods are very fast, as they do not involve any memory copy.+newSelect+  :: Dynamic    -- ^ source tensor+  -> Word       -- ^ dimension to operate over+  -> Int64+  -> IO Dynamic -- ^ return tensor, linked by storage to source tensor+newSelect t a b = withDynamic $ Sig.c_newSelect+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+{-# WARNING newSelect "hasktorch devs have not yet made this safe. You are warned." #-}++-- | get the sizes of each dimension+--+-- FIXME: doublecheck this+newSizeOf :: Dynamic -> TH.IndexStorage+newSizeOf t = unsafeDupablePerformIO . flip with mkCPUIxStorage $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_newSizeOf s' t'+{-# NOINLINE newSizeOf #-}++-- | get the strides of each dimension+--+-- FIXME: doublecheck this+newStrideOf :: Dynamic -> TH.IndexStorage+newStrideOf t = unsafeDupablePerformIO . flip with mkCPUIxStorage $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_newStrideOf s' t'+{-# NOINLINE newStrideOf #-}++-- | pure version of '_transpose'+newTranspose :: Dynamic -> Word -> Word -> Dynamic+newTranspose t a b = unsafeDupablePerformIO . withDynamic $ Sig.c_newTranspose+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+{-# NOINLINE newTranspose #-}++-- | pure version of '_unfold'+newUnfold+  :: Dynamic  -- ^ source tensor+  -> Word     -- ^ dimension to operate on+  -> Int64+  -> Int64+  -> Dynamic  -- ^ return tensor+newUnfold t a b c = unsafeDupablePerformIO . withDynamic $ Sig.c_newUnfold+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+  <*> pure (fromIntegral c)+{-# NOINLINE newUnfold #-}++-- |+-- Creates a view with different dimensions of the storage associated with tensor, returning a new tensor.+--+-- FIXME: I think resizeAs is the non-cloning version of this function. See:+-- https://github.com/torch/torch7/blob/master/doc/tensor.md#result-viewresult-tensor-sizes+--+-- for more.+--+-- NOTE(stites): I think this API can only be kept pure via linear types.+newView :: Dynamic -> TH.IndexStorage -> IO Dynamic+newView t ix = withDynamic $ Sig.c_newView+  <$> managedState+  <*> managedTensor t+  <*> managed (withCPUIxStorage ix)+{-# WARNING newView "hasktorch devs have not yet made this safe. You are warned." #-}++-- | create an uninitialized tensor with the given size and strides (?)+--+-- FIXME: doublecheck what the IndexStorages stands for+newWithSize :: TH.IndexStorage -> TH.IndexStorage -> Dynamic+newWithSize l0 l1 = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithSize+  <$> managedState+  <*> managed (withCPUIxStorage l0)+  <*> managed (withCPUIxStorage l1)+{-# NOINLINE newWithSize #-}++-- | create an uninitialized 1d tensor+newWithSize1d :: Word -> Dynamic+newWithSize1d a0 = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithSize1d+  <$> managedState+  <*> pure (fromIntegral a0)+{-# NOINLINE newWithSize1d #-}++-- | create an uninitialized 2d tensor+newWithSize2d :: Word -> Word -> Dynamic+newWithSize2d a0 a1 = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithSize2d+  <$> managedState+  <*> pure (fromIntegral a0)+  <*> pure (fromIntegral a1)+{-# NOINLINE newWithSize2d #-}++-- | create an uninitialized 3d tensor+newWithSize3d :: Word -> Word -> Word -> Dynamic+newWithSize3d a0 a1 a2 = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithSize3d+  <$> managedState+  <*> pure (fromIntegral a0)+  <*> pure (fromIntegral a1)+  <*> pure (fromIntegral a2)+{-# NOINLINE newWithSize3d #-}++-- | create an uninitialized 4d tensor+newWithSize4d :: Word -> Word -> Word -> Word -> Dynamic+newWithSize4d a0 a1 a2 a3 = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithSize4d+  <$> managedState+  <*> pure (fromIntegral a0)+  <*> pure (fromIntegral a1)+  <*> pure (fromIntegral a2)+  <*> pure (fromIntegral a3)+{-# NOINLINE newWithSize4d #-}++-- | create a new tensor with the given size and strides, storage offset and storage.+newWithStorage :: Storage -> StorageOffset -> TH.IndexStorage -> TH.IndexStorage -> Dynamic+newWithStorage s pd l0 l1 = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithStorage+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+  <*> managed (withForeignPtr (snd $ TH.longStorageState l0))+  <*> managed (withForeignPtr (snd $ TH.longStorageState l1))+{-# NOINLINE newWithStorage #-}+++-- | create a new 1d tensor with the given storage's first dimension.+newWithStorage1d+  :: Storage            -- storage to use+  -> StorageOffset      -- storage offset must be >= 1+  -> (Size, Stride)     -- size is of the 1st dimension, stride is the stride in the first dimension+  -> Dynamic+newWithStorage1d s pd (d00,d01) = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithStorage1d+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+{-# NOINLINE newWithStorage1d #-}+++-- | create a new 2d tensor with the given storage's first 2 dimensions.+newWithStorage2d+  :: Storage+  -> StorageOffset+  -> (Size, Stride)+  -> (Size, Stride)+  -> Dynamic+newWithStorage2d s pd (d00,d01) (d10,d11) = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithStorage2d+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+  <*> pure (fromIntegral d10) <*> pure (fromIntegral d11)+{-# NOINLINE newWithStorage2d #-}+++-- | create a new 3d tensor with the given storage's first 3 dimensions.+newWithStorage3d+  :: Storage+  -> StorageOffset+  -> (Size, Stride)+  -> (Size, Stride)+  -> (Size, Stride)+  -> Dynamic+newWithStorage3d s pd (d00,d01) (d10,d11) (d20,d21) = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithStorage3d+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+  <*> pure (fromIntegral d10) <*> pure (fromIntegral d11)+  <*> pure (fromIntegral d20) <*> pure (fromIntegral d21)+{-# NOINLINE newWithStorage3d #-}+++-- | create a new 4d tensor with the given storage's first 4 dimensions.+newWithStorage4d+  :: Storage+  -> StorageOffset+  -> (Size, Stride)+  -> (Size, Stride)+  -> (Size, Stride)+  -> (Size, Stride)+  -> Dynamic+newWithStorage4d s pd (d00,d01) (d10,d11) (d20,d21) (d30,d31) = unsafeDupablePerformIO . withDynamic $ Sig.c_newWithStorage4d+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+  <*> pure (fromIntegral d10) <*> pure (fromIntegral d11)+  <*> pure (fromIntegral d20) <*> pure (fromIntegral d21)+  <*> pure (fromIntegral d30) <*> pure (fromIntegral d31)+{-# NOINLINE newWithStorage4d #-}++-- | create a new tensor with the given tensor's underlying storage.+newWithTensor :: Dynamic -> IO Dynamic+newWithTensor t = withDynamic $ Sig.c_newWithTensor+  <$> managedState+  <*> managedTensor t+{-# NOINLINE newWithTensor #-}+{-# WARNING newWithTensor "this function causes the input tensor to be impure" #-}++-- | Resize the tensor according to the given LongStorage size (and strides?)+-- FIXME: doublecheck what the IndexStorages stands for+_resize+  :: Dynamic -> TH.IndexStorage -> TH.IndexStorage -> IO ()+_resize t l0 l1 = withLift $ Sig.c_resize+  <$> managedState+  <*> managedTensor t+  <*> managed (withCPUIxStorage l0)+  <*> managed (withCPUIxStorage l1)++-- | resize dimension 1 of a tensor.+resize1d_ :: Dynamic -> Word -> IO ()+resize1d_ t l0 = withLift $ Sig.c_resize1d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)++-- | resize the first 2 dimensions of a tensor.+resize2d_ :: Dynamic -> Word -> Word -> IO ()+resize2d_ t l0 l1 = withLift $ Sig.c_resize2d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)++-- | resize the first 3 dimensions of a tensor.+resize3d_ :: Dynamic -> Word -> Word -> Word -> IO ()+resize3d_ t l0 l1 l2 = withLift $ Sig.c_resize3d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)+  <*> pure (fromIntegral l2)++-- | resize the first 4 dimensions of a tensor.+resize4d_ :: Dynamic -> Word -> Word -> Word -> Word -> IO ()+resize4d_ t l0 l1 l2 l3 = withLift $ Sig.c_resize4d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)+  <*> pure (fromIntegral l2)+  <*> pure (fromIntegral l3)++-- | resize the first 5 dimensions of a tensor.+resize5d_ :: Dynamic -> Word -> Word -> Word -> Word -> Word -> IO ()+resize5d_ t l0 l1 l2 l3 l4 = withLift $ Sig.c_resize5d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)+  <*> pure (fromIntegral l2)+  <*> pure (fromIntegral l3)+  <*> pure (fromIntegral l4)++-- | Resize the tensor as the given tensor.+resizeAs_+  :: Dynamic -- ^ tensor to mutate inplace+  -> Dynamic -- ^ tensor used for its shape+  -> IO ()+resizeAs_ t0 t1 = with2DynamicState t0 t1 Sig.c_resizeAs++-- | resize a tensor with given strides, sizes and a magical parameter.+--+-- FIXME: Someone needs to find out what the magical parameter is.+resizeNd_+  :: Dynamic   -- ^ tensor to resize inplace.+  -> Int32     -- ^ unknown argument. FIXME: Someone needs to find this out.+  -> [Size]    -- ^ new sizes to update+  -> [Stride]  -- ^ new strides to update.+  -> IO ()+resizeNd_ t i l0' l1' = withLift $ Sig.c_resizeNd+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral i)+  <*> liftIO (FM.newArray (coerce l0' :: [CLLong]))+  <*> liftIO (FM.newArray (coerce l1' :: [CLLong]))++-- | Increment the reference counter of the tensor.+--+-- From: https://github.com/torch/torch7/blob/aed31711c6b8846b8337a263a7f9f998697994e7/doc/tensor.md#reference-counting+--+-- Tensors are reference-counted. It means that each time an object (C or the Lua state) need to keep a reference over a tensor, the corresponding tensor reference counter will be increased. The reference counter is decreased when the object does not need the tensor anymore.+--+-- These methods should be used with extreme care. In general, they should never be called, except if you know what you are doing, as the handling of references is done automatically. They can be useful in threaded environments. Note that these methods are atomic operations.+retain :: Dynamic -> IO ()+retain t = withLift $ Sig.c_retain+  <$> managedState+  <*> managedTensor t++-- | returns a tensor which /shares the same 'Storage'/ as the original. Hence, any modification in+-- the memory of the sub-tensor will have an impact on the primary tensor, and vice-versa.+-- These methods are very fast, as they do not involve any memory copy.+_select+  :: Dynamic  -- ^ return tensor which is mutated inplace (C-Style)+  -> Dynamic  -- ^ source tensor+  -> Word     -- ^ dimension to operate over+  -> Word+  -> IO ()+_select t0 t1 a b = with2DynamicState t0 t1 $ \s' t0' t1' ->+  Sig.c_select s' t0' t1' (fromIntegral a) (fromIntegral b)+{-# WARNING _select "hasktorch devs have not yet made this safe. You are warned." #-}++-- | set the source tensor's storage to another tensor.+_set+  :: Dynamic  -- ^ the source tensor which is mutated inplace+  -> Dynamic  -- ^ the tensor who's storage is going to be referenced.+  -> IO ()+_set t0 t1 = with2DynamicState t0 t1 Sig.c_set+{-# WARNING _set "hasktorch devs have not yet made this safe. You are warned." #-}++-- | set a value in dimension 1, inplace.+set1d_+  :: Dynamic -- ^ source tensor+  -> Word    -- ^ rank-1 index+  -> HsReal  -- ^ value to put+  -> IO ()+set1d_ t l0 v = withLift $ Sig.c_set1d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (hs2cReal v)++-- | set a value in dimension 2, inplace.+set2d_+  :: Dynamic -- ^ source tensor+  -> Word    -- ^ rank-1 index+  -> Word    -- ^ rank-2 index+  -> HsReal  -- ^ value to put+  -> IO ()+set2d_ t l0 l1 v = withLift $ Sig.c_set2d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)+  <*> pure (hs2cReal v)++-- | set a value in dimension 3, inplace.+set3d_+  :: Dynamic -- ^ source tensor+  -> Word    -- ^ rank-1 index+  -> Word    -- ^ rank-2 index+  -> Word    -- ^ rank-3 index+  -> HsReal  -- ^ value to put+  -> IO ()+set3d_ t l0 l1 l2 v = withLift $ Sig.c_set3d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)+  <*> pure (fromIntegral l2)+  <*> pure (hs2cReal v)++-- | set a value in dimension 4, inplace.+set4d_+  :: Dynamic -- ^ source tensor+  -> Word    -- ^ rank-1 index+  -> Word    -- ^ rank-2 index+  -> Word    -- ^ rank-3 index+  -> Word    -- ^ rank-4 index+  -> HsReal  -- ^ value to put+  -> IO ()+set4d_ t l0 l1 l2 l3 v = withLift $ Sig.c_set4d+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral l0)+  <*> pure (fromIntegral l1)+  <*> pure (fromIntegral l2)+  <*> pure (fromIntegral l3)+  <*> pure (hs2cReal v)++-- | set the flags on a tensor inplace+setFlag_ :: Dynamic -> Int8 -> IO ()+setFlag_ t l0 = withLift $ Sig.c_setFlag+  <$> managedState+  <*> managedTensor t+  <*> pure (CChar l0)++-- | Set the storage of a tensor.+--+-- FIXME: doublecheck what the IndexStorages stands for+setStorage_ :: Dynamic -> Storage -> StorageOffset -> TH.IndexStorage -> TH.IndexStorage -> IO ()+setStorage_ t s a b c = withLift $ Sig.c_setStorage+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.cstorage s))+  <*> pure (fromIntegral a)+  <*> managed (withCPUIxStorage b)+  <*> managed (withCPUIxStorage c)+{-# WARNING setStorage_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}++-- | Set the storage of a tensor, only referencing 1 dimension of storage+setStorage1d_ :: Dynamic -> Storage -> StorageOffset -> (Size, Stride) -> IO ()+setStorage1d_ t s pd (d00,d01) = withLift $ Sig.c_setStorage1d+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.cstorage s))+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+{-# WARNING setStorage1d_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}++-- | Set the storage of a tensor, only referencing 2 dimensions of storage+setStorage2d_ :: Dynamic -> Storage -> StorageOffset -> (Size, Stride) -> (Size, Stride) -> IO ()+setStorage2d_ t s pd (d00,d01) (d10,d11) = withLift $ Sig.c_setStorage2d+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.cstorage s))+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+  <*> pure (fromIntegral d10) <*> pure (fromIntegral d11)+{-# WARNING setStorage2d_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}+++-- | Set the storage of a tensor, only referencing 3 dimensions of storage+setStorage3d_ :: Dynamic -> Storage -> StorageOffset -> (Size, Stride) -> (Size, Stride) -> (Size, Stride) -> IO ()+setStorage3d_ t s pd (d00,d01) (d10,d11) (d20,d21) = withLift $ Sig.c_setStorage3d+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.cstorage s))+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+  <*> pure (fromIntegral d10) <*> pure (fromIntegral d11)+  <*> pure (fromIntegral d20) <*> pure (fromIntegral d21)+{-# WARNING setStorage3d_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}++-- | Set the storage of a tensor, only referencing 4 dimensions of storage+setStorage4d_ :: Dynamic -> Storage -> StorageOffset -> (Size, Stride) -> (Size, Stride) -> (Size, Stride) -> (Size, Stride) -> IO ()+setStorage4d_ t s pd (d00,d01) (d10,d11) (d20,d21) (d30,d31) = withLift $ Sig.c_setStorage4d+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.cstorage s))+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral d00) <*> pure (fromIntegral d01)+  <*> pure (fromIntegral d10) <*> pure (fromIntegral d11)+  <*> pure (fromIntegral d20) <*> pure (fromIntegral d21)+  <*> pure (fromIntegral d30) <*> pure (fromIntegral d31)+{-# WARNING setStorage4d_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}++-- | Set the storage of a tensor, referencing any number of dimensions of storage+setStorageNd_+  :: Dynamic       -- ^ tensor to mutate, inplace+  -> Storage       -- ^ storage to set+  -> StorageOffset -- ^ offset of the storage to start from+  -> Word          -- ^ dimension... to operate over? to start from? (TODO: allow for "unset" dimension)+  -> [Size]        -- ^ sizes to use with the storage+  -> [Stride]      -- ^ strides to use with the storage+  -> IO ()+setStorageNd_ t s a b hsc hsd = withLift $ Sig.c_setStorageNd+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.cstorage s))+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+  <*> liftIO (FM.newArray (coerce hsc :: [CLLong]))+  <*> liftIO (FM.newArray (coerce hsd :: [CLLong]))+{-# WARNING setStorageNd_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}++-- | get the size of a tensor's specific dimension.+--+-- FIXME: this can throw an exception if the dimension is out-of-bound.+size+  :: Dynamic -- ^ tensor to inspect+  -> Word    -- ^ dimension to get+  -> Word    -- ^ size of the dimension+size t d = unsafeDupablePerformIO . flip with (pure . fromIntegral) . (liftIO =<<) $ Sig.c_size+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral d)+  -- liftIO $  s' t' (fromIntegral l0)++-- | primarily used for debugging. Get the size description from a c call.+sizeDesc :: Dynamic -> IO DescBuff+sizeDesc t = flip with (Sig.descBuff) $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_sizeDesc s' t'++-- | Removes all singleton dimensions of the tensor.+_squeeze :: Dynamic -> Dynamic -> IO ()+_squeeze t0 t1 = withLift $ Sig.c_squeeze+  <$> managedState+  <*> managedTensor t1+  <*> managedTensor t0++-- | Removes a singleton dimensions of the tensor at a given dimension.+squeeze1d_+  :: Dynamic -- ^ tensor to mutate+  -> Word    -- ^ dimension to squeeze+  -> IO ()+squeeze1d_ t d = _squeeze1d t t d++-- | Removes a singleton dimensions of the tensor at a given dimension.+_squeeze1d+  :: Dynamic -- ^ tensor to mutate as return (C-Style)+  -> Dynamic -- ^ source tensor+  -> Word    -- ^ dimension to squeeze+  -> IO ()+_squeeze1d t0 t1 d = withLift $ Sig.c_squeeze1d+  <$> managedState+  <*> managedTensor t1+  <*> managedTensor t0+  <*> pure (fromIntegral d)++-- | get the underlying storage of a tensor+storage :: Dynamic -> Storage+storage t = unsafeDupablePerformIO . withStorage $ Sig.c_storage+  <$> managedState+  <*> managedTensor t+{-# NOINLINE storage #-}+{-# WARNING storage "extracting and using a tensor's storage can make your program unsafe. You are warned." #-}++-- | get the storage offset of a tensor+storageOffset :: Dynamic -> StorageOffset+storageOffset t = fromIntegral . unsafeDupablePerformIO . withLift $ Sig.c_storageOffset+  <$> managedState+  <*> managedTensor t+{-# NOINLINE storageOffset #-}++-- | Returns the jump necessary to go from one element to the next one in the+-- specified dimension dim.+stride+  :: Dynamic   -- ^ tensor to query+  -> Word      -- ^ dimension of tensor+  -> IO Stride -- ^ stride of dimension+stride t a = flip with (pure . fromIntegral) . (liftIO =<<) $ Sig.c_stride+  <$> managedState+  <*> managedTensor t+  <*> pure (fromIntegral a)++-- | Returns a tensor where dimensions dim1 and dim2 have been swapped.+_transpose+  :: Dynamic  -- ^ tensor to mutate into the result.+  -> Dynamic  -- ^ source tensor to use for data.+  -> Word   -- ^ dim1+  -> Word   -- ^ dim2+  -> IO ()+_transpose t0 t1 a b = withLift $ Sig.c_transpose+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)++-- | Returns a tensor which contains all slices of size size in the dimension dim.+-- Step between two slices is given by step.+--+-- If sizedim is the original size of dimension dim, the size of dimension dim+-- in the returned tensor will be (sizedim - size) / step + 1+--+-- An additional dimension of size size is appended in the returned tensor.+--+-- FIXME: this still takes C-like arguments which mutates the first arg inplace.+_unfold+  :: Dynamic  -- ^ tensor to mutate into the result.+  -> Dynamic  -- ^ source tensor to use for data.+  -> Word     -- ^ dimension to operate on+  -> Size+  -> Step+  -> IO ()+_unfold t0 t1 a b c = with2DynamicState t0 t1 $ \s' t0' t1' ->+  Sig.c_unfold s' t0' t1' (fromIntegral a) (fromIntegral b) (fromIntegral c)++-- | unsqueeze a tensor inplace+unsqueeze1d_+  :: Dynamic  -- ^ tensor to mutate+  -> Word     -- ^ dimension to unsqueeze+  -> IO ()+unsqueeze1d_ t = _unsqueeze1d t t++-- | unsqueeze a tensor, adding a singleton dimension at the specified dimval.+_unsqueeze1d+  :: Dynamic  -- ^ tensor to mutate into the result.+  -> Dynamic  -- ^ source tensor to use for data.+  -> Word     -- ^ dimension to unsqueeze+  -> IO ()+_unsqueeze1d t0 t1 d = withLift $ Sig.c_unsqueeze1d+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral d)++-- ========================================================================= --+-- User API (can be bundled into the above)+-- ========================================================================= --++-- | return the a runtime shape representing the dimensions of a 'Dynamic'+shape :: Dynamic -> [Word]+shape t = case nDimension t of+  0 -> []+  d -> (size t . fromIntegral) <$> [0.. d - 1]++-- | set the storage dimensionality of a dynamic tensor, inplace, to any new size and stride pair.+setStorageDim_ :: Dynamic -> Storage -> StorageOffset -> [(Size, Stride)] -> IO ()+setStorageDim_ t s o = \case+  []           -> throwNE "can't setStorage on an empty dimension."+  [x]          -> setStorage1d_ t s o x+  [x, y]       -> setStorage2d_ t s o x y+  [x, y, z]    -> setStorage3d_ t s o x y z+  [x, y, z, q] -> setStorage4d_ t s o x y z q+  _            -> throwGT4 "setStorage"+{-# WARNING setStorageDim_ "mutating a tensor's storage can make your program unsafe. You are warned." #-}++-- | set a value of a dynamic tensor, inplace, with any dimensionality.+setDim_ :: Dynamic -> Dims (d::[Nat]) -> HsReal -> IO ()+setDim_ t d !v = do+ threadDelay 1000+ case fromIntegral <$> listDims d of+  []           -> throwNE "can't set on an empty dimension."+  [x]          -> set1d_ t x       v+  [x, y]       -> set2d_ t x y     v+  [x, y, z]    -> set3d_ t x y z   v+  [x, y, z, q] -> set4d_ t x y z q v+  _            -> throwGT4 "set"++-- | resize a dynamic tensor, inplace, to any new dimensionality+resizeDim_ :: Dynamic -> Dims (d::[Nat]) -> IO ()+resizeDim_ t d = case fromIntegral <$> listDims d of+  []              -> throwNE "can't resize to an empty dimension."+  [x]             -> resize1d_ t x+  [x, y]          -> resize2d_ t x y+  [x, y, z]       -> resize3d_ t x y z+  [x, y, z, q]    -> resize4d_ t x y z q+  [x, y, z, q, w] -> resize5d_ t x y z q w+  _ -> throwFIXME "this should be doable with resizeNd" "resizeDim"+  -- ds              -> _resizeNd t (genericLength ds) ds+                            -- (error "resizeNd_'s stride should be given a c-NULL or a haskell-nullPtr")++-- | create a 1d Dynamic tensor from a list of elements.+--+-- FIXME construct this with TH, not by using 'setDim' inplace (one-by-one) which might be doing a second linear pass.+-- FIXME: CUDA doesn't like the storage allocation:++vectorEIO :: [HsReal] -> ExceptT String IO Dynamic+vectorEIO l = lift $ do+---------------------------------------------------+-- THCudaCheck FAIL file=/home/stites/git/hasktorch/vendor/aten/src/THC/generic/THCStorage.c line=150 error=11 : invalid argument+-- terminate called after throwing an instance of 'std::runtime_error'+--   what():  cuda runtime error (11) : invalid argument at /home/stites/git/hasktorch/vendor/aten/src/THC/generic/THCStorage.c:150+--   Aborted (core dumped)+-- #ifdef HASKTORCH_INTERNAL_CUDA++-- FIXME: uncomment these+  -- res <- new' (someDimsVal [genericLength l])+  -- mapM_  (upd res) (zip [0..genericLength l - 1] l)+  -- pure res++-- #else+--   -- IMPORTANT: This is safe for CPU. For GPU, I think we need to allocate and marshal a haskell list into cuda memory before continuing.+  -- let st = (Storage.fromList l) -- (deepseq l l)+  pure $ newWithStorage1d (fromList l) 0 (genericLength l, 1)+-- #endif++vectorE :: [HsReal] -> Either String Dynamic+vectorE = unsafePerformIO . runExceptT . vectorEIO+{-# NOINLINE vectorE #-}++vector :: [HsReal] -> Maybe Dynamic+vector = either (const Nothing) Just . vectorE++-- | create a 2d Dynamic tensor from a list of list of elements.+matrix :: [[HsReal]] -> ExceptT String IO Dynamic+matrix ls+  | null ls = lift (pure empty)+  | any ((ncols /=) . length) ls = ExceptT . pure $ Left "rows are not all the same length"+  | otherwise = do+-- #ifdef HASKTORCH_INTERNAL_CUDA+    -- vec <- vector (deepseq l l)+    -- lift $ go vec (someDimsVal [nrows, ncols])+    -- pure vec+-- #else+    lift $ do+      -- st <- Storage.fromList (deepseq l l)+      pure $ newWithStorage2d (fromList l) 0 (nrows, ncols) (ncols, 1)+-- #endif+ where+  l = concat ls+  go vec (SomeDims ds) = resizeDim_ vec ds++  ncols :: Integral i => i+  ncols = genericLength (head ls)++  nrows :: Integral i => i+  nrows = genericLength ls+++-- | create a 3d Dynamic tensor (ie: rectangular cuboid) from a nested list of elements.+{-# NOINLINE cuboid #-}+cuboid :: [[[HsReal]]] -> ExceptT String IO Dynamic+cuboid ls+  | isEmpty ls = lift (pure empty)+  | null ls || any null ls || any (any null) ls+                                   = ExceptT . pure . Left $ "can't accept empty lists"+  | innerDimCheck ncols        ls  = ExceptT . pure . Left $ "rows are not all the same length"+  | innerDimCheck ndepth (head ls) = ExceptT . pure . Left $ "columns are not all the same length"++  | otherwise = lift $ do+      -- st <- Storage.fromList l+      -- FIXME: test that this is correct.+      pure $ newWithStorage3d (fromList l) 0 (nrows, ncols * ndepth) (ncols, ndepth) (ndepth, 1)+-- #ifdef HASKTORCH_INTERNAL_CUDA+      -- vec <- vector (deepseq l l)+      -- lift $ go vec (someDimsVal [nrows, ncols, ndepth])+      -- lift $ go vec (someDimsVal [nrows, ncols, ndepth])+      -- print "yas"+      -- pure v+-- #else+--       -- st <- Storage.fromList (deepseq l l)+--       -- hs <- Storage.tensordata st+--+--       -- print (nrows, ncols, ndepth)+--       -- forM_ [0..nrows-1] $ \r -> do+--       -- -- forM_ [0..nrows-1] $ \r -> do+--       --   forM_ [0..ncols-1] $ \c -> do+--       --   -- forM_ [0..1] $ \c -> do+--       --     printf "\n]] "+--       --     forM_ [0..ndepth-1] $ \d -> do+--       --     -- forM_ [0..1] $ \d -> do+--       --       let v = hs List.!! ((r*ncols*ndepth) + (c*ndepth) + d)+--       --       -- let v = (x List.!! 0) List.!! r List.!! c :: HsReal+--       --       printf ((if v < 0 then " " else "  ")++"%.4f") (v :: HsReal)+--       --   putStrLn ("\n" :: String)+--       -- print "ax"+--+--       vec <- vector (deepseq l l)+--       lift $ go vec (someDimsVal [nrows, ncols, ndepth])+--+--+--       -- newWithStorage3d st 0 (nrows, ncols * ndepth) (ncols, ndepth) (ndepth, 1)+--       -- newWithStorage3d st 0 (nrows, nrows) (ncols, 1) (ndepth, 1)+--       -- newWithStorage3d st 0 (nrows, ncols*ndepth) (ncols, ndepth) (ndepth, 1)+-- #endif+ where+  l = concat (concat ls)+  go vec (SomeDims ds) = resizeDim_ vec ds >> pure vec++  isEmpty = \case+    []     -> True+    [[]]   -> True+    [[[]]] -> True+    _      -> False++  innerDimCheck :: Int -> [[x]] -> Bool+  innerDimCheck d = any ((/= d) . length)++  ndepth :: Integral i => i+  ndepth = genericLength (head (head ls))++  ncols :: Integral i => i+  ncols = genericLength (head ls)++  nrows :: Integral i => i+  nrows = genericLength ls+++-- | create a 4d Dynamic tensor (ie: hyperrectangle) from a nested list of elements.+{-# NOINLINE hyper #-}+hyper :: [[[[HsReal]]]] -> ExceptT String IO Dynamic+hyper ls+  | isEmpty ls = lift (pure empty)+  | null ls+    || any null ls+    || any (any null) ls+    || any (any (any null)) ls           = ExceptT . pure . Left $ "can't accept empty lists"+  | innerDimCheck ntime (head (head ls)) = ExceptT . pure . Left $ "rows are not all the same length"+  | innerDimCheck ndepth      (head ls)  = ExceptT . pure . Left $ "cols are not all the same length"+  | innerDimCheck ncols             ls   = ExceptT . pure . Left $ "depths are not all the same length"++  | otherwise = lift $ do+-- #ifdef HASKTORCH_INTERNAL_CUDA+      -- vec <- vector (deepseq l l)+      -- lift $ go vec (someDimsVal [nrows, ncols, ndepth, ntime])+-- #else+      -- st <- Storage.fromList (deepseq l l)+      pure $ newWithStorage4d (fromList l) 0+        (nrows, ncols * ndepth * ntime)+        (ncols, ndepth * ntime)+        (ndepth, ntime)+        (ntime, 1)+-- #endif+ where+  l = concat (concat (concat ls))+  go vec (SomeDims ds) = resizeDim_ vec ds >> pure vec++  isEmpty = \case+    []       -> True+    [[]]     -> True+    [[[]]]   -> True+    [[[[]]]] -> True+    _        -> False++  innerDimCheck :: Int -> [[x]] -> Bool+  innerDimCheck d = any ((/= d) . length)++  ntime :: Integral i => i+  ntime = genericLength (head (head (head ls)))++  ndepth :: Integral i => i+  ndepth = genericLength (head (head ls))++  ncols :: Integral i => i+  ncols = genericLength (head ls)++  nrows :: Integral i => i+  nrows = genericLength ls+++-- -- | resize a dynamic tensor with runtime 'SomeDims' representation of its new shape. Returns a pure copy of the+-- -- input tensor.+-- resizeDim :: Dynamic -> Dims (d::[Nat]) -> IO Dynamic+-- resizeDim src d = let res = newClone src in resizeDim_ res d >> pure res+--+-- -- | alias to 'resizeDim' with a runtime 'SomeDims'+-- resizeDim' :: Dynamic -> SomeDims -> IO Dynamic+-- resizeDim' t (SomeDims d) = resizeDim t d++-- | get the runtime dimension list of a dynamic tensor+getDimsList :: Integral i => Dynamic -> [i]+getDimsList t = map (fromIntegral . size t) [0 .. nDimension t - 1]++-- | alias to 'getDimList' which wraps the dimensions list in a 'SomeDims'+getSomeDims :: Dynamic -> SomeDims+getSomeDims = someDimsVal . getDimsList++-- | create a new dynamic tensor of size @Dims d@+new :: Dims (d::[Nat]) -> Dynamic+new d = case fromIntegral <$> listDims d of+  []           -> empty+  [x]          -> newWithSize1d x+  [x, y]       -> newWithSize2d x y+  [x, y, z]    -> newWithSize3d x y z+  [x, y, z, q] -> newWithSize4d x y z q+  _ -> unsafeDupablePerformIO $ do+    let t = empty+    resizeDim_ t d+    pure t+{-# NOINLINE new #-}++-- | set a specific runtime 'SomeDims' position of a dynamic tensor.+setDim'_ :: Dynamic -> SomeDims -> HsReal -> IO ()+setDim'_ t (SomeDims d) v = setDim_ t d v++-- | resize a dynamic tensor inplace with runtime 'SomeDims' representation of its new shape.+resizeDim'_ :: Dynamic -> SomeDims -> IO ()+resizeDim'_ t (SomeDims d) = resizeDim_ t d++-- | build a new tensor with a runtime 'SomeDims'+new' :: SomeDims -> Dynamic+new' (SomeDims d) = new d++-- | resize a tensor to take the shape of the second 'Dynamic' argument.+-- This is a pure function.+resizeAs+  :: Dynamic -- ^ src tensor to mutate+  -> Dynamic -- ^ a tensor only used for its shape+  -> IO Dynamic  -- ^ a new copy of src with the shape tensor's shape+resizeAs src shape = do+  let res = newClone src+  resizeAs_ res shape+  pure res++-------------------------------------------------------------------------------+-- * Helper functions++-- | run a function with a dynamic tensor and storage's underlying implementation details.+-- withDynamicStateAndStorage :: Sig.Dynamic -> Sig.Storage -> (Ptr Sig.CState -> Ptr Sig.CTensor -> Ptr Sig.CStorage -> IO x) -> IO x+-- withDynamicStateAndStorage t s fn = flip with pure $ do+--   s' <- managedState+--   t' <- managedTensor t+--   liftIO $ withForeignPtr (Sig.cstorage s) (fn s' t')++-- | exported helper function. Not actually "inplace" this is actually "with return and static dimensions"+withInplace :: (Dynamic -> IO ()) -> Dims (d::[Nat]) -> IO Dynamic+withInplace op d =+  let+    r = new d+  in op r >> pure r++-- | exported helper function. not actually "inplace" this is actually "with return and runtime dimensions"+withInplace' :: (Dynamic -> IO ()) -> SomeDims -> IO Dynamic+withInplace' op (SomeDims d) = withInplace op d++-- | exported helper function. This is actually 'inplace'+twice :: Dynamic -> (Dynamic -> Dynamic -> IO ()) -> IO Dynamic+twice t op = op t t >> pure t++-- | exported helper function. Should be renamed to @newFromSize@+-- withEmpty :: Dynamic -> (Dynamic -> IO ()) -> IO Dynamic+-- withEmpty t op = let r = new' (getSomeDimsList t) in op r >> pure r++-- | exported helper function. We can get away with this some of the time, when Torch+-- does the resizing in C, but you need to look at the c implementation+withEmpty' :: (Dynamic -> IO ()) -> IO Dynamic+withEmpty' op = let r = empty in op r >> pure r+++instance IsList Dynamic where+  type Item Dynamic = HsReal+  toList = tensordata+  fromList l = newWithStorage1d (fromList l) 0 (genericLength l, 1)++instance Show Dynamic where+  show t = vs ++ "\n" ++ desc+   where+    dims = getDimsList t+    desc = describeTensor dims (Proxy @HsReal)+    vs = showTensor+      (unsafeGet1d t)+      (unsafeGet2d t)+      (unsafeGet3d t)+      (unsafeGet4d t)+      dims++-- CPU ONLY:+--   desc :: Dynamic -> IO (DescBuff t)++
+ src/Torch/Indef/Dynamic/Tensor/Copy.hs view
@@ -0,0 +1,142 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Copy+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Functions to copy (and cast) tensors into different types.+-- This is a pure module.+-------------------------------------------------------------------------------+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Copy+  ( copy+  , copyByte+  , copyChar+  , copyShort+  , copyInt+  , copyLong+  , copyFloat+  , copyDouble+  ) where++import Foreign hiding (with)+import Foreign.C.Types+import Data.List (intercalate)+import Control.Exception.Safe (throwString)+import Control.Monad.Managed+import System.IO.Unsafe+import Torch.Types.TH (C'THState)+import qualified Torch.Types.TH as TH+import qualified Torch.Sig.Tensor as Sig+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Sig.Tensor.Copy as Sig++import qualified Torch.FFI.TH.Byte.Tensor   as B+import qualified Torch.FFI.TH.Short.Tensor  as S+import qualified Torch.FFI.TH.Int.Tensor    as I+import qualified Torch.FFI.TH.Long.Tensor   as L+import qualified Torch.FFI.TH.Char.Tensor   as C+import qualified Torch.FFI.TH.Float.Tensor  as F+import qualified Torch.FFI.TH.Double.Tensor as D++import Torch.Indef.Types++copyType+  :: (Ptr TH.C'THLongStorage -> Ptr TH.C'THLongStorage -> IO (Ptr a))+  -> FinalizerPtr a+  -> (ForeignPtr C'THState -> ForeignPtr a -> b)++  -> (Ptr CState -> Ptr CTensor -> Ptr a -> IO ())+  -> Dynamic -> b+copyType newWithSize_ fin builder cfun t+  = unsafePerformIO+  . flip with (pure . builder TH.torchstate) $ do+    s' <- managedState+    t' <- managedTensor t+    liftIO $ do+      sizes   <- Sig.c_newSizeOf s' t'+      strides <- Sig.c_newStrideOf s' t'+      target  <- newWithSize_ sizes strides++      cfun s' t' target++      newForeignPtr fin target+{-# NOINLINE copyType #-}++-- | Copy a tensor.+copy :: Dynamic -> Dynamic+copy t = unsafePerformIO . flip with pure $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ do+    target <- Sig.c_new s'+    Sig.c_resizeAs s' target t'+    Sig.c_copy s' target t'+    mkDynamic target+{-# NOINLINE copy #-}++-- | copy a tensor to a byte tensor. *Use at your own discresion*+copyByte :: Dynamic -> TH.ByteDynamic+copyByte = copyType B.c_newWithSize_ B.p_free TH.byteDynamic Sig.c_copyByte+-- | copy a tensor to a char tensor. *Use at your own discresion*+copyChar :: Dynamic -> TH.CharDynamic+copyChar   = copyType C.c_newWithSize_ C.p_free TH.charDynamic Sig.c_copyChar+-- | copy a tensor to a short tensor. *Use at your own discresion*+copyShort :: Dynamic -> TH.ShortDynamic+copyShort  = copyType S.c_newWithSize_ S.p_free TH.shortDynamic Sig.c_copyShort+-- | copy a tensor to a int tensor. *Use at your own discresion*+copyInt :: Dynamic -> TH.IntDynamic+copyInt    = copyType I.c_newWithSize_ I.p_free TH.intDynamic Sig.c_copyInt+-- | copy a tensor to a long tensor. *Use at your own discresion*+copyLong :: Dynamic -> TH.LongDynamic+copyLong   = copyType L.c_newWithSize_ L.p_free TH.longDynamic Sig.c_copyLong+-- | copy a tensor to a float tensor. *Use at your own discresion*+copyFloat :: Dynamic -> TH.FloatDynamic+copyFloat  = copyType F.c_newWithSize_ F.p_free TH.floatDynamic Sig.c_copyFloat+-- | copy a tensor to a double tensor. *Use at your own discresion*+copyDouble :: Dynamic -> TH.DoubleDynamic+copyDouble  = copyType D.c_newWithSize_ D.p_free TH.doubleDynamic Sig.c_copyDouble+-- copyDouble :: Dynamic -> TH.DoubleDynamic+-- copyDouble = copyType D.c_new_ D.p_free TH.doubleDynamic Sig.c_copyDouble D.c_resize++-- copyDouble :: Dynamic -> TH.DoubleDynamic+-- copyDouble t = unsafePerformIO . withDynamicState t $ \s' t' -> do+--   withForeignPtr TH.torchstate $ \ths' -> do+--     sizes   <- Sig.c_newSizeOf s' t'+--     strides <- Sig.c_newStrideOf s' t'+--     target  <- D.c_newWithSize ths' sizes strides+--+--     -- mapM (size t . fromIntegral) [0.. nDimension t - 1] >>=+--     Sig.c_copyDouble s' t' target+--+--     out <- TH.doubleDynamic TH.torchstate <$> newForeignPtr D.p_free target+--     pure out+++-- FIXME: reintroduce Half+-- copyHalf   :: t -> io H.Dynamic++-- #if CUDA+-- class GPUTensorCopy gpu cpu | gpu -> cpu where+--   copyCuda             :: gpu -> io gpu+--   copyIgnoringOverlaps :: gpu -> io gpu+--+--   copyCudaByte    :: gpu -> IO Cuda.ByteDynamic+--   copyCudaChar    :: gpu -> IO Cuda.CharDynamic+--   copyCudaShort   :: gpu -> IO Cuda.ShortDynamic+--   copyCudaInt     :: gpu -> IO Cuda.IntDynamic+--   copyCudaLong    :: gpu -> IO Cuda.LongDynamic+--   copyCudaDouble  :: gpu -> IO Cuda.DoubleDynamic+--+--   copyCPU         :: gpu -> IO cpu+--   copyAsyncCPU    :: gpu -> IO cpu+--+--   thCopyCuda      :: cpu -> IO gpu+--   thCopyAsyncCuda :: cpu -> IO gpu+-- #endif
+ src/Torch/Indef/Dynamic/Tensor/Index.hs view
@@ -0,0 +1,89 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Index+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Index operations for a dyanmic tensor.+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Index+  ( _indexCopy+  , _indexAdd+  , _indexFill+  , _indexSelect+  , _take+  , _put+  ) where++import Foreign+import Foreign.Ptr+import Torch.Sig.Types+import Control.Monad.Managed+import qualified Torch.Sig.Types          as Sig+import qualified Torch.Sig.Types.Global   as Sig+import qualified Torch.Sig.Tensor.Index   as Sig++import Torch.Indef.Types++-- | Copies the elements of tensor into the original tensor by selecting the indices in the order given in index. The shape of tensor must exactly match the elements indexed or an error will be thrown.+_indexCopy :: Dynamic -> Int -> IndexDynamic -> Dynamic -> IO ()+_indexCopy r i ix t = withLift $ Sig.c_indexCopy+  <$> managedState+  <*> managedTensor r+  <*> pure (fromIntegral i)+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t++-- | Accumulate the elements of tensor into the original tensor by adding to the indices in the order given in index. The shape of tensor must exactly match the elements indexed or an error will be thrown.+_indexAdd :: Dynamic -> Int -> IndexDynamic -> Dynamic -> IO ()+_indexAdd r i ix t = withLift $ Sig.c_indexAdd+  <$> managedState+  <*> managedTensor r+  <*> pure (fromIntegral i)+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t++-- | Fills the elements of the original Tensor with value val by selecting the indices in the order given in index.+_indexFill :: Dynamic -> Int -> IndexDynamic -> HsReal -> IO ()+_indexFill r i ix v = withLift $ Sig.c_indexFill+  <$> managedState+  <*> managedTensor r+  <*> pure (fromIntegral i)+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> pure (Sig.hs2cReal v)++-- | Selects the elements of the original Tensor by the index.+_indexSelect :: Dynamic -> Dynamic -> Int -> IndexDynamic -> IO ()+_indexSelect r t i ix = withLift $ Sig.c_indexSelect+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (fromIntegral i)+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))++-- | TODO+_take :: Dynamic -> Dynamic -> IndexDynamic -> IO ()+_take r t ix = withLift $ Sig.c_take+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))++-- | TODO+_put :: Dynamic -> IndexDynamic -> Dynamic -> Int -> IO ()+_put r ix t i = withLift $ Sig.c_put+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t+  <*> pure (fromIntegral i)++-- class GPUTensorIndex Dynamic where+--   _indexCopy_long :: t -> Int -> IndexDynamic t -> t -> IO ()+--   _indexAdd_long :: t -> Int -> IndexDynamic t -> t -> IO ()+--   _indexFill_long :: t -> Int -> IndexDynamic t -> Word -> IO ()+--   _indexSelect_long :: t -> t -> Int -> IndexDynamic t -> IO ()+--   _calculateAdvancedIndexingOffsets :: IndexDynamic t -> t -> Integer -> [IndexTensor t] -> IO ()
+ src/Torch/Indef/Dynamic/Tensor/Masked.hs view
@@ -0,0 +1,66 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Masked+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Operations using a mask tensor to filter which elements will be used.+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Masked where++import Foreign hiding (with)+import Control.Monad.Managed+import qualified Torch.Sig.Types as Sig+import qualified Torch.Sig.Types.Global  as Sig+import qualified Torch.Sig.Tensor.Masked as Sig++import Torch.Indef.Types++-- | fill a dynamic tensor with a value, filtered by a boolean mask tensor+maskedFill_+  :: Dynamic     -- ^ source tensor to mutate, inplace+  -> MaskDynamic -- ^ mask to fill+  -> HsReal      -- ^ value to fill+  -> IO ()+maskedFill_ d m v = withLift $ Sig.c_maskedFill+  <$> managedState+  <*> managedTensor d+  <*> managed (withForeignPtr (snd $ Sig.byteDynamicState m))+  <*> pure (hs2cReal v)++-- | copy a dynamic tensor with a value, filtered by a boolean mask tensor+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_maskedCopy+  :: Dynamic     -- ^ return tensor to mutate, inplace+  -> MaskDynamic -- ^ mask to copy with+  -> Dynamic     -- ^ source tensor to copy from+  -> IO ()+_maskedCopy t m f = withLift $ Sig.c_maskedCopy+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (snd $ Sig.byteDynamicState m))+  <*> managedTensor f++-- | select a dynamic tensor with a value, filtered by a boolean mask tensor+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_maskedSelect+  :: Dynamic     -- ^ return tensor to mutate, inplace+  -> Dynamic     -- ^ source tensor to select from+  -> MaskDynamic -- ^ mask to select with+  -> IO ()+_maskedSelect t sel m = withLift $ Sig.c_maskedSelect+  <$> managedState+  <*> managedTensor t+  <*> managedTensor sel+  <*> managed (withForeignPtr (snd $ Sig.byteDynamicState m))++-- class GPUTensorMasked t where+--   maskedFillByte   :: t -> MaskDynamic t -> HsReal t -> io ()+--   maskedCopyByte   :: t -> MaskDynamic t -> t -> io ()+--   maskedSelectByte :: t -> t -> MaskDynamic t -> io ()+
+ src/Torch/Indef/Dynamic/Tensor/Math.hs view
@@ -0,0 +1,356 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Torch provides MATLAB-like functions for manipulating Tensor objects.+-- Functions fall into several types of categories:+--+--   * Constructors like zeros, ones;+--   * Extractors like diag and triu;+--   * Element-wise mathematical operations like abs and pow;+--   * BLAS operations;+--   * Column or row-wise operations like sum and max;+--   * Matrix-wide operations like trace and norm;+--   * Convolution and cross-correlation operations like conv2;+--   * Basic linear algebra operations like eig;+--   * Logical operations on Tensors.+--+-- Unfortunately the above this comes from the Lua docs. Hasktorch doesn't+-- mimic this exactly and (FIXME) we will have to restructure this module+-- header to reflect these changes.+-------------------------------------------------------------------------------+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math where++import Foreign hiding (new, with)+import Foreign.Ptr+import Control.Monad.Managed+import Data.Foldable (foldrM, foldlM)+import Numeric.Dimensions+import System.IO.Unsafe+import qualified Foreign.Marshal as FM+import Debug.Trace+import Data.List (intercalate)+import Data.List.NonEmpty (NonEmpty((:|)))+import qualified Data.List.NonEmpty as NE+import Data.Vector (Vector)+import qualified Data.Vector as V++import Torch.Indef.Dynamic.Tensor+import Torch.Indef.Types+import qualified Torch.Indef.Index     as Ix+import qualified Torch.Sig.Tensor.Math as Sig+import qualified Torch.Sig.Types       as Sig+import qualified Torch.Sig.State       as Sig+import qualified Torch.Types.TH        as TH (IndexStorage)+++-- | fill a dynamic tensor, inplace, with the given value.+fill_ :: Dynamic -> HsReal -> IO ()+fill_ t v = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_fill s' t' (hs2cReal v)++-- | mutate a tensor, inplace, filling it with zero values.+zero_ :: Dynamic -> IO ()+zero_ t = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_zero s' t'++-- | mutate a tensor, inplace, resizing the tensor to the given IndexStorage+-- size and replacing its value with zeros.+zeros_ :: Dynamic -> IndexStorage -> IO ()+zeros_ t ix = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_zero s' t'++-- | mutate a tensor, inplace, resizing the tensor to the same shape as the second tensor argument+-- and replacing the first tensor's values with zeros.+zerosLike_+  :: Dynamic  -- ^ tensor to mutate inplace and replace contents with zeros+  -> Dynamic  -- ^ tensor to extract shape information from.+  -> IO ()+zerosLike_ t0 t1 = with2DynamicState t0 t1 Sig.c_zerosLike++-- | mutate a tensor, inplace, resizing the tensor to the given IndexStorage+-- size and replacing its value with ones.+ones_ :: Dynamic -> TH.IndexStorage -> IO ()+ones_ t ix = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  ix' <- managed $ Ix.withCPUIxStorage ix+  liftIO $ Sig.c_ones s' t' ix'++-- | mutate a tensor, inplace, resizing the tensor to the same shape as the second tensor argument+-- and replacing the first tensor's values with ones.+onesLike_+  :: Dynamic  -- ^ tensor to mutate inplace and replace contents with ones+  -> Dynamic  -- ^ tensor to extract shape information from.+  -> IO ()+onesLike_ t0 t1 = with2DynamicState t0 t1 Sig.c_onesLike++-- | returns the count of the number of elements in the matrix.+numel :: Dynamic -> Integer+numel t = fromIntegral . unsafePerformIO $ withLift $ Sig.c_numel+  <$> managedState+  <*> managedTensor t+{-# NOINLINE numel #-}++-- |+-- @+--   _reshape y x (Ix.newStorage [m, n, k, l, o])+-- @+--+-- Mutates the @y@ dynamic tensor to be reshaped as a @m × n × k × l × o@ tensor whose elements are+-- taken rowwise from @x@, which must have @m * n * k * l * o@ elements. The elements are copied into+-- the new Tensor.+_reshape :: Dynamic -> Dynamic -> TH.IndexStorage -> IO ()+_reshape t0 t1 ix = with2DynamicState t0 t1 $ \s' t0' t1' -> Ix.withCPUIxStorage ix $ \ix' ->+  Sig.c_reshape s' t0' t1' ix'++-- | pure version of '_catArray'+{-# NOINLINE catArray #-}+catArray :: NonEmpty Dynamic -> Word -> Either String Dynamic+catArray ts dv =+  case catDims ts dv of+    Left msg -> Left msg+    Right ds -> unsafePerformIO $ do+      let r = new' (someDimsVal ds)+      _catArray r ts dv+      pure $ Right r++-- | Concatenate all tensors in a given list of dynamic tensors along the given dimension.+--+-- NOTE: In C, if the dimension is not specified or if it is -1, it is the maximum+-- last dimension over all input tensors, except if all tensors are empty, then it is 1.+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_catArray+  :: Dynamic   -- ^ result to mutate+  -> NonEmpty Dynamic -- ^ tensors to concatenate+  -> Word      -- ^ dimension to concatenate along.+  -> IO ()+_catArray res ds d = runManaged $ do+  s' <- managedState+  r' <- managedTensor res+  liftIO $ do+    ds' <- FM.newArray =<< mapM (\d -> withForeignPtr (ctensor d) pure) (NE.toList ds)+    Sig.c_catArray s' r' ds' (fromIntegral $ length ds) (fromIntegral d)++-- | "Get the lower triangle of a tensor."+--+-- Mutates the first tensor to have the triangular part of the second tensor under the Kth diagonal.+-- where k=0 is the main diagonal, k>0 is above the main diagonal, and k<0 is below the main diagonal.+-- All other elements are set to 0.+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_tril :: Dynamic -> Dynamic -> Integer -> IO ()+_tril t0 t1 i0 = withLift $ Sig.c_tril+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromInteger i0)++-- | "Get the upper triangle of a tensor."+--+-- Mutates the first tensor to have the triangular part of the second tensor above the Kth diagonal.+-- where k=0 is the main diagonal, k>0 is above the main diagonal, and k<0 is below the main diagonal.+-- All other elements are set to 0.+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_triu :: Dynamic -> Dynamic -> Integer -> IO ()+_triu t0 t1 i0 = withLift $ Sig.c_triu+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromInteger i0)++-- | Concatinate two dynamic tensors along the specified dimension, treating the+-- first argument as the return tensor, to be mutated in-place.+--+-- NOTE: In C, if the dimension is not specified or if it is -1, it is the maximum+-- last dimension over all input tensors, except if all tensors are empty, then it is 1.+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_cat :: Dynamic -> Dynamic -> Dynamic+  -> Word  -- ^ dimension to concatenate along+  -> IO ()+_cat t0 t1 t2 i = runManaged $ do+  s'  <- managedState+  t0' <- managedTensor t0+  t1' <- managedTensor t1+  t2' <- managedTensor t2+  liftIO $ Sig.c_cat s' t0' t1' t2' (fromIntegral i)++-- | pure version of '_cat'+{-# NOINLINE cat #-}+cat :: Dynamic -> Dynamic -> Word -> Either String Dynamic+cat t0 t1 dv =+  case catDims (t0:|[t1]) dv of+    Left msg -> Left msg+    Right ds -> unsafePerformIO $ do+      let r = new' (someDimsVal ds)+      _cat r t0 t1 dv+      pure $ Right r+ where+  iv = fromIntegral dv+  s0 = shape t0+  s1 = shape t1++catDims :: NonEmpty Dynamic -> Word -> Either String [Word]+catDims ts dv+  | any ((length s /=) . length) ss = Left "Dimensions must all be same length."+  | all ((ix >=) . length) shapes = Left "Cat dimension must exist on tensors."+  | otherwise =+  case foldlM go 0 ss of+    Nothing -> Left $+      "Dimensionality error: all dimensions must match except in the cat-dimensions. " +++      "Dimensions include: " ++ intercalate ", " (show <$> s:ss) ++ "."+    Just cd -> Right (V.toList $ s V.// [(ix, cd)])+ where+  ix :: Int+  ix = fromIntegral dv++  shapes :: NonEmpty (Vector Word)+  shapes@(s:|ss) = fmap (V.fromList . shape) ts++  go :: Word -> Vector Word -> Maybe Word+  go catdim nxt =+    if length s == length (V.ifilter (\i' j -> s V.! i' == j || i' == ix) nxt)+    then pure $ catdim + nxt V.! ix+    else Nothing++-- | Finds and returns a LongTensor corresponding to the subscript indices of all non-zero elements in tensor.+--+-- C-Style: In the classic Torch C-style, the first argument is treated as the return type and is mutated in-place.+_nonzero :: IndexDynamic -> Dynamic -> IO ()+_nonzero ix t = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Ix.withDynamicState ix $ \_ ix' -> Sig.c_nonzero s' ix' t'++-- | Returns the trace (sum of the diagonal elements) of a matrix x. This is equal to the sum of the+-- eigenvalues of x.+ttrace :: Dynamic -> HsAccReal+ttrace t = unsafePerformIO . flip with (pure . c2hsAccReal) $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_trace s' t'+{-# NOINLINE ttrace #-}++-- | mutates a tensor to be an @n × m@ identity matrix with ones on the diagonal and zeros elsewhere.+eye_+  :: Dynamic  -- ^ tensor to mutate inplace+  -> Integer  -- ^ @n@ dimension in an @n × m@ matrix+  -> Integer  -- ^ @m@ dimension in an @n × m@ matrix+  -> IO ()+eye_ t0 l0 l1 = runManaged $ do+  s'  <- managedState+  t0' <- managedTensor t0+  liftIO $ Sig.c_eye s' t0' (fromIntegral l0) (fromIntegral l1)++-- | identical to a direct C call to the @arange@, or @range@ with special consideration for floating precision types.+_arange :: Dynamic -> HsAccReal -> HsAccReal -> HsAccReal -> IO ()+_arange t0 a0 a1 a2 = runManaged $ do+  s'  <- managedState+  t0' <- managedTensor t0+  liftIO $ Sig.c_arange s' t0' (hs2cAccReal a0) (hs2cAccReal a1) (hs2cAccReal a2)++-- | identical to a direct C call to the @arange@, or @range@ with special consideration for floating precision types.+arange :: HsAccReal -> HsAccReal -> HsAccReal -> Dynamic+arange a0 a1 a2 = unsafePerformIO $ do+  let t = empty+  _arange t a0 a1 a2+  return t+{-# NOINLINE arange #-}++-- | mutate a Tensor inplace, filling it with values from @min@ to @max@ with @step@. Will make the tensor take a+-- shape of size @floor((y - x) / step) + 1@.+range_+  :: Dynamic    -- ^ tensor to mutate+  -> HsAccReal  -- ^ @min@ value+  -> HsAccReal  -- ^ @max@ value+  -> HsAccReal  -- ^ @step@ size+  -> IO ()+range_ t0 a0 a1 a2 = runManaged $ do+  s'  <- managedState+  t0' <- managedTensor t0+  liftIO $ Sig.c_range s' t0' (hs2cAccReal a0) (hs2cAccReal a1) (hs2cAccReal a2)++-- | pure version of 'range_'+range+  :: Dims (d::[Nat])+  -> HsAccReal+  -> HsAccReal+  -> HsAccReal+  -> Dynamic+range d a b c = unsafePerformIO $ withInplace (\r -> range_ r a b c) d+{-# NOINLINE range #-}++-- | create a 'Dynamic' tensor with a given dimension and value+--+-- We can get away 'unsafePerformIO' this as constant is pure and thread-safe+constant :: Dims (d :: [Nat]) -> HsReal -> Dynamic+constant d v = unsafePerformIO $ let r = new d in fill_ r v >> pure r+{-# NOINLINE constant #-}++-- | direct call to the C-FFI of @diag@, mutating the first tensor argument with+-- the data from the remaining aruments.+_diag :: Dynamic -> Dynamic -> Int -> IO ()+_diag t0 t1 i0 = with2DynamicState t0 t1 $ \s' t0' t1' -> Sig.c_diag s' t0' t1' (fromIntegral i0)++-- | mutates the tensor inplace and replaces it with the given k-th diagonal,+-- where k=0 is the main diagonal, k>0 is above the main diagonal, and k<0 is+-- below the main diagonal.+diag_ :: Dynamic -> Int -> IO ()+diag_ t d = _diag t t d++-- | returns the k-th diagonal of the input tensor, where k=0 is the main diagonal,+-- k>0 is above the main diagonal, and k<0 is below the main diagonal.+diag :: Dynamic -> Int -> Dynamic+diag t d = unsafePerformIO $ let r = new' (getSomeDims t) in _diag r t d >> pure r+{-# NOINLINE diag #-}++-- | returns a diagonal matrix with diagonal elements constructed from the input tensor+diag1d :: Dynamic -> Dynamic+diag1d t = diag t 1++-- | helper function for 'onesLike' and 'zerosLike'+_tenLike+  :: (Dynamic -> Dynamic -> IO ())+  -> Dims (d::[Nat]) -> IO Dynamic+_tenLike _fn d = do+  let+    src = new d+    shape = new d+  _fn src shape+  pure src+{-# WARNING _tenLike "this should not be exported outside of hasktorch" #-}++-- | pure version of 'onesLike_'+onesLike :: Dims (d::[Nat]) -> Dynamic+onesLike = unsafePerformIO . _tenLike onesLike_+{-# NOINLINE onesLike #-}++-- | pure version of 'zerosLike_'+zerosLike :: Dims (d::[Nat]) -> Dynamic+zerosLike = unsafePerformIO . _tenLike zerosLike_+{-# NOINLINE zerosLike #-}+++-- class CPUTensorMath t where+--   match    :: t -> t -> t -> IO (HsReal t)+--   kthvalue :: t -> IndexDynamic t -> t -> Integer -> Int -> IO Int+--   randperm :: t -> Generator t -> Integer -> IO ()++
+ src/Torch/Indef/Dynamic/Tensor/Math/Blas.hs view
@@ -0,0 +1,250 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Blas+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Blas functions.+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Blas+  ( addmv+  , addmm+  , addr+  , addbmm+  , baddbmm++  , addmv_+  , addmm_+  , addr_+  , addbmm_+  , baddbmm_++  , dot+  , (<.>)+  ) where+++import Control.Monad.Managed (with)+import Control.Monad.IO.Class (liftIO)+import Foreign hiding (with)+import GHC.Int+import System.IO.Unsafe+import Debug.Trace++import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor+import qualified Torch.Sig.Tensor.Math.Blas as Sig+++blasOp+  :: (Ptr CState -> Ptr CTensor -> CReal -> Ptr CTensor -> CReal -> Ptr CTensor -> Ptr CTensor -> IO ())+  -> Dynamic -> HsReal -> Dynamic -> HsReal -> Dynamic -> Dynamic -> IO ()+blasOp fn r a x b y z =+  with2DynamicState r x $ \s' r' x' ->+    with2DynamicState y z $ \_ y' z' ->+      fn s' r' (hs2cReal a) x' (hs2cReal b) y' z'+++_addmv   = blasOp Sig.c_addmv+_addmm   = blasOp Sig.c_addmm+_addr    = blasOp Sig.c_addr+_addbmm  = blasOp Sig.c_addbmm+_baddbmm = blasOp Sig.c_baddbmm++-- | Performs the dot product between two tensors. The number of elements must match: both tensors are+-- seen as a 1D vector.+dot :: Dynamic -> Dynamic -> HsAccReal+dot a b = unsafeDupablePerformIO $ flip with (fmap c2hsAccReal)+   $  Sig.c_dot+  <$> managedState+  <*> managedTensor a+  <*> managedTensor b+{-# NOINLINE dot #-}++-- class GPUTensorMathBlas t where+--   btrifact :: t -> IntTensor -> IntTensor -> Int -> t -> io ()+--   btrisolve :: t -> t -> t -> IntTensor -> io ()+++-- | inline alias of 'dot'+(<.>) :: Dynamic -> Dynamic -> HsAccReal+(<.>) = dot++mkNewFunction+  :: (Dynamic -> HsReal -> Dynamic -> HsReal -> Dynamic -> Dynamic -> IO ())+  -> HsReal -> Dynamic -> HsReal -> Dynamic -> Dynamic -> Dynamic+mkNewFunction op a m b x y = unsafeDupablePerformIO $+  let r = new' (getSomeDims x)+  in op r a m b x y >> pure r+{-# NOINLINE mkNewFunction #-}++mkInplaceFunction+  :: (Dynamic -> HsReal -> Dynamic -> HsReal -> Dynamic -> Dynamic -> IO ())+  -> HsReal -> Dynamic -> HsReal -> Dynamic -> Dynamic -> IO ()+mkInplaceFunction op a m b x y = op m a m b x y++-- | Performs a matrix-vector multiplication between @mat@ (2D Tensor) and @vec2@+-- (1D Tensor) and add it to @vec1@.+--+-- Values @v1@ and @v2@ are scalars that multiply @vec1@ and @vec2@ respectively.+-- They are optional in C and we may be able to add this to the API in the future.+--+-- In other words,+--+-- @+--   res = (v1 * vec1) + (v2 * (mat * vec2))+-- @+--+-- Sizes must respect the matrix-multiplication operation: if @mat@ is a @n × m@+-- matrix, @vec2@ must be vector of size @m@ and @vec1@ must be a vector of size+-- @n@.+addmv+  :: HsReal    -- ^ v1+  -> Dynamic   -- ^ vec1+  -> HsReal    -- ^ v2+  -> Dynamic   -- ^ mat+  -> Dynamic   -- ^ vec2+  -> Dynamic -- ^ res+addmv = mkNewFunction _addmv++-- | Inline version of 'addmv', mutating @vec1@ inplace.+addmv_+  :: HsReal    -- ^ v1+  -> Dynamic   -- ^ vec1+  -> HsReal    -- ^ v2+  -> Dynamic   -- ^ mat+  -> Dynamic   -- ^ vec2+  -> IO ()+addmv_ = mkInplaceFunction _addmv++-- | Performs a matrix-matrix multiplication between @mat1@ (2D Tensor) and @mat2@ (2D Tensor).+--+-- Values @v1@ and @v2@ are scalars that multiply @M@ and @mat1 * mat2@ respectively.+-- They are optional in C and we may be able to add this to the API in the future.+--+-- In other words,+--+-- @+--   res = (v1 * M) + (v2 * mat1 * mat2)+-- @+--+-- If @mat1@ is a @n × m@ matrix, @mat2@ a @m × p@ matrix, @M@ must be a @n × p@ matrix.+addmm+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ M+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ mat1+  -> Dynamic    -- ^ mat2+  -> Dynamic -- ^ res+addmm = mkNewFunction _addmm++-- | Inline version of 'addmm', mutating @M@ inplace.+addmm_+  :: HsReal    -- ^ v1+  -> Dynamic   -- ^ M+  -> HsReal    -- ^ v2+  -> Dynamic   -- ^ mat1+  -> Dynamic   -- ^ mat2+  -> IO ()+addmm_ = mkInplaceFunction _addmm++-- | Performs the outer-product between @vec1@ (1D Tensor) and @vec2@+-- (1D Tensor).+--+-- Values @v1@ and @v2@ are scalars that multiply @mat_ij@ and @vec1_i [out] vec2_j@ respectively.+-- They are optional in C and we may be able to add this to the API in the future.+--+-- Thus:+--+-- @+--   res_ij = (v1 * mat_ij) + (v2 * vec1_i * vec2_j)+-- @+--+-- If @vec1_@ is a vector of size @i@ and @vec2_j@ is a vector of size @j@, then+-- @mat_ij@ must be a matrix of size @i × j@.+addr+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ mat_ij+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ vec1_i+  -> Dynamic    -- ^ vec2_j+  -> Dynamic -- ^ res_ij+addr = mkNewFunction _addr++-- | Inline version of 'addr', mutating @mat_ij@ in-place.+addr_+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ mat_ij -- mutated inplace+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ vec1_i+  -> Dynamic    -- ^ vec2_j+  -> IO ()+addr_ = mkInplaceFunction _addr++-- | Batch matrix-matrix product of matrices stored in @batch1@ and @batch2@,+-- with a reduced add step (all matrix multiplications get accumulated in+-- a single place).+--+-- @batch1@ and @batch2@ must be 3D Tensors each containing the same number+-- of matrices. If @batch1@ is a @b × n × m@ Tensor, @batch2@ a @b × m × p@+-- Tensor, @res@ will be a @n × p@ Tensor.+--+-- In other words,+--+-- @+--   res = (v1 * M) + (v2 * sum(batch1_i * batch2_i, i = 1, b))+-- @+addbmm+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ M+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ batch1_i+  -> Dynamic    -- ^ batch2_i+  -> Dynamic -- ^ res+addbmm  = mkNewFunction     _addbmm++-- | Inline version of 'addbmm', mutating @M@ in-place.+addbmm_+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ M+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ batch1_i+  -> Dynamic    -- ^ batch2_i+  -> IO ()+addbmm_ = mkInplaceFunction _addbmm++-- | Batch matrix matrix product of matrices stored in batch1 and batch2, with+-- batch add.+--+-- @batch1@ and @batch2@ must be 3D Tensors each containing the same number of+-- matrices. If @batch1@ is a @b × n × m@ Tensor, @batch2@ a @b × m × p@ Tensor,+-- @res@ will be a @b × n × p@ Tensor.+--+-- In other words,+--+-- @+--   res_i = (v1 * M_i) + (v2 * batch1_i * batch2_i)+-- @+baddbmm+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ M_i+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ batch1_i+  -> Dynamic    -- ^ batch2_i+  -> Dynamic -- ^ res_i+baddbmm  = mkNewFunction     _baddbmm++-- | Inline version of 'baddbmm', mutating @M_i@ in-place.+baddbmm_+  :: HsReal     -- ^ v1+  -> Dynamic    -- ^ M_i+  -> HsReal     -- ^ v2+  -> Dynamic    -- ^ batch1_i+  -> Dynamic    -- ^ batch2_i+  -> IO ()+baddbmm_ = mkInplaceFunction _baddbmm+
+ src/Torch/Indef/Dynamic/Tensor/Math/Compare.hs view
@@ -0,0 +1,101 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Compare+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Compare a tensor with a scala value+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Compare+  ( ltValue, ltValueT, ltValueT_+  , leValue, leValueT, leValueT_+  , gtValue, gtValueT, gtValueT_+  , geValue, geValueT, geValueT_+  , neValue, neValueT, neValueT_+  , eqValue, eqValueT, eqValueT_+  ) where++import Foreign hiding (with, new)+import Foreign.Ptr+import Numeric.Dimensions+import System.IO.Unsafe+import Control.Monad.Managed++import Torch.Indef.Types+import Torch.Indef.Mask+import Torch.Indef.Dynamic.Tensor++import qualified Torch.Sig.Tensor.Math.Compare as Sig++_ltValueT, _leValueT, _gtValueT, _geValueT, _neValueT, _eqValueT+  :: Dynamic -> Dynamic -> HsReal -> IO ()+_ltValueT = compareValueTOp Sig.c_ltValueT+_leValueT = compareValueTOp Sig.c_leValueT+_gtValueT = compareValueTOp Sig.c_gtValueT+_geValueT = compareValueTOp Sig.c_geValueT+_neValueT = compareValueTOp Sig.c_neValueT+_eqValueT = compareValueTOp Sig.c_eqValueT++compareValueTOp+  :: (Ptr CState -> Ptr CTensor -> Ptr CTensor -> CReal -> IO ())+  -> Dynamic -> Dynamic -> HsReal -> IO ()+compareValueTOp fn a b v = withLift $ fn+  <$> managedState+  <*> managedTensor a+  <*> managedTensor b+  <*> pure (hs2cReal v)++compareTensorOp+  :: (Ptr CState -> Ptr CByteTensor -> Ptr CTensor -> CReal -> IO ())+  -> Dynamic -> HsReal -> MaskDynamic+compareTensorOp op t0 v = unsafeDupablePerformIO . flip with pure $ do+  s' <- managedState+  t' <- managedTensor t0+  let bt = newMaskDyn' (getSomeDims t0)+  bt' <- managed $ withMask bt+  liftIO $ op s' bt' t' (hs2cReal v)+  pure bt+{-# NOINLINE compareTensorOp #-}++-- | return a byte tensor which contains boolean values indicating the relation between a tensor and a given scalar.+ltValue, leValue, gtValue, geValue, neValue, eqValue+  :: Dynamic -> HsReal -> MaskDynamic+ltValue = compareTensorOp Sig.c_ltValue+leValue = compareTensorOp Sig.c_leValue+gtValue = compareTensorOp Sig.c_gtValue+geValue = compareTensorOp Sig.c_geValue+neValue = compareTensorOp Sig.c_neValue+eqValue = compareTensorOp Sig.c_eqValue++-- | return a tensor which contains numeric values indicating the relation between a tensor and a given scalar.+-- 0 stands for false, 1 stands for true.+ltValueT, leValueT, gtValueT, geValueT, neValueT, eqValueT+  :: Dynamic -> HsReal -> Dynamic+ltValueT  a b = unsafeDupablePerformIO $ let r = empty in _ltValueT r a b >> pure r+leValueT  a b = unsafeDupablePerformIO $ let r = empty in _leValueT r a b >> pure r+gtValueT  a b = unsafeDupablePerformIO $ let r = empty in _gtValueT r a b >> pure r+geValueT  a b = unsafeDupablePerformIO $ let r = empty in _geValueT r a b >> pure r+neValueT  a b = unsafeDupablePerformIO $ let r = empty in _neValueT r a b >> pure r+eqValueT  a b = unsafeDupablePerformIO $ let r = empty in _eqValueT r a b >> pure r+{-# NOINLINE ltValueT #-}+{-# NOINLINE leValueT #-}+{-# NOINLINE gtValueT #-}+{-# NOINLINE geValueT #-}+{-# NOINLINE neValueT #-}+{-# NOINLINE eqValueT #-}++-- | mutate a tensor in-place with its numeric relation to a given scalar, where 0 stands for false and+-- 1 stands for true.+ltValueT_, leValueT_, gtValueT_, geValueT_, neValueT_, eqValueT_+  :: Dynamic -> HsReal -> IO ()+ltValueT_ a b = _ltValueT a a b+leValueT_ a b = _leValueT a a b+gtValueT_ a b = _gtValueT a a b+geValueT_ a b = _geValueT a a b+neValueT_ a b = _neValueT a a b+eqValueT_ a b = _eqValueT a a b+
+ src/Torch/Indef/Dynamic/Tensor/Math/CompareT.hs view
@@ -0,0 +1,104 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.CompareT+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Compare two tensors+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.CompareT+  ( ltTensor, ltTensorT, ltTensorT_+  , leTensor, leTensorT, leTensorT_+  , gtTensor, gtTensorT, gtTensorT_+  , geTensor, geTensorT, geTensorT_+  , neTensor, neTensorT, neTensorT_+  , eqTensor, eqTensorT, eqTensorT_+  ) where++import Foreign hiding (with, new)+import Foreign.Ptr+import System.IO.Unsafe+import Numeric.Dimensions+import qualified Torch.Sig.Tensor.Math.CompareT as Sig++import Torch.Indef.Mask+import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor++_ltTensorT, _leTensorT, _gtTensorT, _geTensorT, _neTensorT, _eqTensorT+  :: Dynamic -> Dynamic -> Dynamic -> IO ()+_ltTensorT = compareTensorTOp Sig.c_ltTensorT+_leTensorT = compareTensorTOp Sig.c_leTensorT+_gtTensorT = compareTensorTOp Sig.c_gtTensorT+_geTensorT = compareTensorTOp Sig.c_geTensorT+_neTensorT = compareTensorTOp Sig.c_neTensorT+_eqTensorT = compareTensorTOp Sig.c_eqTensorT++compareTensorTOp+  :: (Ptr CState -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> IO ())+  -> Dynamic -> Dynamic -> Dynamic -> IO ()+compareTensorTOp fn a b c = withLift $ fn+  <$> managedState+  <*> managedTensor a+  <*> managedTensor b+  <*> managedTensor c+++compareTensorOp+  :: (Ptr CState -> Ptr CByteTensor -> Ptr CTensor -> Ptr CTensor -> IO ())+  -> Dynamic -> Dynamic -> MaskDynamic+compareTensorOp op t0 t1 = unsafeDupablePerformIO $ do+  let+    sd = getSomeDims t0+    bt = newMaskDyn' sd+  with2DynamicState t0 t1 $ \s' t0' t1' ->+    withMask bt $ \bt' -> op s' bt' t0' t1'+  pure bt+{-# NOINLINE compareTensorOp #-}++-- | Return a byte tensor which contains boolean values indicating the relation between two tensors.+ltTensor, leTensor, gtTensor, geTensor, neTensor, eqTensor+  :: Dynamic -> Dynamic -> MaskDynamic+ltTensor = compareTensorOp Sig.c_ltTensor+leTensor = compareTensorOp Sig.c_leTensor+gtTensor = compareTensorOp Sig.c_gtTensor+geTensor = compareTensorOp Sig.c_geTensor+neTensor = compareTensorOp Sig.c_neTensor+eqTensor = compareTensorOp Sig.c_eqTensor++-- | return a tensor which contains numeric values indicating the relation between two tensors.+-- 0 stands for false, 1 stands for true.+ltTensorT, leTensorT, gtTensorT, geTensorT, neTensorT, eqTensorT+  :: Dynamic  -- ^ source tensor.+  -> Dynamic  -- ^ tensor to compare with.+  -> Dynamic  -- ^ new return tensor.+ltTensorT  a b = unsafeDupablePerformIO $ let r = empty in _ltTensorT r a b >> pure r+leTensorT  a b = unsafeDupablePerformIO $ let r = empty in _leTensorT r a b >> pure r+gtTensorT  a b = unsafeDupablePerformIO $ let r = empty in _gtTensorT r a b >> pure r+geTensorT  a b = unsafeDupablePerformIO $ let r = empty in _geTensorT r a b >> pure r+neTensorT  a b = unsafeDupablePerformIO $ let r = empty in _neTensorT r a b >> pure r+eqTensorT  a b = unsafeDupablePerformIO $ let r = empty in _eqTensorT r a b >> pure r+{-# NOINLINE ltTensorT #-}+{-# NOINLINE leTensorT #-}+{-# NOINLINE gtTensorT #-}+{-# NOINLINE geTensorT #-}+{-# NOINLINE neTensorT #-}+{-# NOINLINE eqTensorT #-}++-- | mutate a tensor in-place with its numeric relation to the second tensor of the same size,+-- where 0 stands for false and 1 stands for true.+ltTensorT_, leTensorT_, gtTensorT_, geTensorT_, neTensorT_, eqTensorT_+  :: Dynamic  -- ^ source tensor to mutate inplace.+  -> Dynamic  -- ^ tensor to compare with.+  -> IO ()+ltTensorT_ a b = _ltTensorT a a b+leTensorT_ a b = _leTensorT a a b+gtTensorT_ a b = _gtTensorT a a b+geTensorT_ a b = _geTensorT a a b+neTensorT_ a b = _neTensorT a a b+eqTensorT_ a b = _eqTensorT a a b+
+ src/Torch/Indef/Dynamic/Tensor/Math/Floating.hs view
@@ -0,0 +1,55 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Floating+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Floating where++import Control.Monad.Managed+import GHC.Int+import Numeric.Dimensions+import System.IO.Unsafe++import qualified Torch.Sig.Tensor.Math.Floating as Sig+import Torch.Indef.Dynamic.Tensor (empty)++import Torch.Indef.Types++-- | Returns a one-dimensional Tensor of @n@ equally spaced points between @x1@ and @x2@.+linspace+  :: HsReal  -- ^ @x1@+  -> HsReal  -- ^ @x2@+  -> Int64   -- ^ @n@+  -> Dynamic+linspace a b l = unsafeDupablePerformIO $ let t = empty in linspace_ t a b l >> pure t+{-# NOINLINE linspace #-}++-- | inplace version of 'linspace'+linspace_ :: Dynamic -> HsReal -> HsReal -> Int64 -> IO ()+linspace_ r a b l = runManaged $ do+  s' <- managedState+  r' <- managedTensor r+  liftIO $ Sig.c_linspace s' r' (hs2cReal a) (hs2cReal b) (fromIntegral l)++-- | Returns a one-dimensional Tensor of @n@ logarithmically, equally spaced points between @10^x1@ and @10^x2@.+logspace+  :: HsReal  -- ^ @x1@+  -> HsReal  -- ^ @x2@+  -> Int64   -- ^ @n@+  -> Dynamic+logspace a b l = unsafeDupablePerformIO $ let t = empty in logspace_ t a b l >> pure t+{-# NOINLINE logspace #-}++-- | inplace version of 'logspace'+logspace_ :: Dynamic -> HsReal -> HsReal -> Int64 -> IO ()+logspace_ r a b l = runManaged $ do+  s' <- managedState+  r' <- managedTensor r+  liftIO $ Sig.c_logspace s' r' (hs2cReal a) (hs2cReal b) (fromIntegral l)++
+ src/Torch/Indef/Dynamic/Tensor/Math/Lapack.hs view
@@ -0,0 +1,494 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Lapack+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Functions in this section are implemented with an interface to LAPACK+-- libraries. If LAPACK libraries are not found during compilation step, then+-- these functions will not be available. Hasktorch has not been tested without+-- LAPACK functionality, so that behaviour is currently undefined for an end+-- user. (FIXME) Someone needs to test LAPACK-less compilation steps.+-------------------------------------------------------------------------------+{-# LANGUAGE LambdaCase #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Lapack+  ( getri  , getri_+  , potrf  , potrf_+  , potri  , potri_+  , potrs  , potrs_+  , qr     , qr_     , _geqrf+  , geev   , geev_   , eig     , eig_+  , syev   , syev_   , symeig  , symeig_+  , gesv   , gesv_+  , gels   , gels_+  , gesvd  , gesvd_+  , gesvd2 , gesvd2_++  , Triangle(..), EigenReturn(..), ComputeSingularValues(..)+  ) where++import Control.Monad.Managed+import Data.Coerce+import Foreign+import Foreign.C.Types+import Foreign.C.String+import Foreign.Marshal.Array+import System.IO.Unsafe+import Torch.Indef.Dynamic.Tensor (empty)+import qualified Torch.Sig.Tensor.Math.Lapack as Sig++import Torch.Indef.Types++-- |+-- Docs taken from MAGMA documentation at: http://icl.cs.utk.edu/projectsfiles/magma/doxygen/group__magma__getri.html+--+-- getri computes the inverse of a matrix using the LU factorization computed by+-- 'getrf'.+--+-- This method inverts @U@ and then computes @inv(A)@ by solving the system+-- @inv(A)*L = inv(U)@ for @inv(A)@.+--+-- Note that it is generally both faster and more accurate to use @gesv@, or+-- @getrf@ and @getrs@, to solve the system @AX = B@, rather than inverting the+-- matrix and multiplying to form @X = inv(A)*B@. Only in special instances+-- should an explicit inverse be computed with this routine.+getri :: Dynamic -> Dynamic+getri t = unsafeDupablePerformIO $ let r = empty in _getri r t >> pure r+{-# NOINLINE getri #-}++-- | inplace version of 'getri'+getri_ :: Dynamic -> IO ()+getri_ t = _getri t t++-- | C-style version of 'getri' and 'getri_'.+_getri :: Dynamic -> Dynamic -> IO ()+_getri a b = with2DynamicState a b Sig.c_getri++-- | Cholesky Decomposition of 2D @tensor A@. The matrix, @A@, has to be a+-- positive-definite and either symmetric or complex Hermitian.+--+-- The factorization has the form+--+-- @+--   A = U**T * U,   if UPLO = 'U', or+--   A = L  * L**T,  if UPLO = 'L',+-- @+--+-- where @U@ is an upper triangular matrix and @L@ is lower triangular.+potrf+  :: Dynamic    -- ^ matrix to decompose+  -> Triangle   -- ^ which triangle should be used.+  -> Dynamic+potrf s t = unsafeDupablePerformIO $ let r = empty in _potrf r s t >> pure r+{-# NOINLINE potrf #-}++-- | infix version of 'potrf'.+potrf_+  :: Dynamic   -- ^ matrix to decompose+  -> Triangle  -- ^ which triangle should be used.+  -> IO ()+potrf_ src t = _potrf src src t++-- | C-style version of 'potrf' and 'potrf_' where the first tensor argument is mutated inplace.+_potrf+  :: Dynamic   -- ^ tensor to place the resulting decomposition in.+  -> Dynamic   -- ^ matrix to decompose+  -> Triangle  -- ^ which triangle should be used.+  -> IO ()+_potrf ret src t = withLift $ Sig.c_potrf+  <$> managedState+  <*> managedTensor ret+  <*> managedTensor src+  <*> liftIO (triangleArg2C t)++-- | Returns the inverse of 2D @tensor A@ given its Cholesky decomposition @chol@.+--+-- Square matrix @chol@ should be triangular.+--+-- 'Triangle' specifies matrix @chol@ as either upper or lower triangular.+potri :: Dynamic -> Triangle -> Dynamic+potri s t = unsafeDupablePerformIO $ let r = empty in _potri r s t >> pure r+{-# NOINLINE potri #-}++-- | inplace version of 'potri'.+potri_ :: Dynamic -> Triangle -> IO ()+potri_ s t = _potri s s t++-- | C-style mutation of 'potri_' and 'potri'. Should not be exported.+_potri :: Dynamic -> Dynamic -> Triangle -> IO ()+_potri a b v = withLift $ Sig.c_potri+  <$> managedState+  <*> managedTensor a+  <*> managedTensor b+  <*> liftIO (triangleArg2C v)++-- | Returns the solution to linear system @AX = B@ using the Cholesky+-- decomposition @chol@ of 2D tensor @A@.+--+-- Square matrix @chol@ should be triangular; and, righthand side matrix @B@+-- should be of full rank.+--+-- 'Triangle' specifies matrix @chol@ as either upper or lower triangular.+-- /* Solve A*X = B with a symmetric positive definite matrix A using the Cholesky factorization */+potrs+  :: Dynamic    -- ^ Tensor @B@+  -> Dynamic    -- ^ Cholesky decomposition @chol@+  -> Triangle   -- ^ which triangle to use (upper or lower)+  -> Dynamic+potrs b chol t = unsafeDupablePerformIO $ let r = empty in _potrs r b chol t >> pure r+{-# NOINLINE potrs #-}++-- | Inplace version of 'potri'. Mutating tensor B in place.+potrs_+  :: Dynamic    -- ^ Tensor @B@+  -> Dynamic    -- ^ Cholesky decomposition @chol@+  -> Triangle   -- ^ which triangle to use (upper or lower)+  -> IO ()+potrs_ b chol t = _potrs b b chol t++-- | C-style mutation of 'potrs_' and 'potrs'. Should not be exported.+_potrs :: Dynamic -> Dynamic -> Dynamic -> Triangle -> IO ()+_potrs a b c v =+  triangleArg2C v >>= \v' ->+    with3DynamicState a b c $ \s' a' b' c' -> Sig.c_potrs s' a' b' c' v'++-- | Compute a QR decomposition of the matrix @x@: matrices @q@ and @r@ such that+-- @x = q * r@, with @q@ orthogonal and @r@ upper triangular. This returns the+-- thin (reduced) QR factorization.+--+-- Note that precision may be lost if the magnitudes of the elements of x are+-- large.+--+-- Note also that, while it should always give you a valid decomposition, it may+-- not give you the same one across platforms - it will depend on your LAPACK+-- implementation.+--+-- Note: Irrespective of the original strides, the returned matrix @q@ will be+-- transposed, i.e. with strides @1, m@ instead of @m, 1@.+qr :: Dynamic -> (Dynamic, Dynamic)+qr x = unsafeDupablePerformIO $ let ret = (empty, empty) in qr_ ret x >> pure ret+{-# NOINLINE qr #-}++-- | Inplace version of 'qr'+qr_ :: (Dynamic, Dynamic) -> Dynamic -> IO ()+qr_ (q, r) x = with3DynamicState q r x Sig.c_qr++-- | This is a low-level function for calling LAPACK directly. You'll generally+-- want to use 'qr' instead.+--+-- Computes a QR decomposition of @a@, but without constructing Q and R as+-- explicit separate matrices. Rather, this directly calls the underlying LAPACK+-- function @?geqrf@ which produces a sequence of "elementary reflectors". See+-- <https://software.intel.com/en-us/node/521004 LAPACK documentation from MKL>+-- for further details and <http://icl.cs.utk.edu/projectsfiles/magma/doxygen/group__magma__geqrf.html+-- for MAGMA documentation>.+--+-- Note that, because this is low-level code, hasktorch just calls Torch+-- directly.+_geqrf :: Dynamic -> Dynamic -> Dynamic -> IO ()+_geqrf a b c = with3DynamicState a b c Sig.c_geqrf++-- | @(e, V) <- geev A@ returns eigenvalues and eigenvectors of a general real+-- square matrix @A@.+--+-- @A@ and @V@ are @m × m@ matrices and @e@ is an @m@-dimensional vector.+--+-- This function calculates all right eigenvalues (and vectors) of @A@ such that+-- @A = V diag(e) V@.+--+-- The 'EigenReturn' argument defines computation of eigenvectors or eigenvalues+-- only. It determines if only eigenvalues are computed or if both eigenvalues+-- and eigenvectors are computed.+--+-- The eigenvalues returned follow LAPACK convention and are returned as complex+-- (real/imaginary) pairs of numbers (@2 * m@ dimensional tensor).+--+-- Also called the "eig" fuction in torch.+geev+  :: Dynamic                      -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn                  -- ^ whether or not to return eigenvectors.+  -> (Dynamic, Maybe Dynamic)  -- ^ (e, V) standing for eigenvalues and eigenvectors+geev m er = unsafeDupablePerformIO $ do+  let e = empty+  let v = empty+  geev_ (e, v) m er+  case er of+    ReturnEigenValues          -> pure (e, Just v)+    ReturnEigenValuesAndVector -> pure (e, Nothing)+{-# NOINLINE geev #-}++-- | alias to 'geev' to match Torch naming conventions.+eig = geev++-- | In-place version of 'geev'.+--+-- Note: Irrespective of the original strides, the returned matrix @V@ will be+-- transposed, i.e. with strides @1, m@ instead of @m, 1@.+geev_+  :: (Dynamic, Dynamic)  -- ^ (e, V) standing for eigenvalues and eigenvectors+  -> Dynamic             -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn         -- ^ whether or not to return eigenvectors.+  -> IO ()+geev_ (e, v) m er =+  eigenArg2C er >>= \er' ->+    with3DynamicState e v m $ \s' e' v' m' -> Sig.c_geev s' e' v' m' er'++-- | alias to 'geev_' to match Torch naming conventions.+eig_ = geev_+++-- | @(e, V) <- syev A@ returns eigenvalues and eigenvectors of a symmetric real matrix @A@.+--+-- @A@ and @V@ are @m × m@ matrices and @e@ is a @m@-dimensional vector.+--+-- This function calculates all eigenvalues (and vectors) of @A@ such that @A = V diag(e) V@.+--+-- The 'EigenReturn' argument defines computation of eigenvectors or eigenvalues only.+--+-- Since the input matrix @A@ is supposed to be symmetric, only one triangular portion+-- is used. The 'Triangle' argument indicates if this should be the upper or lower triangle.+syev+  :: Dynamic                      -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn                  -- ^ whether or not to return eigenvectors.+  -> Triangle                     -- ^ whether the upper or lower triangle should be used+  -> (Dynamic, Maybe Dynamic)  -- ^ (e, V) standing for eigenvalues and eigenvectors+syev m er tri = unsafeDupablePerformIO $ do+  let e = empty+  let v = empty+  syev_ (e, v) m er tri+  case er of+    ReturnEigenValues          -> pure (e, Just v)+    ReturnEigenValuesAndVector -> pure (e, Nothing)+{-# NOINLINE syev #-}++-- | alias to 'syev' to match Torch naming conventions.+symeig = syev++-- | Inplace version of 'syev'+--+-- Note: Irrespective of the original strides, the returned matrix V will be transposed, i.e. with strides 1, m instead of m, 1.+syev_+  :: (Dynamic, Dynamic)  -- ^ (e, V) standing for eigenvalues and eigenvectors+  -> Dynamic             -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn         -- ^ whether or not to return eigenvectors.+  -> Triangle            -- ^ whether the upper or lower triangle should be used+  -> IO ()+syev_ (e, v) m er tri = do+  er'  <- eigenArg2C er+  tri' <- triangleArg2C tri+  with3DynamicState e v m $ \s' e' v' m' ->+    Sig.c_syev s' e' v' m' er' tri'++-- | alias to 'syev' to match Torch naming conventions.+symeig_ = syev_++-- | @ (X, LU) <- gesv B A@ returns the solution of @AX = B@ and @LU@ contains @L@+-- and @U@ factors for @LU@ factorization of @A@.+--+-- @A@ has to be a square and non-singular matrix (a 2D tensor). @A@ and @LU@+-- are @m × m@, @X@ is @m × k@ and @B@ is @m × k@.+gesv+  :: Dynamic                -- ^ @B@+  -> Dynamic                -- ^ @A@+  -> (Dynamic, Dynamic)  -- ^ @(X, LU)@+gesv b a = unsafeDupablePerformIO $ let ret = (empty, empty) in gesv_ ret b a >> pure ret+{-# NOINLINE gesv #-}++-- | Inplace version of 'gesv'.+--+-- In this case @x@ and @lu@ will be used for temporary storage and returning the result.+--+--   * @x@ will contain the solution @X@.+--   * @lu@ will contain @L@ and @U@ factors for @LU@ factorization of @A@.+--+-- Note: Irrespective of the original strides, the returned matrices @x@ and @lu@ will be transposed,+-- i.e. with strides @1, m@ instead of @m, 1@.+gesv_+  :: (Dynamic, Dynamic)  -- ^ @(X, LU)@+  -> Dynamic             -- ^ @B@+  -> Dynamic             -- ^ @A@+  -> IO ()+gesv_ (x, lu) b a =+  with2DynamicState x lu $ \s' x' lu' ->+    with2DynamicState b a $ \_ b' a' ->+      Sig.c_gesv s' x' lu' b' a'++-- | Solution of least squares and least norm problems for a full rank @m × n@ matrix @A@.+--+--   * If @n ≤ m@, then solve @||AX-B||_F@.+--   * If @n > m@, then solve @min ||X||_F@ such that @AX = B@.+--+-- On return, first @n@ rows of @x@ matrix contains the solution and the rest+-- contains residual information. Square root of sum squares of elements of each+-- column of @x@ starting at row @n + 1@ is the residual for corresponding column.+gels :: Dynamic -> Dynamic -> (Dynamic, Dynamic)+gels b a = unsafeDupablePerformIO $ let ret = (empty, empty) in gels_ ret b a >> pure ret+{-# NOINLINE gels #-}++-- | Inplace version of 'gels'.+--+-- Note: Irrespective of the original strides, the returned matrices @resb@ and+-- @resa@ will be transposed, i.e. with strides @1, m@ instead of @m, 1@.+gels_+  :: (Dynamic, Dynamic) -- ^ @(resb, resa)@+  -> Dynamic            -- ^ @matrix b@+  -> Dynamic            -- ^ @matrix a@+  -> IO ()+gels_ (a, b) c d =+  with2DynamicState a b $ \s' a' b' ->+    with2DynamicState c d $ \_ c' d' ->+      Sig.c_gels s' a' b' c' d'+++-- | @(U, S, V) <- svd A@ returns the singular value decomposition of a real+-- matrix @A@ of size @n × m@ such that @A = USV'*@.+--+-- @U@ is @n × n@, @S@ is @n × m@ and @V@ is @m × m@.+--+-- The 'ComputeSingularValues' argument represents the number of singular values+-- to be computed. 'SomeSVs' stands for "some" (FIXME: figure out what that means)+-- and 'AllSVs' stands for all.+gesvd+  :: Dynamic+  -> ComputeSingularValues+  -> (Dynamic, Dynamic, Dynamic)+gesvd m num = unsafeDupablePerformIO $ do+  let ret = (empty, empty, empty)+  gesvd_ ret m num+  pure ret+{-# NOINLINE gesvd #-}++-- | Inplace version of 'gesvd'.+--+-- Note: Irrespective of the original strides, the returned matrix @U@ will be+-- transposed, i.e. with strides @1, n@ instead of @n, 1@.+gesvd_+  :: (Dynamic, Dynamic, Dynamic) -- ^ (u, s, v)+  -> Dynamic                     -- ^ m+  -> ComputeSingularValues       -- ^ Whether to compute all or some of the singular values+  -> IO ()+gesvd_ (u, s, v) m num = runManaged $ do+  state' <- managedState+  u' <- managedTensor u+  s' <- managedTensor s+  v' <- managedTensor v+  m' <- managedTensor m+  liftIO $ svArg2C num >>= Sig.c_gesvd state' u' s' v' m'++-- | 'gesvd', computing @A = U*Σ*transpose(V)@.+--+-- NOTE: "'gesvd', computing @A = U*Σ*transpose(V)@." is only inferred documentation. This+-- documentation was made by stites, inferring from the description of the 'gesvd' docs at+-- <https://software.intel.com/en-us/mkl-developer-reference-c-gesvd the intel mkl+-- documentation>.+gesvd2+  :: Dynamic                                 -- ^ m+  -> ComputeSingularValues                   -- ^ Whether to compute all or some of the singular values+  -> (Dynamic, Dynamic, Dynamic, Dynamic) -- ^ (u, s, v, a)+gesvd2 m csv = unsafeDupablePerformIO $ do+  let ret = (empty, empty, empty, empty)+  gesvd2_ ret m csv+  pure ret+{-# NOINLINE gesvd2 #-}++-- | Inplace version of 'gesvd2_'.+gesvd2_+  :: (Dynamic, Dynamic, Dynamic, Dynamic) -- ^ (u, s, v, a)+  -> Dynamic                              -- ^ m+  -> ComputeSingularValues                -- ^ Whether to compute all or some of the singular values+  -> IO ()+gesvd2_ (u, s, v, a) m csv = runManaged $ do+  state' <- managedState+  u' <- managedTensor u+  s' <- managedTensor s+  v' <- managedTensor v+  a' <- managedTensor a+  m' <- managedTensor m+  liftIO $ svArg2C csv >>= Sig.c_gesvd2 state' u' s' v' a' m'++-- ========================================================================= --+-- Helpers++-- | Argument to specify whether the upper or lower triangular decomposition+-- should be used in 'potrf' and 'potrf_'.+data Triangle+  = Upper   -- ^ use upper triangular matrix+  | Lower   -- ^ use lower triangular matrix+  deriving (Eq, Show)++-- | helper function to cast 'Triangle' into C arguments. This should not be exported.+triangleArg2C :: Triangle -> IO (Ptr CChar)+triangleArg2C = \case+  Upper -> newCString "U"+  Lower -> newCString "L"++-- | Argument to be passed to 'geev', 'syev', and their inplace variants.+-- Determines if the a function should only compute eigenvalues or both+-- eigenvalues and eigenvectors.+data EigenReturn+  = ReturnEigenValues+  | ReturnEigenValuesAndVector+  deriving (Eq, Show)++-- | helper function to cast 'Triangle' into C arguments. This should not be exported.+eigenArg2C :: EigenReturn -> IO (Ptr CChar)+eigenArg2C = \case+  ReturnEigenValues          -> newCString "N"+  ReturnEigenValuesAndVector -> newCString "V"++-- | Represents the number of singular values to be computed in 'gesvd' and 'gesvd2'.+-- While fairly opaque about how many values are computed, Torch says we either compute+-- "some" or all of the values.+data ComputeSingularValues+  = SomeSVs+  | AllSVs++-- | helper function to cast 'ComputeSingularValues into C arguments. This should not be exported.+svArg2C :: ComputeSingularValues -> IO (Ptr CChar)+svArg2C = \case+  SomeSVs -> newCString "S"+  AllSVs  -> newCString "A"++{-+class CPUTensorMathLapack t where++  -- |+  -- copied from the Lua docs. See:+  -- https://github.com/torch/torch7/blob/aed31711c6b8846b8337a263a7f9f998697994e7/doc/maths.md#x-torchtrtrsresb-resa-b-a--u-or-l--n-or-t--n-or-u+  --+  -- X = torch.trtrs(B, A) returns the solution of AX = B where A is upper-triangular.+  --+  -- A has to be a square, triangular, non-singular matrix (2D Tensor). A and+  -- resa are m × m, X and B are m × k. (To be very precise: A does not have to+  -- be triangular and non-singular, rather only its upper or lower triangle+  -- will be taken into account and that part has to be non-singular.)+  --+  -- The function has several options:+  --+  --   * uplo ('U' or 'L') specifies whether A is upper or lower triangular; the+  --     default value is 'U'.+  --+  --   * trans ('N' or 'T') specifies the system of equations: 'N' for A * X = B+  --     (no transpose), or 'T' for A^T * X = B (transpose); the default value is 'N'.+  --+  --   * diag ('N' or 'U') 'U' specifies that A is unit triangular, i.e., it has+  --     ones on its diagonal; 'N' specifies that A is not (necessarily) unit+  --     triangular; the default value is 'N'.+  --+  -- If resb and resa are given, then they will be used for temporary storage+  -- and returning the result. resb will contain the solution X.+  --+  -- Note: Irrespective of the original strides, the returned matrices resb and+  -- resa will be transposed, i.e. with strides 1, m instead of m, 1.+  _trtrs     :: t -> t -> t -> t -> [Int8] -> [Int8] -> [Int8] -> IO ()++  _orgqr     :: t -> t -> t -> IO ()+  _ormqr     :: t -> t -> t -> t -> [Int8] -> [Int8] -> IO ()+  _pstrf     :: t -> Int.DynTensor -> t -> [Int8] -> HsReal t -> IO ()+  _btrifact  :: t -> Int.DynTensor -> Int.DynTensor -> Int32 -> t -> IO ()+  _btrisolve :: t -> t -> t -> Int.DynTensor -> IO ()+-}
+ src/Torch/Indef/Dynamic/Tensor/Math/Pairwise.hs view
@@ -0,0 +1,222 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Pairwise+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Pairwise+  ( equal+  , add, add_, add_scaled_+  , sub, sub_, sub_scaled_+  , mul, mul_+  , Torch.Indef.Dynamic.Tensor.Math.Pairwise.div, div_+  , lshift_+  , rshift_+  , fmod_+  , remainder_+  , bitand_+  , bitor_+  , bitxor_+  ) where++import Torch.Indef.Dynamic.Tensor+import Torch.Indef.Types+import System.IO.Unsafe+import Control.Monad.Managed (with)+import Control.Monad.IO.Class (liftIO)++import qualified Torch.Sig.Tensor.Math.Pairwise as Sig++-- | Call Torch's C-level @equal@ function.+equal :: Dynamic -> Dynamic -> Bool+equal r t = unsafeDupablePerformIO . fmap (== 1) . withLift $ Sig.c_equal+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t++-- | add a scalar to a tensor, inplace.+add_ :: Dynamic -> HsReal -> IO ()+add_ t v = _add t t v++-- | add a scalar to a tensor.+add :: Dynamic -> HsReal -> Dynamic+add t v = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _add r t v+  pure r+{-# NOINLINE add #-}++-- | subtract a scalar from a tensor, inplace.+sub_ :: Dynamic -> HsReal -> IO ()+sub_ t v = _sub t t v++-- | subtract a scalar from a tensor.+sub :: Dynamic -> HsReal -> Dynamic+sub  t v = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _sub r t v+  pure r+{-# NOINLINE sub #-}++-- | add a scalar, which has been scaled, to a tensor, inplace.+add_scaled_+  :: Dynamic  -- ^ tensor to scale+  -> HsReal   -- ^ value to add+  -> HsReal   -- ^ amount to scale the value by+  -> IO ()+add_scaled_ t v0 v1 = _add_scaled t t v0 v1++-- | subtract a scalar, which has been scaled, from a tensor, inplace.+sub_scaled_+  :: Dynamic  -- ^ tensor to scale+  -> HsReal   -- ^ value to add+  -> HsReal   -- ^ amount to scale the value by+  -> IO ()+sub_scaled_ t v0 v1 = _sub_scaled t t v0 v1++-- | multiply a tensor by a scalar value, inplace.+mul_ :: Dynamic -> HsReal -> IO ()+mul_ t v = _mul t t v++-- | multiply a tensor by a scalar value, pure.+mul :: Dynamic -> HsReal -> Dynamic+mul t v = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _mul r t v+  pure r+{-# NOINLINE mul #-}++-- | divide a tensor by a scalar value, inplace.+div_ :: Dynamic -> HsReal -> IO ()+div_ t v = _div t t v++-- | divide a tensor by a scalar value, pure.+div :: Dynamic -> HsReal -> Dynamic+div t v = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _div r t v+  pure r+{-# NOINLINE div #-}++-- | Left shift all elements in the tensor by the given value, inplace.+lshift_ :: Dynamic -> HsReal -> IO ()+lshift_ t v = _lshift t t v++-- | Right shift all elements in the tensor by the given value, inplace.+rshift_ :: Dynamic -> HsReal -> IO ()+rshift_ t v = _rshift t t v++-- | Compute the remainder of division ( rounded towards zero) of all elements in the tensor by a given value, inplace.+fmod_ :: Dynamic -> HsReal -> IO ()+fmod_ t v = _fmod t t v++-- | Computes remainder of division (rounded to nearest) of all elements in the tensor by value, inplace+remainder_ :: Dynamic -> HsReal -> IO ()+remainder_ t v = _remainder t t v++-- | Performs the bitwise operation inplace on all elements in the tensor.+bitand_, bitor_, bitxor_ :: Dynamic -> HsReal -> IO ()+bitand_ t v = _bitand t t v+bitor_  t v = _bitor t t v+bitxor_ t v = _bitxor t t v++-- The remainder of this module includes C-styled versions of the haskell API++_add :: Dynamic -> Dynamic -> HsReal -> IO ()+_add r t v = withLift $ Sig.c_add+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_sub :: Dynamic -> Dynamic -> HsReal -> IO ()+_sub r t v = withLift $ Sig.c_sub+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_add_scaled :: Dynamic -> Dynamic -> HsReal -> HsReal -> IO ()+_add_scaled r t v0 v1 = withLift $ Sig.c_add_scaled+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v0)+  <*> pure (hs2cReal v1)++_sub_scaled :: Dynamic -> Dynamic -> HsReal -> HsReal -> IO ()+_sub_scaled r t v0 v1 = withLift $ Sig.c_sub_scaled+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v0)+  <*> pure (hs2cReal v1)++_mul :: Dynamic -> Dynamic -> HsReal -> IO ()+_mul r t v = withLift $ Sig.c_mul+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_div :: Dynamic -> Dynamic -> HsReal -> IO ()+_div r t v = withLift $ Sig.c_div+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_lshift :: Dynamic -> Dynamic -> HsReal -> IO ()+_lshift r t v = withLift $ Sig.c_lshift+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_rshift :: Dynamic -> Dynamic -> HsReal -> IO ()+_rshift r t v = withLift $ Sig.c_rshift+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_fmod :: Dynamic -> Dynamic -> HsReal -> IO ()+_fmod r t v = withLift $ Sig.c_fmod+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_remainder :: Dynamic -> Dynamic -> HsReal -> IO ()+_remainder r t v = withLift $ Sig.c_remainder+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_bitand :: Dynamic -> Dynamic -> HsReal -> IO ()+_bitand r t v = withLift $ Sig.c_bitand+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_bitor :: Dynamic -> Dynamic -> HsReal -> IO ()+_bitor r t v = withLift $ Sig.c_bitor+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_bitxor :: Dynamic -> Dynamic -> HsReal -> IO ()+_bitxor r t v = withLift $ Sig.c_bitxor+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++
+ src/Torch/Indef/Dynamic/Tensor/Math/Pointwise.hs view
@@ -0,0 +1,559 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Pointwise+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Element-wise functions.+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Pointwise+  ( cross+  , sign_       , sign+  , clamp_      , clamp+  , cadd_       , cadd       , (^+^)+  , csub_       , csub       , (^-^)+  , cmul_       , cmul       , (^*^) , square+  , cdiv_       , cdiv       , (^/^)+  , cpow_       , cpow+  , clshift_    , clshift+  , crshift_    , crshift+  , cfmod_      , cfmod+  , cremainder_ , cremainder+  , cmax_       , cmax+  , cmin_       , cmin+  , cmaxValue_  , cmaxValue+  , cminValue_  , cminValue+  , cbitand_    , cbitand+  , cbitor_     , cbitor+  , cbitxor_    , cbitxor+  , addcmul_    , addcmul+  , addcdiv_    , addcdiv+  ) where++import System.IO.Unsafe++import Debug.Trace+import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor++import qualified Torch.Sig.Tensor.Math.Pointwise as Sig++-- | Replaces all elements in-place with the sign of the elements of the tensor.+sign_ :: Dynamic -> IO ()+sign_ a = _sign a a++-- | Returns a new Tensor with the sign (+/- 1) of the elements of a tensor+sign :: Dynamic -> Dynamic+sign t = unsafeDupablePerformIO $ do+  let r = empty+  _sign r t+  pure r+{-# NOINLINE sign #-}++-- |  returns the cross product of vectors in the specified dimension+--+-- a and b must have the same size, and both @a:size(n)@ and @b:size(n)@ must be 3.+cross+  :: Dynamic    -- ^ tensor a+  -> Dynamic    -- ^ tensor b (same size as tensor a in dimension below)+  -> Word       -- ^ dimension to operate over+  -> Dynamic    -- ^ new return tensor+cross a b di = unsafeDupablePerformIO $ do+  let r = empty+  _cross r a b di+  pure r+{-# NOINLINE cross #-}++-- | Clamp all elements, inplace, in the tensor into the range @[min_value, max_value]@. ie:+--+-- @+--         { min_value, if x_i < min_value+--   y_i = { x_i,       if min_value ≤ x_i ≤ max_value+--         { max_value, if x_i > max_value+-- @+clamp_ :: Dynamic -> HsReal -> HsReal -> IO ()+clamp_ t a b = _clamp t t a b++-- | pure version of 'clamp_' returning a new tensor as output.+clamp :: Dynamic -> HsReal -> HsReal -> Dynamic+clamp  t a b = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _clamp r t a b+  pure r+{-# NOINLINE clamp #-}++-- | Multiply elements of tensor2 by the scalar value and add it to tensor1.+-- The number of elements must match, but sizes do not matter.+--+-- Stores the result in tensor1.+cadd_+  :: Dynamic  -- ^ tensor1+  -> HsReal   -- ^ scale term to multiply againts tensor2+  -> Dynamic  -- ^ tensor2+  -> IO ()+cadd_ t v b = _cadd t t v b++-- | Multiply elements of tensor2 by the scalar value and add it to tensor1.+-- The number of elements must match, but sizes do not matter.+cadd+  :: Dynamic  -- ^ tensor1+  -> HsReal   -- ^ scale term to multiply againts tensor2+  -> Dynamic  -- ^ tensor2+  -> Dynamic+cadd t v b = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _cadd r t v b+  pure r+{-# NOINLINE cadd #-}++-- | inline alias to 'cadd'+(^+^) :: Dynamic -> Dynamic -> Dynamic+(^+^) a b = cadd a 1 b++-- | Multiply elements of tensor2 by the scalar value and subtract it from tensor1.+-- The number of elements must match, but sizes do not matter.+--+-- Stores the result in tensor1.+csub_+  :: Dynamic  -- ^ tensor1+  -> HsReal   -- ^ scale term to multiply againts tensor2+  -> Dynamic  -- ^ tensor2+  -> IO ()+csub_ t v b = _csub t t v b++-- | Multiply elements of tensor2 by the scalar value and subtract it from tensor1.+-- The number of elements must match, but sizes do not matter.+csub+  :: Dynamic  -- ^ tensor1+  -> HsReal   -- ^ scale term to multiply againts tensor2+  -> Dynamic  -- ^ tensor2+  -> Dynamic+csub t v b = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t)+  _csub r t v b+  pure r+{-# NOINLINE csub #-}++-- | inline alias to 'csub'+(^-^) :: Dynamic -> Dynamic -> Dynamic+(^-^) a b = csub a 1 b++-- | Performs the element-wise multiplication of tensor1 by tensor2. The number of elements must match,+-- but sizes do not matter.+--+-- Stores the result in tensor1.+cmul_+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+cmul_ t1 t2 = _cmul t1 t1 t2++-- | Performs the element-wise multiplication of tensor1 by tensor2. The number of elements must match,+-- but sizes do not matter.+cmul+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+cmul t1 t2 = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t1)+  _cmul r t1 t2+  pure r+{-# NOINLINE cmul #-}++-- | square a tensor.+--+-- FIXME: this is a call to 'cmul' but it might be better to use 'pow'+square :: Dynamic -> Dynamic+square t = cmul t t++-- | inline alias to 'cmul'+(^*^) :: Dynamic -> Dynamic -> Dynamic+(^*^) = cmul++-- | Performs the element-wise division of tensor1 by tensor2. The number of elements must match,+-- but sizes do not matter.+--+-- Stores the result in tensor1.+cdiv_+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+cdiv_ t1 t2 = _cdiv t1 t1 t2++-- | Performs the element-wise division of tensor1 by tensor2. The number of elements must match,+-- but sizes do not matter.+cdiv+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+cdiv  t1 t2 = unsafeDupablePerformIO $ do+  let r = new' (getSomeDims t1)+  _cdiv r t1 t2+  pure r+{-# NOINLINE cdiv #-}++-- | inline alias to 'cdiv'+(^/^) :: Dynamic -> Dynamic -> Dynamic+(^/^) = cdiv++-- | Element-wise power operation, taking the elements of tensor1 to the powers given by elements+-- of tensor2. The number of elements must match, but sizes do not matter.+--+-- Stores the result in tensor1.+cpow_+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+cpow_ t = _cpow t t++-- | Element-wise power operation, taking the elements of tensor1 to the powers given by elements+-- of tensor2. The number of elements must match, but sizes do not matter.+cpow+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+cpow = _mkNewFunction _cpow++-- | Element-wise, inplace, bitwise left shift. Mutates the first argument.+clshift_ :: Dynamic -> Dynamic -> IO ()+clshift_ t = _clshift t t++-- | Element-wise bitwise left shift.+clshift :: Dynamic -> Dynamic -> Dynamic+clshift = _mkNewFunction _clshift++-- | Element-wise, inplace, bitwise right shift. Mutates the first argument.+crshift_ :: Dynamic -> Dynamic -> IO ()+crshift_ t = _crshift t t++-- | Element-wise bitwise right shift.+crshift :: Dynamic -> Dynamic -> Dynamic+crshift = _mkNewFunction _crshift++-- | Computes the element-wise remainder of the division (rounded towards zero)+-- of tensor1 by tensor2. The number of elements must match, but sizes do not matter.+--+-- Stores the result in tensor1.+cfmod_+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+cfmod_ t = _cfmod t t++-- | Computes the element-wise remainder of the division (rounded towards zero)+-- of tensor1 by tensor2. The number of elements must match, but sizes do not matter.+cfmod+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+cfmod = _mkNewFunction _cfmod++-- | Computes element-wise remainder of the division (rounded to nearest) of+-- tensor1 by tensor2. The number of elements must match, but sizes do not matter.+--+-- Stores the result in tensor1.+cremainder_+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+cremainder_ t = _cremainder t t++-- | Computes element-wise remainder of the division (rounded to nearest) of+-- tensor1 by tensor2. The number of elements must match, but sizes do not matter.+cremainder+  :: Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+cremainder = _mkNewFunction _cremainder++-- | Element-wise, inplace, max function -- storing the higher value. Mutates the first argument.+cmax_ :: Dynamic -> Dynamic -> IO ()+cmax_ t = _cmax t t++-- | Element-wise max function -- keeping the higher value.+cmax :: Dynamic -> Dynamic -> Dynamic+cmax = _mkNewFunction _cmax++-- | Element-wise, inplace, min function -- storing the lower value. Mutates the first argument.+cmin_ :: Dynamic -> Dynamic -> IO ()+cmin_ t =  _cmin t t++-- | Element-wise min function -- keeping the lower value.+cmin :: Dynamic -> Dynamic -> Dynamic+cmin = _mkNewFunction _cmin++-- | Store the maximum of the tensor and a scalar in the input tensor on an element-by-element basis.+cmaxValue_ :: Dynamic -> HsReal -> IO ()+cmaxValue_ t v = _cmaxValue t t v++-- | Store the maximum of the tensor and a scalar in a new tensor on an element-by-element basis.+cmaxValue :: Dynamic -> HsReal -> Dynamic+cmaxValue t v = unsafeDupablePerformIO $ do+  let r = empty+  _cmaxValue r t v+  pure r+{-# NOINLINE cmaxValue #-}++-- | Store the minimum of the tensor and a scalar in the input tensor on an element-by-element basis.+cminValue_ :: Dynamic -> HsReal -> IO ()+cminValue_ t v = _cminValue t t v++-- | Store the minimum of the tensor and a scalar in a new tensor on an element-by-element basis.+cminValue :: Dynamic -> HsReal -> Dynamic+cminValue  t v = unsafeDupablePerformIO $ do+  let r = empty+  _cminValue r t v+  pure r+{-# NOINLINE cminValue #-}++-- | Element-wise, inplace, bitwise @and@. Mutates the first argument.+cbitand_ :: Dynamic -> Dynamic -> IO ()+cbitand_ t = _cbitand t t++-- | Element-wise, bitwise @and@+cbitand :: Dynamic -> Dynamic -> Dynamic+cbitand = _mkNewFunction _cbitand++-- | Element-wise, inplace, bitwise @or@. Mutates the first argument.+cbitor_ :: Dynamic -> Dynamic -> IO ()+cbitor_ t = _cbitor t t++-- | Element-wise, bitwise @or@+cbitor :: Dynamic -> Dynamic -> Dynamic+cbitor = _mkNewFunction _cbitor++-- | Element-wise, inplace, bitwise @xor@. Mutates the first argument.+cbitxor_ :: Dynamic -> Dynamic -> IO ()+cbitxor_ t =  _cbitxor t t++-- | Element-wise, bitwise @xor@+cbitxor :: Dynamic -> Dynamic -> Dynamic+cbitxor = _mkNewFunction _cbitxor++-- | Performs the element-wise multiplication of tensor1 by tensor2, multiplies+-- the result by the scalar value and adds it to tensor0, which it mutates inplace.+--+-- The number of elements must match, but sizes do not matter.+addcmul_+  :: Dynamic  -- ^ tensor0+  -> HsReal   -- ^ scale term+  -> Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+addcmul_ a v b c = _addcmul a a v b c++-- | Performs the element-wise multiplication of tensor1 by tensor2, multiplies+-- the result by the scalar value and adds it to tensor0.+--+-- The number of elements must match, but sizes do not matter.+addcmul+  :: Dynamic  -- ^ tensor0+  -> HsReal   -- ^ scale term+  -> Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+addcmul a v b c = unsafeDupablePerformIO $ do+  let r = empty+  _addcmul r a v b c+  pure r+{-# NOINLINE addcmul #-}+++-- | Performs the element-wise multiplication of tensor1 by tensor2, multiplies+-- the result by the scalar value and adds it to tensor0, which it mutates inplace.+--+-- The number of elements must match, but sizes do not matter.+addcdiv_+  :: Dynamic  -- ^ tensor0+  -> HsReal   -- ^ scale term+  -> Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> IO ()+addcdiv_ a = _addcdiv a a++-- | Performs the element-wise division of tensor1 by tensor2, multiplies+-- the result by the scalar value and adds it to tensor0.+--+-- The number of elements must match, but sizes do not matter.+addcdiv+  :: Dynamic  -- ^ tensor0+  -> HsReal   -- ^ scale term+  -> Dynamic  -- ^ tensor1+  -> Dynamic  -- ^ tensor2+  -> Dynamic+addcdiv a v b c = unsafeDupablePerformIO $ do+  let r = empty+  _addcdiv r a v b c+  pure r+{-# NOINLINE addcdiv #-}++-- ========================================================================= --+-- raw C-level calls++_sign :: Dynamic -> Dynamic -> IO ()+_sign r t = withLift $ Sig.c_sign+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t++_cross :: Dynamic -> Dynamic -> Dynamic -> Word -> IO ()+_cross t0 t1 t2 i0 = withLift $ Sig.c_cross+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> managedTensor t2+  <*> pure (fromIntegral i0)++_clamp :: Dynamic -> Dynamic -> HsReal -> HsReal -> IO ()+_clamp r t v0 v1 = withLift $ Sig.c_clamp+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v0)+  <*> pure (hs2cReal v1)++_cmax :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cmax r t0 t1 = withLift $ Sig.c_cmax+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cmin :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cmin r t0 t1 = withLift $ Sig.c_cmin+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cmaxValue :: Dynamic -> Dynamic -> HsReal -> IO ()+_cmaxValue r t v = withLift $ Sig.c_cmaxValue+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_cminValue :: Dynamic -> Dynamic -> HsReal -> IO ()+_cminValue r t v = withLift $ Sig.c_cminValue+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t+  <*> pure (hs2cReal v)++_addcmul :: Dynamic -> Dynamic -> HsReal -> Dynamic -> Dynamic -> IO ()+_addcmul t0 t1 v t2 t3 = withLift $ Sig.c_addcmul+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (hs2cReal v)+  <*> managedTensor t2+  <*> managedTensor t3++_addcdiv :: Dynamic -> Dynamic -> HsReal -> Dynamic -> Dynamic -> IO ()+_addcdiv t0 t1 v t2 t3 = withLift $ Sig.c_addcdiv+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (hs2cReal v)+  <*> managedTensor t2+  <*> managedTensor t3++_cadd :: Dynamic -> Dynamic -> HsReal -> Dynamic -> IO ()+_cadd t0 t1 v t2 = withLift $ Sig.c_cadd+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (hs2cReal v)+  <*> managedTensor t2++_csub :: Dynamic -> Dynamic -> HsReal -> Dynamic -> IO ()+_csub t0 t1 v t2 = withLift $ Sig.c_csub+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (hs2cReal v)+  <*> managedTensor t2++_cmul :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cmul r t0 t1 = withLift $ Sig.c_cmul+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cpow :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cpow r t0 t1 = withLift $ Sig.c_cpow+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cdiv :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cdiv r t0 t1 = withLift $ Sig.c_cdiv+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_clshift :: Dynamic -> Dynamic -> Dynamic -> IO ()+_clshift r t0 t1 = withLift $ Sig.c_clshift+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_crshift :: Dynamic -> Dynamic -> Dynamic -> IO ()+_crshift r t0 t1 = withLift $ Sig.c_crshift+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cfmod :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cfmod r t0 t1 = withLift $ Sig.c_cfmod+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cremainder :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cremainder r t0 t1 = withLift $ Sig.c_cremainder+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cbitand :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cbitand r t0 t1 = withLift $ Sig.c_cbitand+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cbitor :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cbitor r t0 t1 = withLift $ Sig.c_cbitor+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++_cbitxor :: Dynamic -> Dynamic -> Dynamic -> IO ()+_cbitxor r t0 t1 = withLift $ Sig.c_cbitxor+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t0+  <*> managedTensor t1++-- ========================================================================= --+-- helper functions++_mkNewFunction :: (Dynamic -> Dynamic -> Dynamic -> IO ()) -> Dynamic -> Dynamic -> Dynamic+_mkNewFunction op t1 t2 = unsafeDupablePerformIO $ do+  let r = empty+  op r t1 t2+  pure r+
+ src/Torch/Indef/Dynamic/Tensor/Math/Pointwise/Floating.hs view
@@ -0,0 +1,389 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating+  ( cinv_    , cinv+  , sigmoid_ , sigmoid+  , log_     , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.log+  , lgamma_  , lgamma+  , log1p_   , log1p+  , exp_     , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.exp+  , cos_     , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.cos+  , acos_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.acos+  , cosh_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.cosh+  , sin_     , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.sin+  , asin_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.asin+  , sinh_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.sinh+  , tan_     , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.tan+  , atan_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.atan+  , tanh_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.tanh+  , erf_     , erf+  , erfinv_  , erfinv+  , pow_     , pow+  , tpow_    , tpow+  , sqrt_    , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.sqrt+  , rsqrt_   , rsqrt+  , ceil_    , ceil+  , floor_   , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.floor+  , round_   , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.round+  , trunc_   , trunc+  , frac_    , frac+  , lerp_    , lerp+  , atan2_   , Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating.atan2+  ) where++import GHC.Int+import System.IO.Unsafe+import Torch.Indef.Dynamic.Tensor+import qualified Torch.Sig.Tensor.Math.Pointwise.Floating as Sig++import Torch.Indef.Types++-- | Return a new tensor applying @1.0 / x@ to all elements.+cinv :: Dynamic -> Dynamic+cinv t = unsafeDupablePerformIO $ let r = empty in _cinv r t >> pure r+{-# NOINLINE cinv #-}++-- | Inplace version of 'cinv', mutating the first tensor argument.+cinv_ :: Dynamic -> IO ()+cinv_ t = _cinv t t++-- | Returns a new Tensor with the sigmoid of the elements of x.+sigmoid :: Dynamic -> Dynamic+sigmoid t = unsafeDupablePerformIO $ let r = empty in _sigmoid r t >> pure r+{-# NOINLINE sigmoid #-}++-- | Inplace version of 'sigmoid', mutating the first tensor argument.+sigmoid_ :: Dynamic -> IO ()+sigmoid_ t = _sigmoid t t++-- | Returns a new tensor with the natural logarithm of the elements of x.+log :: Dynamic -> Dynamic+log t = unsafeDupablePerformIO $ let r = empty in _log r t >> pure r+{-# NOINLINE log #-}++-- | Inplace version of 'log', mutating the first tensor argument.+log_ :: Dynamic -> IO ()+log_ t = _log t t++-- | Returns a new tensor with the natural logarithm of the absolute value of the gamma function of the elements of x.+lgamma :: Dynamic -> Dynamic+lgamma t = unsafeDupablePerformIO $ let r = empty in _lgamma r t >> pure r+{-# NOINLINE lgamma #-}++-- | Inplace version of 'lgamma', mutating the first tensor argument.+lgamma_ :: Dynamic -> IO ()+lgamma_ t = _lgamma t t++-- | Returns a new tensor with the natural logarithm of the elements of x + 1.+--+-- This function is more accurate than log for small values of x.+log1p :: Dynamic -> Dynamic+log1p t = unsafeDupablePerformIO $ let r = empty in _log1p r t >> pure r+{-# NOINLINE log1p #-}++-- | Inplace version of 'log1p', mutating the first tensor argument.+log1p_ :: Dynamic -> IO ()+log1p_ t = _log1p t t++-- | Returns, for each element in x, e (Neper number, the base of+-- natural logarithms) raised to the power of the element in x.+exp :: Dynamic -> Dynamic+exp t = unsafeDupablePerformIO $ let r = empty in _exp r t >> pure r+{-# NOINLINE exp #-}++-- | Inplace version of 'exp', mutating the first tensor argument.+exp_ :: Dynamic -> IO ()+exp_ t = _exp t t++-- | Returns a new tensor with the cosine of the elements of x.+cos :: Dynamic -> Dynamic+cos t = unsafeDupablePerformIO $ let r = empty in _cos r t >> pure r+{-# NOINLINE cos #-}++-- | Inplace version of 'cos', mutating the first tensor argument.+cos_ :: Dynamic -> IO ()+cos_ t = _cos t t++-- | Returns a new tensor with the arcosine of the elements of x.+acos :: Dynamic -> Dynamic+acos t = unsafeDupablePerformIO $ let r = empty in _acos r t >> pure r+{-# NOINLINE acos #-}++-- | Inplace version of 'acos', mutating the first tensor argument.+acos_ :: Dynamic -> IO ()+acos_ t = _acos t t++-- | Returns a new tensor with the hyberbolic cosine of the elements of x.+cosh :: Dynamic -> Dynamic+cosh t = unsafeDupablePerformIO $ let r = empty in _cosh r t >> pure r+{-# NOINLINE cosh #-}++-- | Inplace version of 'cosh', mutating the first tensor argument.+cosh_ :: Dynamic -> IO ()+cosh_ t = _cosh t t++-- | Returns a new tensor with the sine of the elements of x.+sin :: Dynamic -> Dynamic+sin t = unsafeDupablePerformIO $ let r = empty in _sin r t >> pure r+{-# NOINLINE sin #-}++-- | Inplace version of 'sin', mutating the first tensor argument.+sin_ :: Dynamic -> IO ()+sin_ t = _sin t t++-- | Returns a new tensor with the arcsine of the elements of x.+asin :: Dynamic -> Dynamic+asin t = unsafeDupablePerformIO $ let r = empty in _asin r t >> pure r+{-# NOINLINE asin #-}++-- | Inplace version of 'asin', mutating the first tensor argument.+asin_ :: Dynamic -> IO ()+asin_ t = _asin t t++-- | Returns a new tensor with the hyperbolic sine of the elements of x.+sinh :: Dynamic -> Dynamic+sinh t = unsafeDupablePerformIO $ let r = empty in _sinh r t >> pure r+{-# NOINLINE sinh #-}++-- | Inplace version of 'sinh', mutating the first tensor argument.+sinh_ :: Dynamic -> IO ()+sinh_ t = _sinh t t++-- | Returns a new tensor with the tangent of the elements of x.+tan :: Dynamic -> Dynamic+tan t = unsafeDupablePerformIO $ let r = empty in _tan r t >> pure r+{-# NOINLINE tan #-}++-- | Inplace version of 'tan', mutating the first tensor argument.+tan_ :: Dynamic -> IO ()+tan_ t = _tan t t++-- | Returns a new tensor with the arctangent of the elements of x.+atan :: Dynamic -> Dynamic+atan t = unsafeDupablePerformIO $ let r = empty in _atan r t >> pure r+{-# NOINLINE atan #-}++-- | Inplace version of 'atan', mutating the first tensor argument.+atan_ :: Dynamic -> IO ()+atan_ t = _atan t t++-- | Returns a new tensor with the hyperbolic tangent of the elements of x.+tanh :: Dynamic -> Dynamic+tanh t = unsafeDupablePerformIO $ let r = empty in _tanh r t >> pure r+{-# NOINLINE tanh #-}++-- | Inplace version of 'tanh', mutating the first tensor argument.+tanh_ :: Dynamic -> IO ()+tanh_ t = _tanh t t++-- | Returns a new tensor with the gauss error function applied to the elements of x.+--+-- The error function comes from https://en.wikipedia.org/wiki/Error_function+erf :: Dynamic -> Dynamic+erf t = unsafeDupablePerformIO $ let r = empty in _erf r t >> pure r+{-# NOINLINE erf #-}++-- | Inplace version of 'erf', mutating the first tensor argument.+erf_ :: Dynamic -> IO ()+erf_ t = _erf t t++-- | Returns a new tensor with the inverse gauss error function applied to the elements of x.+--+-- See https://en.wikipedia.org/wiki/Error_function for the gauss error function. This is its inverse.+erfinv :: Dynamic -> Dynamic+erfinv t = unsafeDupablePerformIO $ let r = empty in _erfinv r t >> pure r+{-# NOINLINE erfinv #-}++-- | Inplace version of 'erfinv', mutating the first tensor argument.+erfinv_ :: Dynamic -> IO ()+erfinv_ t = _erfinv t t++-- | Returns a new tensor with the elements of @x@ to the power of @n@.+pow :: Dynamic -> HsReal -> Dynamic+pow t v = unsafeDupablePerformIO $ let r = empty in _pow r t v >> pure r+{-# NOINLINE pow #-}++-- | Inplace version of 'pow', mutating the first tensor argument.+pow_ :: Dynamic -> HsReal -> IO ()+pow_ t v = _pow t t v++-- | Returns a new tensor with the scalar @n@, raised to the power of each element in the tensor @x@.+tpow+  :: HsReal      -- ^ base scalar @n@+  -> Dynamic     -- ^ tensor @x@ of powers to raise @n@ by.+  -> Dynamic+tpow v t = unsafeDupablePerformIO $ let r = empty in _tpow r v t >> pure r+{-# NOINLINE tpow #-}++-- | Inplace version of 'tpow', mutating the first tensor argument.+tpow_ :: HsReal -> Dynamic -> IO ()+tpow_ v t = _tpow t v t++-- | Returns a new tensor with the square root of the elements of x.+sqrt :: Dynamic -> Dynamic+sqrt t = unsafeDupablePerformIO $ let r = empty in _sqrt r t >> pure r+{-# NOINLINE sqrt #-}++-- | Inplace version of 'sqrt', mutating the first tensor argument.+sqrt_ :: Dynamic -> IO ()+sqrt_ t = _sqrt t t++-- | Returns a new tensor with the reciprocal of the square root of the elements of x.+rsqrt :: Dynamic -> Dynamic+rsqrt t = unsafeDupablePerformIO $ let r = empty in _rsqrt r t >> pure r+{-# NOINLINE rsqrt #-}++-- | Inplace version of 'rsqrt', mutating the first tensor argument.+rsqrt_ :: Dynamic -> IO ()+rsqrt_ t = _rsqrt t t++-- | Returns a new tensor with the values of the elements of x+-- rounded up to the nearest integers.+ceil :: Dynamic -> Dynamic+ceil t = unsafeDupablePerformIO $ let r = empty in _ceil r t >> pure r+{-# NOINLINE ceil #-}++-- | Inplace version of 'ceil', mutating the first tensor argument.+ceil_ :: Dynamic -> IO ()+ceil_ t = _ceil t t++-- | Returns a new Tensor with the values of the elements of x+-- rounded down to the nearest integers.+floor :: Dynamic -> Dynamic+floor t = unsafeDupablePerformIO $ let r = empty in _floor r t >> pure r+{-# NOINLINE floor #-}++-- | Inplace version of 'floor', mutating the first tensor argument.+floor_ :: Dynamic -> IO ()+floor_ t = _floor t t++-- | Returns a new tensor with the values of the elements of x+-- rounded to the nearest integers.+--+-- FIXME: The lua docs don't state how this rounding works. Someone+-- should read the source code and document this.+round :: Dynamic -> Dynamic+round t = unsafeDupablePerformIO $ let r = empty in _round r t >> pure r+{-# NOINLINE round #-}++-- | Inplace version of 'round', mutating the first tensor argument.+round_ :: Dynamic -> IO ()+round_ t = _round t t++-- | Returns a new tensor with the truncated integer values of the+-- elements of x.+--+-- FIXME: The lua docs don't state how this truncation works. Someone+-- should read the source code, document this, and explain how this+-- differs from 'floor'.+trunc :: Dynamic -> Dynamic+trunc t = unsafeDupablePerformIO $ let r = empty in _trunc r t >> pure r+{-# NOINLINE trunc #-}++-- | Inplace version of 'trunc', mutating the first tensor argument.+trunc_ :: Dynamic -> IO ()+trunc_ t = _trunc t t++-- | Returns a new tensor with the fractional portion of the elements+-- of x.+frac :: Dynamic -> Dynamic+frac t = unsafeDupablePerformIO $ let r = empty in _frac r t >> pure r+{-# NOINLINE frac #-}++-- | Inplace version of 'frac', mutating the first tensor argument.+frac_ :: Dynamic -> IO ()+frac_ t = _frac t t++-- | Linear interpolation of two scalars or tensors based on a weight:+--+-- @+--   res = a + weight * (b - a)+-- @+lerp :: Dynamic -> Dynamic -> HsReal -> Dynamic+lerp a b v = unsafeDupablePerformIO $ let r = empty in _lerp r a b v >> pure r+{-# NOINLINE lerp #-}++-- | Inplace version of 'lerp', mutating the first tensor argument.+lerp_ :: Dynamic -> Dynamic -> HsReal -> IO ()+lerp_ a b v = _lerp a a b v++-- | Returns a new tensor with the arctangent of the elements+-- of x and y. Note that the arctangent of the elements x and y+-- refers to the signed angle in radians between the rays ending+-- at origin where the first one starts at (1, 0) and the second+-- at (y, x).+atan2 :: Dynamic -> Dynamic -> Dynamic+atan2 a b = unsafeDupablePerformIO $ let r = empty in _atan2 r a b >> pure r+{-# NOINLINE atan2 #-}++-- | Inplace version of 'atan2', mutating the first tensor argument.+atan2_ :: Dynamic -> Dynamic -> IO ()+atan2_ a b = _atan2 a a b+++-- class CPUTensorMathPointwiseFloating t where+--   histc_        :: Dynamic -> Dynamic -> Int64 -> HsReal -> HsReal -> IO ()+--   bhistc_       :: Dynamic -> Dynamic -> Int64 -> HsReal -> HsReal -> IO ()+++-- ========================================================================= --+-- C-style functions++_cinv, _sigmoid, _log, _lgamma, _log1p, _exp, _cos, _acos, _sinh+  :: Dynamic -> Dynamic -> IO ()+_cinv    a b = with2DynamicState a b Sig.c_cinv+_sigmoid a b = with2DynamicState a b Sig.c_sigmoid+_log     a b = with2DynamicState a b Sig.c_log+_lgamma  a b = with2DynamicState a b Sig.c_lgamma+_log1p   a b = with2DynamicState a b Sig.c_log1p+_exp     a b = with2DynamicState a b Sig.c_exp+_cos     a b = with2DynamicState a b Sig.c_cos+_acos    a b = with2DynamicState a b Sig.c_acos+_sinh    a b = with2DynamicState a b Sig.c_sinh++_asin, _cosh, _sin, _tan, _atan, _tanh, _erf, _erfinv, _sqrt+  :: Dynamic -> Dynamic -> IO ()+_asin   a b = with2DynamicState a b Sig.c_asin+_cosh    a b = with2DynamicState a b Sig.c_cosh+_sin     a b = with2DynamicState a b Sig.c_sin+_tan    a b = with2DynamicState a b Sig.c_tan+_atan   a b = with2DynamicState a b Sig.c_atan+_tanh   a b = with2DynamicState a b Sig.c_tanh+_erf    a b = with2DynamicState a b Sig.c_erf+_erfinv a b = with2DynamicState a b Sig.c_erfinv+_sqrt   a b = with2DynamicState a b Sig.c_sqrt++_rsqrt, _ceil, _floor, _round, _trunc, _frac+  :: Dynamic -> Dynamic -> IO ()+_rsqrt a b = with2DynamicState a b Sig.c_rsqrt+_ceil  a b = with2DynamicState a b Sig.c_ceil+_floor a b = with2DynamicState a b Sig.c_floor+_round a b = with2DynamicState a b Sig.c_round+_trunc a b = with2DynamicState a b Sig.c_trunc+_frac  a b = with2DynamicState a b Sig.c_frac++_atan2 :: Dynamic -> Dynamic -> Dynamic -> IO ()+_atan2 a b c = with3DynamicState a b c Sig.c_atan2++_pow :: Dynamic -> Dynamic -> HsReal -> IO ()+_pow a b v = withLift $ Sig.c_pow+  <$> managedState+  <*> managedTensor a+  <*> managedTensor b+  <*> pure (hs2cReal v)++_tpow :: Dynamic -> HsReal -> Dynamic -> IO ()+_tpow a v b = with2DynamicState a b $ \s' a' b' -> Sig.c_tpow s' a' (hs2cReal v) b'++_lerp :: Dynamic -> Dynamic -> Dynamic -> HsReal -> IO ()+_lerp a b c v = with3DynamicState a b c $ \s' a' b' c' -> Sig.c_lerp s' a' b' c' (hs2cReal v)++
+ src/Torch/Indef/Dynamic/Tensor/Math/Pointwise/Signed.hs view
@@ -0,0 +1,49 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed+  ( neg_, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed.neg+  , abs_, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed.abs+  ) where++import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor+import qualified Torch.Sig.Tensor.Math.Pointwise.Signed as Sig++_abs r t = withLift $ Sig.c_abs+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t++_neg r t = withLift $ Sig.c_neg+  <$> managedState+  <*> managedTensor r+  <*> managedTensor t++-- | Return a new tensor flipping the sign on every element.+neg :: Dynamic -> Dynamic+neg  t = unsafeDupablePerformIO $ let r = empty in _neg r t >> pure r+{-# NOINLINE neg #-}++-- | Inplace version of 'neg'+neg_ :: Dynamic -> IO ()+neg_ t = _neg t t++-- | Return a new tensor applying the absolute function to all elements.+abs :: Dynamic -> Dynamic+abs t = unsafeDupablePerformIO $ let r = empty in _abs r t >> pure r+{-# NOINLINE abs #-}++-- | Inplace version of 'abs'+abs_ :: Dynamic -> IO ()+abs_ t = _abs t t+
+ src/Torch/Indef/Dynamic/Tensor/Math/Random/TH.hs view
@@ -0,0 +1,76 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Random.TH+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Random functions for CPU-based tensors.+-------------------------------------------------------------------------------+++module Torch.Indef.Dynamic.Tensor.Math.Random.TH+  ( _rand+  , _randn+  , _randperm+  ) where++import Foreign+import Foreign.Ptr+import Control.Monad+import Control.Monad.Managed+import Torch.Indef.Types+import qualified Torch.Types.TH as TH+import qualified Torch.Sig.Types as Sig+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Sig.Tensor.Math.Random.TH as Sig++go+  :: (Ptr CState -> Ptr CTensor -> Ptr CGenerator -> Ptr TH.CLongStorage -> IO ())+  -> Dynamic+  -> Generator+  -> TH.IndexStorage+  -> IO ()+go fn d g i = runManaged . (liftIO =<<) $ fn+  <$> managedState+  <*> managedTensor d+  <*> managed (withForeignPtr (Sig.rng g))+  <*> managed (withForeignPtr . snd . TH.longStorageState $ i)++-- | C-style, impure, call to Torch's @rand@ function.+--+-- Returns a tensor filled with random numbers from a uniform distribution+-- on the interval [0, 1).+--+-- In Lua, this is @y = torch.rand(gen, torch.LongStorage{m, n, k, l, o})@, where+-- the 'IndexStorage' holds a list of dimensions to be filled.+_rand  :: Dynamic -> Generator -> TH.IndexStorage -> IO ()+_rand = go Sig.c_rand++-- | C-style, impure, call to Torch's @randn@ function.+--+-- Returns a tensor filled with random numbers from a normal distribution with+-- mean zero and variance one.+--+-- In Lua, this is @y = torch.randn(gen, torch.LongStorage{m, n, k, l, o})@, where+-- the 'IndexStorage' holds a list of dimensions to be filled.+_randn  :: Dynamic -> Generator -> TH.IndexStorage -> IO ()+_randn = go Sig.c_randn++-- | C-style, impure, call to Torch's @randperm@ function.+--+-- Returns a random permutation of integers from 1 to @n@+_randperm+  :: Dynamic   -- ^ tensor to mutate, inplace+  -> Generator -- ^ local generator to use+  -> Integer   -- ^ @n@+  -> IO ()+_randperm t g i = runManaged . (liftIO =<<) $ Sig.c_randperm+  <$> managedState+  <*> managedTensor t+  <*> managed (withForeignPtr (Sig.rng g))+  <*> pure (fromIntegral i)++
+ src/Torch/Indef/Dynamic/Tensor/Math/Reduce.hs view
@@ -0,0 +1,201 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Reduce+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Reduce+  ( minall+  , maxall+  , medianall+  , sumall+  , prodall+  , _max+  , _min+  , _median+  , _sum+  , _prod+  , Torch.Indef.Dynamic.Tensor.Math.Reduce.max+  , Torch.Indef.Dynamic.Tensor.Math.Reduce.min+  , median+  ) where++import Control.Monad.Managed+import Foreign (withForeignPtr)+import System.IO.Unsafe+import Numeric.Dimensions++import Torch.Indef.Types++import Torch.Indef.Dynamic.Tensor+import qualified Torch.Indef.Index as Ix+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Sig.Tensor.Math.Reduce as Sig++-- | get the minima of a tensor's elements+minall :: Dynamic -> HsReal+minall t = unsafeDupablePerformIO . flip with (pure . c2hsReal) . (liftIO =<<) $ Sig.c_minall+  <$> managedState+  <*> managedTensor t+{-# NOINLINE minall #-}++-- | get the maxima of a tensor's elements+maxall :: Dynamic -> HsReal+maxall t = unsafeDupablePerformIO . flip with (pure . c2hsReal) . (liftIO =<<) $ Sig.c_maxall+  <$> managedState+  <*> managedTensor t+{-# NOINLINE maxall #-}++-- | get the median value of a tensor's elements+medianall :: Dynamic -> HsReal+medianall t = unsafeDupablePerformIO . flip with (pure . c2hsReal) . (liftIO =<<) $ Sig.c_medianall+  <$> managedState+  <*> managedTensor t+{-# NOINLINE medianall #-}++-- | get the sum of a tensor's elements+sumall :: Dynamic -> HsAccReal+sumall t = unsafeDupablePerformIO . flip with (pure . c2hsAccReal) . (liftIO =<<) $ Sig.c_sumall+  <$> managedState+  <*> managedTensor t+{-# NOINLINE sumall #-}++-- | get the product of a tensor's elements+prodall :: Dynamic -> HsAccReal+prodall t = unsafeDupablePerformIO . flip with (pure . c2hsAccReal) . (liftIO =<<) $ Sig.c_prodall+  <$> managedState+  <*> managedTensor t+{-# NOINLINE prodall #-}++-- | get the maximal value in the specified dimension and a corresponding index tensor of the maximum value's index.+--+-- Inplace and C-Style mutation+_max+  :: (Dynamic, IndexDynamic) -> Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim -> IO ()+_max (t0, ix) t1 i0 i1 = withLift $ Sig.c_max+  <$> managedState+  <*> managedTensor t0+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromKeepDim i1)+{-# NOINLINE _max #-}++-- | get the minimal value in the specified dimension and a corresponding index tensor of the minimum value's index.+--+-- Inplace and C-Style mutation+_min :: (Dynamic, IndexDynamic) -> Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim -> IO ()+_min (t0, ix) t1 i0 i1  = withLift $ Sig.c_min+  <$> managedState+  <*> managedTensor t0+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromKeepDim i1)+{-# NOINLINE _min #-}++-- | get the median value in the specified dimension and a corresponding index tensor of the median value's index.+--+-- Inplace and C-Style mutation+_median :: (Dynamic, IndexDynamic) -> Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim -> IO ()+_median (t0, ix) t1 i0 i1 = withLift $ Sig.c_median+  <$> managedState+  <*> managedTensor t0+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromKeepDim i1)+{-# NOINLINE _median #-}++-- | sum the tensor in the specified dimension.+--+-- Inplace and C-Style mutation+_sum :: Dynamic -> Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim -> IO ()+_sum t0 t1 i0 i1 = withLift $ Sig.c_sum+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromKeepDim i1)+{-# NOINLINE _sum #-}++-- | take the product of the tensor in the specified dimension.+--+-- Inplace and C-Style mutation+_prod+  :: Dynamic -> Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim -> IO ()+_prod t0 t1 i0 i1 = withLift $ Sig.c_prod+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromKeepDim i1)+{-# NOINLINE _prod #-}+++withKeepDim+  :: ((Dynamic, IndexDynamic) -> Dynamic -> Word -> Maybe KeepDim -> IO ())+  -> Dynamic -> Word -> Maybe KeepDim -> (Dynamic, Maybe (IndexDynamic))+withKeepDim _fn t d k = unsafeDupablePerformIO $ do+  _fn (ret, ix) t d k+  pure (ret, maybe Nothing (\(KeepDim b) -> if b then Just ix else Nothing) k)+  where+    tdim = getSomeDims t+    (i:_) = shape t+    ret :: Dynamic = new' tdim+    ix = Ix.newIxDyn [i]+{-# NOINLINE withKeepDim #-}++-- | get the maximum value in the specified dimension and return an optional corresponding index tensor of the maximum value's index.+max+  :: Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim+  -> (Dynamic, Maybe (IndexDynamic))+max = withKeepDim _max++-- | get the minimum value in the specified dimension and return an optional corresponding index tensor of the minimum value's index.+min+  :: Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim+  -> (Dynamic, Maybe (IndexDynamic))+min = withKeepDim _min++-- | get the median value in the specified dimension and return an optional corresponding index tensor of the median value's index.+median+  :: Dynamic+  -> Word -- ^ dimension to operate over+  -> Maybe KeepDim+  -> (Dynamic, Maybe (IndexDynamic))+median = withKeepDim _median+++-- * not in THC.BYte+-- c_renorm :: Ptr CState -> t -> t -> HsReal t -> CInt -> HsReal t -> IO ()+-- c_std :: Ptr CState -> t -> Ptr CTensor -> CInt -> CInt -> CInt -> IO ()+-- c_stdall :: Ptr CState -> Ptr CTensor -> CInt -> HsReal t+-- c_var :: Ptr CState -> Ptr CTensor -> Ptr CTensor -> CInt -> CInt -> CInt -> IO ()+-- c_varall :: Ptr CState -> Ptr CTensor -> CInt -> HsReal t+-- c_dist :: Ptr CState -> Ptr CTensor -> Ptr CTensor -> HsReal t -> HsReal t++-- * not in TH.Byte+-- c_norm :: Ptr CState -> Ptr CTensor -> Ptr CTensor -> HsReal t -> CInt -> CInt -> IO ()+-- c_normall :: Ptr CState -> Ptr CTensor -> HsReal t -> HsReal t+-- c_mean :: Ptr CState -> Ptr CTensor -> Ptr CTensor -> CInt -> CInt -> IO ()+-- c_meanall :: Ptr CState -> Ptr CTensor -> HsReal t
+ src/Torch/Indef/Dynamic/Tensor/Math/Reduce/Floating.hs view
@@ -0,0 +1,212 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating+  ( mean, mean_+  , std, std_+  , var, var_+  , norm, norm_+  , renorm, renorm_+  , dist+  , meanall+  , varall+  , stdall+  , normall+  ) where++import Control.Monad.Managed+import System.IO.Unsafe+import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor (empty)++import qualified Torch.Sig.Tensor.Math.Reduce.Floating as Sig++-- | Take the mean in the specified dimension.+mean :: Dynamic+  -> Word  -- ^ dimension to operate over+  -> Dynamic+mean t d = unsafeDupablePerformIO $ do+  let r = empty+  _meanKeepDims r t d+  pure r+{-# NOINLINE mean #-}++-- | Inplace 'mean'+mean_ :: Dynamic+  -> Word  -- ^ dimension to operate over+  -> IO ()+mean_ t = _meanKeepDims t t++-- | '_mean' with defaulted 'KeepDim' as 'True' indicating that the result+-- tensor will be 'squeeze1d' in the specified dimension.+_meanKeepDims :: Dynamic -> Dynamic+  -> Word  -- ^ dimension to operate over+  -> IO ()+_meanKeepDims r t d = _mean r t d keep++-- | C-style function of 'mean' and 'mean_'. Should not be exported.+_mean :: Dynamic -> Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> IO ()+_mean r t d b = with2DynamicState r t $ \s' r' t' ->+  Sig.c_mean s' r' t'  (fromIntegral d) (fromIntegral $ fromEnum b)++-- | Performs the @std@ operation over the specified dimension. The 'Bool'+-- parameter specifies whether the standard deviation should be used with+-- @n-1@ or @n@. 'False' normalizes by @n-1@, while 'True' normalizes @n@.+std+  :: Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim+  -> Bool+  -> Dynamic+std t a b c = unsafeDupablePerformIO $ do+  let r = empty+  _std r t a b c+  pure r+{-# NOINLINE std #-}++-- | Infix version of 'std'.+std_ :: Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> Bool -> IO ()+std_ t = _std t t++-- | C-style function of 'std' and 'std_'. Should not be exported.+_std :: Dynamic -> Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> Bool -> IO ()+_std r t a b c = with2DynamicState r t $ \s' r' t' ->+  Sig.c_std s' r' t' (fromIntegral a) (fromIntegral $ fromEnum b) (toEnum $ fromEnum c)++-- | Get the variance over a tensor in the specified dimension. The 'Bool'+-- parameter specifies whether the standard deviation should be used with+-- @n-1@ or @n@. 'False' normalizes by @n-1@, while 'True' normalizes @n@.+var :: Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> Bool -> Dynamic+var t a b c = unsafeDupablePerformIO $ do+  let r = empty+  _var r t a b c+  pure r+{-# NOINLINE var #-}++-- | Infix version of 'var'.+var_ :: Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> Bool -> IO ()+var_ t = _var t t++-- | C-style function of 'var' and 'var_'. Should not be exported.+_var :: Dynamic -> Dynamic+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> Bool -> IO ()+_var r t a b c = with2DynamicState r t $ \s' r' t' -> Sig.c_var s' r' t' (fromIntegral a) (fromIntegral $ fromEnum b) (fromIntegral $ fromEnum c)++-- | Return the @p@-norms of the tensor, computed over dimension @dim@.+norm :: Dynamic -> HsReal+  -> Word  -- ^ dimension to operate over+  -> Dynamic+norm t p d = unsafeDupablePerformIO $ do+  let r = empty+  _normKeepDims r t p d+  pure r+{-# NOINLINE norm #-}++-- | Inplace version of 'norm'+norm_ :: Dynamic -> HsReal+  -> Word  -- ^ dimension to operate over+  -> IO ()+norm_ t = _normKeepDims t t++-- | '_norm' with defaulted 'KeepDim' as 'True' indicating that the result+-- tensor will be 'squeeze1d'd in the specified dimension.+_normKeepDims :: Dynamic -> Dynamic -> HsReal+  -> Word  -- ^ dimension to operate over+  -> IO ()+_normKeepDims r t p d = _norm r t p d keep++-- | C-style function of 'norm' and 'norm_'. Should not be exported.+_norm :: Dynamic -> Dynamic -> HsReal+  -> Word  -- ^ dimension to operate over+  -> KeepDim -> IO ()+_norm r t p d k = with2DynamicState r t $ \s' r' t' -> Sig.c_norm s' r' t' (hs2cReal p) (fromIntegral d) (fromIntegral $ fromEnum k)++-- | Renormalizes the sub-Tensors along dimension @dim@ such that they do not+-- exceed norm @maxnorm@.+--+-- Equivalent to the following lua code: @y = torch.renorm(x, p, dim, maxnorm)@.+-- Returns a version of @x@ with @p@-norms lower than maxnorm over non-@dim@+-- dimensions. The @dim@ argument is not to be confused with the argument of the+-- same name in function 'norm'. In this case, the @p@-norm is measured for each+-- @i@-th sub-tensor (lua: @x:select(dim, i)@).+renorm+  :: Dynamic    -- ^ @x@+  -> HsReal     -- ^ @p@+  -> Int        -- ^ @dim@+  -> HsReal     -- ^ @maxnorm@+  -> Dynamic    -- ^ @res@+renorm x p dim mn = unsafeDupablePerformIO $ do+  let res = empty+  _renorm res x p dim mn+  pure res+{-# NOINLINE renorm #-}++-- | inplace version of 'renorm'+renorm_ :: Dynamic -> HsReal -> Int -> HsReal -> IO ()+renorm_ t = _renorm t t++-- | C-style function of 'renorm' and 'renorm_'. Should not be exported.+_renorm :: Dynamic -> Dynamic -> HsReal -> Int -> HsReal -> IO ()+_renorm r t v a v0 = with2DynamicState r t $ \s' r' t' -> Sig.c_renorm s' r' t' (hs2cReal v) (fromIntegral a) (hs2cReal v0)++-- | Returns the @p@-norm of @x - y@.+dist+  :: Dynamic       -- ^ tensor @x@+  -> Dynamic       -- ^ tensor @y@+  -> HsReal        -- ^ @p@+  -> HsAccReal+dist r t v = unsafeDupablePerformIO $ with2DynamicState r t $ \s' r' t' -> fmap c2hsAccReal $ Sig.c_dist s' r' t' (hs2cReal v)+{-# NOINLINE dist #-}++-- | Returns the mean of all elements.+meanall :: Dynamic -> HsAccReal+meanall t = unsafeDupablePerformIO $ flip with (pure . c2hsAccReal) $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_meanall s' t'+{-# NOINLINE meanall #-}++-- | Returns the variance of all elements.+varall :: Dynamic -> Int -> HsAccReal+varall t v = unsafeDupablePerformIO $ flip with (pure . c2hsAccReal) $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_varall s' t' (fromIntegral v)+{-# NOINLINE varall #-}++-- | Returns the standard deviation of all elements.+stdall :: Dynamic -> Int -> HsAccReal+stdall t v = unsafeDupablePerformIO $ flip with (pure . c2hsAccReal) $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_stdall s' t' (fromIntegral v)+{-# NOINLINE stdall #-}++-- | Returns the @p@-norm of all elements.+normall+  :: Dynamic  -- ^ tensor of values to norm over+  -> HsReal   -- ^ @p@+  -> HsAccReal+normall t v = unsafeDupablePerformIO $ flip with (pure . c2hsAccReal) $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_normall s' t' (hs2cReal v)+{-# NOINLINE normall #-}
+ src/Torch/Indef/Dynamic/Tensor/Math/Scan.hs view
@@ -0,0 +1,39 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Math.Scan+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Math.Scan where++import Torch.Indef.Types++import qualified Torch.Sig.Tensor.Math.Scan as Sig++-- | Mutate the first tensor to contain the cumulative sum of the elements in the second, performing the operation over the specified dimension.+_cumsum+  :: Dynamic     -- ^ return tensor to mutate, inplace+  -> Dynamic     -- ^ source tensor+  -> Word        -- ^ dimension to operate on+  -> IO ()+_cumsum t0 t1 i0 = withLift $ Sig.c_cumsum+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral i0)++-- | Mutate the first tensor to contain the cumulative product of the elements in the second, performing the operation over the specified dimension.+_cumprod+  :: Dynamic     -- ^ return tensor to mutate, inplace+  -> Dynamic     -- ^ source tensor+  -> Word        -- ^ dimension to operate on+  -> IO ()+_cumprod t0 t1 i0 = withLift $ Sig.c_cumprod+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+
+ src/Torch/Indef/Dynamic/Tensor/Mode.hs view
@@ -0,0 +1,41 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Mode+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Mode where++import Control.Monad.Managed+import Foreign (withForeignPtr)++import qualified Torch.Sig.Tensor.Mode as Sig+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Indef.Index as Ix++import Torch.Indef.Types++-- | Mutate the tuple of a tensor and index tensor to contain the most frequent element in the specified dimension.+--+-- FIXME: if KeepDim is False, we need to return Nothing for the index tensor -- otherwise bad things may happen.+_mode+  :: (Dynamic, IndexDynamic)+  -> Dynamic+  -> Word                   -- ^ dimension to operate over+  -> Maybe KeepDim+  -> IO ()+_mode (t0, ix) t1 i0 i1 = withLift $ Sig.c_mode+  <$> managedState+  <*> managedTensor t0+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromKeepDim i1)+-- with2DynamicState t0 t1 $ \s' t0' t1' ->+--   Ix.withDynamicState ix $ \_ ix' ->+    -- Sig.c_mode s' t0' ix' t1' (fromIntegral i0) (fromKeepDim i1)++
+ src/Torch/Indef/Dynamic/Tensor/Random/TH.hs view
@@ -0,0 +1,399 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Random.TH+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Torch provides accurate mathematical random generation, based on+-- <http://www.math.sci.hiroshima-u.ac.jp/%7Em-mat/MT/emt.html Mersenne Twister>+-- random number generator.+--+-- FIXME: verify these are all correct -- I am working off of+-- <https://github.com/torch/torch7/blob/aed31711c6b8846b8337a263a7f9f998697994e7/doc/random.md+-- random.md> from torch/torch7.+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Random.TH+  ( _random                 , random+  , _clampedRandom          , clampedRandom+  , _cappedRandom           , cappedRandom+  , _geometric              , geometric+  , _bernoulli              , bernoulli+  , _bernoulli_FloatTensor  , bernoulli_FloatTensor+  , _bernoulli_DoubleTensor , bernoulli_DoubleTensor+  , _uniform                , uniform+  , _normal                 , normal+  , _normal_means           , normal_means+  , _normal_stddevs         , normal_stddevs+  , _normal_means_stddevs   , normal_means_stddevs+  , _exponential            , exponential+  , _standard_gamma         , standard_gamma+  , _cauchy                 , cauchy+  , _logNormal              , logNormal+  , _multinomial+  , _multinomialAliasSetup+  , _multinomialAliasDraw++  , OpenUnit, openUnit, openUnitValue+  , ClosedUnit, closedUnit, closedUnitValue+  , Positive, positive, positiveValue+  , Ord2Tuple, ord2Tuple, ord2TupleValue+  ) where++import Foreign hiding (with, new)+import Foreign.Ptr+import GHC.Word+import Numeric.Dimensions+import Control.Monad.Managed++import Torch.Types.Numeric+import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor+import qualified Torch.Sig.Tensor.Random.TH as Sig+import qualified Torch.Sig.Types as Sig+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Types.TH as TH++-- | Returns a tensor of specified size with random numbers from [1,2^mantissa].+random :: Dims (d::[Nat]) -> Generator -> IO Dynamic+random d g = withInplace (`_random` g) d++-- | Returns a tensor of specified size with random numbers from @[minBound,maxBound]@.+clampedRandom+  :: Dims (d::[Nat])   -- ^ size of tensor to create+  -> Generator         -- ^ generator+  -> Ord2Tuple Integer -- ^ (minbound, maxBound)+  -> IO Dynamic+clampedRandom d g bs = flip withInplace d $ \t -> _clampedRandom t g bs++-- | Returns a tensor of specified size with random numbers from @[0,maxBound]@.+cappedRandom+  :: Dims (d::[Nat])  -- ^ size of tensor to create+  -> Generator        -- ^ generator+  -> Word64           -- ^ maxbound+  -> IO Dynamic+cappedRandom d g a = flip withInplace d $ \t -> _cappedRandom t g a++-- | Returns a random tensor according to a geometric distribution+-- @p(i) = (1-p) * p^(i-1)@. @p@ must satisfy @0 < p < 1@.+geometric+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> OpenUnit HsAccReal   -- ^ @p@, where @0 < p < 1@+  -> IO Dynamic+geometric d g p = flip withInplace d $ \t -> _geometric t g (openUnitValue p)++-- | Returns a tensor filled with elements which are 1 with probability @p@ and+-- 0 with probability @1-p@. @p@ must satisfy @0 <= p <= 1@.+bernoulli+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> ClosedUnit HsAccReal -- ^ @p@, where @0 <= p <= 1@+  -> IO Dynamic+bernoulli d g a = flip withInplace d $ \t -> _bernoulli t g (closedUnitValue a)++-- | Undocumented in Lua. It is assumed that this returns a tensor filled with+-- elements which are 1 with probability @p@ and 0 with probability @1-p@,+-- where @p@ comes from the 'TH.FloatDynamic' tensor. All @p@s must satisfy+-- @0 <= p <= 1@. It is uncertain if the output dimensions and the+-- 'TH.FloatDynamic' tensor dimensions need to match.+bernoulli_FloatTensor+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> TH.FloatDynamic      -- ^ float tensor of @p@ values, where @0 <= p <= 1@+  -> IO Dynamic+bernoulli_FloatTensor d g a = flip withInplace d $ \t -> _bernoulli_FloatTensor t g a++-- | Undocumented in Lua. It is assumed that this returns a tensor filled with+-- elements which are 1 with probability @p@ and 0 with probability @1-p@,+-- where @p@ comes from the 'TH.DoubleDynamic' tensor. All @p@s must satisfy+-- @0 <= p <= 1@. It is uncertain if the output dimensions and the+-- 'TH.DoubleDynamic' tensor dimensions need to match.+bernoulli_DoubleTensor+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> TH.DoubleDynamic     -- ^ double tensor of @p@ values, where @0 <= p <= 1@+  -> IO Dynamic+bernoulli_DoubleTensor d g a = flip withInplace d $ \t -> _bernoulli_DoubleTensor t g a++-- | Returns a tensor filled with values according to uniform distribution on @[a,b)@.+uniform+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> Ord2Tuple HsAccReal  -- ^ tuple of @(a, b)@ representing the @[a,b)@ interval.+  -> IO Dynamic+uniform d g tup = flip withInplace d $ \t -> _uniform t g tup++-- | Returns a tensor filled with values according to a normal distribution with+-- the given mean and standard deviation stdv. stdv must be positive.+normal+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> HsAccReal            -- ^ mean+  -> Positive HsAccReal   -- ^ standard deviation.+  -> IO Dynamic+normal d g a b = flip withInplace d $ \t -> _normal t g a b++-- | Same as 'normal', taking a tensor of means to use instead of a scalar.+--+-- FIXME: It is uncertain if the output dimensions and mean tensor dimensions+-- need to match.+normal_means+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> Dynamic              -- ^ tensor of means+  -> Positive HsAccReal   -- ^ standard deviation.+  -> IO Dynamic+normal_means d g m b = flip withInplace d $ \t -> _normal_means t g m b++-- | Same as 'normal', taking a tensor of standard deviations to use instead of+-- a scalar. All standard deviations must be positive.+--+-- FIXME: It is uncertain if the output dimensions and stddv tensor dimensions+-- need to match.+normal_stddevs+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> HsAccReal            -- ^ mean+  -> Dynamic              -- ^ tensor of standard deviations+  -> IO Dynamic+normal_stddevs d g a s = flip withInplace d $ \t -> _normal_stddevs t g a s++-- | Same as 'normal', taking a tensor of standard deviations and tensor of means+-- to use instead of a scalar values. All standard deviations must be positive.+--+-- FIXME: It is uncertain if all of the tensor dimensions need to match.+normal_means_stddevs+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> Dynamic              -- ^ tensor of means+  -> Dynamic              -- ^ tensor of standard deviations+  -> IO Dynamic+normal_means_stddevs d g m s = flip withInplace d $ \t -> _normal_means_stddevs t g m s++-- | Returns a tensor filled with values according to the exponential distribution+-- @p(x) = lambda * exp(-lambda * x)@.+exponential+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> HsAccReal            -- ^ lambda+  -> IO Dynamic+exponential d g a = flip withInplace d $ \t -> _exponential t g a++-- |  Draw samples from a standard Gamma distribution.+--+-- PyTorch's @standard_gamma@ function mostly references Numpy's. Documentation can be found here:+-- <https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.standard_gamma.html numpy.random.standard_gamma>+--+-- I (stites) am not sure at the moment if the tensor argument is a tensor of+-- parameters (in which case, can we replace it with something safer?), or a datasource.+--+-- FIXME(stites): This is an undocumented feature as far as I can tell. Someone+-- should update this with a more thorough investigation.+standard_gamma+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> Dynamic+  -> IO Dynamic+standard_gamma d g a = flip withInplace d $ \t -> _standard_gamma t g a++-- | Returns a tensor filled with values according to the Cauchy distribution+-- @p(x) = sigma/(pi*(sigma^2 + (x-median)^2))@+cauchy+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> HsAccReal            -- ^ median+  -> HsAccReal            -- ^ sigma+  -> IO Dynamic+cauchy d g a b = flip withInplace d $ \t -> _cauchy t g a b++-- | Returns a tensor filled with values according to the log-normal+-- distribution with the given mean and standard deviation stdv. mean and stdv+-- are the corresponding mean and standard deviation of the underlying normal+-- distribution, and not of the returned distribution.+--+-- stdv must be positive.+logNormal+  :: Dims (d::[Nat])      -- ^ size of tensor to create+  -> Generator            -- ^ generator+  -> HsAccReal            -- ^ mean+  -> Positive HsAccReal   -- ^ standard deviation.+  -> IO Dynamic+logNormal d g a b = flip withInplace d $ \t -> _logNormal t g a b++-- | call C-level @random@+_random t g = tenGen t g Sig.c_random++-- | call C-level @clampedRandom@+_clampedRandom r g tup = withLift $ Sig.c_clampedRandom+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)+  where+    (a, b) = ord2TupleValue tup++-- | call C-level @cappedRandom@+_cappedRandom r g a = withLift $ Sig.c_cappedRandom+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> pure (fromIntegral a)++-- | call C-level @geometric@+_geometric r g a = withLift $ Sig.c_geometric+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> pure (hs2cAccReal a)++-- | call C-level @bernoulli@+_bernoulli r g a = withLift $ Sig.c_bernoulli+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> pure (hs2cAccReal a)++-- | call C-level @bernoulli_FloatTensor@+_bernoulli_FloatTensor r g a = tenGenTen r g (snd $ TH.floatDynamicState a) Sig.c_bernoulli_FloatTensor++-- | call C-level @bernoulli_DoubleTensor@+_bernoulli_DoubleTensor r g a = tenGenTen r g (snd $ TH.doubleDynamicState a) Sig.c_bernoulli_DoubleTensor++-- | call C-level @uniform@+_uniform :: Dynamic -> Generator -> Ord2Tuple HsAccReal -> IO ()+_uniform r g tup = withLift $ Sig.c_uniform+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> pure (hs2cAccReal a)+  <*> pure (hs2cAccReal b)+  where+    (a, b) = ord2TupleValue tup++-- | call C-level @normal@+_normal :: Dynamic -> Generator -> HsAccReal -> Positive HsAccReal -> IO ()+_normal r g a b = withLift $ Sig.c_normal+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> pure (hs2cAccReal a)+  <*> pure (hs2cAccReal $ positiveValue b)+++-- | call C-level @normal_means@+_normal_means :: Dynamic -> Generator -> Dynamic -> Positive HsAccReal -> IO ()+_normal_means r g m v = withLift $ Sig.c_normal_means+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> managedTensor m+  <*> pure (Sig.hs2cAccReal $ positiveValue v)++-- | call C-level @normal_stddevs@+_normal_stddevs :: Dynamic -> Generator -> HsAccReal -> Dynamic -> IO ()+_normal_stddevs r g v m = withLift $ Sig.c_normal_stddevs+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> pure (Sig.hs2cAccReal v)+  <*> managedTensor m++-- | call C-level @normal_means_stddevs@+_normal_means_stddevs :: Dynamic -> Generator -> Dynamic -> Dynamic -> IO ()+_normal_means_stddevs r g a b = withLift $ Sig.c_normal_means_stddevs+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> managedTensor a+  <*> managedTensor b++-- | call C-level @exponential@+_exponential :: Dynamic -> Generator -> HsAccReal -> IO ()+_exponential r g v = withLift $ Sig.c_exponential+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> pure (Sig.hs2cAccReal v)++-- | call C-level @standard_gamma@+_standard_gamma :: Dynamic -> Generator -> Dynamic -> IO ()+_standard_gamma r g m = withLift $ Sig.c_standard_gamma+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> managedTensor m++-- | call C-level @cauchy@+_cauchy :: Dynamic -> Generator -> HsAccReal -> HsAccReal -> IO ()+_cauchy r g a b = withLift $ Sig.c_cauchy+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> pure (Sig.hs2cAccReal a)+  <*> pure (Sig.hs2cAccReal b)++-- | call C-level @logNormal@+_logNormal :: Dynamic -> Generator -> HsAccReal -> Positive HsAccReal -> IO ()+_logNormal r g a b = withLift $ Sig.c_logNormal+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> pure (Sig.hs2cAccReal a)+  <*> pure (Sig.hs2cAccReal $ positiveValue b)++-- | call C-level @multinomial@+_multinomial :: LongDynamic -> Generator -> Dynamic -> Int -> Int -> IO ()+_multinomial r g t a b = withLift $ Sig.c_multinomial+  <$> managedState+  <*> managed (withForeignPtr . snd . Sig.longDynamicState $ r)+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> managedTensor t+  <*> pure (fromIntegral a)+  <*> pure (fromIntegral b)++-- | call C-level @multinomialAliasSetup@+_multinomialAliasSetup :: Dynamic -> LongDynamic -> Dynamic -> IO ()+_multinomialAliasSetup r l t = withLift $ Sig.c_multinomialAliasSetup+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . snd . Sig.longDynamicState $ l)+  <*> managedTensor t++-- | call C-level @multinomialAliasDraw@+_multinomialAliasDraw  :: LongDynamic -> Generator -> LongDynamic -> Dynamic -> IO ()+_multinomialAliasDraw r g l t = withLift $ Sig.c_multinomialAliasDraw+  <$> managedState+  <*> managed (withForeignPtr . snd . Sig.longDynamicState $ r)+  <*> managed (withForeignPtr . Sig.rng $ g)+  <*> managed (withForeignPtr . snd . Sig.longDynamicState $ l)+  <*> managedTensor t++-- ========================================================================= --+-- helper functions++tenGen+  :: Dynamic+  -> Generator+  -> (Ptr CState -> Ptr CTensor -> Ptr CGenerator -> IO x)+  -> IO x+tenGen r g fn = withLift $ fn+  <$> managedState+  <*> managedTensor r+  <*> managedGen g++tenGenTen+  :: Dynamic+  -> Generator+  -> ForeignPtr a+  -> (Ptr CState -> Ptr CTensor -> Ptr CGenerator -> Ptr a -> IO x)+  -> IO x+tenGenTen r g t fn = withLift $ fn+  <$> managedState+  <*> managedTensor r+  <*> managedGen g+  <*> managed (withForeignPtr t)+
+ src/Torch/Indef/Dynamic/Tensor/Random/THC.hs view
@@ -0,0 +1,199 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Random.THC+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- GPU-backed random functions. The difference between this package and+-- 'Torch.Indef.Dynamic.Tensor.Random.TH' is that these functions do not get+-- passed an explicit 'Generator' argument.+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Random.THC+  ( _random+  , _clampedRandom+  , _cappedRandom+  , _bernoulli+  , _bernoulli_DoubleTensor+  , _geometric+  , _uniform+  , _normal+  , _normal_means+  , _normal_stddevs+  , _normal_means_stddevs+  , _logNormal+  , _exponential+  , _cauchy+  , _multinomial+  , _multinomialAliasSetup+  , _multinomialAliasDraw+  , _rand+  , _randn+++  , OpenUnit, openUnit, openUnitValue+  , ClosedUnit, closedUnit, closedUnitValue+  , Positive, positive, positiveValue+  , Ord2Tuple, ord2Tuple, ord2TupleValue+  ) where++import Control.Monad.Managed (runManaged, managed)+import Foreign (withForeignPtr)+import Control.Monad.IO.Class (liftIO)++import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor.Random.TH+  ( OpenUnit, openUnit, openUnitValue+  , ClosedUnit, closedUnit, closedUnitValue+  , Positive, positive, positiveValue+  , Ord2Tuple, ord2Tuple, ord2TupleValue+  )++import qualified Torch.Sig.Tensor.Random.THC as Sig+import qualified Torch.Sig.Types as Sig+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Types.TH as TH++-- These import is for haddocks:+import qualified Torch.Indef.Dynamic.Tensor.Random.TH as THRandom+import qualified Torch.Indef.Dynamic.Tensor.Math.Random.TH as THRandomMath++-- | CUDA version of 'THRandom._random'+_random :: Dynamic -> IO ()+_random t = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_random s' t'++-- | CUDA version of 'THRandom._clampedRandom'+_clampedRandom :: Dynamic -> Integer -> Integer -> IO ()+_clampedRandom t mn mx = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_clampedRandom s' t' (fromIntegral mn) (fromIntegral mx)++-- | CUDA version of 'THRandom._cappedRandom'+_cappedRandom :: Dynamic -> Integer -> IO ()+_cappedRandom t c = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_cappedRandom s' t' (fromIntegral c)++-- | CUDA version of 'THRandom._bernoulli'+_bernoulli :: Dynamic -> HsAccReal -> IO ()+_bernoulli t v = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_bernoulli s' t' (hs2cAccReal v)++-- | CUDA version of 'THRandom._bernoulli_DoubleTensor'+_bernoulli_DoubleTensor :: Dynamic -> Dynamic -> IO ()+_bernoulli_DoubleTensor t d = with2DynamicState t d Sig.c_bernoulli_DoubleTensor++-- | CUDA version of 'THRandom._geometric'+_geometric :: Dynamic -> HsAccReal -> IO ()+_geometric t v = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_geometric s' t' (hs2cAccReal v)++-- | CUDA version of 'THRandom._uniform'+_uniform :: Dynamic -> Ord2Tuple HsAccReal -> IO ()+_uniform t tup = runManaged $ do+  s' <- managedState+  t' <- managedTensor t+  liftIO $ Sig.c_uniform s' t' (hs2cAccReal a) (hs2cAccReal b)+  where+    (a, b) = ord2TupleValue tup++-- | CUDA version of 'THRandom._normal'+_normal :: Dynamic -> HsAccReal -> Positive HsAccReal -> IO ()+_normal r a b = runManaged . (liftIO =<<) $ Sig.c_normal+   <$> managedState+   <*> managedTensor r+   <*> pure (hs2cAccReal a)+   <*> pure (hs2cAccReal $ positiveValue b)++-- | CUDA version of 'THRandom._normal_means'+_normal_means :: Dynamic -> Dynamic -> Positive HsAccReal -> IO ()+_normal_means r m v = runManaged . (liftIO =<<) $ Sig.c_normal_means+  <$> managedState+  <*> managedTensor r+  <*> managedTensor m+  <*> pure (Sig.hs2cAccReal $ positiveValue v)++-- | CUDA version of 'THRandom._normal_stddevs'+_normal_stddevs :: Dynamic -> HsAccReal -> Dynamic -> IO ()+_normal_stddevs t a b = with2DynamicState t b $ \s' t' b' -> Sig.c_normal_stddevs s' t' (hs2cAccReal a) b'++-- | CUDA version of 'THRandom._normal_means_stddevs'+_normal_means_stddevs :: Dynamic -> Dynamic -> Dynamic -> IO ()+_normal_means_stddevs t t0 t1 = with3DynamicState t t0 t1 Sig.c_normal_means_stddevs++-- | call C-level @logNormal@+-- | CUDA version of 'THRandom._logNormal'+_logNormal :: Dynamic -> HsAccReal -> Positive HsAccReal -> IO ()+_logNormal r a b = runManaged . (liftIO =<<) $ Sig.c_logNormal+  <$> managedState+  <*> managedTensor r+  <*> pure (Sig.hs2cAccReal a)+  <*> pure (Sig.hs2cAccReal $ positiveValue b)+++-- | CUDA version of 'THRandom._exponential'+_exponential :: Dynamic -> HsAccReal -> IO ()+_exponential t v = runManaged . (liftIO =<<) $ Sig.c_exponential+  <$> managedState+  <*> managedTensor t+  <*> pure (hs2cAccReal v)++-- | CUDA version of 'THRandom._cauchy'+_cauchy :: Dynamic -> HsAccReal -> HsAccReal -> IO ()+_cauchy t a b = runManaged . (liftIO =<<) $ Sig.c_cauchy+  <$> managedState+  <*> managedTensor t+  <*> pure (hs2cAccReal a)+  <*> pure (hs2cAccReal b)++-- | CUDA version of 'THRandom._multinomial'+_multinomial :: IndexDynamic -> Dynamic -> Int -> Int -> IO ()+_multinomial r t a b = runManaged . (liftIO =<<) $ Sig.c_multinomial+   <$> managedState+   <*> managed (withForeignPtr . snd . Sig.longDynamicState $ r)+   <*> managedTensor t+   <*> pure (fromIntegral a)+   <*> pure (fromIntegral b)++-- | CUDA version of 'THRandom._multinomialAliasSetup'+_multinomialAliasSetup :: Dynamic -> LongDynamic -> Dynamic -> IO ()+_multinomialAliasSetup r l t = runManaged . (liftIO =<<) $ Sig.c_multinomialAliasSetup+   <$> managedState+   <*> managedTensor r+   <*> managed (withForeignPtr . snd . Sig.longDynamicState $ l)+   <*> managedTensor t++-- | CUDA version of 'THRandom._multinomialAliasDraw'+_multinomialAliasDraw  :: LongDynamic -> LongDynamic -> Dynamic -> IO ()+_multinomialAliasDraw r l t = runManaged . (liftIO =<<) $ Sig.c_multinomialAliasDraw+   <$> managedState+   <*> managed (withForeignPtr . snd . Sig.longDynamicState $ r)+   <*> managed (withForeignPtr . snd . Sig.longDynamicState $ l)+   <*> managedTensor t++-- | CUDA version of 'THRandomMath._rand'+_rand  :: Dynamic -> TH.LongStorage -> IO ()+_rand r l = runManaged . (liftIO =<<) $ Sig.c_rand+   <$> managedState+   <*> managedTensor r+   <*> managed (withForeignPtr . snd . TH.longStorageState $ l)++-- | CUDA version of 'THRandomMath._randn'+_randn  :: Dynamic -> TH.LongStorage -> IO ()+_randn r l = runManaged . (liftIO =<<) $ Sig.c_randn+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr . snd . TH.longStorageState $ l)++
+ src/Torch/Indef/Dynamic/Tensor/ScatterGather.hs view
@@ -0,0 +1,83 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.ScatterGather+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.ScatterGather where++import Control.Monad.Managed+import Torch.Indef.Types+import qualified Torch.Indef.Index as Ix+import qualified Torch.Sig.Tensor.ScatterGather as Sig++-- | From the Lua docs:+--+-- Creates a new Tensor from the original tensor by gathering a number of values from each "row", where the rows are along the dimension dim. The values in a LongTensor, passed as index, specify which values to take from each row. Specifically, the resulting Tensor, which will have the same size as the index tensor, is given by+--+-- @+--   -- dim = 1+--   result[i][j][k]... = src[index[i][j][k]...][j][k]...+--+--   -- dim = 2+--   result[i][j][k]... = src[i][index[i][j][k]...][k]...+--+--   -- etc.+-- @+--+-- where src is the original Tensor.+--+-- The same number of values are selected from each row, and the same value cannot be selected from a row more than once. The values in the index tensor must not be larger than the length of the row, that is they must be between 1 and src:size(dim) inclusive. It can be somewhat confusing to ensure that the index tensor has the correct shape. Viewed pictorially:+_gather+  :: Dynamic+  -> Dynamic+  -> Word               -- ^ dimension to operate on+  -> IndexDynamic+  -> IO ()+_gather r src d ix = with2DynamicState r src $ \s' r' src' ->+  Ix.withDynamicState ix $ \_ ix' ->+    Sig.c_gather s' r' src' (fromIntegral d) ix'++-- | From the Lua docs:+--+-- Writes all values from tensor src or the scalar val into self at the+-- specified indices. The indices are specified with respect to the given+-- dimension, dim, in the manner described in gather. Note that, as for gather,+-- the values of index must be between 1 and self:size(dim) inclusive and all+-- values in a row along the specified dimension must be unique.+_scatter+  :: Dynamic+  -> Word               -- ^ dimension to operate on+  -> IndexDynamic+  -> Dynamic+  -> IO ()+_scatter r d ix src = with2DynamicState r src $ \s' r' src' ->+  Ix.withDynamicState ix $ \_ ix' ->+    Sig.c_scatter s' r' (fromIntegral d) ix' src'++-- | TODO+_scatterAdd+  :: Dynamic+  -> Word               -- ^ dimension to operate on+  -> IndexDynamic+  -> Dynamic+  -> IO ()+_scatterAdd r d ix src = with2DynamicState r src $ \s' r' src' ->+  Ix.withDynamicState ix $ \_ ix' ->+    Sig.c_scatterAdd s' r' (fromIntegral d) ix' src'++-- | TODO+_scatterFill+  :: Dynamic+  -> Word               -- ^ dimension to operate on+  -> IndexDynamic+  -> HsReal+  -> IO ()+_scatterFill r d ix v = runManaged $ do+  s' <- managedState+  r' <- managedTensor r+  liftIO $ Ix.withDynamicState ix $ \_ ix' -> Sig.c_scatterFill s' r' (fromIntegral d) ix' (hs2cReal v)+
+ src/Torch/Indef/Dynamic/Tensor/Sort.hs view
@@ -0,0 +1,38 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.Sort+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.Sort where++import Foreign+import Control.Monad.Managed+import Torch.Indef.Types+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Sig.Tensor.Sort as Sig+import qualified Torch.Indef.Index as Ix++-- | Returns a tensor and index where all entries are sorted along the given+-- dimension, in the chosen sort order. The index corresponds to the original+-- indices.+_sort+  :: (Dynamic, IndexDynamic)+  -> Dynamic+  -> Word           -- ^ dimension to operate on+  -> SortOrder+  -> IO ()+_sort (r, ix) t1 i0 i1 = withLift $ Sig.c_sort+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t1+  <*> pure (fromIntegral i0)+  <*> pure (fromIntegral $ fromEnum i0)+++-- THC Only:+-- sortKeyValueInplace :: t -> IndexDynamic t -> Int -> Int -> IO ()
+ src/Torch/Indef/Dynamic/Tensor/TopK.hs view
@@ -0,0 +1,37 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Tensor.TopK+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Dynamic.Tensor.TopK where++import Foreign+import Control.Monad.Managed+import Torch.Indef.Types+import qualified Torch.Sig.Types.Global as Sig+import qualified Torch.Sig.Tensor.TopK as Sig+import qualified Torch.Indef.Index as Ix++-- | returns all @k@ smallest elements in a tensor over a given dimension, including their indices, in unsorted order.+_topk+  :: (Dynamic, IndexDynamic)+  -> Dynamic+  -> Integer+  -> Word           -- ^ dimension to operate on+  -> TopKOrder+  -> Maybe KeepDim+  -> IO ()+_topk (r, ix) t1 l i0 o sorted = withLift $ Sig.c_topk+  <$> managedState+  <*> managedTensor r+  <*> managed (withForeignPtr (snd $ Sig.longDynamicState ix))+  <*> managedTensor t1+  <*> pure (fromIntegral l)+  <*> pure (fromIntegral i0)+  <*> pure (fromIntegral $ fromEnum o)+  <*> pure (fromKeepDim sorted)+
+ src/Torch/Indef/Index.hs view
@@ -0,0 +1,284 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Index+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Redundant version of @Torch.Indef.{Dynamic/Static}.Tensor@ for Index tensors.+--+-- FIXME: in the future, there could be a smaller subset of Torch which could+-- be compiled to to keep the code dry. Alternatively, if backpack one day+-- supports recursive indefinites, we could use this feature to possibly remove+-- this package and 'Torch.Indef.Mask'.+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE MonoLocalBinds #-}+module Torch.Indef.Index+  ( singleton+  , esingleton+  , newIx+  , newIxDyn+  , zeroIxNd+  , index+  , index1d+  , indexNd+  , indexDyn+  , mkCPUIx+  , withCPUIxStorage+  , withIxStorage+  , withDynamicState+  , mkCPUIxStorage+  , ixShape+  , ixCPUStorage+  , showIx+  ) where++import Foreign+import Foreign.Ptr+import Data.Proxy+import Data.List+import Data.Typeable+import Data.Maybe+import Data.Singletons.Prelude.List+import Control.Monad+import Control.Applicative+import System.IO.Unsafe+import Numeric.Dimensions++import Torch.Sig.State as Sig+import Torch.Sig.Types.Global as Sig+import Torch.Indef.Types hiding (withDynamicState, mkDynamic, mkDynamicIO)+import Torch.Indef.Internal+import qualified Torch.Types.TH as TH+import qualified Torch.Types.TH.Long as THLong+import qualified Torch.Sig.Index.Tensor as IxSig+import qualified Torch.Sig.Index.TensorFree as IxSig+import qualified Torch.FFI.TH.Long.Storage as LongStorage+import qualified Torch.FFI.TH.Long.Storage as LongStorage+import qualified Torch.FFI.TH.Long.Tensor as LongTensor+import qualified Foreign as FM+import qualified Foreign.Marshal.Array as FM++singleton :: Integral i => i -> IndexTensor '[1]+singleton = longAsStatic . indexDyn . (:[]) . fromIntegral++esingleton :: Enum i => i -> IndexTensor '[1]+esingleton = singleton . fromEnum++-- | build a new static index tensor+--+-- FIXME: This can abstracted away with backpack, but I'm not sure if it can do it atm.+newIx :: forall d . Dimensions d => IndexTensor d+newIx = longAsStatic $ newIxDyn (listDims (dims :: Dims d))++-- | build a new, empty, static index tensor with no term-level dimensions -- but allow+-- the type-level dimensions to vary.+--+-- FIXME: this is a bad function and should be replaced with a 'Torch.Indef.Static.Tensor.new' function.+zeroIxNd :: Dimensions d => IndexTensor d+zeroIxNd = longAsStatic $ newIxDyn [0]++-- | build a new 1-dimensional, dynamically-typed index tensor of lenght @i@+newIxDyn :: Integral i => [i] -> IndexDynamic+newIxDyn is = unsafePerformIO $ withForeignPtr Sig.torchstate $ \s ->+  case is of+    [] -> IxSig.c_new s >>= mkDynamic+    [x] -> IxSig.c_newWithSize1d s (fromIntegral x) >>= mkDynamic+    [x, y] -> IxSig.c_newWithSize2d s (fromIntegral x) (fromIntegral y) >>= mkDynamic+    [x, y, z] -> IxSig.c_newWithSize3d s (fromIntegral x) (fromIntegral y) (fromIntegral z) >>= mkDynamic+    _ -> error "> 4-dimensional indexes not currently supported"++-- | Make a dynamic, 1d index tensor from a list.+--+-- FIXME construct this with TH, not with the setting, which might be doing a second linear pass+indexDyn :: [Integer] -> IndexDynamic+indexDyn l = unsafePerformIO $ do+  let res = newIxDyn [length l]+  mapM_  (upd res) (zip [0..length l - 1] l)+  pure res++  where+    upd :: IndexDynamic -> (Int, Integer) -> IO ()+    upd t (idx, v) = withDynamicState t $ \s' t' -> IxSig.c_set1d s' t' (fromIntegral idx) (fromIntegral v)++-- | purely make a 1d static index tensor from a list of integers. Returns Nothing if the+-- list does not match the expected size of the tensor.+--+-- should be depreciated in favor of 'index1d'+index :: forall n . KnownDim n => [Integer] -> Maybe (IndexTensor '[n])+index l+  | genericLength l == dimVal (dim :: Dim n) = Just . longAsStatic . indexDyn $ l+  | otherwise = Nothing++-- | alias to 'index' and should subsume it when this package no longer assumes that index tensors are 1d.+index1d :: KnownDim n => [Integer] -> Maybe (IndexTensor '[n])+index1d = index++-- | n-dimensional version of 'index1d'.+--+-- FIXME: this relies on 'indexDyn' which only makes 1d tensors.+indexNd :: forall d . KnownDim (Product d) => [Integer] -> Maybe (IndexTensor d)+indexNd l+  | genericLength l == dimVal (dim :: Dim (Product d)) = Just . longAsStatic . indexDyn $ l+  | otherwise = Nothing++-- | Convenience method for 'newWithData' specific to longs for making CPU Long storage.+ixCPUStorage :: [Integer] -> IO TH.LongStorage+ixCPUStorage pr = withForeignPtr TH.torchstate $ \st -> do+  pr' <- FM.withArray (THLong.hs2cReal <$> pr) pure+  thl <- LongStorage.c_newWithData st pr' (fromIntegral $ length pr)+  TH.LongStorage <$> ((TH.torchstate,)+    <$> FM.newForeignPtr LongStorage.p_free thl)++-- | resize a 1d dynamic index tensor.+--+-- FIXME: export or remove this function as appropriate.+_resizeDim1d :: IndexDynamic -> Integer -> IO ()+_resizeDim1d t x = withDynamicState t $ \s' t' -> IxSig.c_resize1d s' t' (fromIntegral x)++-- | make a dynamic CPU tensor from a raw torch ctensor+mkCPUIx :: Ptr TH.C'THLongTensor -> IO TH.LongDynamic+mkCPUIx p = fmap TH.LongDynamic+  $ (TH.torchstate,)+  <$> newForeignPtr LongTensor.p_free p++-- | run a function with access to a raw CPU-bound Long tensor storage.+withCPUIxStorage :: TH.LongStorage -> (Ptr TH.C'THLongStorage -> IO x) -> IO x+withCPUIxStorage ix fn = withForeignPtr (snd $ TH.longStorageState ix) fn++-- | run a function with access to a dynamic index tensor's raw internal state and c-pointer.+withDynamicState :: IndexDynamic -> (Ptr Sig.CState -> Ptr Sig.CLongTensor -> IO x) -> IO x+withDynamicState t fn = do+  withForeignPtr (fst $ Sig.longDynamicState t) $ \sref ->+    withForeignPtr (snd $ Sig.longDynamicState t) $ \tref ->+      fn sref tref++-- | run a function with access to a dynamic index storage's raw internal state and c-pointer.+withIxStorage :: Sig.IndexStorage -> (Ptr CLongStorage -> IO x) -> IO x+withIxStorage ix fn = withForeignPtr (snd $ Sig.longStorageState ix) fn++-- | make a dynamic CPU tensor's storage from a raw torch LongStorage+mkCPUIxStorage :: Ptr TH.C'THLongStorage -> IO TH.LongStorage+mkCPUIxStorage p = fmap TH.LongStorage+  $ (TH.torchstate,)+  <$> newForeignPtr LongStorage.p_free p++-- | get the shape of a static index tensor from the term-level+ixShape :: IndexTensor d -> [Word]+ixShape t = unsafePerformIO $ withDynamicState (longAsDynamic t) $ \s' t' -> do+  ds <- IxSig.c_nDimension s' t'+  mapM (fmap fromIntegral . IxSig.c_size s' t' . fromIntegral) [0..ds-1]++-- | show an index.+--+-- FIXME: because we are using backpack, we can't declare a show instance on the IndexTensor both+-- here and in the signatures. /if we want this functionality we must operate on raw code and write+-- the show instance in hasktorch-types/.+{-# NOINLINE showIx #-}+showIx t = unsafePerformIO $ do+  let ds = fromIntegral <$> ixShape t+  (vs, desc) <- go (ixGet1d t) (ixGet2d t) (ixGet3d t) (ixGet4d t) ds+  pure (vs ++ "\n" ++ desc)+ where+  ixGet1d :: IndexTensor d -> Int64 -> IO Integer+  ixGet1d it i = fmap fromIntegral . withDynamicState (longAsDynamic it) $ \s' it' -> IxSig.c_get1d s' it'+    (fromIntegral i)+  ixGet2d :: IndexTensor d -> Int64 -> Int64 -> IO Integer+  ixGet2d it i i1 = fmap fromIntegral . withDynamicState (longAsDynamic it) $ \s' it' -> IxSig.c_get2d s' it'+    (fromIntegral i) (fromIntegral i1)+  ixGet3d :: IndexTensor d -> Int64 -> Int64 -> Int64 -> IO Integer+  ixGet3d it i i1 i2 = fmap fromIntegral . withDynamicState (longAsDynamic it) $ \s' it' -> IxSig.c_get3d s' it'+    (fromIntegral i) (fromIntegral i1) (fromIntegral i2)++  ixGet4d :: IndexTensor d -> Int64 -> Int64 -> Int64 -> Int64 -> IO Integer+  ixGet4d it i i1 i2 i3 = fmap fromIntegral . withDynamicState (longAsDynamic it) $ \s' it' -> IxSig.c_get4d s' it'+    (fromIntegral i) (fromIntegral i1) (fromIntegral i2) (fromIntegral i3)++  go+    :: forall a . (Typeable a, Ord a, Num a, Show a)+    => (Int64 -> IO a)+    -> (Int64 -> Int64 -> IO a)+    -> (Int64 -> Int64 -> Int64 -> IO a)+    -> (Int64 -> Int64 -> Int64 -> Int64 -> IO a)+    -> [Int64]+    -> IO (String, String)+  go get'1d get'2d get'3d get'4d ds =+    (,desc) <$> case ds of+      []  -> pure ""+      [x] -> brackets . intercalate "" <$> mapM (fmap valWithSpace . get'1d) (mkIx x)+      [x,y] -> go "" get'2d x y+      [x,y,z] -> mat3dGo x y z+      [x,y,z,q] -> mat4dGo x y z q+      _ -> pure "Can't print this yet"+   where+    go :: String -> (Int64 -> Int64 -> IO a) -> Int64 -> Int64 -> IO String+    go fill getter x y = do+      vs <- mapM (fmap valWithSpace . uncurry getter) (mkXY x y)+      pure (mat2dGo fill y "" vs)++    mat2dGo :: String -> Int64 -> String -> [String] -> String+    mat2dGo    _ _ acc []  = acc+    mat2dGo fill y acc rcs = mat2dGo fill y acc' rest+      where+        (row, rest) = splitAt (fromIntegral y) rcs+        fullrow = fill ++ brackets (intercalate "" row)+        acc' = if null acc then fullrow else acc ++ "\n" ++ fullrow++    mat3dGo :: Int64 -> Int64 -> Int64 -> IO String+    mat3dGo x y z = fmap (intercalate "") $ forM (mkIx x) $ \x' -> do+      mat <- go "  " (get'3d x') y z+      pure $ gt2IxHeader [x'] ++ mat++    mat4dGo :: Int64 -> Int64 -> Int64 -> Int64 -> IO String+    mat4dGo w q x y = fmap (intercalate "") $ forM (mkXY w q) $ \(w', q') -> do+      mat <- go "  " (get'4d w' q') x y+      pure $ gt2IxHeader [w', q'] ++ mat++    gt2IxHeader :: [Int64] -> String+    gt2IxHeader is = "\n(" ++ intercalate "," (fmap show is) ++",.,.):\n"++    mkIx :: Int64 -> [Int64]+    mkIx x = [0..x - 1]++    mkXY :: Int64 -> Int64 -> [(Int64, Int64)]+    mkXY x y = [ (r, c) | r <- mkIx x, c <- mkIx y ]++    brackets :: String -> String+    brackets s = "[" ++ s ++ "]"++    valWithSpace :: (Typeable a, Ord a, Num a, Show a) => a -> String+    valWithSpace v = spacing ++ value ++ " "+     where+       truncTo :: (RealFrac x, Fractional x) => Int -> x -> x+       truncTo n f = fromInteger (round $ f * (10^n)) / (10.0^^n)++       value :: String+       value = fromMaybe (show v) $+             (show . truncTo 6 <$> (cast v :: Maybe Double))+         <|> (show . truncTo 6 <$> (cast v :: Maybe Float))++       spacing = case compare (signum v) 0 of+          LT -> " "+          _  -> "  "++    descType, descShape, desc :: String+    descType = show (typeRep (Proxy :: Proxy a)) ++ " tensor with "+    descShape = "shape: " ++ intercalate "x" (fmap show ds)+    desc = brackets $ descType ++ descShape++-------------------------------------------------------------------------------+-- Helper functions which mimic code from 'Torch.Indef.Types'++mkDynamic :: Ptr Sig.CLongTensor -> IO IndexDynamic+mkDynamic t =+  withForeignPtr Sig.torchstate $ \s ->+    Sig.longDynamic Sig.torchstate+      <$> newForeignPtrEnv IxSig.p_free s t++
+ src/Torch/Indef/Internal.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE TypeFamilies #-}+module Torch.Indef.Internal+  ( throwFIXME+  , throwNE+  , throwGT4+  ) where++import Foreign+import GHC.ForeignPtr (ForeignPtr)+import Control.Exception.Safe+import qualified Foreign.Marshal.Array as FM++import Torch.Sig.Types++throwFIXME :: MonadThrow io => String -> String -> io x+throwFIXME fixme msg = throwString $ msg ++ " (FIXME: " ++ fixme ++ ")"++throwNE :: MonadThrow io => String -> io x+throwNE = throwFIXME "make this function only take a non-empty [Nat]"++throwGT4 :: MonadThrow io => String -> io x+throwGT4 fnname = throwFIXME+  ("review how TH supports `" ++ fnname ++ "` operations on > rank-4 tensors")+  (fnname ++ " with >4 rank")++
+ src/Torch/Indef/Mask.hs view
@@ -0,0 +1,92 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Mask+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Redundant version of @Torch.Indef.{Dynamic/Static}.Tensor@ for Byte tensors.+--+-- This comes with the same fixme as 'Torch.Indef.Index':+--+-- FIXME: in the future, there could be a smaller subset of Torch which could+-- be compiled to to keep the code dry. Alternatively, if backpack one day+-- supports recursive indefinites, we could use this feature to possibly remove+-- this package and 'Torch.Indef.Mask'.+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+module Torch.Indef.Mask+  ( newMask+  , newMaskDyn+  , newMaskDyn'+  , withMask+  , allOf+  ) where++import Foreign+import Foreign.Ptr+import Data.Proxy+import Data.List+import Control.Monad+import System.IO.Unsafe++import Numeric.Dimensions+import Torch.Sig.Types.Global+import Torch.Indef.Internal+import Control.Monad.Managed as X++import Torch.Sig.State as Sig+import qualified Torch.Types.TH as TH+import qualified Torch.Sig.Mask.Tensor as MaskSig+import qualified Torch.Sig.Mask.MathReduce as MaskSig+import qualified Torch.Sig.Mask.TensorFree as MaskSig++-- | build a new mask tensor with any known Dimension list.+newMask :: forall d . Dimensions d => MaskTensor d+newMask = byteAsStatic $ newMaskDyn (dims :: Dims d)++-- | build a new dynamic mask tensor with any known Nat list.+newMaskDyn :: Dims (d::[Nat]) -> MaskDynamic+newMaskDyn d = unsafeDupablePerformIO $ withForeignPtr Sig.torchstate $ \s -> do+  bytePtr <- case fromIntegral <$> listDims d of+    []           -> MaskSig.c_newWithSize1d s 1+    [x]          -> MaskSig.c_newWithSize1d s x+    [x, y]       -> MaskSig.c_newWithSize2d s x y+    [x, y, z]    -> MaskSig.c_newWithSize3d s x y z+    [x, y, z, q] -> MaskSig.c_newWithSize4d s x y z q+    _ -> error "FIXME: can't build masks of this size yet"++  byteDynamic Sig.torchstate+    <$> newForeignPtrEnv MaskSig.p_free s bytePtr++newMaskDyn' :: SomeDims -> MaskDynamic+newMaskDyn' (SomeDims d) = newMaskDyn d++-- | run a function with access to a dynamic index tensor's raw c-pointer.+withMask :: MaskDynamic -> (Ptr CMaskTensor -> IO x) -> IO x+withMask ix fn = withForeignPtr (snd $ byteDynamicState ix) fn++class IsMask t where+  -- | assert that all of the values of the Byte tensor are true.+  allOf :: t -> Bool+  -- anyOf :: t -> Bool++instance IsMask MaskDynamic where+  allOf t = unsafePerformIO $ flip X.with pure $ do+    s' <- managed $ withForeignPtr s+    t' <- managed $ withForeignPtr fp++    liftIO $ do+      ds <- MaskSig.c_nDimension s' t'+      prod <- foldM (\acc d -> (acc *) <$> MaskSig.c_size s' t' (fromIntegral d)) 1 [0..ds-1]+      tot  <- MaskSig.c_sumall s' t'+      pure $ tot == fromIntegral prod++    where+      (s, fp) = byteDynamicState t++instance IsMask (MaskTensor d) where+  allOf = allOf . byteAsDynamic
+ src/Torch/Indef/Static/NN.hs view
@@ -0,0 +1,136 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.NN+  ( module X+  , _batchNormalization_updateOutput+  , _batchNormalization_backward+  , _col2Im_updateOutput+  , _col2Im_updateGradInput+  , _im2Col_updateOutput+  , _im2Col_updateGradInput+  ) where+++import Torch.Indef.Types++import qualified Torch.Indef.Dynamic.NN as Dynamic+import Torch.Indef.Static.Tensor++import Torch.Indef.Static.NN.Activation as X+import Torch.Indef.Static.NN.Conv1d as X hiding (getTensors, weights, bias, featureSize, outputSize, kernelWidth)+import Torch.Indef.Static.NN.Conv2d as X hiding (getTensors, weights, bias, featureSize, outputSize, kernelWidth, kernelHeight)+-- import Torch.Indef.Static.NN.Conv3d as X+import Torch.Indef.Static.NN.Criterion as X+import Torch.Indef.Static.NN.Layers as X hiding (getTensors, weights, bias, outputSize, inputSize)+import Torch.Indef.Static.NN.Math as X+import Torch.Indef.Static.NN.Padding as X+import Torch.Indef.Static.NN.Pooling as X+import Torch.Indef.Static.NN.Sampling as X+import Torch.Indef.Static.NN.Backprop as X++-- | batchNormalization forward pass (updates the output tensor)+_batchNormalization_updateOutput+  :: Tensor d    -- ^ input+  -> Tensor d    -- ^ output+  -> Tensor d    -- ^ weight+  -> Tensor d    -- ^ bias+  -> Tensor d    -- ^ running mean+  -> Tensor d    -- ^ running var+  -> Tensor d    -- ^ save mean+  -> Tensor d    -- ^ save std+  -> Bool   -- ^ train+  -> Double -- ^ momentum+  -> Double -- ^ eps+  -> IO ()+_batchNormalization_updateOutput t0 t1 t2 t3 t4 t5 t6 t7 = Dynamic._batchNormalization_updateOutput+  (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)+  (asDynamic t5) (asDynamic t6) (asDynamic t7)++-- | batchNormalization backward+_batchNormalization_backward+  :: Tensor d      -- ^ input+  -> Tensor d      -- ^ grad output+  -> Tensor d      -- ^ grad input+  -> Tensor d      -- ^ grad weight+  -> Tensor d      -- ^ grad bias+  -> Tensor d      -- ^ weight+  -> Tensor d      -- ^ running mean+  -> Tensor d      -- ^ running var+  -> Tensor d      -- ^ save mean+  -> Tensor d      -- ^ save std+  -> Bool     -- ^ train+  -> Double   -- ^ momentum+  -> Double   -- ^ eps+  -> IO ()+_batchNormalization_backward t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 = Dynamic._batchNormalization_backward+  (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)+  (asDynamic t5) (asDynamic t6) (asDynamic t7) (asDynamic t8) (asDynamic t9)++-- | col2Im forward pass (updates the output tensor)+_col2Im_updateOutput+  :: Tensor d -- ^ input+  -> Tensor d -- ^ output+  -> Int -- ^ output Height+  -> Int -- ^ output Width+  -> Int -- ^ kH+  -> Int -- ^ kW+  -> Int -- ^ dH+  -> Int -- ^ dW+  -> Int -- ^ padH+  -> Int -- ^ padW+  -> Int -- ^ sH+  -> Int -- ^ sW+  -> IO ()+_col2Im_updateOutput t0 t1 = Dynamic._col2Im_updateOutput (asDynamic t0) (asDynamic t1)++-- | col2Im backward-update (updates the layer and bias tensors)+_col2Im_updateGradInput+  :: Tensor d -- ^ grad output+  -> Tensor d -- ^ grad input+  -> Int -- ^ kH+  -> Int -- ^ kW+  -> Int -- ^ dH+  -> Int -- ^ dW+  -> Int -- ^ padH+  -> Int -- ^ padW+  -> Int -- ^ sH+  -> Int -- ^ sW+  -> IO ()+_col2Im_updateGradInput g0 g1 = Dynamic._col2Im_updateGradInput (asDynamic g0) (asDynamic g1)++-- | im2Col forward pass (updates the output tensor)+_im2Col_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_im2Col_updateOutput g0 g1 = Dynamic._im2Col_updateOutput (asDynamic g0) (asDynamic g1)++-- | im2Col backward-update (updates the layer and bias tensors)+_im2Col_updateGradInput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_im2Col_updateGradInput g0 g1 = Dynamic._im2Col_updateGradInput (asDynamic g0) (asDynamic g1)++{-+class CPUNN t d where+  unfolded_acc  :: t d -> t d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+  unfolded_copy :: t d -> t d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+  volumetricConvolutionMM_updateOutput :: t d -> t d -> t d -> t d -> t d -> t d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+  volumetricConvolutionMM_updateGradInput :: t d -> t d -> t d -> t d -> t d -> t d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+  volumetricConvolutionMM_accGradParameters :: t d -> t d -> t d -> t d -> t d -> t d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+  temporalSubSampling_updateOutput :: t d -> t d -> t d -> t d -> Int -> Int -> Int -> IO ()+  temporalSubSampling_updateGradInput :: t d -> t d -> t d -> t d -> Int -> Int -> IO ()+  temporalSubSampling_accGradParameters :: t d -> t d -> t d -> t d -> Int -> Int -> Double -> IO ()+  spatialFullConvolutionMap_updateOutput :: t d -> t d -> t d -> t d -> t d -> Int -> Int -> Int -> Int -> IO ()+  spatialFullConvolutionMap_updateGradInput :: t d -> t d -> t d -> t d -> t d -> t d -> Int -> Int -> Int -> Int -> IO ()+  spatialFullConvolutionMap_accGradParameters :: t d -> t d -> t d -> t d -> t d -> Int -> Int -> Int -> Int -> Double -> IO ()+  hardShrink_updateOutput      :: t d -> t d -> Double -> IO ()+  hardShrink_updateGradInput   :: t d -> t d -> t d -> Double -> IO ()+  linear_updateOutput      :: t d -> t d -> t d -> t d -> t d -> IO ()+  linear_updateGradInput   :: t d -> t d -> t d -> t d -> IO ()+  linear_accGradParameters :: t d -> t d -> t d -> t d -> t d -> t d -> t d -> t d -> Double -> IO ()+  sparseLinear_legacyZeroGradParameters :: t d -> t d -> t d -> IO ()+  sparseLinear_legacyUpdateParameters   :: t d -> t d -> t d -> t d -> t d -> Double -> IO ()+-}
+ src/Torch/Indef/Static/NN/Activation.hs view
@@ -0,0 +1,155 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Activation+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Activation where++import Numeric.Backprop+import Numeric.Dimensions+import Control.Monad+import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Copy+import Torch.Indef.Static.NN.Backprop ()++import qualified Torch.Indef.Dynamic.NN.Activation as Dynamic++-- | pReLU updateOutput+_pReLU_updateOutput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_pReLU_updateOutput a0 a1 a2 = Dynamic._pReLU_updateOutput (asDynamic a0) (asDynamic a1) (asDynamic a2)++-- | pReLU updateGradInput+_pReLU_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_pReLU_updateGradInput a0 a1 a2 a3 =+  Dynamic._pReLU_updateGradInput (asDynamic a0) (asDynamic a1) (asDynamic a2) (asDynamic a3)++-- | pReLU accGradParameters+_pReLU_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> IO ()+_pReLU_accGradParameters a0 a1 a2 a3 a4 =+  Dynamic._pReLU_accGradParameters (asDynamic a0) (asDynamic a1) (asDynamic a2) (asDynamic a3) (asDynamic a4)++-- | rReLU updateOutput+_rReLU_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Double -> Double -> Bool -> Bool -> Generator -> IO ()+_rReLU_updateOutput t0 t1 t2 d0 d1 b0 b1 g =+  Dynamic._rReLU_updateOutput+    (asDynamic t0) (asDynamic t1) (asDynamic t2)+    (d0) (d1)+    (b0) (b1)+    g++-- | rReLU updateGradInput+_rReLU_updateGradInput   :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> Double -> Bool -> Bool -> IO ()+_rReLU_updateGradInput t0 t1 t2 t3 d0 d1 b0 b1 =+  Dynamic._rReLU_updateGradInput+    (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)+    (d0) (d1)+    (b0) (b1)++-- | eLU updateOutput+_eLU_updateOutput :: Tensor d -> Tensor d -> Double -> Double -> Bool -> IO ()+_eLU_updateOutput t0 t1 d0 d1 b0 =+  Dynamic._eLU_updateOutput+    (asDynamic t0) (asDynamic t1)+    (d0) (d1)+    (b0)++-- | eLU updateGradInput+_eLU_updateGradInput :: Tensor d -> Tensor d' -> Tensor d'' -> Double -> Double -> IO ()+_eLU_updateGradInput t0 t1 t2 d0 d1 =+  Dynamic._eLU_updateGradInput+    (asDynamic t0) (asDynamic t1) (asDynamic t2)+    (d0) (d1)++-- | leakyReLU updateOutput+_leakyReLU_updateOutput :: Tensor d -> Tensor d -> Double -> Bool -> IO ()+_leakyReLU_updateOutput t0 t1 d0 b0 =+  Dynamic._leakyReLU_updateOutput+    (asDynamic t0) (asDynamic t1)+    (d0) (b0)+++-- | leakyReLU updateGradInput+_leakyReLU_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Double -> Bool -> IO ()+_leakyReLU_updateGradInput t0 t1 t2 d0 b0 =+  Dynamic._leakyReLU_updateGradInput+    (asDynamic t0) (asDynamic t1) (asDynamic t2)+    (d0) (b0)++-- | ReLU activation function+relu :: Reifies s W => Dimensions d => BVar s (Tensor d) -> BVar s (Tensor d)+relu = threshold 0 0++-- | ReLU activation function+reluIO :: Dimensions d => Tensor d -> IO (Tensor d, Tensor d -> IO (Tensor d))+reluIO = thresholdIO 0 0++{-# NOINLINE threshold #-}+-- | run a threshold function againts two BVar variables+threshold+  :: forall s d . Reifies s W+  => Dimensions d+  => Double               -- ^ threshold+  -> Double               -- ^ replacement value+  -> BVar s (Tensor d)    -- ^ input+  -> BVar s (Tensor d)    -- ^ output+threshold thr value = liftOp1 . op1 $ \inp -> unsafePerformIO $ do+  (out, getgrad) <- thresholdIO thr value inp+  pure (out, unsafePerformIO . getgrad)++-- | run a threshold function in IO+thresholdIO+  :: forall d+  .  Dimensions d+  => Double      -- ^ threshold+  -> Double      -- ^ replacement value+  -> Tensor d    -- ^ input+  -> IO (Tensor d, Tensor d -> IO (Tensor d))    -- ^ output+thresholdIO thr value inp = do+  out <- _threshold_updateOutput thr value False inp+  pure (out, _threshold_updateGradInput thr value False inp)++  where+    _threshold_updateOutput+      :: Double              -- ^ threshold+      -> Double              -- ^ replacement value+      -> Bool                -- ^ inplace+      -> Tensor d            -- ^ input+      -> IO (Tensor d)       -- ^ output+    _threshold_updateOutput thr val inplace input = do+      let out = new+      -- FIXME: this looks like a bug in ATen. Need to check if this still exists after updating.+      let input' = if inplace then input else copy input++      Dynamic._threshold_updateOutput+        (asDynamic input') (asDynamic out)+        thr val+        inplace++      pure out++    _threshold_updateGradInput+      :: Dimensions d => Double        -- ^ threshold+      -> Double        -- ^ replacement value+      -> Bool          -- ^ inplace+      -> Tensor d      -- ^ input+      -> Tensor d      -- ^ gradient output+      -> IO (Tensor d) -- ^ gradient input+    _threshold_updateGradInput thr val inplace input gout = do+      let gin = new+      let input' = if inplace then input else copy input+      Dynamic._threshold_updateGradInput+        (asDynamic input') (asDynamic gout) (asDynamic gin)+        thr val+        inplace+      pure gin++
+ src/Torch/Indef/Static/NN/Backprop.hs view
@@ -0,0 +1,109 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Backprop+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Backprop helper instances for static tensors, as well as any helper+-- functions that might work well with backprop.+-------------------------------------------------------------------------------+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Torch.Indef.Static.NN.Backprop where++import Numeric.Backprop+import Numeric.Dimensions+import Data.Singletons.Prelude.List (SplitAt, Product)+import qualified Data.Singletons.Prelude.List as S -- hiding (All, Drop, Take, type (++))++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.Pointwise.Signed ()+import qualified Torch.Indef.Index as Ix+import qualified Torch.Indef.Static.Tensor as T++import System.IO.Unsafe+import qualified Torch.Indef.Dynamic.Tensor.Math as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math.Pointwise as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math.Pairwise as Dynamic+import Debug.Trace++-- instance Dimensions d => Backprop (Tensor d) where+instance Dimensions d => Backprop (Tensor d) where+  add a b = a + b+  zero = (const . constant) 0+  one = (const . constant) 1+  -- zero a = unsafePerformIO $ Dynamic.zero_ (asDynamic a) >> pure a+  -- {-# NOINLINE zero #-}+  -- one a = unsafePerformIO $ Dynamic.onesLike_ (asDynamic a) (asDynamic a) >> pure a+  -- {-# NOINLINE one #-}+  -- add a b = unsafePerformIO $ Dynamic.cadd_ (asDynamic b) 1 (asDynamic a) >> pure b+  -- {-# NOINLINE add #-}+++  -- :: Dimensions d+  -- => Dim n+  -- -> Tensor d+  -- -> Tensor (rs ++ '[1] ++ ls)++unsqueeze1dBP+  :: forall s d rs ls n+  .  Reifies s W+  => All Dimensions '[d, (rs ++ '[1] ++ ls)]+  => '( rs, ls) ~ (SplitAt n d)+  => '( rs, 1:+ls) ~ (SplitAt n (rs ++ '[1] ++ ls))+  => (rs ++ ls) ~ d+  => Dim n+  -> BVar s (Tensor d)+  -> BVar s (Tensor (rs ++ '[1] ++ ls))+unsqueeze1dBP d = liftOp1 . op1 $ \t ->+  (T.unsqueeze1d d t, go)+  where+    go :: Tensor (rs ++ '[1] ++ ls) -> Tensor d+    go o = T.squeeze1d d o++-- | Squeeze a dimension of size 1 out of the tensor+squeeze1dBP+  :: forall s d rs ls n+  .  Reifies s W+  => All Dimensions '[d, rs ++ ls]+  => All KnownDim '[n]+  => '(rs, 1:+ls) ~ (SplitAt n d)+  => d ~ (S.Take n (rs ++ ls) ++ '[1] ++ S.Drop n (rs ++ ls))+  => Dim n+  -> BVar s (Tensor d)+  -> BVar s (Tensor (rs ++ ls))+squeeze1dBP d = liftOp1 . op1 $ \t ->+  (T.squeeze1d d t, go)+  where+    go :: Tensor (rs ++ ls) -> Tensor d+    go o = T.unsqueeze1d (dim::Dim n) o++-- | A backprop-able 'flatten' operation with a batch dimension in IO+flattenBatchIO+  :: forall d bs . (All KnownDim '[Product d, bs], All Dimensions '[bs:+d, d])+  => Product (bs:+d) ~ Product '[bs, Product d]+  => Tensor (bs:+d)+  -> IO (Tensor '[bs, Product d], Tensor '[bs, Product d] -> IO (Tensor (bs:+d)))+flattenBatchIO i = do+  o <- pure $ resizeAs i+  pure (o, \gout -> pure $ resizeAs gout)++-- clip :: Reifies s W => (HsReal, HsReal) -> BVar s (Tensor '[1]) -> BVar s (Tensor '[1])+-- clip (mn,mx) = liftOp1 . op1 $ \i ->+--   let+--     x = case get1d i 0 of+--           x | x > mx ->   mx+--             | x < mn ->   mn+--             | otherwise -> x+--   in+--     (scalar x, id)
+ src/Torch/Indef/Static/NN/Conv1d.hs view
@@ -0,0 +1,314 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Conv1d+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Temporal (1D) Convolutions+-------------------------------------------------------------------------------+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE CPP #-}++#if MIN_VERSION_base(4,12,0)+{-# LANGUAGE NoStarIsType #-}+#endif++{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Conv1d+  ( Conv1d(..)+  , weights+  , bias+  , featureSize+  , kernelWidth+  , stepSize++  , conv1d+  , conv1d_forward+  , conv1d_backwardGradInput+  , conv1d_updGradParams++  , conv1dBatch+  , conv1d_forwardBatch+  , conv1d_backwardGradInputBatch+  , conv1d_updGradParamsBatch++  -- still need work:+  , _temporalRowConvolution_updateOutput+  , _temporalRowConvolution_updateGradInput+  , _temporalRowConvolution_updGradParameters+  ) where++import Numeric.Backprop+import Numeric.Dimensions+import Data.Kind (Type)+import Data.List (intercalate)+import Data.Singletons.Prelude (type (>), type (<))+import Data.Singletons.TypeLits+import System.IO.Unsafe+import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Copy+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.CompareT+import Torch.Indef.Static.NN.Backprop ()++import qualified Torch.Indef.Dynamic.NN as Dynamic+++-- | ADT representation of a convolutional 1d layer.+--+-- FIXME: the type is a bit of a hiccup: can we remove the kernel dimensions or+-- move pad/stride into the phantoms?+--+-- See 'Conv2d' for ideas.+newtype Conv1d f o kW dW+  = Conv1d { getTensors :: (Tensor '[o, f*kW], Tensor '[o]) }++instance (KnownDim f, KnownDim o, KnownDim kW, KnownDim dW)+  => Show (Conv1d f o kW dW) where+  show c = intercalate ","+    [ "Conv1d ("+    ++ "features: " ++ show (featureSize c)+    , " output: "   ++ show (outputSize c)+    , " kernel: "   ++ show (kernelWidth c)+    , " step: "     ++ show (stepSize c)+    ++ ")"+    ]++instance (KnownDim (f*kW), KnownDim o) => Backprop (Conv1d f o kW dW) where+  zero = const . Conv1d $ (constant 0, constant 0)+  one  = const . Conv1d $ (constant 1, constant 1)+  add c0 c1 = Conv1d (weights c0 + weights c1, bias c0 + bias c1)++-- | get the weights from a 'Conv1d' ADT+weights :: Conv1d f o kW dW -> Tensor '[o, f*kW]+weights (Conv1d (w, _)) = w++-- | get the bias from a 'Conv1d' ADT+bias :: Conv1d f o kW dW -> Tensor '[o]+bias (Conv1d (_, b)) = b++-- | get the featureSize from a 'Conv1d' ADT+featureSize :: forall f o kW dW . KnownDim f => Conv1d f o kW dW -> Int+featureSize _ = fromIntegral (dimVal (dim :: Dim f))++-- | get the outputSize from a 'Conv1d' ADT+outputSize :: forall f o kW dW . KnownDim o => Conv1d f o kW dW -> Int+outputSize _ = fromIntegral (dimVal (dim :: Dim o))++-- | kW: The kernel width of the convolution+kernelWidth :: forall f o kW dW . KnownDim kW => Conv1d f o kW dW -> Int+kernelWidth _ = fromIntegral (dimVal (dim :: Dim kW))++-- | dW: The step of the convolution. Default is 1 in C.+stepSize :: forall f o kW dW . KnownDim dW => Conv1d f o kW dW -> Int+stepSize _ = fromIntegral (dimVal (dim :: Dim dW))++-- ========================================================================= --++-- | Type constraints required for temporal convolution+type TemporalConvC s f kW dW o =+  ( All KnownDim '[s,f,kW,dW,o]+  , (s > kW) ~ 'True+  , (kW > 0) ~ 'True+  , (dW > 0) ~ 'True+  -- , o ~ ((Div (s - kW) dW) + 1)+  )++-- | Backprop convolution function+conv1d+  :: forall s seq f kW dW o+  .  Reifies s W+  => KnownDim (f*kW)+  => TemporalConvC seq f kW dW o+  => Double+  -> BVar s (Conv1d f o kW dW)+  -> BVar s (Tensor '[seq, f])+  -> BVar s (Tensor '[seq, o])+conv1d = _conv1d++-- | Backprop convolution function with batching+conv1dBatch+  :: forall s seq f kW dW o b+  .  Reifies s W+  => KnownDim b+  => KnownDim (f*kW)+  => TemporalConvC seq f kW dW o+  => Double+  -> BVar s (Conv1d f o kW dW)+  -> BVar s (Tensor '[b, seq, f])+  -> BVar s (Tensor '[b, seq, o])+conv1dBatch = _conv1d++-- | Backprop convolution function without specifying constraints or dimensions+_conv1d+  -- :: forall s seq f kW dW o d d'+  :: Reifies s W+  => KnownDim (f*kW)+  => All KnownDim '[f,kW,dW,o]+  => All Dimensions '[d,d']+  => Double+  -> BVar s (Conv1d f o kW dW)+  -> BVar s (Tensor d)+  -> BVar s (Tensor d')+_conv1d lr = liftOp2 . op2 $ \c inp ->+  (unsafePerformIO $ _conv1d_forward c inp, \gout ->+      ( unsafePerformIO $ _conv1d_updGradParams c inp gout lr+      , unsafePerformIO $ _conv1d_backwardGradInput c inp gout+      ) )++-------------------------------------------------------------------------------+-- * Functions for temporal convolution++-- | If the input sequence is a 2D tensor of dimension+-- (nInputFrame x inputFrameSize), the output sequence will be+-- (nOutputFrame x outputFrameSize) where+--+--    nOutputFrame = (nInputFrame - kW) / dW + 1+--+conv1d_forward+  :: TemporalConvC s f kW dW o+  => Conv1d f o kW dW+  -> Tensor '[s, f]+  -> IO (Tensor '[s, o])+conv1d_forward = _conv1d_forward++-- | backward pass, computing the gradient input+conv1d_backwardGradInput+  :: TemporalConvC seq f kW dW o+  => Conv1d f o kW dW             -- ^ conv1d state+  -> Tensor '[seq, f]             -- ^ input: s for 'sequence dimension', f for 'feature dimension'+  -> Tensor '[seq, o]             -- ^ grad output+  -> IO (Tensor '[seq, f])        -- ^ grad input+conv1d_backwardGradInput = _conv1d_backwardGradInput++-- | backward pass, computing the weight and bias parameters+--+-- WARNING: this is _pure_ which may be slow for large tensors.+-- Speeding this up will be in active development as the need arises+-- (see issue hasktorch/hasktorch#85)+conv1d_updGradParams+  :: TemporalConvC s f kW dW o+  => Conv1d f o kW dW       -- ^ input state of conv1d (which includes weights and bias)+  -> Tensor '[s, f]         -- ^ input tensor+  -> Tensor '[s, o]         -- ^ output gradient+  -> Double                 -- ^ scale+  -> IO (Conv1d f o kW dW)  -- ^ gradient of (weights, bias)+conv1d_updGradParams = _conv1d_updGradParams++-------------------------------------------------------------------------------+-- * Functions for temporal convolution with a batch dimension++-- | Applies a 1D convolution over an input sequence composed of nInputFrame+-- frames. The input tensor in forward(input) is expected to be a 2D tensor+-- (nInputFrame x inputFrameSize) or a 3D tensor+-- (nBatchFrame x nInputFrame x inputFrameSize).+conv1d_forwardBatch+  :: TemporalConvC s f kW dW o+  => Conv1d f o kW dW+  -> Tensor '[b,s,f]+  -> IO (Tensor '[b,s,o])+conv1d_forwardBatch = _conv1d_forward++-- | 'conv1d_backwardGradInput' with a batch dimension+conv1d_backwardGradInputBatch+  :: TemporalConvC s f kW dW o+  => KnownDim b+  => Conv1d f o kW dW             -- ^ conv1d state+  -> Tensor '[b, s, f]            -- ^ input: s for 'sequence dimension', f for 'feature dimension'+  -> Tensor '[b, s, o]            -- ^ grad output+  -> IO (Tensor '[b, s, f])       -- ^ output+conv1d_backwardGradInputBatch = _conv1d_backwardGradInput++-- | 'conv1d_updGradParams' with a batch dimension+conv1d_updGradParamsBatch+  :: TemporalConvC s f kW dW o+  => KnownDim b+  => Conv1d f o kW dW             -- ^ conv1d state+  -> Tensor '[b, s, f]            -- ^ input: s for 'sequence dimension', f for 'feature dimension'+  -> Tensor '[b, s, o]            -- ^ grad output+  -> Double                       -- ^ scale+  -> IO (Conv1d f o kW dW)        -- ^ output+conv1d_updGradParamsBatch = _conv1d_updGradParams++++-------------------------------------------------------------------------------+-- * helper functions++-- | forward pass without locking down the tensor dimensions+{-# NOINLINE _conv1d_forward #-}+_conv1d_forward :: All KnownDim '[f,kW,dW,o] => Conv1d f o kW dW -> Tensor d -> IO (Tensor d')+_conv1d_forward conv inp = do+  let out = empty+  Dynamic._temporalConvolution_updateOutput+    (asDynamic inp) (asDynamic out)+    (asDynamic (weights conv)) (asDynamic (bias conv))+    (kernelWidth conv) (stepSize conv)+    (featureSize conv) (outputSize conv)+  pure out++-- | backward pass, computing the gradient input, without locking down the tensor dimensions+{-# NOINLINE _conv1d_backwardGradInput #-}+_conv1d_backwardGradInput+  :: forall f o kW dW inputDim goutDim+  .  All KnownDim '[f,kW,dW,o]+  => All Dimensions '[inputDim,goutDim]+  => Conv1d f o kW dW+  -> Tensor inputDim+  -> Tensor goutDim+  -> IO (Tensor inputDim)+_conv1d_backwardGradInput conv input gradOut = do+  let gradIn = empty+  Dynamic._temporalConvolution_updateGradInput+    (asDynamic input)  (asDynamic gradOut)+    (asDynamic gradIn) (asDynamic (weights conv))+    (kernelWidth conv) (stepSize conv)+  pure gradIn++{-# NOINLINE _conv1d_updGradParams #-}+-- | backward pass, computing the weight updates, without locking down the tensor dimensions+_conv1d_updGradParams+  :: forall f o kW dW inputDim gOutDim+  .  All KnownDim '[f,kW,dW,o]+  => All Dimensions '[inputDim,gOutDim]+  => Conv1d f o kW dW       -- ^ input state of conv1d (which includes weights and bias)+  -> Tensor inputDim        -- ^ input tensor+  -> Tensor gOutDim         -- ^ output gradient+  -> Double                 -- ^ scale+  -> IO (Conv1d f o kW dW)  -- ^ gradient of (weights, bias)+_conv1d_updGradParams c@(Conv1d (w, b)) input gout scale = do+  -- FIXME: this is _not going to scale well_ and coming up with a mutable version of Conv layers will be nessecary+  let w' = copy w+  let b' = copy b+  Dynamic._temporalConvolution_accGradParameters+    (asDynamic input) (asDynamic gout) (asDynamic w') (asDynamic b')+    (kernelWidth c) (stepSize c) scale+  pure $ Conv1d (w', b')++-- ========================================================================= --++-- |  temporalRowConvolution forward pass (updates the output tensor)+_temporalRowConvolution_updateOutput :: Tensor d -> Tensor d' -> Tensor d'' -> Tensor d''' -> Tensor d -> Tensor d -> Int -> Int -> Int -> Bool -> IO ()+_temporalRowConvolution_updateOutput t0 t1 t2 t3 t4 t5 = Dynamic._temporalRowConvolution_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5)++-- |  temporalRowConvolution backward-update (updates the layer and bias tensors)+_temporalRowConvolution_updateGradInput :: Tensor d -> Tensor d' -> Tensor d'' -> Tensor d''' -> Tensor d -> Tensor d -> Int -> Int -> Int -> Bool -> IO ()+_temporalRowConvolution_updateGradInput t0 t1 t2 t3 t4 t5 = Dynamic._temporalRowConvolution_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5)++-- |  temporalRowConvolution backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_temporalRowConvolution_updGradParameters :: Tensor d -> Tensor d' -> Tensor d'' -> Tensor d''' -> Tensor d -> Tensor d -> Int -> Int -> Int -> Bool -> Double -> IO ()+_temporalRowConvolution_updGradParameters t0 t1 t2 t3 t4 t5 = Dynamic._temporalRowConvolution_accGradParameters (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5)++
+ src/Torch/Indef/Static/NN/Conv2d.hs view
@@ -0,0 +1,436 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Conv2d+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Spatial (2D) Convolutions.+--+-- Excluding an optional batch dimension, spatial layers expect a 3D Tensor as+-- input. The first dimension is the number of features (e.g. frameSize), the+-- last two dimensions are spatial (e.g. height x width). These are commonly+-- used for processing images.+--+-- Complete types and documentation at https://github.com/torch/nn/blob/master/doc/convolution.md#spatial-modules+-------------------------------------------------------------------------------+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE CPP #-}++#if MIN_VERSION_base(4,12,0)+{-# LANGUAGE NoStarIsType #-}+#endif++{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Conv2d where++import Control.Arrow+import Data.Kind (Type)+import Data.List (intercalate)+import Data.Maybe+import Numeric.Backprop+import Numeric.Dimensions+import System.IO.Unsafe+import Data.Singletons.Prelude (type (>), type (<), Fst, Snd)+import GHC.TypeLits (Div) -- (type Div)++import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Copy+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.Pairwise (Pairwise(..))+import Torch.Indef.Static.NN.Backprop ()+import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.NN as Dynamic++import qualified Torch.Indef.Dynamic.Tensor.Math as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math.Pointwise as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math.Pairwise as Dynamic++-- ========================================================================= --++-- | ADT representation of a convolutional 2d layer.+--+-- FIXME: the type is a bit of a hiccup: can we remove the kernel dimensions or+-- move pad/stride into the phantoms?+--+-- possibly something like @Conv2d i o (kH, kW) (dH, dW) (pH, pW)@ or+-- @Conv2d i o (kH, kW) (Maybe (dH, dW)) (Maybe (pH, pW))@+newtype Conv2d i o kers+  = Conv2d { getTensors :: (Tensor '[o, i, Fst kers, Snd kers], Tensor '[o]) }++instance (KnownDim i, KnownDim o, KnownDim kH, KnownDim kW)+  => Show (Conv2d i o '(kH, kW)) where+  show c = intercalate ","+    [ "Conv2d ("+    ++ "features: " ++ show (featureSize c)+    , " output: "   ++ show (outputSize c)+    , " kernelWidth: "   ++ show (kernelWidth c)+    , " kernelHeight: "     ++ show (kernelHeight c)+    ++ ")"+    ]++-- instance (KnownDim i, KnownDim o, KnownDim kH, KnownDim kW)+--   => Backprop (Conv2d i o '(kH,kW)) where+--++instance (KnownDim i, KnownDim o, KnownDim kH, KnownDim kW)+  => Backprop (Conv2d i o '(kH,kW)) where+  one  = const $ Conv2d (constant 1, constant 1)+  zero = const $ Conv2d (constant 0, constant 0)++--   one  (Conv2d (a, b)) = unsafePerformIO $ do+--     Dynamic.onesLike_ (asDynamic a) (asDynamic a)+--     Dynamic.onesLike_ (asDynamic b) (asDynamic b)+--     pure (Conv2d (a, b))+--   {-# NOINLINE one #-}+--+--   zero (Conv2d (a, b)) = unsafePerformIO $ do+--     Dynamic.zerosLike_ (asDynamic a) (asDynamic a)+--     Dynamic.zerosLike_ (asDynamic b) (asDynamic b)+--     pure (Conv2d (a, b))+--   {-# NOINLINE zero #-}+--+  add (Conv2d (a0, b0)) (Conv2d (a1, b1)) = unsafePerformIO $ do+    Dynamic.cadd_ (asDynamic a1) 1 (asDynamic a0)+    Dynamic.cadd_ (asDynamic b1) 1 (asDynamic b0)+    pure (Conv2d (a1, b1))+  {-# NOINLINE add #-}+  -- add c0 c1 = Conv2d (weights c0 + weights c1, bias c0 + bias c1)++instance (All KnownDim '[i, o, Fst kers, Snd kers]) => Num (Conv2d i o kers) where+  (+) (Conv2d (a0, b0)) (Conv2d (a1, b1)) = Conv2d (a0+a1, b0+b1)+  (-) (Conv2d (a0, b0)) (Conv2d (a1, b1)) = Conv2d (a0-a1, b0-b1)+  (*) (Conv2d (a0, b0)) (Conv2d (a1, b1)) = Conv2d (a0*a1, b0*b1)+  abs (Conv2d (a0, b0)) = Conv2d (abs a0, abs b0)+  fromInteger i = Conv2d (fromInteger i, fromInteger i)++instance (All KnownDim '[i, o, Fst kers, Snd kers]) => Pairwise (Conv2d i o kers) HsReal where+  (Conv2d tens) ^+ v = Conv2d (tens ^+ v)+  (Conv2d tens) ^- v = Conv2d (tens ^- v)+  (Conv2d tens) ^* v = Conv2d (tens ^* v)+  (Conv2d tens) ^/ v = Conv2d (tens ^/ v)+++-- | update a Conv2d layer+update+  :: (KnownDim i, KnownDim o, KnownDim kH, KnownDim kW)+  => Conv2d i o '(kH, kW)  -- ^ network to update+  -> HsReal                -- ^ learning rate+  -> Conv2d i o '(kH, kW)  -- ^ gradient+  -> Conv2d i o '(kH, kW)  -- ^ updated network+update (Conv2d (w, b)) lr (Conv2d (gw, gb)) = Conv2d (w + gw ^* lr, b + gb ^* lr)++-- | update a Conv2d layer inplace+update_+  :: (KnownDim i, KnownDim o, KnownDim kH, KnownDim kW)+  => Conv2d i o '(kH, kW)  -- ^ network to update+  -> HsReal                -- ^ learning rate+  -> Conv2d i o '(kH, kW)  -- ^ gradient+  -> IO ()  -- ^ update network+update_ (Conv2d (w, b)) lr (Conv2d (gw, gb)) = do+  Dynamic.cadd_ (asDynamic w) lr (asDynamic gw)+  Dynamic.cadd_ (asDynamic b) lr (asDynamic gb)+++++-- | get the weights from a 'Conv2d' ADT+weights :: Conv2d i o '(kH,kW) -> Tensor '[o, i, kH, kW]+weights (Conv2d (w, _)) = w++-- | get the bias from a 'Conv2d' ADT+bias :: Conv2d i o '(kH,kW) -> Tensor '[o]+bias (Conv2d (_, b)) = b++-- | get the featureSize from a 'Conv2d' ADT+featureSize :: forall i o kH kW . KnownDim i => Conv2d i o '(kH,kW) -> Int+featureSize _ = fromIntegral (dimVal (dim :: Dim i))++-- | get the outputSize from a 'Conv2d' ADT+outputSize :: forall f o kH kW . KnownDim o => Conv2d f o '(kH,kW) -> Int+outputSize _ = fromIntegral (dimVal (dim :: Dim o))++-- | get the kernelWidth from a 'Conv2d' ADT+kernelWidth :: forall i f o kH kW . (Integral i, KnownDim kW) => Conv2d f o '(kH,kW) -> i+kernelWidth _ = fromIntegral (dimVal (dim :: Dim kW))++-- | get the kernelHeight from a 'Conv2d' ADT+kernelHeight :: forall i f o kH kW . (Integral i, KnownDim kH) => Conv2d f o '(kH,kW) -> i+kernelHeight _ = fromIntegral (dimVal (dim :: Dim kH))++-- | get the kernel tuple as (width, height) from a 'Conv2d' ADT+--+-- FIXME: Isn't this supposed to be "height" /then/ "width"???+kernel2d :: (Integral i, KnownDim kH, KnownDim kW) => Conv2d f o '(kH,kW) -> (i, i)+kernel2d = kernelWidth &&& kernelHeight++-------------------------------------------------------------------------------++-- | Typeclass to generically pull out Width and Height information from a parameter+--+-- FIXME: this can be replaced with simple functions.+class Param2d (p :: (Nat, Nat) -> Type) where++  -- | get the width parameter+  paramW :: forall w h i . (KnownDim w, Integral i) => p '(h, w) -> i+  paramW _ = fromIntegral $ dimVal (dim :: Dim w)++  -- | get the height parameter+  paramH :: forall w h i . (KnownDim h, Integral i) => p '(h, w) -> i+  paramH _ = fromIntegral $ dimVal (dim :: Dim h)++  -- | get both parameters as a (width, height) tuple+  -- FIXME: Isn't this supposed to be "height" /then/ "width"???+  param2d :: (KnownDim h, KnownDim w, Integral i) => p '(h, w) -> (i, i)+  param2d = paramW &&& paramH++-- | Representation of how much to step in the height and width dimensions+data Step2d (hw :: (Nat, Nat)) = Step2d++-- | Representation of how much to pad in the height and width dimensions+data Padding2d (hw :: (Nat, Nat)) = Padding2d++-- | Representation of how big a kernel will be in the height and width dimensions+data Kernel2d (hw :: (Nat, Nat)) = Kernel2d++-- | Representation of how much to dilate in the height and width dimensions+data Dilation2d (hw :: (Nat, Nat)) = Dilation2d++instance Param2d Step2d+instance Param2d Padding2d+instance Param2d Kernel2d+instance Param2d Dilation2d+instance Param2d (Conv2d f o) where++-- ========================================================================= --++-- | Constraint to check both sides (height and width) of a function and+-- assert that all nessecary dimension values are 'KnownDim's.+type SpatialConvolutionC f h w kH kW dH dW pH pW oH oW =+  ( All KnownDim '[f * kH * kW, oH * oW, f]++  , SideCheck h kH dH pH oH+  , SideCheck w kW dW pW oW+  )++-- | Constraint to check valid dimensions on one side.+type SideCheck h k d p o =+  -- all of these are nats and 'dimensions' knows about them+  ( All KnownDim '[h,k,d,p,o]+  -- kernel and step size must be > 0+  , (k > 0) ~ 'True+  , (d > 0) ~ 'True+  -- kernel size can't be greater than actual input size+  , ((h + (2*p)) < k) ~ 'False++  -- output size must be greater than 0+  , (o > 0) ~ 'True++  -- output forumlation:+  , o ~ ((Div ((h + (2*p)) - k) d) + 1)+  )+++-- | Backprop convolution function with batching+conv2dBatchIO+  :: forall f h w kH kW dH dW pH pW oW oH s o b+  .  SpatialConvolutionC f h w kH kW dH dW pH pW oH oW+  => All KnownDim '[f,o,b,kW*kH*f,oH*oW]+  => Step2d '(dH,dW)                -- ^ step of the convolution in width and height dimensions.+  -> Padding2d '(pH,pW)             -- ^ zero padding to the input plane for width and height.+  -> Double                      -- ^ learning rate+  -> (Conv2d f o '(kH,kW))   -- ^ conv2d state+  -> (Tensor '[b,f,h,w])    -- ^ input: f stands for "features" or "input plane")+  -> IO (Tensor '[b, o,oH,oW], (Tensor '[b,o,oH,oW] -> IO (Conv2d f o '(kH,kW), Tensor '[b,f,h,w])))+conv2dBatchIO = genericConv2dWithIO+  (Just ( constant 0 :: Tensor '[b,f,h,w]))+  (Just ( constant 0 :: Tensor '[b,kW*kH*f,oH*oW]))+  (Just ( constant 0 :: Tensor '[b,kW*kH*f,oH*oW]))+  (Just $ constant 0)+  (Just $ constant 0)+  (Just $ Conv2d (constant 0, constant 0))++-- | Backprop convolution function with batching+{-# NOINLINE conv2dBatch #-}+conv2dBatch+  :: Reifies s W+  => SpatialConvolutionC f h w kH kW dH dW pH pW oH oW+  => All KnownDim '[f,o,kH,kW,dH,dW,pH,pW,b]+  => All KnownDim '[kW*kH*f,oH*oW]+  => Step2d '(dH,dW)                -- ^ step of the convolution in width and height dimensions.+                                 --   C-default is 1 for both.+                                 --+  -> Padding2d '(pH,pW)             -- ^ zero padding to the input plane for width and height.+                                 --   (kW-1)/2 is often used. C-default is 0 for both.+                                 --+  -> Double                      -- ^ learning rate+  -> BVar s (Conv2d f o '(kH,kW))   -- ^ conv2d state+  -> BVar s (Tensor '[b,f,h,w])    -- ^ input: f stands for "features" or "input plane")+  -> BVar s (Tensor '[b, o,oH,oW])+conv2dBatch step pad lr = liftOp2 . op2 $ \conv inp -> unsafePerformIO $ do+  (o, getgrad) <- conv2dBatchIO step pad lr conv inp+  pure (o, unsafePerformIO . getgrad)+++-- | Backprop convolution function with batching+conv2dIO+  :: forall f h w kH kW dH dW pH pW oW oH s o+  .  SpatialConvolutionC f h w kH kW dH dW pH pW oH oW+  => All KnownDim '[f,o,kW*kH*f,oH*oW]+  => Step2d '(dH,dW)                -- ^ step of the convolution in width and height dimensions.+  -> Padding2d '(pH,pW)             -- ^ zero padding to the input plane for width and height.+  -> Double                      -- ^ learning rate+  -> (Conv2d f o '(kH,kW))   -- ^ conv2d state+  -> (Tensor '[f,h,w])    -- ^ input: f stands for "features" or "input plane")+  -> IO (Tensor '[o,oH,oW], (Tensor '[o,oH,oW] -> IO (Conv2d f o '(kH,kW), Tensor '[f,h,w])))+conv2dIO = genericConv2dWithIO+  (Just ( constant 0 :: Tensor '[f,h,w]))+  (Just ( constant 0 :: Tensor '[kW*kH*f,oH*oW]))+  (Just ( constant 0 :: Tensor '[kW*kH*f,oH*oW]))+  (Just $ constant 0)+  (Just $ constant 0)+  (Just $ Conv2d (constant 0, constant 0))+++-- | Backprop convolution function+{-# NOINLINE conv2d #-}+conv2d+  :: Reifies s W+  => SpatialConvolutionC f h w kH kW dH dW pH pW oH oW+  => All KnownDim '[f,o,kH,kW,dH,dW,pH,pW]+  => All KnownDim '[kW*kH*f,oH*oW]+  => Step2d '(dH,dW)                -- ^ step of the convolution in width and height dimensions.+                                 --   C-default is 1 for both.+                                 --+  -> Padding2d '(pH,pW)             -- ^ zero padding to the input plane for width and height.+                                 --   (kW-1)/2 is often used. C-default is 0 for both.+                                 --+  -> Double                      -- ^ learning rate+  -> BVar s (Conv2d f o '(kH,kW))   -- ^ conv2d state+  -> BVar s (Tensor '[f,h,w])    -- ^ input: f stands for "features" or "input plane")+  -> BVar s (Tensor '[o,oH,oW])+conv2d step pad lr = liftOp2 . op2 $ \conv inp -> unsafePerformIO $ do+  (o, getgrad) <- conv2dIO step pad lr conv inp+  pure (o, unsafePerformIO . getgrad)++genericConv2dWithIO+  :: forall din dout fgin f o kH kW dH dW pH pW inBuff+  .  All Dimensions '[din,dout,fgin, inBuff]+  => All KnownDim '[f,o,kH,kW,dH,dW,pH,pW]++  -- buffers+  => Maybe (Tensor fgin)            -- ^ grad input buffer+  -> Maybe (Tensor inBuff)            -- ^ columns buffer+  -> Maybe (Tensor inBuff)            -- ^ ones buffer++  -- cacheables+  -> Maybe (Tensor dout)            -- output+  -> Maybe (Tensor din)             -- gradient input+  -> Maybe (Conv2d f o '(kH, kW))   -- gradient params++  -> Step2d '(dH,dW)                -- ^ step of the convolution in width and height dimensions.+  -> Padding2d '(pH,pW)             -- ^ zero padding to the input plane for width and height.+  -> Double                      -- ^ learning rate++  -> (Conv2d f o '(kH,kW))   -- ^ conv2d state+  -> (Tensor din)    -- ^ input: f stands for "features" or "input plane")+  -> IO (Tensor dout, (Tensor dout -> IO (Conv2d f o '(kH,kW), Tensor din)))+genericConv2dWithIO+  mginbuffer mfinput mfgradInput mout mgin mgparams+  step pad lr conv inp = do+  let ginbuffer = fromMaybe new mginbuffer+  let finput = fromMaybe new mfinput+  let fgradInput = fromMaybe new mfgradInput+  let out = fromMaybe new mout++  zero_ out+  updateOutput_ finput fgradInput step pad conv inp out++  pure (copy out,+    \gout -> do+      let gin = fromMaybe new mgin+      let gparams = fromMaybe (Conv2d (new, new)) mgparams+      zero_ gin+      zero_ (weights gparams)+      zero_ (bias gparams)++      updateGradInput_ inp gout gin conv finput fgradInput step pad++      accGradParameters_ inp gout gparams finput fgradInput step pad+      print (weights gparams)++      pure (gparams, gin))+ where+  updateOutput_ finput fgradInput step pad conv inp out =+    Dynamic._spatialConvolutionMM_updateOutput+      (asDynamic inp)                      -- ^ input+      (asDynamic out)                      -- ^ output+      (asDynamic (weights conv))    -- ^ 3D weight tensor (connTable:size(1) x kH x kW)+      (asDynamic (bias conv))       -- ^ 1D bias tensor (nOutputPlane)++      (asDynamic finput)                  -- ^ BUFFER: temporary columns -- also called "finput"+      (asDynamic fgradInput)              -- ^ BUFFER: buffer of ones for bias accumulation  -- also called "fgradInput"++      (kernel2d conv)               -- ^ (kW, kH) kernel height and width+      (param2d step)                       -- ^ (dW, dH) step of the convolution in width and height dimensions. C-default is 1 for both.+      (param2d pad)                        -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used. C-default is 0 for both.++  updateGradInput_ inp gout gin conv colsbuffer onesbuffer step pad = do+    Dynamic._spatialConvolutionMM_updateGradInput+      (asDynamic inp)                      -- ^ input+      (asDynamic gout)                     -- ^ gradOutput+      (asDynamic gin)                      -- ^ gradInput+      (asDynamic (weights conv))    -- ^ weight+      (asDynamic colsbuffer)               -- ^ columns+      (asDynamic onesbuffer)               -- ^ ones+      (kernel2d conv)               -- ^ (kW, kH) kernel height and width+      (param2d step)                       -- ^ (dW, dH) step of the convolution in width and height dimensions+      (param2d pad)                        -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used.+++  accGradParameters_ inp gout gconv columnsbuff onesbuff step pad = do+    Dynamic._spatialConvolutionMM_accGradParameters+      (asDynamic inp)    -- ^ input+      (asDynamic gout)    -- ^ gradOutput+      (asDynamic (weights gconv))    -- ^ gradWeight+      (asDynamic (bias gconv))    -- ^ gradBias+      (asDynamic columnsbuff)    -- ^ finput/columns <<- required. This can be NULL in C if gradWeight is NULL.+      (asDynamic onesbuff)   -- ^ ones+      (kernel2d conv) -- ^ (kW, kH) kernel height and width+      (param2d step)         -- ^ (dW, dH) step of the convolution in width and height dimensions+      (param2d pad)          -- ^ (pW, pH) zero padding to the input plane for width and height. (kW-1)/2 is often used.+      lr++-- ========================================================================= --++-- Applies a 2D locally-connected layer over an input image composed of several input planes. The input tensor in forward(input) is expected to be a 3D or 4D tensor. A locally-connected layer is similar to a convolution layer but without weight-sharing.+-- _spatialConvolutionLocal_updateOutput      :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Integer -> Integer -> Integer -> Integer -> IO ()+-- _spatialConvolutionLocal_updateGradInput   :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Integer -> Integer -> Integer -> Integer -> IO ()+-- _spatialConvolutionLocal_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Integer -> Integer -> Integer -> Integer -> Double -> IO ()++-- Applies a 2D full convolution over an input image composed of several input planes. The input tensor in forward(input) is expected to be a 3D or 4D tensor. Note that instead of setting adjW and adjH, SpatialFullConvolution also accepts a table input with two tensors: {convInput, sizeTensor} where convInput is the standard input on which the full convolution is applied, and the size of sizeTensor is used to set the size of the output. Using the two-input version of forward will ignore the adjW and adjH values used to construct the module. The layer can be used without a bias by module:noBias().+-- spatialFullConvolution_updateOutput      :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- spatialFullConvolution_updateGradInput   :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- spatialFullConvolution_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()++-- Also sometimes referred to as atrous convolution. Applies a 2D dilated convolution over an input image composed of several input planes. The input tensor in forward(input) is expected to be a 3D or 4D tensor.+-- spatialDilatedConvolution_updateOutput      :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- spatialDilatedConvolution_updateGradInput   :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- spatialDilatedConvolution_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()+--+-- spatialFullDilatedConvolution_updateOutput      :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- spatialFullDilatedConvolution_updateGradInput   :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+-- spatialFullDilatedConvolution_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> IO ()++
+ src/Torch/Indef/Static/NN/Criterion.hs view
@@ -0,0 +1,473 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Criterion+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE CPP #-}++#if MIN_VERSION_base(4,12,0)+{-# LANGUAGE NoStarIsType #-}+#endif++{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Criterion where++import Control.Arrow ((&&&))+import GHC.TypeLits+import Numeric.Dimensions+import Numeric.Backprop+import System.IO.Unsafe+import Control.Concurrent+import Debug.Trace+import Data.Singletons.Prelude hiding (All, type (*), type (-), type (+))+import Data.Maybe+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Types+import Torch.Indef.Static.NN.Backprop ()+import qualified Torch.Indef.Dynamic.NN.Criterion as Dynamic+import qualified Torch.Sig.Types.Global as Ix++import Torch.Indef.Static.Tensor.Random.THC+++-- | absCriterion forward pass (updates the output tensor)+_absCriterion_updateOutput+  :: Tensor d     -- ^ input+  -> Tensor d'    -- ^ target+  -> Tensor d''   -- ^ output+  -> Bool    -- ^ size average+  -> Bool    -- ^ reduce+  -> IO ()+_absCriterion_updateOutput i t o = Dynamic._absCriterion_updateOutput (asDynamic i) (asDynamic t) (asDynamic o)++-- | absCriterion backward-update (updates the layer and bias tensors)+_absCriterion_updateGradInput+  :: Tensor d     -- ^ input+  -> Tensor d'    -- ^ target+  -> Tensor d''   -- ^ gradOutput+  -> Tensor d''   -- ^ gradInput+  -> Bool    -- ^ size average+  -> Bool    -- ^ reduce+  -> IO ()+_absCriterion_updateGradInput i t go gi = Dynamic._absCriterion_updateGradInput (asDynamic i) (asDynamic t) (asDynamic go) (asDynamic gi)++-- | Binary cross-entropy for Sigmoid (two-class version of ClassNLLCriterion)+--+-- Creates a criterion that measures the Binary Cross Entropy between the target and+-- the output:+-- @+--   loss(o, t) = - 1/n sum_i (t[i] * log(o[i]) + (1 - t[i]) * log(1 - o[i]))+-- @+-- or in the case of the weights argument being specified:+-- @+--   loss(o, t) = - 1/n sum_i weights[i] * (t[i] * log(o[i]) + (1 - t[i]) * log(1 - o[i]))+-- @+-- This is used for measuring the error of a reconstruction in for example an+-- auto-encoder. Note that the outputs o[i] should be numbers between 0 and 1,+-- for instance, the output of an nn.Sigmoid layer and should be interpreted as+-- the probability of predicting t[i] = 1. Note t[i] can be either 0 or 1.+--+-- By default, the losses are averaged for each minibatch over observations as+-- well as over dimensions. However, if the field sizeAverage is set to false,+-- the losses are instead summed.+bCECriterion'+  :: forall s n+  . (Reifies s W, KnownNat n, KnownDim n)+  => Bool                          -- ^ sizeAverage (TODO: swap this out with 'Reduction')+  -> Bool                          -- ^ reduce (TODO: swap this out with 'Reduction')+  -> Maybe (Tensor '[n])           -- ^ weights+  -> Tensor '[n]                   -- ^ target+  -> BVar s (Tensor '[n])          -- ^ input+  -> BVar s (Tensor '[1])          -- ^ output+bCECriterion' savg r mw tar = liftOp1 . op1 $ (updateOutput &&& updateGradInput)+  where+    {-# NOINLINE updateOutput #-}+    updateOutput+      :: Tensor '[n]          -- input+      -> Tensor '[1]          -- output+    updateOutput i = unsafePerformIO $ let o = new in+      Dynamic._bCECriterion_updateOutput+        (asDynamic i) (asDynamic tar) (asDynamic o) savg (asDynamic <$> mw) r+      >> pure o++    {-# NOINLINE updateGradInput #-}+    updateGradInput+      :: Tensor '[n]          -- input+      -> Tensor '[1]          -- grad output+      -> Tensor '[n]          -- grad input+    updateGradInput i go = unsafePerformIO $ do+      let gi = new+      Dynamic._bCECriterion_updateGradInput+        (asDynamic i) (asDynamic tar) (asDynamic go) (asDynamic gi) savg (asDynamic <$> mw) r+      pure gi++bCECriterion+  :: (Reifies s W, KnownNat n, KnownDim n)+  => Tensor '[n]                   -- ^ target+  -> BVar s (Tensor '[n])          -- ^ input+  -> BVar s (Tensor '[1])          -- ^ output+bCECriterion = bCECriterion' True True Nothing++-- | marginCriterion forward pass (updates the output tensor)+_marginCriterion_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Bool -> Double -> IO ()+_marginCriterion_updateOutput t0 t1 t2 = Dynamic._marginCriterion_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- | marginCriterion backward-update (updates the layer and bias tensors)+_marginCriterion_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Bool -> Double -> IO ()+_marginCriterion_updateGradInput t0 t1 t2 = Dynamic._marginCriterion_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | softMarginCriterion forward pass (updates the output tensor)+_softMarginCriterion_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Bool -> Bool -> IO ()+_softMarginCriterion_updateOutput t0 t1 t2 = Dynamic._softMarginCriterion_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- | softMarginCriterion backward-update (updates the layer and bias tensors)+_softMarginCriterion_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Bool -> Bool -> IO ()+_softMarginCriterion_updateGradInput t0 t1 t2 t3 = Dynamic._softMarginCriterion_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- | MSECriterion+--+-- Creates a criterion that measures the mean squared error between n elements+-- in the input x and output y:+--+-- @+--   loss(x, y) = 1/n \sum |x_i - y_i|^2 .+-- @+--+-- If x and y are d-dimensional Tensors with a total of n elements, the sum+-- operation still operates over all the elements, and divides by n. The two+-- Tensors must have the same number of elements (but their sizes might be+-- different).+--+-- The division by n can be avoided if one sets the internal variable sizeAverage+-- to false:+--+-- criterion = nn.MSECriterion()+-- criterion.sizeAverage = false+--+-- By default, the losses are averaged over observations for each minibatch.+-- However, if the field sizeAverage is set to false, the losses are instead+-- summed.+mSECriterionWith+  :: forall s bs d d' reduce out size_average+  .  Reifies s W+  => All Dimensions '[d', d, out]+  => KnownDim bs+  => d ~ (bs :+ d') -- must have minibatch+  => out ~ (If reduce '[1] d)+  => SBool size_average  -- ^ size_average:+                         --     By default, the losses are averaged over each loss element in the batch.+                         --     Note that for some losses, there multiple elements per sample.+                         --     If the field size_average is set to False, the losses are instead+                         --     summed for each minibatch. Ignored when reduce is False. Default: True+  -> SBool reduce        -- ^ reduce:+                         --     By default, the losses are averaged or summed over observations for each+                         --     minibatch depending on size_average. When reduce is False, returns a loss+                         --     per batch element instead and ignores size_average. Default: True+  -> Tensor d            -- ^ target+  -> BVar s (Tensor d)   -- ^ input+  -> BVar s (Tensor out) -- ^ loss value and arrow from output gradient to input gradient+mSECriterionWith sizeAvg reduce target = liftOp1 . op1 $ \i -> unsafePerformIO $ do+  (o, getgrad) <- mSECriterionWithIO sizeAvg reduce target i+  pure (o, unsafePerformIO . getgrad)+{-# NOINLINE mSECriterionWith #-}+++mSECriterion :: forall s bs d d'+  .  All Dimensions '[d', d]+  => Reifies s W+  => KnownDim bs+  => d ~ (bs :+ d')      -- must have minibatch+  => Tensor d            -- ^ target+  -> BVar s (Tensor d)   -- ^ input+  -> BVar s (Tensor '[1]) -- ^ loss value and arrow from output gradient to input gradient+mSECriterion = mSECriterionWith (sing :: SBool 'True) (sing :: SBool 'True)++++{-# NOINLINE mSECriterionWithIO #-}+mSECriterionWithIO+  :: forall bs d d' reduce out size_average+  .  All Dimensions '[d', d, out]+  => KnownDim bs+  => d ~ (bs :+ d') -- must have minibatch+  => out ~ (If reduce '[1] d)+  => SBool size_average  -- ^ size_average:+                         --     By default, the losses are averaged over each loss element in the batch.+                         --     Note that for some losses, there multiple elements per sample.+                         --     If the field size_average is set to False, the losses are instead+                         --     summed for each minibatch. Ignored when reduce is False. Default: True+  -> SBool reduce        -- ^ reduce:+                         --     By default, the losses are averaged or summed over observations for each+                         --     minibatch depending on size_average. When reduce is False, returns a loss+                         --     per batch element instead and ignores size_average. Default: True+  -> Tensor d            -- ^ target+  -> Tensor d            -- ^ input+  -> IO (Tensor out, Tensor out -> IO (Tensor d)) -- ^ loss value and arrow from output gradient to input gradient+mSECriterionWithIO sizeAvg' reduce' target i = do+  let o = new++  -- mSECriterion forward pass (updates the output tensor)+  Dynamic._mSECriterion_updateOutput (asDynamic i) (asDynamic target) (asDynamic o) sizeAvg reduce++  pure (o, \gout -> do+    -- mSECriterion backward-update (updates the layer and bias tensors)+    let gin = new+    Dynamic._mSECriterion_updateGradInput (asDynamic i) (asDynamic target) (asDynamic gout) (asDynamic gin) sizeAvg reduce+    pure gin)+  where+    sizeAvg = fromSing sizeAvg'+    reduce = fromSing reduce'++mSECriterionIO :: forall bs d d'+  .  All Dimensions '[d', d]+  => KnownDim bs+  => d ~ (bs :+ d')      -- must have minibatch+  => Tensor d            -- ^ target+  -> Tensor d            -- ^ input+  -> IO (Tensor '[1], Tensor '[1] -> IO (Tensor d)) -- ^ loss value and arrow from output gradient to input gradient+mSECriterionIO = mSECriterionWithIO (sing :: SBool 'True) (sing :: SBool 'True)+++-- | The <https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence Kullback-Leibler divergence> Loss+--+-- KL divergence is a useful distance measure for continuous distributions and+-- is often useful when performing direct regression over the space of+-- (discretely sampled) continuous output distributions.+--+-- As with 'NLLLoss', the input given is expected to contain log-probabilities,+-- however unlike 'ClassNLLLoss', input is not restricted to a 2D Tensor,+-- because the criterion is applied element-wise.+--+-- This criterion expects a target Tensor of the same size as the input Tensor.+--+-- The loss can be described as:+-- @+--   \ell(x, y) = L = \{l_1,\dots,l_N\}^\top, \quad+--   l_n = y_n \odot \left( \log y_n - x_n \right),+-- @+--+-- where @N@ is the batch size. If @reduce@ is @True@, then:+-- @+--   \begin{split}\ell(x, y) = \begin{cases}+--       \operatorname{mean}(L), & \text{if}\; \text{size_average} = \text{True},\\+--       \operatorname{sum}(L),  & \text{if}\; \text{size_average} = \text{False}.+--   \end{cases}\end{split}+-- @+--+-- By default, the losses are averaged for each minibatch over observations as+-- well as over dimensions. However, if the field @size_average@ is set to+-- @False@, the losses are instead summed.+++-- | distKLDivCriterion forward pass (updates the output tensor)+_distKLDivCriterion_updateOutput+  :: Tensor d  -- ^ output tensor to update+  -> Tensor d  -- ^ input tensor+  -> Tensor d  -- ^ comparative tensor+  -> Bool      -- ^ size_average+  -> Bool      -- ^ reduce+  -> IO ()+_distKLDivCriterion_updateOutput t0 t1 t2 = Dynamic._distKLDivCriterion_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | distKLDivCriterion backward-update (updates the layer and bias tensors)+_distKLDivCriterion_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Bool -> Bool -> IO ()+_distKLDivCriterion_updateGradInput t0 t1 t2 t3 = Dynamic._distKLDivCriterion_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- | smoothL1Criterion forward pass (updates the output tensor)+_smoothL1Criterion_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Bool -> Bool -> IO ()+_smoothL1Criterion_updateOutput t0 t1 t2 = Dynamic._smoothL1Criterion_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- | smoothL1Criterion backward-update (updates the layer and bias tensors)+_smoothL1Criterion_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Bool -> Bool -> IO ()+_smoothL1Criterion_updateGradInput t0 t1 t2 t3 = Dynamic._smoothL1Criterion_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- | l1Cost forward pass (updates the output tensor)+_l1Cost_updateOutput :: Tensor d -> Tensor d -> IO ()+_l1Cost_updateOutput t0 t1 = Dynamic._l1Cost_updateOutput (asDynamic t0) (asDynamic t1)+-- | l1Cost backward-update (updates the layer and bias tensors)+_l1Cost_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_l1Cost_updateGradInput t0 t1 t2 = Dynamic._l1Cost_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | ClassNLLCriterion+--+-- The negative log likelihood (NLL) criterion. It is useful to train a classification problem with n classes. If provided, the optional argument weights should be a 1D Tensor assigning weight to each of the classes. This is particularly useful when you have an unbalanced training set.+--+-- The input given through a forward() is expected to contain log-probabilities of each class: input has to be a 1D Tensor of size n. Obtaining log-probabilities in a neural network is easily achieved by adding a LogSoftMax layer in the last layer of your neural network. You may use CrossEntropyCriterion instead, if you prefer not to add an extra layer to your network. This criterion expects a class index (1 to the number of class) as target when calling forward(input, target) and backward(input, target).+--+-- The loss can be described as:+--+-- loss(x, class) = -x[class]+--+-- or in the case of the weights argument, it is specified as follows:+--+-- loss(x, class) = -weights[class] * x[class]+--+-- or in the case of the ignoreIndex argument:+--+-- loss(x, class) = class != ignoreIndex ? -weights[class] * x[class] : 0+--+-- Indeed, the ignoreIndex (defaults to -100) specifies a value for targets to be ignored. The commensurate gradInput for that target will be zero. When sizeAverage=true (the default), the gradInput and output are averaged over non-ignored targets.+--+-- Due to the behaviour of the backend code, it is necessary to set sizeAverage to false when calculating losses in non-batch mode.+--+-- The following is a code fragment showing how to make a gradient step given an input x, a desired output y (an integer 1 to n, in this case n = 2 classes), a network mlp and a learning rate learningRate:+--+-- function gradUpdate(mlp, x, y, learningRate)+--    local criterion = nn.ClassNLLCriterion()+--    local pred = mlp:forward(x)+--    local err = criterion:forward(pred, y)+--    mlp:zeroGradParameters()+--    local t = criterion:backward(pred, y)+--    mlp:backward(x, t)+--    mlp:updateParameters(learningRate)+-- end+--+-- By default, the losses are averaged over observations for each minibatch. However, if the argument sizeAverage is set to false, the losses are instead summed for each minibatch.+-- FIXME: add batch dimension+classNLLCriterion'+  :: forall s i sz ps+  . (Reifies s W, All KnownDim '[sz, ps])+  => Integer                    -- int64_t ignore_index,+  -> Bool                       -- bool sizeAverage,+  -> Bool                       -- bool reduce+  -> IndexTensor '[sz]          -- THIndexTensor *target. _not_ a one-hot encoded vector.+  -- -> Maybe Dynamic           -- THTensor *weights,+  -> BVar s (Tensor '[sz, ps])  -- THTensor *input,+  -> BVar s (Tensor '[1])       -- THTensor *output,+classNLLCriterion' ix szAvg reduce target = liftOp1 . op1 $ \inp ->+  let+    (out, total_weight) = updateOutput inp target szAvg Nothing ix reduce+  in+    (out, \gout -> updateGradInput inp target gout szAvg Nothing total_weight ix reduce)+  where+    {-# NOINLINE updateOutput #-}+    updateOutput+      :: Tensor '[sz, ps]            -- THTensor *input,+      -> IndexTensor '[sz]           -- THIndexTensor *target,+      -> Bool                        -- bool sizeAverage,+      -> Maybe (Tensor '[sz, ps])    -- THTensor *weights,+      -> Integer                     -- int64_t ignore_index,+      -> Bool                        -- bool reduce+      -> (Tensor '[1], Tensor '[1])+    updateOutput inp tar szAvg mws ix reduce = unsafePerformIO $ do+      let out = new+      let total_weight = constant 1  -- https://github.com/torch/nn/commit/3585e827eb65d071272a4aa4fab567b0b1eeee54#diff-1aa6a505cf16ad0e59498ada8432afb5+      Dynamic._ClassNLLCriterion_updateOutput (asDynamic inp) (Ix.longAsDynamic tar) (asDynamic out)+        szAvg (asDynamic <$> mws) (asDynamic total_weight) ix reduce+      pure (out, total_weight)++    {-# NOINLINE updateGradInput #-}+    updateGradInput+      :: Tensor '[sz, ps]          -- THTensor *input,+      -> IndexTensor '[sz]         -- THIndexTensor *target,+      -> Tensor '[1]               -- THTensor *gradOutput,+      -> Bool                      -- bool sizeAverage,+      -> Maybe (Tensor '[sz, ps])  -- THTensor *weights,+      -> Tensor '[1]               -- THTensor *total_weight,+      -> Integer                   -- int64_t ignore_index,+      -> Bool                      -- bool reduce+      -> Tensor '[sz, ps]+    updateGradInput inp tar gout szAvg mws total_weight ix reduce = unsafePerformIO $ do+      let gin = empty+      Dynamic._ClassNLLCriterion_updateGradInput+        (asDynamic inp) (Ix.longAsDynamic tar) (asDynamic gout) (asDynamic gin)+        szAvg (asDynamic <$> mws) (asDynamic total_weight) ix reduce+      pure gin+++-- | Due to behaviour of backend code, it is nessecary to set sizeAverage to False in Non-Batch mode.+classNLLCriterion+  :: (Reifies s W, All KnownDim '[n, c])+  => IndexTensor '[n]            -- THIndexTensor *target,+  -> BVar s (Tensor '[n, c])     -- THTensor *input,+  -> BVar s (Tensor '[1])        -- THTensor *output,+classNLLCriterion = classNLLCriterion' (-100) True True++classNLLIO+  :: forall sz ps+  .  (KnownDim sz, KnownDim ps)+  => IndexTensor '[sz]+  -> (Tensor '[sz, ps]+  -> IO (Tensor '[1], Tensor '[1] -> IO (Tensor '[sz, ps])))+classNLLIO = classNLLWithIO (Just new) (Just new) (Just new)++classNLLWithIO+  :: forall sz ps+  .  (KnownDim sz, KnownDim ps)+  => Maybe (Tensor '[1])+  -> Maybe (Tensor '[1])+  -> Maybe (Tensor '[sz, ps])+  -> IndexTensor '[sz]+  -> (Tensor '[sz, ps]                                       --  \___ these constitue a closed cartesian category and+  -> IO (Tensor '[1], Tensor '[1] -> IO (Tensor '[sz, ps]))) --  /    can be abstracted away into an autodiff lib.+classNLLWithIO cnlloutref cnllwRef mgin target inp = do+  let out = fromMaybe new cnlloutref+  let total_weight = fromMaybe new cnllwRef+  -- let total_weight = constant 1  -- https://github.com/torch/nn/commit/3585e827eb65d071272a4aa4fab567b0b1eeee54#diff-1aa6a505cf16ad0e59498ada8432afb5+  onesLike_ total_weight total_weight++  updateOutput_ inp target szAvg Nothing ix reduce (out, total_weight)++  pure (out, \gout -> do+    let gin = fromMaybe new mgin+    zero_ gin+    updateGradInput_ inp target gout szAvg Nothing total_weight ix reduce gin+    pure gin)+  where+    ix = (-100)+    reduce = True+    szAvg = True++    updateOutput_+      :: Tensor '[sz, ps]            -- THTensor *input,+      -> IndexTensor '[sz]           -- THIndexTensor *target,+      -> Bool                        -- bool sizeAverage,+      -> Maybe (Tensor '[sz, ps])    -- THTensor *weights,+      -> Integer                     -- int64_t ignore_index,+      -> Bool                        -- bool reduce+      -> (Tensor '[1], Tensor '[1])  -- THTensor *input, total_weight+      -> IO ()+    updateOutput_ inp tar szAvg mws ix reduce (out, total_weight) = do+      Dynamic._ClassNLLCriterion_updateOutput (asDynamic inp) (Ix.longAsDynamic tar) (asDynamic out)+        szAvg (asDynamic <$> mws) (asDynamic total_weight) ix reduce++    updateGradInput_+      :: Tensor '[sz, ps]          -- THTensor *input,+      -> IndexTensor '[sz]         -- THIndexTensor *target,+      -> Tensor '[1]               -- THTensor *gradOutput,+      -> Bool                      -- bool sizeAverage,+      -> Maybe (Tensor '[sz, ps])  -- THTensor *weights,+      -> Tensor '[1]               -- THTensor *total_weight,+      -> Integer                   -- int64_t ignore_index,+      -> Bool                      -- bool reduce++      -> Tensor '[sz, ps]          -- gradient to update inplace+      -> IO ()+    updateGradInput_ inp tar gout szAvg mws total_weight ix reduce gin =+      Dynamic._ClassNLLCriterion_updateGradInput (asDynamic inp) (Ix.longAsDynamic tar) (asDynamic gout) (asDynamic gin)+        szAvg (asDynamic <$> mws) (asDynamic total_weight) ix reduce+++{-+c_SpatialClassNLLCriterion_updateOutput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> CBool -> Ptr CTensor -> Ptr CTensor -> CLLong -> CBool -> IO ()+c_SpatialClassNLLCriterion_updateGradInput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> CBool -> Ptr CTensor -> Ptr CTensor -> CLLong -> CBool -> IO ()+c_MultiLabelMarginCriterion_updateOutput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> CBool -> CBool -> IO ()+c_MultiLabelMarginCriterion_updateGradInput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> CBool -> CBool -> IO ()+c_MultiMarginCriterion_updateOutput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> CBool -> CInt -> Ptr CTensor -> CDouble -> CBool -> IO ()+c_MultiMarginCriterion_updateGradInput :: Ptr CNNState -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> CBool -> CInt -> Ptr CTensor -> CDouble -> CBool -> IO ()+-}++{-+c_LookupTable_renorm :: Ptr CNNState -> Ptr CIndexTensor -> Ptr CTensor -> CDouble -> CDouble -> IO ()+c_IndexLinear_updateOutput :: Ptr CNNState -> Ptr CIndexTensor -> CLLong -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> CInt -> IO ()+c_IndexLinear_accGradParameters :: Ptr CNNState -> Ptr CIndexTensor -> CLLong -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> CDouble -> CDouble -> IO ()+c_IndexLinear_accUpdateGradParameters :: Ptr CNNState -> Ptr CIndexTensor -> CLLong -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CIndexTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> CDouble -> CDouble -> IO ()+c_IndexLinear_updateParameters :: Ptr CNNState -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CTensor -> Ptr CIndexTensor -> Ptr CIndexTensor -> CLLong -> CDouble -> CDouble -> IO ()++-}
+ src/Torch/Indef/Static/NN/Layers.hs view
@@ -0,0 +1,86 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Layers+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Miscellaneous layer functions.+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+module Torch.Indef.Static.NN.Layers where++import Data.List+import Data.Singletons.Prelude.List hiding (All)+import Numeric.Backprop+import Numeric.Dimensions++import Debug.Trace as D+import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.Reduce+import Torch.Indef.Static.Tensor.Math.Pairwise ((^/), (^-))+import Torch.Indef.Static.Tensor.Math.Pointwise ((^*^), (^-^))+import Torch.Indef.Static.Tensor.Math.Blas+import Torch.Indef.Static.NN.Backprop ()+import qualified Torch.Indef.Dynamic.NN as Dynamic++-- | A backpropable 'flatten' operation+flattenBP+  :: (Reifies s W, KnownDim (Product d), Dimensions (d::[Nat]))+  => BVar s (Tensor d) -> BVar s (Tensor '[Product d])+flattenBP = liftOp1 . op1 $ \t -> (flatten t, resizeAs)++-- | A backpropable 'flatten' operation with a batch dimension+flattenBPBatch+  :: (Reifies s W, All KnownDim '[Product d, bs], Dimensions d)+  => Product (bs:+d) ~ Product '[bs, Product d]+  => BVar s (Tensor (bs:+d))+  -> BVar s (Tensor '[bs, Product d])+flattenBPBatch = liftOp1 . op1 $ \t -> (resizeAs t, resizeAs)++-------------------------------------------------------------------------------++-- |  sparseLinear forward pass (updates the output tensor)+_sparseLinear_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_sparseLinear_updateOutput t0 t1 t2 t3 = Dynamic._sparseLinear_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)+-- |  sparseLinear backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_sparseLinear_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> Double -> IO ()+_sparseLinear_accGradParameters t0 t1 t2 t3 t4 t5 = Dynamic._sparseLinear_accGradParameters (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5)++-- |  sparseLinear zeroGradParameters+_sparseLinear_zeroGradParameters :: Tensor d -> Tensor d -> Tensor d -> IO ()+_sparseLinear_zeroGradParameters t0 t1 t2 = Dynamic._sparseLinear_zeroGradParameters (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- |  sparseLinear updateParameters+_sparseLinear_updateParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> IO ()+_sparseLinear_updateParameters t0 t1 t2 t3 t4 = Dynamic._sparseLinear_updateParameters (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)++-- |  gatedLinear forward pass (updates the output tensor)+_gatedLinear_updateOutput :: Tensor d -> Tensor d -> Int -> IO ()+_gatedLinear_updateOutput t0 t1 = Dynamic._gatedLinear_updateOutput (asDynamic t0) (asDynamic t1)+-- |  gatedLinear backward-update (updates the layer and bias tensors)+_gatedLinear_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_gatedLinear_updateGradInput t0 t1 t2 = Dynamic._gatedLinear_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- |  gRUFused forward pass (updates the output tensor)+_gRUFused_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_gRUFused_updateOutput t0 t1 t2 t3 t4 t5 t6 = Dynamic._gRUFused_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5) (asDynamic t6)+-- |  gRUFused backward-update (updates the layer and bias tensors)+_gRUFused_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_gRUFused_updateGradInput t0 t1 t2 t3 t4 = Dynamic._gRUFused_updateGradInput  (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)++-- |  lSTMFused forward pass (updates the output tensor)+_lSTMFused_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_lSTMFused_updateOutput t0 t1 t2 t3 t4 t5 t6 = Dynamic._lSTMFused_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5) (asDynamic t6)+-- |  lSTMFused backward-update (updates the layer and bias tensors)+_lSTMFused_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_lSTMFused_updateGradInput t0 t1 t2 t3 t4 t5 t6 = Dynamic._lSTMFused_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5) (asDynamic t6)++
+ src/Torch/Indef/Static/NN/Linear.hs view
@@ -0,0 +1,328 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Linear+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Linear layers+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Linear where++import Data.List+import GHC.Generics+import Data.Singletons.Prelude.List hiding (All)+import Numeric.Backprop+import Numeric.Dimensions+import System.IO.Unsafe++import Debug.Trace+import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.Blas+import Torch.Indef.Static.Tensor.Math.Pointwise+import Torch.Indef.Static.Tensor.Math.Pointwise.Signed ()+import Torch.Indef.Static.Tensor.Math.Pairwise (Pairwise(..))+import Torch.Indef.Static.NN.Backprop ()+import qualified Torch.Indef.Dynamic.NN as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math.Pointwise as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Math.Pairwise as Dynamic++-- | datatype representing a linear layer with bias. Represents+-- @y = Ax + b@.+newtype Linear i o+  = Linear { getTensors :: (Tensor '[i, o], Tensor '[o]) }+  deriving (Eq, Generic)++instance (KnownDim i, KnownDim o) => Show (Linear i o) where+  show c = intercalate ","+    [ "Linear ("+    ++ "input: "  ++ show (inputSize c)+    , " output: " ++ show (outputSize c)+    ++ ")"+    ]++instance (KnownDim i, KnownDim o) => Backprop (Linear i o) where+  zero = const . Linear $ (constant 0, constant 0)+  one  = const . Linear $ (constant 1, constant 1)+-- instance (KnownDim i, KnownDim o) => Backprop (Linear i o) where+--   one  (Linear (a, b)) = unsafePerformIO $ do+--     Dynamic.onesLike_ (asDynamic a) (asDynamic a)+--     Dynamic.onesLike_ (asDynamic b) (asDynamic b)+--     pure (Linear (a, b))+--   {-# NOINLINE one #-}++--   zero (Linear (a, b)) = unsafePerformIO $ do+--     Dynamic.zerosLike_ (asDynamic a) (asDynamic a)+--     Dynamic.zerosLike_ (asDynamic b) (asDynamic b)+--     pure (Linear (a, b))+--   {-# NOINLINE zero #-}+++  add (Linear (a0, b0)) (Linear (a1, b1)) = unsafePerformIO $ do+    Dynamic.cadd_ (asDynamic a1) 1 (asDynamic a0)+    Dynamic.cadd_ (asDynamic b1) 1 (asDynamic b0)+    pure (Linear (a1, b1))+  {-# NOINLINE add #-}++instance (KnownDim i, KnownDim o) => Num (Linear i o) where+  (+) (Linear (a0, b0)) (Linear (a1, b1)) = Linear (a0+a1, b0+b1)+  (-) (Linear (a0, b0)) (Linear (a1, b1)) = Linear (a0-a1, b0-b1)+  (*) (Linear (a0, b0)) (Linear (a1, b1)) = Linear (a0*a1, b0*b1)+  abs (Linear (a0, b0)) = Linear (abs a0, abs b0)+  fromInteger i = Linear (fromInteger i, fromInteger i)++instance (KnownDim i, KnownDim o) => Pairwise (Linear i o) HsReal where+  (Linear tens) ^+ v = Linear (tens ^+ v)+  (Linear tens) ^- v = Linear (tens ^- v)+  (Linear tens) ^* v = Linear (tens ^* v)+  (Linear tens) ^/ v = Linear (tens ^/ v)++-- -- | update a Linear layer+-- updatePure+--   :: (KnownDim i, KnownDim o)+--   => Linear i o   -- ^ layer to update+--   -> HsReal       -- ^ learning rate+--   -> Linear i o   -- ^ gradient+--   -> Linear i o   -- ^ updated layer+-- updatePure net lr (Linear (gw, gb)) = add net $ Linear (lr *^ gw, lr *^ gb)++-- | update a Conv2d layer inplace+update_+  :: (KnownDim i, KnownDim o)+  => Linear i o   -- ^ layer to update+  -> HsReal       -- ^ learning rate+  -> Linear i o   -- ^ gradient+  -> IO ()+update_ (Linear (w, b)) lr (Linear (gw, gb)) = do+  Dynamic.cadd_ (asDynamic w) lr (asDynamic gw)+  Dynamic.cadd_ (asDynamic b) lr (asDynamic gb)+++-- | update a Conv2d layer+update+  :: (KnownDim i, KnownDim o)+  => Linear i o   -- ^ layer to update+  -> HsReal       -- ^ learning rate+  -> Linear i o   -- ^ gradient+  -> Linear i o   -- ^ updated layer+update layer lr grads = layer + (grads ^* lr)+++-- | the dense weight matrix of a linear layer+weights :: Linear i o -> Tensor '[i, o]+weights (Linear (w, _)) = w++-- | the bias vector of a linear layer+bias :: Linear i o -> Tensor '[o]+bias (Linear (_, b)) = b++-- | The input size of a linear layer+inputSize :: forall i o . KnownDim i => Linear i o -> Int+inputSize _ = fromIntegral (dimVal (dim :: Dim i))++-- | The output size of a linear layer+outputSize :: forall i o kW dW . KnownDim o => Linear i o -> Int+outputSize _ = fromIntegral (dimVal (dim :: Dim o))++mkLinear+  :: (KnownDim i, KnownDim o)+  => (forall d . Dimensions d => IO (Tensor d))+  -> IO (Linear i o)+mkLinear initer = Linear <$> ((,) <$> initer <*> initer)++-- ========================================================================= --++-- | Linear+--+-- module = nn.Linear(inputDimension, outputDimension, [bias = true])+--+-- Applies a linear transformation to the incoming data, i.e. y = Ax + b. The input tensor given in forward(input) must be either a vector (1D tensor) or matrix (2D tensor). If the input is a matrix, then each row is assumed to be an input sample of given batch. The layer can be used without bias by setting bias = false.+--+-- You can create a layer in the following way:+--+--  module = nn.Linear(10, 5)  -- 10 inputs, 5 outputs+--+-- Usually this would be added to a network of some kind, e.g.:+--+--  mlp = nn.Sequential()+--  mlp:add(module)+--+-- The weights and biases (A and b) can be viewed with:+--+--  print(module.weight)+--  print(module.bias)+--+-- The gradients for these weights can be seen with:+--+--  print(module.gradWeight)+--  print(module.gradBias)+--+-- As usual with nn modules, applying the linear transformation is performed with:+--+-- x = torch.Tensor(10) -- 10 inputs+-- y = module:forward(x)+linear+  :: forall s i o+  .  Reifies s W+  => All KnownDim '[i,o]+  => BVar s (Linear i o)+  -> BVar s (Tensor '[i])+  -> BVar s (Tensor '[o])+linear = liftOp2 $ op2 $ \l i ->+  (updateOutput i l, \gout -> (accGradParameters i gout l, updateGradInput i gout (weights l)))+  where+    updateOutput :: Tensor '[i] -> Linear i o -> Tensor '[o]+    updateOutput i (Linear (w,b)) = addmv 1 b 1 (transpose2d w) i++    updateGradInput :: Tensor '[i] -> Tensor '[o] -> Tensor '[i,o] -> Tensor '[i]+    updateGradInput i gout w = addmv 0 (constant 0) 1 w gout++    accGradParameters :: Tensor '[i] -> Tensor '[o] -> Linear i o -> Linear i o+    accGradParameters i gout (Linear (w, b)) = Linear (w', b')+      where+        lr = 1+        w' = addr 1 (constant 0) lr i gout+        b' = cadd b lr gout++-- | 'linear' with a batch dimension+linearBatch+  :: forall s i o b+  .  Reifies s W+  => All KnownDim '[b,i,o]+  => BVar s (Linear i o)+  -> BVar s (Tensor '[b, i])+  -> BVar s (Tensor '[b, o])+linearBatch = liftOp2 $ op2 $ \l i -> unsafePerformIO $ do+  (o, getgrad) <- linearBatchIO l i+  pure (o, unsafePerformIO . getgrad)++linearBatchIO+  :: forall i o b+   . All KnownDim '[b,i,o]+  => (Linear i o)+  -> (Tensor '[b, i])+  -> IO (Tensor '[b, o], Tensor '[b, o] -> IO ((Linear i o),  (Tensor '[b, i])))     --- by "simple autodifferentiation", I am seeing that this is a fork+linearBatchIO = linearBatchWithIO (Just new) (Just new) (Just $ Linear (new, new))++-- | 'linear' with a batch dimension+linearBatchWithIO+  :: forall i o b+   . All KnownDim '[b,i,o]+  => Maybe (Tensor '[b, o])       -- output buffer. currently mutable.+  -> Maybe (Tensor '[b, i])       -- gradin buffer. currently mutable.+  -> Maybe (Linear i o)           -- gradparam buffer. currently mutable.+  -> (Linear i o)+  -> (Tensor '[b, i])+  -> IO (Tensor '[b, o], Tensor '[b, o] -> IO ((Linear i o),  (Tensor '[b, i])))     --- by "simple autodifferentiation", I am seeing that this is a fork+linearBatchWithIO moutbuffer mgradinbuf mgradparambuf l i = do+  let o = updateOutput i l+  pure (o, \gout -> do+    let g@(Linear (gw, gb)) = accGradParameters i gout l+    let gin = updateGradInput i gout (weights l)+    pure (g, gin))+   where+    lr = 1+    updateOutput :: Tensor '[b, i] -> Linear i o -> Tensor '[b, o]+    updateOutput i (Linear (w,b)) =+      let+        o = addmm 1 (constant 0) 1 i w+      in+        addr 1 o 1 (constant 1) b++    updateGradInput :: Tensor '[b, i] -> Tensor '[b, o] -> Tensor '[i,o] -> Tensor '[b, i]+    updateGradInput i gout w = addmm 0 (constant 0) 1 gout (transpose2d w)++    accGradParameters :: Tensor '[b,i] -> Tensor '[b,o] -> Linear i o -> Linear i o+    accGradParameters i gout (Linear (w, b)) = Linear (gw, gb)+      where+        gw :: Tensor '[i, o]+        gw = addmm 1 (constant 0) lr (transpose2d i) gout++        gb :: Tensor '[o]+        gb = addmv 1 (constant 0) lr tgout (constant 1)++        tgout :: Tensor '[o,b]+        tgout = transpose2d gout++++{-+-- | SparseLinear+--+-- Applies a linear transformation to the incoming sparse data, i.e. y = Ax + b.+-- The input tensor given in forward(input) must be a sparse vector represented+-- as 2D tensor of the form torch.Tensor(N, 2) where the pairs represent indices+-- and values. The SparseLinear layer is useful when the number of input dimensions+-- is very large and the input data is sparse.+--+-- You can create a sparse linear layer in the following way:+--+-- The sparse linear module may be used as part of a larger network, and apart+-- from the form of the input, SparseLinear operates in exactly the same way as+-- the Linear layer.+--+-- A sparse input vector may be created as so...+--+-- > x = torch.Tensor({ {1, 0.1}, {2, 0.3}, {10, 0.3}, {31, 0.2} })+-- > print(x)+-- >   1.0000   0.1000+-- >   2.0000   0.3000+-- >  10.0000   0.3000+-- >  31.0000   0.2000+-- > [torch.Tensor of dimension 4x2]+--+-- The first column contains indices, the second column contains values in a+-- vector where all other elements are zeros. The indices should not exceed the+-- stated dimensions of the input to the layer (10000 in the example).+sparselinear+  :: forall s i o+  .  Reifies s W+  => All KnownDim '[i,o]+  => HsReal+  -> BVar s (Linear i o)+  -> BVar s (Tensor '[i, 2])+  -> BVar s (Tensor '[o])+sparselinear lr = liftOp2 $ op2 $ \l i ->+  let+    o = updateOutput i l+  in+    (o, \gout -> ())+  where+    -- sparseLinear forward pass (updates the output tensor)+    updateOutput :: Tensor '[i, 2] -> Linear i o -> Tensor '[o]+    updateOutput i (Linear (w,b)) = unsafePerformIO $ do+      o <- new+      Dynamic._sparseLinear_updateOutput (asDynamic i) (asDynamic o) (asDynamic w) (asDynamic b)+      pure o++    -- sparseLinear backward-update (updates the layer and bias tensors).+    -- Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+    _accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> Double -> IO ()+    _accGradParameters t0 t1 t2 t3 t4 t5 =+      Dynamic._sparseLinear_accGradParameters+        (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4) (asDynamic t5)++    -- sparseLinear zeroGradParameters+    _zeroGradParameters :: Tensor d -> Tensor d -> Tensor d -> IO ()+    _zeroGradParameters t0 t1 t2 =+      Dynamic._sparseLinear_zeroGradParameters (asDynamic t0) (asDynamic t1) (asDynamic t2)++    -- sparseLinear updateParameters+    _updateParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> IO ()+    _updateParameters t0 t1 t2 t3 t4 =+      Dynamic._sparseLinear_updateParameters (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)+-}+
+ src/Torch/Indef/Static/NN/Math.hs view
@@ -0,0 +1,231 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Math+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Math where++import Data.Singletons.Prelude.Ord (type (<))+import Data.Singletons.Prelude.List+import Numeric.Dimensions hiding (Length)+import Numeric.Backprop+import System.IO.Unsafe+import Torch.Indef.Static.Tensor.Math.Reduce (sumall, maxall)+import Torch.Indef.Static.Tensor.Math.Pointwise ((^*^), (^-^))+import Torch.Indef.Static.Tensor.Math.Pairwise ((^-), (^/))++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.NN.Backprop ()+import qualified Torch.Indef.Dynamic.NN as Dynamic+import qualified Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch++-- | abs forward pass (updates the output tensor)+abs_updateOutput :: Tensor d -> IO (Tensor d)+abs_updateOutput i =+  let o = empty+  in Dynamic._abs_updateOutput (asDynamic i) (asDynamic o)+  >> pure o++-- | abs backward-update (updates the layer and bias tensors)+abs_updateGradInput+  :: (Product d ~ Product d')+  => Tensor d        -- ^ input+  -> Tensor d'       -- ^ gradOutput+  -> IO (Tensor d)   -- ^ gradInput+abs_updateGradInput i go =+  let gi = empty+  in Dynamic._abs_updateGradInput (asDynamic i) (asDynamic go) (asDynamic gi)+  >> pure gi++-- |  sqrt forward pass (updates the output tensor)+_sqrt_updateOutput :: Tensor d -> Tensor d -> Double -> IO ()+_sqrt_updateOutput t0 t1 = Dynamic._sqrt_updateOutput (asDynamic t0) (asDynamic t1)+-- |  sqrt backward-update (updates the layer and bias tensors)+_sqrt_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_sqrt_updateGradInput t0 t1 t2 t3 = Dynamic._sqrt_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- |  square forward pass (updates the output tensor)+_square_updateOutput :: Tensor d -> Tensor d -> IO ()+_square_updateOutput t0 t1 = Dynamic._square_updateOutput (asDynamic t0) (asDynamic t1)+-- |  square backward-update (updates the layer and bias tensors)+_square_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_square_updateGradInput t0 t1 t2 = Dynamic._square_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- |  logSigmoid forward pass (updates the output tensor)+_logSigmoid_updateOutput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_logSigmoid_updateOutput t0 t1 t2 = Dynamic._logSigmoid_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- |  logSigmoid backward-update (updates the layer and bias tensors)+_logSigmoid_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> IO ()+_logSigmoid_updateGradInput t0 t1 t2 t3 = Dynamic._logSigmoid_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- |  sigmoid forward pass (updates the output tensor)+_sigmoid_updateOutput :: Tensor d -> Tensor d -> IO ()+_sigmoid_updateOutput t0 t1 = Dynamic._sigmoid_updateOutput (asDynamic t0) (asDynamic t1)+-- |  sigmoid backward-update (updates the layer and bias tensors)+_sigmoid_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_sigmoid_updateGradInput t0 t1 t2 = Dynamic._sigmoid_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-------------------------------------------------------------------------------++-- | one dimensional version of 'softmaxN'+softmax+  :: KnownDim n+  => Reifies s W+  => BVar s (Tensor '[n])    -- ^ input+  -> BVar s (Tensor '[n])    -- ^ output+softmax = softmaxN (dim :: Dim 0)++-- | 'softmaxN' along the mini-batch dimension.+softmaxBatch+  :: KnownDim b+  => KnownDim n+  => Reifies s W+  => BVar s (Tensor '[b, n])    -- ^ input+  -> BVar s (Tensor '[b, n])    -- ^ output+softmaxBatch = softmaxN (dim :: Dim 1)+++-- | run a threshold function againts two BVar variables+softmaxN+  :: forall s i d+  .  Reifies s W+  => (i < Length d) ~ True+  => Dimensions d+  => Dim i                -- ^ dimension to softmax over+  -> BVar s (Tensor d)    -- ^ input+  -> BVar s (Tensor d)    -- ^ output+softmaxN d = liftOp1 . op1 $ \inp ->+  let+    idim = fromIntegral (dimVal d)+    out = updateOutput inp idim+  in+    (out, \gout -> updateGradInput inp gout out idim)+ where+  {-# NOINLINE updateOutput #-}+  updateOutput :: Dimensions d => Tensor d -> Integer -> Tensor d+  updateOutput inp i = unsafePerformIO $ let out = new in do+    Dynamic._softMax_updateOutput+      (asDynamic inp)+      (asDynamic out)+      i+    >> pure out++  {-# NOINLINE updateGradInput #-}+  -- FIXME: There seems to be a bug in softmax. In the mean time, using a translation+  -- of the raw THNN code:+  -- https://github.com/hasktorch/ATen/blob/hasktorch-expand/src/THNN/generic/SoftMax.c#L111+  updateGradInput+    :: Dimensions d+    => Tensor d  -- input+    -> Tensor d  -- gradOutput+    -> Tensor d  -- output+    -> Integer   -- dimension+    -> Tensor d  -- gradInput+  -- updateGradInput inp gout out d = unsafePerformIO $ do+    -- let mult = gout ^*^ out+    -- pure $ mult ^*^ (gout ^- acc2real (sumall mult))++  -- NOTE: This would have been the original codebase.+  updateGradInput inp gout out d = unsafePerformIO $ let gin = new in do+    Dynamic._softMax_updateGradInput+      (asDynamic inp)  -- input+      (asDynamic gout) -- gradOutput+      (asDynamic gin)  -- gradInput+      (asDynamic out)  -- output+      d                -- dimension+    >> pure gin+++-- | run a threshold function againts two BVar variables+logSoftMax+  :: KnownDim n+  => Reifies s W+  => BVar s (Tensor '[n])    -- ^ input+  -> BVar s (Tensor '[n])    -- ^ output+logSoftMax = logSoftMaxN (dim :: Dim 0)++-- | run a threshold function againts two BVar variables+logSoftMaxBatch+  :: KnownDim n+  => KnownDim b+  => Reifies s W+  => BVar s (Tensor '[b, n])    -- ^ input+  -> BVar s (Tensor '[b, n])    -- ^ output+logSoftMaxBatch = logSoftMaxN (dim :: Dim 1)+++-- | run a threshold function againts two BVar variables+logSoftMaxN+  :: forall s i d+  .  Reifies s W+  => (i < Length d) ~ True+  => Dimensions d+  => Dim i                -- ^ dimension to logSoftMax over+  -> BVar s (Tensor d)    -- ^ input+  -> BVar s (Tensor d)    -- ^ output+logSoftMaxN i = liftOp1 . op1 $ \inp ->+  let out = updateOutput inp i+  in (updateOutput inp i, \gout -> updateGradInput inp gout out i)+ where+  {-# NOINLINE updateOutput #-}+  updateOutput :: Tensor d -> Dim i -> Tensor d+  updateOutput inp i = unsafePerformIO $ let out = new in+    Dynamic._logSoftMax_updateOutput (asDynamic inp) (asDynamic out) (fromIntegral $ dimVal i)+    >> pure out++  {-# NOINLINE updateGradInput #-}+  updateGradInput+    :: Tensor d  -- input+    -> Tensor d  -- gradOutput+    -> Tensor d  -- output+    -> Dim i     -- dimension+    -> Tensor d  -- gradInput+  updateGradInput inp gout out i = unsafePerformIO $ let gin = new in+    Dynamic._logSoftMax_updateGradInput+      (asDynamic inp)             -- input+      (asDynamic gout)            -- gradOutput+      (asDynamic gin)             -- gradInput+      (asDynamic out)             -- output+      (fromIntegral $ dimVal i)   -- dimension+    >> pure gin+++-- |  softPlus forward pass (updates the output tensor)+_softPlus_updateOutput :: Tensor d -> Tensor d -> Double -> Double -> IO ()+_softPlus_updateOutput t0 t1 = Dynamic._softPlus_updateOutput (asDynamic t0) (asDynamic t1)+-- |  softPlus backward-update (updates the layer and bias tensors)+_softPlus_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> Double -> IO ()+_softPlus_updateGradInput t0 t1 t2 t3 = Dynamic._softPlus_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- |  softShrink forward pass (updates the output tensor)+_softShrink_updateOutput :: Tensor d -> Tensor d -> Double -> IO ()+_softShrink_updateOutput t0 t1 = Dynamic._softShrink_updateOutput (asDynamic t0) (asDynamic t1)+-- |  softShrink backward-update (updates the layer and bias tensors)+_softShrink_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Double -> IO ()+_softShrink_updateGradInput t0 t1 t2 = Dynamic._softShrink_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- |  tanh forward pass (updates the output tensor)+_tanh_updateOutput :: Tensor d -> Tensor d -> IO ()+_tanh_updateOutput t0 t1 = Dynamic._tanh_updateOutput (asDynamic t0) (asDynamic t1)+-- |  tanh backward-update (updates the layer and bias tensors)+_tanh_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_tanh_updateGradInput t0 t1 t2 = Dynamic._tanh_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- |  hardTanh forward pass (updates the output tensor)+_hardTanh_updateOutput :: Tensor d -> Tensor d -> Double -> Double -> Bool -> IO ()+_hardTanh_updateOutput t0 t1 = Dynamic._hardTanh_updateOutput (asDynamic t0) (asDynamic t1)++-- |  hardTanh backward-update (updates the layer and bias tensors)+_hardTanh_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Double -> Double -> Bool -> IO ()+_hardTanh_updateGradInput t0 t1 t2 = Dynamic._hardTanh_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)+
+ src/Torch/Indef/Static/NN/Padding.hs view
@@ -0,0 +1,46 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Padding+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.NN.Padding where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.NN as Dynamic++-- |  spatialReflectionPadding forward pass (updates the output tensor)+_spatialReflectionPadding_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_spatialReflectionPadding_updateOutput t0 t1 = Dynamic._spatialReflectionPadding_updateOutput (asDynamic t0) (asDynamic t1)+-- |  spatialReflectionPadding backward-update (updates the layer and bias tensors)+_spatialReflectionPadding_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_spatialReflectionPadding_updateGradInput t0 t1 t2 = Dynamic._spatialReflectionPadding_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- |  spatialReplicationPadding forward pass (updates the output tensor)+_spatialReplicationPadding_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_spatialReplicationPadding_updateOutput t0 t1 = Dynamic._spatialReplicationPadding_updateOutput (asDynamic t0) (asDynamic t1)+-- |  spatialReplicationPadding backward-update (updates the layer and bias tensors)+_spatialReplicationPadding_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_spatialReplicationPadding_updateGradInput t0 t1 t2 = Dynamic._spatialReplicationPadding_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- |  volumetricReplicationPadding forward pass (updates the output tensor)+_volumetricReplicationPadding_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricReplicationPadding_updateOutput t0 t1 = Dynamic._volumetricReplicationPadding_updateOutput (asDynamic t0) (asDynamic t1)+-- |  volumetricReplicationPadding backward-update (updates the layer and bias tensors)+_volumetricReplicationPadding_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricReplicationPadding_updateGradInput t0 t1 t2 = Dynamic._volumetricReplicationPadding_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- |  temporalReflectionPadding forward pass (updates the output tensor)+_temporalReflectionPadding_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> IO ()+_temporalReflectionPadding_updateOutput t0 t1 = Dynamic._temporalReflectionPadding_updateOutput (asDynamic t0) (asDynamic t1)+-- |  temporalReflectionPadding backward-update (updates the layer and bias tensors)+_temporalReflectionPadding_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> IO ()+_temporalReflectionPadding_updateGradInput t0 t1 t2 = Dynamic._temporalReflectionPadding_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- |  temporalReplicationPadding forward pass (updates the output tensor)+_temporalReplicationPadding_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> IO ()+_temporalReplicationPadding_updateOutput t0 t1 = Dynamic._temporalReplicationPadding_updateOutput (asDynamic t0) (asDynamic t1)+-- |  temporalReplicationPadding backward-update (updates the layer and bias tensors)+_temporalReplicationPadding_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> IO ()+_temporalReplicationPadding_updateGradInput t0 t1 t2 = Dynamic._temporalReplicationPadding_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++
+ src/Torch/Indef/Static/NN/Pooling.hs view
@@ -0,0 +1,619 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Pooling+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}++#if MIN_VERSION_base(4,12,0)+{-# LANGUAGE NoStarIsType #-}+#endif++{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.NN.Pooling where++import Data.Maybe+import Numeric.Backprop+import Numeric.Dimensions+import System.IO.Unsafe+import Data.Singletons.Prelude hiding (All, type (*), type (-), type (+))+import Data.Singletons.TypeLits++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math (zero_)+import Torch.Indef.Static.NN.Backprop ()+import Torch.Indef.Static.NN.Conv2d (Conv2d(..), Param2d(..), Kernel2d(..), Dilation2d(..), Padding2d(..), Step2d(..))+import Data.Singletons.Prelude.Bool++import qualified Torch.Indef.Index as Ix+import qualified Torch.Indef.Static.NN.Conv2d as Conv2d+import qualified Torch.Indef.Dynamic.NN.Pooling as Dynamic+++-- |  featureLPPooling forward pass (updates the output tensor)+_featureLPPooling_updateOutput :: Tensor d -> Tensor d -> Double -> Int -> Int -> Bool -> IO ()+_featureLPPooling_updateOutput t0 t1 = Dynamic._featureLPPooling_updateOutput (asDynamic t0) (asDynamic t1)++-- |  featureLPPooling backward-update (updates the layer and bias tensors)+_featureLPPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Double -> Int -> Int -> Bool -> IO ()+_featureLPPooling_updateGradInput t0 t1 t2 t3 = Dynamic._featureLPPooling_updateGradInput (asDynamic t0) (asDynamic t1)+ (asDynamic t2) (asDynamic t3)++-- * 1d pooling functions++-- |  temporalMaxPooling forward pass (updates the output tensor)+_temporalMaxPooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> IO ()+_temporalMaxPooling_updateOutput t0 t1 ix0 = Dynamic._temporalMaxPooling_updateOutput (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  temporalMaxPooling backward-update (updates the layer and bias tensors)+_temporalMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> IO ()+_temporalMaxPooling_updateGradInput t0 t1 t2 ix0 = Dynamic._temporalMaxPooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- * 2d pooling functions++-- | Constraint to assert that all hyperparameters are valid+-- and to make the requirement that all dimension values are+-- 'KnownDim's.+type SpatialDilationCheckC kH kW dH dW pH pW dilH dilW =+  ( All KnownDim '[kH,kW,pH,pW,dH,dW,dilH,dilW]+  , (kW > 0) ~ 'True+  , (kH > 0) ~ 'True+  , (dW > 0) ~ 'True+  , (dH > 0) ~ 'True+  , (dilW > 0) ~ 'True+  , (dilH > 0) ~ 'True+  , ((Div kW 2) >= pW) ~ 'True+  , ((Div kH 2) >= pH) ~ 'True+  )++-- | Type-level if statement to indicate what the output dimension should be if+-- CeilMode is turned on.+type CeilModeOutputDims i k d p o dil ceilMode =+  ( If (ceilMode && (Rem (i - (dil * (k - 1) + 1) + (2 * p)) d > 0))+      ((2 + (Div (i - (dil * (k - 1) + 1) + (2 * p)) d)) ~ o)+      ((1 + (Div (i - (dil * (k - 1) + 1) + (2 * p)) d)) ~ o)+  )++-- | Top-level constraint to assert that checks 'CeilModeOutputDims' on+-- height and width dimensions and asserts that all dimensions checks in+-- 'SpatialDilationCheckC' are true.+type SpatialDilationC iH iW kH kW dH dW pH pW oW oH dilH dilW ceilMode =+   ( SpatialDilationCheckC kH kW dH dW pH pW dilH dilW+   , CeilModeOutputDims iH kH dH pH oH dilH ceilMode+   , CeilModeOutputDims iW kW dW pW oW dilW ceilMode+   , All KnownDim '[oH,oW,iH,iW]+   )+++-- | run a backprop-aware @dilatedMaxPooling2d@ function+dilatedMaxPooling2d+  :: (SpatialDilationC iH iW kH kW dH dW pH pW oW oH dilH dilW ceilMode)+  => KnownDim inPlane+  => Reifies s W++  -- Parameters+  => Kernel2d '(kH, kW)         -- ^ kernel size+  -> Step2d '(dH, dW)           -- ^ step size+  -> Padding2d '(pH, pW)        -- ^ padding size+  -> Dilation2d '(dilH, dilW)   -- ^ dilation size+  -> SBool ceilMode         -- ^ ceil mode++  -- function arguments+  -> BVar s (Tensor '[inPlane, iW, iH])+  -> BVar s (Tensor '[inPlane, oW, oH])+dilatedMaxPooling2d = _dilatedMaxPooling2d++-- | run a backprop-aware @dilatedMaxPooling2d@ function with a batch dimension.+dilatedMaxPooling2dBatch+  :: (SpatialDilationC iH iW kH kW dH dW pH pW oW oH dilH dilW ceilMode)+  => KnownDim inPlane+  => KnownDim b+  => Reifies s W++  -- Parameters+  => Kernel2d '(kH, kW)         -- ^ kernel size+  -> Step2d '(dH, dW)           -- ^ step size+  -> Padding2d '(pH, pW)        -- ^ padding size+  -> Dilation2d '(dilH, dilW)   -- ^ dilation size+  -> SBool ceilMode         -- ^ ceil mode++  -- function arguments+  -> BVar s (Tensor '[b, inPlane, iW, iH])+  -> BVar s (Tensor '[b, inPlane, oW, oH])+dilatedMaxPooling2dBatch = _dilatedMaxPooling2d++-- | internal function of 'dilatedMaxPooling2d' and 'dilatedMaxPooling2dBatch'. Should not be used.+{-# NOINLINE _dilatedMaxPooling2d #-}+_dilatedMaxPooling2d+  :: forall s d d' kH kW dH dW pH pW dilH dilW ceilMode+  .  All KnownDim '[kH,kW,pH,pW,dH,dW,dilH,dilW]+  => All Dimensions '[d',d]+  => Reifies s W++  -- Parameters+  => Kernel2d '(kH, kW)         -- ^ kernel size+  -> Step2d '(dH, dW)           -- ^ step size+  -> Padding2d '(pH, pW)        -- ^ padding size+  -> Dilation2d '(dilH,dilW)   -- ^ dilation size+  -> SBool ceilMode         -- ^ ceil mode++  -- function arguments+  -> BVar s (Tensor d)      -- ^ input+  -> BVar s (Tensor d')     -- ^ output+_dilatedMaxPooling2d ker step pad dil ceil = liftOp1 . op1 $ \inp -> unsafePerformIO $ do+  (ix, out) <- _spatialDilatedMaxPooling_updateOutput inp ker step pad dil ceil+  pure (out, \gout ->+   unsafePerformIO (_spatialDilatedMaxPooling_updateGradInput inp gout ix ker step pad dil ceil))+ where+  {-# NOINLINE _spatialDilatedMaxPooling_updateOutput #-}+  _spatialDilatedMaxPooling_updateOutput+    :: Tensor d              -- ^ input+    -> Kernel2d '(kH, kW)        -- ^ kernel size+    -> Step2d '(dH, dW)          -- ^ step size+    -> Padding2d '(pH, pW)       -- ^ padding size+    -> Dilation2d '(dilH, dilW)  -- ^ dilation size+    -> SBool ceilMode        -- ^ ceil mode+    -> IO (IndexTensor d', Tensor d') -- ^ index of each max from the indicies, output of the max pooling+  _spatialDilatedMaxPooling_updateOutput inp ker step pad dil ceilMode = do+    let out = empty+    let ix = Ix.zeroIxNd :: IndexTensor d'+    Dynamic._spatialDilatedMaxPooling_updateOutput (asDynamic inp) (asDynamic out) (longAsDynamic ix)+      (param2d ker) (param2d step) (param2d pad) (param2d dil) (fromSing ceilMode)+    pure (ix, out)++  _spatialDilatedMaxPooling_updateGradInput+    :: Tensor d              -- ^ input+    -> Tensor d'             -- ^ gradOutput+    -> IndexTensor d'        -- ^ indices+    -> Kernel2d '(kH, kW)        -- ^ kernel size+    -> Step2d '(dH, dW)          -- ^ step size+    -> Padding2d '(pH, pW)       -- ^ padding size+    -> Dilation2d '(dilH, dilW)  -- ^ dilation size+    -> SBool ceilMode        -- ^ ceil mode+    -> IO (Tensor d)         -- ^ gradInput+  _spatialDilatedMaxPooling_updateGradInput inp gout ix ker step pad dil ceilMode = do+    let gin = empty+    Dynamic._spatialDilatedMaxPooling_updateGradInput+      (asDynamic inp) (asDynamic gout) (asDynamic gin) (longAsDynamic ix)+      (param2d ker) (param2d step) (param2d pad) (param2d dil) (fromSing ceilMode)+    pure gin++-- * 2d max pooling helpers++{-# NOINLINE _maxPooling2d #-}+-- | internal function of 'maxPooling2d' and 'maxPooling2dBatch'. Should not be used.+_maxPooling2d+  :: forall s d d' kH kW dH dW pH pW ceilMode+  .  All KnownDim '[kH,kW,pH,pW,dH,dW]+  => All Dimensions '[d',d]+  => Reifies s W++  -- Parameters+  => Kernel2d '(kH, kW)         -- ^ kernel size+  -> Step2d '(dH, dW)           -- ^ step size. Note: default in C is the kernel size.+  -> Padding2d '(pH, pW)        -- ^ padding size+  -> SBool ceilMode         -- ^ ceil mode++  -- function arguments+  -> BVar s (Tensor d)      -- ^ input+  -> BVar s (Tensor d')     -- ^ output+_maxPooling2d ker step pad ceil = liftOp1 . op1 $ \inp -> unsafePerformIO $ do+  (ix, out) <- _spatialMaxPooling_updateOutput inp ker step pad ceil+  print ("_maxpooling2d forward - input", shape inp)+  pure (out, \gout -> unsafePerformIO $ do+    gin <- _spatialMaxPooling_updateGradInput inp gout ix ker step pad ceil+    print ("_maxpooling2d backward- gin  ", shape gin)+    pure gin)++ where++  {-# NOINLINE _spatialMaxPooling_updateOutput #-}+  _spatialMaxPooling_updateOutput+    :: Tensor d              -- ^ input+    -> Kernel2d '(kH, kW)        -- ^ kernel size+    -> Step2d '(dH, dW)          -- ^ step size+    -> Padding2d '(pH, pW)       -- ^ padding size+    -> SBool ceilMode                         -- ^ ceil mode+    -> IO (IndexTensor d', Tensor d')           -- ^ output+  _spatialMaxPooling_updateOutput inp ker step pad ceilMode = do+    let out = empty+    let ix = Ix.zeroIxNd :: IndexTensor d'+    Dynamic._spatialMaxPooling_updateOutput (asDynamic inp) (asDynamic out) (longAsDynamic ix)+      (param2d ker) (param2d step) (param2d pad) (fromSing ceilMode)+    pure (ix, out)++  {-# NOINLINE _spatialMaxPooling_updateGradInput #-}+  _spatialMaxPooling_updateGradInput+    :: Tensor d              -- ^ input+    -> Tensor d'             -- ^ gradOutput+    -> IndexTensor d'        -- ^ indices+    -> Kernel2d '(kH, kW)        -- ^ kernel size+    -> Step2d '(dH, dW)          -- ^ step size+    -> Padding2d '(pH, pW)       -- ^ padding size+    -> SBool ceilMode        -- ^ ceil mode+    -> IO (Tensor d)              -- ^ gradInput+  _spatialMaxPooling_updateGradInput inp gout ix ker step pad ceilMode = do+    let gin = empty+    Dynamic._spatialMaxPooling_updateGradInput+      (asDynamic inp) (asDynamic gout) (asDynamic gin) (longAsDynamic ix)+      (param2d ker) (param2d step) (param2d pad) (fromSing ceilMode)+    pure gin++-- | backprop-aware @maxPooling2d@ function.+maxPooling2d+  :: (SpatialDilationC iH iW kH kW dH dW pH pW oW oH 1 1 ceilMode)+  => Reifies s W+  => KnownDim inPlane++  -- Parameters+  => Kernel2d '(kH, kW)       -- ^ kernel size+  -> Step2d '(dH, dW)       -- ^ step size+  -> Padding2d '(pH, pW)       -- ^ padding size+  -> SBool ceilMode        -- ^ ceil mode++  -> BVar s (Tensor '[inPlane, iH, iW])+  -> BVar s (Tensor '[inPlane, oH, oW])+maxPooling2d = _maxPooling2d++-- | backprop-aware @maxPooling2d@ function with a batch dimension.+maxPooling2dBatch+  :: (SpatialDilationC iH iW kH kW dH dW pH pW oW oH 1 1 ceilMode)+  => Reifies s W+  => KnownDim inPlane+  => KnownDim b++  -- Parameters+  => Kernel2d '(kH, kW)        -- ^ kernel size+  -> Step2d '(dH, dW)          -- ^ step size+  -> Padding2d '(pH, pW)       -- ^ padding size+  -> SBool ceilMode        -- ^ ceil mode++  -> BVar s (Tensor '[b, inPlane, iH, iW])+  -> BVar s (Tensor '[b, inPlane, oH, oW])+maxPooling2dBatch = _maxPooling2d++-- | internal function of 'maxPooling2d' and 'maxPooling2dBatch'. Should not be used.+maxPooling2dWithIO+  :: forall d d' kH kW dH dW pH pW ceilMode+  .  All KnownDim '[kH,kW,pH,pW,dH,dW]+  => All Dimensions '[d',d]++  -- optional buffers+  => Maybe (IndexTensor d')+  -> Maybe (Tensor d')+  -> Maybe (Tensor d)++  -- Parameters+  -> Kernel2d '(kH, kW)         -- ^ kernel size+  -> Step2d '(dH, dW)           -- ^ step size. Note: default in C is the kernel size.+  -> Padding2d '(pH, pW)        -- ^ padding size+  -> SBool ceilMode         -- ^ ceil mode++  -- function arguments+  -> Tensor d+  -> IO (Tensor d', Tensor d' -> IO (Tensor d))+maxPooling2dWithIO mix mout mgin ker step pad ceil inp = do+  -- let ix = fromMaybe new mix+  -- Ix.zero_ ix+  let ix = Ix.zeroIxNd :: IndexTensor d'+  let out = fromMaybe new mout+  zero_ out++  updateOutput_ inp ker step pad ceil (ix, out)+  pure (out, \gout -> do+    let gin = fromMaybe new mgin+    zero_ gin+    updateGradInput_ inp gout ix ker step pad ceil gin+    pure gin)++ where+  updateOutput_+    :: Tensor d              -- ^ input+    -> Kernel2d '(kH, kW)        -- ^ kernel size+    -> Step2d '(dH, dW)          -- ^ step size+    -> Padding2d '(pH, pW)       -- ^ padding size+    -> SBool ceilMode                         -- ^ ceil mode+    -> (IndexTensor d', Tensor d')           -- ^ output+    -> IO ()+  updateOutput_ inp ker step pad sceil (ix, out) = do+    Dynamic._spatialMaxPooling_updateOutput (asDynamic inp) (asDynamic out) (longAsDynamic ix)+      (param2d ker) (param2d step) (param2d pad) (fromSing sceil)++  updateGradInput_+    :: Tensor d              -- ^ input+    -> Tensor d'             -- ^ gradOutput+    -> IndexTensor d'        -- ^ indices+    -> Kernel2d '(kH, kW)        -- ^ kernel size+    -> Step2d '(dH, dW)          -- ^ step size+    -> Padding2d '(pH, pW)       -- ^ padding size+    -> SBool ceilMode        -- ^ ceil mode+    -> Tensor d              -- ^ gradInput+    -> IO ()+  updateGradInput_ inp gout ix ker step pad sceil gin =+    Dynamic._spatialMaxPooling_updateGradInput+      (asDynamic inp) (asDynamic gout) (asDynamic gin) (longAsDynamic ix)+      (param2d ker) (param2d step) (param2d pad) (fromSing sceil)++-- | backprop-aware @maxPooling2d@ function.+maxPooling2dIO+  :: forall iH iW kH kW dH dW pH pW oW oH ceilMode inPlane+  .  (SpatialDilationC iH iW kH kW dH dW pH pW oW oH 1 1 ceilMode)+  => KnownDim inPlane++  -- Parameters+  => Kernel2d '(kH, kW)       -- ^ kernel size+  -> Step2d '(dH, dW)       -- ^ step size+  -> Padding2d '(pH, pW)       -- ^ padding size+  -> SBool ceilMode        -- ^ ceil mode++  -> (Tensor '[inPlane, iH, iW])+  -> IO (Tensor '[inPlane, oH, oW], Tensor '[inPlane, oH, oW] -> IO (Tensor '[inPlane, iH, iW]))+maxPooling2dIO =+  maxPooling2dWithIO+    (Just (Ix.newIx :: IndexTensor '[inPlane, oH, oW]))+    (Just (new :: Tensor '[inPlane, oH, oW]))+    (Just (new :: Tensor '[inPlane, iH, iW]))++-- | backprop-aware @maxPooling2d@ function with a batch dimension.+maxPooling2dBatchIO+  :: forall iH iW kH kW dH dW pH pW oW oH ceilMode b inPlane+  .  (SpatialDilationC iH iW kH kW dH dW pH pW oW oH 1 1 ceilMode)+  => KnownDim inPlane+  => KnownDim b++  -- Parameters+  => Kernel2d '(kH, kW)        -- ^ kernel size+  -> Step2d '(dH, dW)          -- ^ step size+  -> Padding2d '(pH, pW)       -- ^ padding size+  -> SBool ceilMode        -- ^ ceil mode++  -> (Tensor '[b, inPlane, iH, iW])+  -> IO (Tensor '[b, inPlane, oH, oW], Tensor '[b, inPlane, oH, oW] -> IO (Tensor '[b, inPlane, iH, iW]))+maxPooling2dBatchIO =+  maxPooling2dWithIO+    (Just (Ix.newIx :: IndexTensor '[b, inPlane, oH, oW]))+    (Just (new :: Tensor '[b, inPlane, oH, oW]))+    (Just (new :: Tensor '[b, inPlane, iH, iW]))++++-- |  spatialAdaptiveMaxPooling forward pass (updates the output tensor)+_spatialAdaptiveMaxPooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> IO ()+_spatialAdaptiveMaxPooling_updateOutput t0 t1 ix0 = do+  Dynamic._spatialAdaptiveMaxPooling_updateOutput (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  spatialAdaptiveMaxPooling backward-update (updates the layer and bias tensors)+_spatialAdaptiveMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> IO ()+_spatialAdaptiveMaxPooling_updateGradInput t0 t1 t2 ix0 = Dynamic._spatialAdaptiveMaxPooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- |  spatialFractionalMaxPooling forward pass (updates the output tensor)+_spatialFractionalMaxPooling_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IndexTensor d -> Tensor d -> IO ()+_spatialFractionalMaxPooling_updateOutput t0 t1 a0 a1 a2 a3 ix0 t2 = Dynamic._spatialFractionalMaxPooling_updateOutput (asDynamic t0) (asDynamic t1) a0 a1 a2 a3 (longAsDynamic ix0) (asDynamic t2)++-- |  spatialFractionalMaxPooling backward-update (updates the layer and bias tensors)+_spatialFractionalMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IndexTensor d -> IO ()+_spatialFractionalMaxPooling_updateGradInput t0 t1 t2 a0 a1 a2 a3 ix0 = Dynamic._spatialFractionalMaxPooling_updateGradInput  (asDynamic t0) (asDynamic t1) (asDynamic t2) a0 a1 a2 a3 (longAsDynamic ix0)++-- |  spatialMaxUnpooling forward pass (updates the output tensor)+_spatialMaxUnpooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> IO ()+_spatialMaxUnpooling_updateOutput t0 t1 ix0 = Dynamic._spatialMaxUnpooling_updateOutput  (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  spatialMaxUnpooling backward-update (updates the layer and bias tensors)+_spatialMaxUnpooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> IO ()+_spatialMaxUnpooling_updateGradInput t0 t1 t2 ix0 = Dynamic._spatialMaxUnpooling_updateGradInput  (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- |  spatialAdaptiveAveragePooling forward pass (updates the output tensor)+_spatialAdaptiveAveragePooling_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> IO ()+_spatialAdaptiveAveragePooling_updateOutput t0 t1 = Dynamic._spatialAdaptiveAveragePooling_updateOutput (asDynamic t0) (asDynamic t1)++-- |  spatialAdaptiveAveragePooling backward-update (updates the layer and bias tensors)+_spatialAdaptiveAveragePooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_spatialAdaptiveAveragePooling_updateGradInput t0 t1 t2 = Dynamic._spatialAdaptiveAveragePooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | Type-level if statement to indicate what the output dimension should be if+-- CeilMode is turned on.+type AvgPool2dOutputDim i k p s ceilMode o =+  ( If (ceilMode && (Rem (i + (2 * p) - k) s > 0))+      ((2 + (Div (i + (2 * p) - k) s)) ~ o)+      ((1 + (Div (i + (2 * p) - k) s)) ~ o)+  , (k > 0) ~ 'True+  , (s > 0) ~ 'True+  , (o > 0) ~ 'True+  , ((Div k 2) >= p) ~ 'True+  )++-- | spatial global average pooling on batches in IO+gapPool2dBatchIO+  :: forall iH iW b c varlist+  . varlist ~ '[b, c, iH, iW]+  => All KnownNat varlist+  => All KnownDim varlist+  => AvgPool2dOutputDim iH iH 0 iH 'False 1+  => AvgPool2dOutputDim iW iW 0 iW 'False 1+  => Tensor '[b, c, iH, iW]               -- ^ input tensor+  -> IO (Tensor '[b, c], Tensor '[b, c] -> IO (Tensor '[b, c, iH, iW]))+gapPool2dBatchIO inp = do+  (out, getgrad) <- avgPool2dBatchIO (Kernel2d  @'(iH, iW)) inp+  pure (resizeAs out, getgrad . resizeAs)+++-- | spatial average pooling with backprop support in IO+avgPool2dWithIO+  :: All KnownNat '[c, iH, iW, oH, oW, kW, kH, dW, dH, padW, padH]+  => All KnownDim '[c, iH, iW, oH, oW, kW, kH, dW, dH, padW, padH]+  => AvgPool2dOutputDim iH kH padH dH ceil_mode oH+  => AvgPool2dOutputDim iW kW padW dW ceil_mode oW+  => Kernel2d  '(kH, kW)      -- ^ kernel sizes+  -> Step2d    '(dH, dW)      -- ^ step sizes+  -> Padding2d '(padH, padW)  -- ^ pad sizes+  -> SBool ceil_mode          -- ^ ceiling mode: when True, will use `ceil` instead of `floor` to compute the output shape+  -> SBool count_include_pad  -- ^ count_include_pad: when True, will include the zero-padding in the averaging calculation+  -> Tensor '[c, iH, iW]      -- ^ input tensor+  -> IO (Tensor '[c, oH, oW], Tensor '[c, oH, oW] -> IO (Tensor '[c, iH, iW]))+avgPool2dWithIO = _avgPool2dWithIO (Just new) (Just new)+++-- | spatial average pooling on batches with backprop support in IO and defaults+avgPool2dBatchIO+  :: forall iH iW kH kW oH oW b c+  .  All KnownNat '[b, c, iH, iW, oH, oW, kW, kH]+  => All KnownDim '[b, c, iH, iW, oH, oW, kW, kH]+  => AvgPool2dOutputDim iH kH 0 kH 'False oH+  => AvgPool2dOutputDim iW kW 0 kW 'False oW+  => Kernel2d  '(kH, kW)                  -- ^ kernel sizes+  -> Tensor '[b, c, iH, iW]               -- ^ input tensor+  -> IO (Tensor '[b, c, oH, oW], Tensor '[b, c, oH, oW] -> IO (Tensor '[b, c, iH, iW]))+avgPool2dBatchIO ker = _avgPool2dWithIO (Just new) (Just new) ker (Step2d @'(kH, kW))+      (Padding2d @'(0, 0))+      (sing :: SBool 'False)+      (sing :: SBool 'True)+++-- | spatial average pooling on batches with backprop support in IO+avgPool2dBatchWithIO+  :: All KnownNat '[b, c, iH, iW, oH, oW, kW, kH, dW, dH, padW, padH]+  => All KnownDim '[b, c, iH, iW, oH, oW, kW, kH, dW, dH, padW, padH]+  => AvgPool2dOutputDim iH kH padH dH ceil_mode oH+  => AvgPool2dOutputDim iW kW padW dW ceil_mode oW+  => Kernel2d  '(kH, kW)      -- ^ kernel sizes+  -> Step2d    '(dH, dW)      -- ^ step sizes+  -> Padding2d '(padH, padW)  -- ^ pad sizes+  -> SBool ceil_mode          -- ^ ceiling mode: when True, will use `ceil` instead of `floor` to compute the output shape+  -> SBool count_include_pad  -- ^ count_include_pad: when True, will include the zero-padding in the averaging calculation+  -> Tensor '[b, c, iH, iW]               -- ^ input tensor+  -> IO (Tensor '[b, c, oH, oW], Tensor '[b, c, oH, oW] -> IO (Tensor '[b, c, iH, iW]))+avgPool2dBatchWithIO = _avgPool2dWithIO (Just new) (Just new)++-- | generic spatial average pooling with backprop support in IO. This works without constraints and can be applied on either+-- batch or non-batch tensors, but C errors may occur if you misuse this function.+_avgPool2dWithIO+  :: forall din kW kH dW dH padW padH ceil_mode count_include_pad dout+  .  All KnownNat '[kW, kH, dW, dH, padW, padH]+  => All KnownDim '[kW, kH, dW, dH, padW, padH]+  => All Dimensions '[dout, din]+  => Maybe (Tensor dout)      -- ^ cached output (optional)+  -> Maybe (Tensor din)       -- ^ cached input gradient (optional)+  -> Kernel2d  '(kH, kW)      -- ^ kernel sizes+  -> Step2d    '(dH, dW)      -- ^ step sizes+  -> Padding2d '(padH, padW)  -- ^ pad sizes+  -> SBool ceil_mode          -- ^ ceiling mode: when True, will use `ceil` instead of `floor` to compute the output shape+  -> SBool count_include_pad  -- ^ count_include_pad: when True, will include the zero-padding in the averaging calculation+  -> Tensor din               -- ^ input tensor+  -> IO (Tensor dout, Tensor dout -> IO (Tensor din))+_avgPool2dWithIO mout mgin kers steps pads ceilMode countIncludePad inp = do+  let out = fromMaybe new mout+  _updateOutput+    (asDynamic inp) (asDynamic out)+    (param2d kers) (param2d steps) (param2d pads)+    (fromSing ceilMode) (fromSing countIncludePad)+  pure (out, \gout -> do+    let gin = fromMaybe new mgin+    _updateGradInput+      (asDynamic inp) (asDynamic gout) (asDynamic gin)+      (param2d kers) (param2d steps) (param2d pads)+      (fromSing ceilMode) (fromSing countIncludePad)+    pure gin)+  where+    -- spatialAveragePooling forward pass (updates the output tensor)+    _updateOutput+      :: Dynamic         -- input tensor+      -> Dynamic         -- output tensor+      -> (Int, Int)      -- kernel sizes+      -> (Int, Int)      -- step sizes+      -> (Int, Int)      -- pad sizes+      -> Bool            -- ceiling mode: when True, will use `ceil` instead of `floor` to compute the output shape+      -> Bool            -- count_include_pad: when True, will include the zero-padding in the averaging calculation+      -> IO ()+    _updateOutput inp out (kW, kH) (dW, dH) (padW, padH) ceil_mode count_include_pad =+      Dynamic._spatialAveragePooling_updateOutput+        inp out kW kH dW dH padW padH ceil_mode count_include_pad++    -- spatialAveragePooling backward-update (updates the layer and bias tensors)+    _updateGradInput+      :: Dynamic         -- input tensor+      -> Dynamic         -- gradient output tensor+      -> Dynamic         -- gradient input tensor+      -> (Int, Int)      -- kernel sizes+      -> (Int, Int)      -- step sizes+      -> (Int, Int)      -- pad sizes+      -> Bool            -- ceiling mode: when True, will use `ceil` instead of `floor` to compute the output shape+      -> Bool            -- count_include_pad: when True, will include the zero-padding in the averaging calculation+      -> IO ()+    _updateGradInput inp gout gin (kW, kH) (dW, dH) (padW, padH) ceil_mode count_include_pad =+      Dynamic._spatialAveragePooling_updateGradInput+        inp gout gin kW kH dW dH padW padH ceil_mode count_include_pad++-- * 3D pooling functions++-- |  volumetricFractionalMaxPooling forward pass (updates the output tensor)+_volumetricFractionalMaxPooling_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> IndexTensor d -> Tensor d -> IO ()+_volumetricFractionalMaxPooling_updateOutput t0 t1 i0 i1 i2 i3 i4 i5 ix0 t2 = Dynamic._volumetricFractionalMaxPooling_updateOutput (asDynamic t0) (asDynamic t1) i0 i1 i2 i3 i4 i5 (longAsDynamic ix0) (asDynamic t2)++-- |  volumetricFractionalMaxPooling backward-update (updates the layer and bias tensors)+_volumetricFractionalMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> IndexTensor d -> IO ()+_volumetricFractionalMaxPooling_updateGradInput t0 t1 t2 i0 i1 i2 i3 i4 i5 ix0 = Dynamic._volumetricFractionalMaxPooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) i0 i1 i2 i3 i4 i5 (longAsDynamic ix0)++-- |  volumetricMaxPooling forward pass (updates the output tensor)+_volumetricMaxPooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricMaxPooling_updateOutput t0 t1 ix0 = Dynamic._volumetricMaxPooling_updateOutput  (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  volumetricMaxPooling backward-update (updates the layer and bias tensors)+_volumetricMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricMaxPooling_updateGradInput t0 t1 t2 ix0 = Dynamic._volumetricMaxPooling_updateGradInput  (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- |  volumetricDilatedMaxPooling forward pass (updates the output tensor)+_volumetricDilatedMaxPooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricDilatedMaxPooling_updateOutput t0 t1 ix0 = Dynamic._volumetricDilatedMaxPooling_updateOutput  (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  volumetricDilatedMaxPooling backward-update (updates the layer and bias tensors)+_volumetricDilatedMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> IO ()+_volumetricDilatedMaxPooling_updateGradInput t0 t1 t2 ix0 = Dynamic._volumetricDilatedMaxPooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- |  volumetricMaxUnpooling forward pass (updates the output tensor)+_volumetricMaxUnpooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricMaxUnpooling_updateOutput t0 t1 ix0 = Dynamic._volumetricMaxUnpooling_updateOutput (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  volumetricMaxUnpooling backward-update (updates the layer and bias tensors)+_volumetricMaxUnpooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricMaxUnpooling_updateGradInput t0 t1 t2 ix0 = Dynamic._volumetricMaxUnpooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- |  volumetricAdaptiveMaxPooling forward pass (updates the output tensor)+_volumetricAdaptiveMaxPooling_updateOutput :: Tensor d -> Tensor d -> IndexTensor d -> Int -> Int -> Int -> IO ()+_volumetricAdaptiveMaxPooling_updateOutput t0 t1 ix0 = Dynamic._volumetricAdaptiveMaxPooling_updateOutput  (asDynamic t0) (asDynamic t1) (longAsDynamic ix0)++-- |  volumetricAdaptiveMaxPooling backward-update (updates the layer and bias tensors)+_volumetricAdaptiveMaxPooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IndexTensor d -> IO ()+_volumetricAdaptiveMaxPooling_updateGradInput t0 t1 t2 ix0 = Dynamic._volumetricAdaptiveMaxPooling_updateGradInput  (asDynamic t0) (asDynamic t1) (asDynamic t2) (longAsDynamic ix0)++-- |  volumetricAveragePooling forward pass (updates the output tensor)+_volumetricAveragePooling_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> IO ()+_volumetricAveragePooling_updateOutput t0 t1 =+  Dynamic._volumetricAveragePooling_updateOutput (asDynamic t0) (asDynamic t1)++-- |  volumetricAveragePooling backward-update (updates the layer and bias tensors)+_volumetricAveragePooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> IO ()+_volumetricAveragePooling_updateGradInput t0 t1 t2 =+  Dynamic._volumetricAveragePooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- |  volumetricAdaptiveAveragePooling forward pass (updates the output tensor)+_volumetricAdaptiveAveragePooling_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> IO ()+_volumetricAdaptiveAveragePooling_updateOutput t0 t1 = Dynamic._volumetricAdaptiveAveragePooling_updateOutput (asDynamic t0) (asDynamic t1)++-- |  volumetricAdaptiveAveragePooling backward-update (updates the layer and bias tensors)+_volumetricAdaptiveAveragePooling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> IO ()+_volumetricAdaptiveAveragePooling_updateGradInput t0 t1 t2 =+  Dynamic._volumetricAdaptiveAveragePooling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++
+ src/Torch/Indef/Static/NN/Sampling.hs view
@@ -0,0 +1,85 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.NN.Sampling+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.NN.Sampling where++import Control.Monad+import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.NN as Dynamic++-- * 1d sampling++-- | temporalUpSamplingNearest forward pass (updates the output tensor)+_temporalUpSamplingNearest_updateOutput :: Tensor d -> Tensor d -> Int -> IO ()+_temporalUpSamplingNearest_updateOutput t0 t1 = Dynamic._temporalUpSamplingNearest_updateOutput (asDynamic t0) (asDynamic t1)+-- | temporalUpSamplingNearest backward-update (updates the layer and bias tensors)+_temporalUpSamplingNearest_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_temporalUpSamplingNearest_updateGradInput t0 t1 t2 = Dynamic._temporalUpSamplingNearest_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | temporalUpSamplingLinear forward pass (updates the output tensor)+_temporalUpSamplingLinear_updateOutput :: Tensor d -> Tensor d -> Int -> IO ()+_temporalUpSamplingLinear_updateOutput t0 t1 = Dynamic._temporalUpSamplingLinear_updateOutput (asDynamic t0) (asDynamic t1)+-- | temporalUpSamplingLinear backward-update (updates the layer and bias tensors)+_temporalUpSamplingLinear_updateGradInput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_temporalUpSamplingLinear_updateGradInput t0 t1 = Dynamic._temporalUpSamplingLinear_updateGradInput (asDynamic t0) (asDynamic t1)++-- * 2d sampling++-- | spatialSubSampling forward pass (updates the output tensor)+_spatialSubSampling_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_spatialSubSampling_updateOutput t0 t1 t2 t3 = Dynamic._spatialSubSampling_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)+-- | spatialSubSampling backward-update (updates the layer and bias tensors)+_spatialSubSampling_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> IO ()+_spatialSubSampling_updateGradInput t0 t1 t2 t3 = Dynamic._spatialSubSampling_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)+-- | spatialSubSampling backward-update (updates the layer and bias tensors). Called 'accGradParameters' in C to indicate accumulating the gradient parameters.+_spatialSubSampling_accGradParameters :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Double -> IO ()+_spatialSubSampling_accGradParameters t0 t1 t2 t3 = Dynamic._spatialSubSampling_accGradParameters (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3)++-- | spatialUpSamplingNearest forward pass (updates the output tensor)+_spatialUpSamplingNearest_updateOutput :: Tensor d -> Tensor d -> Int -> IO ()+_spatialUpSamplingNearest_updateOutput t0 t1 = Dynamic._spatialUpSamplingNearest_updateOutput (asDynamic t0) (asDynamic t1)+-- | spatialUpSamplingNearest backward-update (updates the layer and bias tensors)+_spatialUpSamplingNearest_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_spatialUpSamplingNearest_updateGradInput t0 t1 t2 = Dynamic._spatialUpSamplingNearest_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | spatialUpSamplingBilinear forward pass (updates the output tensor)+_spatialUpSamplingBilinear_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> IO ()+_spatialUpSamplingBilinear_updateOutput t0 t1 = Dynamic._spatialUpSamplingBilinear_updateOutput (asDynamic t0) (asDynamic t1)+-- | spatialUpSamplingBilinear backward-update (updates the layer and bias tensors)+_spatialUpSamplingBilinear_updateGradInput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_spatialUpSamplingBilinear_updateGradInput t0 t1 = Dynamic._spatialUpSamplingBilinear_updateGradInput (asDynamic t0) (asDynamic t1)++-- | spatialGridSamplerBilinear forward pass (updates the output tensor)+_spatialGridSamplerBilinear_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_spatialGridSamplerBilinear_updateOutput t0 t1 t2 = Dynamic._spatialGridSamplerBilinear_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- | spatialGridSamplerBilinear backward-update (updates the layer and bias tensors)+_spatialGridSamplerBilinear_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_spatialGridSamplerBilinear_updateGradInput t0 t1 t2 t3 t4 = Dynamic._spatialGridSamplerBilinear_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)++-- * 3d sampling+-- | volumetricGridSamplerBilinear forward pass (updates the output tensor)+_volumetricGridSamplerBilinear_updateOutput :: Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_volumetricGridSamplerBilinear_updateOutput t0 t1 t2 = Dynamic._volumetricGridSamplerBilinear_updateOutput (asDynamic t0) (asDynamic t1) (asDynamic t2)+-- | volumetricGridSamplerBilinear backward-update (updates the layer and bias tensors)+_volumetricGridSamplerBilinear_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_volumetricGridSamplerBilinear_updateGradInput t0 t1 t2 t3 t4 = Dynamic._volumetricGridSamplerBilinear_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2) (asDynamic t3) (asDynamic t4)++-- | volumetricUpSamplingNearest forward pass (updates the output tensor)+_volumetricUpSamplingNearest_updateOutput :: Tensor d -> Tensor d -> Int -> IO ()+_volumetricUpSamplingNearest_updateOutput t0 t1 = Dynamic._volumetricUpSamplingNearest_updateOutput (asDynamic t0) (asDynamic t1)+-- | volumetricUpSamplingNearest backward-update (updates the layer and bias tensors)+_volumetricUpSamplingNearest_updateGradInput :: Tensor d -> Tensor d -> Tensor d -> Int -> IO ()+_volumetricUpSamplingNearest_updateGradInput t0 t1 t2 = Dynamic._volumetricUpSamplingNearest_updateGradInput (asDynamic t0) (asDynamic t1) (asDynamic t2)++-- | volumetricUpSamplingTrilinear forward pass (updates the output tensor)+_volumetricUpSamplingTrilinear_updateOutput :: Tensor d -> Tensor d -> Int -> Int -> Int -> IO ()+_volumetricUpSamplingTrilinear_updateOutput t0 t1 = Dynamic._volumetricUpSamplingTrilinear_updateOutput (asDynamic t0) (asDynamic t1)+-- | volumetricUpSamplingTrilinear backward-update (updates the layer and bias tensors)+_volumetricUpSamplingTrilinear_updateGradInput :: Tensor d -> Tensor d -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> IO ()+_volumetricUpSamplingTrilinear_updateGradInput t0 t1 = Dynamic._volumetricUpSamplingTrilinear_updateGradInput (asDynamic t0) (asDynamic t1)
+ src/Torch/Indef/Static/Tensor.hs view
@@ -0,0 +1,561 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE CPP #-}++#if MIN_VERSION_base(4,12,0)+{-# LANGUAGE NoStarIsType #-}+#endif++{-# OPTIONS_GHC -fno-cse -Wno-deprecations #-} -- no deprications because we still bundle up all mutable functions+module Torch.Indef.Static.Tensor where++import Control.Exception.Safe+import Control.Monad+import Control.Monad.Trans+import Control.Monad.Trans.Maybe+import Data.Coerce+import Data.Maybe+import Data.List+import Data.Singletons.Prelude.List hiding (All, type (++))+import Data.Proxy+import GHC.Natural+import System.IO.Unsafe+import GHC.TypeLits+import Numeric.Dimensions+import Control.Monad.Trans.Except++import Torch.Indef.Types+import Torch.Indef.Index+import Torch.Indef.Static.Tensor.Copy+import qualified Torch.Indef.Dynamic.Tensor as Dynamic+import qualified Torch.Types.TH as TH+import qualified Torch.FFI.TH.Long.Storage as TH+import qualified Torch.Sig.Types as Sig++instance Show (Tensor d) where+  show t = show (asDynamic t)++-- unnessecary+-- -- | same as 'Dynamic.isSameSizeAs' but only uses type-level dimensions to compute.+-- isSameSizeAs :: forall d d' . (All Dimensions '[d, d']) => Tensor d -> Tensor d' -> Bool+-- isSameSizeAs _ _ = (fromIntegral <$> listDims (dim :: Dim d)) == (fromIntegral <$> listDims (dim :: Dim d'))++scalar :: HsReal -> Tensor '[1]+scalar = unsafeDupablePerformIO . unsafeVector . (:[])+{-# NOINLINE scalar #-}++-- | Purely make a 1d tensor from a list of unknown length.+vector :: forall n . KnownDim n => KnownNat n => [HsReal] -> ExceptT String IO (Tensor '[n])+vector rs+  | genericLength rs == dimVal (dim :: Dim n) = asStatic <$> Dynamic.vectorEIO rs+  | otherwise = ExceptT . pure $ Left "Vector dimension does not match length of list"++unsafeVector :: (KnownDim n, KnownNat n) => [HsReal] -> IO (Tensor '[n])+unsafeVector = fmap (either error id) . runExceptT . vector++-- | Static call to 'Dynamic.newExpand'+newExpand :: Tensor d -> TH.IndexStorage -> Tensor d'+newExpand t = asStatic . Dynamic.newExpand (asDynamic t)++-- | Static call to 'Dynamic._expand'+_expand r t = Dynamic._expand (asDynamic r) (asDynamic t)+-- | Static call to 'Dynamic._expandNd'+_expandNd rs os = Dynamic._expandNd (fmap asDynamic rs) (fmap asDynamic os)++-- | Static call to 'Dynamic.resize_'+_resize t a b = Dynamic._resize (asDynamic t) a b >> pure ((asStatic . asDynamic) t)+-- | Static call to 'Dynamic.resize1d_'+resize1d_ t a = Dynamic.resize1d_ (asDynamic t) a >> pure ((asStatic . asDynamic) t)+-- | Static call to 'Dynamic.resize2d_'+resize2d_ t a b = Dynamic.resize2d_ (asDynamic t) a b >> pure ((asStatic . asDynamic) t)+-- | Static call to 'Dynamic.resize3d_'+resize3d_ t a b c = Dynamic.resize3d_ (asDynamic t) a b c >> pure ((asStatic . asDynamic) t)+-- | Static call to 'Dynamic.resize4d_'+resize4d_ t a b c d = Dynamic.resize4d_ (asDynamic t) a b c d >> pure ((asStatic . asDynamic) t)+-- | Static call to 'Dynamic.resize5d_'+resize5d_ t a b c d e = Dynamic.resize5d_ (asDynamic t) a b c d e >> pure ((asStatic . asDynamic) t)+-- | Static call to 'Dynamic.resizeAs_'+resizeAsT_ src tar = Dynamic.resizeAs_ (asDynamic src) (asDynamic tar) >> pure ((asStatic . asDynamic) src)+-- | Static call to 'Dynamic.resizeNd_'+resizeNd_ src a b c = Dynamic.resizeNd_ (asDynamic src) a b c >> pure ((asStatic . asDynamic) src)+-- | Static call to 'Dynamic.retain'+retain t = Dynamic.retain (asDynamic t)+-- | Static call to 'Dynamic._clearFlag'+_clearFlag t = Dynamic._clearFlag (asDynamic t)+#ifndef HASKTORCH_CORE_CUDA+-- | Static call to 'Dynamic.tensordata'+tensordata t = Dynamic.tensordata (asDynamic t)+#endif+-- | Static call to 'Dynamic.get1d'+get1d t = Dynamic.get1d (asDynamic t)+-- | Static call to 'Dynamic.get2d'+get2d t = Dynamic.get2d (asDynamic t)+-- | Static call to 'Dynamic.get3d'+get3d t = Dynamic.get3d (asDynamic t)+-- | Static call to 'Dynamic.get4d'+get4d t = Dynamic.get4d (asDynamic t)+-- | Static call to 'Dynamic.isContiguous'+isContiguous t = Dynamic.isContiguous (asDynamic t)++-- | Static call to 'Dynamic.isSetTo'+isSetTo t0 t1 = Dynamic.isSetTo (asDynamic t0) (asDynamic t1)+-- | Static call to 'Dynamic.isSize'+isSize t = Dynamic.isSize (asDynamic t)+-- | Static call to 'Dynamic.nDimension'+nDimension t = Dynamic.nDimension (asDynamic t)+-- | Static call to 'Dynamic.nElement'+nElement t = Dynamic.nElement (asDynamic t)+-- | Static call to 'Dynamic._narrow'+_narrow t0 t1 = Dynamic._narrow (asDynamic t0) (asDynamic t1)++-- | renamed from TH's @new@ because this always returns an empty tensor+-- FIXME: this __technically should be @IO (Tensor '[])@, but if you leave it as-is+-- the types line-up nicely (and we currently don't use rank-0 tensors).+empty = asStatic Dynamic.empty++-- | Static call to 'Dynamic.newClone'+newClone :: Tensor d -> Tensor d+newClone t = asStatic $ Dynamic.newClone (asDynamic t)++-- | Static call to 'Dynamic.newContiguous'+newContiguous t = asStatic $ Dynamic.newContiguous (asDynamic t)+-- | Static call to 'Dynamic.newNarrow'+newNarrow t a b c = asStatic <$> Dynamic.newNarrow (asDynamic t) a b c++-- | Static call to 'Dynamic.newSelect'+newSelect+  :: KnownDim i+  => '(ls, r:+rs) ~ SplitAt i d+  => Tensor d+  -> (Dim i, Idx i)+  -> IO (Tensor (ls ++ rs))+newSelect t (d, i) =+  asStatic <$>+    Dynamic.newSelect+      (asDynamic t)+      (fromIntegral (dimVal d))+      (fromIntegral (fromEnum i))++-- | Static call to 'Dynamic.newSizeOf'+newSizeOf t = Dynamic.newSizeOf (asDynamic t)+-- | Static call to 'Dynamic.newStrideOf'+newStrideOf t = Dynamic.newStrideOf (asDynamic t)++-- | Static call to 'Dynamic.newTranspose'+newTranspose t a b = asStatic $ Dynamic.newTranspose (asDynamic t) a b++-- | Static call to 'Dynamic.newUnfold'+newUnfold t a b c = asStatic $ Dynamic.newUnfold (asDynamic t) a b c++-- | Make a new view of a tensor.+view :: forall d d' . (Dimensions d, Dimensions d') => Tensor d -> IO (Tensor d')+view src = do+  longs <- ixCPUStorage $ fromIntegral <$> listDims (dims :: Dims d)+  asStatic <$> Dynamic.newView (asDynamic src) longs+++-- | Static call to 'Dynamic.newWithSize'+newWithSize a0 a1 = asStatic $ Dynamic.newWithSize a0 a1+-- | Static call to 'Dynamic.newWithSize1d'+newWithSize1d a0 = asStatic $ Dynamic.newWithSize1d a0+-- | Static call to 'Dynamic.newWithSize2d'+newWithSize2d a0 a1 = asStatic $ Dynamic.newWithSize2d a0 a1+-- | Static call to 'Dynamic.newWithSize3d'+newWithSize3d a0 a1 a2 = asStatic $ Dynamic.newWithSize3d a0 a1 a2+-- | Static call to 'Dynamic.newWithSize4d'+newWithSize4d a0 a1 a2 a3 = asStatic $ Dynamic.newWithSize4d a0 a1 a2 a3+-- | Static call to 'Dynamic.newWithStorage'+newWithStorage a0 a1 a2 a3 = asStatic $ Dynamic.newWithStorage a0 a1 a2 a3+-- | Static call to 'Dynamic.newWithStorage1d'+newWithStorage1d a0 a1 a2 = asStatic $ Dynamic.newWithStorage1d a0 a1 a2+-- | Static call to 'Dynamic.newWithStorage2d'+newWithStorage2d a0 a1 a2 a3 = asStatic $ Dynamic.newWithStorage2d a0 a1 a2 a3+-- | Static call to 'Dynamic.newWithStorage3d'+newWithStorage3d a0 a1 a2 a3 a4 = asStatic $ Dynamic.newWithStorage3d a0 a1 a2 a3 a4+-- | Static call to 'Dynamic.newWithStorage4d'+newWithStorage4d a0 a1 a2 a3 a4 a5 = asStatic $ Dynamic.newWithStorage4d a0 a1 a2 a3 a4 a5+-- | Static call to 'Dynamic.newWithTensor'+newWithTensor t = asStatic <$> Dynamic.newWithTensor (asDynamic t)+-- | Static call to 'Dynamic._select'+_select t0 t1 = Dynamic._select (asDynamic t0) (asDynamic t1)+-- | Static call to 'Dynamic._set'+_set t0 t1 = Dynamic._set (asDynamic t0) (asDynamic t1)+-- | Static call to 'Dynamic.set1d_'+set1d_ t = Dynamic.set1d_ (asDynamic t)+-- | Static call to 'Dynamic.set2d_'+set2d_ t = Dynamic.set2d_ (asDynamic t)+-- | Static call to 'Dynamic.set3d_'+set3d_ t = Dynamic.set3d_ (asDynamic t)+-- | Static call to 'Dynamic.set4d_'+set4d_ t = Dynamic.set4d_ (asDynamic t)+-- | Static call to 'Dynamic.setFlag_'+setFlag_ t = Dynamic.setFlag_ (asDynamic t)+-- | Static call to 'Dynamic.setStorage_'+setStorage_ t = Dynamic.setStorage_ (asDynamic t)+-- | Static call to 'Dynamic.setStorage1d_'+setStorage1d_ t = Dynamic.setStorage1d_ (asDynamic t)+-- | Static call to 'Dynamic.setStorage2d_'+setStorage2d_ t = Dynamic.setStorage2d_ (asDynamic t)+-- | Static call to 'Dynamic.setStorage3d_'+setStorage3d_ t = Dynamic.setStorage3d_ (asDynamic t)+-- | Static call to 'Dynamic.setStorage4d_'+setStorage4d_ t = Dynamic.setStorage4d_ (asDynamic t)+-- | Static call to 'Dynamic.setStorageNd_'+setStorageNd_ t = Dynamic.setStorageNd_ (asDynamic t)+-- | Static call to 'Dynamic.size'+size t = Dynamic.size (asDynamic t)+-- | Static call to 'Dynamic.sizeDesc'+sizeDesc t = Dynamic.sizeDesc (asDynamic t)++-- | Static call to 'Dynamic._squeeze'+_squeeze t0 t1 = Dynamic._squeeze (asDynamic t0) (asDynamic t1)++-- | Squeeze a dimension of size 1 out of the tensor+squeeze1d+  :: Dimensions d+  => '(rs, 1:+ls) ~ (SplitAt n d)+  => Dim n+  -> Tensor d+  -> Tensor (rs ++ ls)+squeeze1d n t =  unsafeDupablePerformIO $ squeeze1d_ n (newClone t)+{-# NOINLINE squeeze1d #-}++-- | *Not safe:*  squeeze a dimension of size 1 out of the tensor.+squeeze1d_+  :: Dimensions d+  => '(rs, 1:+ls) ~ (SplitAt n d)+  => Dim n+  -> Tensor d+  -> IO (Tensor (rs ++ ls))+squeeze1d_ n t = do+  let t' = asDynamic t+  Dynamic.squeeze1d_ t' (fromIntegral (dimVal n))+  pure (asStatic t')+++-- | Static call to 'Dynamic.storage'+storage t = Dynamic.storage (asDynamic t)+-- | Static call to 'Dynamic.storageOffset'+storageOffset t = Dynamic.storageOffset (asDynamic t)+-- | Static call to 'Dynamic.stride'+stride t = Dynamic.stride (asDynamic t)+-- | Static call to 'Dynamic._transpose'+_transpose t0 t1 = Dynamic._transpose (asDynamic t0) (asDynamic t1)+-- | Static call to 'Dynamic._unfold'+_unfold t0 t1 = Dynamic._unfold (asDynamic t0) (asDynamic t1)++-- | Unsqueeze a dimension of size 1 into the tensor (pure, dupable)+unsqueeze1d+  :: Dimensions d+  => '(rs, ls) ~ (SplitAt n d)+  => Dim n+  -> Tensor d+  -> Tensor (rs ++ '[1] ++ ls)+unsqueeze1d n t = unsafeDupablePerformIO $ unsqueeze1d_ n (newClone t)+{-# NOINLINE unsqueeze1d #-}++-- | *Not safe:*  unsqueeze a dimension of size 1 into the tensor.+unsqueeze1d_+  :: Dimensions d+  => '(rs, ls) ~ (SplitAt n d)+  => Dim n+  -> Tensor d+  -> IO (Tensor (rs ++ '[1] ++ ls))+unsqueeze1d_ n t = do+  Dynamic.unsqueeze1d_ (asDynamic t) (fromIntegral (dimVal n))+  pure (asStatic (asDynamic t))+++-- ========================================================================= --++-- | Get runtime shape information from a tensor+shape :: Tensor d -> [Word]+shape t = Dynamic.shape (asDynamic t)++-- | alias to 'shape', casting the dimensions into a runtime 'SomeDims'.+getSomeDims :: Tensor d -> SomeDims+getSomeDims = someDimsVal . shape++-- -- | helper function to make other parts of hasktorch valid pure functions.+-- withNew :: forall d . (Dimensions d) => (Tensor d -> IO ()) -> IO (Tensor d)+-- withNew op = new >>= \r -> op r >> pure r+--+-- -- | Should be renamed to @newFromSize@+-- withEmpty :: forall d . Dimensions d => (Tensor d -> IO ()) -> IO (Tensor d)+-- withEmpty op = let r = new in op r >> pure r++-- | same as 'withEmpty' (which should be called @newFromSize@) and 'withNew',+-- but passes in an empty tensor to be mutated and returned with a static+-- dimensionality that it is assumed to take on after the mutation.+--+-- Note: We can get away with this when Torch does resizing in C, but you need+-- to examine the C implementation of the function you are trying to make pure.+-- withEmpty' :: (Dimensions d) => (Tensor d -> IO ()) -> IO (Tensor d)+-- withEmpty' op = let r = empty in op r >> pure r++-- |+-- This is actually 'inplace'. Dimensions may change from original tensor given Torch resizing.+--+-- FIXME: remove this function+withInplace :: (Dimensions d) => Tensor d -> (Tensor d -> Tensor d -> IO ()) -> IO (Tensor d)+withInplace t op = op t t >> pure t+{-# DEPRECATED withInplace "this is a trivial function with a bad API" #-}++-- | throw a "FIXME" string.+throwFIXME :: MonadThrow io => String -> String -> io x+throwFIXME fixme msg = throwString $ msg ++ " (FIXME: " ++ fixme ++ ")"++-- | throw an "unsafe head" string.+throwNE :: MonadThrow io => String -> io x+throwNE = throwFIXME "make this function only take a non-empty [Nat]"++-- | throw an "unsupported dimension" string.+throwGT4 :: MonadThrow io => String -> io x+throwGT4 fnname = throwFIXME+  ("review how TH supports `" ++ fnname ++ "` operations on > rank-4 tensors")+  (fnname ++ " with >4 rank")+++-- | Set the storage of a tensor. This is incredibly unsafe.+setStorageDim_ :: Tensor d -> Storage -> StorageOffset -> [(Size, Stride)] -> IO ()+setStorageDim_ t s o = Dynamic.setStorageDim_ (asDynamic t) s o++-- | Set the value of a tensor at a given index+--+-- FIXME: there should be a constraint to see that d' is in d+setDim_ :: Tensor d -> Dims (d'::[Nat]) -> HsReal -> IO ()+setDim_ t = Dynamic.setDim_ (asDynamic t)+++-- | runtime version of 'setDim_'+setDim'_ :: Tensor d -> SomeDims -> HsReal -> IO ()+setDim'_ t (SomeDims d) = setDim_ t d -- (d :: Dims d')++-- | get the value of a tensor at the given index+--+-- FIXME: there should be a constraint to see that d' is in d+getDim+  :: forall d i d'+  .  All Dimensions '[d, i:+d']+  => Tensor (d::[Nat])+  -> Dims ((i:+d')::[Nat]) -- ^ the index to get is a non-empty dims list+  -> Maybe HsReal+getDim t d = Dynamic.getDim (asDynamic t) d++-- | Select a dimension of a tensor. If a vector is passed in, return a singleton tensor+-- with the index value of the vector.+(!!)+  :: forall d ls r rs i+  .  '(ls, r:+rs) ~ SplitAt i d+  => KnownDim i+  => Dimensions d+  => Tensor d+  -> Dim i+  -> Tensor (ls ++ rs)+t !! i = unsafePerformIO $+  case nDimension t of+    0 -> pure empty+    1 -> fromMaybe empty <$> runMaybeT selectVal+    _ -> newSelect t (i, Idx 1)++  where+    selectVal :: MaybeT IO (Tensor (ls ++ rs))+    selectVal = do+      guard (dimVal i < size t (dimVal i))+      v <- MaybeT . pure $ get1d t (fromIntegral $ dimVal i)+      lift $ do+        let r = newWithSize1d 1+        set1d_ r 0 v+        pure r+{-# NOINLINE (!!) #-}+++-- | Create a new tensor. Elements have not yet been allocated and there will+-- not be any gauruntees regarding what is inside.+new :: forall d . Dimensions d => Tensor d+new = asStatic $ Dynamic.new (dims :: Dims d)++-- | Resize a tensor, returning the same tensor with a the changed dimensions.+--+-- NOTE: This is copied from the dynamic version to keep the constraints clean and is _unsafe_+_resizeDim :: forall d d' . (Dimensions d') => Tensor d -> IO (Tensor d')+_resizeDim t = do+  Dynamic.resizeDim_ (asDynamic t) (dims :: Dims d')+  pure $ asStatic (asDynamic t)++-- | Resize the input with the output shape. impure and mutates the tensor inplace.+--+-- FIXME: replace @d@ with a linear type?+resizeAs_ :: forall d d' . (All Dimensions '[d, d'], Product d ~ Product d') => Tensor d -> IO (Tensor d')+resizeAs_ src = resizeAsT_ src (new :: Tensor d')++-- | Pure version of 'resizeAs_' which clones the input tensor (pure, dupable?)+--+-- WARNING: This might be not be garbage collected as you expect since the input argument becomes a dangling phantom type.+resizeAs :: forall d d' . (All Dimensions [d,d'], Product d ~ Product d') => Tensor d -> Tensor d'+resizeAs src = unsafeDupablePerformIO $+  resizeAsT_ (newClone src :: Tensor d) (new :: Tensor d')+{-# NOINLINE resizeAs #-}++-- | flatten a tensor (pure, dupable)+flatten :: (Dimensions d, KnownDim (Product d)) => Tensor d -> Tensor '[Product d]+flatten = resizeAs++-- | Initialize a tensor of arbitrary dimension from a list+-- FIXME: There might be a faster way to do this with newWithSize+fromList+  :: forall d .  Dimensions d+  => KnownNat (Product d)+  => KnownDim (Product d)+  => [HsReal] -> IO (Maybe (Tensor d))+fromList l = runMaybeT $ do+  evec <- lift $ runExceptT (vector l)+  vec :: Tensor '[Product d] <-+    case evec of+      Left _ -> mzero+      Right t -> pure t+  guard (genericLength l == dimVal (dim :: Dim (Product d)))+  lift $ _resizeDim vec+{-# NOINLINE fromList #-}++-- | Purely construct a matrix from a list of lists. This assumes that the list of lists is+-- a dense matrix representation. Returns either the successful construction of the tensor,+-- or a string explaining what went wrong.+matrix+  :: forall n m+  .  (All KnownDim '[n, m], All KnownNat '[n, m])+#if MIN_VERSION_singletons(2,4,0)+  => KnownDim (n*m) => KnownNat (n*m)+#else+  => KnownDim (n*:m) => KnownNat (n*:m)+#endif+  => [[HsReal]] -> ExceptT String IO (Tensor '[n, m])+matrix ls+  | null ls = ExceptT . pure . Left $ "no support for empty lists"++  | colLen /= mVal =+    ExceptT . pure . Left $ "length of outer list "++show colLen++" must match type-level columns " ++ show mVal++  | any (/= colLen) (fmap length ls) =+    ExceptT . pure . Left $ "can't build a matrix from jagged lists: " ++ show (fmap length ls)++  | rowLen /= nVal =+    ExceptT . pure . Left $ "inner list length " ++ show rowLen ++ " must match type-level rows " ++ show nVal++  | otherwise = asStatic <$> Dynamic.matrix ls+  where+    rowLen :: Integral l => l+    rowLen = genericLength ls++    colLen :: Integral l => l+    colLen = genericLength (head ls)++    nVal = dimVal (dim :: Dim n)+    mVal = dimVal (dim :: Dim m)++unsafeMatrix+  :: forall n m+  .  All KnownDim '[n, m, n*m]+  => All KnownNat '[n, m, n*m]+  => [[HsReal]] -> IO (Tensor '[n, m])+unsafeMatrix = fmap (either error id) . runExceptT . matrix++-- | Purely construct a cuboid from a list of list of lists. This assumes a dense+-- representation. Returns either the successful construction of the tensor,+-- or a string explaining what went wrong.+cuboid+  :: forall c h w+  .  (All KnownDim '[c, h, w], All KnownNat '[c, h, w])+  => [[[HsReal]]] -> ExceptT String IO (Tensor '[c, h, w])+cuboid ls+  | isEmpty ls                       = ExceptT . pure . Left $ "no support for empty lists"+  | chan /= length ls                = ExceptT . pure . Left $ "channels are not all of length " ++ show chan+  | any (/= rows) (lens ls)          = ExceptT . pure . Left $     "rows are not all of length " ++ show rows+  | any (/= cols) (lens (concat ls)) = ExceptT . pure . Left $  "columns are not all of length " ++ show cols+  | otherwise = asStatic <$> Dynamic.cuboid ls+  where+    isEmpty = \case+      []     -> True+      [[]]   -> True+      [[[]]] -> True+      list   -> null list || any null list || any (any null) list+++    chan = fromIntegral $ dimVal (dim :: Dim c)+    rows = fromIntegral $ dimVal (dim :: Dim h)+    cols = fromIntegral $ dimVal (dim :: Dim w)+    lens = fmap length++    innerDimCheck :: Int -> [Int] -> Bool+    innerDimCheck d = any ((/= d))++unsafeCuboid+  :: forall c h w+  .  All KnownDim '[c, h, w]+  => All KnownNat '[c, h, w]+  => [[[HsReal]]] -> IO (Tensor '[c, h, w])+unsafeCuboid = fmap (either error id) . runExceptT . cuboid+++-- | transpose a matrix (pure, dupable)+transpose2d :: (All KnownDim '[r,c]) => Tensor '[r, c] -> Tensor '[c, r]+transpose2d t = newTranspose t 1 0+++-- | Expand a vector by copying into a matrix by set dimensions+-- TODO - generalize this beyond the matrix case+expand2d+  :: forall x y . (All KnownDim '[x, y])+  => Tensor '[x] -> Tensor '[y, x]+expand2d t = unsafeDupablePerformIO $ do+  let res :: Tensor '[y, x] = new+  s <- mkCPUIxStorage =<< TH.c_newWithSize2_ s2 s1+  _expand res t s+  pure res+  where+    s1 = fromIntegral $ dimVal (dim :: Dim  x)+    s2 = fromIntegral $ dimVal (dim :: Dim  y)+{-# NOINLINE expand2d #-}++-- | Get an element from a matrix with runtime index values.+--+-- FIXME: This is primarily for backwards compatability with lasso+-- and should be removed.+getElem2d+  :: forall (n::Nat) (m::Nat) . (All KnownDim '[n, m])+  => Tensor '[n, m] -> Word -> Word -> Maybe (HsReal)+getElem2d t r c+  | r > fromIntegral (dimVal (dim :: Dim n)) ||+    c > fromIntegral (dimVal (dim :: Dim m))+      = Nothing+  | otherwise = get2d t (fromIntegral r) (fromIntegral c)+{-# DEPRECATED getElem2d "use getDim instead" #-}++-- | Set an element on a matrix with runtime index values.+--+-- FIXME: This is primarily for backwards compatability with lasso+-- and should be removed.+setElem2d+  :: forall (n::Nat) (m::Nat) ns . (All KnownDim '[n, m])+  => Tensor '[n, m] -> Word -> Word -> HsReal -> IO ()+setElem2d t r c v+  | r > fromIntegral (dimVal (dim :: Dim n)) ||+    c > fromIntegral (dimVal (dim :: Dim m))+      = throwString "Indices out of bounds"+  | otherwise = set2d_ t (fromIntegral r) (fromIntegral c) v+{-# DEPRECATED setElem2d "use setDim_ instead" #-}++
+ src/Torch/Indef/Static/Tensor/Copy.hs view
@@ -0,0 +1,51 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Copy+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Functions to copy (and cast) tensors into different types.+-- This is a pure module.+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Copy where++import Torch.Types.TH+import Torch.Indef.Types (Tensor, asDynamic, asStatic)+import qualified Torch.Indef.Dynamic.Tensor.Copy as Dynamic++-- | copy a tensor+copy :: Tensor d -> Tensor d+copy = asStatic . Dynamic.copy . asDynamic++-- | copy a tensor to a byte tensor. *Use at your own discresion*+copyByte :: Tensor d -> ByteTensor d+copyByte = byteAsStatic . Dynamic.copyByte . asDynamic++-- | copy a tensor to a char tensor. *Use at your own discresion*+copyChar :: Tensor d -> CharTensor d+copyChar = charAsStatic . Dynamic.copyChar . asDynamic++-- | copy a tensor to a short tensor. *Use at your own discresion*+copyShort :: Tensor d -> ShortTensor d+copyShort = shortAsStatic . Dynamic.copyShort . asDynamic++-- | copy a tensor to a int tensor. *Use at your own discresion*+copyInt :: Tensor d -> IntTensor d+copyInt = intAsStatic . Dynamic.copyInt . asDynamic++-- | copy a tensor to a long tensor. *Use at your own discresion*+copyLong :: Tensor d -> LongTensor d+copyLong = longAsStatic . Dynamic.copyLong . asDynamic++-- | copy a tensor to a float tensor. *Use at your own discresion*+copyFloat :: Tensor d -> FloatTensor d+copyFloat = floatAsStatic . Dynamic.copyFloat . asDynamic++-- | copy a tensor to a double tensor. *Use at your own discresion*+copyDouble :: Tensor d -> DoubleTensor d+copyDouble = doubleAsStatic . Dynamic.copyDouble . asDynamic++
+ src/Torch/Indef/Static/Tensor/Index.hs view
@@ -0,0 +1,79 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Index+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.Tensor.Index where++import Numeric.Dimensions+import GHC.TypeLits+import Control.Exception.Safe+import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Index as Ix+import qualified Torch.Indef.Dynamic.Tensor as Dynamic+import qualified Torch.Indef.Dynamic.Tensor.Index as Dynamic++-- | Static call to 'Dynamic._indexCopy'+_indexCopy :: Tensor d -> Int -> IndexTensor '[n] -> Tensor d' -> IO ()+_indexCopy r x ix t = Dynamic._indexCopy (asDynamic r) x (longAsDynamic ix) (asDynamic t)++-- | Static call to 'Dynamic._indexAdd'+_indexAdd :: Tensor d -> Int -> IndexTensor '[n] -> Tensor d' -> IO ()+_indexAdd r x ix t = Dynamic._indexAdd (asDynamic r) x (longAsDynamic ix) (asDynamic t)++-- | Static call to 'Dynamic._indexFill'+_indexFill :: Tensor d -> Int -> IndexTensor '[n] -> HsReal -> IO ()+_indexFill r x ix v = Dynamic._indexFill (asDynamic r) x (longAsDynamic ix) v++-- | Static call to 'Dynamic._indexSelect'+_indexSelect :: Tensor d -> Tensor d' -> Int -> IndexTensor '[n] -> IO ()+_indexSelect r t d ix = Dynamic._indexSelect (asDynamic r) (asDynamic t) d (longAsDynamic ix)++-- | Static call to 'Dynamic._take'+_take :: Tensor d -> Tensor d' -> IndexTensor '[n] -> IO ()+_take r t ix = Dynamic._take (asDynamic r) (asDynamic t) (longAsDynamic ix)++-- | Static call to 'Dynamic._put'+_put :: Tensor d -> IndexTensor '[n] -> Tensor d' -> Int -> IO ()+_put r ix t d = Dynamic._put (asDynamic r) (longAsDynamic ix) (asDynamic t) d+++-- | Retrieve a single row from a matrix+--+-- FIXME: Use 'Idx' and remove the 'throwString' function+getRow+  :: forall t n m . (All KnownDim '[n, m], KnownNat m)+  => Tensor '[n, m] -> Word -> Maybe (Tensor '[1, m])+getRow t r+  | r > dimVal (dim :: Dim n) = Nothing+  | otherwise = unsafeDupablePerformIO $ do+      let res = Dynamic.new (dims :: Dims '[1, m])+      let ixs = Ix.indexDyn [ fromIntegral r ]+      Dynamic._indexSelect res (asDynamic t) 0 ixs+      pure . Just $ asStatic res+{-# NOINLINE getRow #-}++-- | Retrieve a single column from a matrix+--+-- FIXME: Use 'Idx' and remove the 'throwString' function+getColumn+  :: forall t n m . (All KnownDim '[n, m], KnownNat n)+  => Tensor '[n, m] -> Word -> Maybe (Tensor '[n, 1])+getColumn t r+  | r > dimVal (dim :: Dim m) = Nothing+  | otherwise = unsafeDupablePerformIO $ do+      let res = Dynamic.new (dims :: Dims '[n, 1])+      let ixs = Ix.indexDyn [ fromIntegral r ]+      Dynamic._indexSelect res (asDynamic t) 1 ixs+      pure . Just $ asStatic res+{-# NOINLINE getColumn #-}+
+ src/Torch/Indef/Static/Tensor/Masked.hs view
@@ -0,0 +1,22 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Masked+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Masked where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Masked as Dynamic++-- | Static call to 'Dynamic.maskedFill_'+maskedFill_ t m v = Dynamic.maskedFill_ (asDynamic t) (byteAsDynamic m) v+-- | Static call to 'Dynamic._maskedCopy'+_maskedCopy r m t = Dynamic._maskedCopy (asDynamic r) (byteAsDynamic m) (asDynamic t)+-- | Static call to 'Dynamic._maskedSelect'+_maskedSelect r s m = Dynamic._maskedSelect (asDynamic r) (asDynamic s) (byteAsDynamic m)++
+ src/Torch/Indef/Static/Tensor/Math.hs view
@@ -0,0 +1,262 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.Tensor.Math where++import Numeric.Dimensions -- hiding (Length)++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import System.IO.Unsafe+import Data.Singletons.Prelude (fromSing)+import Data.List.NonEmpty (NonEmpty)+import Data.Either (fromRight)+import qualified Data.Singletons.Prelude.List as Sing hiding (All, type (++))+import qualified Torch.Types.TH as TH+import qualified Torch.Indef.Dynamic.Tensor.Math as Dynamic++-- | Static call to 'Dynamic.fill_'+fill_ r = Dynamic.fill_ (asDynamic r)+-- | Static call to 'Dynamic.zero_'+zero_ r = Dynamic.zero_ (asDynamic r)++-- | mutate a tensor, inplace, resizing the tensor to the given IndexStorage+-- size and replacing its value with zeros.+zeros_ :: Tensor d -> IndexStorage -> IO ()+zeros_ t0 ix = Dynamic.zeros_ (asDynamic t0) ix++-- | mutate a tensor, inplace, resizing the tensor to the same shape as the second tensor argument+-- and replacing the first tensor's values with zeros.+zerosLike_+  :: Tensor d  -- ^ tensor to mutate inplace and replace contents with zeros+  -> Tensor d'  -- ^ tensor to extract shape information from.+  -> IO ()+zerosLike_ t0 t1 = Dynamic.zerosLike_ (asDynamic t0) (asDynamic t1)++-- | mutate a tensor, inplace, resizing the tensor to the given IndexStorage+-- size and replacing its value with ones.+ones_ :: Tensor d -> TH.IndexStorage -> IO ()+ones_ t0 ix = Dynamic.ones_ (asDynamic t0) ix++-- | mutate a tensor, inplace, resizing the tensor to the same shape as the second tensor argument+-- and replacing the first tensor's values with ones.+onesLike_+  :: Tensor d  -- ^ tensor to mutate inplace and replace contents with ones+  -> Tensor d'  -- ^ tensor to extract shape information from.+  -> IO ()+onesLike_ t0 t1 = Dynamic.onesLike_ (asDynamic t0) (asDynamic t1)+++-- | Static call to 'Dynamic.numel'+numel t = Dynamic.numel (asDynamic t)+-- | Static call to 'Dynamic._reshape'+_reshape r t = Dynamic._reshape (asDynamic r) (asDynamic t)+-- | Static call to 'Dynamic._catArray'+_catArray r = Dynamic._catArray (asDynamic r)+-- | Static call to 'Dynamic._nonzero'+_nonzero r t = Dynamic._nonzero (longAsDynamic r) (asDynamic t)+-- | Static call to 'Dynamic._tril'+_tril r t = Dynamic._tril (asDynamic r) (asDynamic t)+-- | Static call to 'Dynamic._triu'+_triu r t = Dynamic._triu (asDynamic r) (asDynamic t)+-- | Static call to 'Dynamic.eye_'+eye_ r = Dynamic.eye_ (asDynamic r)++-- | Returns the trace (sum of the diagonal elements) of a matrix x. This is+-- equal to the sum of the eigenvalues of x.+--+-- Static call to 'Dynamic.ttrace'+ttrace r = Dynamic.ttrace (asDynamic r)+-- | Identical to a direct C call to the @arange@, or @range@ with special consideration for floating precision types. Static call to 'Dynamic._arange'+_arange r = Dynamic._arange (asDynamic r)++-- | Static call to 'Dynamic.range_'+range_ r = Dynamic.range_ (asDynamic r)++-- | Static call to 'Dynamic.constant'+constant :: forall d . Dimensions d => HsReal -> Tensor d+constant = asStatic . Dynamic.constant (dims :: Dims d)++-- | Static call to 'Dynamic.diag_'+diag_ :: All Dimensions '[d, d'] => Tensor d -> Int -> IO (Tensor d')+diag_ t d = do+  Dynamic.diag_ (asDynamic t) d+  pure $ (asStatic . asDynamic) t++-- | Static call to 'Dynamic.diag'+diag :: All Dimensions '[d, d'] => Tensor d -> Int -> Tensor d'+diag t d = asStatic $ Dynamic.diag (asDynamic t) d++-- | Create a diagonal matrix from a 1D vector+diag1d :: (KnownDim n) => Tensor '[n] -> Tensor '[n, n]+diag1d t = diag t 0++-- | Static call to 'Dynamic.cat_'. Unsafely returning the resulting tensor with new dimensions.+cat_+  :: All Dimensions '[d, d', d'']+  => Tensor d -> Tensor d' -> Word -> IO (Tensor d'')+cat_ a b d = do+  Dynamic._cat (asDynamic a) (asDynamic a) (asDynamic b) d+  pure (asStatic (asDynamic a))+{-# WARNING cat_ "this function is impure and the dimensions can fall out of sync with the type, if used incorrectly" #-}++-- | Static call to 'Dynamic.cat'+cat+  :: '(ls, r0:+rs) ~ Sing.SplitAt i d+  => '(ls, r1:+rs) ~ Sing.SplitAt i d'+  => Tensor d+  -> Tensor d'+  -> Dim (i::Nat)+  -> Tensor (ls ++ '[r0 + r1] ++ rs)+cat a b d = fromRight (error "impossible: cat type should not allow this branch") $+  asStatic <$> Dynamic.cat (asDynamic a) (asDynamic b) (fromIntegral $ dimVal d)++-- | convenience function, specifying a type-safe 'cat' operation.+cat1d+  :: (All KnownDim '[n1,n2,n], n ~ Sing.Sum [n1, n2])+  => Tensor '[n1] -> Tensor '[n2] -> Tensor '[n]+cat1d a b = cat a b (dim :: Dim 0)++-- | convenience function, specifying a type-safe 'cat' operation.+cat2d0 :: (All KnownDim '[n,m,n0,n1], n ~ Sing.Sum [n0, n1]) => Tensor '[n0, m] -> Tensor '[n1, m] -> Tensor '[n, m]+cat2d0 a b = cat a b (dim :: Dim 0)++-- | convenience function, stack two rank-1 tensors along the 0-dimension+stack1d0 :: KnownDim m => Tensor '[m] -> Tensor '[m] -> (Tensor '[2, m])+stack1d0 a b = cat2d0+  (unsqueeze1d (dim :: Dim 0) a)+  (unsqueeze1d (dim :: Dim 0) b)++-- | convenience function, specifying a type-safe 'cat' operation.+cat2d1 :: (All KnownDim '[n,m,m0,m1], m ~ Sing.Sum [m0, m1]) => Tensor '[n, m0] -> Tensor '[n, m1] -> (Tensor '[n, m])+cat2d1 a b = cat a b (dim :: Dim 1)++-- | convenience function, stack two rank-1 tensors along the 1-dimension+stack1d1 :: KnownDim n => Tensor '[n] -> Tensor '[n] -> (Tensor '[n, 2])+stack1d1 a b = cat2d1+  (unsqueeze1d (dim :: Dim 1) a)+  (unsqueeze1d (dim :: Dim 1) b)++-- | convenience function, specifying a type-safe 'cat' operation.+cat3d0+  :: (All KnownDim '[x,y,x0,x1,z], x ~ Sing.Sum [x0, x1])+  => Tensor '[x0, y, z]+  -> Tensor '[x1, y, z]+  -> (Tensor '[x, y, z])+cat3d0 a b = cat a b (dim :: Dim 0)++-- | convenience function, specifying a type-safe 'cat' operation.+cat3d1+  :: (All KnownDim '[x,y,y0,y1,z], y ~ Sing.Sum [y0, y1])+  => Tensor '[x, y0, z]+  -> Tensor '[x, y1, z]+  -> (Tensor '[x, y, z])+cat3d1 a b = cat a b (dim :: Dim 1)++-- | convenience function, specifying a type-safe 'cat' operation.+cat3d2+  :: (All KnownDim '[x,y,z0,z1,z], z ~ Sing.Sum [z0, z1])+  => Tensor '[x, y, z0]+  -> Tensor '[x, y, z1]+  -> (Tensor '[x, y, z])+cat3d2 a b = cat a b (dim :: Dim 2)++-- | Concatenate all tensors in a given list of dynamic tensors along the given dimension.+--+-- NOTE: In C, if the dimension is not specified or if it is -1, it is the maximum+-- last dimension over all input tensors, except if all tensors are empty, then it is 1.+catArray+  :: (Dimensions d)+  => NonEmpty Dynamic+  -> Word+  -> Either String (Tensor d)+catArray ts dv = asStatic <$> Dynamic.catArray ts dv++-- | Concatenate all tensors in a given list of dynamic tensors along the given dimension.+-- --+-- -- NOTE: In C, if the dimension is not specified or if it is -1, it is the maximum+-- -- last dimension over all input tensors, except if all tensors are empty, then it is 1.+-- catArray0+--   :: forall d ls rs r0 r1 i+--   .  Dimensions d+--   => '([], r0:+rs) ~ Sing.SplitAt i d+--   => (forall _i . [Tensor (_i+:rs)])+--   -> IO (Tensor (r0+:rs))+-- catArray0 ts dv = catArray (asDynamic <$> ts) (dimVal dv)+++-- | Concatenate all tensors in a given list of dynamic tensors along the given dimension.+--+-- NOTE: In C, if the dimension is not specified or if it is -1, it is the maximum+-- last dimension over all input tensors, except if all tensors are empty, then it is 1.+catArray'+  :: forall d ls rs r0 r1 i+  .  Dimensions d+  => '(ls, r0:+rs) ~ Sing.SplitAt i d+  => d ~ (ls ++ '[r0] ++ rs)+  => (forall _i . NonEmpty (Tensor (ls ++ '[_i] ++ rs)))+  -> Dim i+  -> Either String (Tensor d)+catArray' ts dv = catArray (asDynamic <$> ts) (dimVal dv)++catArray0 :: (Dimensions d, Dimensions d2) => NonEmpty (Tensor d2) -> Either String (Tensor d)+catArray0 ts = catArray (asDynamic <$> ts) 0++{-+catArray_+  :: forall d ls rs out n+  .  All Dimensions '[out]+  => out ~ (rs ++ '[Length '[Tensor d]] ++ ls)+  => '(ls, rs) ~ Sing.SplitAt n d++  => Sing.SList '[Tensor d]+  -> Dim n+  -> IO (Tensor out)+catArray_ ts dv+  = -- fmap asStatic+    catArray+    (asDynamic <$> (fromSing ts :: [Tensor d]))+    (fromIntegral $ dimVal dv)++-- data Sing (z :: [a]) where+--     SNil :: Sing ([] :: [k])+--     SCons :: Sing (n ': n)++singToList :: forall k ks k2 x . Sing.SList '[x] -> [x]+singToList sl = go [] sl+ where+  go :: [x] -> Sing.SList '[x] -> [x]+  -- go acc Sing.SNil = acc+  -- go acc (Sing.SNil :: Sing.SList ('[] :: [x])) = acc+  -- go acc (Sing.SConst :: Sing.Sing '[]) = acc+  go acc (Sing.SCons k ks) = go acc ks++    -- | fromSing (Sing.sNull sl) = reverse acc+    -- | otherwise = go (fromSing (Sing.sHead sl):acc) (Sing.sTail acc)+  -- Sing.SNil = reverse acc+  -- go acc (Sing.SCons sval rest) = go (fromSing sval:acc) rest+-}++-- | Static call to 'Dynamic.onesLike'+onesLike :: forall d . Dimensions d => (Tensor d)+onesLike = asStatic $ Dynamic.onesLike (dims :: Dims d)++-- | Static call to 'Dynamic.zerosLike'+zerosLike :: forall d . Dimensions d => (Tensor d)+zerosLike = asStatic $ Dynamic.zerosLike (dims :: Dims d)+++
+ src/Torch/Indef/Static/Tensor/Math/Blas.hs view
@@ -0,0 +1,245 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Blas+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.Tensor.Math.Blas where++import Numeric.Dimensions+import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math++import qualified Torch.Indef.Dynamic.Tensor.Math.Blas as Dynamic++-- | Performs a matrix-vector multiplication between @mat@ (2D Tensor) and @vec2@+-- (1D Tensor) and add it to @vec1@.+--+-- Values @v1@ and @v2@ are scalars that multiply @vec1@ and @vec2@ respectively.+-- They are optional in C and we may be able to add this to the API in the future.+--+-- In other words,+--+-- @+--   res = (v1 * vec1) + (v2 * (mat * vec2))+-- @+--+-- Sizes must respect the matrix-multiplication operation: if @mat@ is a @n × m@+-- matrix, @vec2@ must be vector of size @m@ and @vec1@ must be a vector of size+-- @n@.+addmv+  :: (All KnownDim '[r, c])+  => HsReal           -- ^ v1+  -> Tensor '[r]      -- ^ vec1+  -> HsReal           -- ^ v2+  -> Tensor '[r, c]   -- ^ mat+  -> Tensor '[c]      -- ^ vec2+  -> Tensor '[r]      -- ^ res+addmv a b c d e = asStatic $ Dynamic.addmv a (asDynamic b) c (asDynamic d) (asDynamic e)++-- safeAddmv a b c d e = asStatic $ Dynamic.addmv a (asDynamic b) c (asDynamic d) (asDynamic e)++-- | Inline version of 'addmv', mutating @vec1@ inplace.+addmv_+  :: (All KnownDim '[r, c])+  => HsReal           -- ^ v1+  -> Tensor '[r]      -- ^ vec1+  -> HsReal           -- ^ v2+  -> Tensor '[r, c]   -- ^ mat+  -> Tensor '[c]      -- ^ vec2+  -> IO ()+addmv_ a b c d e = Dynamic.addmv_ a (asDynamic b) c (asDynamic d) (asDynamic e)++-- | added simplified use of addmv: src1 #> src2+mv+  :: (All KnownDim '[r, c])+  => Tensor '[r, c] -> Tensor '[c] -> Tensor '[r]+mv m v = addmv 0 (constant 0) 1 m v++-- | inline version of 'mv'+(!*) :: (All KnownDim '[r, c]) => Tensor '[r, c] -> Tensor '[c] -> Tensor '[r]+(!*) a b = mv a b++-- | Performs a matrix-matrix multiplication between @mat1@ (2D Tensor) and @mat2@ (2D Tensor).+--+-- Values @v1@ and @v2@ are scalars that multiply @M@ and @mat1 * mat2@ respectively.+-- They are optional in C and we may be able to add this to the API in the future.+--+-- In other words,+--+-- @+--   res = (v1 * M) + (v2 * mat1 * mat2)+-- @+--+-- If @mat1@ is a @n × m@ matrix, @mat2@ a @m × p@ matrix, @M@ must be a @n × p@ matrix.+addmm+  :: All KnownDim '[a, b, c]+  => HsReal                  -- ^ v1+  -> Tensor '[a, c]          -- ^ M+  -> HsReal                  -- ^ v2+  -> Tensor '[a, b]          -- ^ mat1+  -> Tensor '[b, c]          -- ^ mat2+  -> Tensor '[a, c]          -- ^ res+addmm a b c d e = asStatic $ Dynamic.addmm a (asDynamic b) c (asDynamic d) (asDynamic e)+++-- | Inline version of 'addmm', mutating @M@ inplace.+addmm_+  :: All KnownDim '[a, b, c]+  => HsReal                  -- ^ v1+  -> Tensor '[a, c]          -- ^ M+  -> HsReal                  -- ^ v2+  -> Tensor '[a, b]          -- ^ mat1+  -> Tensor '[b, c]          -- ^ mat2+  -> IO ()+addmm_ a b c d e = Dynamic.addmm_ a (asDynamic b) c (asDynamic d) (asDynamic e)++-- | simplified wrapper of 'addmm'+--+-- FIXME: see if we can pass a null pointer in as the constant value (which might eliminate a noop linear pass).+mmult+  :: All KnownDim '[a, b, c]+  => Tensor '[a, b]+  -> Tensor '[b, c]+  -> Tensor '[a, c]+mmult x y = addmm 1 (constant 0) 1 x y++-- | infix 'mmult'+(!*!) :: (All KnownDim '[a, b, c]) => Tensor '[a, b] -> Tensor '[b, c] -> Tensor '[a, c]+(!*!) = mmult+++-- | Performs the outer-product between @vec1@ (1D Tensor) and @vec2@+-- (1D Tensor).+--+-- Values @v1@ and @v2@ are scalars that multiply @mat_ij@ and @vec1_i [out] vec2_j@ respectively.+-- They are optional in C and we may be able to add this to the API in the future.+--+-- Thus:+--+-- @+--   res_ij = (v1 * mat_ij) + (v2 * vec1_i * vec2_j)+-- @+--+-- If @vec1_@ is a vector of size @i@ and @vec2_j@ is a vector of size @j@, then+-- @mat_ij@ must be a matrix of size @i × j@.+addr+  :: All KnownDim '[r, c]+  => HsReal              -- ^ v1+  -> Tensor '[r,c]       -- ^ mat_ij+  -> HsReal              -- ^ v2+  -> Tensor '[r]         -- ^ vec1_i+  -> Tensor '[c]         -- ^ vec2_j+  -> Tensor '[r, c]      -- ^ res_ij+addr a b c d e = asStatic $ Dynamic.addr a (asDynamic b) c (asDynamic d) (asDynamic e)++++-- | Inline version of 'addr', mutating @mat_ij@ in-place.+addr_+  :: All KnownDim '[r, c]+  => HsReal              -- ^ v1+  -> Tensor '[r,c]       -- ^ mat_ij -- mutated inplace+  -> HsReal              -- ^ v2+  -> Tensor '[r]         -- ^ vec1_i+  -> Tensor '[c]         -- ^ vec2_j+  -> IO ()+addr_ a b c d e = Dynamic.addr_ a (asDynamic b) c (asDynamic d) (asDynamic e)++-- | 'addr' with the parameters for an outer product filled in.+outer+  :: forall t r c . (All KnownDim '[r, c])+  => Tensor '[r] -> Tensor '[c] -> Tensor '[r, c]+outer v1 v2 = addr 0 (constant 0) 1 v1 v2+++-- | Batch matrix-matrix product of matrices stored in @batch1@ and @batch2@,+-- with a reduced add step (all matrix multiplications get accumulated in+-- a single place).+--+-- @batch1@ and @batch2@ must be 3D Tensors each containing the same number+-- of matrices. If @batch1@ is a @b × n × m@ Tensor, @batch2@ a @b × m × p@+-- Tensor, @res@ will be a @n × p@ Tensor.+--+-- In other words,+--+-- @+--   res = (v1 * M) + (v2 * sum(batch1_i * batch2_i, i = 1, b))+-- @+addbmm+  :: All KnownDim '[n,p,b,m]+  => HsReal             -- ^ v1+  -> Tensor '[n, p]     -- ^ M+  -> HsReal             -- ^ v2+  -> Tensor '[b, n, m]  -- ^ batch1_i+  -> Tensor '[b, m, p]  -- ^ batch2_i+  -> Tensor '[n, p]     -- ^ res+addbmm a b c d e = asStatic $ Dynamic.addbmm a (asDynamic b) c (asDynamic d) (asDynamic e)+++-- | Inline version of 'addbmm', mutating @M@ in-place.+addbmm_+  :: All KnownDim '[n,p,b,m]+  => HsReal             -- ^ v1+  -> Tensor '[n, p]     -- ^ M -- mutated inplace+  -> HsReal             -- ^ v2+  -> Tensor '[b, n, m]  -- ^ batch1_i+  -> Tensor '[b, m, p]  -- ^ batch2_i+  -> IO ()+addbmm_ a b c d e = Dynamic.addbmm_ a (asDynamic b) c (asDynamic d) (asDynamic e)++-- | Batch matrix matrix product of matrices stored in batch1 and batch2, with+-- batch add.+--+-- @batch1@ and @batch2@ must be 3D Tensors each containing the same number of+-- matrices. If @batch1@ is a @b × n × m@ Tensor, @batch2@ a @b × m × p@ Tensor,+-- @res@ will be a @b × n × p@ Tensor.+--+-- In other words,+--+-- @+--   res_i = (v1 * M_i) + (v2 * batch1_i * batch2_i)+-- @+baddbmm+  :: All KnownDim '[n,p,b,m]+  => HsReal              -- ^ v1+  -> Tensor '[b, n, p]   -- ^ M_i+  -> HsReal              -- ^ v2+  -> Tensor '[b, n, m]   -- ^ batch1_i+  -> Tensor '[b, m, p]   -- ^ batch2_i+  -> Tensor '[b, n, p]   -- ^ res_i+baddbmm a b c d e = asStatic $ Dynamic.baddbmm a (asDynamic b) c (asDynamic d) (asDynamic e)++-- | Inline version of 'baddbmm', mutating @M_i@ in-place.+baddbmm_+  :: All KnownDim '[n,p,b,m]+  => HsReal              -- ^ v1+  -> Tensor '[b, n, p]   -- ^ M_i  -- mutated inplace+  -> HsReal              -- ^ v2+  -> Tensor '[b, n, m]   -- ^ batch1_i+  -> Tensor '[b, m, p]   -- ^ batch2_i+  -> IO ()+baddbmm_ a b c d e = Dynamic.baddbmm_ a (asDynamic b) c (asDynamic d) (asDynamic e)+++-- | Performs the dot product between two tensors. The number of elements must match: both tensors are+-- seen as a 1D vector.+dot :: All Dimensions '[d,d'] => Tensor d -> Tensor d' -> HsAccReal+dot a b = Dynamic.dot (asDynamic a) (asDynamic b)++-- | inline alias of 'dot'+(<.>)+  :: (All Dimensions '[d,d'])+  => Tensor d+  -> Tensor d'+  -> HsAccReal+(<.>) a b = dot a b+
+ src/Torch/Indef/Static/Tensor/Math/Compare.hs view
@@ -0,0 +1,61 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Compare+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+module Torch.Indef.Static.Tensor.Math.Compare+  ( ltValue, ltValueT, ltValueT_+  , leValue, leValueT, leValueT_+  , gtValue, gtValueT, gtValueT_+  , geValue, geValueT, geValueT_+  , neValue, neValueT, neValueT_+  , eqValue, eqValueT, eqValueT_+  ) where++import Numeric.Dimensions++import Torch.Indef.Mask+import Torch.Indef.Static.Tensor+import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Math.Compare as Dynamic++-- | return a byte tensor which contains boolean values indicating the relation between a tensor and a given scalar.+ltValue, leValue, gtValue, geValue, neValue, eqValue+  :: Dimensions d+  => Tensor d -> HsReal -> MaskTensor d+ltValue a v = byteAsStatic $ Dynamic.ltValue (asDynamic a) v+leValue a v = byteAsStatic $ Dynamic.leValue (asDynamic a) v+gtValue a v = byteAsStatic $ Dynamic.gtValue (asDynamic a) v+geValue a v = byteAsStatic $ Dynamic.geValue (asDynamic a) v+neValue a v = byteAsStatic $ Dynamic.neValue (asDynamic a) v+eqValue a v = byteAsStatic $ Dynamic.eqValue (asDynamic a) v++-- | return a tensor which contains numeric values indicating the relation between a tensor and a given scalar.+-- 0 stands for false, 1 stands for true.+ltValueT, leValueT, gtValueT, geValueT, neValueT, eqValueT+  :: (Dimensions d)+  => Tensor d -> HsReal -> Tensor d+ltValueT a b = asStatic $ Dynamic.ltValueT (asDynamic a) b+leValueT a b = asStatic $ Dynamic.leValueT (asDynamic a) b+gtValueT a b = asStatic $ Dynamic.gtValueT (asDynamic a) b+geValueT a b = asStatic $ Dynamic.geValueT (asDynamic a) b+neValueT a b = asStatic $ Dynamic.neValueT (asDynamic a) b+eqValueT a b = asStatic $ Dynamic.eqValueT (asDynamic a) b++-- | mutate a tensor in-place with its numeric relation to a given scalar, where 0 stands for false and+-- 1 stands for true.+ltValueT_, leValueT_, gtValueT_, geValueT_, neValueT_, eqValueT_+  :: (Dimensions d)+  => Tensor d -> HsReal -> IO ()+ltValueT_ a b = Dynamic.ltValueT_ (asDynamic a) b+leValueT_ a b = Dynamic.leValueT_ (asDynamic a) b+gtValueT_ a b = Dynamic.gtValueT_ (asDynamic a) b+geValueT_ a b = Dynamic.geValueT_ (asDynamic a) b+neValueT_ a b = Dynamic.neValueT_ (asDynamic a) b+eqValueT_ a b = Dynamic.eqValueT_ (asDynamic a) b+
+ src/Torch/Indef/Static/Tensor/Math/CompareT.hs view
@@ -0,0 +1,63 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.CompareT+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.CompareT+  ( ltTensor, ltTensorT, ltTensorT_+  , leTensor, leTensorT, leTensorT_+  , gtTensor, gtTensorT, gtTensorT_+  , geTensor, geTensorT, geTensorT_+  , neTensor, neTensorT, neTensorT_+  , eqTensor, eqTensorT, eqTensorT_+  ) where++import Numeric.Dimensions+import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Dynamic.Tensor.Math.CompareT as Dynamic++-- | Return a byte tensor which contains boolean values indicating the relation between two tensors.+ltTensor, leTensor, gtTensor, geTensor, neTensor, eqTensor+  :: (Dimensions d)+  => Tensor d -> Tensor d -> MaskTensor d+ltTensor a b = byteAsStatic $ Dynamic.ltTensor (asDynamic a) (asDynamic b)+leTensor a b = byteAsStatic $ Dynamic.leTensor (asDynamic a) (asDynamic b)+gtTensor a b = byteAsStatic $ Dynamic.gtTensor (asDynamic a) (asDynamic b)+geTensor a b = byteAsStatic $ Dynamic.geTensor (asDynamic a) (asDynamic b)+neTensor a b = byteAsStatic $ Dynamic.neTensor (asDynamic a) (asDynamic b)+eqTensor a b = byteAsStatic $ Dynamic.eqTensor (asDynamic a) (asDynamic b)++-- | return a tensor which contains numeric values indicating the relation between two tensors.+-- 0 stands for false, 1 stands for true.+ltTensorT, leTensorT, gtTensorT, geTensorT, neTensorT, eqTensorT+  :: Dimensions d+  => Tensor d  -- ^ source tensor.+  -> Tensor d  -- ^ tensor to compare with.+  -> Tensor d  -- ^ new return tensor.+ltTensorT a b = asStatic $ Dynamic.ltTensorT (asDynamic a) (asDynamic b)+leTensorT a b = asStatic $ Dynamic.leTensorT (asDynamic a) (asDynamic b)+gtTensorT a b = asStatic $ Dynamic.gtTensorT (asDynamic a) (asDynamic b)+geTensorT a b = asStatic $ Dynamic.geTensorT (asDynamic a) (asDynamic b)+neTensorT a b = asStatic $ Dynamic.neTensorT (asDynamic a) (asDynamic b)+eqTensorT a b = asStatic $ Dynamic.eqTensorT (asDynamic a) (asDynamic b)++-- | mutate a tensor in-place with its numeric relation to the second tensor of the same size,+-- where 0 stands for false and 1 stands for true.+ltTensorT_, leTensorT_, gtTensorT_, geTensorT_, neTensorT_, eqTensorT_+  :: Tensor d  -- ^ source tensor to mutate inplace.+  -> Tensor d  -- ^ tensor to compare with.+  -> IO ()+ltTensorT_ a b = Dynamic.ltTensorT_ (asDynamic a) (asDynamic b)+leTensorT_ a b = Dynamic.leTensorT_ (asDynamic a) (asDynamic b)+gtTensorT_ a b = Dynamic.gtTensorT_ (asDynamic a) (asDynamic b)+geTensorT_ a b = Dynamic.geTensorT_ (asDynamic a) (asDynamic b)+neTensorT_ a b = Dynamic.neTensorT_ (asDynamic a) (asDynamic b)+eqTensorT_ a b = Dynamic.eqTensorT_ (asDynamic a) (asDynamic b)+
+ src/Torch/Indef/Static/Tensor/Math/Floating.hs view
@@ -0,0 +1,33 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Floating+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Floating where++import Numeric.Dimensions+import GHC.Int++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Math.Floating as Dynamic++-- | Static call to 'Dynamic.linspace'+linspace :: Dimensions d => HsReal -> HsReal -> Int64 -> (Tensor d)+linspace a b c = asStatic $ Dynamic.linspace a b c++-- | Static call to 'Dynamic.linspace_'+linspace_ :: Dimensions d => Tensor d -> HsReal -> HsReal -> Int64 -> IO ()+linspace_ r = Dynamic.linspace_ (asDynamic r)++-- | Static call to 'Dynamic.logspace'+logspace :: Dimensions d => HsReal -> HsReal -> Int64 -> (Tensor d)+logspace a b c = asStatic $ Dynamic.logspace a b c++-- | Static call to 'Dynamic.logspace_'+logspace_ :: Dimensions d => Tensor d -> HsReal -> HsReal -> Int64 -> IO ()+logspace_ r = Dynamic.logspace_ (asDynamic r)+
+ src/Torch/Indef/Static/Tensor/Math/Lapack.hs view
@@ -0,0 +1,322 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Lapack+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Lapack+  ( getri  , getri_+  , potrf  , potrf_+  , potri  , potri_+  , potrs  , potrs_+  , qr     , qr_     , _geqrf+  , geev   , geev_   , eig     , eig_+  , syev   , syev_   , symeig  , symeig_+  , gesv   , gesv_+  , gels   , gels_+  , gesvd  , gesvd_+  , gesvd2 , gesvd2_++  , Triangle(..), EigenReturn(..), ComputeSingularValues(..)+  ) where++import GHC.Int++import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor.Math.Lapack (Triangle(..), EigenReturn(..), ComputeSingularValues(..))+import qualified Torch.Indef.Dynamic.Tensor.Math.Lapack as Dynamic++-- |+-- Docs taken from MAGMA documentation at: http://icl.cs.utk.edu/projectsfiles/magma/doxygen/group__magma__getri.html+--+-- getri computes the inverse of a matrix using the LU factorization computed by+-- 'getrf'.+--+-- This method inverts @U@ and then computes @inv(A)@ by solving the system+-- @inv(A)*L = inv(U)@ for @inv(A)@.+--+-- Note that it is generally both faster and more accurate to use @gesv@, or+-- @getrf@ and @getrs@, to solve the system @AX = B@, rather than inverting the+-- matrix and multiplying to form @X = inv(A)*B@. Only in special instances+-- should an explicit inverse be computed with this routine.+getri :: Tensor d -> (Tensor d')+getri t = asStatic $ Dynamic.getri (asDynamic t)++-- | inplace version of 'getri'+getri_ :: Tensor d -> IO ()+getri_ t = Dynamic.getri_ (asDynamic t)++-- | Cholesky Decomposition of 2D @tensor A@. The matrix, @A@, has to be a+-- positive-definite and either symmetric or complex Hermitian.+--+-- The factorization has the form+--+-- @+--   A = U**T * U,   if UPLO = 'U', or+--   A = L  * L**T,  if UPLO = 'L',+-- @+--+-- where @U@ is an upper triangular matrix and @L@ is lower triangular.+potrf+  :: Tensor d   -- ^ matrix to decompose+  -> Triangle   -- ^ which triangle should be used.+  -> (Tensor d')+potrf s t = asStatic $ Dynamic.potrf (asDynamic s) t++-- | infix version of 'potrf'.+potrf_+  :: Tensor d  -- ^ matrix to decompose+  -> Triangle  -- ^ which triangle should be used.+  -> IO ()+potrf_ s = Dynamic.potrf_ (asDynamic s)++-- | Returns the inverse of 2D @tensor A@ given its Cholesky decomposition @chol@.+--+-- Square matrix @chol@ should be triangular.+--+-- 'Triangle' specifies matrix @chol@ as either upper or lower triangular.+potri :: Tensor d -> Triangle -> (Tensor d')+potri s t = asStatic $ Dynamic.potri (asDynamic s) t++-- | inplace version of 'potri'.+potri_ :: Tensor d -> Triangle -> IO ()+potri_ s t = Dynamic.potri_ (asDynamic s) t++-- | Returns the solution to linear system @AX = B@ using the Cholesky+-- decomposition @chol@ of 2D tensor @A@.+--+-- Square matrix @chol@ should be triangular; and, righthand side matrix @B@+-- should be of full rank.+--+-- 'Triangle' specifies matrix @chol@ as either upper or lower triangular.+-- /* Solve A*X = B with a symmetric positive definite matrix A using the Cholesky factorization */+potrs+  :: Tensor d    -- ^ Tensor @B@+  -> Tensor d'   -- ^ Cholesky decomposition @chol@+  -> Triangle   -- ^ which triangle to use (upper or lower)+  -> (Tensor d'')+potrs b chol t = asStatic $ Dynamic.potrs (asDynamic b) (asDynamic chol) t++-- | Inplace version of 'potri'. Mutating tensor B in place.+potrs_+  :: Tensor d    -- ^ Tensor @B@+  -> Tensor d'   -- ^ Cholesky decomposition @chol@+  -> Triangle   -- ^ which triangle to use (upper or lower)+  -> IO ()+potrs_ b chol t = Dynamic.potrs_ (asDynamic b) (asDynamic chol) t+++-- | Compute a QR decomposition of the matrix @x@: matrices @q@ and @r@ such that+-- @x = q * r@, with @q@ orthogonal and @r@ upper triangular. This returns the+-- thin (reduced) QR factorization.+--+-- Note that precision may be lost if the magnitudes of the elements of x are+-- large.+--+-- Note also that, while it should always give you a valid decomposition, it may+-- not give you the same one across platforms - it will depend on your LAPACK+-- implementation.+--+-- Note: Irrespective of the original strides, the returned matrix @q@ will be+-- transposed, i.e. with strides @1, m@ instead of @m, 1@.+qr :: Tensor d -> (Tensor d', Tensor d'')+qr x = (asStatic ra, asStatic rb)+  where (ra, rb) = Dynamic.qr (asDynamic x)++-- | Inplace version of 'qr'+qr_ :: (Tensor d, Tensor d') -> Tensor d'' -> IO ()+qr_ (q, r) x = Dynamic.qr_ (asDynamic q, asDynamic r) (asDynamic x)++-- | This is a low-level function for calling LAPACK directly. You'll generally+-- want to use 'qr' instead.+--+-- Computes a QR decomposition of @a@, but without constructing Q and R as+-- explicit separate matrices. Rather, this directly calls the underlying LAPACK+-- function @?geqrf@ which produces a sequence of "elementary reflectors". See+-- <https://software.intel.com/en-us/node/521004 LAPACK documentation from MKL>+-- for further details and <http://icl.cs.utk.edu/projectsfiles/magma/doxygen/group__magma__geqrf.html+-- for MAGMA documentation>.+--+-- Note that, because this is low-level code, hasktorch just calls Torch+-- directly.+_geqrf :: Tensor d -> Tensor d' -> Tensor d'' -> IO ()+_geqrf a b c = Dynamic._geqrf (asDynamic a) (asDynamic b) (asDynamic c)++-- | @(e, V) <- geev A@ returns eigenvalues and eigenvectors of a general real+-- square matrix @A@.+--+-- @A@ and @V@ are @m × m@ matrices and @e@ is an @m@-dimensional vector.+--+-- This function calculates all right eigenvalues (and vectors) of @A@ such that+-- @A = V diag(e) V@.+--+-- The 'EigenReturn' argument defines computation of eigenvectors or eigenvalues+-- only. It determines if only eigenvalues are computed or if both eigenvalues+-- and eigenvectors are computed.+--+-- The eigenvalues returned follow LAPACK convention and are returned as complex+-- (real/imaginary) pairs of numbers (@2 * m@ dimensional tensor).+--+-- Also called the "eig" fuction in torch.+geev+  :: Tensor d                      -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn                  -- ^ whether or not to return eigenvectors.+  -> (Tensor d', Maybe (Tensor d''))  -- ^ (e, V) standing for eigenvalues and eigenvectors+geev m er = (asStatic r, asStatic <$> mt)+  where (r, mt) = Dynamic.geev (asDynamic m) er++-- | alias to 'geev' to match Torch naming conventions.+eig = geev++-- | In-place version of 'geev'.+--+-- Note: Irrespective of the original strides, the returned matrix @V@ will be+-- transposed, i.e. with strides @1, m@ instead of @m, 1@.+geev_+  :: (Tensor d, Tensor d')  -- ^ (e, V) standing for eigenvalues and eigenvectors+  -> Tensor d''             -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn            -- ^ whether or not to return eigenvectors.+  -> IO ()+geev_ (e, v) m er = Dynamic.geev_ (asDynamic e, asDynamic v) (asDynamic m) er++-- | alias to 'geev_' to match Torch naming conventions.+eig_ = geev_+++-- | @(e, V) <- syev A@ returns eigenvalues and eigenvectors of a symmetric real matrix @A@.+--+-- @A@ and @V@ are @m × m@ matrices and @e@ is a @m@-dimensional vector.+--+-- This function calculates all eigenvalues (and vectors) of @A@ such that @A = V diag(e) V@.+--+-- The 'EigenReturn' argument defines computation of eigenvectors or eigenvalues only.+--+-- Since the input matrix @A@ is supposed to be symmetric, only one triangular portion+-- is used. The 'Triangle' argument indicates if this should be the upper or lower triangle.+syev+  :: Tensor d                      -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn                  -- ^ whether or not to return eigenvectors.+  -> Triangle                     -- ^ whether the upper or lower triangle should be used+  -> (Tensor d', Maybe (Tensor d''))  -- ^ (e, V) standing for eigenvalues and eigenvectors+syev m er tri = (asStatic r, asStatic <$> mt)+  where (r, mt) = Dynamic.syev (asDynamic m) er tri++-- | alias to 'syev' to match Torch naming conventions.+symeig = syev++-- | Inplace version of 'syev'+--+-- Note: Irrespective of the original strides, the returned matrix V will be transposed, i.e. with strides 1, m instead of m, 1.+syev_+  :: (Tensor d, Tensor d')  -- ^ (e, V) standing for eigenvalues and eigenvectors+  -> Tensor d''             -- ^ square matrix to get eigen{values/vectors} of.+  -> EigenReturn         -- ^ whether or not to return eigenvectors.+  -> Triangle            -- ^ whether the upper or lower triangle should be used+  -> IO ()+syev_ (e, v) m er tri = Dynamic.syev_ (asDynamic e, asDynamic v) (asDynamic m) er tri++-- | alias to 'syev' to match Torch naming conventions.+symeig_ = syev_++-- | @ (X, LU) <- gesv B A@ returns the solution of @AX = B@ and @LU@ contains @L@+-- and @U@ factors for @LU@ factorization of @A@.+--+-- @A@ has to be a square and non-singular matrix (a 2D tensor). @A@ and @LU@+-- are @m × m@, @X@ is @m × k@ and @B@ is @m × k@.+gesv+  :: Tensor '[m, k]                       -- ^ @B@+  -> Tensor '[m, m]                       -- ^ @A@+  -> (Tensor '[m, k], Tensor '[m, m])  -- ^ @(X, LU)@+gesv b a = (asStatic ra, asStatic rb)+  where (ra, rb) = Dynamic.gesv (asDynamic b) (asDynamic a)++-- | Inplace version of 'gesv'.+--+-- In this case @x@ and @lu@ will be used for temporary storage and returning the result.+--+--   * @x@ will contain the solution @X@.+--   * @lu@ will contain @L@ and @U@ factors for @LU@ factorization of @A@.+--+-- Note: Irrespective of the original strides, the returned matrices @x@ and @lu@ will be transposed,+-- i.e. with strides @1, m@ instead of @m, 1@.+gesv_+  :: (Tensor '[m, k], Tensor '[m, m])  -- ^ @(X, LU)@+  -> Tensor '[m, k]                    -- ^ @B@+  -> Tensor '[m, m]                    -- ^ @A@+  -> IO ()+gesv_ (x, lu) b a = Dynamic.gesv_ (asDynamic x, asDynamic lu) (asDynamic b) (asDynamic a)++-- | Solution of least squares and least norm problems for a full rank @m × n@ matrix @A@.+--+--   * If @n ≤ m@, then solve @||AX-B||_F@.+--   * If @n > m@, then solve @min ||X||_F@ such that @AX = B@.+--+-- On return, first @n@ rows of @x@ matrix contains the solution and the rest+-- contains residual information. Square root of sum squares of elements of each+-- column of @x@ starting at row @n + 1@ is the residual for corresponding column.+gels :: Tensor d -> Tensor d' -> (Tensor d'', Tensor d''')+gels b a = (asStatic ra, asStatic rb)+  where (ra, rb) = Dynamic.gels (asDynamic b) (asDynamic a)++-- | Inplace version of 'gels'.+--+-- Note: Irrespective of the original strides, the returned matrices @resb@ and+-- @resa@ will be transposed, i.e. with strides @1, m@ instead of @m, 1@.+gels_+  :: (Tensor d, Tensor d') -- ^ @(resb, resa)@+  -> Tensor d''            -- ^ @matrix b@+  -> Tensor d'''            -- ^ @matrix a@+  -> IO ()+gels_ (a, b) c d = Dynamic.gels_ (asDynamic a, asDynamic b) (asDynamic c) (asDynamic d)+++-- | @(U, S, V) <- svd A@ returns the singular value decomposition of a real+-- matrix @A@ of size @n × m@ such that @A = USV'*@.+--+-- @U@ is @n × n@, @S@ is @n × m@ and @V@ is @m × m@.+--+-- The 'ComputeSingularValues' argument represents the number of singular values+-- to be computed. 'SomeSVs' stands for "some" (FIXME: figure out what that means)+-- and 'AllSVs' stands for all.+gesvd+  :: Tensor d+  -> ComputeSingularValues+  -> (Tensor d', Tensor d'', Tensor d''')+gesvd m num = (asStatic ra, asStatic rb, asStatic rc)+  where (ra, rb, rc) = Dynamic.gesvd (asDynamic m) num++-- | Inplace version of 'gesvd'.+--+-- Note: Irrespective of the original strides, the returned matrix @U@ will be+-- transposed, i.e. with strides @1, n@ instead of @n, 1@.+gesvd_+  :: (Tensor d, Tensor d', Tensor d'') -- ^ (u, s, v)+  -> Tensor d'''                     -- ^ m+  -> ComputeSingularValues       -- ^ Whether to compute all or some of the singular values+  -> IO ()+gesvd_ (u, s, v) m num = Dynamic.gesvd_ (asDynamic u, asDynamic s, asDynamic v) (asDynamic m) num++-- | 'gesvd', computing @A = U*Σ*transpose(V)@.+--+-- NOTE: "'gesvd', computing @A = U*Σ*transpose(V)@." is only inferred documentation. This+-- documentation was made by stites, inferring from the description of the 'gesvd' docs at+-- <https://software.intel.com/en-us/mkl-developer-reference-c-gesvd the intel mkl+-- documentation>.+gesvd2+  :: Tensor d                                 -- ^ m+  -> ComputeSingularValues                   -- ^ Whether to compute all or some of the singular values+  -> (Tensor d', Tensor d'', Tensor d''', Tensor d'''') -- ^ (u, s, v, a)+gesvd2 m csv = (asStatic ra, asStatic rb, asStatic rc, asStatic rd)+  where (ra, rb, rc, rd) = Dynamic.gesvd2 (asDynamic m) csv++-- | Inplace version of 'gesvd2_'.+gesvd2_+  :: (Tensor d, Tensor d', Tensor d'', Tensor d''') -- ^ (u, s, v, a)+  -> Tensor d''''                              -- ^ m+  -> ComputeSingularValues                -- ^ Whether to compute all or some of the singular values+  -> IO ()+gesvd2_ (u, s, v, a) m = Dynamic.gesvd2_ (asDynamic u, asDynamic s, asDynamic v, asDynamic a) (asDynamic m)+
+ src/Torch/Indef/Static/Tensor/Math/Pairwise.hs view
@@ -0,0 +1,129 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Pairwise+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+module Torch.Indef.Static.Tensor.Math.Pairwise where++import Numeric.Dimensions+import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Dynamic.Tensor.Math.Pairwise as Dynamic++class Num real => Pairwise tensor real where+  -- | infix version of 'add'+  (^+) :: tensor -> real -> tensor+  -- | infix version of 'sub'+  (^-) :: tensor -> real -> tensor+  -- | infix version of 'mul'+  (^*) :: tensor -> real -> tensor+  -- | infix version of 'div'+  (^/) :: tensor -> real -> tensor++instance (Pairwise t0 r, Pairwise t1 r) => Pairwise (t0, t1) r where+  (a,b) ^+ v = (a ^+ v, b ^+ v)+  (a,b) ^- v = (a ^- v, b ^- v)+  (a,b) ^* v = (a ^* v, b ^* v)+  (a,b) ^/ v = (a ^/ v, b ^/ v)++infixl 7 ^*,^/+infixl 6 ^+,^-++instance Dimensions d => Pairwise (Tensor d) HsReal where+  (^+) = add+  (^-) = sub+  (^*) = mul+  (^/) = Torch.Indef.Static.Tensor.Math.Pairwise.div++-- | flipped version of '(^+)'+(+^) :: Pairwise ten real => real -> ten -> ten+(+^) = flip (^+)++-- | flipped version of '(^*)'+(*^) :: Pairwise ten real => real -> ten -> ten+(*^) = flip (^*)++-- | flipped version of '(^/)'+(/^) :: Pairwise ten real => real -> ten -> ten+(/^) = flip (^/)++-- | flipped version of '(^-)'+(-^) :: forall ten real . Pairwise ten real => real -> ten -> ten+(-^) v t = v +^ (negate (1::real) *^ t)++-- | static version of 'Dynamic.add_'+add_ :: Dimensions d => Tensor d -> HsReal -> IO ()+add_ t = Dynamic.add_ (asDynamic t)++-- | static version of 'Dynamic.add'+add :: Dimensions d => Tensor d -> HsReal -> Tensor d+add t v = asStatic $ Dynamic.add (asDynamic t) v++-- | static version of 'Dynamic.sub_'+sub_ :: Dimensions d => Tensor d -> HsReal -> IO ()+sub_ t = Dynamic.sub_ (asDynamic t)++-- | static version of 'Dynamic.sub'+sub :: Dimensions d => Tensor d -> HsReal -> Tensor d+sub t v = asStatic $ Dynamic.sub (asDynamic t) v++-- | static version of 'Dynamic.add_'+add_scaled_ :: Dimensions d => Tensor d -> HsReal -> HsReal -> IO ()+add_scaled_ t = Dynamic.add_scaled_ (asDynamic t)++-- | static version of 'Dynamic.sub_'+sub_scaled_ :: Dimensions d => Tensor d -> HsReal -> HsReal -> IO ()+sub_scaled_ t = Dynamic.sub_scaled_ (asDynamic t)++-- | static version of 'Dynamic.mul_'+mul_ :: Dimensions d => Tensor d -> HsReal -> IO ()+mul_ t = Dynamic.mul_ (asDynamic t)++-- | static version of 'Dynamic.mul'+mul :: Dimensions d => Tensor d -> HsReal -> Tensor d+mul t v = asStatic $ Dynamic.mul (asDynamic t) v++-- | static version of 'Dynamic.div_'+div_ t = Dynamic.div_ (asDynamic t)++-- | static version of 'Dynamic.div'+div t v = asStatic $ Dynamic.div (asDynamic t) v++-- | static version of 'Dynamic.lshift_'+lshift_ :: Dimensions d => Tensor d -> HsReal -> IO ()+lshift_ t = Dynamic.lshift_ (asDynamic t)++-- | static version of 'Dynamic.rshift_'+rshift_ :: Dimensions d => Tensor d -> HsReal -> IO ()+rshift_ t = Dynamic.rshift_ (asDynamic t)++-- | static version of 'Dynamic.fmod_'+fmod_ :: Dimensions d => Tensor d -> HsReal -> IO ()+fmod_ t = Dynamic.fmod_ (asDynamic t)++-- | static version of 'Dynamic.remainder_'+remainder_ :: Dimensions d => Tensor d -> HsReal -> IO ()+remainder_ t = Dynamic.remainder_ (asDynamic t)++-- | static version of 'Dynamic.bitand_'+bitand_ :: Dimensions d => Tensor d -> HsReal -> IO ()+bitand_ t = Dynamic.bitand_ (asDynamic t)++-- | static version of 'Dynamic.bitor_'+bitor_ :: Dimensions d => Tensor d -> HsReal -> IO ()+bitor_ t = Dynamic.bitor_ (asDynamic t)++-- | static version of 'Dynamic.bitxor_'+bitxor_ :: Dimensions d => Tensor d -> HsReal -> IO ()+bitxor_ t = Dynamic.bitxor_ (asDynamic t)++
+ src/Torch/Indef/Static/Tensor/Math/Pointwise.hs view
@@ -0,0 +1,117 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Pointwise+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.Tensor.Math.Pointwise where++import Numeric.Dimensions+import System.IO.Unsafe+import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Dynamic.Tensor.Math.Pointwise as Dynamic++-- | Static version of 'Dynamic.sign'+sign :: Tensor d -> Tensor d+sign t = asStatic $ Dynamic.sign (asDynamic t)++-- | Static version of 'Dynamic.clamp'+clamp :: Tensor d -> HsReal -> HsReal -> Tensor d+clamp t a b = asStatic $ Dynamic.clamp (asDynamic t) a b++-- | Multiply elements of tensor2 by the scalar value and add it to tensor1.+-- The number of elements must match, but sizes do not matter.+--+-- Static version of 'Dynamic.cadd'.+cadd+  :: Tensor d  -- ^ tensor1+  -> HsReal    -- ^ scale term to multiply againts tensor2+  -> Tensor d  -- ^ tensor2+  -> Tensor d+cadd t v b = asStatic $ Dynamic.cadd (asDynamic t) v (asDynamic b)++-- | infix version of 'cadd' on dimension 1+(^+^) a b = cadd a 1 b++-- | Static version of 'Dynamic.csub'+csub+  :: Tensor d  -- ^ tensor1+  -> HsReal    -- ^ scale term to multiply againts tensor2+  -> Tensor d  -- ^ tensor2+  -> Tensor d+csub t v b = asStatic $ Dynamic.csub (asDynamic t) v (asDynamic b)++-- | infix version of 'csub' on dimension 1+(^-^) a b = csub a 1 b++-- | Static version of 'Dynamic.cmul'+cmul :: Tensor d -> Tensor d -> Tensor d+cmul t1 t2 = asStatic $ Dynamic.cmul (asDynamic t1) (asDynamic t2)++-- | square a tensor+square t = cmul t t++-- | infix version of 'cmul'.+(^*^) a b = cmul a b++-- | Static version of 'Dynamic.cdiv'+cdiv :: Tensor d -> Tensor d -> Tensor d+cdiv t1 t2 = asStatic $ Dynamic.cdiv (asDynamic t1) (asDynamic t2)++-- | Infix version of 'cdiv'.+(^/^) a b = cdiv a b++-- | Static version of 'Dynamic.cpow'+cpow :: Tensor d -> Tensor d -> Tensor d+cpow t1 t2 = asStatic $ Dynamic.cpow (asDynamic t1) (asDynamic t2)++-- | Static version of 'Dynamic.clshift'+clshift :: Tensor d -> Tensor d -> Tensor d+clshift t1 t2 = asStatic $ Dynamic.clshift (asDynamic t1) (asDynamic t2)++-- | Static version of 'Dynamic.crshift'+crshift :: Tensor d -> Tensor d -> Tensor d+crshift t1 t2 = asStatic $ Dynamic.crshift (asDynamic t1) (asDynamic t2)++-- | Static version of 'Dynamic.cfmod'+cfmod :: Tensor d -> Tensor d -> Tensor d+cfmod t1 t2 = asStatic $ Dynamic.cfmod (asDynamic t1) (asDynamic t2)++-- | Static version of 'Dynamic.cremainder'+cremainder :: Tensor d -> Tensor d -> Tensor d+cremainder t1 t2 = asStatic $ Dynamic.cremainder (asDynamic t1) (asDynamic t2)++-- | Static version of 'Dynamic.cmax'+cmax :: Tensor d -> Tensor d -> Tensor d+cmax  a b = asStatic $ Dynamic.cmax (asDynamic a) (asDynamic b)++-- | Static version of 'Dynamic.cmin'+cmin :: Tensor d -> Tensor d -> Tensor d+cmin  a b = asStatic $ Dynamic.cmin (asDynamic a) (asDynamic b)++-- | Static version of 'Dynamic.cbitand'+cbitand :: Tensor d -> Tensor d -> Tensor d+cbitand  a b = asStatic $ Dynamic.cbitand (asDynamic a) (asDynamic b)++-- | Static version of 'Dynamic.cbitor'+cbitor :: Tensor d -> Tensor d -> Tensor d+cbitor  a b = asStatic $ Dynamic.cbitor (asDynamic a) (asDynamic b)++-- | Static version of 'Dynamic.cbitxor'+cbitxor :: Tensor d -> Tensor d -> Tensor d+cbitxor  a b = asStatic $ Dynamic.cbitxor (asDynamic a) (asDynamic b)++-- | Static version of 'Dynamic.addcmul'+addcmul  a v b c = asStatic $ Dynamic.addcmul (asDynamic a) v (asDynamic b) (asDynamic c)++-- | Static version of 'Dynamic.addcdiv'+addcdiv  a v b c = asStatic $ Dynamic.addcdiv (asDynamic a) v (asDynamic b) (asDynamic c)++++
+ src/Torch/Indef/Static/Tensor/Math/Pointwise/Floating.hs view
@@ -0,0 +1,130 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Pointwise.Floating+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Pointwise.Floating where++import Numeric.Dimensions+import GHC.Int+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Dynamic++import Torch.Indef.Types++-- | Static version of 'Dynamic.cinv'+cinv :: Dimensions d => Tensor d -> Tensor d+cinv t = asStatic $ Dynamic.cinv (asDynamic t)++-- | Static version of 'Dynamic.sigmoid'+sigmoid :: Dimensions d => Tensor d -> Tensor d+sigmoid  t = asStatic $ Dynamic.sigmoid (asDynamic t)++-- | Static version of 'Dynamic.log'+log :: Dimensions d => Tensor d -> Tensor d+log  t = asStatic $ Dynamic.log (asDynamic t)++-- | Static version of 'Dynamic.lgamma'+lgamma :: Dimensions d => Tensor d -> Tensor d+lgamma  t = asStatic $ Dynamic.lgamma (asDynamic t)++-- | Static version of 'Dynamic.log1p'+log1p :: Dimensions d => Tensor d -> Tensor d+log1p  t = asStatic $ Dynamic.log1p (asDynamic t)++-- | Static version of 'Dynamic.exp'+exp :: Dimensions d => Tensor d -> Tensor d+exp  t = asStatic $ Dynamic.exp (asDynamic t)++-- | Static version of 'Dynamic.cos'+cos :: Dimensions d => Tensor d -> Tensor d+cos  t = asStatic $ Dynamic.cos (asDynamic t)++-- | Static version of 'Dynamic.acos'+acos :: Dimensions d => Tensor d -> Tensor d+acos  t = asStatic $ Dynamic.acos (asDynamic t)++-- | Static version of 'Dynamic.cosh'+cosh :: Dimensions d => Tensor d -> Tensor d+cosh  t = asStatic $ Dynamic.cosh (asDynamic t)++-- | Static version of 'Dynamic.sin'+sin :: Dimensions d => Tensor d -> Tensor d+sin  t = asStatic $ Dynamic.sin (asDynamic t)++-- | Static version of 'Dynamic.asin'+asin :: Dimensions d => Tensor d -> Tensor d+asin  t = asStatic $ Dynamic.asin (asDynamic t)++-- | Static version of 'Dynamic.sinh'+sinh :: Dimensions d => Tensor d -> Tensor d+sinh  t = asStatic $ Dynamic.sinh (asDynamic t)++-- | Static version of 'Dynamic.tan'+tan :: Dimensions d => Tensor d -> Tensor d+tan  t = asStatic $ Dynamic.tan (asDynamic t)++-- | Static version of 'Dynamic.atan'+atan :: Dimensions d => Tensor d -> Tensor d+atan  t = asStatic $ Dynamic.atan (asDynamic t)++-- | Static version of 'Dynamic.tanh'+tanh :: Dimensions d => Tensor d -> Tensor d+tanh  t = asStatic $ Dynamic.tanh (asDynamic t)++-- | Static version of 'Dynamic.erf'+erf :: Dimensions d => Tensor d -> Tensor d+erf  t = asStatic $ Dynamic.erf (asDynamic t)++-- | Static version of 'Dynamic.erfinv'+erfinv :: Dimensions d => Tensor d -> Tensor d+erfinv  t = asStatic $ Dynamic.erfinv (asDynamic t)++-- | Static version of 'Dynamic.pow'+pow :: Dimensions d => Tensor d -> HsReal -> Tensor d+pow  t v = asStatic $ Dynamic.pow (asDynamic t) v++-- | Static version of 'Dynamic.tpow'+tpow :: Dimensions d => HsReal -> Tensor d -> Tensor d+tpow v t = asStatic $ Dynamic.tpow v (asDynamic t)++-- | Static version of 'Dynamic.sqrt'+sqrt :: Dimensions d => Tensor d -> Tensor d+sqrt  t = asStatic $ Dynamic.sqrt (asDynamic t)++-- | Static version of 'Dynamic.rsqrt'+rsqrt :: Dimensions d => Tensor d -> Tensor d+rsqrt  t = asStatic $ Dynamic.rsqrt (asDynamic t)++-- | Static version of 'Dynamic.ceil'+ceil :: Dimensions d => Tensor d -> Tensor d+ceil  t = asStatic $ Dynamic.ceil (asDynamic t)++-- | Static version of 'Dynamic.floor'+floor :: Dimensions d => Tensor d -> Tensor d+floor  t = asStatic $ Dynamic.floor (asDynamic t)++-- | Static version of 'Dynamic.round'+round :: Dimensions d => Tensor d -> Tensor d+round  t = asStatic $ Dynamic.round (asDynamic t)++-- | Static version of 'Dynamic.trunc'+trunc :: Dimensions d => Tensor d -> Tensor d+trunc  t = asStatic $ Dynamic.trunc (asDynamic t)++-- | Static version of 'Dynamic.frac'+frac :: Dimensions d => Tensor d -> Tensor d+frac  t = asStatic $ Dynamic.frac (asDynamic t)++-- | Static version of 'Dynamic.lerp'+lerp :: Dimensions d => Tensor d -> Tensor d -> HsReal -> Tensor d+lerp a b v = asStatic $ Dynamic.lerp (asDynamic a) (asDynamic b) v++-- | Static version of 'Dynamic.atan2'+atan2 :: Dimensions d => Tensor d -> Tensor d -> Tensor d+atan2 a b = asStatic $ Dynamic.atan2 (asDynamic a) (asDynamic b)+
+ src/Torch/Indef/Static/Tensor/Math/Pointwise/Signed.hs view
@@ -0,0 +1,49 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Pointwise.Signed+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Pointwise.Signed where++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math (constant)+import Torch.Indef.Static.Tensor.Math.Pointwise (sign, (^*^), (^-^), (^+^))+import qualified Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Dynamic++import Numeric.Dimensions+import System.IO.Unsafe++-- | Static call to 'Dynamic.abs_'+abs_ :: Tensor d -> IO ()+abs_ t = Dynamic.abs_ (asDynamic t)++-- | Static call to 'Dynamic.neg_'+neg_ :: Tensor d -> IO ()+neg_ t = Dynamic.neg_ (asDynamic t)++-- | Static call to 'Dynamic.neg'+neg :: Dimensions d => Tensor d -> Tensor d+neg t = asStatic $ Dynamic.neg (asDynamic t)++-- | Static call to 'Dynamic.abs'+abs :: Dimensions d => Tensor d -> Tensor d+abs t = asStatic $ Dynamic.abs (asDynamic t)+++instance Dimensions d => Num (Tensor d) where+  (+) = (^+^)++  (-) = (^-^)++  (*) = (^*^)++  abs = Torch.Indef.Static.Tensor.Math.Pointwise.Signed.abs++  signum = sign++  fromInteger = constant . fromIntegral
+ src/Torch/Indef/Static/Tensor/Math/Random/TH.hs view
@@ -0,0 +1,32 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Random.TH+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- FIXME: copy-paste, or switch documentation to preference Static modules.+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Random.TH where++import Numeric.Dimensions++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Math.Random.TH as Dynamic+import qualified Torch.Types.TH as TH++-- | Statically typed version of 'Dynamic._rand'.+_rand :: Dimensions d => Tensor d -> Generator -> TH.LongStorage -> IO ()+_rand t = Dynamic._rand (asDynamic t)++-- | Statically typed version of 'Dynamic._randn'.+_randn :: Dimensions d => Tensor d -> Generator -> TH.LongStorage -> IO ()+_randn t = Dynamic._randn (asDynamic t)++-- | Statically typed version of 'Dynamic._randperm'.+_randperm :: Dimensions d => Tensor d -> Generator -> Integer -> IO ()+_randperm t = Dynamic._randperm (asDynamic t)++
+ src/Torch/Indef/Static/Tensor/Math/Reduce.hs view
@@ -0,0 +1,181 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Reduce+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.Tensor.Math.Reduce+  ( minall+  , maxall+  , medianall+  , sumall+  , prodall++  , Torch.Indef.Static.Tensor.Math.Reduce.min+  , Torch.Indef.Static.Tensor.Math.Reduce.max+  , median++  , minIndex1d    , min1d+  , maxIndex1d    , max1d, max2d0, max2d1+  , medianIndex1d , median1d++  , Torch.Indef.Static.Tensor.Math.Reduce.sum, rowsum, colsum+  , _prod+  ) where++import Numeric.Dimensions+import Data.Coerce+import System.IO.Unsafe+import Data.Singletons.Prelude.List hiding (All, type (++), Length)+import Data.Singletons.Prelude.Ord+import GHC.TypeLits+++import Data.Maybe (fromJust)+import Torch.Indef.Index+import Torch.Indef.Static.Tensor+import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Math.Reduce as Dynamic+++-- | Static call to 'Dynamic.minall'+minall :: Tensor d -> HsReal+minall t = Dynamic.minall (asDynamic t)++-- | Static call to 'Dynamic.maxall'+maxall :: Tensor d -> HsReal+maxall t = Dynamic.maxall (asDynamic t)++-- | Static call to 'Dynamic.medianall'+medianall :: Tensor d -> HsReal+medianall t = Dynamic.medianall (asDynamic t)++-- | Static call to 'Dynamic.sumall'+sumall :: Tensor d -> HsAccReal+sumall t = Dynamic.sumall (asDynamic t)++-- | Static call to 'Dynamic.prodall'+prodall :: Tensor d -> HsAccReal+prodall t = Dynamic.prodall (asDynamic t)++-- | Static call to 'Dynamic.max'+max+  :: forall d n ix rs ls+  .  All Dimensions '[d, rs ++ '[1] ++ ls]+  => All KnownNat '[n, ix]+  => All KnownDim '[n, ix]+  => (Length d > ix) ~ True+  => '(rs, n:+ls) ~ (SplitAt ix d)+  => Tensor d+  -> Dim ix+  -> KeepDim+  -> (Tensor (rs ++ '[1] ++ ls), Maybe (IndexTensor (rs ++ '[1] ++ ls)))+max = withKeepDim Dynamic._max++-- | Static call to 'Dynamic.min'+min+  :: forall d n ix rs ls+  .  All Dimensions '[d, rs ++ '[1] ++ ls]+  => All KnownNat '[n, ix]+  => All KnownDim '[n, ix]+  => (Length d > ix) ~ True+  => '(rs, n:+ls) ~ (SplitAt ix d)+  => Tensor d+  -> Dim ix+  -> KeepDim+  -> (Tensor (rs ++ '[1] ++ ls), Maybe (IndexTensor (rs ++ '[1] ++ ls)))+min = withKeepDim Dynamic._min++-- | Static call to 'Dynamic.median'+median+  :: forall d n ix rs ls+  .  All Dimensions '[d, rs ++ '[1] ++ ls]+  => All KnownNat '[n, ix]+  => All KnownDim '[n, ix]+  => (Length d > ix) ~ True+  => '(rs, n:+ls) ~ (SplitAt ix d)+  => Tensor d+  -> Dim ix+  -> KeepDim+  -> (Tensor (rs ++ '[1] ++ ls), Maybe (IndexTensor (rs ++ '[1] ++ ls)))+median = withKeepDim Dynamic._median++-- | Convenience method for 'max' over vectors+max1d :: (KnownNat n, KnownDim n) => Tensor '[n] -> KeepDim -> (Tensor '[1], Maybe (IndexTensor '[1]))+max1d t = Torch.Indef.Static.Tensor.Math.Reduce.max t (dim :: Dim 0)++-- | Convenience method for 'max' over matricies+max2d0 :: (KnownDim m, KnownNat n, KnownDim n) => Tensor '[n, m] -> KeepDim -> (Tensor '[1, m], Maybe (IndexTensor '[1, m]))+max2d0 t = Torch.Indef.Static.Tensor.Math.Reduce.max t (dim :: Dim 0)++-- | Convenience method for 'max' over matricies+max2d1 :: (KnownDim n, KnownDim m, KnownNat m) => Tensor '[n, m] -> KeepDim -> (Tensor '[n, 1], Maybe (IndexTensor '[n, 1]))+max2d1 t = Torch.Indef.Static.Tensor.Math.Reduce.max t (dim :: Dim 1)++-- | Convenience method for 'min'+min1d :: (KnownNat n, KnownDim n) => Tensor '[n] -> KeepDim -> (Tensor '[1], Maybe (IndexTensor '[1]))+min1d t = Torch.Indef.Static.Tensor.Math.Reduce.min t (dim :: Dim 0)++-- | Convenience method for 'median'+median1d :: (KnownNat n, KnownDim n) => Tensor '[n] -> KeepDim -> (Tensor '[1], Maybe (IndexTensor '[1]))+median1d t = median t (dim :: Dim 0)++-- | Convenience method for 'max'+maxIndex1d t = fromJust . snd $ max1d t keep++-- | Convenience method for 'min'+minIndex1d t = fromJust . snd $ min1d t keep++-- | Convenience method for 'median'+medianIndex1d t = fromJust . snd $ median1d t keep++-- | Static call to 'Dynamic._prod'+_prod :: Tensor d -> Tensor d -> Word -> Maybe KeepDim -> IO ()+_prod r t = Dynamic._prod (asDynamic r) (asDynamic t)++-------------------------------------------------------------------------------++withKeepDim+  :: forall d n ix rs ls+  .  All Dimensions '[d, rs ++ '[1] ++ ls]+  => All KnownNat '[n, ix]+  => All KnownDim '[n, ix]+  => (Length d > ix) ~ True+  => '(rs, n:+ls) ~ (SplitAt ix d)+  => ((Dynamic, IndexDynamic) -> Dynamic -> Word -> Maybe KeepDim -> IO ())+  -> Tensor d+  -> Dim ix+  -> KeepDim+  -> (Tensor (rs ++ '[1] ++ ls), Maybe (IndexTensor (rs ++ '[1] ++ ls)))+withKeepDim _fn t d k = unsafePerformIO $ do+  let ret = new+  let ix :: IndexTensor (rs ++ '[1] ++ ls) = newIx+  _fn (asDynamic ret, longAsDynamic ix) (asDynamic t) (dimVal d) (Just k)+  pure (ret, if coerce k then Just ix else Nothing)+{-# NOINLINE withKeepDim #-}+++-- | Static call to 'Dynamic.sum'+sum :: Dimensions d' => Tensor d -> Word -> KeepDim -> Tensor d'+sum t d k = unsafePerformIO $ do+  let r = new+  Dynamic._sum (asDynamic r) (asDynamic t) d (Just k)+  pure r+{-# NOINLINE sum #-}++-- | convenience function for 'sum'+rowsum :: (All KnownDim '[r,c]) => Tensor '[r, c] -> (Tensor '[1, c])+rowsum t = Torch.Indef.Static.Tensor.Math.Reduce.sum t 0 keep++-- | convenience function for 'sum'+colsum :: (All KnownDim '[r,c]) => Tensor '[r, c] -> (Tensor '[r, 1])+colsum t = Torch.Indef.Static.Tensor.Math.Reduce.sum t 0 keep++
+ src/Torch/Indef/Static/Tensor/Math/Reduce/Floating.hs view
@@ -0,0 +1,77 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Reduce.Floating+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Reduce.Floating where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Dynamic++-- | Returns the @p@-norm of @x - y@.+dist+  :: Tensor d      -- ^ tensor @x@+  -> Tensor d      -- ^ tensor @y@+  -> HsReal        -- ^ @p@+  -> HsAccReal+dist r t = Dynamic.dist (asDynamic r) (asDynamic t)++-- | Get the variance over a tensor in the specified dimension. The 'Bool'+-- parameter specifies whether the standard deviation should be used with+-- @n-1@ or @n@. 'False' normalizes by @n-1@, while 'True' normalizes @n@.+var :: Tensor d+  -> Word -- ^ dimension to operate over+  -> KeepDim -> Bool -> (Tensor d')+var r a b c = asStatic $ Dynamic.var (asDynamic r) a b c++-- | Returns the variance of all elements.+varall  :: Tensor d -> Int -> (HsAccReal)+varall t = Dynamic.varall (asDynamic t)++-- | Performs the @std@ operation over the specified dimension. The 'Bool'+-- parameter specifies whether the standard deviation should be used with+-- @n-1@ or @n@. 'False' normalizes by @n-1@, while 'True' normalizes @n@.+std+  :: (Tensor d)+  -> Word -- ^ dimension to operate over+  -> KeepDim+  -> Bool+  -> (Tensor d')+std t a b c = asStatic $ Dynamic.std (asDynamic t) a b c++-- | Returns the standard deviation of all elements.+stdall  :: Tensor d -> Int -> (HsAccReal)+stdall t = Dynamic.stdall (asDynamic t)++-- | Static 'Dynamic.renorm'+renorm  :: Tensor d -> HsReal -> Int -> HsReal -> (Tensor d')+renorm t a b c = asStatic $ Dynamic.renorm (asDynamic t) a b c++-- | Static 'Dynamic.norm'+norm :: Tensor d -> HsReal+  -> Word -- ^ dimension to operate over+  -> (Tensor d')+norm t a b = asStatic $ Dynamic.norm (asDynamic t) a b++-- | Returns the @p@-norm of all elements.+normall+  :: Tensor d  -- ^ tensor of values to norm over+  -> HsReal   -- ^ @p@+  -> HsAccReal+normall t = Dynamic.normall (asDynamic t)++-- | Static 'Dynamic.mean+mean :: Tensor d+  -> Word -- ^ dimension to operate over+  -> (Tensor d')+mean r a = asStatic $ Dynamic.mean (asDynamic r) a++-- | Returns the mean of all elements.+meanall :: Tensor d -> HsAccReal+meanall t = Dynamic.meanall (asDynamic t)++
+ src/Torch/Indef/Static/Tensor/Math/Scan.hs view
@@ -0,0 +1,22 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Math.Scan+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Math.Scan where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Math.Scan as Dynamic++-- | Static call to 'Dynamic._cumsum'+_cumsum :: Tensor d -> Tensor d -> Word -> IO ()+_cumsum r t = Dynamic._cumsum (asDynamic r) (asDynamic t)++-- | Static call to 'Dynamic._cumprod'+_cumprod :: Tensor d -> Tensor d -> Word -> IO ()+_cumprod r t = Dynamic._cumprod (asDynamic r) (asDynamic t)+
+ src/Torch/Indef/Static/Tensor/Mode.hs view
@@ -0,0 +1,18 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Mode+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Mode where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Mode as Dynamic++-- | Static call to 'Dynamic._mode'+_mode :: (Tensor d, IndexTensor '[n]) -> Tensor d -> Word -> Maybe KeepDim -> IO ()+_mode (r, ix) t = Dynamic._mode (asDynamic r, longAsDynamic ix) (asDynamic t)+
+ src/Torch/Indef/Static/Tensor/Random/TH.hs view
@@ -0,0 +1,218 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Random.TH+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+module Torch.Indef.Static.Tensor.Random.TH+  ( _random                 , random+  , _clampedRandom          , clampedRandom+  , _cappedRandom           , cappedRandom+  , _geometric              , geometric+  , _bernoulli              , bernoulli+  , _bernoulli_FloatTensor  , bernoulli_FloatTensor+  , _bernoulli_DoubleTensor , bernoulli_DoubleTensor+  , _uniform                , uniform+  , _normal                 , normal+  , _normal_means           , normal_means+  , _normal_stddevs         , normal_stddevs+  , _normal_means_stddevs   , normal_means_stddevs+  , _exponential            , exponential+  , _standard_gamma         , standard_gamma+  , _cauchy                 , cauchy+  , _logNormal              , logNormal+  , _multinomial+  , _multinomialAliasSetup+  , _multinomialAliasDraw++  , OpenUnit   , Dynamic.openUnit   , Dynamic.openUnitValue+  , ClosedUnit , Dynamic.closedUnit , Dynamic.closedUnitValue+  , Positive   , Dynamic.positive   , Dynamic.positiveValue+  , Ord2Tuple  , Dynamic.ord2Tuple  , Dynamic.ord2TupleValue++  , multivariate_normal+  ) where+++import Numeric.Dimensions+import Control.Monad+import GHC.Word+import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.Pointwise+import Torch.Indef.Static.Tensor.Math.Blas+import Torch.Indef.Dynamic.Tensor.Random.TH (Ord2Tuple, Positive, ClosedUnit, OpenUnit)+import qualified Torch.Indef.Dynamic.Tensor.Random.TH as Dynamic+import qualified Torch.Types.TH as TH+import qualified Torch.Sig.Tensor.Random.TH as Sig+import qualified Torch.Sig.Types as Sig+import qualified Torch.Sig.Types.Global as Sig++-- | Static call to 'Dynamic._random'+_random :: Dimensions d => Tensor d -> Generator -> IO ()+_random r = Dynamic._random (asDynamic r)++-- | Static call to 'Dynamic._clampedRandom'+_clampedRandom :: Dimensions d => Tensor d -> Generator -> Ord2Tuple Integer -> IO ()+_clampedRandom r = Dynamic._clampedRandom (asDynamic r)++-- | Static call to 'Dynamic._cappedRandom'+_cappedRandom :: Dimensions d => Tensor d -> Generator -> Integer -> IO ()+_cappedRandom r = Dynamic._cappedRandom (asDynamic r)++-- | Static call to 'Dynamic._geometric'+_geometric :: Dimensions d => Tensor d -> Generator -> HsAccReal -> IO ()+_geometric r = Dynamic._geometric (asDynamic r)++-- | Static call to 'Dynamic._bernoulli'+_bernoulli :: Dimensions d => Tensor d -> Generator -> HsAccReal -> IO ()+_bernoulli r = Dynamic._bernoulli (asDynamic r)++-- | Static call to 'Dynamic._bernoulli_FloatTensor'+_bernoulli_FloatTensor :: Dimensions d => Tensor d -> Generator -> TH.FloatTensor d -> IO ()+_bernoulli_FloatTensor r g f = Dynamic._bernoulli_FloatTensor (asDynamic r) g (TH.floatAsDynamic f)++-- | Static call to 'Dynamic._bernoulli_DoubleTensor'+_bernoulli_DoubleTensor :: Dimensions d => Tensor d -> Generator -> TH.DoubleTensor d -> IO ()+_bernoulli_DoubleTensor r g d = Dynamic._bernoulli_DoubleTensor (asDynamic r) g (TH.doubleAsDynamic d)++-- | Static call to 'Dynamic._uniform'+_uniform :: Dimensions d => Tensor d -> Generator -> Ord2Tuple HsAccReal -> IO ()+_uniform r = Dynamic._uniform (asDynamic r)++-- | Static call to 'Dynamic._normal'+_normal :: Dimensions d => Tensor d -> Generator -> HsAccReal -> Positive HsAccReal -> IO ()+_normal r = Dynamic._normal (asDynamic r)++-- | Static call to 'Dynamic._normal_means'+_normal_means :: Dimensions d => Tensor d -> Generator -> Tensor d -> Positive HsAccReal -> IO ()+_normal_means r g a = Dynamic._normal_means (asDynamic r) g (asDynamic a)++-- | Static call to 'Dynamic._normal_stddevs'+_normal_stddevs :: Dimensions d => Tensor d -> Generator -> HsAccReal -> Tensor d -> IO ()+_normal_stddevs r g v a = Dynamic._normal_stddevs (asDynamic r) g v (asDynamic a)++-- | Static call to 'Dynamic._normal_means_stddevs'+_normal_means_stddevs :: Dimensions d => Tensor d -> Generator -> Tensor d -> Tensor d -> IO ()+_normal_means_stddevs r g a b = Dynamic._normal_means_stddevs (asDynamic r) g (asDynamic a) (asDynamic b)++-- | Static call to 'Dynamic._exponential'+_exponential :: Dimensions d => Tensor d -> Generator -> HsAccReal -> IO ()+_exponential r = Dynamic._exponential (asDynamic r)++-- | Static call to 'Dynamic._standard_gamma'+_standard_gamma :: Dimensions d => Tensor d -> Generator -> Tensor d -> IO ()+_standard_gamma r g t = Dynamic._standard_gamma (asDynamic r) g (asDynamic t)++-- | Static call to 'Dynamic._cauchy'+_cauchy :: Dimensions d => Tensor d -> Generator -> HsAccReal -> HsAccReal -> IO ()+_cauchy r = Dynamic._cauchy (asDynamic r)++-- | Static call to 'Dynamic._logNormal'+_logNormal :: Dimensions d => Tensor d -> Generator -> HsAccReal -> Positive HsAccReal -> IO ()+_logNormal r = Dynamic._logNormal (asDynamic r)++-- | Static call to 'Dynamic._multinomial'+_multinomial :: Dimensions d => IndexTensor d -> Generator -> Tensor d -> Int -> Int -> IO ()+_multinomial r g t = Dynamic._multinomial (longAsDynamic r) g (asDynamic t)++-- | Static call to 'Dynamic._multinomialAliasSetup'+_multinomialAliasSetup :: Dimensions d => Tensor d -> IndexTensor d -> Tensor d -> IO ()+_multinomialAliasSetup r g t = Dynamic._multinomialAliasSetup (asDynamic r) (longAsDynamic g) (asDynamic t)++-- | Static call to 'Dynamic._multinomialAliasDraw'+_multinomialAliasDraw :: Dimensions d => IndexTensor d -> Generator -> IndexTensor d -> Tensor d -> IO ()+_multinomialAliasDraw r g a b = Dynamic._multinomialAliasDraw (longAsDynamic r) g (longAsDynamic a) (asDynamic b)++-- | Static call to 'Dynamic.random'+random :: forall d . Dimensions d => Generator -> IO (Tensor d)+random g = asStatic <$> Dynamic.random (dims :: Dims d) g++-- | Static call to 'Dynamic.clampedRandom'+clampedRandom :: forall d . (Dimensions d) => Generator -> Ord2Tuple Integer -> IO (Tensor d)+clampedRandom g a = asStatic <$> Dynamic.clampedRandom (dims :: Dims d) g a++-- | Static call to 'Dynamic.cappedRandom'+cappedRandom :: forall d . (Dimensions d) => Generator -> Word64 -> IO (Tensor d)+cappedRandom g a = asStatic <$> Dynamic.cappedRandom (dims :: Dims d) g a++-- | Static call to 'Dynamic.geometric'+geometric :: forall d . (Dimensions d) => Generator -> OpenUnit HsAccReal -> IO (Tensor d)+geometric g a = asStatic <$> Dynamic.geometric (dims :: Dims d) g a++-- | Static call to 'Dynamic.bernoulli'+bernoulli :: forall d . (Dimensions d) => Generator -> ClosedUnit HsAccReal -> IO (Tensor d)+bernoulli g a = asStatic <$> Dynamic.bernoulli (dims :: Dims d) g a++-- | Static call to 'Dynamic.bernoulli_FloatTensor'+bernoulli_FloatTensor :: forall d . (Dimensions d) => Generator -> TH.FloatTensor d -> IO (Tensor d)+bernoulli_FloatTensor g a = asStatic <$> Dynamic.bernoulli_FloatTensor (dims :: Dims d) g (TH.floatAsDynamic a)++-- | Static call to 'Dynamic.bernoulli_DoubleTensor'+bernoulli_DoubleTensor :: forall d . (Dimensions d) => Generator -> TH.DoubleTensor d -> IO (Tensor d)+bernoulli_DoubleTensor g a = asStatic <$> Dynamic.bernoulli_DoubleTensor (dims :: Dims d) g (TH.doubleAsDynamic a)++-- | Static call to 'Dynamic.uniform'+uniform :: forall d . (Dimensions d) => Generator -> Ord2Tuple HsAccReal -> IO (Tensor d)+uniform g a = asStatic <$> Dynamic.uniform (dims :: Dims d) g a++-- | Static call to 'Dynamic.normal'+normal :: forall d . (Dimensions d) => Generator -> HsAccReal -> Positive HsAccReal -> IO (Tensor d)+normal g a b = asStatic <$> Dynamic.normal (dims :: Dims d) g a b++-- | Static call to 'Dynamic.normal_means'+normal_means :: forall d . (Dimensions d) => Generator -> Tensor d -> Positive HsAccReal -> IO (Tensor d)+normal_means g m b = asStatic <$> Dynamic.normal_means (dims :: Dims d) g (asDynamic m) b++-- | Static call to 'Dynamic.normal_stddevs'+normal_stddevs :: forall d . (Dimensions d) => Generator -> HsAccReal -> Tensor d -> IO (Tensor d)+normal_stddevs g a s = asStatic <$> Dynamic.normal_stddevs (dims :: Dims d) g a (asDynamic s)++-- | Static call to 'Dynamic.normal_means_stddevs'+normal_means_stddevs :: forall d . (Dimensions d) => Generator -> Tensor d -> Tensor d -> IO (Tensor d)+normal_means_stddevs g m s = asStatic <$> Dynamic.normal_means_stddevs (dims :: Dims d) g (asDynamic m) (asDynamic s)++-- | Static call to 'Dynamic.exponential'+exponential :: forall d . (Dimensions d) => Generator -> HsAccReal -> IO (Tensor d)+exponential g a = asStatic <$> Dynamic.exponential (dims :: Dims d) g a++-- | Static call to 'Dynamic.standard_gamma'+standard_gamma :: forall d . (Dimensions d) => Generator -> Tensor d -> IO (Tensor d)+standard_gamma g a = asStatic <$> Dynamic.standard_gamma (dims :: Dims d) g (asDynamic a)++-- | Static call to 'Dynamic.cauchy'+cauchy :: forall d . (Dimensions d) => Generator -> HsAccReal -> HsAccReal -> IO (Tensor d)+cauchy g a b = asStatic <$> Dynamic.cauchy (dims :: Dims d) g a b++-- | Static call to 'Dynamic.logNormal'+logNormal :: forall d . (Dimensions d) => Generator -> HsAccReal -> Positive HsAccReal -> IO (Tensor d)+logNormal g a b = asStatic <$> Dynamic.logNormal (dims :: Dims d) g a b++-- ========================================================================= --+-- * Custom functions++-- | find the multivariate normal distribution given @mu@, an @eigenvector@ and @eigenvalues@.+multivariate_normal+  :: forall n p . (All KnownDim '[n,p])+  => Generator+  -> Tensor '[p]       -- ^ mu+  -> Tensor '[p, p]    -- ^ eigenvec+  -> Tensor '[p]       -- ^ eigenval+  -> IO (Tensor '[n, p])+multivariate_normal g mu eigvec eigval = go (transpose2d eigvec) (diag1d eigval) (expand2d mu)+  <$> normal g 0 p1+ where+  Just p1 = Dynamic.positive 1++  go :: Tensor '[p, p] -> Tensor '[p, p] -> Tensor '[n, p] -> Tensor '[p, n] -> Tensor '[n, p]+  go evec' eval' offset samps = transpose2d (y !*! samps) ^+^ offset+    where+      x = evec' !*! eval'+      y = x !*! eigvec++
+ src/Torch/Indef/Static/Tensor/Random/THC.hs view
@@ -0,0 +1,125 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Random.THC+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Random.THC+  ( random+  , clampedRandom+  , cappedRandom+  , bernoulli+  , bernoulli_DoubleTensor+  , geometric+  , uniform+  , normal+  , normal_means+  , normal_stddevs+  , normal_means_stddevs+  , logNormal+  , exponential+  , cauchy+  , rand+  , randn+  , _multinomial+  , _multinomialAliasSetup+  , _multinomialAliasDraw+++  , OpenUnit, openUnit, openUnitValue+  , ClosedUnit, closedUnit, closedUnitValue+  , Positive, positive, positiveValue+  , Ord2Tuple, ord2Tuple, ord2TupleValue+  ) where+++import Numeric.Dimensions++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Dynamic.Tensor.Random.THC as Dynamic+import qualified Torch.Types.TH as TH+import Torch.Indef.Dynamic.Tensor.Random.TH+  ( OpenUnit, openUnit, openUnitValue+  , ClosedUnit, closedUnit, closedUnitValue+  , Positive, positive, positiveValue+  , Ord2Tuple, ord2Tuple, ord2TupleValue+  )+++-- | Static call to 'Dynamic.random'+random :: (Dimensions d) => IO (Tensor d)+random = let d = new in Dynamic._random (asDynamic d) >> pure d++-- | Static call to 'Dynamic.clampedRandom'+clampedRandom :: (Dimensions d) => Integer -> Integer -> IO (Tensor d)+clampedRandom a b = let d = new in Dynamic._clampedRandom (asDynamic d) a b >> pure d++-- | Static call to 'Dynamic.cappedRandom'+cappedRandom :: (Dimensions d) => Integer -> IO (Tensor d)+cappedRandom a = let d = new in Dynamic._cappedRandom (asDynamic d) a >> pure d++-- | Static call to 'Dynamic.bernoulli'+bernoulli :: (Dimensions d) => HsAccReal -> IO (Tensor d)+bernoulli a = let d = new in Dynamic._bernoulli (asDynamic d) a >> pure d++-- | Static call to 'Dynamic.geometric'+geometric :: (Dimensions d) => HsAccReal -> IO (Tensor d)+geometric a = let d = new in Dynamic._geometric (asDynamic d) a >> pure d++-- | Static call to 'Dynamic.bernoulli_DoubleTensor'+bernoulli_DoubleTensor :: (Dimensions d) => Tensor d -> IO (Tensor d)+bernoulli_DoubleTensor t = let r = new in Dynamic._bernoulli_DoubleTensor (asDynamic r) (asDynamic t) >> pure r++-- | Static call to 'Dynamic.uniform'+uniform :: Dimensions d => Ord2Tuple HsAccReal -> IO (Tensor d)+uniform tup = let d = new in Dynamic._uniform (asDynamic d) tup >> pure d++-- | Static call to 'Dynamic.normal'+normal :: Dimensions d => HsAccReal -> Positive HsAccReal -> IO (Tensor d)+normal a b = let d = new in Dynamic._normal (asDynamic d) a b >> pure d++-- | Static call to 'Dynamic.normal_means'+normal_means :: (Dimensions d) => Tensor d -> Positive HsAccReal -> IO (Tensor d)+normal_means a b = let d = new in Dynamic._normal_means (asDynamic d) (asDynamic a) b >> pure d++-- | Static call to 'Dynamic.normal_stddevs'+normal_stddevs :: (Dimensions d) => HsAccReal -> Tensor d -> IO (Tensor d)+normal_stddevs a b = let d = new in Dynamic._normal_stddevs (asDynamic d) a (asDynamic b) >> pure d++-- | Static call to 'Dynamic.normal_means_stddevs'+normal_means_stddevs :: (Dimensions d) => Tensor d -> Tensor d -> IO (Tensor d)+normal_means_stddevs a b = let d = new in+  Dynamic._normal_means_stddevs (asDynamic d) (asDynamic a) (asDynamic b) >> pure d++-- | Static call to 'Dynamic.logNormal'+logNormal :: Dimensions d => HsAccReal -> Positive HsAccReal -> IO (Tensor d)+logNormal a b = let d = new in Dynamic._logNormal (asDynamic d) a b >> pure d++-- | Static call to 'Dynamic.exponential'+exponential :: (Dimensions d) => HsAccReal -> IO (Tensor d)+exponential a = let d = new in Dynamic._exponential (asDynamic d) a >> pure d++-- | Static call to 'Dynamic.cauchy'+cauchy :: (Dimensions d) => HsAccReal -> HsAccReal -> IO (Tensor d)+cauchy a b = let d = new in Dynamic._cauchy (asDynamic d) a b >> pure d++-- | Static call to 'Dynamic.rand'+rand :: (Dimensions d) => TH.LongStorage -> IO (Tensor d)+rand a = let d = new in Dynamic._rand (asDynamic d) a >> pure d++-- | Static call to 'Dynamic.randn'+randn :: (Dimensions d) => TH.LongStorage -> IO (Tensor d)+randn a = let d = new in Dynamic._randn (asDynamic d) a >> pure d++-- | Static call to 'Dynamic._multinomial'+_multinomial d t = Dynamic._multinomial (longAsDynamic d) (asDynamic t)++-- | Static call to 'Dynamic._multinomialAliasSetup'+_multinomialAliasSetup d l t = Dynamic._multinomialAliasSetup (asDynamic d) (longAsDynamic l) (asDynamic t)++-- | Static call to 'Dynamic._multinomialAliasDraw'+_multinomialAliasDraw d a b = Dynamic._multinomialAliasDraw (longAsDynamic d) (longAsDynamic a) (asDynamic b)
+ src/Torch/Indef/Static/Tensor/ScatterGather.hs view
@@ -0,0 +1,30 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.ScatterGather+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.ScatterGather where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.ScatterGather as Dynamic++-- | Static call to 'Dynamic._gather'+_gather :: Tensor d -> Tensor d -> Word -> IndexTensor '[n] -> IO ()+_gather r src d ix = Dynamic._gather (asDynamic r) (asDynamic src) d (longAsDynamic ix)++-- | Static call to 'Dynamic._scatter'+_scatter :: Tensor d -> Word -> IndexTensor '[n] -> Tensor d -> IO ()+_scatter r d ix src = Dynamic._scatter (asDynamic r) d (longAsDynamic ix) (asDynamic src)++-- | Static call to 'Dynamic._scatterAdd'+_scatterAdd   :: Tensor d -> Word -> IndexTensor '[n] -> Tensor d -> IO ()+_scatterAdd r d ix src = Dynamic._scatterAdd (asDynamic r) d (longAsDynamic ix) (asDynamic src)++-- | Static call to 'Dynamic._scatterFill'+_scatterFill  :: Tensor d -> Word -> IndexTensor '[n] -> HsReal -> IO ()+_scatterFill r d ix = Dynamic._scatterFill (asDynamic r) d (longAsDynamic ix)+
+ src/Torch/Indef/Static/Tensor/Sort.hs view
@@ -0,0 +1,20 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.Sort+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+module Torch.Indef.Static.Tensor.Sort where++import Torch.Indef.Types+import qualified Torch.Indef.Dynamic.Tensor.Sort as Dynamic++-- | Static call to 'Dynamic._sort'+_sort :: (Tensor d', IndexTensor '[n]) -> Tensor d -> Word -> SortOrder -> IO ()+_sort (r, ix) t = Dynamic._sort (asDynamic r, longAsDynamic ix) (asDynamic t)++-- GPU only:+--   sortKeyValueInplace :: t -> IndexDynamic t -> Int -> Int -> IO ()
+ src/Torch/Indef/Static/Tensor/TopK.hs view
@@ -0,0 +1,34 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Static.Tensor.TopK+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Static.Tensor.TopK where++import Numeric.Dimensions+import System.IO.Unsafe++import Torch.Indef.Types+import Torch.Indef.Static.Tensor+import qualified Torch.Indef.Dynamic.Tensor.TopK as Dynamic+import Torch.Indef.Index++-- | returns all @k@ smallest elements in a tensor over a given dimension, including their indices, in unsorted order.+topk+  :: forall d' d n+  .  (All Dimensions '[d, d'], KnownDim n)+  => Tensor d -> Integer -> Word -> TopKOrder -> Maybe KeepDim -> (Tensor d', IndexTensor '[n])+topk t k d o sorted = unsafeDupablePerformIO $ do+  let ix :: IndexTensor '[n] = newIx+  let r  :: Tensor d' = new+  Dynamic._topk (asDynamic r, longAsDynamic ix) (asDynamic t) k d o sorted+  pure (r, ix)+{-# NOINLINE topk #-}++
+ src/Torch/Indef/Storage.hs view
@@ -0,0 +1,276 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Storage+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Storages are basically a way to access memory of a C pointer or array.+-- Storages can also map the contents of a file to memory. A Storage is an+-- array of basic C types.+--+-- Several Storage classes for all the basic C types exist and have the+-- following self-explanatory names: ByteStorage, CharStorage, ShortStorage,+-- IntStorage, LongStorage, FloatStorage, DoubleStorage.+--+-- Note that ByteStorage and CharStorage represent both arrays of bytes.+-- ByteStorage represents an array of unsigned chars, while CharStorage+-- represents an array of signed chars.+-------------------------------------------------------------------------------+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Strict #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Storage+  ( IsList(..)+  , Storage(..)++  , cstorage+  , storage+  , storageState+  , storageStateRef++  , storagedata+  , size+  , set+  , get+  , empty+  , newWithSize+  , newWithSize1+  , newWithSize2+  , newWithSize3+  , newWithSize4+  , newWithMapping+  , newWithData+  , setFlag+  , clearFlag+  , retain+  , resize+  , fill+  ) where++import Torch.Indef.Storage.Copy as X++import Foreign hiding (with, new)+import Foreign.C.Types+import GHC.ForeignPtr (ForeignPtr)+import GHC.Int+import GHC.Word+import Control.Monad+import Control.Monad.Managed+import Control.DeepSeq+import System.IO.Unsafe+import GHC.Exts (IsList(..))+import Control.Monad.ST+import Data.STRef++import Torch.Indef.Types+import Torch.Indef.Internal++import qualified Torch.Sig.Types          as Sig+import qualified Torch.Sig.Types.Global   as Sig+import qualified Torch.Sig.Storage        as Sig+import qualified Torch.Sig.Storage.Memory as Sig+import qualified Foreign.Marshal.Array    as FM++-- TODO: use these?+-- newtype MStorage s = MStorage (STRef s Storage)+--+-- freeze :: (forall s . STRef s Storage) -> Storage+-- freeze ref = runST (readSTRef ref)+--+-- thaw :: Storage -> ST s (MStorage s)+-- thaw s = MStorage <$> newSTRef s+++-- | return the internal data of 'Storage' as a list of haskell values.+storagedata :: Storage -> [HsReal]+storagedata s = unsafeDupablePerformIO . flip with (pure . fmap c2hsReal) $ do+  st <- managedState+  s' <- managedStorage s+  liftIO $ do+    -- a strong dose of paranoia+    sz <- fromIntegral <$> Sig.c_size st s'+    tmp <- FM.mallocArray sz++    creals <- Sig.c_data st s'+    FM.copyArray tmp creals sz+    FM.peekArray sz tmp+ where+  arrayLen :: Ptr CState -> Ptr CStorage -> IO Int+  arrayLen st p = fromIntegral <$> Sig.c_size st p+{-# NOINLINE storagedata #-}++-- | Returns the number of elements in the storage. Equivalent to #.+size :: Storage -> Int+size s = unsafeDupablePerformIO . fmap fromIntegral . withLift $ Sig.c_size+  <$> managedState+  <*> managedStorage s+{-# NOINLINE size #-}++-- | set the value at 'Index' to 'HsReal' in a given 'Storage'.+set :: Storage -> Word -> HsReal -> IO ()+set s pd v = withLift $ Sig.c_set+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+  <*> pure (hs2cReal v)++-- | get the value at 'Index' from a given 'Storage'.+get :: Storage -> Word -> HsReal+get s pd = unsafeDupablePerformIO . fmap c2hsReal . withLift $ Sig.c_get+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)+{-# NOINLINE get #-}++-- | make a new empty 'Storage'.+empty :: Storage+empty = unsafeDupablePerformIO . withStorage $ Sig.c_new+  <$> managedState+{-# NOINLINE empty #-}++-- | create a new storage of a given length, 'StorageSize'.+newWithSize :: Word -> Storage+newWithSize pd = unsafeDupablePerformIO . withStorage $ Sig.c_newWithSize+  <$> managedState+  <*> pure (fromIntegral pd)+{-# NOINLINE newWithSize #-}++-- | make a new 'Storage' with a single value.+newWithSize1 :: HsReal -> Storage+newWithSize1 a0 = unsafeDupablePerformIO . withStorage $ Sig.c_newWithSize1+  <$> managedState+  <*> pure (hs2cReal a0)+{-# NOINLINE newWithSize1 #-}++-- | make a new 'Storage' with two values.+newWithSize2 :: HsReal -> HsReal -> Storage+newWithSize2 a0 a1 = unsafeDupablePerformIO . withStorage $ Sig.c_newWithSize2+  <$> managedState+  <*> pure (hs2cReal a0)+  <*> pure (hs2cReal a1)+{-# NOINLINE newWithSize2 #-}++-- | make a new 'Storage' with three values.+newWithSize3 :: HsReal -> HsReal -> HsReal -> Storage+newWithSize3 a0 a1 a2 = unsafeDupablePerformIO . withStorage $ Sig.c_newWithSize3+  <$> managedState+  <*> pure (hs2cReal a0)+  <*> pure (hs2cReal a1)+  <*> pure (hs2cReal a2)+{-# NOINLINE newWithSize3 #-}++-- | make a new 'Storage' with four values.+newWithSize4 :: HsReal -> HsReal -> HsReal -> HsReal -> Storage+newWithSize4 a0 a1 a2 a3 = unsafeDupablePerformIO . withStorage $ Sig.c_newWithSize4+  <$> managedState+  <*> pure (hs2cReal a0)+  <*> pure (hs2cReal a1)+  <*> pure (hs2cReal a2)+  <*> pure (hs2cReal a3)+{-# NOINLINE newWithSize4 #-}++-- | FIXME: This is totally broken. This takes a filename, size, and flags, and produces+-- 'Storage' from these inputs. Figure out how to fix this, ideally.+--+-- See:+-- https://github.com/torch/torch7/blob/04e1d1dce0f02aea82dc433c4f39e42650c4390f/lib/TH/generic/THStorage.h#L49+newWithMapping+  :: [Int8]       -- ^ filename+  -> Word64       -- ^ size+  -> Int32        -- ^ flags+  -> IO Storage+newWithMapping pcc' pd ci = withStorage $ Sig.c_newWithMapping+  <$> managedState+  <*> liftIO (FM.newArray (map fromIntegral pcc'))+  <*> pure (fromIntegral pd)+  <*> pure (fromIntegral ci)++-- | make a new 'Storage' from a given list and 'StorageSize'.+--+-- FIXME: find out if 'StorageSize' always corresponds to the length of the list. If so,+-- remove it!+newWithData+  :: [HsReal]+  -> Word64   -- ^ storage size+  -> Storage+newWithData pr pd = unsafeDupablePerformIO . withStorage $ Sig.c_newWithData+  <$> managedState+  <*> liftIO (FM.newArray (hs2cReal <$> pr))+  <*> pure (fromIntegral pd)+{-# NOINLINE newWithData #-}++-- | set the flags of a given 'Storage'. Flags are applied via bitwise-or.+setFlag :: Storage -> Int8 -> IO ()+setFlag s cc = withLift $ Sig.c_setFlag+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral cc)++-- | clear the flags of a given 'Storage'. Flags are cleanred via bitwise-and.+clearFlag :: Storage -> Int8 -> IO ()+clearFlag s cc = withLift $ Sig.c_clearFlag+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral cc)++-- | Increment the reference counter of the storage.+--+-- This method should be used with extreme care. In general, they should never be called,+-- except if you know what you are doing, as the handling of references is done+-- automatically. They can be useful in threaded environments. Note that these+-- methods are atomic operations.+retain :: Storage -> IO ()+retain s = withLift $ Sig.c_retain+  <$> managedState+  <*> managedStorage s++-- | Resize the storage to the provided size. /The new contents are undetermined/.+resize :: Storage -> Word32 -> IO ()+resize s pd = withLift $ Sig.c_resize+  <$> managedState+  <*> managedStorage s+  <*> pure (fromIntegral pd)++-- | Fill the Storage with the given value.+fill :: Storage -> HsReal -> IO ()+fill s v = withLift $ Sig.c_fill+  <$> managedState+  <*> managedStorage s+  <*> pure (hs2cReal v)++instance IsList Storage where+  type Item Storage = HsReal+  toList = storagedata+  fromList pr = newWithData pr (fromIntegral $ length pr)++instance Show Storage where+  show = show . storagedata++{-+-- FIXME: find out where signatures should go to fill in these indefinites++instance Class.CPUStorage Storage where+  newWithAllocator :: StorageSize -> (CTHAllocatorPtr, AllocatorContext) -> IO Storage+  newWithAllocator pd (alloc, AllocatorContext ctx) = Sig.c_newWithAllocator (fromIntegral pd) alloc ctx >>= mkStorage++  newWithDataAndAllocator :: [HsReal] -> StorageSize -> (CTHAllocatorPtr, AllocatorContext) -> IO Storage+  newWithDataAndAllocator pr pd (alloc, AllocatorContext ctx) = do+    pr' <- FM.withArray (hs2cReal <$> pr) pure+    s <- Sig.c_newWithDataAndAllocator pr' (fromIntegral pd) alloc ctx {-seems like it's fine to pass nullPtr-}+    mkStorage s++  swap :: Storage -> Storage -> IO ()+  swap s0 s1 =+    withForeignPtr (storage s0) $ \s0' ->+      withForeignPtr (storage s1) $ \s1' ->+        Sig.c_swap s0' s1'+++instance Class.GPUStorage t where+  c_getDevice :: t -> io Int+-}
+ src/Torch/Indef/Storage/Copy.hs view
@@ -0,0 +1,128 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Storage.Copy+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+--+-- Conversions between two Storage types. Behaviour is not yet specified as to+-- what happens when you copy between incompatible types.+-------------------------------------------------------------------------------+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -fno-cse #-}+module Torch.Indef.Storage.Copy+  ( copy+  , copyByte+  , copyChar+  , copyShort+  , copyInt+  , copyLong+  , copyFloat+  , copyDouble+  ) where++import Foreign hiding (new, with)+import Foreign.Ptr+import Control.Monad.Managed+import System.IO.Unsafe++import qualified Torch.Types.TH           as TH+import qualified Foreign.Marshal.Array    as FM+import qualified Torch.Sig.Types          as Sig+import qualified Torch.Sig.Types.Global   as Sig+import qualified Torch.Sig.Storage        as Sig+import qualified Torch.Sig.Storage.Memory as Sig+import qualified Torch.Sig.Storage.Copy   as Sig++import qualified Torch.FFI.TH.Long.Storage   as L+import qualified Torch.FFI.TH.Float.Storage  as F+import qualified Torch.FFI.TH.Byte.Storage   as B+import qualified Torch.FFI.TH.Char.Storage   as C+import qualified Torch.FFI.TH.Short.Storage  as S+import qualified Torch.FFI.TH.Int.Storage    as I+import qualified Torch.FFI.TH.Double.Storage as D++import Torch.Indef.Types++copyType+  :: IO (Ptr a)+  -> FinalizerPtr a+  -> (ForeignPtr TH.C'THState -> ForeignPtr a -> b)+  -> (Ptr CState -> Ptr CStorage -> Ptr a -> IO ())+  -> Storage -> b+copyType newPtr fin builder cfun t = unsafeDupablePerformIO . flip with (pure . builder TH.torchstate) $ do+  s' <- managedState+  t' <- managedStorage t+  liftIO $ do+    target <- newPtr+    -- throwString $ intercalate ""+    --   [ "'hasktorch-indef-unsigned:Torch.Indef.Tensor.Dynamic.Copy.copyType':"+    --   , "must resize the target tensor before continuing"+    --   ]+    -- Sig.c_resizeAs s' target t'       -- << THIS NEEDS TO BE REMAPPED TO TENSORLONG SIZES+    cfun s' t' target++    newForeignPtr fin target+{-# NOINLINE copyType #-}++rawCopy :: Storage -> [HsReal]+rawCopy t = unsafeDupablePerformIO . flip with (pure . fmap c2hsReal) $ do+  s' <- managedState+  t' <- managedStorage t+  liftIO $ do+    sz  <- fromIntegral <$> Sig.c_size s' t'+    res <- FM.mallocArray (fromIntegral sz)+    Sig.c_rawCopy s' t' res+    FM.peekArray (fromIntegral sz) res+{-# NOINLINE rawCopy #-}++-- | Copy a Storage object.+copy :: Storage -> Storage+copy t = unsafeDupablePerformIO . flip with mkStorage $ do+  s' <- managedState+  t' <- managedStorage t+  liftIO $ do+    store <- Sig.c_new s'+    Sig.c_copy s' t' store+    pure store+{-# NOINLINE copy #-}++-- | Copy a 'Storage' object to a CPU-backed LongStorage.+copyLong :: Storage -> TH.LongStorage+copyLong = copyType L.c_new_ L.p_free TH.longStorage   Sig.c_copyLong++-- | Copy a 'Storage' object to a CPU-backed FloatStorage.+copyFloat :: Storage -> TH.FloatStorage+copyFloat = copyType F.c_new_ F.p_free TH.floatStorage  Sig.c_copyFloat++-- | Copy a 'Storage' object to a CPU-backed ByteStorage.+copyByte :: Storage -> TH.ByteStorage+copyByte = copyType B.c_new_ B.p_free TH.byteStorage   Sig.c_copyByte++-- | Copy a 'Storage' object to a CPU-backed CharStorage.+copyChar :: Storage -> TH.CharStorage+copyChar = copyType C.c_new_ C.p_free TH.charStorage   Sig.c_copyChar++-- | Copy a 'Storage' object to a CPU-backed ShortStorage.+copyShort :: Storage -> TH.ShortStorage+copyShort  = copyType S.c_new_ S.p_free TH.shortStorage  Sig.c_copyShort++-- | Copy a 'Storage' object to a CPU-backed IntStorage.+copyInt :: Storage -> TH.IntStorage+copyInt = copyType I.c_new_ I.p_free TH.intStorage    Sig.c_copyInt++-- | Copy a 'Storage' object to a CPU-backed DoubleStorage.+copyDouble :: Storage -> TH.DoubleStorage+copyDouble = copyType D.c_new_ D.p_free TH.doubleStorage Sig.c_copyDouble++-- FIXME: reintroduce half+-- copyHalf   :: t -> IO HalfStorage++-- class GPUStorageCopy gpu cpu | gpu -> cpu where+--   thCopyCuda :: cpu -> IO gpu+--   copyCuda   :: gpu -> IO gpu+--   copyCPU    :: gpu -> IO cpu+
+ src/Torch/Indef/Types.hs view
@@ -0,0 +1,250 @@+-------------------------------------------------------------------------------+-- |+-- Module    :  Torch.Indef.Dynamic.Types+-- Copyright :  (c) Sam Stites 2017+-- License   :  BSD3+-- Maintainer:  sam@stites.io+-- Stability :  experimental+-- Portability: non-portable+-------------------------------------------------------------------------------+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE Strict #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Torch.Indef.Types+  ( module Sig+  , DimVal(..)++  , Step(..), Stride(..), StorageOffset(..), Size(..), KeepDim(..), fromKeepDim, keep, ignore, SortOrder(..), TopKOrder(..)+  , AllocatorContext(..) -- , StorageSize(..), Index(..)++  , (.:)++  -- manage arguments to c functions+  , managedState+  , managedStorage+  , managedTensor+  , managedGen++  -- lift managed IO actions+  , withLift+  , withDynamic+  , withStorage++  -- monadic patterns to be replaced with applicative-style+  , with2DynamicState+  , with3DynamicState++  -- helper functions for monadic construction+  , mkDynamic+  , mkStorage+  ) where++import Foreign hiding (with)+import Foreign.C.Types+import Foreign.Ptr+import GHC.Int (Int64(..), Int32(..))+import Control.Monad.Managed+import Numeric.Dimensions+import qualified Foreign.Marshal.Array as FM++import Control.Arrow+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Reader.Class+import Torch.Types.TH (C'THState)+import GHC.TypeLits++import Torch.Sig.State as Sig+import Torch.Sig.Types as Sig+import Torch.Sig.Types.Global as Sig++import qualified Numeric.Dimensions (KnownDim)+import qualified Torch.Types.TH as TH+import qualified Torch.FFI.TH.Long.Storage as TH+import qualified Torch.Sig.Tensor.Memory as SigTen+import qualified Torch.Sig.Storage.Memory as SigStore+++-------------------------------------------------------------------------------++-- | From+-- https://github.com/pytorch/pytorch/blob/c61f0217a536d19c9ff3290067ddcbb9ce3a5c6a/aten/src/THNN/Reduction.h+--+-- NB: Keep this in sync with Reduction class in torch/nn/modules/functional.py+-- These constants control the reduction behavior of loss functions.+-- Ideally, this would be a scoped enum, but jit doesn't support that+data Reduction+  = NoReduce         -- ^ Do not reduce+  | ElementwiseMean  -- ^ Sum losses and take mean over each individually computed loss element+  | Sum              -- ^ Sum losses++-------------------------------------------------------------------------------+-- helpers for dimensions:++-- | term-level representation of an index.+newtype DimVal = DimVal Int32+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++-- | term-level representation of an index.+newtype Index = Index Int64+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++{-# DEPRECATED DimVal, Index "Use dimensions package's Idx instead" #-}++{-+transferDims :: Proxy (ds::[Nat]) -> Dim ds+transferDims p = undefined+ where++go :: forall f m . Proxy (m::[Nat]) -> Dim (f :: [Nat])+go _ =+  if null (fromSing (sing :: Sing m))+  then (D  :: Dim f)+  else (Dn :: (x:xs) ~ m => Dim (x::Nat)) :* (go (Proxy :: (x:xs) ~ m => Proxy xs))+-- -}++-- Helper function to debug dimensions package. We return @Integral i@ in case we need to cast directly to C-level types.++++-------------------------------------------------------------------------------++-- | newtype wrapper around the C-level representation of a tensor's internal+-- 'Storage' stride for each dimension.+newtype Stride = Stride CLLong+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++-- | newtype wrapper around the C-level representation of a dimension's size+newtype Size = Size CLLong+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++-- | newtype wrapper around the C-level representation of a storage offset+newtype StorageOffset = Offset CPtrdiff+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++-- | Represents the size of storage, should be CPtrdiff to match with the C internals+newtype StorageSize = StorageSize CPtrdiff+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++-- | newtype wrapper around the C-level representation of a step size+newtype Step = Step CLong+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)++-- | haskell representation of a CInt which determines whether or not to return dimensions+newtype KeepDim = KeepDim { keepIt :: Bool }+  deriving (Bounded, Enum, Eq, Ord, Read, Show)++-- | cast a 'KeepDim' to a numerical representation.+--+-- NOTE: don't bind the @i@ in case there are some differences between THC and TH+fromKeepDim :: Integral i => Maybe KeepDim -> i+fromKeepDim = maybe 0 (fromIntegral . fromEnum)++-- | smart constructors for keepdim since we don't get inference for free like Num+keep,  ignore :: KeepDim+(keep, ignore) = (KeepDim True, KeepDim False)++-- | Simple datatype to represent sort order arguments which torch provides to us.+data SortOrder = Ascending | Descending+  deriving (Eq, Show, Ord, Enum, Bounded)++-- | Simple datatype to represent arguments for a topk function.+--+-- See https://github.com/torch/torch7/blob/75a86469aa9e2f5f04e11895b269ec22eb0e4687/lib/TH/generic/THTensorMath.c#L2545+data TopKOrder = KAscending | KNone | KDescending+  deriving (Eq, Show, Ord, Enum, Bounded)++-- | this is supposed to represent the AllocatorContext, but it should not be exposed to a user.+newtype AllocatorContext = AllocatorContext (Ptr ())+{-# WARNING AllocatorContext "this should not be used or referenced -- we are still figuring out what to do with this." #-}++-------------------------------------------------------------------------------++ptrArray2hs :: (Ptr a -> IO (Ptr CReal)) -> (Ptr a -> IO Int) -> ForeignPtr a -> IO [HsReal]+ptrArray2hs updPtrArray toSize fp = do+  sz <- withForeignPtr fp toSize+  creals <- withForeignPtr fp updPtrArray+  (fmap.fmap) c2hsReal (FM.peekArray sz creals)++-- | The blackbird combinator.+--+-- (stites): This happens often enough that I'm pulling in the blackbird+--+-- FIXME(stites): remove this+(.:) :: (b -> c) -> (a0 -> a1 -> b) -> a0 -> a1 -> c+(.:) = (.) . (.)+infixl 5 .:++-- | run a function against the internal reference of a torch generator.+withGen :: Sig.Generator -> (Ptr CGenerator -> IO x) -> IO x+withGen g fn = withForeignPtr (Sig.rng g) fn++-- | run a function with a managed state's raw internal pointer.+managedState :: Managed (Ptr Sig.CState)+managedState = managed (withForeignPtr Sig.torchstate)++managedTensor :: Sig.Dynamic -> Managed (Ptr Sig.CTensor)+managedTensor t = managed (withForeignPtr (Sig.ctensor t))++managedStorage :: Sig.Storage -> Managed (Ptr Sig.CStorage)+managedStorage t = managed (withForeignPtr (Sig.cstorage t))++managedGen :: Sig.Generator -> Managed (Ptr CGenerator)+managedGen g = managed (withForeignPtr (Sig.rng g))+++-- | run a function with two tensors with reference to the first tensor's underlying state.+with2DynamicState+  :: Sig.Dynamic+  -> Sig.Dynamic+  -> (Ptr Sig.CState -> Ptr Sig.CTensor -> Ptr Sig.CTensor -> IO x)+  -> IO x+with2DynamicState t0 t1 fn = withLift $ fn+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1++-- | run a function with three tensors with reference to the first tensor's underlying state.+with3DynamicState+  :: Sig.Dynamic+  -> Sig.Dynamic+  -> Sig.Dynamic+  -> (Ptr Sig.CState -> Ptr Sig.CTensor -> Ptr Sig.CTensor -> Ptr Sig.CTensor -> IO x)+  -> IO x+with3DynamicState t0 t1 t2 fn = withLift $ fn+  <$> managedState+  <*> managedTensor t0+  <*> managedTensor t1+  <*> managedTensor t2++withLift :: Managed (IO x) -> IO x+withLift = flip with pure . (liftIO =<<)++-- | smart constructor for a Managed 'Sig.Dynamic' tensor+withDynamic :: Managed (IO (Ptr Sig.CTensor)) -> IO Sig.Dynamic+withDynamic = flip with mkDynamic . (liftIO =<<)++-- | smart constructor for a Managed 'Sig.Storage' tensor+withStorage :: Managed (IO (Ptr Sig.CStorage)) -> IO Sig.Storage+withStorage = flip with mkStorage . (liftIO =<<)++-- | smart constructor for a 'Sig.Dynamic' tensor+mkDynamic :: Ptr Sig.CTensor -> IO Sig.Dynamic+mkDynamic t = with managedState $ \s ->+  Sig.dynamic Sig.torchstate <$> newForeignPtrEnv SigTen.p_free s t++-- | run a function with access to a 'Sig.Storage's underlying state and C-reference.+withStorageState :: Sig.Storage -> (Ptr Sig.CState -> Ptr Sig.CStorage -> IO x) -> IO x+withStorageState t fn = flip with pure . (liftIO =<<) $ fn+  <$> managedState+  <*> managedStorage t++-- | smart constructor for 'Sig.Storage'+mkStorage :: Ptr Sig.CStorage -> IO Sig.Storage+mkStorage t = with managedState $ \s ->+  Sig.storage Sig.torchstate <$> newForeignPtrEnv SigStore.p_free s t+
+ tests/Spec.hs view
@@ -0,0 +1,17 @@+{- OPTIONS_GHC -F -pgmF hspec-discover #-}+module Main where++import Test.Hspec+import qualified Torch.Indef.StorageSpec             as Storage+import qualified Torch.Indef.Dynamic.TensorSpec      as Dynamic.Tensor+import qualified Torch.Indef.Dynamic.Tensor.MathSpec as Dynamic.Tensor.Math+import qualified Torch.Indef.Static.TensorSpec       as Static.Tensor+import qualified Torch.Indef.Static.Tensor.MathSpec  as Static.Tensor.Math++main :: IO ()+main = hspec $ do+  describe "Storage"             Storage.spec+  describe "Dynamic.Tensor"      Dynamic.Tensor.spec+  describe "Dynamic.Tensor.Math" Dynamic.Tensor.Math.spec+  describe "Static.Tensor"       Static.Tensor.spec+  describe "Static.Tensor.Math"  Static.Tensor.Math.spec
+ tests/Torch/Indef/Dynamic/TensorSpec.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE ScopedTypeVariables #-}+module Torch.Indef.Dynamic.TensorSpec where++import Test.Hspec+import Test.Hspec.QuickCheck hiding (resize)+import Test.QuickCheck ((.||.), (==>), (===), property)+import Test.QuickCheck.Monadic+import Data.List (genericLength)+import GHC.Exts++import Torch.Indef.Types+import Torch.Indef.Dynamic.Tensor++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  prop "fromList / toList forms the identity" $ \xs ->+    toList ((fromList xs) :: Dynamic) `shouldBe` xs++  describe "empty" $ do+    it "has 0 dimensions" $ nDimension empty `shouldBe` 0+    it "has 0 elements" $ nElement empty `shouldBe` 0+    it "is contiguous" $ isContiguous empty `shouldBe` True+    it "is the same size as other empty tensors" $ isSameSizeAs empty empty `shouldBe` True+    it "is 'set to' the same storage as other empty tensors (ie: is set to NULL)" $ isSetTo empty empty `shouldBe` True++  describe "fromList" $ do+    prop "will have 1 dimension (given non-empty list)" $ \xs -> not (null xs) ==> nDimension (fromList xs) === 1+    prop "will have the same number of elements as input list" $ \xs -> nElement (fromList xs) === genericLength xs+    prop "will be contiguous" $ \xs -> isContiguous (fromList xs) === True++  describe "operations on vectors (made fromList)" $ do+    describe "newClone on vectors" $ do+      prop "will have identical dimensions" $ \xs -> let v = fromList xs in nDimension (newClone v) === nDimension v+      prop "will have identical elements" $ \xs -> let v = fromList xs in nElement (newClone v) === nElement v+      prop "will both identically contiguous" $ \xs -> let v = fromList xs in isContiguous (newClone v) === isContiguous v+      prop "will not be set to the same storage" $ \xs -> let v = fromList xs in isSetTo (newClone v) v === False++    prop "get1d will be Nothing for empty tensors and the index'd value otherwise" $ \xs i ->+      let+        t = fromList xs+        i' = fromIntegral i+      in     (length xs < i' ==> get1d t i === Nothing)+        .||. (i' < length xs ==> get1d t i === Just (xs !! i'))++    prop "get2d will always be Nothing" $ \xs i0 i1       -> get2d (fromList xs) i0 i1       === Nothing+    prop "get3d will always be Nothing" $ \xs i0 i1 i2    -> get3d (fromList xs) i0 i1 i2    === Nothing+    prop "get4d will always be Nothing" $ \xs i0 i1 i2 i3 -> get4d (fromList xs) i0 i1 i2 i3 === Nothing++  it "size" $ pending+  it "sizeDesc" $ pending+  it "newClone on higher-ranked tensor" $ pending+  it "get1d on higher-ranked tensor" $ pending+  it "get2d on higher-ranked tensor" $ pending+  it "get3d on higher-ranked tensor" $ pending+  it "get4d on higher-ranked tensor" $ pending+  it "isContiguous on higher-ranked tensor" $ pending+  it "isSameSizeAs on higher-ranked tensor" $ pending+  it "isSetTo on higher-ranked tensor" $ pending+  it "isSize" $ pending+  it "_narrow" $ pending+  it "newExpand" $ pending+  it "_expand" $ pending+  it "_expandNd" $ pending+  it "newContiguous" $ pending+  it "newNarrow" $ pending+  it "newSelect" $ pending+  it "newSizeOf" $ pending+  it "newStrideOf" $ pending+  it "newTranspose" $ pending+  it "newUnfold" $ pending+  it "newView" $ pending+  it "newWithSize" $ pending+  it "newWithSize1d" $ pending+  it "newWithSize2d" $ pending+  it "newWithSize3d" $ pending+  it "newWithSize4d" $ pending+  it "newWithStorage" $ pending+  it "newWithStorage1d" $ pending+  it "newWithStorage2d" $ pending+  it "newWithStorage3d" $ pending+  it "newWithStorage4d" $ pending+  it "newWithTensor" $ pending+  it "_resize" $ pending+  it "_resize1d" $ pending+  it "_resize2d" $ pending+  it "_resize3d" $ pending+  it "_resize4d" $ pending+  it "_resize5d" $ pending+  it "_resizeAs" $ pending+  it "resizeAs" $ pending+  it "_resizeNd" $ pending+  it "retain" $ pending+  it "_select" $ pending+  it "_set" $ pending+  it "_set1d" $ pending+  it "_set2d" $ pending+  it "_set3d" $ pending+  it "_set4d" $ pending+  it "_setStorage" $ pending+  it "_setStorage1d" $ pending+  it "_setStorage2d" $ pending+  it "_setStorage3d" $ pending+  it "_setStorage4d" $ pending+  it "_setStorageNd" $ pending+  it "_squeeze" $ pending+  it "_squeeze1d" $ pending+  it "storage" $ pending+  it "storageOffset" $ pending+  it "stride" $ pending+  it "_transpose" $ pending+  it "_unfold" $ pending+  it "_unsqueeze1d" $ pending+  it "vector" $ pending+  it "matrix" $ pending+  it "cuboid" $ pending+  it "hyper" $ pending+  it "tensorSlices" $ pending+
+ tests/Torch/Indef/Static/TensorSpec.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Torch.Indef.Static.TensorSpec (spec) where++import Control.Monad (replicateM, void)+import Data.Maybe (fromMaybe)+import Numeric.Dimensions (Dim, dim)+import Test.Hspec+import Test.QuickCheck (Property)+import Test.QuickCheck.Monadic (run, monadicIO)+import qualified Data.List as List+import qualified Data.List.NonEmpty as NE++import Torch.Indef.Mask+import Torch.Indef.Static.Tensor+import Torch.Indef.Static.Tensor.Math+import Torch.Indef.Static.Tensor.Math.CompareT+import Torch.Indef.Types (Tensor, HsReal, asDynamic)+import qualified Torch.Indef.Dynamic.Tensor as Dynamic+import qualified Torch.Indef.Storage as Storage+++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  -- describe "Eq instance" eqSpec+  describe "transpose"   transpose2dSpec+  describe "resize"      resizeSpec+  describe "scenario" $+    it "runs this scenario as expected without crashing" testScenario+  describe "expand" $+    it "can expand a vector without crashing" expandScenario+  describe "tensor construction and access" tensorConstructionSpec+  describe "stacking" stackingSpec+  describe "un/squeezing" squeezeUnsqeezeSpec+  describe "transpose2d" transpose2dSpec+  xdescribe "expectations between tensor and storage" tensorStorageExpectationsSpec++testScenario :: Property+testScenario = monadicIO . run $ do+  putStrLn "\n1 - new [2, 2]"+  print (new :: Tensor '[2, 2])+  putStrLn "\n2 - new [2, 4]"+  print (new :: Tensor '[2, 4])+  putStrLn "\n3 - new [2, 2, 2]"+  print (new :: Tensor '[2, 2, 2])+  putStrLn "\n4 - new [8, 4]"+  print (new :: Tensor '[8, 4])+  putStrLn "\n5 - constant [3, 4]"+  print $ asDynamic (constant 2 :: Tensor '[3, 4])+  putStrLn "\n6 - newClone [2, 3]"+  print $ newClone (constant 2 :: Tensor '[2, 3])++eqSpec :: Spec+eqSpec = do+  it "should be True"  . allOf $ (constant 4 :: Tensor '[2,3]) `eqTensor` (constant 4 :: Tensor '[2,3])+  it "should be False" . allOf $ (constant 3 :: Tensor '[2,3]) `eqTensor` (constant 1 :: Tensor '[2,3])++-- transposeSpec :: Spec+-- transposeSpec = do+--   runIO $ print $ trans . trans . trans $ (constant 3 :: Tensor '[3,2])+--   it "should transpose correctly" $ (trans . trans $ (constant 3 :: Tensor '[3,2])) == (constant 3 :: Tensor '[3,2])++resizeSpec :: Spec+resizeSpec = runIO $ do+  Just (vec :: Tensor '[6]) <- fromList [1, 5, 2, 4, 3, 3.5]+  let mtx = resizeAs vec :: Tensor '[3,2]+  print vec+  print mtx+ where++expandScenario :: IO ()+expandScenario = do+  Just (foo :: Tensor '[4]) <- fromList [1,2,3,4]+  let result = expand2d foo :: Tensor '[3, 4]+  print result++tensorConstructionSpec :: Spec+tensorConstructionSpec =+  describe "matrix" $ do+    it "with two rows of 3 elements" $ do+      let (r1, r2) = ([1,2,3],[4,5,6])+      (tensordata <$> (unsafeMatrix [r1, r2] :: IO (Tensor '[2,3])))+        >>= (`shouldBe` r1 ++ r2)++    describe "15x25 elements" $ do+      let ixs :: [(Word, [(Word, Double)])]+          ixs = fmap (\r -> (r, fmap (\c -> (c, fromIntegral $ 12 * r + c)) [0..24])) [0..14]+          xs  = fmap ((fmap snd) . snd) ixs+      ten :: Tensor '[15,25] <- runIO $ unsafeMatrix xs++      it "returns the same values with tensordata" $ do+        tensordata ten `shouldBe` concat xs+        tensordata ten `shouldBe` concat xs++      it "returns the same values with get2d" $ do+        let+          tvals :: [[HsReal]]+          tvals =+            flip fmap ixs $ \(r, ics) ->+              flip fmap ics $ \(c, _) ->+                fromMaybe (error "test is set up incorrectly") $ get2d ten r c+        pure tvals >>= (`shouldBe` xs)++tensorStorageExpectationsSpec :: Spec+tensorStorageExpectationsSpec = do+  let ixs :: [(Word, [(Word, Double)])]+      ixs = fmap (\r -> (r, fmap (\c -> (c, fromIntegral $ 12 * r + c)) [0..24])) [0..14]+      xs  = fmap ((fmap snd) . snd) ixs+  ten :: Tensor '[15,25] <- runIO $ unsafeMatrix xs++  it "prints the same storage values that it gets" $ do+    let std = Storage.storagedata (storage ten)+    let td = tensordata ten+    std `shouldBe` td++  -- forM_ [1,2,3] $ \i -> do+  --   it ("[Attempt " ++ show i ++ "] prints the same storage values as tensorSlices") $ do+  --     SomeDims ds <- getDims ten+  --     let t = asDynamic ten+  --         ds' = (fromIntegral <$> listDims ds)+  --     Dynamic.TenMatricies (m@(r0:|rs):|[]) <- Dynamic.tensorSlices+  --       t+  --       undefined+  --       (Dynamic.get2d t)+  --       ds'+  --     m `shouldBe` (NE.fromList xs)++  it "has the same data after printing (paranoia levels=high)" $ do+    tensordata ten `shouldBe` concat xs++  it "has the same storage data after printing (paranoia levels=high)" $ do+    Storage.storagedata (storage ten) `shouldBe` concat xs+++stackingSpec :: Spec+stackingSpec = do+  it "works with two identical tensors" $ do+    let t = constant (-(1/4)) :: Tensor '[6]+    tensordata (stack1d0 t t) `shouldBe` (replicate 12 (-1/4))++  it "works with two differing tensors" $ do+    let t1 = constant (-(1/4)) :: Tensor '[6]+        t2 = constant   (1/4)  :: Tensor '[6]+    tensordata (stack1d0 t1 t2) `shouldBe` (replicate 6 (-1/4) ++ replicate 6 (1/4))++squeezeUnsqeezeSpec :: Spec+squeezeUnsqeezeSpec = do+  let d1 = dim :: Dim 1+  it "unsqueeze1d adds a dimension" $ do+    shape (unsqueeze1d d1 (constant 50 :: Tensor '[3,4,5])) `shouldBe` [3,1,4,5]++  it "unsqueeze1d_ adds a dimension and is unsafe" $ do+    let t = constant 50 :: Tensor '[3,4,5]+    shape t `shouldBe` [3,4,5]+    t' <- unsqueeze1d_ d1 t+    shape t' `shouldBe` [3,1,4,5]+    shape t  `shouldBe` [3,1,4,5]++  it "squeeze removes a dimension" $ do+    let t = (constant 50 :: Tensor '[3,1,4,5])+    shape t `shouldBe` [3,1,4,5]+    shape (squeeze1d d1 t) `shouldBe` [3,4,5]++  it "squeeze1d_ adds a dimension and is unsafe" $ do+    let t = (constant 50 :: Tensor '[3,1,4,5])+    shape t `shouldBe` [3,1,4,5]+    t' <- squeeze1d_ d1 t+    shape t' `shouldBe` [3,4,5]+    shape t  `shouldBe` [3,4,5]++  it "unsqueeze+squeeze forms an identity" $ do+    let t  = constant 50 :: Tensor '[3,4,5]+        t' = squeeze1d d1 (unsqueeze1d d1 t)+    shape t' `shouldBe` [3,4,5]+    nElement t' `shouldBe` product [3,4,5]+    tensordata t' `shouldSatisfy` all (== 50)++transpose2dSpec :: Spec+transpose2dSpec = do+  it "transposes the shape" $ do+    let t = constant 10 :: Tensor '[2,3]+    shape t `shouldBe` [2,3]+    shape (transpose2d t) `shouldBe` [3,2]+    shape t `shouldBe` [2,3]++  it "doesn't change the underlying data" $ do+    let xs = [[1..3],[4..6]]+    t :: Tensor '[2,3] <- unsafeMatrix xs+    tensordata t `shouldBe` tensordata (transpose2d t)+    tensordata t `shouldBe` concat xs++
+ tests/Torch/Indef/StorageSpec.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE ScopedTypeVariables #-}+module Torch.Indef.StorageSpec where++import Control.Monad+import GHC.Int+import Test.Hspec+import Test.Hspec.QuickCheck hiding (resize)+import Test.QuickCheck ((.&&.), (==>), (===), property, Arbitrary(..))+import qualified Test.QuickCheck as QC+import Test.QuickCheck.Monadic+import GHC.Exts+import Debug.Trace+import Control.Monad.IO.Class+import Data.List+import Data.Word+import GHC.Natural++import Torch.Indef.Storage++data ListWithIx a = ListWithIx Word [a]+  deriving (Eq, Show)++instance Arbitrary a => Arbitrary (ListWithIx a) where+  arbitrary = do+    xs <- QC.listOf1 arbitrary+    ix <- QC.choose (0, genericLength xs - 1)+    pure $ ListWithIx ix xs++data ListWithOOB a = ListWithOOB Word [a]+  deriving (Eq, Show)++instance Arbitrary a => Arbitrary (ListWithOOB a) where+  arbitrary = do+    xs <- QC.listOf1 arbitrary+    ix <- QC.choose (genericLength xs, genericLength xs * 5)+    pure $ ListWithOOB ix xs++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "fromList / storagedata" $ do+    let+      xs = [0..500]+      st = fromList xs++    it "is instantiated with an offset of 0" $+      size st `shouldBe` length xs++    it "returns xs for storagedata" $+      storagedata st `shouldBe` xs++    it ("can access the first 50 elements by `get`") $ do+      forM_ [0..50] $ \i ->+        get st i `shouldBe` fromIntegral i++    it "should continue to be consistent after gets" $+      storagedata st `shouldBe` xs++  prop "fromList / toList should form the identity" $ \xs ->+    toList (fromList xs :: Storage) `shouldBe` xs++  prop "size should be the identical to the length" $ \xs ->+    size (fromList xs) `shouldBe` (length xs)++  describe "set / get" $ do+    it "can update any index" $ property $ \ (x, ListWithIx i xs) -> do+      let st = fromList xs+      get st (fromIntegral i) /= x ==> do+        set st (fromIntegral i) x+        get st (fromIntegral i) `shouldBe` x++  describe "empty" $ do+    it "has a size of 0" $ do+      let st = empty+      size empty `shouldBe` 0++  prop "newWithSize returns a size of input argument" $ \(i::Word16) ->+    size (newWithSize $ fromIntegral i) `shouldBe` fromIntegral i++  prop "newWithSize1 has size 1 and sets the argument" $ \v0 ->+    let st = newWithSize1 v0+    in size st === 1 .&&. get st 0 === v0++  prop "newWithSize2 has size 2 and sets the arguments" $ \v0 v1 ->+    let st = newWithSize2 v0 v1+    in   size st === 2+    .&&. get st 0 === v0+    .&&. get st 1 === v1++  prop "newWithSize3 has size 3 and sets the arguments" $ \v0 v1 v2 ->+    let st = newWithSize3 v0 v1 v2+    in   size st === 3+    .&&. get st 0 === v0+    .&&. get st 1 === v1+    .&&. get st 2 === v2++  prop "newWithSize4 has size 4 and sets the arguments" $ \v0 v1 v2 v3 ->+    let st = newWithSize4 v0 v1 v2 v3+    in   size st === 4+    .&&. get st 0 === v0+    .&&. get st 1 === v1+    .&&. get st 2 === v2+    .&&. get st 3 === v3++  prop "fill will overwrite the storage contents" $ \xs v ->+    length xs > 1 ==> do+    let st = fromList xs+    toList st `shouldBe` xs+    fill st v+    toList st `shouldSatisfy` (all (== v))++  describe "resize" $ do+    prop "will truncate storage if the new size is less than the old one (old size < 100)" $+      \(ListWithIx i xs) -> length xs < 100 ==> do+        let st = fromList xs+        resize st (fromIntegral i)+        toList st `shouldBe` take (fromIntegral i) xs++    prop "will expand storage if the new size is greater than the old one (new size <100)" $+      \(ListWithOOB i xs) -> i < 100 ==> do+        let st = fromList xs+        resize st (fromIntegral i)+        take (length xs) (toList st) `shouldBe` xs+