multilinear-io 0.4.0.0 → 0.5.0.0
raw patch · 14 files changed
+717/−302 lines, 14 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Multilinear.Generic.Serialize: fromBinary :: (Serialize a, Unbox a) => ByteString -> Either String (Tensor a)
- Multilinear.Generic.Serialize: fromBinaryFile :: (Serialize a, Unbox a) => String -> ExceptT String IO (Tensor a)
- Multilinear.Generic.Serialize: fromCSVFile :: (FromField a, Unbox a) => String -> Char -> String -> ExceptT String IO (Tensor a)
- Multilinear.Generic.Serialize: fromJSON :: (FromJSON a, Unbox a) => ByteString -> Maybe (Tensor a)
- Multilinear.Generic.Serialize: fromJSONFile :: (FromJSON a, Unbox a) => String -> MaybeT IO (Tensor a)
- Multilinear.Generic.Serialize: instance (Data.Aeson.Types.FromJSON.FromJSON a, Data.Vector.Unboxed.Base.Unbox a) => Data.Aeson.Types.FromJSON.FromJSON (Multilinear.Generic.Sequential.Tensor a)
- Multilinear.Generic.Serialize: instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Vector.Unboxed.Base.Unbox a) => Data.Aeson.Types.ToJSON.ToJSON (Multilinear.Generic.Sequential.Tensor a)
- Multilinear.Generic.Serialize: instance (Data.Csv.Conversion.FromField a, Data.Vector.Unboxed.Base.Unbox a) => Data.Csv.Conversion.FromRecord (Multilinear.Generic.Sequential.Tensor a)
- Multilinear.Generic.Serialize: instance (Data.Csv.Conversion.ToField a, Data.Vector.Unboxed.Base.Unbox a) => Data.Csv.Conversion.ToRecord (Multilinear.Generic.Sequential.Tensor a)
- Multilinear.Generic.Serialize: instance (Data.Serialize.Serialize a, Data.Vector.Unboxed.Base.Unbox a) => Data.Serialize.Serialize (Multilinear.Generic.Sequential.Tensor a)
- Multilinear.Generic.Serialize: toBinary :: (Serialize a, Unbox a) => Tensor a -> ByteString
- Multilinear.Generic.Serialize: toBinaryFile :: (Serialize a, Unbox a) => Tensor a -> String -> IO ()
- Multilinear.Generic.Serialize: toCSVFile :: (ToField a, Unbox a) => Tensor a -> String -> IO ()
- Multilinear.Generic.Serialize: toJSON :: (ToJSON a, Unbox a) => Tensor a -> ByteString
- Multilinear.Generic.Serialize: toJSONFile :: (ToJSON a, Unbox a) => Tensor a -> String -> IO ()
+ Multilinear.Generic.MultiCore.Serialize: fromBinary :: (Serialize a, Unbox a) => ByteString -> Either String (Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: fromBinaryFile :: (Serialize a, Unbox a) => String -> ExceptT String IO (Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: fromCSVFile :: (FromField a, Unbox a) => String -> Char -> String -> ExceptT String IO (Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: fromJSON :: (FromJSON a, Unbox a) => ByteString -> Maybe (Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: fromJSONFile :: (FromJSON a, Unbox a) => String -> MaybeT IO (Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: instance (Data.Aeson.Types.FromJSON.FromJSON a, Data.Vector.Unboxed.Base.Unbox a) => Data.Aeson.Types.FromJSON.FromJSON (Multilinear.Generic.MultiCore.Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Vector.Unboxed.Base.Unbox a) => Data.Aeson.Types.ToJSON.ToJSON (Multilinear.Generic.MultiCore.Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: instance (Data.Csv.Conversion.FromField a, Data.Vector.Unboxed.Base.Unbox a) => Data.Csv.Conversion.FromRecord (Multilinear.Generic.MultiCore.Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: instance (Data.Csv.Conversion.ToField a, Data.Vector.Unboxed.Base.Unbox a) => Data.Csv.Conversion.ToRecord (Multilinear.Generic.MultiCore.Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: instance (Data.Serialize.Serialize a, Data.Vector.Unboxed.Base.Unbox a) => Data.Serialize.Serialize (Multilinear.Generic.MultiCore.Tensor a)
+ Multilinear.Generic.MultiCore.Serialize: toBinary :: (Serialize a, Unbox a) => Tensor a -> ByteString
+ Multilinear.Generic.MultiCore.Serialize: toBinaryFile :: (Serialize a, Unbox a) => Tensor a -> String -> IO ()
+ Multilinear.Generic.MultiCore.Serialize: toCSVFile :: (ToField a, Unbox a) => Tensor a -> String -> IO ()
+ Multilinear.Generic.MultiCore.Serialize: toJSON :: (ToJSON a, Unbox a) => Tensor a -> ByteString
+ Multilinear.Generic.MultiCore.Serialize: toJSONFile :: (ToJSON a, Unbox a) => Tensor a -> String -> IO ()
+ Multilinear.Generic.Sequential.Serialize: fromBinary :: (Serialize a, Unbox a) => ByteString -> Either String (Tensor a)
+ Multilinear.Generic.Sequential.Serialize: fromBinaryFile :: (Serialize a, Unbox a) => String -> ExceptT String IO (Tensor a)
+ Multilinear.Generic.Sequential.Serialize: fromCSVFile :: (FromField a, Unbox a) => String -> Char -> String -> ExceptT String IO (Tensor a)
+ Multilinear.Generic.Sequential.Serialize: fromJSON :: (FromJSON a, Unbox a) => ByteString -> Maybe (Tensor a)
+ Multilinear.Generic.Sequential.Serialize: fromJSONFile :: (FromJSON a, Unbox a) => String -> MaybeT IO (Tensor a)
+ Multilinear.Generic.Sequential.Serialize: instance (Data.Aeson.Types.FromJSON.FromJSON a, Data.Vector.Unboxed.Base.Unbox a) => Data.Aeson.Types.FromJSON.FromJSON (Multilinear.Generic.Sequential.Tensor a)
+ Multilinear.Generic.Sequential.Serialize: instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Vector.Unboxed.Base.Unbox a) => Data.Aeson.Types.ToJSON.ToJSON (Multilinear.Generic.Sequential.Tensor a)
+ Multilinear.Generic.Sequential.Serialize: instance (Data.Csv.Conversion.FromField a, Data.Vector.Unboxed.Base.Unbox a) => Data.Csv.Conversion.FromRecord (Multilinear.Generic.Sequential.Tensor a)
+ Multilinear.Generic.Sequential.Serialize: instance (Data.Csv.Conversion.ToField a, Data.Vector.Unboxed.Base.Unbox a) => Data.Csv.Conversion.ToRecord (Multilinear.Generic.Sequential.Tensor a)
+ Multilinear.Generic.Sequential.Serialize: instance (Data.Serialize.Serialize a, Data.Vector.Unboxed.Base.Unbox a) => Data.Serialize.Serialize (Multilinear.Generic.Sequential.Tensor a)
+ Multilinear.Generic.Sequential.Serialize: toBinary :: (Serialize a, Unbox a) => Tensor a -> ByteString
+ Multilinear.Generic.Sequential.Serialize: toBinaryFile :: (Serialize a, Unbox a) => Tensor a -> String -> IO ()
+ Multilinear.Generic.Sequential.Serialize: toCSVFile :: (ToField a, Unbox a) => Tensor a -> String -> IO ()
+ Multilinear.Generic.Sequential.Serialize: toJSON :: (ToJSON a, Unbox a) => Tensor a -> ByteString
+ Multilinear.Generic.Sequential.Serialize: toJSONFile :: (ToJSON a, Unbox a) => Tensor a -> String -> IO ()
Files
- ChangeLog.md +3/−0
- multilinear-io.cabal +11/−3
- src/Multilinear/Generic/MultiCore/Serialize.hs +178/−0
- src/Multilinear/Generic/Sequential/Serialize.hs +178/−0
- src/Multilinear/Generic/Serialize.hs +2/−164
- test/binary/Spec.hs +16/−26
- test/binary/Test/MultiCore.hs +27/−0
- test/binary/Test/Sequential.hs +27/−0
- test/csv/Spec.hs +52/−84
- test/csv/Test/MultiCore.hs +77/−0
- test/csv/Test/Sequential.hs +77/−0
- test/json/Spec.hs +15/−25
- test/json/Test/MultiCore.hs +27/−0
- test/json/Test/Sequential.hs +27/−0
ChangeLog.md view
@@ -1,3 +1,6 @@+# 0.5.0.0, 2018-11-25 +- ported to multilinear-0.5.0.0 + # 0.4.0.0, 2018-11-24 - ported to multilinear-0.4.0.0 - added more robust tests
multilinear-io.cabal view
@@ -2,11 +2,11 @@ -- -- see: https://github.com/sol/hpack ----- hash: e8f399289e551ae39e7efffa83e1b8f92a5cb52d1d5f332879287e1a14387be1+-- hash: a89d39464086b0628b927b55e010617142476609ffbe530733fcd3edbcf08938 name: multilinear-io-version: 0.4.0.0-synopsis: Conduit-vased input/output capability for multilinear package.+version: 0.5.0.0+synopsis: Conduit-based input/output capability for multilinear package. description: Conduit-based input & output capability for multilinear package <https://hackage.haskell.org/package/multilinear>. Supports various file formats: binary, CSV, JSON. More information available on GitHub: <https://github.com/ArturB/multilinear-io#readme> category: Machine learning homepage: https://github.com/ArturB/multilinear-io#readme@@ -28,6 +28,8 @@ library exposed-modules:+ Multilinear.Generic.MultiCore.Serialize+ Multilinear.Generic.Sequential.Serialize Multilinear.Generic.Serialize Multilinear.Index.Finite.Serialize other-modules:@@ -55,6 +57,8 @@ type: exitcode-stdio-1.0 main-is: Spec.hs other-modules:+ Test.MultiCore+ Test.Sequential Paths_multilinear_io hs-source-dirs: test/binary@@ -73,6 +77,8 @@ type: exitcode-stdio-1.0 main-is: Spec.hs other-modules:+ Test.MultiCore+ Test.Sequential Paths_multilinear_io hs-source-dirs: test/csv@@ -91,6 +97,8 @@ type: exitcode-stdio-1.0 main-is: Spec.hs other-modules:+ Test.MultiCore+ Test.Sequential Paths_multilinear_io hs-source-dirs: test/json
+ src/Multilinear/Generic/MultiCore/Serialize.hs view
@@ -0,0 +1,178 @@+{-| +Module : Multilinear.Generic.Serialize +Description : Generic array tensor serialization: binary, JSON, CSV. +Copyright : (c) Artur M. Brodzki, 2018 +License : BSD3 +Maintainer : artur@brodzki.org +Stability : experimental +Portability : Windows/POSIX + +-} + +module Multilinear.Generic.MultiCore.Serialize ( + toBinary, toBinaryFile, + fromBinary, fromBinaryFile, + Multilinear.Generic.MultiCore.Serialize.toJSON, + Multilinear.Generic.MultiCore.Serialize.toJSONFile, + Multilinear.Generic.MultiCore.Serialize.fromJSON, + Multilinear.Generic.MultiCore.Serialize.fromJSONFile, + fromCSVFile, toCSVFile +) where + +import Codec.Compression.GZip +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except +import Control.Monad.Trans.Maybe +import Data.Aeson +import qualified Data.ByteString.Internal as BS +import qualified Data.ByteString.Lazy as ByteString +import Data.Conduit +import Data.Conduit.Combinators +import Data.Csv +import Data.Either +import Data.Serialize +import qualified Data.Vector as Boxed +import Data.Vector.Serialize () +import qualified Data.Vector.Unboxed as Unboxed +import Multilinear.Generic.MultiCore +import qualified Multilinear.Index.Finite as Finite +import Multilinear.Index.Finite.Serialize () + +-- Binary serialization instance +instance (Serialize a, Unboxed.Unbox a) => Serialize (Tensor a) +-- JSON serialization instance +instance (ToJSON a, Unboxed.Unbox a) => ToJSON (Tensor a) +-- JSON deserialization instance +instance (FromJSON a, Unboxed.Unbox a) => FromJSON (Tensor a) +-- CSV serialization instance +instance (ToField a, Unboxed.Unbox a) => ToRecord (Tensor a) where + toRecord (Scalar x) = record [toField x] + toRecord (SimpleFinite _ scalars) = toRecord scalars + toRecord _ = error "Only 1-order tensor may be converted to record!" +instance (FromField a, Unboxed.Unbox a) => FromRecord (Tensor a) where + parseRecord v = + if Boxed.length v == 1 then + Scalar <$> v .! 0 + else + error "non-scalar" + + +{-| Serialize tensor to zlib compressed binary string -} +toBinary :: ( + Serialize a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> ByteString.ByteString -- ^ Tensor serialized to lazy ByteString +toBinary = compress . Data.Serialize.encodeLazy + +{-| Write tensor to binary file. Uses compression with gzip -} +toBinaryFile :: ( + Serialize a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> String -- ^ File name + -> IO () +toBinaryFile t fileName = do + let bs = toBinary t + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +{-| Deserialize tensor from zlib compressed binary string -} +fromBinary :: ( + Serialize a, Unboxed.Unbox a + ) => ByteString.ByteString -- ^ ByteString to deserialize + -> Either String (Tensor a) -- ^ Deserialized tensor or an error message. +fromBinary = Data.Serialize.decodeLazy . decompress + +{-| Read tensor from binary file -} +fromBinaryFile :: ( + Serialize a, Unboxed.Unbox a + ) => String -- ^ File path. + -> ExceptT String IO (Tensor a) -- ^ Deserialized tensor or an error message +fromBinaryFile fileName = do + contents <- lift $ runConduitRes $ + sourceFile fileName .| sinkLazy + ExceptT $ return $ fromBinary contents + +{-| Serialize tensor to JSON string -} +toJSON :: ( + ToJSON a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize. + -> ByteString.ByteString -- ^ Tensor serialized to lazy ByteString. +toJSON = Data.Aeson.encode + +{-| Write tensor to JSON file -} +toJSONFile :: ( + ToJSON a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> String -- ^ File path. + -> IO () +toJSONFile t fileName = do + let bs = Multilinear.Generic.MultiCore.Serialize.toJSON t + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +{-| Deserialize tensor from JSON string -} +fromJSON :: ( + FromJSON a, Unboxed.Unbox a + ) => ByteString.ByteString -- ^ ByteString to deserialize + -> Maybe (Tensor a) -- ^ Deserialized tensor or Nothing, if deserialization error occured. +fromJSON = Data.Aeson.decode + +{-| Read tensor from JSON file -} +fromJSONFile :: ( + FromJSON a, Unboxed.Unbox a + ) => String -- ^ File path. + -> MaybeT IO (Tensor a) -- ^ Deserialized tensor or Nothing, if error occured. +fromJSONFile fileName = do + contents <- lift $ runConduitRes $ + sourceFile fileName .| sinkLazy + MaybeT $ return $ Multilinear.Generic.MultiCore.Serialize.fromJSON contents + +{-| Write tensor to CSV file -} +toCSVFile :: ( + ToField a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> String -- ^ File path + -> IO () + +-- Encoding Scalar value +toCSVFile s@(Scalar _) fileName = do + let bs = Data.Csv.encode [s] + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +-- Encoding SimpleFinite (1D) tensor +toCSVFile (SimpleFinite _ vs) fileName = do + let rows = [vs] + let bs = Data.Csv.encode rows + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +-- Encoding FiniteTensor (many dimensions) +toCSVFile (FiniteTensor _ vrows) fileName = do + let rows = Boxed.toList vrows + let bs = Data.Csv.encode rows + runConduitRes $ + sourceLazy bs .| sinkFile fileName + + +{-| Read tensor from CSV -} +fromCSVFile :: ( + FromField a, Unboxed.Unbox a + ) => String -- ^ File path. + -> Char -- ^ CSV separator + -> String -- ^ Matrix indices names + -> ExceptT String IO (Tensor a) -- ^ Deserialized tensor or an error message +fromCSVFile fileName separator [conI,covI] = do + --let csvSettings = CSVSettings separator Nothing + contents <- lift $ runConduitRes $ + sourceFile fileName .| sinkLazy + let decodedData = Data.Csv.decodeWith (DecodeOptions (BS.c2w separator)) NoHeader contents :: (FromField a, Unboxed.Unbox a) => Either String (Boxed.Vector (Unboxed.Vector a)) + if isLeft decodedData + then do + let msg = fromLeft "" decodedData + ExceptT $ return $ Left msg + else do + let components = fromRight Boxed.empty decodedData + let rows = (\r -> SimpleFinite (Finite.Covariant (Unboxed.length r) [covI]) r) <$> components + ExceptT $ return $ Right $ FiniteTensor (Finite.Contravariant (Boxed.length rows) [conI]) rows +fromCSVFile _ _ _ = error "You must provide exactly two indices names!"
+ src/Multilinear/Generic/Sequential/Serialize.hs view
@@ -0,0 +1,178 @@+{-| +Module : Multilinear.Generic.Serialize +Description : Generic array tensor serialization: binary, JSON, CSV. +Copyright : (c) Artur M. Brodzki, 2018 +License : BSD3 +Maintainer : artur@brodzki.org +Stability : experimental +Portability : Windows/POSIX + +-} + +module Multilinear.Generic.Sequential.Serialize ( + toBinary, toBinaryFile, + fromBinary, fromBinaryFile, + Multilinear.Generic.Sequential.Serialize.toJSON, + Multilinear.Generic.Sequential.Serialize.toJSONFile, + Multilinear.Generic.Sequential.Serialize.fromJSON, + Multilinear.Generic.Sequential.Serialize.fromJSONFile, + fromCSVFile, toCSVFile +) where + +import Codec.Compression.GZip +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except +import Control.Monad.Trans.Maybe +import Data.Aeson +import qualified Data.ByteString.Internal as BS +import qualified Data.ByteString.Lazy as ByteString +import Data.Conduit +import Data.Conduit.Combinators +import Data.Csv +import Data.Either +import Data.Serialize +import qualified Data.Vector as Boxed +import Data.Vector.Serialize () +import qualified Data.Vector.Unboxed as Unboxed +import Multilinear.Generic.Sequential +import qualified Multilinear.Index.Finite as Finite +import Multilinear.Index.Finite.Serialize () + +-- Binary serialization instance +instance (Serialize a, Unboxed.Unbox a) => Serialize (Tensor a) +-- JSON serialization instance +instance (ToJSON a, Unboxed.Unbox a) => ToJSON (Tensor a) +-- JSON deserialization instance +instance (FromJSON a, Unboxed.Unbox a) => FromJSON (Tensor a) +-- CSV serialization instance +instance (ToField a, Unboxed.Unbox a) => ToRecord (Tensor a) where + toRecord (Scalar x) = record [toField x] + toRecord (SimpleFinite _ scalars) = toRecord scalars + toRecord _ = error "Only 1-order tensor may be converted to record!" +instance (FromField a, Unboxed.Unbox a) => FromRecord (Tensor a) where + parseRecord v = + if Boxed.length v == 1 then + Scalar <$> v .! 0 + else + error "non-scalar" + + +{-| Serialize tensor to zlib compressed binary string -} +toBinary :: ( + Serialize a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> ByteString.ByteString -- ^ Tensor serialized to lazy ByteString +toBinary = compress . Data.Serialize.encodeLazy + +{-| Write tensor to binary file. Uses compression with gzip -} +toBinaryFile :: ( + Serialize a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> String -- ^ File name + -> IO () +toBinaryFile t fileName = do + let bs = toBinary t + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +{-| Deserialize tensor from zlib compressed binary string -} +fromBinary :: ( + Serialize a, Unboxed.Unbox a + ) => ByteString.ByteString -- ^ ByteString to deserialize + -> Either String (Tensor a) -- ^ Deserialized tensor or an error message. +fromBinary = Data.Serialize.decodeLazy . decompress + +{-| Read tensor from binary file -} +fromBinaryFile :: ( + Serialize a, Unboxed.Unbox a + ) => String -- ^ File path. + -> ExceptT String IO (Tensor a) -- ^ Deserialized tensor or an error message +fromBinaryFile fileName = do + contents <- lift $ runConduitRes $ + sourceFile fileName .| sinkLazy + ExceptT $ return $ fromBinary contents + +{-| Serialize tensor to JSON string -} +toJSON :: ( + ToJSON a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize. + -> ByteString.ByteString -- ^ Tensor serialized to lazy ByteString. +toJSON = Data.Aeson.encode + +{-| Write tensor to JSON file -} +toJSONFile :: ( + ToJSON a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> String -- ^ File path. + -> IO () +toJSONFile t fileName = do + let bs = Multilinear.Generic.Sequential.Serialize.toJSON t + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +{-| Deserialize tensor from JSON string -} +fromJSON :: ( + FromJSON a, Unboxed.Unbox a + ) => ByteString.ByteString -- ^ ByteString to deserialize + -> Maybe (Tensor a) -- ^ Deserialized tensor or Nothing, if deserialization error occured. +fromJSON = Data.Aeson.decode + +{-| Read tensor from JSON file -} +fromJSONFile :: ( + FromJSON a, Unboxed.Unbox a + ) => String -- ^ File path. + -> MaybeT IO (Tensor a) -- ^ Deserialized tensor or Nothing, if error occured. +fromJSONFile fileName = do + contents <- lift $ runConduitRes $ + sourceFile fileName .| sinkLazy + MaybeT $ return $ Multilinear.Generic.Sequential.Serialize.fromJSON contents + +{-| Write tensor to CSV file -} +toCSVFile :: ( + ToField a, Unboxed.Unbox a + ) => Tensor a -- ^ Tensor to serialize + -> String -- ^ File path + -> IO () + +-- Encoding Scalar value +toCSVFile s@(Scalar _) fileName = do + let bs = Data.Csv.encode [s] + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +-- Encoding SimpleFinite (1D) tensor +toCSVFile (SimpleFinite _ vs) fileName = do + let rows = [vs] + let bs = Data.Csv.encode rows + runConduitRes $ + sourceLazy bs .| sinkFile fileName + +-- Encoding FiniteTensor (many dimensions) +toCSVFile (FiniteTensor _ vrows) fileName = do + let rows = Boxed.toList vrows + let bs = Data.Csv.encode rows + runConduitRes $ + sourceLazy bs .| sinkFile fileName + + +{-| Read tensor from CSV -} +fromCSVFile :: ( + FromField a, Unboxed.Unbox a + ) => String -- ^ File path. + -> Char -- ^ CSV separator + -> String -- ^ Matrix indices names + -> ExceptT String IO (Tensor a) -- ^ Deserialized tensor or an error message +fromCSVFile fileName separator [conI,covI] = do + --let csvSettings = CSVSettings separator Nothing + contents <- lift $ runConduitRes $ + sourceFile fileName .| sinkLazy + let decodedData = Data.Csv.decodeWith (DecodeOptions (BS.c2w separator)) NoHeader contents :: (FromField a, Unboxed.Unbox a) => Either String (Boxed.Vector (Unboxed.Vector a)) + if isLeft decodedData + then do + let msg = fromLeft "" decodedData + ExceptT $ return $ Left msg + else do + let components = fromRight Boxed.empty decodedData + let rows = (\r -> SimpleFinite (Finite.Covariant (Unboxed.length r) [covI]) r) <$> components + ExceptT $ return $ Right $ FiniteTensor (Finite.Contravariant (Boxed.length rows) [conI]) rows +fromCSVFile _ _ _ = error "You must provide exactly two indices names!"
src/Multilinear/Generic/Serialize.hs view
@@ -10,169 +10,7 @@ -} module Multilinear.Generic.Serialize ( - toBinary, toBinaryFile, - fromBinary, fromBinaryFile, - Multilinear.Generic.Serialize.toJSON, - Multilinear.Generic.Serialize.toJSONFile, - Multilinear.Generic.Serialize.fromJSON, - Multilinear.Generic.Serialize.fromJSONFile, - fromCSVFile, toCSVFile + module DefaultTensorImplementation ) where -import Codec.Compression.GZip -import Control.Monad.Trans.Class -import Control.Monad.Trans.Except -import Control.Monad.Trans.Maybe -import Data.Aeson -import qualified Data.ByteString.Internal as BS -import qualified Data.ByteString.Lazy as ByteString -import Data.Conduit -import Data.Conduit.Combinators -import Data.Csv -import Data.Either -import Data.Serialize -import qualified Data.Vector as Boxed -import Data.Vector.Serialize () -import qualified Data.Vector.Unboxed as Unboxed -import Multilinear.Generic -import qualified Multilinear.Index.Finite as Finite -import Multilinear.Index.Finite.Serialize () - --- Binary serialization instance -instance (Serialize a, Unboxed.Unbox a) => Serialize (Tensor a) --- JSON serialization instance -instance (ToJSON a, Unboxed.Unbox a) => ToJSON (Tensor a) --- JSON deserialization instance -instance (FromJSON a, Unboxed.Unbox a) => FromJSON (Tensor a) --- CSV serialization instance -instance (ToField a, Unboxed.Unbox a) => ToRecord (Tensor a) where - toRecord (Scalar x) = record [toField x] - toRecord (SimpleFinite _ scalars) = toRecord scalars - toRecord _ = error "Only 1-order tensor may be converted to record!" -instance (FromField a, Unboxed.Unbox a) => FromRecord (Tensor a) where - parseRecord v = - if Boxed.length v == 1 then - Scalar <$> v .! 0 - else - error "non-scalar" - - -{-| Serialize tensor to zlib compressed binary string -} -toBinary :: ( - Serialize a, Unboxed.Unbox a - ) => Tensor a -- ^ Tensor to serialize - -> ByteString.ByteString -- ^ Tensor serialized to lazy ByteString -toBinary = compress . Data.Serialize.encodeLazy - -{-| Write tensor to binary file. Uses compression with gzip -} -toBinaryFile :: ( - Serialize a, Unboxed.Unbox a - ) => Tensor a -- ^ Tensor to serialize - -> String -- ^ File name - -> IO () -toBinaryFile t fileName = do - let bs = toBinary t - runConduitRes $ - sourceLazy bs .| sinkFile fileName - -{-| Deserialize tensor from zlib compressed binary string -} -fromBinary :: ( - Serialize a, Unboxed.Unbox a - ) => ByteString.ByteString -- ^ ByteString to deserialize - -> Either String (Tensor a) -- ^ Deserialized tensor or an error message. -fromBinary = Data.Serialize.decodeLazy . decompress - -{-| Read tensor from binary file -} -fromBinaryFile :: ( - Serialize a, Unboxed.Unbox a - ) => String -- ^ File path. - -> ExceptT String IO (Tensor a) -- ^ Deserialized tensor or an error message -fromBinaryFile fileName = do - contents <- lift $ runConduitRes $ - sourceFile fileName .| sinkLazy - ExceptT $ return $ fromBinary contents - -{-| Serialize tensor to JSON string -} -toJSON :: ( - ToJSON a, Unboxed.Unbox a - ) => Tensor a -- ^ Tensor to serialize. - -> ByteString.ByteString -- ^ Tensor serialized to lazy ByteString. -toJSON = Data.Aeson.encode - -{-| Write tensor to JSON file -} -toJSONFile :: ( - ToJSON a, Unboxed.Unbox a - ) => Tensor a -- ^ Tensor to serialize - -> String -- ^ File path. - -> IO () -toJSONFile t fileName = do - let bs = Multilinear.Generic.Serialize.toJSON t - runConduitRes $ - sourceLazy bs .| sinkFile fileName - -{-| Deserialize tensor from JSON string -} -fromJSON :: ( - FromJSON a, Unboxed.Unbox a - ) => ByteString.ByteString -- ^ ByteString to deserialize - -> Maybe (Tensor a) -- ^ Deserialized tensor or Nothing, if deserialization error occured. -fromJSON = Data.Aeson.decode - -{-| Read tensor from JSON file -} -fromJSONFile :: ( - FromJSON a, Unboxed.Unbox a - ) => String -- ^ File path. - -> MaybeT IO (Tensor a) -- ^ Deserialized tensor or Nothing, if error occured. -fromJSONFile fileName = do - contents <- lift $ runConduitRes $ - sourceFile fileName .| sinkLazy - MaybeT $ return $ Multilinear.Generic.Serialize.fromJSON contents - -{-| Write tensor to CSV file -} -toCSVFile :: ( - ToField a, Unboxed.Unbox a - ) => Tensor a -- ^ Tensor to serialize - -> String -- ^ File path - -> IO () - --- Encoding Scalar value -toCSVFile s@(Scalar _) fileName = do - let bs = Data.Csv.encode [s] - runConduitRes $ - sourceLazy bs .| sinkFile fileName - --- Encoding SimpleFinite (1D) tensor -toCSVFile (SimpleFinite _ vs) fileName = do - let rows = [vs] - let bs = Data.Csv.encode rows - runConduitRes $ - sourceLazy bs .| sinkFile fileName - --- Encoding FiniteTensor (many dimensions) -toCSVFile (FiniteTensor _ vrows) fileName = do - let rows = Boxed.toList vrows - let bs = Data.Csv.encode rows - runConduitRes $ - sourceLazy bs .| sinkFile fileName - - -{-| Read tensor from CSV -} -fromCSVFile :: ( - FromField a, Unboxed.Unbox a - ) => String -- ^ File path. - -> Char -- ^ CSV separator - -> String -- ^ Matrix indices names - -> ExceptT String IO (Tensor a) -- ^ Deserialized tensor or an error message -fromCSVFile fileName separator [conI,covI] = do - --let csvSettings = CSVSettings separator Nothing - contents <- lift $ runConduitRes $ - sourceFile fileName .| sinkLazy - let decodedData = Data.Csv.decodeWith (DecodeOptions (BS.c2w separator)) NoHeader contents :: (FromField a, Unboxed.Unbox a) => Either String (Boxed.Vector (Unboxed.Vector a)) - if isLeft decodedData - then do - let msg = fromLeft "" decodedData - ExceptT $ return $ Left msg - else do - let components = fromRight Boxed.empty decodedData - let rows = (\r -> SimpleFinite (Finite.Covariant (Unboxed.length r) [covI]) r) <$> components - ExceptT $ return $ Right $ FiniteTensor (Finite.Contravariant (Boxed.length rows) [conI]) rows -fromCSVFile _ _ _ = error "You must provide exactly two indices names!" +import Multilinear.Generic.Sequential.Serialize as DefaultTensorImplementation
test/binary/Spec.hs view
@@ -2,42 +2,32 @@ main ) where -import Control.Monad.Trans.Class import Control.Monad.Trans.Except -import Data.Maybe -import Multilinear.Class -import Multilinear.Generic -import Multilinear.Generic.Serialize -import Multilinear.Index -import qualified Multilinear.Matrix as Matrix +import qualified Multilinear.Generic.MultiCore as MultiCore +import qualified Multilinear.Generic.Sequential as Sequential +import qualified Multilinear.Matrix as Matrix import System.Directory +import Test.MultiCore +import Test.Sequential fileName1 :: String fileName1 = "test/m1" -m1 :: Tensor Double -m1 = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) - -writeMatrixBinary :: Tensor Double -> String -> IO () -writeMatrixBinary m fileName = do - let [xsize,ysize] = indexSize <$> indices m1 - putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".zlib..." - m `toBinaryFile` (fileName ++ ".zlib") - putStrLn $ "Matrix successfully written!" +m1Seq :: Sequential.Tensor Double +m1Seq = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) -readMatrixBinary :: String -> ExceptT String IO () -readMatrixBinary fileName = do - lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".zlib..." - m1' <- fromBinaryFile (fileName ++ ".zlib") - if m1' == m1 then - lift $ putStrLn "Matrix successfully read!" - else - ExceptT $ return $ Left "Matrix deserialization error" +m1MC :: MultiCore.Tensor Double +m1MC = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) -- ENTRY POINT main :: IO () main = do - writeMatrixBinary m1 fileName1 - runExceptT $ readMatrixBinary fileName1 + putStrLn "Testing MultiCore..." + Test.MultiCore.writeMatrixBinary m1MC fileName1 + runExceptT $ Test.MultiCore.readMatrixBinary m1MC fileName1 + removeFile $ fileName1 ++ ".zlib" + putStrLn "Testing Sequential..." + Test.Sequential.writeMatrixBinary m1Seq fileName1 + runExceptT $ Test.Sequential.readMatrixBinary m1Seq fileName1 removeFile $ fileName1 ++ ".zlib" return ()
+ test/binary/Test/MultiCore.hs view
@@ -0,0 +1,27 @@+module Test.MultiCore ( + writeMatrixBinary, readMatrixBinary +) where + +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except +import Data.Maybe +import Multilinear.Class +import Multilinear.Generic.MultiCore +import Multilinear.Generic.MultiCore.Serialize +import Multilinear.Index + +writeMatrixBinary :: Tensor Double -> String -> IO () +writeMatrixBinary m fileName = do + let [xsize,ysize] = indexSize <$> indices m + putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".zlib..." + m `toBinaryFile` (fileName ++ ".zlib") + putStrLn $ "Matrix successfully written!" + +readMatrixBinary :: Tensor Double -> String -> ExceptT String IO () +readMatrixBinary m fileName = do + lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".zlib..." + m1' <- fromBinaryFile (fileName ++ ".zlib") + if m1' == m then + lift $ putStrLn "Matrix successfully read!" + else + ExceptT $ return $ Left "Matrix deserialization error"
+ test/binary/Test/Sequential.hs view
@@ -0,0 +1,27 @@+module Test.Sequential ( + writeMatrixBinary, readMatrixBinary +) where + +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except +import Data.Maybe +import Multilinear.Class +import Multilinear.Generic.Sequential +import Multilinear.Generic.Sequential.Serialize +import Multilinear.Index + +writeMatrixBinary :: Tensor Double -> String -> IO () +writeMatrixBinary m fileName = do + let [xsize,ysize] = indexSize <$> indices m + putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".zlib..." + m `toBinaryFile` (fileName ++ ".zlib") + putStrLn $ "Matrix successfully written!" + +readMatrixBinary :: Tensor Double -> String -> ExceptT String IO () +readMatrixBinary m fileName = do + lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".zlib..." + m1' <- fromBinaryFile (fileName ++ ".zlib") + if m1' == m then + lift $ putStrLn "Matrix successfully read!" + else + ExceptT $ return $ Left "Matrix deserialization error"
test/csv/Spec.hs view
@@ -2,108 +2,76 @@ main ) where -import Control.Monad.Trans.Class import Control.Monad.Trans.Except -import Data.Maybe -import Multilinear.Class -import Multilinear.Generic -import Multilinear.Generic.Serialize -import Multilinear.Index -import qualified Multilinear.Matrix as Matrix -import qualified Multilinear.Vector as Vector +import qualified Multilinear.Generic.MultiCore as MultiCore +import qualified Multilinear.Generic.Sequential as Sequential +import qualified Multilinear.Matrix as Matrix +import qualified Multilinear.Vector as Vector import System.Directory - -matrix :: Tensor Double -matrix = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) - -vector :: Tensor Double -vector = Vector.fromIndices "i" 50 $ \i -> cos (fromIntegral i) - -form :: Tensor Double -form = Vector.fromIndices "i" 50 $ \i -> cos (fromIntegral i) - -scalar :: Tensor Double -scalar = Scalar 5.0 +import Test.MultiCore +import Test.Sequential -writeScalarCSV :: Tensor Double -> String -> IO () -writeScalarCSV m fileName = do - putStrLn $ "Writing scalar to " ++ fileName ++ ".csv..." - m `toCSVFile` (fileName ++ ".csv") - putStrLn "Scalar successfully written!" +matrixSeq :: Sequential.Tensor Double +matrixSeq = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) -readScalarCSV :: Tensor Double -> String -> ExceptT String IO () -readScalarCSV m fileName = do - lift $ putStrLn $ "Reading scalar s1 from " ++ fileName ++ ".csv..." - (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" - if m1' == m then - lift $ putStrLn "Scalar successfully read!" - else - ExceptT $ return $ Left "Scalar deserialization error" +vectorSeq :: Sequential.Tensor Double +vectorSeq = Vector.fromIndices "i" 50 $ \i -> cos (fromIntegral i) -writeVectorCSV :: Tensor Double -> String -> IO () -writeVectorCSV m fileName = do - let size = fromJust . indexSize <$> head $ indices m - putStrLn $ "Writing " ++ show size ++ " elements vector to " ++ fileName ++ ".csv..." - m `toCSVFile` (fileName ++ ".csv") - putStrLn "Vector successfully written!" +formSeq :: Sequential.Tensor Double +formSeq = Vector.fromIndices "i" 50 $ \i -> cos (fromIntegral i) -readVectorCSV :: Tensor Double -> String -> ExceptT String IO () -readVectorCSV m fileName = do - lift $ putStrLn $ "Reading vector v1 from " ++ fileName ++ ".csv..." - (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" - if m1' == m then - lift $ putStrLn "Vector successfully read!" - else - ExceptT $ return $ Left "Vector deserialization error" +scalarSeq :: Sequential.Tensor Double +scalarSeq = Sequential.Scalar 5.0 -writeFormCSV :: Tensor Double -> String -> IO () -writeFormCSV m fileName = do - let size = fromJust . indexSize <$> head $ indices m - putStrLn $ "Writing " ++ show size ++ " elements form to " ++ fileName ++ ".csv..." - m `toCSVFile` (fileName ++ ".csv") - putStrLn "Form successfully written!" +matrixMC :: MultiCore.Tensor Double +matrixMC = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) -readFormCSV :: Tensor Double -> String -> ExceptT String IO () -readFormCSV m fileName = do - lift $ putStrLn $ "Reading form f1 from " ++ fileName ++ ".csv..." - (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" - if m1' == m then - lift $ putStrLn "Form successfully read!" - else - ExceptT $ return $ Left "Form deserialization error" +vectorMC :: MultiCore.Tensor Double +vectorMC = Vector.fromIndices "i" 50 $ \i -> cos (fromIntegral i) -writeMatrixCSV :: Tensor Double -> String -> IO () -writeMatrixCSV m fileName = do - let [xsize,ysize] = indexSize <$> indices m - putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".csv..." - m `toCSVFile` (fileName ++ ".csv") - putStrLn "Matrix successfully written!" +formMC :: MultiCore.Tensor Double +formMC = Vector.fromIndices "i" 50 $ \i -> cos (fromIntegral i) -readMatrixCSV :: Tensor Double -> String -> ExceptT String IO () -readMatrixCSV m fileName = do - lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".csv..." - (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" - if m1' == m then - lift $ putStrLn "Matrix successfully read!" - else - ExceptT $ return $ Left "Matrix deserialization error" +scalarMC :: MultiCore.Tensor Double +scalarMC = MultiCore.Scalar 5.0 - -- ENTRY POINT main :: IO () main = do + -- TEST MULTICORE + putStrLn "Testing MultiCore..." -- Scalar CSV read/write - writeScalarCSV scalar "test/s1" - runExceptT $ readScalarCSV scalar "test/s1" + Test.MultiCore.writeScalarCSV scalarMC "test/s1" + runExceptT $ Test.MultiCore.readScalarCSV scalarMC "test/s1" -- Vector CSV read/write - writeVectorCSV vector "test/v1" - runExceptT $ readVectorCSV vector "test/v1" + Test.MultiCore.writeVectorCSV vectorMC "test/v1" + runExceptT $ Test.MultiCore.readVectorCSV vectorMC "test/v1" -- Form CSV read/write - writeFormCSV form "test/f1" - runExceptT $ readFormCSV form "test/f1" + Test.MultiCore.writeFormCSV formMC "test/f1" + runExceptT $ Test.MultiCore.readFormCSV formMC "test/f1" -- Matrix CSV read/write - writeMatrixCSV matrix "test/m1" - runExceptT $ readMatrixCSV matrix "test/m1" + Test.MultiCore.writeMatrixCSV matrixMC "test/m1" + runExceptT $ Test.MultiCore.readMatrixCSV matrixMC "test/m1" + -- Remove test file + removeFile "test/s1.csv" + removeFile "test/v1.csv" + removeFile "test/f1.csv" + removeFile "test/m1.csv" + + -- TEST SEQUENTIAL + putStrLn "Testing Sequential..." + -- Scalar CSV read/write + Test.Sequential.writeScalarCSV scalarSeq "test/s1" + runExceptT $ Test.Sequential.readScalarCSV scalarSeq "test/s1" + -- Vector CSV read/write + Test.Sequential.writeVectorCSV vectorSeq "test/v1" + runExceptT $ Test.Sequential.readVectorCSV vectorSeq "test/v1" + -- Form CSV read/write + Test.Sequential.writeFormCSV formSeq "test/f1" + runExceptT $ Test.Sequential.readFormCSV formSeq "test/f1" + -- Matrix CSV read/write + Test.Sequential.writeMatrixCSV matrixSeq "test/m1" + runExceptT $ Test.Sequential.readMatrixCSV matrixSeq "test/m1" -- Remove test file removeFile "test/s1.csv" removeFile "test/v1.csv"
+ test/csv/Test/MultiCore.hs view
@@ -0,0 +1,77 @@+module Test.MultiCore ( + writeScalarCSV, readScalarCSV, + writeVectorCSV, readVectorCSV, + writeFormCSV, readFormCSV, + writeMatrixCSV, readMatrixCSV +) where + +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except +import Data.Maybe +import Multilinear.Class +import Multilinear.Generic.MultiCore +import Multilinear.Generic.MultiCore.Serialize +import Multilinear.Index + +writeScalarCSV :: Tensor Double -> String -> IO () +writeScalarCSV m fileName = do + putStrLn $ "Writing scalar to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Scalar successfully written!" + +readScalarCSV :: Tensor Double -> String -> ExceptT String IO () +readScalarCSV m fileName = do + lift $ putStrLn $ "Reading scalar s1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Scalar successfully read!" + else + ExceptT $ return $ Left "Scalar deserialization error" + +writeVectorCSV :: Tensor Double -> String -> IO () +writeVectorCSV m fileName = do + let size = fromJust . indexSize <$> head $ indices m + putStrLn $ "Writing " ++ show size ++ " elements vector to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Vector successfully written!" + +readVectorCSV :: Tensor Double -> String -> ExceptT String IO () +readVectorCSV m fileName = do + lift $ putStrLn $ "Reading vector v1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Vector successfully read!" + else + ExceptT $ return $ Left "Vector deserialization error" + +writeFormCSV :: Tensor Double -> String -> IO () +writeFormCSV m fileName = do + let size = fromJust . indexSize <$> head $ indices m + putStrLn $ "Writing " ++ show size ++ " elements form to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Form successfully written!" + +readFormCSV :: Tensor Double -> String -> ExceptT String IO () +readFormCSV m fileName = do + lift $ putStrLn $ "Reading form f1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Form successfully read!" + else + ExceptT $ return $ Left "Form deserialization error" + +writeMatrixCSV :: Tensor Double -> String -> IO () +writeMatrixCSV m fileName = do + let [xsize,ysize] = indexSize <$> indices m + putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Matrix successfully written!" + +readMatrixCSV :: Tensor Double -> String -> ExceptT String IO () +readMatrixCSV m fileName = do + lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Matrix successfully read!" + else + ExceptT $ return $ Left "Matrix deserialization error"
+ test/csv/Test/Sequential.hs view
@@ -0,0 +1,77 @@+module Test.Sequential ( + writeScalarCSV, readScalarCSV, + writeVectorCSV, readVectorCSV, + writeFormCSV, readFormCSV, + writeMatrixCSV, readMatrixCSV +) where + +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except +import Data.Maybe +import Multilinear.Class +import Multilinear.Generic.Sequential +import Multilinear.Generic.Sequential.Serialize +import Multilinear.Index + +writeScalarCSV :: Tensor Double -> String -> IO () +writeScalarCSV m fileName = do + putStrLn $ "Writing scalar to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Scalar successfully written!" + +readScalarCSV :: Tensor Double -> String -> ExceptT String IO () +readScalarCSV m fileName = do + lift $ putStrLn $ "Reading scalar s1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Scalar successfully read!" + else + ExceptT $ return $ Left "Scalar deserialization error" + +writeVectorCSV :: Tensor Double -> String -> IO () +writeVectorCSV m fileName = do + let size = fromJust . indexSize <$> head $ indices m + putStrLn $ "Writing " ++ show size ++ " elements vector to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Vector successfully written!" + +readVectorCSV :: Tensor Double -> String -> ExceptT String IO () +readVectorCSV m fileName = do + lift $ putStrLn $ "Reading vector v1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Vector successfully read!" + else + ExceptT $ return $ Left "Vector deserialization error" + +writeFormCSV :: Tensor Double -> String -> IO () +writeFormCSV m fileName = do + let size = fromJust . indexSize <$> head $ indices m + putStrLn $ "Writing " ++ show size ++ " elements form to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Form successfully written!" + +readFormCSV :: Tensor Double -> String -> ExceptT String IO () +readFormCSV m fileName = do + lift $ putStrLn $ "Reading form f1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Form successfully read!" + else + ExceptT $ return $ Left "Form deserialization error" + +writeMatrixCSV :: Tensor Double -> String -> IO () +writeMatrixCSV m fileName = do + let [xsize,ysize] = indexSize <$> indices m + putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".csv..." + m `toCSVFile` (fileName ++ ".csv") + putStrLn "Matrix successfully written!" + +readMatrixCSV :: Tensor Double -> String -> ExceptT String IO () +readMatrixCSV m fileName = do + lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".csv..." + (m1' :: Tensor Double) <- fromCSVFile (fileName ++ ".csv") ',' "ij" + if m1' == m then + lift $ putStrLn "Matrix successfully read!" + else + ExceptT $ return $ Left "Matrix deserialization error"
test/json/Spec.hs view
@@ -2,42 +2,32 @@ main ) where -import Control.Monad.Trans.Class import Control.Monad.Trans.Maybe -import Data.Maybe -import Multilinear.Class -import Multilinear.Generic -import Multilinear.Generic.Serialize -import Multilinear.Index +import qualified Multilinear.Generic.MultiCore as MultiCore +import qualified Multilinear.Generic.Sequential as Sequential import qualified Multilinear.Matrix as Matrix import System.Directory +import Test.MultiCore +import Test.Sequential fileName1 :: String fileName1 = "test/m1" -m1 :: Tensor Double -m1 = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) - -writeMatrixJSON :: Tensor Double -> String -> IO () -writeMatrixJSON m fileName = do - let [xsize,ysize] = indexSize <$> indices m1 - putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".json..." - m `toJSONFile` (fileName ++ ".json") - putStrLn $ "Matrix successfully written!" +m1MC :: MultiCore.Tensor Double +m1MC = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) -readMatrixJSON :: String -> MaybeT IO () -readMatrixJSON fileName = do - lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".json..." - m1' <- fromJSONFile (fileName ++ ".json") - if m1' == m1 then - lift $ putStrLn "Matrix successfully read!" - else - MaybeT $ return Nothing +m1Seq :: Sequential.Tensor Double +m1Seq = Matrix.fromIndices "ij" 50 50 $ \i j -> cos (fromIntegral i) + sin (fromIntegral j) -- ENTRY POINT main :: IO () main = do - writeMatrixJSON m1 fileName1 - runMaybeT $ readMatrixJSON fileName1 + putStrLn "Testing MultiCore..." + Test.MultiCore.writeMatrixJSON m1MC fileName1 + runMaybeT $ Test.MultiCore.readMatrixJSON m1MC fileName1 + removeFile $ fileName1 ++ ".json" + putStrLn "Testing Sequential..." + Test.Sequential.writeMatrixJSON m1Seq fileName1 + runMaybeT $ Test.Sequential.readMatrixJSON m1Seq fileName1 removeFile $ fileName1 ++ ".json" return ()
+ test/json/Test/MultiCore.hs view
@@ -0,0 +1,27 @@+module Test.MultiCore ( + writeMatrixJSON, readMatrixJSON +) where + +import Control.Monad.Trans.Class +import Control.Monad.Trans.Maybe +import Data.Maybe +import Multilinear.Class +import Multilinear.Generic.MultiCore +import Multilinear.Generic.MultiCore.Serialize +import Multilinear.Index + +writeMatrixJSON :: Tensor Double -> String -> IO () +writeMatrixJSON m fileName = do + let [xsize,ysize] = indexSize <$> indices m + putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".json..." + m `toJSONFile` (fileName ++ ".json") + putStrLn $ "Matrix successfully written!" + +readMatrixJSON :: Tensor Double -> String -> MaybeT IO () +readMatrixJSON m fileName = do + lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".json..." + m1' <- fromJSONFile (fileName ++ ".json") + if m1' == m then + lift $ putStrLn "Matrix successfully read!" + else + MaybeT $ return Nothing
+ test/json/Test/Sequential.hs view
@@ -0,0 +1,27 @@+module Test.Sequential ( + writeMatrixJSON, readMatrixJSON +) where + +import Control.Monad.Trans.Class +import Control.Monad.Trans.Maybe +import Data.Maybe +import Multilinear.Class +import Multilinear.Generic.Sequential +import Multilinear.Generic.Sequential.Serialize +import Multilinear.Index + +writeMatrixJSON :: Tensor Double -> String -> IO () +writeMatrixJSON m fileName = do + let [xsize,ysize] = indexSize <$> indices m + putStrLn $ "Writing " ++ show (fromJust xsize) ++ "x" ++ show (fromJust ysize) ++ " matrix to " ++ fileName ++ ".json..." + m `toJSONFile` (fileName ++ ".json") + putStrLn $ "Matrix successfully written!" + +readMatrixJSON :: Tensor Double -> String -> MaybeT IO () +readMatrixJSON m fileName = do + lift $ putStrLn $ "Reading matrix m1 from " ++ fileName ++ ".json..." + m1' <- fromJSONFile (fileName ++ ".json") + if m1' == m then + lift $ putStrLn "Matrix successfully read!" + else + MaybeT $ return Nothing