liquidhaskell 0.8.10.7 → 0.8.10.7.1
raw patch · 2619 files changed
+2/−400479 lines, 2619 filesdep ~tastynew-uploader
Dependency ranges changed: tasty
This diff is very large; some files are shown as “too large to diff”. Download the raw patch for the complete diff.
Files
- .circleci/config.yml +0/−207
- .ghci +0/−2
- HLint.hs +0/−5
- INSTALL.md +0/−102
- LICENSE_Z3 +0/−7
- MIRRORING_MODULES.md +0/−62
- Makefile +0/−112
- Syntax.md +0/−297
- TODO.EASY.md +0/−22
- TODO.md +0/−1333
- appveyor-copy.bat +0/−9
- appveyor.yml +0/−57
- benchmarks/NOTES.txt +0/−4
- benchmarks/base-4.5.1.0/Control/Applicative.hs +0/−279
- benchmarks/base-4.5.1.0/Control/Arrow.hs +0/−350
- benchmarks/base-4.5.1.0/Control/Category.hs +0/−54
- benchmarks/base-4.5.1.0/Control/Concurrent.hs +0/−669
- benchmarks/base-4.5.1.0/Control/Concurrent/Chan.hs +0/−156
- benchmarks/base-4.5.1.0/Control/Concurrent/MVar.hs +0/−234
- benchmarks/base-4.5.1.0/Control/Concurrent/QSem.hs +0/−89
- benchmarks/base-4.5.1.0/Control/Concurrent/QSemN.hs +0/−81
- benchmarks/base-4.5.1.0/Control/Concurrent/SampleVar.hs +0/−136
- benchmarks/base-4.5.1.0/Control/Exception.hs +0/−405
- benchmarks/base-4.5.1.0/Control/Exception/Base.hs +0/−735
- benchmarks/base-4.5.1.0/Control/Monad.hs +0/−372
- benchmarks/base-4.5.1.0/Control/Monad/Fix.hs +0/−98
- benchmarks/base-4.5.1.0/Control/Monad/Instances.hs +0/−41
- benchmarks/base-4.5.1.0/Control/Monad/ST.hs +0/−53
- benchmarks/base-4.5.1.0/Control/Monad/ST/Imp.hs +0/−73
- benchmarks/base-4.5.1.0/Control/Monad/ST/Lazy.hs +0/−51
- benchmarks/base-4.5.1.0/Control/Monad/ST/Lazy/Imp.hs +0/−161
- benchmarks/base-4.5.1.0/Control/Monad/ST/Lazy/Safe.hs +0/−36
- benchmarks/base-4.5.1.0/Control/Monad/ST/Lazy/Unsafe.hs +0/−28
- benchmarks/base-4.5.1.0/Control/Monad/ST/Safe.hs +0/−33
- benchmarks/base-4.5.1.0/Control/Monad/ST/Strict.hs +0/−20
- benchmarks/base-4.5.1.0/Control/Monad/ST/Unsafe.hs +0/−29
- benchmarks/base-4.5.1.0/Control/Monad/Zip.hs +0/−55
- benchmarks/base-4.5.1.0/Control/OldException.hs +0/−806
- benchmarks/base-4.5.1.0/Data/Bits.hs +0/−410
- benchmarks/base-4.5.1.0/Data/Bool.hs +0/−42
- benchmarks/base-4.5.1.0/Data/Char.hs +0/−210
- benchmarks/base-4.5.1.0/Data/Complex.hs +0/−206
- benchmarks/base-4.5.1.0/Data/Data.hs +0/−1339
- benchmarks/base-4.5.1.0/Data/Dynamic.hs +0/−171
- benchmarks/base-4.5.1.0/Data/Either.hs +0/−100
- benchmarks/base-4.5.1.0/Data/Eq.hs +0/−25
- benchmarks/base-4.5.1.0/Data/Fixed.hs +0/−249
- benchmarks/base-4.5.1.0/Data/Foldable.hs +0/−325
- benchmarks/base-4.5.1.0/Data/Function.hs +0/−88
- benchmarks/base-4.5.1.0/Data/Functor.hs +0/−36
- benchmarks/base-4.5.1.0/Data/HashTable.hs +0/−534
- benchmarks/base-4.5.1.0/Data/IORef.hs +0/−141
- benchmarks/base-4.5.1.0/Data/Int.hs +0/−68
- benchmarks/base-4.5.1.0/Data/Ix.hs +0/−78
- benchmarks/base-4.5.1.0/Data/List.hs +0/−1170
- benchmarks/base-4.5.1.0/Data/Maybe.hs +0/−151
- benchmarks/base-4.5.1.0/Data/Monoid.hs +0/−288
- benchmarks/base-4.5.1.0/Data/Ord.hs +0/−37
- benchmarks/base-4.5.1.0/Data/Ratio.hs +0/−98
- benchmarks/base-4.5.1.0/Data/STRef.hs +0/−45
- benchmarks/base-4.5.1.0/Data/STRef/Lazy.hs +0/−39
- benchmarks/base-4.5.1.0/Data/STRef/Strict.hs +0/−22
- benchmarks/base-4.5.1.0/Data/String.hs +0/−44
- benchmarks/base-4.5.1.0/Data/Traversable.hs +0/−199
- benchmarks/base-4.5.1.0/Data/Tuple.hs +0/−109
- benchmarks/base-4.5.1.0/Data/Typeable.hs +0/−212
- benchmarks/base-4.5.1.0/Data/Typeable.hs-boot +0/−10
- benchmarks/base-4.5.1.0/Data/Typeable/Internal.hs +0/−570
- benchmarks/base-4.5.1.0/Data/Typeable/Internal.hs-boot +0/−28
- benchmarks/base-4.5.1.0/Data/Unique.hs +0/−78
- benchmarks/base-4.5.1.0/Data/Version.hs +0/−147
- benchmarks/base-4.5.1.0/Data/Word.hs +0/−71
- benchmarks/base-4.5.1.0/Debug/Trace.hs +0/−181
- benchmarks/base-4.5.1.0/Foreign.hs +0/−55
- benchmarks/base-4.5.1.0/Foreign/C.hs +0/−27
- benchmarks/base-4.5.1.0/Foreign/C/Error.hs +0/−619
- benchmarks/base-4.5.1.0/Foreign/C/String.hs +0/−544
- benchmarks/base-4.5.1.0/Foreign/C/Types.hs +0/−334
- benchmarks/base-4.5.1.0/Foreign/Concurrent.hs +0/−54
- benchmarks/base-4.5.1.0/Foreign/ForeignPtr.hs +0/−64
- benchmarks/base-4.5.1.0/Foreign/ForeignPtr/Imp.hs +0/−182
- benchmarks/base-4.5.1.0/Foreign/ForeignPtr/Safe.hs +0/−55
- benchmarks/base-4.5.1.0/Foreign/ForeignPtr/Unsafe.hs +0/−28
- benchmarks/base-4.5.1.0/Foreign/Marshal.hs +0/−58
- benchmarks/base-4.5.1.0/Foreign/Marshal/Alloc.hs +0/−248
- benchmarks/base-4.5.1.0/Foreign/Marshal/Array.hs +0/−280
- benchmarks/base-4.5.1.0/Foreign/Marshal/Error.hs +0/−86
- benchmarks/base-4.5.1.0/Foreign/Marshal/Pool.hs +0/−212
- benchmarks/base-4.5.1.0/Foreign/Marshal/Safe.hs +0/−36
- benchmarks/base-4.5.1.0/Foreign/Marshal/Unsafe.hs +0/−49
- benchmarks/base-4.5.1.0/Foreign/Marshal/Utils.hs +0/−181
- benchmarks/base-4.5.1.0/Foreign/Ptr.hs +0/−165
- benchmarks/base-4.5.1.0/Foreign/Safe.hs +0/−40
- benchmarks/base-4.5.1.0/Foreign/StablePtr.hs +0/−64
- benchmarks/base-4.5.1.0/Foreign/Storable.hs +0/−287
- benchmarks/base-4.5.1.0/GHC/Arr.lhs +0/−844
- benchmarks/base-4.5.1.0/GHC/Base.lhs +0/−831
- benchmarks/base-4.5.1.0/GHC/Conc.lhs +0/−118
- benchmarks/base-4.5.1.0/GHC/Conc/IO.hs +0/−159
- benchmarks/base-4.5.1.0/GHC/Conc/Signal.hs +0/−91
- benchmarks/base-4.5.1.0/GHC/Conc/Sync.lhs +0/−816
- benchmarks/base-4.5.1.0/GHC/Conc/Windows.hs +0/−327
- benchmarks/base-4.5.1.0/GHC/ConsoleHandler.hs +0/−158
- benchmarks/base-4.5.1.0/GHC/Constants.hs +0/−12
- benchmarks/base-4.5.1.0/GHC/Desugar.hs +0/−44
- benchmarks/base-4.5.1.0/GHC/Enum.lhs +0/−699
- benchmarks/base-4.5.1.0/GHC/Environment.hs +0/−53
- benchmarks/base-4.5.1.0/GHC/Err.lhs +0/−91
- benchmarks/base-4.5.1.0/GHC/Err.lhs-boot +0/−22
- benchmarks/base-4.5.1.0/GHC/Event.hs +0/−48
- benchmarks/base-4.5.1.0/GHC/Event/Array.hs +0/−315
- benchmarks/base-4.5.1.0/GHC/Event/Clock.hsc +0/−50
- benchmarks/base-4.5.1.0/GHC/Event/Control.hs +0/−216
- benchmarks/base-4.5.1.0/GHC/Event/EPoll.hsc +0/−211
- benchmarks/base-4.5.1.0/GHC/Event/IntMap.hs +0/−378
- benchmarks/base-4.5.1.0/GHC/Event/Internal.hs +0/−140
- benchmarks/base-4.5.1.0/GHC/Event/KQueue.hsc +0/−302
- benchmarks/base-4.5.1.0/GHC/Event/Manager.hs +0/−407
- benchmarks/base-4.5.1.0/GHC/Event/PSQ.hs +0/−485
- benchmarks/base-4.5.1.0/GHC/Event/Poll.hsc +0/−163
- benchmarks/base-4.5.1.0/GHC/Event/Thread.hs +0/−151
- benchmarks/base-4.5.1.0/GHC/Event/Unique.hs +0/−42
- benchmarks/base-4.5.1.0/GHC/Exception.lhs +0/−196
- benchmarks/base-4.5.1.0/GHC/Exts.hs +0/−141
- benchmarks/base-4.5.1.0/GHC/Fingerprint.hs +0/−78
- benchmarks/base-4.5.1.0/GHC/Fingerprint.hs-boot +0/−13
- benchmarks/base-4.5.1.0/GHC/Fingerprint/Type.hs +0/−21
- benchmarks/base-4.5.1.0/GHC/Float.lhs +0/−1173
- benchmarks/base-4.5.1.0/GHC/Float/ConversionUtils.hs +0/−99
- benchmarks/base-4.5.1.0/GHC/Float/RealFracMethods.hs +0/−344
- benchmarks/base-4.5.1.0/GHC/Foreign.hs +0/−257
- benchmarks/base-4.5.1.0/GHC/ForeignPtr.hs +0/−390
- benchmarks/base-4.5.1.0/GHC/Handle.hs +0/−57
- benchmarks/base-4.5.1.0/GHC/IO.hs +0/−489
- benchmarks/base-4.5.1.0/GHC/IO.hs-boot +0/−9
- benchmarks/base-4.5.1.0/GHC/IO/Buffer.hs +0/−291
- benchmarks/base-4.5.1.0/GHC/IO/BufferedIO.hs +0/−127
- benchmarks/base-4.5.1.0/GHC/IO/Device.hs +0/−179
- benchmarks/base-4.5.1.0/GHC/IO/Encoding.hs +0/−233
- benchmarks/base-4.5.1.0/GHC/IO/Encoding.hs-boot +0/−10
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/CodePage.hs +0/−172
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/CodePage/Table.hs +0/−432
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/Failure.hs +0/−204
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/Iconv.hs +0/−187
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/Latin1.hs +0/−153
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/Types.hs +0/−134
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/UTF16.hs +0/−358
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/UTF32.hs +0/−334
- benchmarks/base-4.5.1.0/GHC/IO/Encoding/UTF8.hs +0/−360
- benchmarks/base-4.5.1.0/GHC/IO/Exception.hs +0/−343
- benchmarks/base-4.5.1.0/GHC/IO/Exception.hs-boot +0/−15
- benchmarks/base-4.5.1.0/GHC/IO/FD.hs +0/−667
- benchmarks/base-4.5.1.0/GHC/IO/Handle.hs +0/−744
- benchmarks/base-4.5.1.0/GHC/IO/Handle.hs-boot +0/−10
- benchmarks/base-4.5.1.0/GHC/IO/Handle/FD.hs +0/−289
- benchmarks/base-4.5.1.0/GHC/IO/Handle/FD.hs-boot +0/−10
- benchmarks/base-4.5.1.0/GHC/IO/Handle/Internals.hs +0/−915
- benchmarks/base-4.5.1.0/GHC/IO/Handle/Text.hs +0/−1010
- benchmarks/base-4.5.1.0/GHC/IO/Handle/Types.hs +0/−431
- benchmarks/base-4.5.1.0/GHC/IO/IOMode.hs +0/−30
- benchmarks/base-4.5.1.0/GHC/IOArray.hs +0/−73
- benchmarks/base-4.5.1.0/GHC/IOBase.hs +0/−93
- benchmarks/base-4.5.1.0/GHC/IORef.hs +0/−53
- benchmarks/base-4.5.1.0/GHC/Int.hs +0/−950
- benchmarks/base-4.5.1.0/GHC/List.lhs +0/−812
- benchmarks/base-4.5.1.0/GHC/MVar.hs +0/−145
- benchmarks/base-4.5.1.0/GHC/Num.lhs +0/−125
- benchmarks/base-4.5.1.0/GHC/PArr.hs +0/−37
- benchmarks/base-4.5.1.0/GHC/Pack.lhs +0/−104
- benchmarks/base-4.5.1.0/GHC/Ptr.lhs +0/−168
- benchmarks/base-4.5.1.0/GHC/Read.lhs +0/−703
- benchmarks/base-4.5.1.0/GHC/Real.lhs +0/−615
- benchmarks/base-4.5.1.0/GHC/ST.lhs +0/−175
- benchmarks/base-4.5.1.0/GHC/STRef.lhs +0/−53
- benchmarks/base-4.5.1.0/GHC/Show.lhs +0/−553
- benchmarks/base-4.5.1.0/GHC/Show.lhs-boot +0/−11
- benchmarks/base-4.5.1.0/GHC/Stable.lhs +0/−113
- benchmarks/base-4.5.1.0/GHC/Stack.hsc +0/−108
- benchmarks/base-4.5.1.0/GHC/Stats.hsc +0/−130
- benchmarks/base-4.5.1.0/GHC/Storable.lhs +0/−165
- benchmarks/base-4.5.1.0/GHC/TopHandler.lhs +0/−219
- benchmarks/base-4.5.1.0/GHC/Unicode.hs +0/−224
- benchmarks/base-4.5.1.0/GHC/Unicode.hs-boot +0/−20
- benchmarks/base-4.5.1.0/GHC/Weak.lhs +0/−148
- benchmarks/base-4.5.1.0/GHC/Windows.hs +0/−48
- benchmarks/base-4.5.1.0/GHC/Word.hs +0/−856
- benchmarks/base-4.5.1.0/LICENSE +0/−83
- benchmarks/base-4.5.1.0/Numeric.hs +0/−221
- benchmarks/base-4.5.1.0/Prelude.hs +0/−194
- benchmarks/base-4.5.1.0/Setup.hs +0/−6
- benchmarks/base-4.5.1.0/System/CPUTime.hsc +0/−186
- benchmarks/base-4.5.1.0/System/Console/GetOpt.hs +0/−396
- benchmarks/base-4.5.1.0/System/Environment.hs +0/−343
- benchmarks/base-4.5.1.0/System/Exit.hs +0/−95
- benchmarks/base-4.5.1.0/System/IO.hs +0/−693
- benchmarks/base-4.5.1.0/System/IO/Error.hs +0/−478
- benchmarks/base-4.5.1.0/System/IO/Unsafe.hs +0/−61
- benchmarks/base-4.5.1.0/System/Info.hs +0/−70
- benchmarks/base-4.5.1.0/System/Mem.hs +0/−39
- benchmarks/base-4.5.1.0/System/Mem/StableName.hs +0/−127
- benchmarks/base-4.5.1.0/System/Mem/Weak.hs +0/−154
- benchmarks/base-4.5.1.0/System/Posix/Internals.hs +0/−581
- benchmarks/base-4.5.1.0/System/Posix/Internals.hs-boot +0/−9
- benchmarks/base-4.5.1.0/System/Posix/Types.hs +0/−210
- benchmarks/base-4.5.1.0/System/Timeout.hs +0/−95
- benchmarks/base-4.5.1.0/Text/ParserCombinators/ReadP.hs +0/−543
- benchmarks/base-4.5.1.0/Text/ParserCombinators/ReadPrec.hs +0/−164
- benchmarks/base-4.5.1.0/Text/Printf.hs +0/−331
- benchmarks/base-4.5.1.0/Text/Read.hs +0/−102
- benchmarks/base-4.5.1.0/Text/Read/Lex.hs +0/−559
- benchmarks/base-4.5.1.0/Text/Show.hs +0/−50
- benchmarks/base-4.5.1.0/Text/Show/Functions.hs +0/−39
- benchmarks/base-4.5.1.0/Unsafe/Coerce.hs +0/−47
- benchmarks/base-4.5.1.0/aclocal.m4 +0/−231
- benchmarks/base-4.5.1.0/base.cabal +0/−253
- benchmarks/base-4.5.1.0/cbits/PrelIOUtils.c +0/−52
- benchmarks/base-4.5.1.0/cbits/WCsubst.c +0/−4398
- benchmarks/base-4.5.1.0/cbits/Win32Utils.c +0/−132
- benchmarks/base-4.5.1.0/cbits/consUtils.c +0/−111
- benchmarks/base-4.5.1.0/cbits/iconv.c +0/−25
- benchmarks/base-4.5.1.0/cbits/inputReady.c +0/−168
- benchmarks/base-4.5.1.0/cbits/md5.c +0/−238
- benchmarks/base-4.5.1.0/cbits/primFloat.c +0/−532
- benchmarks/base-4.5.1.0/cbits/selectUtils.c +0/−3
- benchmarks/base-4.5.1.0/config.guess +0/−1500
- benchmarks/base-4.5.1.0/config.sub +0/−1608
- benchmarks/base-4.5.1.0/configure +0/−21596
- benchmarks/base-4.5.1.0/configure.ac +0/−183
- benchmarks/base-4.5.1.0/ieee-flpt.h +0/−35
- benchmarks/base-4.5.1.0/include/CTypes.h +0/−214
- benchmarks/base-4.5.1.0/include/EventConfig.h +0/−86
- benchmarks/base-4.5.1.0/include/HsBase.h +0/−645
- benchmarks/base-4.5.1.0/include/HsBaseConfig.h +0/−599
- benchmarks/base-4.5.1.0/include/Typeable.h +0/−123
- benchmarks/base-4.5.1.0/include/WCsubst.h +0/−24
- benchmarks/base-4.5.1.0/include/consUtils.h +0/−13
- benchmarks/base-4.5.1.0/include/ieee-flpt.h +0/−35
- benchmarks/base-4.5.1.0/include/md5.h +0/−24
- benchmarks/base-4.5.1.0/install-sh +0/−507
- benchmarks/bytestring-0.9.2.1/Data/ByteString.T.hs +0/−2380
- benchmarks/bytestring-0.9.2.1/Data/ByteString.hs +0/−2335
- benchmarks/bytestring-0.9.2.1/Data/ByteString.hs.hquals +0/−33
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Char8.hs +0/−1097
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Fusion.T.hs +0/−808
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Fusion.hs +0/−802
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Internal.hs +0/−636
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Lazy.hs +0/−1705
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Lazy/Char8.hs +0/−874
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Lazy/Internal.hs +0/−200
- benchmarks/bytestring-0.9.2.1/Data/ByteString/LazyZip.hs +0/−216
- benchmarks/bytestring-0.9.2.1/Data/ByteString/Unsafe.hs +0/−346
- benchmarks/bytestring-0.9.2.1/cbits/fpstring.c +0/−82
- benchmarks/bytestring-0.9.2.1/count.py +0/−37
- benchmarks/bytestring-0.9.2.1/count.sh +0/−14
- benchmarks/bytestring-0.9.2.1/include/fpstring.h +0/−6
- benchmarks/containers-0.5.0.0/Data/Graph.hs +0/−448
- benchmarks/containers-0.5.0.0/Data/IntMap.hs +0/−95
- benchmarks/containers-0.5.0.0/Data/IntMap/Base.hs +0/−2171
- benchmarks/containers-0.5.0.0/Data/IntMap/Lazy.hs +0/−214
- benchmarks/containers-0.5.0.0/Data/IntMap/Strict.hs +0/−964
- benchmarks/containers-0.5.0.0/Data/IntSet.hs +0/−148
- benchmarks/containers-0.5.0.0/Data/IntSet/Base.hs +0/−1485
- benchmarks/containers-0.5.0.0/Data/Map.hs +0/−104
- benchmarks/containers-0.5.0.0/Data/Map/Base.hs +0/−2992
- benchmarks/containers-0.5.0.0/Data/Map/Base0.hs +0/−251
- benchmarks/containers-0.5.0.0/Data/Map/Base00.hs +0/−66
- benchmarks/containers-0.5.0.0/Data/Map/Base1.hs +0/−2718
- benchmarks/containers-0.5.0.0/Data/Map/Lazy.hs +0/−227
- benchmarks/containers-0.5.0.0/Data/Map/Strict.hs +0/−1139
- benchmarks/containers-0.5.0.0/Data/Sequence.hs +0/−1793
- benchmarks/containers-0.5.0.0/Data/Set.hs +0/−144
- benchmarks/containers-0.5.0.0/Data/Set/Base.hs +0/−1364
- benchmarks/containers-0.5.0.0/Data/StrictPair.hs +0/−6
- benchmarks/containers-0.5.0.0/Data/Tree.hs +0/−170
- benchmarks/containers-0.5.0.0/LICENSE +0/−83
- benchmarks/containers-0.5.0.0/Setup.hs +0/−6
- benchmarks/containers-0.5.0.0/benchmarks/IntMap.hs +0/−94
- benchmarks/containers-0.5.0.0/benchmarks/IntSet.hs +0/−48
- benchmarks/containers-0.5.0.0/benchmarks/LookupGE/IntMap.hs +0/−51
- benchmarks/containers-0.5.0.0/benchmarks/LookupGE/LookupGE_IntMap.hs +0/−97
- benchmarks/containers-0.5.0.0/benchmarks/LookupGE/LookupGE_Map.hs +0/−78
- benchmarks/containers-0.5.0.0/benchmarks/LookupGE/Makefile +0/−3
- benchmarks/containers-0.5.0.0/benchmarks/LookupGE/Map.hs +0/−50
- benchmarks/containers-0.5.0.0/benchmarks/Makefile +0/−16
- benchmarks/containers-0.5.0.0/benchmarks/Map.hs +0/−126
- benchmarks/containers-0.5.0.0/benchmarks/Sequence.hs +0/−34
- benchmarks/containers-0.5.0.0/benchmarks/Set.hs +0/−49
- benchmarks/containers-0.5.0.0/benchmarks/SetOperations/Makefile +0/−3
- benchmarks/containers-0.5.0.0/benchmarks/SetOperations/SetOperations-IntMap.hs +0/−6
- benchmarks/containers-0.5.0.0/benchmarks/SetOperations/SetOperations-IntSet.hs +0/−6
- benchmarks/containers-0.5.0.0/benchmarks/SetOperations/SetOperations-Map.hs +0/−6
- benchmarks/containers-0.5.0.0/benchmarks/SetOperations/SetOperations-Set.hs +0/−6
- benchmarks/containers-0.5.0.0/benchmarks/SetOperations/SetOperations.hs +0/−45
- benchmarks/containers-0.5.0.0/benchmarks/bench-cmp.pl +0/−24
- benchmarks/containers-0.5.0.0/benchmarks/bench-cmp.sh +0/−3
- benchmarks/containers-0.5.0.0/containers.cabal +0/−193
- benchmarks/containers-0.5.0.0/include/Typeable.h +0/−59
- benchmarks/containers-0.5.0.0/tests/Makefile +0/−20
- benchmarks/containers-0.5.0.0/tests/intmap-properties.hs +0/−1041
- benchmarks/containers-0.5.0.0/tests/intset-properties.hs +0/−312
- benchmarks/containers-0.5.0.0/tests/map-properties.hs +0/−1188
- benchmarks/containers-0.5.0.0/tests/seq-properties.hs +0/−598
- benchmarks/containers-0.5.0.0/tests/set-properties.hs +0/−341
- benchmarks/cse230/LICENSE +0/−21
- benchmarks/cse230/README.md +0/−1
- benchmarks/cse230/src/Week10/Axiomatic.hs +0/−364
- benchmarks/cse230/src/Week10/BigStep.hs +0/−160
- benchmarks/cse230/src/Week10/Expressions.hs +0/−144
- benchmarks/cse230/src/Week10/Imp.hs +0/−36
- benchmarks/cse230/src/Week10/Lec_3_11.hs +0/−427
- benchmarks/cse230/src/Week10/Lec_3_15.hs +0/−170
- benchmarks/cse230/src/Week10/ProofCombinators.hs +0/−183
- benchmarks/cse230/src/Week10/STLC.lhs +0/−473
- benchmarks/cse230/src/Week10/State.hs +0/−32
- benchmarks/cse230/src/Week10/Verifier.hs +0/−149
- benchmarks/esop2013-submission/Array.hs +0/−175
- benchmarks/esop2013-submission/Base.hquals +0/−3
- benchmarks/esop2013-submission/Base.hs +0/−3167
- benchmarks/esop2013-submission/Fib.hs +0/−73
- benchmarks/esop2013-submission/GhcListSort.hs +0/−129
- benchmarks/esop2013-submission/ListSort.hs +0/−64
- benchmarks/esop2013-submission/Splay.hs +0/−426
- benchmarks/esop2013-submission/Toy.hs +0/−113
- benchmarks/esop2013-submission/count.py +0/−35
- benchmarks/esop2013-submission/count.sh +0/−10
- benchmarks/haskell16/pos/tmp/MonoidPeano.hs +0/−100
- benchmarks/hmatrix-0.15.0.1/Config.hs +0/−155
- benchmarks/hmatrix-0.15.0.1/LICENSE +0/−2
- benchmarks/hmatrix-0.15.0.1/Setup.lhs +0/−18
- benchmarks/hmatrix-0.15.0.1/examples/bool.hs +0/−54
- benchmarks/hmatrix-0.15.0.1/examples/data.txt +0/−10
- benchmarks/hmatrix-0.15.0.1/examples/deriv.hs +0/−8
- benchmarks/hmatrix-0.15.0.1/examples/devel/ej1/functions.c +0/−35
- benchmarks/hmatrix-0.15.0.1/examples/devel/ej1/wrappers.hs +0/−44
- benchmarks/hmatrix-0.15.0.1/examples/devel/ej2/functions.c +0/−24
- benchmarks/hmatrix-0.15.0.1/examples/devel/ej2/wrappers.hs +0/−32
- benchmarks/hmatrix-0.15.0.1/examples/error.hs +0/−21
- benchmarks/hmatrix-0.15.0.1/examples/fitting.hs +0/−24
- benchmarks/hmatrix-0.15.0.1/examples/inplace.hs +0/−152
- benchmarks/hmatrix-0.15.0.1/examples/integrate.hs +0/−24
- benchmarks/hmatrix-0.15.0.1/examples/kalman.hs +0/−51
- benchmarks/hmatrix-0.15.0.1/examples/lie.hs +0/−65
- benchmarks/hmatrix-0.15.0.1/examples/minimize.hs +0/−50
- benchmarks/hmatrix-0.15.0.1/examples/monadic.hs +0/−118
- benchmarks/hmatrix-0.15.0.1/examples/multiply.hs +0/−100
- benchmarks/hmatrix-0.15.0.1/examples/ode.hs +0/−50
- benchmarks/hmatrix-0.15.0.1/examples/parallel.hs +0/−28
- benchmarks/hmatrix-0.15.0.1/examples/pca1.hs +0/−46
- benchmarks/hmatrix-0.15.0.1/examples/pca2.hs +0/−65
- benchmarks/hmatrix-0.15.0.1/examples/pinv.hs +0/−20
- benchmarks/hmatrix-0.15.0.1/examples/plot.hs +0/−20
- benchmarks/hmatrix-0.15.0.1/examples/root.hs +0/−31
- benchmarks/hmatrix-0.15.0.1/examples/vector.hs +0/−31
- benchmarks/hmatrix-0.15.0.1/hmatrix.cabal +0/−207
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed.hs +0/−28
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Development.hs +0/−30
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Foreign.hs +0/−99
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Internal.hs +0/−26
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Internal/Common.hs +0/−184
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Internal/Matrix.hs +0/−470
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Internal/Signatures.hs +0/−72
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Internal/Vector.hs +0/−523
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Matrix.hs +0/−420
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Random.hs +0/−57
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/ST.hs +0/−178
- benchmarks/hmatrix-0.15.0.1/lib/Data/Packed/Vector.hs +0/−90
- benchmarks/hmatrix-0.15.0.1/lib/Graphics/Plot.hs +0/−183
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/Chain.hs +0/−140
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/Container.hs +0/−145
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/ContainerBoot.hs +0/−603
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/Conversion.hs +0/−91
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL.hs +0/−43
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Differentiation.hs +0/−87
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Fitting.hs +0/−177
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Fourier.hs +0/−47
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Integration.hs +0/−198
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Internal.hs +0/−76
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Minimization.hs +0/−194
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/ODE.hs +0/−136
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Polynomials.hs +0/−58
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Root.hs +0/−209
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/Vector.hs +0/−327
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/gsl-aux.c +0/−1472
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/GSL/gsl-ode.c +0/−182
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/IO.hs +0/−160
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra.hs +0/−28
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra/Algorithms.hs +0/−731
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra/LAPACK.hs +0/−536
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c +0/−1448
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.h +0/−60
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra/Util.hs +0/−233
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/LinearAlgebra/Util/Convolution.hs +0/−114
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/Matrix.hs +0/−71
- benchmarks/hmatrix-0.15.0.1/lib/Numeric/Vector.hs +0/−158
- benchmarks/icfp15/MiniPosix.hs +0/−95
- benchmarks/icfp15/neg/Composition.hs +0/−63
- benchmarks/icfp15/neg/DBMovies.hs +0/−159
- benchmarks/icfp15/neg/DataBase.hs +0/−250
- benchmarks/icfp15/neg/IfM.hs +0/−88
- benchmarks/icfp15/neg/RIO.hs +0/−71
- benchmarks/icfp15/neg/Records.hs too large to diff
- benchmarks/icfp15/neg/TestM.hs too large to diff
- benchmarks/icfp15/neg/TwiceM.hs too large to diff
- benchmarks/icfp15/neg/WhileM.hs too large to diff
- benchmarks/icfp15/pos/Append.hs too large to diff
- benchmarks/icfp15/pos/CompareConstraints.hs too large to diff
- benchmarks/icfp15/pos/Composition.hs too large to diff
- benchmarks/icfp15/pos/CopyRec.hs too large to diff
- benchmarks/icfp15/pos/DBMovies.hs too large to diff
- benchmarks/icfp15/pos/DataBase.hs too large to diff
- benchmarks/icfp15/pos/Filter.lhs too large to diff
- benchmarks/icfp15/pos/FindRec.hs too large to diff
- benchmarks/icfp15/pos/FoldAbs.hs too large to diff
- benchmarks/icfp15/pos/ICFP15.lhs too large to diff
- benchmarks/icfp15/pos/IfM.hs too large to diff
- benchmarks/icfp15/pos/IfM2.hs too large to diff
- benchmarks/icfp15/pos/Incr-elim.hs too large to diff
- benchmarks/icfp15/pos/Incr.hs too large to diff
- benchmarks/icfp15/pos/Overview.lhs too large to diff
- benchmarks/icfp15/pos/Privileges.hs too large to diff
- benchmarks/icfp15/pos/RIO.hs too large to diff
- benchmarks/icfp15/pos/RIO2.hs too large to diff
- benchmarks/icfp15/pos/TestM.hs too large to diff
- benchmarks/icfp15/pos/TwiceM.hs too large to diff
- benchmarks/icfp15/pos/WhileM.hs too large to diff
- benchmarks/icfp15/pos/WhileTest.hs too large to diff
- benchmarks/icfp15/pos/dropwhile.hs too large to diff
- benchmarks/icfp15/todo/Append.T.hs too large to diff
- benchmarks/icfp15/todo/Dyn.hs too large to diff
- benchmarks/icfp15/todo/FindRec.hs too large to diff
- benchmarks/icfp15/todo/Reverse.hs too large to diff
- benchmarks/icfp15/todo/WhileM.hs too large to diff
- benchmarks/kmeans-0.1.2/Data/KMeans.hs too large to diff
- benchmarks/kmeans-0.1.2/Data/KMeans.orig.hs too large to diff
- benchmarks/kmeans-0.1.2/Data/KMeans0.hs too large to diff
- benchmarks/kmeans-0.1.2/LICENSE too large to diff
- benchmarks/kmeans-0.1.2/Setup.lhs too large to diff
- benchmarks/kmeans-0.1.2/kmeans.cabal too large to diff
- benchmarks/llrbtree-0.1.1/Data/Heap/Binominal.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Heap/Leftist.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Heap/Skew.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Heap/Splay.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/BUSplay.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/LLRBTree.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree-appel-height.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree-appel.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree-mini-color.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree-mini.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree-ord.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/RBTree0.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/Splay.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/Splay0.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/WBTree.hs too large to diff
- benchmarks/llrbtree-0.1.1/Data/Set/fixme.hs too large to diff
- benchmarks/llrbtree-0.1.1/LICENSE too large to diff
- benchmarks/llrbtree-0.1.1/Setup.hs too large to diff
- benchmarks/llrbtree-0.1.1/llrbtree.cabal too large to diff
- benchmarks/nofib/imaginary/bernouilli/Main.hs too large to diff
- benchmarks/nofib/imaginary/digits-of-e1/Main.lhs too large to diff
- benchmarks/nofib/imaginary/digits-of-e2/Main.lhs too large to diff
- benchmarks/nofib/imaginary/exp3_8/Main.hs too large to diff
- benchmarks/nofib/imaginary/gen_regexps/Main.hs too large to diff
- benchmarks/nofib/imaginary/integrate/Main.hs too large to diff
- benchmarks/nofib/imaginary/paraffins/Main.hs too large to diff
- benchmarks/nofib/imaginary/primes/Main.hs too large to diff
- benchmarks/nofib/imaginary/queens/Main.hs too large to diff
- benchmarks/nofib/imaginary/rfib/Main.hs too large to diff
- benchmarks/nofib/imaginary/tak/Main.hs too large to diff
- benchmarks/nofib/imaginary/wheel-sieve1/Main.hs too large to diff
- benchmarks/nofib/imaginary/wheel-sieve2/Main.hs too large to diff
- benchmarks/nofib/imaginary/x2n1/Main.hs too large to diff
- benchmarks/originals/base-4.5.1.0.tar.gz too large to diff
- benchmarks/originals/bytestring-0.9.0.2.tar.gz too large to diff
- benchmarks/originals/containers-0.5.0.0.tar.gz too large to diff
- benchmarks/originals/ghc-7.4.1.tgz too large to diff
- benchmarks/originals/hmatrix-0.15.0.1.tar.gz too large to diff
- benchmarks/originals/llrbtree-0.1.1.tar.gz too large to diff
- benchmarks/originals/text-0.11.2.3.tar.gz too large to diff
- benchmarks/originals/unordered-containers-0.2.1.0.tar.gz too large to diff
- benchmarks/originals/vector-0.10.0.1.tar.gz too large to diff
- benchmarks/originals/vector-0.9.1.tar.gz too large to diff
- benchmarks/originals/vector-algorithms-0.5.4.2.tar.gz too large to diff
- benchmarks/originals/wouter-swierstra-xmonad-7715ec2.zip too large to diff
- benchmarks/originals/xmonad-0.10.tar.gz too large to diff
- benchmarks/popl18/lib/Helper.hs too large to diff
- benchmarks/popl18/lib/Proves.hs too large to diff
- benchmarks/popl18/nople/neg/Ackermann.hs too large to diff
- benchmarks/popl18/nople/neg/Append.hs too large to diff
- benchmarks/popl18/nople/neg/ApplicativeList.hs too large to diff
- benchmarks/popl18/nople/neg/ApplicativeMaybe.hs too large to diff
- benchmarks/popl18/nople/neg/BasicLambdas.hs too large to diff
- benchmarks/popl18/nople/neg/Fibonacci.hs too large to diff
- benchmarks/popl18/nople/neg/FunctorList.hs too large to diff
- benchmarks/popl18/nople/neg/FunctorMaybe.hs too large to diff
- benchmarks/popl18/nople/neg/MapFusion.hs too large to diff
- benchmarks/popl18/nople/neg/MonadList.hs too large to diff
- benchmarks/popl18/nople/neg/MonadMaybe.hs too large to diff
- benchmarks/popl18/nople/neg/MonadReader.hs too large to diff
- benchmarks/popl18/nople/pos/Ackermann.hs too large to diff
- benchmarks/popl18/nople/pos/Append.hs too large to diff
- benchmarks/popl18/nople/pos/ApplicativeId.hs too large to diff
- benchmarks/popl18/nople/pos/ApplicativeList.hs too large to diff
- benchmarks/popl18/nople/pos/ApplicativeMaybe.hs too large to diff
- benchmarks/popl18/nople/pos/ApplicativeReader.hs too large to diff
- benchmarks/popl18/nople/pos/BasicLambdas.hs too large to diff
- benchmarks/popl18/nople/pos/Compose.hs too large to diff
- benchmarks/popl18/nople/pos/Euclide.hs too large to diff
- benchmarks/popl18/nople/pos/Fibonacci.hs too large to diff
- benchmarks/popl18/nople/pos/FoldrUniversal.hs too large to diff
- benchmarks/popl18/nople/pos/FunctorId.hs too large to diff
- benchmarks/popl18/nople/pos/FunctorList.hs too large to diff
- benchmarks/popl18/nople/pos/FunctorMaybe.hs too large to diff
- benchmarks/popl18/nople/pos/FunctorReader.NoExtensionality.hs too large to diff
- benchmarks/popl18/nople/pos/FunctorReader.hs too large to diff
- benchmarks/popl18/nople/pos/MapFusion.hs too large to diff
- benchmarks/popl18/nople/pos/MonadId.hs too large to diff
- benchmarks/popl18/nople/pos/MonadList.hs too large to diff
- benchmarks/popl18/nople/pos/MonadMaybe.hs too large to diff
- benchmarks/popl18/nople/pos/MonadReader.hs too large to diff
- benchmarks/popl18/nople/pos/MonoidList.hs too large to diff
- benchmarks/popl18/nople/pos/MonoidMaybe.hs too large to diff
- benchmarks/popl18/nople/pos/NatInduction.hs too large to diff
- benchmarks/popl18/nople/pos/NaturalDeduction.hs too large to diff
- benchmarks/popl18/nople/pos/Overview.hs too large to diff
- benchmarks/popl18/nople/pos/OverviewListInfix.hs too large to diff
- benchmarks/popl18/nople/pos/Peano.hs too large to diff
- benchmarks/popl18/nople/pos/Solver.hs too large to diff
- benchmarks/popl18/nople/pos/Unification.hs too large to diff
- benchmarks/popl18/nople/todo/Soundness.hs too large to diff
- benchmarks/popl18/ple/pos/Ackermann.hs too large to diff
- benchmarks/popl18/ple/pos/Append.hs too large to diff
- benchmarks/popl18/ple/pos/ApplicativeId.hs too large to diff
- benchmarks/popl18/ple/pos/ApplicativeList.hs too large to diff
- benchmarks/popl18/ple/pos/ApplicativeMaybe.hs too large to diff
- benchmarks/popl18/ple/pos/BasicLambdas.hs too large to diff
- benchmarks/popl18/ple/pos/Compose.hs too large to diff
- benchmarks/popl18/ple/pos/Euclide.hs too large to diff
- benchmarks/popl18/ple/pos/Fibonacci.hs too large to diff
- benchmarks/popl18/ple/pos/FoldrUniversal.hs too large to diff
- benchmarks/popl18/ple/pos/FunctorId.hs too large to diff
- benchmarks/popl18/ple/pos/FunctorList.hs too large to diff
- benchmarks/popl18/ple/pos/FunctorMaybe.hs too large to diff
- benchmarks/popl18/ple/pos/Lists.hs too large to diff
- benchmarks/popl18/ple/pos/MapFusion.hs too large to diff
- benchmarks/popl18/ple/pos/Maybe.hs too large to diff
- benchmarks/popl18/ple/pos/MonadId.hs too large to diff
- benchmarks/popl18/ple/pos/MonadList.hs too large to diff
- benchmarks/popl18/ple/pos/MonadMaybe.hs too large to diff
- benchmarks/popl18/ple/pos/MonoidList.hs too large to diff
- benchmarks/popl18/ple/pos/MonoidMaybe.hs too large to diff
- benchmarks/popl18/ple/pos/NatInduction.hs too large to diff
- benchmarks/popl18/ple/pos/NaturalDeduction.hs too large to diff
- benchmarks/popl18/ple/pos/Overview.hs too large to diff
- benchmarks/popl18/ple/pos/OverviewListInfix.hs too large to diff
- benchmarks/popl18/ple/pos/Peano.hs too large to diff
- benchmarks/popl18/ple/pos/Solver.hs too large to diff
- benchmarks/popl18/ple/pos/Unification.hs too large to diff
- benchmarks/sf/Basics.hs too large to diff
- benchmarks/sf/Induction.hs too large to diff
- benchmarks/sf/InductionRJ.hs too large to diff
- benchmarks/sf/Lists.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Array.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Axioms.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding/Error.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding/Fusion.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding/Fusion/Common.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding/Utf16.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding/Utf32.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Encoding/Utf8.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Foreign.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Fusion-debug.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Fusion.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Fusion/CaseMapping.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Fusion/Common.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Fusion/Internal.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Fusion/Size.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/IO.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/IO/Internal.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Internal.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Builder.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Builder/Functions.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Builder/Int.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Builder/RealFloat.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Builder/RealFloat/Functions.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Encoding.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Encoding/Fusion.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Fusion.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/IO.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Internal.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Read.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Lazy/Search.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Private.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Read.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Search.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Unsafe.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Unsafe/Base.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/UnsafeChar.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/UnsafeShift.hs too large to diff
- benchmarks/text-0.11.2.3/Data/Text/Util.hs too large to diff
- benchmarks/text-0.11.2.3/LICENSE too large to diff
- benchmarks/text-0.11.2.3/LIQUID.txt too large to diff
- benchmarks/text-0.11.2.3/README.markdown too large to diff
- benchmarks/text-0.11.2.3/Setup.lhs too large to diff
- benchmarks/text-0.11.2.3/cbits/cbits.c too large to diff
- benchmarks/text-0.11.2.3/count.py too large to diff
- benchmarks/text-0.11.2.3/count.sh too large to diff
- benchmarks/text-0.11.2.3/tests-and-benchmarks.markdown too large to diff
- benchmarks/text-0.11.2.3/text.cabal too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashMap/Array.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashMap/Base.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashMap/Lazy.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashMap/PopCount.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashMap/Strict.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashMap/UnsafeShift.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/Data/HashSet.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/LICENSE too large to diff
- benchmarks/unordered-containers-0.2.1.0/Setup.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/cbits/popc.c too large to diff
- benchmarks/unordered-containers-0.2.1.0/tests/HashMapProperties.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/tests/HashSetProperties.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/tests/Regressions.hs too large to diff
- benchmarks/unordered-containers-0.2.1.0/unordered-containers.cabal too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Fusion/Stream.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Fusion/Stream/Monadic.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Fusion/Stream/Monadic.nocpp.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Fusion/Stream/Size.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Fusion/Util.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic.nocpp.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic/Base.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic/Mutable.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic/New.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic/New.nocpp.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Generic/New0.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Internal/Check.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Mutable.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Primitive.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Primitive/Mutable.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Primitive/Mutable.nocpp.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Storable.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Storable/Internal.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Storable/Mutable.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Unboxed.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Unboxed/Base.hs too large to diff
- benchmarks/vector-0.10.0.1/Data/Vector/Unboxed/Mutable.hs too large to diff
- benchmarks/vector-0.10.0.1/LICENSE too large to diff
- benchmarks/vector-0.10.0.1/Setup.hs too large to diff
- benchmarks/vector-0.10.0.1/include/vector.h too large to diff
- benchmarks/vector-0.10.0.1/internal/GenUnboxTuple.hs too large to diff
- benchmarks/vector-0.10.0.1/internal/unbox-tuple-instances too large to diff
- benchmarks/vector-0.10.0.1/vector.cabal too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/AmericanFlag.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Combinators.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Common.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Heap.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Insertion.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Intro.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Merge.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Optimal.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Radix.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Search.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Termination.hs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/LICENSE too large to diff
- benchmarks/vector-algorithms-0.5.4.2/Setup.lhs too large to diff
- benchmarks/vector-algorithms-0.5.4.2/count.py too large to diff
- benchmarks/vector-algorithms-0.5.4.2/count.sh too large to diff
- benchmarks/vector-algorithms-0.5.4.2/include/vector.h too large to diff
- benchmarks/vector-algorithms-0.5.4.2/liquid.sh too large to diff
- benchmarks/vector-algorithms-0.5.4.2/vector-algorithms.cabal too large to diff
- benchmarks/xmonad-0.10/CONFIG too large to diff
- benchmarks/xmonad-0.10/LICENSE too large to diff
- benchmarks/xmonad-0.10/Main.hs too large to diff
- benchmarks/xmonad-0.10/README too large to diff
- benchmarks/xmonad-0.10/STYLE too large to diff
- benchmarks/xmonad-0.10/Setup.lhs too large to diff
- benchmarks/xmonad-0.10/TODO too large to diff
- benchmarks/xmonad-0.10/XMonad.hs too large to diff
- benchmarks/xmonad-0.10/XMonad/Config.hs too large to diff
- benchmarks/xmonad-0.10/XMonad/Core.hs too large to diff
- benchmarks/xmonad-0.10/XMonad/Layout.hs too large to diff
- benchmarks/xmonad-0.10/XMonad/LiquidStackSet.lhs too large to diff
- benchmarks/xmonad-0.10/XMonad/Main.hsc too large to diff
- benchmarks/xmonad-0.10/XMonad/ManageHook.hs too large to diff
- benchmarks/xmonad-0.10/XMonad/Operations.hs too large to diff
- benchmarks/xmonad-0.10/XMonad/StackSet.hs too large to diff
- benchmarks/xmonad-0.10/man/xmonad.1 too large to diff
- benchmarks/xmonad-0.10/man/xmonad.1.markdown too large to diff
- benchmarks/xmonad-0.10/man/xmonad.hs too large to diff
- benchmarks/xmonad-0.10/tests/Properties.hs too large to diff
- benchmarks/xmonad-0.10/tests/loc.hs too large to diff
- benchmarks/xmonad-0.10/util/GenerateManpage.hs too large to diff
- benchmarks/xmonad-0.10/xmonad.cabal too large to diff
- benchmarks/xmonad-0.11/XMonad/StackSet.hs too large to diff
- benchmarks/xmonad-0.11/tests/Properties.txt too large to diff
- cabal.ghc9.project too large to diff
- cabal.project too large to diff
- cleanup too large to diff
- docs/blog/2013-01-01-refinement-types-101.lhs too large to diff
- docs/blog/2013-01-27-refinements101-reax.lhs too large to diff
- docs/blog/2013-01-31-safely-catching-a-list-by-its-tail.lhs too large to diff
- docs/blog/2013-02-16-kmeans-clustering-I.lhs too large to diff
- docs/blog/2013-02-17-kmeans-clustering-II.lhs too large to diff
- docs/blog/2013-03-04-bounding-vectors.lhs too large to diff
- docs/blog/2013-03-26-talking-about-sets.lhs too large to diff
- docs/blog/2013-05-16-unique-zippers.lhs too large to diff
- docs/blog/2013-05-24-unique-zipper.lhs too large to diff
- docs/blog/2013-06-03-abstracting-over-refinements.lhs too large to diff
- docs/blog/2013-07-29-putting-things-in-order.lhs too large to diff
- docs/blog/2013-11-23-telling_lies.lhs too large to diff
- docs/blog/2013-12-01-getting-to-the-bottom.lhs too large to diff
- docs/blog/2013-12-02-getting-to-the-bottom.lhs too large to diff
- docs/blog/2013-12-09-checking-termination.lhs too large to diff
- docs/blog/2013-12-14-gcd.lhs too large to diff
- docs/blog/2013-12-22-measuring-the-size-of-structures.lhs too large to diff
- docs/blog/2013-12-24-lexicographic-termination.lhs too large to diff
- docs/blog/2013-12-29-decreasing-expressions.lhs too large to diff
- docs/blog/2014-02-11-the-advantage-of-measures.lhs too large to diff
- docs/blog/2014-02-16-text-read.lhs too large to diff
- docs/blog/2014-02-23-text-write.lhs too large to diff
- docs/blog/2014-03-01-text-bug.lhs too large to diff
- docs/blog/2014-05-28-pointers-gone-wild.lhs too large to diff
- docs/blog/2014-08-15-a-finer-filter.lhs too large to diff
- docs/blog/2015-01-30-okasakis-lazy-queue.lhs too large to diff
- docs/blog/2015-06-13-bounded-refinement-types.lhs too large to diff
- docs/blog/2016-09-01-normal-forms.lhs too large to diff
- docs/blog/2016-09-18-refinement-reflection.lhs too large to diff
- docs/blog/2016-10-06-structural-induction.lhs too large to diff
- docs/blog/2016-12-25-isomorphisms.lhs too large to diff
- docs/blog/2017-01-06-reductions.lhs too large to diff
- docs/blog/2017-03-20-arithmetic-overflows.lhs too large to diff
- docs/blog/2017-12-15-splitting-and-splicing-intervals-I.lhs too large to diff
- docs/blog/2017-12-24-splitting-and-splicing-intervals-II.lhs too large to diff
- docs/blog/2018-02-23-measures-and-case-splitting.lhs too large to diff
- docs/blog/2018-05-17-hillel-verifier-rodeo-I-leftpad.lhs too large to diff
- docs/blog/2020-04-12-polymorphic-perplexion.lhs too large to diff
- docs/blog/2020-08-20-lh-as-a-ghc-plugin.lhs too large to diff
- docs/blog/todo/Iso.lhs too large to diff
- docs/blog/todo/LambdaEval.hs too large to diff
- docs/blog/todo/Termination.hs too large to diff
- docs/blog/todo/TextBug.lhs too large to diff
- docs/blog/todo/TextInternal.lhs too large to diff
- docs/blog/todo/TextRead.lhs too large to diff
- docs/blog/todo/TextWrite.lhs too large to diff
- docs/blog/todo/basic_termination.lhs too large to diff
- docs/blog/todo/binary-search-trees.lhs too large to diff
- docs/blog/todo/encoding-induction.lhs too large to diff
- docs/blog/todo/index-dependent-maps.hs too large to diff
- docs/blog/todo/index-dependent-maps.lhs too large to diff
- docs/blog/todo/kmeans-full.lhs too large to diff
- docs/blog/todo/lets-talk-about-sets.lhs.markdown too large to diff
- docs/blog/todo/red-black-intro.lhs too large to diff
- docs/blog/todo/red-black-order.lhs too large to diff
- docs/blog/todo/telling-lies-old.lhs too large to diff
- docs/blog/todo/termination.lhs too large to diff
- docs/blog/todo/text-layout.png too large to diff
- docs/blog/todo/text-lifecycle.png too large to diff
- docs/blog/todo/verifying-efficient-sorting-algorithms.lhs too large to diff
- docs/language/Makefile too large to diff
- docs/language/commands.sty too large to diff
- docs/language/haskellListings.tex too large to diff
- docs/language/language.tex too large to diff
- docs/language/liquidHaskell.sty too large to diff
- docs/language/main.pdf too large to diff
- docs/language/main.tex too large to diff
- docs/language/typeInference.tex too large to diff
- docs/mkDocs/README.md too large to diff
- docs/mkDocs/docs/blogposts/.pages too large to diff
- docs/mkDocs/docs/blogposts/2013-01-01-refinement-types-101.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-01-27-refinements101-reax.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-01-28-bounding-vectors.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-01-31-safely-catching-a-list-by-its-tail.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-02-16-kmeans-clustering-I.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-02-17-kmeans-clustering-II.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-03-04-bounding-vectors.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-03-26-talking-about-sets.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-05-24-unique-zipper.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-06-03-abstracting-over-refinements.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-07-29-putting-things-in-order.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-10-10-csv-tables.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-11-23-telling_lies.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-12-02-getting-to-the-bottom.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-12-09-checking-termination.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2013-12-14-gcd.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2014-02-11-the-advantage-of-measures.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2014-05-28-pointers-gone-wild.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2014-08-15-a-finer-filter.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2015-01-30-okasakis-lazy-queue.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2016-09-01-normal-forms.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2016-09-18-refinement-reflection.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2016-10-06-structural-induction.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2017-03-20-arithmetic-overflows.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2017-12-15-splitting-and-splicing-intervals-I.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2017-12-24-splitting-and-splicing-intervals-II.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2018-02-23-measures-and-case-splitting.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2018-05-17-hillel-verifier-rodeo-I-leftpad.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2019-10-20-why-types.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2020-04-12-polymorphic-perplexion.lhs.md too large to diff
- docs/mkDocs/docs/blogposts/2020-08-20-lh-as-a-ghc-plugin.lhs.md too large to diff
- docs/mkDocs/docs/index.md too large to diff
- docs/mkDocs/docs/install.md too large to diff
- docs/mkDocs/docs/legacy.md too large to diff
- docs/mkDocs/docs/options.md too large to diff
- docs/mkDocs/docs/papers.md too large to diff
- docs/mkDocs/docs/specifications.md too large to diff
- docs/mkDocs/docs/static/img/angles.jpg too large to diff
- docs/mkDocs/docs/static/img/ansel-adams-la-jolla.jpg too large to diff
- docs/mkDocs/docs/static/img/beach.jpg too large to diff
- docs/mkDocs/docs/static/img/dafny-leftpad-spec.png too large to diff
- docs/mkDocs/docs/static/img/emacs.png too large to diff
- docs/mkDocs/docs/static/img/escher-helix.jpg too large to diff
- docs/mkDocs/docs/static/img/falling.jpg too large to diff
- docs/mkDocs/docs/static/img/favicon.ico too large to diff
- docs/mkDocs/docs/static/img/garter-snake.jpg too large to diff
- docs/mkDocs/docs/static/img/geisel2.jpg too large to diff
- docs/mkDocs/docs/static/img/hillel-tweet-1.png too large to diff
- docs/mkDocs/docs/static/img/hillel-tweet-2.png too large to diff
- docs/mkDocs/docs/static/img/ico.png too large to diff
- docs/mkDocs/docs/static/img/la-jolla-shores-2.jpg too large to diff
- docs/mkDocs/docs/static/img/la-jolla-shores.jpg too large to diff
- docs/mkDocs/docs/static/img/leftpad-spec.png too large to diff
- docs/mkDocs/docs/static/img/lem_intersect.png too large to diff
- docs/mkDocs/docs/static/img/lem_sub.png too large to diff
- docs/mkDocs/docs/static/img/lem_union.png too large to diff
- docs/mkDocs/docs/static/img/logo-header.png too large to diff
- docs/mkDocs/docs/static/img/logo.png too large to diff
- docs/mkDocs/docs/static/img/odometer-rollover.jpg too large to diff
- docs/mkDocs/docs/static/img/out.gif too large to diff
- docs/mkDocs/docs/static/img/plugin-emacs.gif too large to diff
- docs/mkDocs/docs/static/img/plugin-ghcid.gif too large to diff
- docs/mkDocs/docs/static/img/plugin-vim.png too large to diff
- docs/mkDocs/docs/static/img/plugin-vscode.gif too large to diff
- docs/mkDocs/docs/static/img/preloader.gif too large to diff
- docs/mkDocs/docs/static/img/queue-lists.png too large to diff
- docs/mkDocs/docs/static/img/queue-rotate.png too large to diff
- docs/mkDocs/docs/static/img/queue.png too large to diff
- docs/mkDocs/docs/static/img/regehr-tweet-quantifiers.png too large to diff
- docs/mkDocs/docs/static/img/ribbon.png too large to diff
- docs/mkDocs/docs/static/img/sea.jpg too large to diff
- docs/mkDocs/docs/static/img/splash-append.png too large to diff
- docs/mkDocs/docs/static/img/splash-assocpf.gif too large to diff
- docs/mkDocs/docs/static/img/splash-assocpf.png too large to diff
- docs/mkDocs/docs/static/img/splash-assocthm.gif too large to diff
- docs/mkDocs/docs/static/img/splash-assocthm.png too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-A.gif too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-A.png too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-B.gif too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-B.png too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-C.gif too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-C.png too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-D.gif too large to diff
- docs/mkDocs/docs/static/img/splash-binarySearch-D.png too large to diff
- docs/mkDocs/docs/static/img/splash-dotproduct.gif too large to diff
- docs/mkDocs/docs/static/img/splash-dotproduct.png too large to diff
- docs/mkDocs/docs/static/img/splash-fib.gif too large to diff
- docs/mkDocs/docs/static/img/splash-fib.png too large to diff
- docs/mkDocs/docs/static/img/splash-head.gif too large to diff
- docs/mkDocs/docs/static/img/splash-head.png too large to diff
- docs/mkDocs/docs/static/img/splash-insertsort.gif too large to diff
- docs/mkDocs/docs/static/img/splash-insertsort.png too large to diff
- docs/mkDocs/docs/static/img/splash-merge.gif too large to diff
- docs/mkDocs/docs/static/img/splash-merge.png too large to diff
- docs/mkDocs/docs/static/img/splash-unsafetake.gif too large to diff
- docs/mkDocs/docs/static/img/splash-unstutter.gif too large to diff
- docs/mkDocs/docs/static/img/splash-unstutter.png too large to diff
- docs/mkDocs/docs/static/img/splash-ups.gif too large to diff
- docs/mkDocs/docs/static/img/splash-ups.png too large to diff
- docs/mkDocs/docs/static/img/splash-vectorsum.gif too large to diff
- docs/mkDocs/docs/static/img/splash-vectorsum.png too large to diff
- docs/mkDocs/docs/static/img/text-layout.png too large to diff
- docs/mkDocs/docs/static/img/text-lifecycle.png too large to diff
- docs/mkDocs/docs/static/img/white.jpg too large to diff
- docs/mkDocs/docs/static/img/why_types_1_1.png too large to diff
- docs/mkDocs/docs/static/img/why_types_1_2.png too large to diff
- docs/mkDocs/docs/static/img/why_types_1_3.png too large to diff
- docs/mkDocs/docs/static/img/why_types_2.png too large to diff
- docs/mkDocs/docs/static/img/why_types_2_1.png too large to diff
- docs/mkDocs/docs/static/img/why_types_2_2.png too large to diff
- docs/mkDocs/docs/static/img/why_types_3_1.png too large to diff
- docs/mkDocs/docs/static/img/why_types_3_2.png too large to diff
- docs/mkDocs/docs/static/img/why_types_3_3.png too large to diff
- docs/mkDocs/docs/static/img/why_types_3_4.png too large to diff
- docs/mkDocs/docs/static/liquid-dark.css too large to diff
- docs/mkDocs/docs/static/liquid-light.css too large to diff
- docs/mkDocs/docs/static/misc.css too large to diff
- docs/mkDocs/mkdocs.yml too large to diff
- docs/mkDocs/theme-overrides/main.html too large to diff
- docs/slides/BOS14/Makefile too large to diff
- docs/slides/BOS14/README.md too large to diff
- docs/slides/BOS14/_support/liquid.css too large to diff
- docs/slides/BOS14/_support/liquidhaskell.css too large to diff
- docs/slides/BOS14/_support/reveal.js/.travis.yml too large to diff
- docs/slides/BOS14/_support/reveal.js/Gruntfile.js too large to diff
- docs/slides/BOS14/_support/reveal.js/LICENSE too large to diff
- docs/slides/BOS14/_support/reveal.js/README.md too large to diff
- docs/slides/BOS14/_support/reveal.js/css/print/paper.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/print/pdf.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/reveal.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/reveal.min.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/README.md too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/beige.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/blood.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/default.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/moon.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/night.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/seminar.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/seminar.orig.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/serif.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/simple.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/sky.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/solarized.css too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/beige.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/blood.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/default.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/moon.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/night.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/serif.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/simple.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/sky.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/source/solarized.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/template/mixins.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/template/settings.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/css/theme/template/theme.scss too large to diff
- docs/slides/BOS14/_support/reveal.js/index.html too large to diff
- docs/slides/BOS14/_support/reveal.js/js/reveal.js too large to diff
- docs/slides/BOS14/_support/reveal.js/js/reveal.min.js too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/css/zenburn.css too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/font/league_gothic-webfont.eot too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/font/league_gothic-webfont.svg too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/font/league_gothic-webfont.woff too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/font/league_gothic_license too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/js/classList.js too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/js/head.min.js too large to diff
- docs/slides/BOS14/_support/reveal.js/lib/js/html5shiv.js too large to diff
- docs/slides/BOS14/_support/reveal.js/package.json too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/highlight/highlight.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/leap/leap.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/markdown/example.html too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/markdown/example.md too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/markdown/markdown.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/markdown/marked.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/math/math.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/multiplex/client.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/multiplex/index.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/multiplex/master.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/notes-server/client.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/notes-server/index.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/notes-server/notes.html too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/notes/notes.html too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/notes/notes.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/postmessage/example.html too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/postmessage/postmessage.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/print-pdf/print-pdf.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/remotes/remotes.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/search/search.js too large to diff
- docs/slides/BOS14/_support/reveal.js/plugin/zoom-js/zoom.js too large to diff
- docs/slides/BOS14/_support/reveal.js/test/examples/assets/image1.png too large to diff
- docs/slides/BOS14/_support/reveal.js/test/examples/assets/image2.png too large to diff
- docs/slides/BOS14/_support/reveal.js/test/examples/barebones.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/examples/embedded-media.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/examples/math.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/examples/slide-backgrounds.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/qunit-1.12.0.css too large to diff
- docs/slides/BOS14/_support/reveal.js/test/qunit-1.12.0.js too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test-markdown-element-attributes.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test-markdown-element-attributes.js too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test-markdown-slide-attributes.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test-markdown-slide-attributes.js too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test-markdown.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test-markdown.js too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test.html too large to diff
- docs/slides/BOS14/_support/reveal.js/test/test.js too large to diff
- docs/slides/BOS14/_support/template.reveal too large to diff
- docs/slides/BOS14/hs/end/000_Refinements.hs too large to diff
- docs/slides/BOS14/hs/end/001_Refinements.hs too large to diff
- docs/slides/BOS14/hs/end/01_Elements.hs too large to diff
- docs/slides/BOS14/hs/end/02_AbstractRefinements.hs too large to diff
- docs/slides/BOS14/hs/end/03_Termination.hs too large to diff
- docs/slides/BOS14/hs/end/05_Memory.hs too large to diff
- docs/slides/BOS14/hs/end/06_Eval.hs too large to diff
- docs/slides/BOS14/hs/long/AlphaConvert.hs too large to diff
- docs/slides/BOS14/hs/long/GhcListSort.hs too large to diff
- docs/slides/BOS14/hs/long/KMP.hs too large to diff
- docs/slides/BOS14/hs/long/RBTree-ord.hs too large to diff
- docs/slides/BOS14/hs/long/RBTree.hs too large to diff
- docs/slides/BOS14/hs/long/SoCalledHeartBleed.hs too large to diff
- docs/slides/BOS14/hs/start/000_Refinements.hs too large to diff
- docs/slides/BOS14/hs/start/001_Refinements.hs too large to diff
- docs/slides/BOS14/hs/start/01_Elements.hs too large to diff
- docs/slides/BOS14/hs/start/02_AbstractRefinements.hs too large to diff
- docs/slides/BOS14/hs/start/03_Termination.hs too large to diff
- docs/slides/BOS14/hs/start/04_Streams.hs too large to diff
- docs/slides/BOS14/hs/start/05_Memory.hs too large to diff
- docs/slides/BOS14/hs/start/06_Eval-done.hs too large to diff
- docs/slides/BOS14/hs/start/06_Eval.hs too large to diff
- docs/slides/BOS14/img/RedBlack.png too large to diff
- docs/slides/BOS14/img/RobertMorris.png too large to diff
- docs/slides/BOS14/img/bytestring.png too large to diff
- docs/slides/BOS14/img/code-spec-indiv.png too large to diff
- docs/slides/BOS14/img/code-spec-total.png too large to diff
- docs/slides/BOS14/img/firstbug-crop.jpg too large to diff
- docs/slides/BOS14/img/firstbug-crop2.jpg too large to diff
- docs/slides/BOS14/img/firstbug.jpg too large to diff
- docs/slides/BOS14/img/george-orwell.jpg too large to diff
- docs/slides/BOS14/img/gotofail.png too large to diff
- docs/slides/BOS14/img/heartbleed.png too large to diff
- docs/slides/BOS14/img/minindex-classic.png too large to diff
- docs/slides/BOS14/img/minindex-invariant.png too large to diff
- docs/slides/BOS14/img/minindex-modern.png too large to diff
- docs/slides/BOS14/img/minindex-reduce.png too large to diff
- docs/slides/BOS14/img/overflow.png too large to diff
- docs/slides/BOS14/img/rbtree-bad1.png too large to diff
- docs/slides/BOS14/img/rbtree-bad2.png too large to diff
- docs/slides/BOS14/img/rbtree-ok.png too large to diff
- docs/slides/BOS14/img/tension0.png too large to diff
- docs/slides/BOS14/img/tension1.png too large to diff
- docs/slides/BOS14/img/tension2.png too large to diff
- docs/slides/BOS14/img/tension3.png too large to diff
- docs/slides/BOS14/img/termination-results.png too large to diff
- docs/slides/BOS14/img/thoughtcrime.png too large to diff
- docs/slides/BOS14/img/ungood-small.jpg too large to diff
- docs/slides/BOS14/lhs/00_Motivation.lhs too large to diff
- docs/slides/BOS14/lhs/00_Motivation_Long.lhs too large to diff
- docs/slides/BOS14/lhs/01_SimpleRefinements.lhs too large to diff
- docs/slides/BOS14/lhs/02_Measures.lhs too large to diff
- docs/slides/BOS14/lhs/03_HigherOrderFunctions.lhs too large to diff
- docs/slides/BOS14/lhs/04_AbstractRefinements.lhs too large to diff
- docs/slides/BOS14/lhs/05_Composition.lhs too large to diff
- docs/slides/BOS14/lhs/06_Inductive.lhs too large to diff
- docs/slides/BOS14/lhs/07_Array.lhs too large to diff
- docs/slides/BOS14/lhs/08_Recursive.lhs too large to diff
- docs/slides/BOS14/lhs/09_Laziness.lhs too large to diff
- docs/slides/BOS14/lhs/10_Termination.lhs too large to diff
- docs/slides/BOS14/lhs/11_Evaluation.lhs too large to diff
- docs/slides/BOS14/lhs/12_Conclusion.lhs too large to diff
- docs/slides/BOS14/lhs/13_RedBlack.lhs too large to diff
- docs/slides/BOS14/lhs/14_Memory.lhs too large to diff
- docs/slides/BOS14/lhs/Index-Boston-Haskell.lhs too large to diff
- docs/slides/BOS14/lhs/Index-Tufts.lhs too large to diff
- docs/slides/BOS14/lhs/Index.lhs too large to diff
- docs/slides/ETH14/Makefile too large to diff
- docs/slides/ETH14/MkCode.hs too large to diff
- docs/slides/ETH14/_support/liquid.css too large to diff
- docs/slides/ETH14/_support/liquidhaskell.css too large to diff
- docs/slides/ETH14/_support/reveal.js/.travis.yml too large to diff
- docs/slides/ETH14/_support/reveal.js/Gruntfile.js too large to diff
- docs/slides/ETH14/_support/reveal.js/LICENSE too large to diff
- docs/slides/ETH14/_support/reveal.js/lib/font/league_gothic-webfont.eot too large to diff
- docs/slides/ETH14/_support/reveal.js/lib/font/league_gothic-webfont.svg too large to diff
- docs/slides/ETH14/_support/reveal.js/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/ETH14/_support/reveal.js/lib/font/league_gothic-webfont.woff too large to diff
- docs/slides/ETH14/_support/reveal.js/lib/font/league_gothic_license too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/highlight/highlight.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/leap/leap.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/markdown/markdown.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/markdown/marked.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/math/math.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/multiplex/client.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/multiplex/index.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/multiplex/master.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/notes-server/client.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/notes-server/index.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/notes/notes.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/postmessage/postmessage.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/print-pdf/print-pdf.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/remotes/remotes.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/search/search.js too large to diff
- docs/slides/ETH14/_support/reveal.js/plugin/zoom-js/zoom.js too large to diff
- docs/slides/ETH14/_support/reveal.js/test/examples/assets/image1.png too large to diff
- docs/slides/ETH14/_support/reveal.js/test/examples/assets/image2.png too large to diff
- docs/slides/ETH14/_support/reveal.js/test/qunit-1.12.0.css too large to diff
- docs/slides/ETH14/_support/reveal.js/test/qunit-1.12.0.js too large to diff
- docs/slides/ETH14/_support/reveal.js/test/test-markdown-element-attributes.js too large to diff
- docs/slides/ETH14/_support/reveal.js/test/test-markdown-slide-attributes.js too large to diff
- docs/slides/ETH14/_support/reveal.js/test/test-markdown.js too large to diff
- docs/slides/ETH14/_support/reveal.js/test/test.js too large to diff
- docs/slides/ETH14/_support/template.reveal too large to diff
- docs/slides/ETH14/cleanup too large to diff
- docs/slides/ETH14/img/RedBlack.png too large to diff
- docs/slides/ETH14/img/minindex-classic.png too large to diff
- docs/slides/ETH14/img/minindex-invariant.png too large to diff
- docs/slides/ETH14/img/minindex-modern.png too large to diff
- docs/slides/ETH14/img/minindex-reduce.png too large to diff
- docs/slides/ETH14/img/tension0.png too large to diff
- docs/slides/ETH14/img/tension1.png too large to diff
- docs/slides/ETH14/img/tension2.png too large to diff
- docs/slides/ETH14/img/tension3.png too large to diff
- docs/slides/ETH14/lhs/00_Motivation.lhs too large to diff
- docs/slides/ETH14/lhs/01_SimpleRefinements.lhs too large to diff
- docs/slides/ETH14/lhs/02_Measures.lhs too large to diff
- docs/slides/ETH14/lhs/03_HigherOrderFunctions.lhs too large to diff
- docs/slides/ETH14/lhs/04_AbstractRefinements.lhs too large to diff
- docs/slides/ETH14/lhs/05_Composition.lhs too large to diff
- docs/slides/ETH14/lhs/06_Inductive.lhs too large to diff
- docs/slides/ETH14/lhs/07_Array.lhs too large to diff
- docs/slides/ETH14/lhs/08_Recursive.lhs too large to diff
- docs/slides/ETH14/lhs/09_Laziness.lhs too large to diff
- docs/slides/ETH14/lhs/10_Termination.lhs too large to diff
- docs/slides/ETH14/lhs/11_Evaluation.lhs too large to diff
- docs/slides/ETH14/lhs/12_Conclusion.lhs too large to diff
- docs/slides/ETH14/lhs/Index.lhs too large to diff
- docs/slides/Galois2014/000_Refinements.hs too large to diff
- docs/slides/Galois2014/001_Refinements.hs too large to diff
- docs/slides/Galois2014/01_Elements.hs too large to diff
- docs/slides/Galois2014/05_Memory.hs too large to diff
- docs/slides/HS2014/Basics-blank.hs too large to diff
- docs/slides/HS2014/Basics.lhs too large to diff
- docs/slides/HS2014/ByteString-BAD-DIFFCHECK.hs too large to diff
- docs/slides/HS2014/ByteString-blank.hs too large to diff
- docs/slides/HS2014/ByteString.lhs too large to diff
- docs/slides/HS2014/TODO.md too large to diff
- docs/slides/HS2014/Totality-blank.hs too large to diff
- docs/slides/HS2014/Totality.lhs too large to diff
- docs/slides/IHP14/Makefile too large to diff
- docs/slides/IHP14/MkCode.hs too large to diff
- docs/slides/IHP14/_support/.template2.reveal.swp too large to diff
- docs/slides/IHP14/_support/liquid.css too large to diff
- docs/slides/IHP14/_support/liquidhaskell.css too large to diff
- docs/slides/IHP14/_support/reveal.js/.travis.yml too large to diff
- docs/slides/IHP14/_support/reveal.js/Gruntfile.js too large to diff
- docs/slides/IHP14/_support/reveal.js/LICENSE too large to diff
- docs/slides/IHP14/_support/reveal.js/README.md too large to diff
- docs/slides/IHP14/_support/reveal.js/css/print/paper.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/print/pdf.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/reveal.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/reveal.min.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/README.md too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/beige.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/blood.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/default.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/moon.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/night.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/seminar.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/seminar.orig.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/serif.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/simple.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/sky.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/solarized.css too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/beige.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/blood.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/default.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/moon.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/night.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/serif.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/simple.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/sky.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/source/solarized.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/template/mixins.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/template/settings.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/css/theme/template/theme.scss too large to diff
- docs/slides/IHP14/_support/reveal.js/index.html too large to diff
- docs/slides/IHP14/_support/reveal.js/js/reveal.js too large to diff
- docs/slides/IHP14/_support/reveal.js/js/reveal.min.js too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/css/zenburn.css too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/font/league_gothic-webfont.eot too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/font/league_gothic-webfont.svg too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/font/league_gothic-webfont.woff too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/font/league_gothic_license too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/js/classList.js too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/js/head.min.js too large to diff
- docs/slides/IHP14/_support/reveal.js/lib/js/html5shiv.js too large to diff
- docs/slides/IHP14/_support/reveal.js/package.json too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/highlight/highlight.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/leap/leap.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/markdown/example.html too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/markdown/example.md too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/markdown/markdown.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/markdown/marked.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/math/math.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/multiplex/client.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/multiplex/index.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/multiplex/master.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/notes-server/client.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/notes-server/index.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/notes-server/notes.html too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/notes/notes.html too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/notes/notes.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/postmessage/example.html too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/postmessage/postmessage.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/print-pdf/print-pdf.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/remotes/remotes.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/search/search.js too large to diff
- docs/slides/IHP14/_support/reveal.js/plugin/zoom-js/zoom.js too large to diff
- docs/slides/IHP14/_support/reveal.js/test/examples/assets/image1.png too large to diff
- docs/slides/IHP14/_support/reveal.js/test/examples/assets/image2.png too large to diff
- docs/slides/IHP14/_support/reveal.js/test/examples/barebones.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/examples/embedded-media.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/examples/math.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/examples/slide-backgrounds.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/qunit-1.12.0.css too large to diff
- docs/slides/IHP14/_support/reveal.js/test/qunit-1.12.0.js too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test-markdown-element-attributes.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test-markdown-element-attributes.js too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test-markdown-slide-attributes.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test-markdown-slide-attributes.js too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test-markdown.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test-markdown.js too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test.html too large to diff
- docs/slides/IHP14/_support/reveal.js/test/test.js too large to diff
- docs/slides/IHP14/_support/template.reveal too large to diff
- docs/slides/IHP14/cleanup too large to diff
- docs/slides/IHP14/img/RedBlack.png too large to diff
- docs/slides/IHP14/img/tension0.png too large to diff
- docs/slides/IHP14/img/tension1.png too large to diff
- docs/slides/IHP14/img/tension2.png too large to diff
- docs/slides/IHP14/img/tension3.png too large to diff
- docs/slides/IHP14/lhs/00_Motivation_GoWrong.lhs too large to diff
- docs/slides/IHP14/lhs/00_Motivation_Logic.lhs too large to diff
- docs/slides/IHP14/lhs/01_SimpleRefinements.lhs too large to diff
- docs/slides/IHP14/lhs/02_Measures.lhs too large to diff
- docs/slides/IHP14/lhs/03_HigherOrderFunctions.lhs too large to diff
- docs/slides/IHP14/lhs/04_AbstractRefinements.lhs too large to diff
- docs/slides/IHP14/lhs/05_Composition.lhs too large to diff
- docs/slides/IHP14/lhs/06_Inductive.lhs too large to diff
- docs/slides/IHP14/lhs/07_Array.lhs too large to diff
- docs/slides/IHP14/lhs/08_Recursive.lhs too large to diff
- docs/slides/IHP14/lhs/09_Laziness.lhs too large to diff
- docs/slides/IHP14/lhs/10_Termination.lhs too large to diff
- docs/slides/IHP14/lhs/11_Evaluation.lhs too large to diff
- docs/slides/IHP14/lhs/12_Conclusion.lhs too large to diff
- docs/slides/IHP14/lhs/Index.lhs too large to diff
- docs/slides/LambdaConf15/lhs/01_SimpleRefinements.lhs too large to diff
- docs/slides/NEU14/00_Refinements-blank.hs too large to diff
- docs/slides/NEU14/00_Refinements.hs too large to diff
- docs/slides/NEU14/01_AbstractRefinements-blank.hs too large to diff
- docs/slides/NEU14/01_AbstractRefinements.hs too large to diff
- docs/slides/NEU14/02_Termination-blank.hs too large to diff
- docs/slides/NEU14/02_Termination.hs too large to diff
- docs/slides/NEU14/AlphaConvert.hs too large to diff
- docs/slides/NEU14/Eval.hs too large to diff
- docs/slides/NEU14/RBTree.hs too large to diff
- docs/slides/flops14/Makefile too large to diff
- docs/slides/flops14/TODO.md too large to diff
- docs/slides/flops14/_support/liquid.css too large to diff
- docs/slides/flops14/_support/reveal/LICENSE too large to diff
- docs/slides/flops14/_support/reveal/README.md too large to diff
- docs/slides/flops14/_support/reveal/css/liquidhaskell.css too large to diff
- docs/slides/flops14/_support/reveal/css/main.css too large to diff
- docs/slides/flops14/_support/reveal/css/print/paper.css too large to diff
- docs/slides/flops14/_support/reveal/css/print/pdf.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/beige.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/default.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/seminar.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/seminar.orig.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/serif.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/simple.css too large to diff
- docs/slides/flops14/_support/reveal/css/theme/sky.css too large to diff
- docs/slides/flops14/_support/reveal/js/.reveal.js.swo too large to diff
- docs/slides/flops14/_support/reveal/js/.reveal.js.swp too large to diff
- docs/slides/flops14/_support/reveal/js/.reveal.min.js.swo too large to diff
- docs/slides/flops14/_support/reveal/js/.reveal.min.js.swp too large to diff
- docs/slides/flops14/_support/reveal/js/reveal.js too large to diff
- docs/slides/flops14/_support/reveal/js/reveal.min.js too large to diff
- docs/slides/flops14/_support/reveal/lib/css/zenburn.css too large to diff
- docs/slides/flops14/_support/reveal/lib/font/OpenSans-Regular.ttf too large to diff
- docs/slides/flops14/_support/reveal/lib/font/PT_Sans-Narrow-Web-Regular.ttf too large to diff
- docs/slides/flops14/_support/reveal/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/flops14/_support/reveal/lib/js/classList.js too large to diff
- docs/slides/flops14/_support/reveal/lib/js/data-markdown.js too large to diff
- docs/slides/flops14/_support/reveal/lib/js/head.min.js too large to diff
- docs/slides/flops14/_support/reveal/lib/js/highlight.js too large to diff
- docs/slides/flops14/_support/reveal/lib/js/html5shiv.js too large to diff
- docs/slides/flops14/_support/reveal/lib/js/showdown.js too large to diff
- docs/slides/flops14/_support/reveal/package.json too large to diff
- docs/slides/flops14/_support/reveal/plugin/speakernotes/client.js too large to diff
- docs/slides/flops14/_support/reveal/plugin/speakernotes/index.js too large to diff
- docs/slides/flops14/_support/reveal/plugin/speakernotes/notes.html too large to diff
- docs/slides/flops14/_support/template.reveal too large to diff
- docs/slides/flops14/cleanup too large to diff
- docs/slides/flops14/img/RedBlack.png too large to diff
- docs/slides/flops14/lhs/00_Index.lhs too large to diff
- docs/slides/flops14/lhs/01_SimpleRefinements.lhs too large to diff
- docs/slides/flops14/lhs/02_Measures.lhs too large to diff
- docs/slides/flops14/lhs/03_HigherOrderFunctions.lhs too large to diff
- docs/slides/flops14/lhs/04_AbstractRefinements.lhs too large to diff
- docs/slides/flops14/lhs/05_Composition.lhs too large to diff
- docs/slides/flops14/lhs/06_Inductive.lhs too large to diff
- docs/slides/flops14/lhs/07_Array.lhs too large to diff
- docs/slides/flops14/lhs/08_Recursive.lhs too large to diff
- docs/slides/flops14/lhs/09_Laziness.lhs too large to diff
- docs/slides/flops14/lhs/10_Termination.lhs too large to diff
- docs/slides/flops14/lhs/11_Evaluation.lhs too large to diff
- docs/slides/flops14/reveal.js/.gitignore too large to diff
- docs/slides/flops14/reveal.js/.travis.yml too large to diff
- docs/slides/flops14/reveal.js/Gruntfile.js too large to diff
- docs/slides/flops14/reveal.js/LICENSE too large to diff
- docs/slides/flops14/reveal.js/lib/font/league_gothic-webfont.eot too large to diff
- docs/slides/flops14/reveal.js/lib/font/league_gothic-webfont.svg too large to diff
- docs/slides/flops14/reveal.js/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/flops14/reveal.js/lib/font/league_gothic-webfont.woff too large to diff
- docs/slides/flops14/reveal.js/lib/font/league_gothic_license too large to diff
- docs/slides/flops14/reveal.js/plugin/highlight/highlight.js too large to diff
- docs/slides/flops14/reveal.js/plugin/leap/leap.js too large to diff
- docs/slides/flops14/reveal.js/plugin/markdown/markdown.js too large to diff
- docs/slides/flops14/reveal.js/plugin/markdown/marked.js too large to diff
- docs/slides/flops14/reveal.js/plugin/math/math.js too large to diff
- docs/slides/flops14/reveal.js/plugin/multiplex/client.js too large to diff
- docs/slides/flops14/reveal.js/plugin/multiplex/index.js too large to diff
- docs/slides/flops14/reveal.js/plugin/multiplex/master.js too large to diff
- docs/slides/flops14/reveal.js/plugin/notes-server/client.js too large to diff
- docs/slides/flops14/reveal.js/plugin/notes-server/index.js too large to diff
- docs/slides/flops14/reveal.js/plugin/notes/notes.js too large to diff
- docs/slides/flops14/reveal.js/plugin/postmessage/postmessage.js too large to diff
- docs/slides/flops14/reveal.js/plugin/print-pdf/print-pdf.js too large to diff
- docs/slides/flops14/reveal.js/plugin/remotes/remotes.js too large to diff
- docs/slides/flops14/reveal.js/plugin/search/search.js too large to diff
- docs/slides/flops14/reveal.js/plugin/zoom-js/zoom.js too large to diff
- docs/slides/flops14/reveal.js/test/examples/assets/image1.png too large to diff
- docs/slides/flops14/reveal.js/test/examples/assets/image2.png too large to diff
- docs/slides/flops14/reveal.js/test/qunit-1.12.0.css too large to diff
- docs/slides/flops14/reveal.js/test/qunit-1.12.0.js too large to diff
- docs/slides/flops14/reveal.js/test/test-markdown-element-attributes.js too large to diff
- docs/slides/flops14/reveal.js/test/test-markdown-slide-attributes.js too large to diff
- docs/slides/flops14/reveal.js/test/test-markdown.js too large to diff
- docs/slides/flops14/reveal.js/test/test.js too large to diff
- docs/slides/niki/Makefile too large to diff
- docs/slides/niki/fonts/OFT.txt too large to diff
- docs/slides/niki/fonts/PT_Mono-Regular.ttf too large to diff
- docs/slides/niki/fonts/PT_Sans-Narrow-Web-Bold.ttf too large to diff
- docs/slides/niki/fonts/PT_Sans-Narrow-Web-Regular.ttf too large to diff
- docs/slides/niki/fonts/PT_Sans-Web-Bold.ttf too large to diff
- docs/slides/niki/fonts/PT_Sans-Web-BoldItalic.ttf too large to diff
- docs/slides/niki/fonts/PT_Sans-Web-Italic.ttf too large to diff
- docs/slides/niki/fonts/PT_Sans-Web-Regular.ttf too large to diff
- docs/slides/niki/html/benchmarks.png too large to diff
- docs/slides/niki/html/fonts/OFT.txt too large to diff
- docs/slides/niki/html/fonts/PT_Mono-Regular.ttf too large to diff
- docs/slides/niki/html/fonts/PT_Sans-Narrow-Web-Bold.ttf too large to diff
- docs/slides/niki/html/fonts/PT_Sans-Narrow-Web-Regular.ttf too large to diff
- docs/slides/niki/html/fonts/PT_Sans-Web-Bold.ttf too large to diff
- docs/slides/niki/html/fonts/PT_Sans-Web-BoldItalic.ttf too large to diff
- docs/slides/niki/html/fonts/PT_Sans-Web-Italic.ttf too large to diff
- docs/slides/niki/html/fonts/PT_Sans-Web-Regular.ttf too large to diff
- docs/slides/niki/html/liquid.css too large to diff
- docs/slides/niki/html/slides.css too large to diff
- docs/slides/niki/lhs/AbstractRefinements.lhs too large to diff
- docs/slides/niki/lhs/Array.lhs too large to diff
- docs/slides/niki/lhs/Composition.lhs too large to diff
- docs/slides/niki/lhs/Inductive.lhs too large to diff
- docs/slides/niki/lhs/Laziness.lhs too large to diff
- docs/slides/niki/lhs/List.lhs too large to diff
- docs/slides/niki/lhs/Loop.lhs too large to diff
- docs/slides/niki/lhs/Measures.lhs too large to diff
- docs/slides/niki/lhs/SimpleRefinements.lhs too large to diff
- docs/slides/niki/lhs/liquid.css too large to diff
- docs/slides/niki/lhs/slides.css too large to diff
- docs/slides/plpv14/Makefile too large to diff
- docs/slides/plpv14/_support/liquid.css too large to diff
- docs/slides/plpv14/_support/reveal/LICENSE too large to diff
- docs/slides/plpv14/_support/reveal/README.md too large to diff
- docs/slides/plpv14/_support/reveal/css/liquidhaskell.css too large to diff
- docs/slides/plpv14/_support/reveal/css/main.css too large to diff
- docs/slides/plpv14/_support/reveal/css/print/paper.css too large to diff
- docs/slides/plpv14/_support/reveal/css/print/pdf.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/beige.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/default.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/seminar.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/seminar.orig.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/serif.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/simple.css too large to diff
- docs/slides/plpv14/_support/reveal/css/theme/sky.css too large to diff
- docs/slides/plpv14/_support/reveal/js/.reveal.js.swo too large to diff
- docs/slides/plpv14/_support/reveal/js/.reveal.js.swp too large to diff
- docs/slides/plpv14/_support/reveal/js/.reveal.min.js.swo too large to diff
- docs/slides/plpv14/_support/reveal/js/.reveal.min.js.swp too large to diff
- docs/slides/plpv14/_support/reveal/js/reveal.js too large to diff
- docs/slides/plpv14/_support/reveal/js/reveal.min.js too large to diff
- docs/slides/plpv14/_support/reveal/lib/css/zenburn.css too large to diff
- docs/slides/plpv14/_support/reveal/lib/font/OpenSans-Regular.ttf too large to diff
- docs/slides/plpv14/_support/reveal/lib/font/PT_Sans-Narrow-Web-Regular.ttf too large to diff
- docs/slides/plpv14/_support/reveal/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/plpv14/_support/reveal/lib/js/classList.js too large to diff
- docs/slides/plpv14/_support/reveal/lib/js/data-markdown.js too large to diff
- docs/slides/plpv14/_support/reveal/lib/js/head.min.js too large to diff
- docs/slides/plpv14/_support/reveal/lib/js/highlight.js too large to diff
- docs/slides/plpv14/_support/reveal/lib/js/html5shiv.js too large to diff
- docs/slides/plpv14/_support/reveal/lib/js/showdown.js too large to diff
- docs/slides/plpv14/_support/reveal/package.json too large to diff
- docs/slides/plpv14/_support/reveal/plugin/speakernotes/client.js too large to diff
- docs/slides/plpv14/_support/reveal/plugin/speakernotes/index.js too large to diff
- docs/slides/plpv14/_support/reveal/plugin/speakernotes/notes.html too large to diff
- docs/slides/plpv14/_support/template.reveal too large to diff
- docs/slides/plpv14/hopa/AbstractRefinements.lhs too large to diff
- docs/slides/plpv14/lhs/.01_SimpleRefinements.lhs.swn too large to diff
- docs/slides/plpv14/lhs/00_Index.lhs too large to diff
- docs/slides/plpv14/lhs/00_Index.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/01_SimpleRefinements.lhs too large to diff
- docs/slides/plpv14/lhs/01_SimpleRefinements.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/02_Measures.lhs too large to diff
- docs/slides/plpv14/lhs/02_Measures.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/03_HigherOrderFunctions.lhs too large to diff
- docs/slides/plpv14/lhs/03_HigherOrderFunctions.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/04_AbstractRefinements.lhs too large to diff
- docs/slides/plpv14/lhs/04_AbstractRefinements.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/05_Composition.lhs too large to diff
- docs/slides/plpv14/lhs/05_Composition.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/06_Inductive.lhs too large to diff
- docs/slides/plpv14/lhs/06_Inductive.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/07_Array.lhs too large to diff
- docs/slides/plpv14/lhs/07_Array.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/08_Recursive.lhs too large to diff
- docs/slides/plpv14/lhs/08_Recursive.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/09_Laziness.lhs too large to diff
- docs/slides/plpv14/lhs/09_Laziness.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/10_Termination.lhs too large to diff
- docs/slides/plpv14/lhs/10_Termination.lhs.markdown too large to diff
- docs/slides/plpv14/lhs/liquid.css too large to diff
- docs/slides/plpv14/pdcreveal.tgz too large to diff
- docs/slides/plpv14/reveal.js/.gitignore too large to diff
- docs/slides/plpv14/reveal.js/.travis.yml too large to diff
- docs/slides/plpv14/reveal.js/Gruntfile.js too large to diff
- docs/slides/plpv14/reveal.js/LICENSE too large to diff
- docs/slides/plpv14/reveal.js/lib/font/league_gothic-webfont.eot too large to diff
- docs/slides/plpv14/reveal.js/lib/font/league_gothic-webfont.svg too large to diff
- docs/slides/plpv14/reveal.js/lib/font/league_gothic-webfont.ttf too large to diff
- docs/slides/plpv14/reveal.js/lib/font/league_gothic-webfont.woff too large to diff
- docs/slides/plpv14/reveal.js/lib/font/league_gothic_license too large to diff
- docs/slides/plpv14/reveal.js/plugin/highlight/highlight.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/leap/leap.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/markdown/markdown.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/markdown/marked.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/math/math.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/multiplex/client.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/multiplex/index.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/multiplex/master.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/notes-server/client.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/notes-server/index.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/notes/notes.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/postmessage/postmessage.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/print-pdf/print-pdf.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/remotes/remotes.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/search/search.js too large to diff
- docs/slides/plpv14/reveal.js/plugin/zoom-js/zoom.js too large to diff
- docs/slides/plpv14/reveal.js/test/examples/assets/image1.png too large to diff
- docs/slides/plpv14/reveal.js/test/examples/assets/image2.png too large to diff
- docs/slides/plpv14/reveal.js/test/qunit-1.12.0.css too large to diff
- docs/slides/plpv14/reveal.js/test/qunit-1.12.0.js too large to diff
- docs/slides/plpv14/reveal.js/test/test-markdown-element-attributes.js too large to diff
- docs/slides/plpv14/reveal.js/test/test-markdown-slide-attributes.js too large to diff
- docs/slides/plpv14/reveal.js/test/test-markdown.js too large to diff
- docs/slides/plpv14/reveal.js/test/test.js too large to diff
- docs/slides/plpv14/tmp/Foo.hs too large to diff
- docs/slides/plpv14/tmp/liquid.css too large to diff
- external/hsmisc/Graphs.hs too large to diff
- external/hsmisc/Lhs2Hs.hs too large to diff
- include/Data/ByteString/Lazy/Char8.spec too large to diff
- include/Data/Map.hiddenspec too large to diff
- include/Data/Time/Calendar.spec too large to diff
- liquid-base/LICENSE too large to diff
- liquid-base/Setup.hs too large to diff
- liquid-base/liquid-base.cabal too large to diff
- liquid-base/src/Control/Applicative.hs too large to diff
- liquid-base/src/Control/Arrow.hs too large to diff
- liquid-base/src/Control/Category.hs too large to diff
- liquid-base/src/Control/Concurrent.hs too large to diff
- liquid-base/src/Control/Concurrent/Chan.hs too large to diff
- liquid-base/src/Control/Concurrent/MVar.hs too large to diff
- liquid-base/src/Control/Concurrent/QSem.hs too large to diff
- liquid-base/src/Control/Concurrent/QSemN.hs too large to diff
- liquid-base/src/Control/Exception.hs too large to diff
- liquid-base/src/Control/Exception.spec too large to diff
- liquid-base/src/Control/Exception/Base.hs too large to diff
- liquid-base/src/Control/Monad.hs too large to diff
- liquid-base/src/Control/Monad/Fail.hs too large to diff
- liquid-base/src/Control/Monad/Fix.hs too large to diff
- liquid-base/src/Control/Monad/IO/Class.hs too large to diff
- liquid-base/src/Control/Monad/Instances.hs too large to diff
- liquid-base/src/Control/Monad/ST.hs too large to diff
- liquid-base/src/Control/Monad/ST/Lazy.hs too large to diff
- liquid-base/src/Control/Monad/ST/Lazy/Safe.hs too large to diff
- liquid-base/src/Control/Monad/ST/Lazy/Unsafe.hs too large to diff
- liquid-base/src/Control/Monad/ST/Safe.hs too large to diff
- liquid-base/src/Control/Monad/ST/Strict.hs too large to diff
- liquid-base/src/Control/Monad/ST/Unsafe.hs too large to diff
- liquid-base/src/Control/Monad/Zip.hs too large to diff
- liquid-base/src/Data/Bifoldable.hs too large to diff
- liquid-base/src/Data/Bifunctor.hs too large to diff
- liquid-base/src/Data/Bitraversable.hs too large to diff
- liquid-base/src/Data/Bits.hs too large to diff
- liquid-base/src/Data/Bits.spec too large to diff
- liquid-base/src/Data/Bool.hs too large to diff
- liquid-base/src/Data/Char.hs too large to diff
- liquid-base/src/Data/Coerce.hs too large to diff
- liquid-base/src/Data/Complex.hs too large to diff
- liquid-base/src/Data/Data.hs too large to diff
- liquid-base/src/Data/Dynamic.hs too large to diff
- liquid-base/src/Data/Either.hs too large to diff
- liquid-base/src/Data/Either.spec too large to diff
- liquid-base/src/Data/Eq.hs too large to diff
- liquid-base/src/Data/Fixed.hs too large to diff
- liquid-base/src/Data/Foldable.hs too large to diff
- liquid-base/src/Data/Foldable.spec too large to diff
- liquid-base/src/Data/Function.hs too large to diff
- liquid-base/src/Data/Functor.hs too large to diff
- liquid-base/src/Data/Functor/Classes.hs too large to diff
- liquid-base/src/Data/Functor/Compose.hs too large to diff
- liquid-base/src/Data/Functor/Const.hs too large to diff
- liquid-base/src/Data/Functor/Contravariant.hs too large to diff
- liquid-base/src/Data/Functor/Identity.hs too large to diff
- liquid-base/src/Data/Functor/Product.hs too large to diff
- liquid-base/src/Data/Functor/Sum.hs too large to diff
- liquid-base/src/Data/IORef.hs too large to diff
- liquid-base/src/Data/Int.hs too large to diff
- liquid-base/src/Data/Int.spec too large to diff
- liquid-base/src/Data/Ix.hs too large to diff
- liquid-base/src/Data/Kind.hs too large to diff
- liquid-base/src/Data/List.hs too large to diff
- liquid-base/src/Data/List/NonEmpty.hs too large to diff
- liquid-base/src/Data/Maybe.hs too large to diff
- liquid-base/src/Data/Maybe.spec too large to diff
- liquid-base/src/Data/Monoid.hs too large to diff
- liquid-base/src/Data/Ord.hs too large to diff
- liquid-base/src/Data/Proxy.hs too large to diff
- liquid-base/src/Data/Ratio.hs too large to diff
- liquid-base/src/Data/STRef.hs too large to diff
- liquid-base/src/Data/STRef/Lazy.hs too large to diff
- liquid-base/src/Data/STRef/Strict.hs too large to diff
- liquid-base/src/Data/Semigroup.hs too large to diff
- liquid-base/src/Data/String.hs too large to diff
- liquid-base/src/Data/String.spec too large to diff
- liquid-base/src/Data/Traversable.hs too large to diff
- liquid-base/src/Data/Tuple.hs too large to diff
- liquid-base/src/Data/Tuple.spec too large to diff
- liquid-base/src/Data/Type/Bool.hs too large to diff
- liquid-base/src/Data/Type/Coercion.hs too large to diff
- liquid-base/src/Data/Type/Equality.hs too large to diff
- liquid-base/src/Data/Typeable.hs too large to diff
- liquid-base/src/Data/Unique.hs too large to diff
- liquid-base/src/Data/Version.hs too large to diff
- liquid-base/src/Data/Void.hs too large to diff
- liquid-base/src/Data/Word.hs too large to diff
- liquid-base/src/Data/Word.spec too large to diff
- liquid-base/src/Debug/Trace.hs too large to diff
- liquid-base/src/Foreign.hs too large to diff
- liquid-base/src/Foreign/C.hs too large to diff
- liquid-base/src/Foreign/C/Error.hs too large to diff
- liquid-base/src/Foreign/C/String.hs too large to diff
- liquid-base/src/Foreign/C/String.spec too large to diff
- liquid-base/src/Foreign/C/Types.hs too large to diff
- liquid-base/src/Foreign/C/Types.spec too large to diff
- liquid-base/src/Foreign/Concurrent.hs too large to diff
- liquid-base/src/Foreign/Concurrent.spec too large to diff
- liquid-base/src/Foreign/ForeignPtr.hs too large to diff
- liquid-base/src/Foreign/ForeignPtr.spec too large to diff
- liquid-base/src/Foreign/ForeignPtr/Safe.hs too large to diff
- liquid-base/src/Foreign/ForeignPtr/Unsafe.hs too large to diff
- liquid-base/src/Foreign/Marshal.hs too large to diff
- liquid-base/src/Foreign/Marshal/Alloc.hs too large to diff
- liquid-base/src/Foreign/Marshal/Alloc.spec too large to diff
- liquid-base/src/Foreign/Marshal/Array.hs too large to diff
- liquid-base/src/Foreign/Marshal/Error.hs too large to diff
- liquid-base/src/Foreign/Marshal/Pool.hs too large to diff
- liquid-base/src/Foreign/Marshal/Safe.hs too large to diff
- liquid-base/src/Foreign/Marshal/Unsafe.hs too large to diff
- liquid-base/src/Foreign/Marshal/Utils.hs too large to diff
- liquid-base/src/Foreign/Ptr.hs too large to diff
- liquid-base/src/Foreign/Ptr.spec too large to diff
- liquid-base/src/Foreign/Safe.hs too large to diff
- liquid-base/src/Foreign/StablePtr.hs too large to diff
- liquid-base/src/Foreign/Storable.hs too large to diff
- liquid-base/src/Foreign/Storable.spec too large to diff
- liquid-base/src/GHC/Arr.hs too large to diff
- liquid-base/src/GHC/Base.hs too large to diff
- liquid-base/src/GHC/Base.spec too large to diff
- liquid-base/src/GHC/ByteOrder.hs too large to diff
- liquid-base/src/GHC/Char.hs too large to diff
- liquid-base/src/GHC/Clock.hs too large to diff
- liquid-base/src/GHC/Conc.hs too large to diff
- liquid-base/src/GHC/Conc/IO.hs too large to diff
- liquid-base/src/GHC/Conc/Signal.hs too large to diff
- liquid-base/src/GHC/Conc/Sync.hs too large to diff
- liquid-base/src/GHC/ConsoleHandler.hs too large to diff
- liquid-base/src/GHC/Constants.hs too large to diff
- liquid-base/src/GHC/Desugar.hs too large to diff
- liquid-base/src/GHC/Enum.hs too large to diff
- liquid-base/src/GHC/Environment.hs too large to diff
- liquid-base/src/GHC/Err.hs too large to diff
- liquid-base/src/GHC/Exception.hs too large to diff
- liquid-base/src/GHC/Exception/Type.hs too large to diff
- liquid-base/src/GHC/ExecutionStack.hs too large to diff
- liquid-base/src/GHC/ExecutionStack/Internal.hs too large to diff
- liquid-base/src/GHC/Exts.hs too large to diff
- liquid-base/src/GHC/Fingerprint.hs too large to diff
- liquid-base/src/GHC/Fingerprint/Type.hs too large to diff
- liquid-base/src/GHC/Float.hs too large to diff
- liquid-base/src/GHC/Float/ConversionUtils.hs too large to diff
- liquid-base/src/GHC/Float/RealFracMethods.hs too large to diff
- liquid-base/src/GHC/Foreign.hs too large to diff
- liquid-base/src/GHC/ForeignPtr.hs too large to diff
- liquid-base/src/GHC/ForeignPtr.spec too large to diff
- liquid-base/src/GHC/GHCi.hs too large to diff
- liquid-base/src/GHC/GHCi/Helpers.hs too large to diff
- liquid-base/src/GHC/Generics.hs too large to diff
- liquid-base/src/GHC/IO.hs too large to diff
- liquid-base/src/GHC/IO/Buffer.hs too large to diff
- liquid-base/src/GHC/IO/BufferedIO.hs too large to diff
- liquid-base/src/GHC/IO/Device.hs too large to diff
- liquid-base/src/GHC/IO/Encoding.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/CodePage.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/Failure.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/Iconv.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/Latin1.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/Types.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/UTF16.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/UTF32.hs too large to diff
- liquid-base/src/GHC/IO/Encoding/UTF8.hs too large to diff
- liquid-base/src/GHC/IO/Exception.hs too large to diff
- liquid-base/src/GHC/IO/FD.hs too large to diff
- liquid-base/src/GHC/IO/Handle.hs too large to diff
- liquid-base/src/GHC/IO/Handle.spec too large to diff
- liquid-base/src/GHC/IO/Handle/FD.hs too large to diff
- liquid-base/src/GHC/IO/Handle/Internals.hs too large to diff
- liquid-base/src/GHC/IO/Handle/Lock.hs too large to diff
- liquid-base/src/GHC/IO/Handle/Text.hs too large to diff
- liquid-base/src/GHC/IO/Handle/Types.hs too large to diff
- liquid-base/src/GHC/IO/IOMode.hs too large to diff
- liquid-base/src/GHC/IO/Unsafe.hs too large to diff
- liquid-base/src/GHC/IOArray.hs too large to diff
- liquid-base/src/GHC/IORef.hs too large to diff
- liquid-base/src/GHC/Int.hs too large to diff
- liquid-base/src/GHC/Int.spec too large to diff
- liquid-base/src/GHC/Ix.hs too large to diff
- liquid-base/src/GHC/List.hs too large to diff
- liquid-base/src/GHC/List.spec too large to diff
- liquid-base/src/GHC/MVar.hs too large to diff
- liquid-base/src/GHC/Maybe.hs too large to diff
- liquid-base/src/GHC/Natural.hs too large to diff
- liquid-base/src/GHC/Num.hs too large to diff
- liquid-base/src/GHC/Num.spec too large to diff
- liquid-base/src/GHC/OldList.hs too large to diff
- liquid-base/src/GHC/OverloadedLabels.hs too large to diff
- liquid-base/src/GHC/Pack.hs too large to diff
- liquid-base/src/GHC/Profiling.hs too large to diff
- liquid-base/src/GHC/Ptr.hs too large to diff
- liquid-base/src/GHC/Ptr.spec too large to diff
- liquid-base/src/GHC/RTS/Flags.hs too large to diff
- liquid-base/src/GHC/Read.hs too large to diff
- liquid-base/src/GHC/Real.hs too large to diff
- liquid-base/src/GHC/Real.spec too large to diff
- liquid-base/src/GHC/Records.hs too large to diff
- liquid-base/src/GHC/ResponseFile.hs too large to diff
- liquid-base/src/GHC/ST.hs too large to diff
- liquid-base/src/GHC/STRef.hs too large to diff
- liquid-base/src/GHC/Show.hs too large to diff
- liquid-base/src/GHC/Stable.hs too large to diff
- liquid-base/src/GHC/StableName.hs too large to diff
- liquid-base/src/GHC/Stack.hs too large to diff
- liquid-base/src/GHC/Stack/CCS.hs too large to diff
- liquid-base/src/GHC/Stack/Types.hs too large to diff
- liquid-base/src/GHC/StaticPtr.hs too large to diff
- liquid-base/src/GHC/Stats.hs too large to diff
- liquid-base/src/GHC/Storable.hs too large to diff
- liquid-base/src/GHC/TopHandler.hs too large to diff
- liquid-base/src/GHC/TypeLits.hs too large to diff
- liquid-base/src/GHC/TypeNats.hs too large to diff
- liquid-base/src/GHC/Unicode.hs too large to diff
- liquid-base/src/GHC/Weak.hs too large to diff
- liquid-base/src/GHC/Word.hs too large to diff
- liquid-base/src/GHC/Word.spec too large to diff
- liquid-base/src/Liquid/Prelude/NotReal.hs too large to diff
- liquid-base/src/Liquid/Prelude/NotReal.spec too large to diff
- liquid-base/src/Liquid/Prelude/Real.hs too large to diff
- liquid-base/src/Liquid/Prelude/Real.spec too large to diff
- liquid-base/src/Liquid/Prelude/Totality.hs too large to diff
- liquid-base/src/Liquid/Prelude/Totality.spec too large to diff
- liquid-base/src/Numeric.hs too large to diff
- liquid-base/src/Numeric/Natural.hs too large to diff
- liquid-base/src/Prelude.hs too large to diff
- liquid-base/src/Prelude.spec too large to diff
- liquid-base/src/System/CPUTime.hs too large to diff
- liquid-base/src/System/Console/GetOpt.hs too large to diff
- liquid-base/src/System/Environment.hs too large to diff
- liquid-base/src/System/Environment/Blank.hs too large to diff
- liquid-base/src/System/Exit.hs too large to diff
- liquid-base/src/System/IO.hs too large to diff
- liquid-base/src/System/IO.spec too large to diff
- liquid-base/src/System/IO/Error.hs too large to diff
- liquid-base/src/System/IO/Unsafe.hs too large to diff
- liquid-base/src/System/Info.hs too large to diff
- liquid-base/src/System/Mem.hs too large to diff
- liquid-base/src/System/Mem/StableName.hs too large to diff
- liquid-base/src/System/Mem/Weak.hs too large to diff
- liquid-base/src/System/Posix/Internals.hs too large to diff
- liquid-base/src/System/Posix/Types.hs too large to diff
- liquid-base/src/System/Timeout.hs too large to diff
- liquid-base/src/Text/ParserCombinators/ReadP.hs too large to diff
- liquid-base/src/Text/ParserCombinators/ReadPrec.hs too large to diff
- liquid-base/src/Text/Printf.hs too large to diff
- liquid-base/src/Text/Read.hs too large to diff
- liquid-base/src/Text/Read/Lex.hs too large to diff
- liquid-base/src/Text/Show.hs too large to diff
- liquid-base/src/Text/Show/Functions.hs too large to diff
- liquid-base/src/Type/Reflection.hs too large to diff
- liquid-base/src/Type/Reflection/Unsafe.hs too large to diff
- liquid-base/src/Unsafe/Coerce.hs too large to diff
- liquid-bytestring/LICENSE too large to diff
- liquid-bytestring/Setup.hs too large to diff
- liquid-bytestring/liquid-bytestring.cabal too large to diff
- liquid-bytestring/src/Data/ByteString.hs too large to diff
- liquid-bytestring/src/Data/ByteString.spec too large to diff
- liquid-bytestring/src/Data/ByteString/Builder.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Builder/Extra.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Builder/Internal.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Builder/Prim.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Builder/Prim/Internal.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Char8.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Char8.spec too large to diff
- liquid-bytestring/src/Data/ByteString/Internal.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy.spec too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy/Builder.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy/Builder/ASCII.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy/Builder/Extras.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy/Char8.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy/Char8.spec too large to diff
- liquid-bytestring/src/Data/ByteString/Lazy/Internal.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Short.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Short.spec too large to diff
- liquid-bytestring/src/Data/ByteString/Short/Internal.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Unsafe.hs too large to diff
- liquid-bytestring/src/Data/ByteString/Unsafe.spec too large to diff
- liquid-containers/LICENSE too large to diff
- liquid-containers/Setup.hs too large to diff
- liquid-containers/liquid-containers.cabal too large to diff
- liquid-containers/src/Data/Containers/ListUtils.hs too large to diff
- liquid-containers/src/Data/Graph.hs too large to diff
- liquid-containers/src/Data/IntMap.hs too large to diff
- liquid-containers/src/Data/IntMap/Internal.hs too large to diff
- liquid-containers/src/Data/IntMap/Internal/Debug.hs too large to diff
- liquid-containers/src/Data/IntMap/Lazy.hs too large to diff
- liquid-containers/src/Data/IntMap/Merge/Lazy.hs too large to diff
- liquid-containers/src/Data/IntMap/Merge/Strict.hs too large to diff
- liquid-containers/src/Data/IntMap/Strict.hs too large to diff
- liquid-containers/src/Data/IntMap/Strict/Internal.hs too large to diff
- liquid-containers/src/Data/IntSet.hs too large to diff
- liquid-containers/src/Data/IntSet/Internal.hs too large to diff
- liquid-containers/src/Data/Map.hs too large to diff
- liquid-containers/src/Data/Map/Internal.hs too large to diff
- liquid-containers/src/Data/Map/Internal/Debug.hs too large to diff
- liquid-containers/src/Data/Map/Lazy.hs too large to diff
- liquid-containers/src/Data/Map/Merge/Lazy.hs too large to diff
- liquid-containers/src/Data/Map/Merge/Strict.hs too large to diff
- liquid-containers/src/Data/Map/Strict.hs too large to diff
- liquid-containers/src/Data/Map/Strict/Internal.hs too large to diff
- liquid-containers/src/Data/Sequence.hs too large to diff
- liquid-containers/src/Data/Sequence/Internal.hs too large to diff
- liquid-containers/src/Data/Sequence/Internal/Sorting.hs too large to diff
- liquid-containers/src/Data/Set.hs too large to diff
- liquid-containers/src/Data/Set.spec too large to diff
- liquid-containers/src/Data/Set/Internal.hs too large to diff
- liquid-containers/src/Data/Tree.hs too large to diff
- liquid-containers/src/Utils/Containers/Internal/BitQueue.hs too large to diff
- liquid-containers/src/Utils/Containers/Internal/BitUtil.hs too large to diff
- liquid-containers/src/Utils/Containers/Internal/StrictPair.hs too large to diff
- liquid-ghc-prim/LICENSE too large to diff
- liquid-ghc-prim/Setup.hs too large to diff
- liquid-ghc-prim/liquid-ghc-prim.cabal too large to diff
- liquid-ghc-prim/src/GHC/CString.hs too large to diff
- liquid-ghc-prim/src/GHC/CString.spec too large to diff
- liquid-ghc-prim/src/GHC/Classes.hs too large to diff
- liquid-ghc-prim/src/GHC/Classes.spec too large to diff
- liquid-ghc-prim/src/GHC/Debug.hs too large to diff
- liquid-ghc-prim/src/GHC/IntWord64.hs too large to diff
- liquid-ghc-prim/src/GHC/Magic.hs too large to diff
- liquid-ghc-prim/src/GHC/Prim.hs too large to diff
- liquid-ghc-prim/src/GHC/Prim/Ext.hs too large to diff
- liquid-ghc-prim/src/GHC/PrimopWrappers.hs too large to diff
- liquid-ghc-prim/src/GHC/Tuple.hs too large to diff
- liquid-ghc-prim/src/GHC/Types.hs too large to diff
- liquid-ghc-prim/src/GHC/Types.spec too large to diff
- liquid-parallel/LICENSE too large to diff
- liquid-parallel/Setup.hs too large to diff
- liquid-parallel/liquid-parallel.cabal too large to diff
- liquid-parallel/src/Control/Parallel.hs too large to diff
- liquid-parallel/src/Control/Parallel/Strategies.hs too large to diff
- liquid-parallel/src/Control/Parallel/Strategies.spec too large to diff
- liquid-parallel/src/Control/Seq.hs too large to diff
- liquid-platform/LICENSE too large to diff
- liquid-platform/liquid-platform.cabal too large to diff
- liquid-platform/src/Gradual.hs too large to diff
- liquid-platform/src/Liquid.hs too large to diff
- liquid-platform/src/Target.hs too large to diff
- liquid-prelude/LICENSE too large to diff
- liquid-prelude/Setup.hs too large to diff
- liquid-prelude/liquid-prelude.cabal too large to diff
- liquid-prelude/src/KMeansHelper.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/Bag.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/Equational.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/Foreign.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/List.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/Prelude.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/ProofCombinators.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/RTick.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/RTick/Combinators.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/String.hs too large to diff
- liquid-prelude/src/Language/Haskell/Liquid/Synthesize/Error.hs too large to diff
- liquid-vector/LICENSE too large to diff
- liquid-vector/Setup.hs too large to diff
- liquid-vector/liquid-vector.cabal too large to diff
- liquid-vector/src/Data/Vector.hs too large to diff
- liquid-vector/src/Data/Vector.spec too large to diff
- liquid-vector/src/Data/Vector/Fusion/Bundle.hs too large to diff
- liquid-vector/src/Data/Vector/Fusion/Bundle/Monadic.hs too large to diff
- liquid-vector/src/Data/Vector/Fusion/Bundle/Size.hs too large to diff
- liquid-vector/src/Data/Vector/Fusion/Stream/Monadic.hs too large to diff
- liquid-vector/src/Data/Vector/Fusion/Util.hs too large to diff
- liquid-vector/src/Data/Vector/Generic.hs too large to diff
- liquid-vector/src/Data/Vector/Generic/Base.hs too large to diff
- liquid-vector/src/Data/Vector/Generic/Mutable.hs too large to diff
- liquid-vector/src/Data/Vector/Generic/Mutable/Base.hs too large to diff
- liquid-vector/src/Data/Vector/Generic/New.hs too large to diff
- liquid-vector/src/Data/Vector/Internal/Check.hs too large to diff
- liquid-vector/src/Data/Vector/Mutable.hs too large to diff
- liquid-vector/src/Data/Vector/Primitive.hs too large to diff
- liquid-vector/src/Data/Vector/Primitive/Mutable.hs too large to diff
- liquid-vector/src/Data/Vector/Storable.hs too large to diff
- liquid-vector/src/Data/Vector/Storable/Internal.hs too large to diff
- liquid-vector/src/Data/Vector/Storable/Mutable.hs too large to diff
- liquid-vector/src/Data/Vector/Unboxed.hs too large to diff
- liquid-vector/src/Data/Vector/Unboxed/Base.hs too large to diff
- liquid-vector/src/Data/Vector/Unboxed/Mutable.hs too large to diff
- liquidhaskell.cabal too large to diff
- nixpkgs.nix too large to diff
- resources/icon.png too large to diff
- resources/icon.svg too large to diff
- resources/logo.png too large to diff
- resources/logo.svg too large to diff
- scripts/CountBinders.hs too large to diff
- scripts/dump_ghc_environment too large to diff
- scripts/generate_testing_ghc_env too large to diff
- scripts/haskell_count too large to diff
- scripts/head.hackage.sh too large to diff
- scripts/metrics.py too large to diff
- scripts/performance/cleanup.bash too large to diff
- scripts/performance/generate.bash too large to diff
- scripts/performance/initialize.bash too large to diff
- scripts/plot-benchmarks/README.md too large to diff
- scripts/plot-benchmarks/Setup.hs too large to diff
- scripts/plot-benchmarks/plot-benchmarks.cabal too large to diff
- scripts/plot-benchmarks/src/Benchmark.hs too large to diff
- scripts/plot-benchmarks/src/Config.hs too large to diff
- scripts/plot-benchmarks/src/Main.hs too large to diff
- scripts/plot-benchmarks/src/Parse.hs too large to diff
- scripts/plot-benchmarks/src/Plot.hs too large to diff
- scripts/plot-benchmarks/stack.yaml too large to diff
- scripts/plot-performance/README.md too large to diff
- scripts/plot-performance/chart_perf.sh too large to diff
- scripts/plot-performance/perf.gnuplot too large to diff
- scripts/release_to_hackage.sh too large to diff
- scripts/test/test_810.sh too large to diff
- scripts/test/test_810_legacy.sh too large to diff
- scripts/test/test_810_plugin.sh too large to diff
- scripts/test/test_865.sh too large to diff
- scripts/test/test_884.sh too large to diff
- scripts/test/test_901_plugin.sh too large to diff
- scripts/travis too large to diff
- shell-stack.nix too large to diff
- shell.nix too large to diff
- src/LHi.hs too large to diff
- src/Language/Haskell/Liquid/GHC.hs too large to diff
- src/Language/Haskell/Liquid/Types/Annotations.hs too large to diff
- src/Language/Haskell/Liquid/UX/Server.hs too large to diff
- stack.yaml too large to diff
- stack.yaml.lock too large to diff
- syntax/hsannot.css too large to diff
- syntax/hscolour.css too large to diff
- syntax/liquidBody.css too large to diff
- syntax/liquid_dark_blog.css too large to diff
- syntax/liquid_light_blog.css too large to diff
- tests-by-syntax.md too large to diff
- tests/DependentHaskell/todo/ClassKind.hs too large to diff
- tests/DependentHaskell/todo/LF326.hs too large to diff
- tests/DependentHaskell/todo/TypeFamilies.hs too large to diff
- tests/RankNTypes/pos/Test.hs too large to diff
- tests/RankNTypes/pos/Test0.hs too large to diff
- tests/RankNTypes/pos/Test00.hs too large to diff
- tests/TestCommits.hs too large to diff
- tests/absref/neg/FlipArgs.hs too large to diff
- tests/absref/neg/ListISort-LType.hs too large to diff
- tests/absref/neg/ListISort.hs too large to diff
- tests/absref/neg/ListQSort.hs too large to diff
- tests/absref/neg/deppair0.hs too large to diff
- tests/absref/neg/deptup0.hs too large to diff
- tests/absref/neg/deptupW.hs too large to diff
- tests/absref/pos/AbsRef00.hs too large to diff
- tests/absref/pos/FlipArgs.hs too large to diff
- tests/absref/pos/ListISort-LType.hs too large to diff
- tests/absref/pos/ListISort.hs too large to diff
- tests/absref/pos/ListQSort.hs too large to diff
- tests/absref/pos/Papp00.hs too large to diff
- tests/absref/pos/VectorLoop.hs too large to diff
- tests/absref/pos/deppair0.hs too large to diff
- tests/absref/pos/deppair2.hs too large to diff
- tests/absref/pos/deptup0.hs too large to diff
- tests/absref/pos/deptupW.hs too large to diff
- tests/absref/pos/state00.hs too large to diff
- tests/basic/neg/Inc04.hs too large to diff
- tests/basic/neg/Inc04Lib.hs too large to diff
- tests/basic/neg/List00.hs too large to diff
- tests/basic/neg/T1459.hs too large to diff
- tests/basic/neg/inc01.hs too large to diff
- tests/basic/neg/inc01q.hs too large to diff
- tests/basic/neg/inc02.hs too large to diff
- tests/basic/neg/inc03.hs too large to diff
- tests/basic/neg/poly00.hs too large to diff
- tests/basic/pos/Float.hs too large to diff
- tests/basic/pos/Inc03Lib.hs too large to diff
- tests/basic/pos/List00.hs too large to diff
- tests/basic/pos/SkipDerived00.hs too large to diff
- tests/basic/pos/alias00.hs too large to diff
- tests/basic/pos/alias01.hs too large to diff
- tests/basic/pos/alias02.hs too large to diff
- tests/basic/pos/alias03.hs too large to diff
- tests/basic/pos/alias04.hs too large to diff
- tests/basic/pos/alias05.hs too large to diff
- tests/basic/pos/inc00.hs too large to diff
- tests/basic/pos/inc01.hs too large to diff
- tests/basic/pos/inc01q.hs too large to diff
- tests/basic/pos/inc02.hs too large to diff
- tests/basic/pos/inc03.hs too large to diff
- tests/basic/pos/inc04.hs too large to diff
- tests/basic/pos/infer00.hs too large to diff
- tests/basic/pos/poly00.hs too large to diff
- tests/classes/neg/Class00.hs too large to diff
- tests/classes/neg/Class01.hs too large to diff
- tests/classes/neg/Inst00.hs too large to diff
- tests/classes/neg/RealProps0.hs too large to diff
- tests/classes/pos/Class00.hs too large to diff
- tests/classes/pos/HiddenMethod00.hs too large to diff
- tests/classes/pos/Inst00.hs too large to diff
- tests/classes/pos/RealProps0.hs too large to diff
- tests/classes/pos/RealProps1.hs too large to diff
- tests/classes/pos/STMonad.hs too large to diff
- tests/classes/pos/TypeEquality00.hs too large to diff
- tests/classes/pos/TypeEquality01.hs too large to diff
- tests/datacon/neg/AdtPeano2.hs too large to diff
- tests/datacon/neg/Data00.hs too large to diff
- tests/datacon/neg/Data00Lib.hs too large to diff
- tests/datacon/neg/Data01.hs too large to diff
- tests/datacon/neg/Data02.hs too large to diff
- tests/datacon/neg/Data02Lib.hs too large to diff
- tests/datacon/neg/Date.hs too large to diff
- tests/datacon/neg/NewTypes.hs too large to diff
- tests/datacon/neg/NewTypes0.hs too large to diff
- tests/datacon/pos/AdtPeano2.hs too large to diff
- tests/datacon/pos/Data00.hs too large to diff
- tests/datacon/pos/Data00Lib.hs too large to diff
- tests/datacon/pos/Data01.hs too large to diff
- tests/datacon/pos/Data02.hs too large to diff
- tests/datacon/pos/Data02Lib.hs too large to diff
- tests/datacon/pos/Date.hs too large to diff
- tests/datacon/pos/NewType.hs too large to diff
- tests/datacon/pos/T1446.hs too large to diff
- tests/datacon/pos/T1473A.hs too large to diff
- tests/datacon/pos/T1473B.hs too large to diff
- tests/datacon/pos/T1476.hs too large to diff
- tests/datacon/pos/T1477.hs too large to diff
- tests/datacon/pos/T1777.hs too large to diff
- tests/golden/json_output.golden too large to diff
- tests/golden/json_output.hs too large to diff
- tests/gradual/neg/Gradual.hs too large to diff
- tests/gradual/neg/Interpretations.hs too large to diff
- tests/gradual/neg/Intro.hs too large to diff
- tests/gradual/pos/Discussion.hs too large to diff
- tests/gradual/pos/Dynamic.hs too large to diff
- tests/gradual/pos/Gradual.hs too large to diff
- tests/gradual/pos/Interpretations.hs too large to diff
- tests/gradual/pos/Intro.hs too large to diff
- tests/gradual/todo/Measures.hs too large to diff
- tests/implicit/neg/Implicit1.hs too large to diff
- tests/implicit/pos/Implicit1.hs too large to diff
- tests/implicit/pos/Implicit3.hs too large to diff
- tests/implicit/pos/ImplicitDouble.hs too large to diff
- tests/implicit/pos/ImplicitTrivial.hs too large to diff
- tests/import/deps/A.hs too large to diff
- tests/import/deps/B.hs too large to diff
- tests/import/deps/C.hs too large to diff
- tests/import/deps/D.hs too large to diff
- tests/log/summary-develop.csv too large to diff
- tests/log/summary-map_fusion.csv too large to diff
- tests/logs/borscht-2015-06-09T20-35-28/summary.csv too large to diff
- tests/logs/borscht-2015-07-23T20-12-37/summary.csv too large to diff
- tests/logs/compare-PLE.csv too large to diff
- tests/logs/compare-develop-gradual.csv too large to diff
- tests/logs/defunctionalized.csv too large to diff
- tests/logs/f4764fa7e9b3992c80c4d9f73cbfbcaea4c16071-all-import.csv too large to diff
- tests/logs/f4764fa7e9b3992c80c4d9f73cbfbcaea4c16071-no-import.csv too large to diff
- tests/logs/f4764fa7e9b3992c80c4d9f73cbfbcaea4c16071-used-import.csv too large to diff
- tests/logs/gradual-with-bools.csv too large to diff
- tests/logs/gradual.csv too large to diff
- tests/logs/regrtest_results_goto_Fri_Feb__8_2013_POST_SPLITFIX_HUGHESPJ too large to diff
- tests/logs/regrtest_results_goto_Fri_Sep_21_171954_2012 too large to diff
- tests/logs/regrtest_results_goto_Mon_Feb__4_082521_2013 too large to diff
- tests/logs/regrtest_results_goto_Mon_Jul_14_master too large to diff
- tests/logs/regrtest_results_goto_Mon_Jul_14_post_parseparens too large to diff
- tests/logs/regrtest_results_goto_Mon_Oct_22_154504_2012 too large to diff
- tests/logs/regrtest_results_goto_Mon_Oct_22_205256_2012 too large to diff
- tests/logs/regrtest_results_goto_Sat_Feb_23_183819_2013 too large to diff
- tests/logs/regrtest_results_goto_Sun_Jan_13_171109_2013 too large to diff
- tests/logs/regrtest_results_goto_Sun_Jul_13_221212_2014_post_errormsg_parseparens too large to diff
- tests/logs/regrtest_results_goto_Sun_Oct_28_172434_2012 too large to diff
- tests/logs/regrtest_results_goto_Thu_Nov_21_2013-lazyinst too large to diff
- tests/logs/regrtest_results_goto_Thu_Nov_21_2013-master too large to diff
- tests/logs/regrtest_results_goto_Tue_Jul_15-post-parseparens-and-errormsg-improved too large to diff
- tests/logs/regrtest_results_goto_Wed_Nov_20_152850_2013-master too large to diff
- tests/logs/regrtest_results_goto_post_qualshrink_Mon_Jul_22_2013 too large to diff
- tests/logs/regrtest_results_goto_smtlib1_Thu_Jul_18_2013 too large to diff
- tests/logs/regrtest_results_goto_z3mem_Thu_Jul_18_2013 too large to diff
- tests/logs/regrtest_results_goto_z3mem_Thu_Jul_18_new_2013 too large to diff
- tests/logs/regrtest_results_nikiL_Fri_Mar_29_125637_2013 too large to diff
- tests/logs/regrtest_results_ubuntu_Fri_Jul_29_173855_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Mon_Dec__5_033239_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Sun_Sep_11_155257_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Sun_Sep_11_193855_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Sun_Sep_11_201206_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Thu_Dec_22_025146_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Tue_Jul_19_100718_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_031145_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_031429_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_164526_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_180931_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_184219_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_191326_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Dec_21_191410_2011 too large to diff
- tests/logs/regrtest_results_ubuntu_Wed_Sep__7_144519_2011 too large to diff
- tests/logs/slowdown.csv too large to diff
- tests/logs/summary-develop-for-gradual.csv too large to diff
- tests/logs/summary-develop.csv too large to diff
- tests/logs/summary-first-ghc8.csv too large to diff
- tests/logs/summary-fix-inst-borscht-9-27-2015.csv too large to diff
- tests/logs/summary-last-ghc7.csv too large to diff
- tests/logs/summary-master-borscht-9-27-2015.csv too large to diff
- tests/logs/summary-new.csv too large to diff
- tests/logs/summary-old-dev.csv too large to diff
- tests/logs/summary-old-develop.csv too large to diff
- tests/logs/summary-pAnd.csv too large to diff
- tests/logs/summary-ple.csv too large to diff
- tests/logs/summary-symbol-borscht-10-08-2015.csv too large to diff
- tests/logs/summary-symbol-intern-borscht-10-08-2015.csv too large to diff
- tests/logs/typeclasses-analysis/analysis.R too large to diff
- tests/logs/typeclasses-analysis/compare-typeclass.csv too large to diff
- tests/logs/typeclasses-analysis/summary_dev.csv too large to diff
- tests/logs/typeclasses-analysis/summary_typeclasses.csv too large to diff
- tests/measure/neg/GList00Lib.hs too large to diff
- tests/measure/neg/Len00.hs too large to diff
- tests/measure/neg/Len01.hs too large to diff
- tests/measure/neg/List00.hs too large to diff
- tests/measure/neg/List01.hs too large to diff
- tests/measure/neg/List02.hs too large to diff
- tests/measure/neg/Ple1Lib.hs too large to diff
- tests/measure/neg/Using00.hs too large to diff
- tests/measure/neg/bag.hs too large to diff
- tests/measure/neg/fst00.hs too large to diff
- tests/measure/neg/fst01.hs too large to diff
- tests/measure/neg/fst02.hs too large to diff
- tests/measure/neg/ple0.hs too large to diff
- tests/measure/neg/ple1.hs too large to diff
- tests/measure/pos/AbsMeasure.hs too large to diff
- tests/measure/pos/ExactFunApp.hs too large to diff
- tests/measure/pos/GList000.hs too large to diff
- tests/measure/pos/GList00Lib.hs too large to diff
- tests/measure/pos/HiddenData.hs too large to diff
- tests/measure/pos/HiddenDataLib.hs too large to diff
- tests/measure/pos/Len00.hs too large to diff
- tests/measure/pos/Len01.hs too large to diff
- tests/measure/pos/Len02.hs too large to diff
- tests/measure/pos/List00.hs too large to diff
- tests/measure/pos/List00Lib.hs too large to diff
- tests/measure/pos/List01.hs too large to diff
- tests/measure/pos/List02.hs too large to diff
- tests/measure/pos/List02Lib.hs too large to diff
- tests/measure/pos/Ple1Lib.hs too large to diff
- tests/measure/pos/PruneHO.hs too large to diff
- tests/measure/pos/RecordAccessors.hs too large to diff
- tests/measure/pos/Using00.hs too large to diff
- tests/measure/pos/bag.hs too large to diff
- tests/measure/pos/fst00.hs too large to diff
- tests/measure/pos/fst01.hs too large to diff
- tests/measure/pos/fst02.hs too large to diff
- tests/measure/pos/ple00.hs too large to diff
- tests/measure/pos/ple01.hs too large to diff
- tests/measure/pos/ple1.hs too large to diff
- tests/names/neg/Assume00.hs too large to diff
- tests/names/neg/Capture01.hs too large to diff
- tests/names/neg/Set00.hs too large to diff
- tests/names/neg/Set01.hs too large to diff
- tests/names/neg/Set02.hs too large to diff
- tests/names/neg/T1078.hs too large to diff
- tests/names/neg/local00.hs too large to diff
- tests/names/neg/vector0.hs too large to diff
- tests/names/neg/vector1.hs too large to diff
- tests/names/pos/Alias00.hs too large to diff
- tests/names/pos/Assume00.hs too large to diff
- tests/names/pos/Assume01.hs too large to diff
- tests/names/pos/BasicLambdas00.hs too large to diff
- tests/names/pos/BasicLambdas01.hs too large to diff
- tests/names/pos/Capture01.hs too large to diff
- tests/names/pos/Capture02.hs too large to diff
- tests/names/pos/ClojurVector.hs too large to diff
- tests/names/pos/HideName00.hs too large to diff
- tests/names/pos/HidePrelude.hs too large to diff
- tests/names/pos/List00.hs too large to diff
- tests/names/pos/LocalSpec.hs too large to diff
- tests/names/pos/Ord.hs too large to diff
- tests/names/pos/Set00.hs too large to diff
- tests/names/pos/Set01.hs too large to diff
- tests/names/pos/Set02.hs too large to diff
- tests/names/pos/Shadow00.hs too large to diff
- tests/names/pos/Shadow01.hs too large to diff
- tests/names/pos/T1521.hs too large to diff
- tests/names/pos/T675.hs too large to diff
- tests/names/pos/Uniques.hs too large to diff
- tests/names/pos/local00.hs too large to diff
- tests/names/pos/local01.hs too large to diff
- tests/names/pos/local02.hs too large to diff
- tests/names/pos/local03.hs too large to diff
- tests/names/pos/vector0.hs too large to diff
- tests/names/pos/vector04.hs too large to diff
- tests/names/pos/vector1.hs too large to diff
- tests/neg/ListRange.dat too large to diff
- tests/neg/Sumk.hquals too large to diff
- tests/parser/pos/NestedTuples.hs too large to diff
- tests/parser/pos/Parens.hs too large to diff
- tests/parser/pos/ReflectedInfix.hs too large to diff
- tests/parser/pos/T1012.hs too large to diff
- tests/parser/pos/T1481.hs too large to diff
- tests/parser/pos/T1531.hs too large to diff
- tests/parser/pos/T338.hs too large to diff
- tests/parser/pos/T871.hs too large to diff
- tests/parser/pos/T873.hs too large to diff
- tests/parser/pos/T884.hs too large to diff
- tests/parser/pos/T892.hs too large to diff
- tests/parser/pos/TokensAsPrefixes.hs too large to diff
- tests/parser/pos/Tuples.hs too large to diff
- tests/pattern/pos/ANF.hs too large to diff
- tests/pattern/pos/Invariants.hs too large to diff
- tests/pattern/pos/MultipleInvariants.hs too large to diff
- tests/pattern/pos/Return00.hs too large to diff
- tests/pattern/pos/Return01.hs too large to diff
- tests/pattern/pos/ReturnStrata00.hs too large to diff
- tests/pattern/pos/TemplateHaskell.hs too large to diff
- tests/pattern/pos/TemplateHaskellLib.hs too large to diff
- tests/pattern/pos/contra0.hs too large to diff
- tests/pattern/pos/monad0.hs too large to diff
- tests/pattern/pos/monad1.hs too large to diff
- tests/pattern/pos/monad7.hs too large to diff
- tests/ple/neg/BinahQuery.hs too large to diff
- tests/ple/neg/BinahUpdate.hs too large to diff
- tests/ple/neg/BinahUpdateClient.hs too large to diff
- tests/ple/neg/BinahUpdateLib.hs too large to diff
- tests/ple/neg/BinahUpdateLib1.hs too large to diff
- tests/ple/neg/ExactGADT5.hs too large to diff
- tests/ple/neg/ReflectDefault.hs too large to diff
- tests/ple/neg/T1173.hs too large to diff
- tests/ple/neg/T1192.hs too large to diff
- tests/ple/neg/T1289.hs too large to diff
- tests/ple/neg/T1371_Tick.hs too large to diff
- tests/ple/neg/T1409.hs too large to diff
- tests/ple/neg/T1424.hs too large to diff
- tests/ple/neg/ple0.hs too large to diff
- tests/ple/neg/ple_sum.hs too large to diff
- tests/ple/pos/BinahQuery.hs too large to diff
- tests/ple/pos/BinahUpdate.hs too large to diff
- tests/ple/pos/Compiler.hs too large to diff
- tests/ple/pos/ExactGADT4.hs too large to diff
- tests/ple/pos/ExactGADT5.hs too large to diff
- tests/ple/pos/ExactGADT7.hs too large to diff
- tests/ple/pos/Fulcrum.hs too large to diff
- tests/ple/pos/IndLast.hs too large to diff
- tests/ple/pos/IndPal0.hs too large to diff
- tests/ple/pos/IndPal00.hs too large to diff
- tests/ple/pos/IndPalindrome.hs too large to diff
- tests/ple/pos/IndPerm.hs too large to diff
- tests/ple/pos/IndStar.hs too large to diff
- tests/ple/pos/IndStarHole.hs too large to diff
- tests/ple/pos/ListAnd.hs too large to diff
- tests/ple/pos/Lists.hs too large to diff
- tests/ple/pos/MJFix.hs too large to diff
- tests/ple/pos/MossakaBug.hs too large to diff
- tests/ple/pos/NNFPiotr.hs too large to diff
- tests/ple/pos/NegNormalForm.hs too large to diff
- tests/ple/pos/ReflectDefault.hs too large to diff
- tests/ple/pos/RegexpDerivative.hs too large to diff
- tests/ple/pos/RosePLEDiv.hs too large to diff
- tests/ple/pos/STLC0.hs too large to diff
- tests/ple/pos/STLC1.hs too large to diff
- tests/ple/pos/STLC2.hs too large to diff
- tests/ple/pos/STLCB0.hs too large to diff
- tests/ple/pos/STLCB1.hs too large to diff
- tests/ple/pos/StlcBug.hs too large to diff
- tests/ple/pos/T1173.hs too large to diff
- tests/ple/pos/T1190.hs too large to diff
- tests/ple/pos/T1257.hs too large to diff
- tests/ple/pos/T1289.hs too large to diff
- tests/ple/pos/T1302b.hs too large to diff
- tests/ple/pos/T1371.hs too large to diff
- tests/ple/pos/T1371_NNF.hs too large to diff
- tests/ple/pos/T1382.hs too large to diff
- tests/ple/pos/T1409.hs too large to diff
- tests/ple/pos/T1424.hs too large to diff
- tests/ple/pos/T1424A.hs too large to diff
- tests/ple/pos/filterPLE.hs too large to diff
- tests/ple/pos/padLeft.hs too large to diff
- tests/ple/pos/ple0.hs too large to diff
- tests/ple/pos/pleORM.hs too large to diff
- tests/ple/pos/ple_sum.hs too large to diff
- tests/ple/pos/tmp.hs too large to diff
- tests/ple/pos/tmp1.hs too large to diff
- tests/pos/Deptup1.pred too large to diff
- tests/pos/T1045.hs-boot too large to diff
- tests/refined-classes/semigroup.hs too large to diff
- tests/refined-classes/semigroup_desugared.hs too large to diff
- tests/refined-classes/semigroup_unsound.hs too large to diff
- tests/reflect/neg/DoubleLit.hs too large to diff
- tests/reflect/neg/ReflString0.hs too large to diff
- tests/reflect/neg/ReflString1.hs too large to diff
- tests/reflect/pos/DoubleLit.hs too large to diff
- tests/reflect/pos/ReflString0.hs too large to diff
- tests/reflect/pos/ReflString1.hs too large to diff
- tests/spec/neg/Compose1.hs too large to diff
- tests/spec/pos/BS1.hs too large to diff
- tests/spec/pos/Compose.hs too large to diff
- tests/spec/pos/Compose1.hs too large to diff
- tests/specfiles/pos/Empty.spec too large to diff
- tests/specfiles/pos/T707.spec too large to diff
- tests/specfiles/pos/T788.spec too large to diff
- tests/specfiles/pos/T924.spec too large to diff
- tests/strings/neg/StringIndexingStep1.hs too large to diff
- tests/strings/pos/DivideAndQunquer.hs too large to diff
- tests/strings/pos/Proves.hs too large to diff
- tests/strings/pos/String.hs too large to diff
- tests/strings/pos/StringIndexing.hs too large to diff
- tests/strings/pos/StringIndexingStep1.hs too large to diff
- tests/strings/pos/StringIndexingStep2.hs too large to diff
- tests/strings/pos/StringIndexingStep3.hs too large to diff
- tests/strings/todo/Boyer_Moore.hs too large to diff
- tests/strings/todo/StringIndexing.hs too large to diff
- tests/synthesis/TODO/ListConcat.hs too large to diff
- tests/synthesis/TODO/ListToBST.hs too large to diff
- tests/synthesis/TODO/TreeToList.hs too large to diff
- tests/synthesis/TODO/User.hs too large to diff
- tests/synthesis/logs/.gitkeep too large to diff
- tests/synthesis/static/Append.hs too large to diff
- tests/synthesis/static/BSTFlatten.hs too large to diff
- tests/synthesis/static/BSTSort.hs too large to diff
- tests/synthesis/static/BinHeapSingleton.hs too large to diff
- tests/synthesis/static/Data.hs too large to diff
- tests/synthesis/static/Data2.hs too large to diff
- tests/synthesis/static/Data3.hs too large to diff
- tests/synthesis/static/IntSimple.hs too large to diff
- tests/synthesis/static/ListId.hs too large to diff
- tests/synthesis/static/ListInsertSort.hs too large to diff
- tests/synthesis/static/ListNull.hs too large to diff
- tests/synthesis/static/ListZip.hs too large to diff
- tests/synthesis/static/ListZipWith.hs too large to diff
- tests/synthesis/static/NestedListSimple.hs too large to diff
- tests/synthesis/static/Stutter.hs too large to diff
- tests/synthesis/static/TreeOne.hs too large to diff
- tests/synthesis/static/TupleListSimple.hs too large to diff
- tests/synthesis/static/map.hs too large to diff
- tests/synthesis/static/single-elem-list.hs too large to diff
- tests/synthesis/tests/Append.hs too large to diff
- tests/synthesis/tests/BSTFlatten.hs too large to diff
- tests/synthesis/tests/BSTSort.hs too large to diff
- tests/synthesis/tests/BinHeapSingleton.hs too large to diff
- tests/synthesis/tests/Data.hs too large to diff
- tests/synthesis/tests/Data2.hs too large to diff
- tests/synthesis/tests/Data3.hs too large to diff
- tests/synthesis/tests/IntSimple.hs too large to diff
- tests/synthesis/tests/ListId.hs too large to diff
- tests/synthesis/tests/ListInsertSort.hs too large to diff
- tests/synthesis/tests/ListNull.hs too large to diff
- tests/synthesis/tests/ListZip.hs too large to diff
- tests/synthesis/tests/ListZipWith.hs too large to diff
- tests/synthesis/tests/NestedListSimple.hs too large to diff
- tests/synthesis/tests/Stutter.hs too large to diff
- tests/synthesis/tests/TreeOne.hs too large to diff
- tests/synthesis/tests/TupleListSimple.hs too large to diff
- tests/synthesis/tests/map.hs too large to diff
- tests/synthesis/tests/single-elem-list.hs too large to diff
- tests/terminate/neg/AutoTerm.hs too large to diff
- tests/terminate/neg/Even.hs too large to diff
- tests/terminate/neg/Rename.hs too large to diff
- tests/terminate/neg/Sum.hs too large to diff
- tests/terminate/neg/T1404.0.hs too large to diff
- tests/terminate/neg/T1404.1.hs too large to diff
- tests/terminate/neg/T1404.2.hs too large to diff
- tests/terminate/neg/T1404.3.hs too large to diff
- tests/terminate/neg/T745.hs too large to diff
- tests/terminate/neg/qsloop.hs too large to diff
- tests/terminate/neg/term00.hs too large to diff
- tests/terminate/neg/testRec.hs too large to diff
- tests/terminate/neg/total00.hs too large to diff
- tests/terminate/neg/total01.hs too large to diff
- tests/terminate/neg/total02.hs too large to diff
- tests/terminate/pos/Ackermann.hs too large to diff
- tests/terminate/pos/AutoTerm.hs too large to diff
- tests/terminate/pos/Lexicographic.hs too large to diff
- tests/terminate/pos/LocalTermExpr.hs too large to diff
- tests/terminate/pos/StructSecondArg.hs too large to diff
- tests/terminate/pos/Sum.hs too large to diff
- tests/terminate/pos/T1245.hs too large to diff
- tests/terminate/pos/T1396.0.hs too large to diff
- tests/terminate/pos/T1396.1.hs too large to diff
- tests/terminate/pos/T1403.hs too large to diff
- tests/terminate/pos/list00-local.hs too large to diff
- tests/terminate/pos/list00-str.hs too large to diff
- tests/terminate/pos/list00.hs too large to diff
- tests/terminate/pos/list01.hs too large to diff
- tests/terminate/pos/list02.hs too large to diff
- tests/terminate/pos/list03.hs too large to diff
- tests/terminate/pos/list04-local.hs too large to diff
- tests/terminate/pos/list04.hs too large to diff
- tests/terminate/pos/list05-local.hs too large to diff
- tests/terminate/pos/term00.hs too large to diff
- tests/tmp/Class2.hs too large to diff
- tests/tmp/Class3.hs too large to diff
- tests/tmp/LiquidR.hs too large to diff
- tests/tmp/LiquidR2.hs too large to diff
- tests/tmp/Mode.hs too large to diff
- tests/tmp/T776.hs too large to diff
- tests/tmp/T777.hs too large to diff
- tests/todo-rebare/DataKinds.hs too large to diff
- tests/todo-rebare/Inst01_UNSAFE.hs too large to diff
- tests/todo-rebare/NatClass.hs too large to diff
- tests/todo-rebare/Strata.hs too large to diff
- tests/todo-rebare/T1089b.hs too large to diff
- tests/todo-rebare/VerifiedMonoid_NEG.hs too large to diff
- tests/todo-rebare/VerifiedMonoid_POS.hs too large to diff
- tests/todo/12-case-study-AVL.lhs too large to diff
- tests/todo/2013-01-10-measuring-lists-I.lhs too large to diff
- tests/todo/AA.hs too large to diff
- tests/todo/AVLTree.hs too large to diff
- tests/todo/AbsRef.hs too large to diff
- tests/todo/AbsRefNameClash.hs too large to diff
- tests/todo/Adt0.hs too large to diff
- tests/todo/AdtBin.hs too large to diff
- tests/todo/Aliases.hs too large to diff
- tests/todo/AmortizedQueue.hs too large to diff
- tests/todo/Append.hs too large to diff
- tests/todo/Append0.hs too large to diff
- tests/todo/ApplicativeMaybe0.hs too large to diff
- tests/todo/ApplicativeMaybe1.hs too large to diff
- tests/todo/Ast.hs too large to diff
- tests/todo/AxiomBug.hs too large to diff
- tests/todo/Axiomatize.hs too large to diff
- tests/todo/BadArguments.hs too large to diff
- tests/todo/Box.hs too large to diff
- tests/todo/Braun.hs too large to diff
- tests/todo/CatMaybes.hs too large to diff
- tests/todo/CheckProofs.hs too large to diff
- tests/todo/Class1.hs too large to diff
- tests/todo/Class2.hs too large to diff
- tests/todo/Class3.hs too large to diff
- tests/todo/Class4.hs too large to diff
- tests/todo/Class4Import.hs too large to diff
- tests/todo/ClassMeasureBAD.hs too large to diff
- tests/todo/ClassMeasureIdeal.hs too large to diff
- tests/todo/ClassMeasureOK.hs too large to diff
- tests/todo/ClassReflect.hs too large to diff
- tests/todo/CmpBug.hs too large to diff
- tests/todo/CountMonadMap.hs too large to diff
- tests/todo/DB0.hs too large to diff
- tests/todo/DBMovies0.hs too large to diff
- tests/todo/DerivingRead.hs too large to diff
- tests/todo/DiffCheck.hs too large to diff
- tests/todo/Eff0.hs too large to diff
- tests/todo/Eff1.hs too large to diff
- tests/todo/Eff2.hs too large to diff
- tests/todo/EffSTT.hs too large to diff
- tests/todo/Ensure.hs too large to diff
- tests/todo/EnumFromTo.hs too large to diff
- tests/todo/Equational.hs too large to diff
- tests/todo/ExactGADT3.hs too large to diff
- tests/todo/ExactGADT5.hs too large to diff
- tests/todo/ExactGADT6.hs too large to diff
- tests/todo/FixCrash.hs too large to diff
- tests/todo/FldBug.hs too large to diff
- tests/todo/GhcListSort.hs too large to diff
- tests/todo/ImportBound.hs too large to diff
- tests/todo/ImportReflected.hs too large to diff
- tests/todo/ImportedNumericInstances.hs too large to diff
- tests/todo/Incr.hs too large to diff
- tests/todo/InfiniteLists.hs too large to diff
- tests/todo/InfixClient.hs too large to diff
- tests/todo/InfixLib.hs too large to diff
- tests/todo/InlineMeasure.hs too large to diff
- tests/todo/IntInvariants.hs too large to diff
- tests/todo/Interpreter.hs too large to diff
- tests/todo/Intervals.hs too large to diff
- tests/todo/InvBug.hs too large to diff
- tests/todo/Invariants.hs too large to diff
- tests/todo/Invariants1.hs too large to diff
- tests/todo/Invariants2.hs too large to diff
- tests/todo/InvariantsTermination.hs too large to diff
- tests/todo/LambdaDeBruijn.hs too large to diff
- tests/todo/LambdaDeBruijn0.hs too large to diff
- tests/todo/LazyVar.hs too large to diff
- tests/todo/LetRecStack.hs too large to diff
- tests/todo/ListDataCons-Neg.hs too large to diff
- tests/todo/ListDataCons-Pos.hs too large to diff
- tests/todo/ListDataCons.hs too large to diff
- tests/todo/ListMem.hs too large to diff
- tests/todo/LocalRecursiveFuns.hs too large to diff
- tests/todo/LocalSpec.hs too large to diff
- tests/todo/LocalSpec1.hs too large to diff
- tests/todo/LocalSpecImport.hs too large to diff
- tests/todo/LocalSpecTyVar.hs too large to diff
- tests/todo/LocalTermExpr1.hs too large to diff
- tests/todo/Machine.hs too large to diff
- tests/todo/Map-strict.hs too large to diff
- tests/todo/Map-wierd.hs too large to diff
- tests/todo/MaybeReflect0.hs too large to diff
- tests/todo/MaybeReflect1.hs too large to diff
- tests/todo/Means.hs too large to diff
- tests/todo/Measure.hs too large to diff
- tests/todo/MeasureImport.hs too large to diff
- tests/todo/MissingAbsRefArgs.hs too large to diff
- tests/todo/NameClash.hs too large to diff
- tests/todo/NativeFixCrash.hs too large to diff
- tests/todo/NeuralNetwork.hs too large to diff
- tests/todo/NewType00.hs too large to diff
- tests/todo/NoInlines.hs too large to diff
- tests/todo/NoInstance.hs too large to diff
- tests/todo/NotesOnProductivityTest.hs too large to diff
- tests/todo/Parse.hs too large to diff
- tests/todo/Parse1.hs too large to diff
- tests/todo/PartialAbsApplication.hs too large to diff
- tests/todo/Plus.hs too large to diff
- tests/todo/QualifCheck.hs too large to diff
- tests/todo/RG.hs too large to diff
- tests/todo/Recursion.hs too large to diff
- tests/todo/Recursion1.hs too large to diff
- tests/todo/RedBlack.hs too large to diff
- tests/todo/RefinedData.hs too large to diff
- tests/todo/RefinedEquality.hs too large to diff
- tests/todo/ReflImp.hs too large to diff
- tests/todo/RegexpDerivative.hs too large to diff
- tests/todo/SMTDiverge.hs too large to diff
- tests/todo/SS.hs too large to diff
- tests/todo/SYB_Literals.hs too large to diff
- tests/todo/SearchTree.hs too large to diff
- tests/todo/SelfRefPredicates.hs too large to diff
- tests/todo/Signal.hs too large to diff
- tests/todo/SortedLists.lhs too large to diff
- tests/todo/StateConstraints.hs too large to diff
- tests/todo/Strings.hs too large to diff
- tests/todo/SubType.hs too large to diff
- tests/todo/SuperClassBounds.hs too large to diff
- tests/todo/T1037A.hs too large to diff
- tests/todo/T1037B.hs too large to diff
- tests/todo/T1037C.hs too large to diff
- tests/todo/T1089.hs too large to diff
- tests/todo/T1094_Lib.hs too large to diff
- tests/todo/T1109.hs too large to diff
- tests/todo/T1189.hs too large to diff
- tests/todo/T1278.1.hs too large to diff
- tests/todo/T1326A.hs too large to diff
- tests/todo/T1326B.hs too large to diff
- tests/todo/T1326C.hs too large to diff
- tests/todo/T1481.hs too large to diff
- tests/todo/T1549.hs too large to diff
- tests/todo/T1551.hs too large to diff
- tests/todo/T1555.hs too large to diff
- tests/todo/T1649.hs too large to diff
- tests/todo/T658.hs too large to diff
- tests/todo/T765.hs too large to diff
- tests/todo/T770.hs too large to diff
- tests/todo/T771.hs too large to diff
- tests/todo/T772.hs too large to diff
- tests/todo/T776.hs too large to diff
- tests/todo/T781.hs too large to diff
- tests/todo/T791.hs too large to diff
- tests/todo/T791a.hs too large to diff
- tests/todo/T870.hs too large to diff
- tests/todo/T995.hs too large to diff
- tests/todo/T996.hs too large to diff
- tests/todo/T997.hs too large to diff
- tests/todo/T997a.hs too large to diff
- tests/todo/Theorems0.hs too large to diff
- tests/todo/Times.hs too large to diff
- tests/todo/TreeMap.hs too large to diff
- tests/todo/TreeMap0.hs too large to diff
- tests/todo/TypeError.hs too large to diff
- tests/todo/TypeFun.hs too large to diff
- tests/todo/TypeSynonyms.hs too large to diff
- tests/todo/UnboundSigs.hs too large to diff
- tests/todo/UnboundVarInAssume1.hs too large to diff
- tests/todo/UnfoldDataCons.hs too large to diff
- tests/todo/Unsound.hs too large to diff
- tests/todo/UnsoundMeasure.hs too large to diff
- tests/todo/Until.hs too large to diff
- tests/todo/UseBound.hs too large to diff
- tests/todo/VerifiedNum.hs too large to diff
- tests/todo/WBL-crash.hs too large to diff
- tests/todo/When.hs too large to diff
- tests/todo/absref-crash0.hs too large to diff
- tests/todo/aliasConst.hs too large to diff
- tests/todo/aliasError.hs too large to diff
- tests/todo/appCheck.hs too large to diff
- tests/todo/apply.hs too large to diff
- tests/todo/baderror.hs too large to diff
- tests/todo/baffled.hs too large to diff
- tests/todo/binsearch.hs too large to diff
- tests/todo/boolparse.hs too large to diff
- tests/todo/cases.hs too large to diff
- tests/todo/cont.hs too large to diff
- tests/todo/contra.hs too large to diff
- tests/todo/decr.hs too large to diff
- tests/todo/doubleError.hs too large to diff
- tests/todo/dyn.hs too large to diff
- tests/todo/empty-or.hs too large to diff
- tests/todo/err0.hs too large to diff
- tests/todo/err1.hs too large to diff
- tests/todo/err10.hs too large to diff
- tests/todo/err11.hs too large to diff
- tests/todo/err12.hs too large to diff
- tests/todo/err13.hs too large to diff
- tests/todo/err2.hs too large to diff
- tests/todo/err3.hs too large to diff
- tests/todo/err4.hs too large to diff
- tests/todo/err5.hs too large to diff
- tests/todo/err6.hs too large to diff
- tests/todo/err7.hs too large to diff
- tests/todo/err8.hs too large to diff
- tests/todo/err9.hs too large to diff
- tests/todo/existsAbs.hs too large to diff
- tests/todo/false.hs too large to diff
- tests/todo/fft.hs too large to diff
- tests/todo/fio.hs too large to diff
- tests/todo/fixme.lhs too large to diff
- tests/todo/funrec.hs too large to diff
- tests/todo/gadtEval.hs too large to diff
- tests/todo/if.hs too large to diff
- tests/todo/inccheck0.hs too large to diff
- tests/todo/intP.hs too large to diff
- tests/todo/kmpMonad.hs too large to diff
- tests/todo/liftbug.hs too large to diff
- tests/todo/linspace-crash.hs too large to diff
- tests/todo/linspace.hs too large to diff
- tests/todo/list-screen.hs too large to diff
- tests/todo/lit01.hs too large to diff
- tests/todo/mapreduce.hs too large to diff
- tests/todo/maps.hs too large to diff
- tests/todo/maybe0.hs too large to diff
- tests/todo/maybe0000.hs too large to diff
- tests/todo/maybe4.hs too large to diff
- tests/todo/measbug.hs too large to diff
- tests/todo/measfield.hs too large to diff
- tests/todo/overload.hs too large to diff
- tests/todo/partialmeasureOld.hs too large to diff
- tests/todo/ptr.hs too large to diff
- tests/todo/ptr2.hs too large to diff
- tests/todo/ptr3.hs too large to diff
- tests/todo/read.hs too large to diff
- tests/todo/satsolver.hs too large to diff
- tests/todo/satsolver0.hs too large to diff
- tests/todo/splash-total.hs too large to diff
- tests/todo/splash-vector.hs too large to diff
- tests/todo/stacks1.hs too large to diff
- tests/todo/state.hs too large to diff
- tests/todo/tdb.hs too large to diff
- tests/todo/trans.lhs too large to diff
- tests/todo/tupleplus.hs too large to diff
- tests/todo/txrec0.hs too large to diff
- tests/todo/vector2.hs too large to diff
- tests/typeclasses/pos/Lemma.hs too large to diff
- tests/typeclasses/pos/Lib.hs too large to diff
- tests/typeclasses/pos/PNat.hs too large to diff
- tests/typeclasses/pos/Semigroup.hs too large to diff
- typeclass-tests/Data/All.hs too large to diff
- typeclass-tests/Data/All/Semigroup.hs too large to diff
- typeclass-tests/Data/Any.hs too large to diff
- typeclass-tests/Data/Any/Semigroup.hs too large to diff
- typeclass-tests/Data/Dual.hs too large to diff
- typeclass-tests/Data/Dual/Semigroup.hs too large to diff
- typeclass-tests/Data/Either.hs too large to diff
- typeclass-tests/Data/Either/Functor.hs too large to diff
- typeclass-tests/Data/Endo.hs too large to diff
- typeclass-tests/Data/Endo/Semigroup.hs too large to diff
- typeclass-tests/Data/Foldable/Classes.hs too large to diff
- typeclass-tests/Data/Function.hs too large to diff
- typeclass-tests/Data/Functor.hs too large to diff
- typeclass-tests/Data/Functor/Classes.hs too large to diff
- typeclass-tests/Data/Functor/Const.hs too large to diff
- typeclass-tests/Data/Functor/Const/Foldable.hs too large to diff
- typeclass-tests/Data/Functor/Const/Functor.hs too large to diff
- typeclass-tests/Data/Functor/Identity.hs too large to diff
- typeclass-tests/Data/Functor/Identity/Foldable.hs too large to diff
- typeclass-tests/Data/Functor/Identity/Functor.hs too large to diff
- typeclass-tests/Data/Functor/Identity/Semigroup.hs too large to diff
- typeclass-tests/Data/Functor/State.hs too large to diff
- typeclass-tests/Data/Functor/State/Functor.hs too large to diff
- typeclass-tests/Data/Lattice.hs too large to diff
- typeclass-tests/Data/List.hs too large to diff
- typeclass-tests/Data/List/Foldable.hs too large to diff
- typeclass-tests/Data/List/Functor.hs too large to diff
- typeclass-tests/Data/List/NonEmpty.hs too large to diff
- typeclass-tests/Data/List/Semigroup.hs too large to diff
- typeclass-tests/Data/Maybe.hs too large to diff
- typeclass-tests/Data/Maybe/Foldable.hs too large to diff
- typeclass-tests/Data/Maybe/Functor.hs too large to diff
- typeclass-tests/Data/Maybe/Semigroup.hs too large to diff
- typeclass-tests/Data/Num/Semigroup.hs too large to diff
- typeclass-tests/Data/PNat.hs too large to diff
- typeclass-tests/Data/PNat/Semigroup.hs too large to diff
- typeclass-tests/Data/Proxy.hs too large to diff
- typeclass-tests/Data/Reader.hs too large to diff
- typeclass-tests/Data/Reader/Functor.hs too large to diff
- typeclass-tests/Data/Semigroup/Classes.hs too large to diff
- typeclass-tests/Data/Successors.hs too large to diff
- typeclass-tests/Data/Successors/Functor.hs too large to diff
- typeclass-tests/Liquid/ProofCombinators.hs too large to diff
@@ -1,207 +0,0 @@-----version: 2.1--commands:- setup_project:- description: "Setup the machine, clone the repo, checkout the submodules."- steps:- - run: sudo apt-get update && sudo apt-get install -y curl git ssh unzip wget libtinfo-dev gcc make- - run:- name: Install z3- command: |- wget https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-ubuntu-16.04.zip- unzip z3-4.8.7-x64-ubuntu-16.04.zip- rm -f z3-4.8.7-x64-ubuntu-16.04.zip- sudo cp z3-4.8.7-x64-ubuntu-16.04/bin/libz3.a /usr/local/lib- sudo cp z3-4.8.7-x64-ubuntu-16.04/bin/z3 /usr/local/bin- sudo cp z3-4.8.7-x64-ubuntu-16.04/include/* /usr/local/include- rm -rf z3-4.8.7-x64-ubuntu-16.04- z3 --version-- - checkout- - add_ssh_keys- - run: git submodule sync- - run: git submodule update --init-- cabal_build_and_test:- description: "Build the project and run the tests"- parameters:- allow_test_failures:- type: boolean- default: false- cabal_update_command:- type: string- default: "cabal v2-update"- ghc_version:- type: string- default: "8.10.7"- project_file:- type: string- default: "cabal.project"- extra_test_flags:- type: string- default: ""- liquid_runner:- type: string- default: "--liquid-runner=cabal v2-run liquidhaskell -- "- ghc_options:- type: string- default: "--ghc-options=\"+RTS -M2G -RTS\""- setup_test_extra_steps:- type: string- default: ""- steps:- - setup_project- - run: git ls-tree HEAD liquid-fixpoint > liquid-fixpoint-commit- - restore_cache:- keys:- - cabal-cache-v3-{{ checksum "liquidhaskell.cabal" }}-{{ checksum "<< parameters.project_file >>" }}-{{ checksum "liquid-fixpoint-commit" }}- - cabal-cache-v3-{{ checksum "liquidhaskell.cabal" }}-{{ checksum "<< parameters.project_file >>" }}- - run:- name: Dependencies- command: |- wget https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup- chmod +x ./x86_64-linux-ghcup- ./x86_64-linux-ghcup install ghc << parameters.ghc_version >>- ./x86_64-linux-ghcup set ghc << parameters.ghc_version >>- ./x86_64-linux-ghcup install cabal 3.6.2.0- export PATH=~/.ghcup/bin:$PATH- echo 'export PATH=~/.ghcup/bin:$PATH' >> $BASH_ENV- << parameters.cabal_update_command >>- cabal v2-clean- cabal v2-build --project-file << parameters.project_file >> --flag include --flag devel -j2 --enable-tests all- - save_cache:- key: cabal-cache-v3-{{ checksum "liquidhaskell.cabal" }}-{{ checksum "<< parameters.project_file >>" }}-{{ checksum "liquid-fixpoint-commit" }}- paths:- - ~/.cabal/store- - ~/.ghcup- - ./dist-newstyle- - run:- name: Setup Test- command: |- mkdir -p /tmp/junit/cabal- << parameters.setup_test_extra_steps >>- - run:- name: Test- command: |- (liquidhaskell_datadir=$PWD cabal v2-test -j1 --project-file << parameters.project_file >> liquidhaskell:test << parameters.extra_test_flags >> --flag include --flag devel --test-show-details=streaming --test-option="<< parameters.liquid_runner >>" --test-options="-t 1200s --xml=/tmp/junit/cabal/main-test-results.xml") || (<<parameters.allow_test_failures>>)- (liquidhaskell_datadir=$PWD cabal v2-test -j1 --project-file << parameters.project_file >> liquidhaskell:liquidhaskell-parser --flag include --flag devel --test-show-details=streaming --test-options="--xml=/tmp/junit/cabal/parser-test-results.xml") || (<<parameters.allow_test_failures>>)- no_output_timeout: 30m- - store_test_results:- path: /tmp/junit/cabal- - run:- name: Compress artifacts- command: tar cvzf logs.tar.gz tests/logs/cur- - store_artifacts:- path: logs.tar.gz-- stack_build_and_test:- description: "Build and test the project using Stack"- parameters:- stack_yaml_file:- type: string- default: "stack.yaml"- liquid_runner:- type: string- default: "stack --silent exec -- liquidhaskell -v0"- extra_test_flags:- type: string- default: ""- extra_build_flags:- type: string- default: ""- steps:- - run: sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 8B1DA6120C2BF624- - setup_project- - run: git ls-tree HEAD liquid-fixpoint > liquid-fixpoint-commit- - restore_cache:- keys:- - stack-cache-v1-{{ checksum "<< parameters.stack_yaml_file >>" }}-{{ checksum "liquidhaskell.cabal" }}-{{ checksum "liquid-fixpoint-commit" }}- - stack-cache-v1-{{ checksum "<< parameters.stack_yaml_file >>" }}-{{ checksum "liquidhaskell.cabal" }}- - stack-cache-v1-{{ checksum "<< parameters.stack_yaml_file >>" }}- - run:- name: Dependencies- command: |- wget -qO- https://get.haskellstack.org/ | sudo sh- stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> setup- stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> build -j2 --only-dependencies --test --no-run-tests << parameters.extra_build_flags >>- - save_cache:- key: stack-cache-v1-{{ checksum "<< parameters.stack_yaml_file >>" }}-{{ checksum "liquidhaskell.cabal" }}-{{ checksum "liquid-fixpoint-commit" }}- paths:- - ~/.stack- - ./.stack-work- - run:- name: Test- command: |- stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> clean- mkdir -p /tmp/junit/stack- stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> test -j1 liquidhaskell:test << parameters.extra_build_flags >> << parameters.extra_test_flags >> --ta="--liquid-runner \"<< parameters.liquid_runner >>\"" --ta="-t 1200s --xml=/tmp/junit/stack/main-test-results.xml": #--liquid-opts='--cores=1'":- stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> test -j1 liquidhaskell:liquidhaskell-parser << parameters.extra_build_flags >> --ta="--xml=/tmp/junit/stack/parser-test-results.xml":- no_output_timeout: 30m- - run:- name: Generate haddock- command: |- # stack haddock liquidhaskell --flag liquidhaskell:-devel --no-haddock-deps --haddock-arguments="--no-print-missing-docs --odir=$CIRCLE_ARTIFACTS"- # skip if extra_build_flags are set- [ ! -z "<< parameters.extra_build_flags >>" ] || stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> haddock << parameters.extra_build_flags >> liquidhaskell --no-haddock-deps --haddock-arguments="--no-print-missing-docs"- - store_test_results:- path: /tmp/junit/stack- - run:- name: Compress artifacts- command: tar cvzf logs.tar.gz tests/logs/cur- - store_artifacts:- path: logs.tar.gz- - run:- name: Dist- command: |- # skip if extra_build_flags are set- [ ! -z "<< parameters.extra_build_flags >>" ] || stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> sdist--jobs:-- stack_810_legacy_executable:- machine:- image: ubuntu-2004:202107-02- steps:- - stack_build_and_test:- stack_yaml_file: "stack.yaml"- liquid_runner: "stack --silent exec -- liquid"- extra_build_flags: "--flag liquidhaskell:include --flag liquid-platform:devel --flag liquidhaskell:no-plugin"-- stack_810:- machine:- image: ubuntu-2004:202107-02- steps:- - stack_build_and_test:- stack_yaml_file: "stack.yaml"- extra_test_flags: " liquid-platform:liquidhaskell "-- cabal_810:- machine:- image: ubuntu-2004:202107-02- steps:- - cabal_build_and_test:- liquid_runner: "--liquid-runner=cabal -v0 v2-exec liquidhaskell -- -v0 \- -package-env=$(./scripts/generate_testing_ghc_env) \- -package=liquidhaskell -package=Cabal "-- cabal_900:- machine:- image: ubuntu-2004:202107-02- steps:- - cabal_build_and_test:- ghc_version: "9.0.1"- project_file: "cabal.ghc9.project"- extra_test_flags: ' --test-options '' -p "$0 != \"Tests.Benchmarks.text.Data/Text/Foreign.hs\" && ! /Tests.Micro.typeclass-pos./"'' '- liquid_runner: "--liquid-runner=cabal -v0 v2-exec --project-file cabal.ghc9.project liquidhaskell -- -v0 \- -package-env=$(./scripts/generate_testing_ghc_env cabal.ghc9.project) \- -package=liquidhaskell -package=Cabal "--workflows:- version: 2- build_stack_and_cabal:- jobs:- - stack_810_legacy_executable- - stack_810- - cabal_810- - cabal_900
@@ -1,2 +0,0 @@-:set -isrc-:set prompt "\ESC[34mλ> \ESC[m"
@@ -1,5 +0,0 @@-import "hint" HLint.Default-import "hint" HLint.Dollar--ignore "Eta reduce"-ignore "Use ."
@@ -1,102 +0,0 @@-# Install LiquidHaskell--To run `liquid` you need to install:--1. An SMT solver-2. The `liquid` binary via package manager *or* source.---## Step 1: Install SMT Solver--You can skip this if you will be building LiquidHaskell with [Nix][nix].--Download and install *at least one* of--+ [Z3](https://github.com/Z3Prover/z3/releases) or [Microsoft official binary](https://www.microsoft.com/en-us/download/details.aspx?id=52270)-+ [CVC4](http://cvc4.cs.stanford.edu/web/)-+ [MathSat](http://mathsat.fbk.eu/download.html)--Note: It should be findable from PATH. LiquidHaskell is executing it as a child process.--## Step 2: Install `liquid` via Package Manager--The `liquid` executable is provided as part of a standalone, battery-included package called `liquid-platform`.--Simply do:-- cabal install liquid-platform--We are working to put `liquid` on `stackage`.--You can designate a specific version of LiquidHaskell to ensure that the correct-GHC version is in the environment. As an example,-- cabal install liquid-platform-0.9.0.0--## Step 2: Install `liquid` from Source--If you want the most recent version, you can build from source as follows,-either using `stack` (recommended) or `cabal`. In either case: *recursively*-clone the repo and then build:--### Build with `stack` and `Nix`--This doesn't require to install `stack` or `z3` in advance. Though it will require-installing [Nix][nix].-- git clone --recursive git@github.com:ucsd-progsys/liquidhaskell.git- cd liquidhaskell- nix-shell --pure --run "stack install liquid-platform"--### Build with `stack` (recommended)--This requires that you have installed [stack][stack] (which we strongly recommend!)-- git clone --recursive git@github.com:ucsd-progsys/liquidhaskell.git- cd liquidhaskell- stack install liquid-platform--If you haven't set up your ssh keys with github, use the `https` method to clone and build-- git clone --recursive https://github.com/ucsd-progsys/liquidhaskell.git- cd liquidhaskell- stack install liquid-platform--#### A note on the GHC_PACKAGE_PATH--In order for `liquid` to work correctly, it needs to have access to auxiliary packages-installed as part of the executable. Therefore, you might need to extend your `$GHC_PACKAGE_PATH` to-have it point to the right location(s). Typically the easiest way is to call `stack path`, which will-print a lot of diagnostic output. From that it should be suffient to copy the paths printed as part of-`ghc-package-path: <some-paths>` and extend the `GHC_PACKAGE_PATH` this way -(typically editing your `.bashrc` to make the changes permanent):--```-export GHC_PACKAGE_PATH=$GHC_PACKAGE_PATH:<some-paths>-```--After that, running `liquid` anywhere from the filesystem should work.---## Troubleshooting---1. If you're on Windows, please make sure the SMT solver is installed- in the **same** directory as LiquidHaskell itself (i.e. wherever- `cabal` or `stack` puts your binaries). That is, do:-- ```- which liquid- ```-- and make sure that `z3` or `cvc4` or `mathsat` are in the `PATH`- returned by the above.--2. If you installed via `stack` and are experiencing path related woes, try:-- ```- stack exec -- liquid path/to/file.hs- ```--[nix]: https://nixos.org/download.html-[stack]: https://github.com/commercialhaskell/stack/blob/master/doc/install_and_upgrade.md
@@ -1,7 +0,0 @@-Z3-Copyright (c) Microsoft Corporation-All rights reserved. -MIT License-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.-THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,62 +0,0 @@--## Mirroring modules for the liquid ecosystem--We provide a fairly simple tool (under the form of an Haskell executable) to make the process of-generating "mirror modules" easy. This need might arise when developing new packages containing only refinemnents-for existing packages. These modules are usually meant to be considered \"drop in\", which means they should-expose the very same modules the original package provided. For big and rich packages, this process can be-tedious to do by hand, especially if only a handful of modules contains refinemnents. This is where this-tool comes in hand.--The tool for now can be built only if the `mirror-modules-helper` flag is passed -(and it's **not** turned on by default) to avoid pulling unnecessary dependencies when we build-the `liquidhaskell` library. We can in principle move this into a standalone package, in the future.--### Installation instructions (stack)--```-stack build --flag liquidhaskell:mirror-modules-helper-```--### Usage--The tool accepts the following options:--```-stack exec mirror-modules -- --help--Usage: mirror-modules [--unsafe-override-files] (-l|--modules-list ARG)- (-p|--mirror-package-name ARG) (-i|--target ARG)- Create modules to be used in mirror packages.--Available options:- --unsafe-override-files Overrides an Haskell module if already present in the- folder.- -l,--modules-list ARG The path to a file containing a newline-separated- list of modules to mirror.- -p,--mirror-package-name ARG- The name of the mirror package we are targeting.- (example: liquid-foo)- -i,--target ARG The path to the root of the module hierarchy for the- target package. (example: liquid-foo/src)- -h,--help Show this help text-```---The tool is faily simple and eschew more sophisticated mechanisms (like automatically pulling the mirrored-package from Hackage and extract the exposed-modules from the parsed Cabal manifest), so it accepts a file-with the full list of exposed modules of the mirrored package (which can be copied and pasted from the Cabal-manifest directly) and it's smart enough to figure out which modules needs mirroring. The user can decide-to unsafely override existing modules by passing the `--unsafe-override-files` option as input.-Last but not least, we require the name of the mirror package (e.g. `liquid-foo`) as well as the path-(relative or absolute) where the source files are (e.g. `liquid-foo/src`).--### Example (liquid-base)--For example, this is how we can mirror all the packages from `base` into `liquid-base`:--```-stack exec mirror-modules -- -l ../packages.txt -p liquid-base -i liquid-base/src/-```--Where `packages.txt` contains the newline-separated list of all the `exposed-modules` from `base`.
@@ -1,112 +0,0 @@-THREADS=1-SMTSOLVER=z3--FASTOPTS=-O0-DISTOPTS=-O2-PROFOPTS=-O2 --enable-library-profiling --enable-executable-profiling-LIQUIDOPTS=--CABAL=cabal-CABALI=$(CABAL) install-CABALP=$(CABAL) install --enable-library-profiling--# to deal with cabal sandboxes using dist/dist-sandbox-xxxxxx/build/test/test-# TASTY=find dist -type f -name test | head -n1-TASTY=./dist/build/test/test--DEPS=--dependencies-only--ghcid: - stack exec -- ghcid --command="stack ghci --ghci-options=-fno-code"---##############################################################################-##############################################################################-##############################################################################--fast:- $(CABAL) install -fdevel $(FASTOPTS)--first:- $(CABAL) install $(FASTOPTS) --only-dependencies --enable-tests --enable-benchmarks--dist:- # $(CABAL) install $(DISTOPTS)- $(CABAL) configure -fdevel --enable-tests --disable-library-profiling -O2- $(CABAL) build- -prof:- $(CABAL) install $(PROFOPTS)--igotgoto:- $(CABAL) build $(OPTS)- cp dist/build/liquid/liquid ~/.cabal/bin/--clean:- cabal clean--docs:- $(CABAL) hscolour- $(CABAL) haddock --hoogle--deps:- $(CABALI) $(DEPS)--pdeps:- $(CABALP) $(DEPS)--all-test-py:- cd tests && ./regrtest.py -a -t $(THREADS) && cd ../--test-py:- cd tests && ./regrtest.py -t $(THREADS) && cd ../--test:- $(CABAL) configure -fdevel --enable-tests --disable-library-profiling -O2- $(CABAL) build- $(CABAL) exec $(TASTY) -- --smtsolver $(SMTSOLVER) --hide-successes --rerun-update -p 'Unit/' -j$(THREADS) +RTS -N$(THREADS) -RTS- # $(CABAL) exec $(TASTY) -- --smtsolver $(SMTSOLVER) --liquid-opts='$(LIQUIDOPTS)' --hide-successes --rerun-update -p 'Unit/' -j$(THREADS) +RTS -N$(THREADS) -RTS--test710:- $(CABAL) configure -fdevel --enable-tests --disable-library-profiling -O2- $(CABAL) build- $(TASTY) --smtsolver $(SMTSOLVER) --hide-successes --rerun-update -p 'Unit/' -j$(THREADS) +RTS -N$(THREADS) -RTS---retest:- cabal configure -fdevel --enable-tests --disable-library-profiling -O2- cabal build- cabal exec $(TASTY) -- --smtsolver $(SMTSOLVER) --hide-successes --rerun-filter "exceptions,failures,new" --rerun-update -p 'Unit/' -j$(THREADS) +RTS -N$(THREADS) -RTS--all-test:- cabal configure -fdevel --enable-tests --disable-library-profiling -O2- cabal build- cabal exec $(TASTY) -- --smtsolver $(SMTSOLVER) --hide-successes --rerun-update -j$(THREADS) +RTS -N$(THREADS) -RTS--all-test-710:- cabal configure -fdevel --enable-tests --disable-library-profiling -O2- cabal build- $(TASTY) --smtsolver $(SMTSOLVER) --hide-successes --rerun-update -j$(THREADS) +RTS -N$(THREADS) -RTS----all-retest:- cabal configure -fdevel --enable-tests --disable-library-profiling -O2- cabal build- cabal exec $(TASTY) -- --smtsolver $(SMTSOLVER) --hide-successes --rerun-filter "exceptions,failures,new" --rerun-update -j$(THREADS) +RTS -N$(THREADS) -RTS--all-retest-710:- cabal configure -fdevel --enable-tests --disable-library-profiling -O2- cabal build- $(TASTY) --smtsolver $(SMTSOLVER) --hide-successes --rerun-filter "exceptions,failures,new" --rerun-update -j$(THREADS) +RTS -N$(THREADS) -RTS----lint:- hlint --colour --report .--tags:- hasktags -x -c src/- # hasktags -c src/- # hasktags -e src/-
@@ -1,297 +0,0 @@-## New Syntax for Abstract Refinements--### Ghost Parameters---```haskell-A n -> B (n + 1)---- becomes-{ p n => q (n + 1)}. A<p> -> B<q>---- i.e.-{ p n => v = n + 1 => q v}. A<p> -> B<q>-```--which means, I suppose that--```haskell-A n -> B (op n)---- becomes-{ p n => q (op n) }. A<p> -> B<q>---- i.e.--{ p n => v = op n => q v }. A<p> -> B<q>-```---(a -> Count b <<p>>) -> xs:List a -> (Count (List b) <<q>>)---```haskell-A n -> B m -> C (n + m)---- becomes-{ p n => q m => r (n + m) }. A<p> -> B<q> -> C<r>---- i.e.-{ p n => q m => v = n + m => r v }. A<p> -> B<q> -> C<r>-```--{ n::Int<p> |- {v:Int | v = n+1} <: Int<q> }--```haskell-{-@ bump1 :: forall <p::Int -> Bool, q::Int -> Bool>.- { n::Int<p> |- {v:Int | v = n + 1} <: Int<q> }- (Int -> Int<p>) -> Int<q>- @-}-bump1 :: (Int -> Int) -> Int-bump1 f = f 0 + 1--{-@ bumps :: forall <p::[Int] -> Bool, q::Int -> Bool>.- { xs :: [Int]<p> |- {v:Int | v = len xs} <: Int<q> }- (Int -> [Int]<p>) -> Int<q>- @-}--bumps :: (Int -> ListN Int n) -> IntN n-bumps f = size (f 0)--{-@ bump2 :: forall <p::Int -> Bool, q::Int -> Bool, r::Int -> Bool>.- { n::Int<p>, m::Int<q> |- {v:Int | v = n + m} <: Int<r> }- (Int -> Int<p>) -> (Int -> Int<q>) -> Int<r>- @-}-bump2 :: (Int -> Int) -> (Int -> Int) -> Int-bump2 f g = f 0 + g 0--{-@ flerb :: ({v:Int | v = 6}, {v:Int | v = 10}) @-}-flerb = (a, b) - where- a = bump zong- b = bump2 zong zong- zong :: Int -> Int- zong n = 5--{-@ type IntN N = {v:Int | v == N} @-}-bump1 :: Ghost n. (Int -> IntN n) -> IntN (n+1)-bump2 :: Ghost n m. (Int -> IntN n) -> (Int -> IntN m) -> IntN (n+m)-```--### New Proposal--**NOTE:** I believe this is a **purely syntactic change**:-it should not affect how absref is actually implemented,-but it more precisely describes the implementation than-the current `-> Bool` formulation.--#### Step 1: Abstract Refinement is "Type with Shape"--Key idea is to think of an abstract refinement as a (function returning a) refinement type.--That is, the abstract refinement:--```haskell- T1 -> T2 -> T3 -> ... -> S -> Bool-```--now just becomes--```haskell- T1 -> T2 -> T3 -> ... -> {S}-```--Here, `{S}` denotes a refinement type with shape `S`--**Key Payoff:** This means that we don't need an _explicit application_ form, that is--```haskell- foo :: forall <p :: Int -> Bool>. [Int<p>] -> Int<p>-```--can just be written as--```haskell- foo :: forall <p :: {Int}>. [p] -> p-```--where we need not write `Int<p>`, its enough to just write `p`.--#### Step 2: An explicit "Meet" Operator--However, sometimes you need to write things like:--```haskell- List <p> a <<p>>-```--where `p :: List a -> Bool` i.e. `p :: {List a}` and which denotes--* a list-of-a that is recursively indexed by `p`, AND-* where the top-level list is constrained by `p`.--That is, more generally, where you want to--* additionally, index the type with other abstract refinements, AND-* "apply" an abstract refinement to the "top-level" type.--For this, I think we should have an explicit *meet* operator-Note that, earlier `Int<p>` was an *implicit* meet operator,-where we were *conjoining* `Int` and `p`. Viewing `p` as-just being a refined `Int` allows us to SEPARATE "meet"-to only those places where its really needed.--So we can write the funny `List <p> a <<p>>` as:--```haskell- p /\ List <p> a-```--See below for many other examples:--#### Example: Value Dependencies--**Old**--```haskell- foo :: forall <p :: Int -> Int -> Bool>. x:Int -> [Int<p x>] -> Int<p x>-```--**New**--```haskell- foo :: forall <p :: Int -> {Int}>. x:Int -> [p x] -> p x-```--#### Example: Dependent Pairs--**Old**--```haskell- data Pair a b <p :: a -> b -> Bool>- = Pair { pairX :: a- , pairB :: b<p pairX>- }-- type OrdPair a = Pair <{\px py -> px < py}> a a-```--**New**--```haskell- data Pair a b <p :: a -> {b}>- = Pair { pairX :: a- , pairY :: p pairX- }--- type OrdPair a = Pair a a <\px -> {py:a | px < py}>-```--#### Example: Binary Search Maps--**Old**--```haskell- data Map k a <l :: root:k -> k -> Bool, r :: root:k -> k -> Bool>- = Tip- | Bin { mSz :: Size- , mKey :: k- , mValue :: a- , mLeft :: Map <l, r> (k <l mKey>) a- , mRight :: Map <l, r> (k <r mKey>) a }-- type OMap k a = Map <{\root v -> v < root }, {\root v -> v > root}> k a-```--**New**--```haskell- data Map k a <l :: root:k -> {k}, r :: root:k -> {k}>- = Tip- | Bin { mSz :: Size- , mKey :: k- , mValue :: a- , mLeft :: Map (l mKey) a <l, r>- , mRight :: Map (r mKey) a <l, r> }-- type OMap k a = Map k a <\root -> {v:k | v < root }, \root -> {v:k | root < v}>-```--#### Example: Ordered Lists--**Old**--```haskell- data List a <p :: a -> a -> Bool>- = Emp- | Cons { lHd :: a- , lTl :: List <p> (a<p lHd>)- }-- type OList a = List <{\x v -> x <= v}> a-```--**New**--```haskell- data List a <p :: a -> {a}>- = Emp- | Cons { lHd :: a- , lTl :: List (p lHd) <p>- }-- type OList a = List a <\x -> {v:a | x <= v}>-```--#### Example: Infinite Streams--**Old**--```haskell- data List a <p :: List a -> Prop>- = N- | C { x :: a- , xs :: List <p> a <<p>>- }-- type Stream a = {xs: List <{\v -> isCons v}> a | isCons xs}-```--**New**--```haskell- data List a <p :: {List a}>- = N- | C { x :: a- , xs :: p /\ List a <p>- }-- type Stream a = {xs: List a <{v | isCons v}> | isCons xs}-```-----### Old Proposal---| | Current Syntax | Future Syntax |-|----------------------|-------------------------------|-------------------------------|-| Abstract Refinements | `List <{\x v -> v >= x}> Int` | `List Int (\x v -> v >= x)` |-| | `[a<p>]<{\x v -> v >= x}>` | `[a p] (\x v -> v >= x) (??)` |-| | `Int<p>` | `Int p` |-| | `Int<\x -> x >=0>` | `Int (\x -> x >= 0)` |--| | `Maybe <<p>> (a<q>) (?)` | `Maybe (a q) p` |-| | `Map <l, r> <<p>> k v (?)` | `Maybe k v l r p` |--| Type Arguments | `ListN a {len xs + len ys}` | `ListN a (len xs + len ys)` |--Q: How do I distinguish `Int p` with `ListN a n`?-(`p` is a abstract refinement and `n` is an `Integer`)--A: From the context!-Use simple kinds, i.e.-`ListN :: * -> Int -> *`-`Int :: ?AR -> *`
@@ -1,22 +0,0 @@-- Verification of Libraries - - [zlib](https://hackage.haskell.org/package/zlib)- - [probability](https://github.com/nikivazou/probability)- -- fix parser error message- - Parse Errors [#241](https://github.com/ucsd-progsys/liquidhaskell/issues/241)- - Liquid Haskell doesn't accept Haskell names containing ' (single-quote) [#273](https://github.com/ucsd-progsys/liquidhaskell/issues/273)- - Error messages [#400](https://github.com/ucsd-progsys/liquidhaskell/issues/400)- - Add list of reserved tokens--- Parse Propositional Variables in Refinements [#338](https://github.com/ucsd-progsys/liquidhaskell/issues/338)--- Combine GHC and Liquid Type Aliases [#381](https://github.com/ucsd-progsys/liquidhaskell/issues/381)--- Applying data type with wrong number of abstract refinement params could give better errors [#297](https://github.com/ucsd-progsys/liquidhaskell/issues/297)--- Export qualifiers from measure types [#302](https://github.com/ucsd-progsys/liquidhaskell/issues/302)--- systematically remove all error calls -- NV: Not sure how easy this is, as it requires deep understanding of the code- to distinguish dead code from our errors.
@@ -1,1333 +0,0 @@-# TODO---## ISSUE: why does bounds stuff take so long?--https://ucsd-progsys.slack.com/archives/DU17X62Q5/p1621006535008300--DISCO full full GHC+LH build = 120s- vs Z3 ... 7s (!)--```-$ stack build --dependencies-only-$ time stack build-```--`develop`--________________________________________________________-Executed in 166.60 secs fish external- usr time 156.04 secs 66.80 millis 155.98 secs- sys time 7.46 secs 9.35 millis 7.45 secs--#1150 -- FUNCTION-https://github.com/ucsd-progsys/liquidhaskell/issues/1149 -- ???-https://github.com/ucsd-progsys/liquidhaskell/issues/1120----fullcheck---checkderived---noclasscheck-----<<<<<<< HEAD---## no-adt--#1150 -- FUNCTION-https://github.com/ucsd-progsys/liquidhaskell/issues/1149 -- ???-https://github.com/ucsd-progsys/liquidhaskell/issues/1120--Don't encode non-encodable ADTs (by default)--=======->>>>>>> 102b3384caff33c1d722dcbb96eb20913bcbb064-## Fix: SpecDependencyGraph--1. Implement `Bare.SpecDep` -2. Use `slice` to pre-filter the `BareSpec` prior to resolution --```haskell--- | This module has datatypes and code for building a Specification Dependency Graph --- whose vertices are 'names' that need to be resolve, and edges are 'dependencies'.--module SpecDep (slice) where---- | A datatype for the different kinds of names we have to resolve-data Label- = Sign -- ^ identifier signature- | Func -- ^ measure or reflect- | DCon -- ^ data constructor- | TCon -- ^ type constructor---- | A datatype for nodes which are pairs of names and labels-data Node = MkNode- { nodeName :: LocSymbol- , nodeLabel :: Label- }--type Graph = Map Node [Node]---- | A way to combine graphs of multiple modules--instance Semigroup Graph where- TODO--instance Monoid Graph where- TODO---- | A function to build the dependencies for each module--specDepGraph :: BareSpec -> Graph-specDepGraph = _TODO--mkDepGraph :: [BareSpec] -> Graph-mkDepGraph specs = mconcat [specDepGraph sp | sp <- specs]---- | 'reachable roots g' returns the list of Node transitively reachable from roots-reachable :: [Node] -> Graph -> [Node]-reachable roots g = _TODO---- | Top-level "slicing" function-slice :: (ModName, BareSpec) -> [(ModName, BareSpec)] -> [(ModName, BareSpec)]-slice (tgt, tgtSpec) specs = _TODO-```--## CallStack/Error--The use of `Prelude.error` gives a crazy performance hit-apparently even without cut-vars being generated, this is-because of some bizarro GHC transforms, that thwart eliminate.-This is because GHC now threads `callstack` through such-computations, which make a top-level signature no longer top-level.-- Prelude.error -> dummyError (no call-stack)- LambdaEval.hs 11 -> 4 -> 4- Map0.hs 27 -> 13 -> 13- Map2.hs "" - Map.hs ""- Base 103 -> 76.18 -> 68--Not clear-Does all that `PatSelfBind` stuff help at all with these benchmarks?-- NO.-- Or do we need to really use a different `error`?-- If not, REMOVE IT.--- [ ] ES:fix Target-- [ ] ES:bring back bench-- [ ] NV: Termination requires Haskell signature in `tests/pos/Term.hs`-- [ ] NV: bound syntax `tests/todo/dropWhile.hs`-- [ ] NV: bound `icfp/pos/FindRec.hs`-- [ ] NV: HACK IO TyCon lookup, it appears as a data con (in Lookup)--TODO-====---Prune Unsorted Refs----------------------The below gives a nice SORT error--```haskell-import Data.Set--data RBTree a = Leaf | Node--{-@ measure isB :: RBTree a -> (Set a)- isB (Leaf) = 1- isB (Node) = (Set_empty 0)- @-}-```--rjhala@borscht ~/r/s/liquidhaskell (prune-unsorted-error)> stack exec -- liquid tests/todo/prune.hs-- /Users/rjhala/research/stack/liquidhaskell/tests/todo/prune.hs:7:13-15: Error: Bad Type Specification- measure isB :: (RBTree a b) -> (Set a)- Type constructor Prune.RBTree expects a maximum 1 arguments but was given 2 arguments-- /Users/rjhala/research/stack/liquidhaskell/tests/todo/prune.hs:14:13: Error: Bad Measure Specification- measure isB- The sort (Set_Set @(42)) is not numeric- because- Cannot unify (Set_Set @(42)) with int in expression: 1- because- Cannot cast 1 of sort int to incompatible sort func(1, [(Set_Set @(0))])--now put another SORT CHECK for measures:-- * Input type should be "isGeneric"-- isGeneric T if-- * T is a TyConApp `c [t1...tn]`-- where t1 .. tn are DISTINCT type variables.--If the above SORT CHECK fails for any measure print an ERROR message saying:-- please rerun with --prune-unsorted--```haskell--(:) :: Int -> [Int] -> [Int]--sum :: [Int] -> Int-sum [] = 0-sum (x:xs) = x + sum xs---sum :: Tree Int a -> Int-sum Leaf = 0-sum Node k _ l r = k + sum l + sum r-```--Check Covariance-------------------See https://github.com/ucsd-progsys/liquidhaskell/blob/master/tests/todo/kmpMonad.hs#L55-It is safe is 100 is changed to 0. WHY?--LAZYVAR----------Restore LAZYVARS in `Data/Text.hs`, `Data/Text/Unsafe.hs`---Automatically refine *inductors*-----------------------------------Proposed by Valentine: in dependent languages (Coq)-inductors (like our `loop` for natural numbers)-automatically get types abstracted over properties.-Traversal should create such functions.-Maybe we can automatically refine them.--benchmarks--------------* benchmarks: Data.Bytestring- ? readsPrec- ? big constants issue : _word64 34534523452134213524525 due to (deriving Typeable)- - see others below--* hmatrix--* error messages (see issues on github)--Benchmarks-==========-- time(O|N|C) TOTAL(O|N) solve (O|N) refines iterfreq- Map.hs : 54/50/32/10 21/15/8.7 14/8/4.3 9100/4900/2700 16/28/7- ListSort.hs : */7.5/5.5/2 */2.5/1.8 */1.5/1.0 */1100/600 */9/7- GhcListSort.hs : 23/22/17/5 7.3/7.8/5 4.5/5.0/2.7 3700/4400/1900 10/23/6- LambdaEval.hs : 36/32/25/12 17/12/10 11.7/6.0/5 8500/3100/2400 12/5/5- Base.hs : 26mi/2m---Benchmarks-==========--[OK] Data.KMeans-[OK] GHC.List (../benchmarks/ghc-7.4.1/List.lhs)-[OK] bytestring-[OK] text--[??-PP] Data.Map (supersedes set)- - ordering [OK]- - size- - key-set-properties- - key-dependence- - balance (NO)--- vector-algorithms "vector bounds checking"- - e.g. "unsafeSlice"- - maybe only specify types for Vector?--- vector-- repa-- repa-algorithms-- xmonad (stackset)-- snap/security-- hmatrix- > http://hackage.haskell.org/packages/archive/hmatrix/0.12.0.1/doc/html/src/Data-Packed-Internal-Matrix.html#Matrix- > http://hackage.haskell.org/packages/archive/hmatrix/0.12.0.1/doc/html/src/Data-Packed-Internal-Vector.html#fromList--Other Benchmarks-================---> FingerTrees (containers / Data.Seq)--> Union-Find (PLDI09 port if necessary?)--> BDD (PLDI09 port if necessary?)--[NO] Data.Set (Map redux)- > ordering- > size- > set-properties- > balance (NO)--[NO] Data.IntSet- > tricky bit-level operations/invariants--Paper #2---> Haskell + DB / Yesod / Snap--> NDM/catch benchmarks (with refinements)--Known Bugs-==========---> tests/todo/fft.hs---> binsearch crashes because you have chains like:-- x1 = 2- x2 = x1- x3 = x2- z = x3 / 2-- so I guess you need some constprop inside the constraint simplification.--- tests/pos/data-mono0.hs- partial pattern match desugars into exception syntax with unhandled- casts. Throws an error in fixpoint. At least throw error in Constraint Gen?- (\ _ ->- (Control.Exception.Base.irrefutPatError- @ () "pos/data-mono0.hs:8:9-23|(Test.Cons x _)")- `cast` (UnsafeCo () GHC.Types.Int :: () ~ GHC.Types.Int))- GHC.Prim.realWorld#;---Xmonad Case Study-=================--Theorems (from Wouter Swierstra's Coq Development)-- - Invariant: NoDuplicates-- - prop_empty_I : new : ? -> {v | invariant(v)}- - prop_view_I : view : ? -> {v | invariant(v)}- - prop_greedyView_I : view : ? -> {v | invariant(v)}- - prop_focusUp_I- - prop_focusMaster_I- - prop_focusDown_I- - prop_focus_I- - prop_insertUp_I- - prop_delete_I- - prop_swap_master_I- - prop_swap_left_I - - prop_swap_right_I- - prop_shift_I- - prop_shift_win_I--[prop_FOO_I] check that various functions outputs satisfy "invariant"-- FOO :: ??? -> {v: StackSet | invariant(v)}-- > Theorem prop_swap_master_I (s : StackSet.stackSet i l a sd) :- > Theorem prop_view_I (l a sd : Set) (n : nat) (s : StackSet.stackSet nat l a sd) :- > Theorem prop_greedyView_I (l a sd : Set) (n : nat) (s : StackSet.stackSet nat l a sd) :- > Theorem prop_focusUp_I (l a sd : Set) (n : nat) (s : StackSet.stackSet nat l a sd) :- > Theorem prop_focusDown_I (l a sd : Set) (n : nat) (s : StackSet.stackSet nat l a sd) :- > Theorem prop_focusMaster_I (l a sd : Set) (n : nat) (s : StackSet.stackSet nat l a sd) :- > Theorem prop_empty_I (m : l) (wids : {wids : list i | wids <> nil})- > Theorem prop_empty (m : l) (wids : {wids : list i | wids <> nil})- > Theorem prop_differentiate (xs : list a) :--[prop_FOO_local] check that various functions preserve a [hidden_spaces] MEASURE-- FOO :: x: StackSet -> {v: StackSet | hidden_spaces(v) = hidden_spaces(x) }-- > Theorem prop_focus_down_local (s : stackSet i l a sd) :- > Theorem prop_focus_up_local (s : stackSet i l a sd) :- > Theorem prop_focus_master_local (s : stackSet i l a sd) :- > Theorem prop_delete_local (s : stackSet i l a sd) (eq_dec : forall x y, {x = y} + {x <> y}) :- > Theorem prop_swap_master_local (s : stackSet i l a sd) :- > Theorem prop_swap_left_local (s : stackSet i l a sd) :- > Theorem prop_swap_right_local (s : stackSet i l a sd) :- > Theorem prop_shift_master_local (s : stackSet i l a sd) :- > Theorem prop_insert_local (x : stackSet i l a sd) (eq_dec : forall x y, {x = y} + {x <> y}) :---BAD: these check that: forall x: foo (bar x) == x-- > Theorem prop_focus_right (s : StackSet.stackSet i l a sd) :- > Theorem prop_focus_left (s : StackSet.stackSet i l a sd) :--[prop_swap_*_focus] check that various functions preserve a [peek] MEASURE- > Theorem prop_swap_master_focus (x : StackSet.stackSet i l a sd) :- > Theorem prop_swap_left_focus (x : StackSet.stackSet i l a sd) :- > Theorem prop_swap_right_focus (x : StackSet.stackSet i l a sd) :---BAD? forall x. swapMaster (swapMaster x) == x- > Theorem prop_swap_master_idempotent (x : StackSet.stackSet i l a sd) :--BAD? forall x. view i (view i x) == (view i x)- > Theorem prop_focusMaster_idem (x : StackSet.stackSet i l a sd) :-- NO. Prove: view :: i -> x -> {v: focus(v) = i}- :: i -> x -> {v: focus(x) = i => x = v }-- To prove foo_IDEMPOTENT, find a property P such that:-- foo :: x:t -> {v:t | P(v)}- foo :: x:t -> {v:t | P(x) => v = x }--SETS:- > Theorem prop_screens (s : stackSet i l a sd) :---TRIV/HARD: (function definition)- > [TRIV] Theorem prop_screens_work (x : stackSet i l a sd) :- > Theorem prop_mapWorkspaceId (x : stackSet i l a sd) :- > Theorem prop_mapLayoutId (s : stackSet i l a sd) :- > Theorem prop_mapLayoutInverse (s : stackSet i nat a sd) :- > Theorem prop_mapWorkspaceInverse (s : stackSet nat l a sd) :--Theorem prop_lookup_current (x : stackSet i l a sd) :-Theorem prop_lookup_visible (x : stackSet i l a sd) :---Random Links-============--- Useful for DIGRAPH VIZ: http://arborjs.org/halfviz/#---Benchmark Tags-==============--- LIQUIDFAIL : impossible to do verify the spec here-- LIQUIDTODO : possible with some further hacking----------------------------------------------------------------------------------http://www.cs.st-andrews.ac.uk/~eb/writings/fi-cbc.pdf--McBride's Stack Machine youtube mcbride icfp 2012 monday keynote agda-curious-- data Instr = Push Val | Add- type Val = Int-- measure needs :: [Instr] -> Int- needs (Add : is) = min (2, 1 + needs(is))- needs (Push v : is) = 0-- run :: is:[Instr] -> {v:[Val] | len(v) >= needs(is)} -> [Val]- run (Add:is) (x1:x2:vs) = run is (x1 + x2 : vs)- run (Push v : is) vs = run is (v : vs)--PROJECT: Termination for Combinator-based Parsers----------------------------------------------------btw, did you guys see this:--http://www.reddit.com/r/haskell/comments/1okcmh/odd_space_leak_when_using_parsec/--the poster probably feels silly, but I have, on several occasions, hit-this issue with parsec. Wonder whether our termination checker could be used... hmm...--Sure! You just have to give--type GenParser tok st = Parsec [tok] st--a size, I guess (len [tok]). The hard part will be to prove it when the size is actually decreasing...--Hmm... Surely we need to track somehow the "effect" of executing a single parsing action.--For example,-- chars :: Char -> Parser [Char]- chars c = do z <- char c- zs <- chars c- return (z:zs)--What is the machinery by which the "recursive call" is run on a "smaller" GenParser?-Does it help if we remove the `do` block?-- chars :: Char -> Parser [Char]- chars c = char c >>= \z -> - chars c >>= \zs ->- return (z:zs)--I guess the question becomes, how/where do we specify (let alone verify) that the function-`char c` *consumes* one character, hence causing the `chars` to run on a *smaller* input?---Phew, after banging my head against this all day, this is what I came up with.--You need a measure-- measure eats :: Parser a -> Nat--which describes (a lower bound) on the number of tokens consumed by the action `Parser a`.--Now, you give-- return :: a -> {v: Parser a | (eats v) = 0}--and most importantly,-- (>>=) :: forall <Q :: Parser b -> Prop>- x: Parser a- -> f:{v: a -> Parser b <Q> | (rec v) => (eats x) > 0}- -> exists z:Parser b <Q>. {v:Parser b | (eats v) = (eats z) + (eats x)}--(Of course you have to give appropriate signatures for the parsec combinators--- perhaps one can even PROVE the `eats` measure. However, note that-- type Parser a = [Char] -> (a, [Char])--roughly speaking, and here `eats` is actually the DIFFERENCE of the lengths of-the input and output [Char] ... so I'm not sure how exactly we would reason about-the IMPLEMENTATION of `eats` but certainly we should be able to USE it in clients-of parsec.--Note that you need a refinement ON the function type, the idea being that:--1. the BODY of a recursive function is checked in the termination-strengthened-environment that constrains the function to satisfy the predicate `rec`--2. whenever you use >>= on a recursive function, the PRECEDING action must have-consumed some tokens.--3. the number of tokens consumed by the combined action equals the sum of the two-actions (all the business about exists z and Q is to allow us to depend on the output-value of `f` (c.f. tests/pos/cont1.hs)---PROJECT: HTT style ST/IO reasoning with Abstract Refinements---------------------------------------------------------------+ Create a test case: `tests/todo/Eff*.hs`--+ Introduce a new sort of refinement `Ref` (with alias `RTProp`)- + Types.hs: Add to `Ref` -- in addition to `RMono` [---> `RPropP`] and `RPoly` [---> `RProp`]- + Types.hs: Add a `World t` for SL formulas...---+ Allow `PVar` to have the sort `HProp`- + CHANGE `ptype :: PVKind t` where `data PVKind t = PVProp t | PVHProp`- + Can we reuse `RAllP` to encode `HProp`-quantification? (YES)- + Update `RTyCon` to store `HProp` vars--- Update consgen- + Can we reuse type-application sites for `HProp`-instantiation? (Yes)- - Constraint.hs :1642: = errorstar "TODO:EFFECTS:freshPredRef"- - PredType.hs : go _ (_, RHProp _ _) = errorstar "TODO:EFFECTS:replacePreds"--- Write cons-solve- - eliminate/solve `HProp` constraints prior to subtype splitting.--- Index `IO` or `State` by `HProp`- - Parse.hs: Update `data` parser to allow `TyCon` to be indexed by abstract `HProp`- - Bare.hs :482 : addSymSortRef _ (RHProp _ _) = errorstar "TODO:EFFECTS:addSymSortRef"--**TODO:EFFECTS:ASKNIKI**-+ What is `isBind`,`pushConsBind` in Constraint.hs?---3. Suitable signatures for monadic operators--### RHProp--a. Following `RProp` we should have-- * RHProp := x1:t1,...,xn:tn -> World--b. Where `World` is a _spatial conjunction_ of-- * WPreds : (h v1 ... vn), h2, ...- * Wbinds : x1 := T1, x2 := T2, ...--c. Such that each `World` has _at most one_ `WPred` (that is _not rigid_ i.e. can be solved for.)--**Problem:** rejigger _inference_ to account for parameters in heap variables.----### RPoly (---> RProp)--Per Niki:-- RProp := x1:t1,...,xn:tn -> RType--with the 'predicate' application implicitly buried as a `ur_pred` inside the RType--For example, we represent-- [a]<p>--as-- RApp [] a (RPoly [(h:a)] {v:a<p>}) true--which is the `RTycon` for lists `[]` applied to:--+ Tyvar `a`--+ RPoly with:- * _params_ `h:a`- * _body_ `{v:a<p> | true}` which is really, `RVar a {ur_reft = true, ur_pred = (Predicate 'p' with params 'h')}`--+ Outer refinement `true`--------**Heap Propositions** `HProp`--```haskell-CP := l :-> T * CP -- Concrete Heap- | emp--HP := CP - | CP * H -- Heap Variable-```--That is, an `HProp` is of the form:-- H * l1 |-> T1 * ... * ln |-> Tn--or-- l1 |-> T1 * ... * ln |-> Tn--I am disallowing multiple variables because it causes problems...---**Abstractly Refined ST/IO**--```haskell-data IO a <Pre :: HProp, Post :: a -> HProp>-```--**Refined Monadic Operators**--```haskell-return :: forall a, <H :: HProp>.- a -> IO <H, \_ -> H> a--(>>=) :: forall a, b, <P :: HProp, Q :: a -> HProp, R :: b -> HProp>.- IO<P, Q> a -> (x:a -> IO<Q x, R> b) -> IO<P, R> b-```--**Q1.** How does LH *reason* about `HProp`?--Via subtyping as always, so:-- forall i. Γ |- Ti <: Ti'- ------------------------------------ Γ |- *_i li :-> Ti <: *_i li -> Ti'--For this, we need to put in explicit `HProp` instantiations, just like-tyvar (α) and predvar (π) instinstatntiations. This is doable with a-pre-pass that generates and solves `HProp` constraints as follows:--1. At each instantiation, make up _fresh_ variables `h`-2. Treat _bound_ heap-variables as **constants**-3. Instantiation yields a set of constraints over `h`-4. Solve constraints via algorithm below.--**Q2.** Can you _name_ values inside `HProp`?--Nope. There's no reason for this, but its tedious to have to make up-new heap binders and what not. Clutters stuff. This is _slightly_-problematic. For example, how do you write a function of the form:--```haskell-incr :: p:IORef Int -> IO Int-```--which _increments_ the value stored at the reference? Solution is slightly-clunky: rather than the _implicit_ heap binder, add an explicit pure parameter:--```haskell-incr :: p:IORef Int -> i:Int -> IO {v:Int| v = i} <p |-> {v = i}, p |-> {v = i + 1}>-```--**Q3.** How to relate `Post`-condition to the `Pre`-conditions?--Note that the `Post`-condition is a unary predicate -- i.e. _does not_-refer to the input world. How then do we relate the input and output heaps?-As above: _name_ the values of the input heap that you care about, and then-relate `Post` to `Pre` via the name.--**Q4.** How to _read_ values off the heap?--Given that we don't have heap binders, this might seem like a problem? Not-really. Just write signatures like:-- read :: IORef a -> IO a--aha, but there's a problem: the `a` is too _coarse_ or flow-insensitive: it-holds a supertype of all the values written at the location, as opposed to the-_current_ value. No matter, abstract refinements to the rescue:-- read :: forall <I :: a -> Prop>.- p:IORef a -> IO <p |-> a<I>, p |-> a<I>> a<I>--**Q5.** How do you do _subtyping_ on heaps/frame rule?--Wait, how do I write _compositional_ signatures that only talk about a-particular part of the state but allow me to say _other_ parts are unmodified-etc? Don't you need heap subtyping? No: we can make the frame rule explicit by-abstracting over heaps:-- read :: forall <I :: a -> Prop, H :: HProp>.- p:IORef a -> IO <p |-> a<I> * H, p |-> a<I> * H> a<I>--**Q6.** How to solve heap constraints?--Heap constraints are of the form:--+ (C0) `ch1 = ch2` -- constants-+ (C1) `H1 * ch1 = ch2` -- 1-variable-+ (C2) `H1 * ch1 = H2 * ch2` -- 2-variable--Here, each `ch` is of the form:-- l1 |-> τ1 * ... * ln -> τn * A1 * ... * An--where each `Ai` is a _rigid_ or quantified heap var that is atomic,-i.e. cannot be further solved for. For solving, we throw away _all_-refinements, and just use the shape τ.--```-solve :: Sol -> [Constraint] -> Maybe Sol-solve σ [] - = Just σ-solve σ (c:cs)- = case c of- C0 ch1 ch2 ->- if ch1 `equals` ch2 then- -- c is trivially SAT,- solve σ cs- else- -- c and hence all constraints are unsat- Nothing-- C1 (H1 * ch1) ch2 ->- if ch1 `subset` ch2 then- let σ' = [H1 := c2 `minus` c1]- solve (σ . σ') (σ' <$> cs)- else- -- c and hence all constraints are unsat- Nothing-- C2 (H1 * ch1) (H2 * ch2) ->- let H = fresh heap variable- let σ' = [H1 := H * ch2, H2 := H * ch1]- solve (σ . σ') (σ' <$> cs)-```----PROJECT: (OLD) HTT style ST/IO reasoning with Abstract Refinements----------------------------------------------------------------------Can we use abstract refinements to do "stateful reasoning",-e.g. about stuff in `IO` ? For example, to read files, this-is the API:-- open :: FilePath -> IO Handle- read :: Handle -> IO String- write :: Handle -> String -> IO ()- close :: Handle -> IO ()--The catch is that:--+ `read` and `write` require the `Handle` to be in an "open" state,-+ which is the state of the `Handle` returned by `open`,-+ while `close` presumably puts the `Handle` in a "closed" state.--So, suppose we parameterize IO with two predicates a `Pre` and `Post` condition-- data IO a <Pre :: World -> Prop> <Post :: a -> World -> World -> Prop>--where `World` is some abstract type denoting the global machine state.-Now, it should be possible to give types like:-- (>>=) :: IO a <P, Q> -> (x:a -> IO b<Q x, R>) -> IO b<P, R>- return :: a -> IO a <P, P>--which basically state whats going on with connecting the conditions, and then,-give types to the File API:-- open :: FilePath -> IO Handle <\_ -> True> <\h _ w -> (IsOpen h w)>- read :: h:Handle -> IO String <\w -> (IsOpen h w)> <\_ _ w -> (IsOpen h w)>- close :: h:Handle -> IO () <\w -> (IsOpen h w)> <\_ _ w -> not (IsOpen h w)>--Wonder if something like this would work?--Niki:-My question is how do you make Q from a post-condition (Q :: a -> Word -> Word -> Prop)-to a pre-condition.-I guess you need to apply a value x :: a and a w :: Word to write (a -> IO b<Q x w, R>).--I think the problem is that the "correct" values x and w are not "in scope"---So assume-- data IO a <P :: Word -> Prop, Q: a -> Word -> Word -> Prop>- = IO (x:Word<P> -> (y:a, Word<Q y x>))--and you want to type-- bind :: IO a <P,Q> -> (a -> IO b <Q x w, R>) -> IO b <P,R>- bind (IO m) k = IO $ \s -> case m s of- (a, s') -> unIO (k a) s'---You have-- IO m :: IO a <P. Q> => m :: xx:Word <P> -> (y:a, Word <Q y xx>)--you can assume-- s:: Word <P>--so-- m s :: (y:a, Word <Q y s>)- k a :: IO b <Q x w, R>- uniIO (k a) :: z:Word <Q x w> -> (xx:b, Word <R xx z>)--and we want-- (uniIO k a) s :: (xx:b , Word <R xx s>)--so basically we need-- P => Q x w--to be able to make the final application--**Ranjit**-You are right. We need to convert the "post" of the first action into the "pre"-of the second, which is a problem since the former takes three, parameters while-the latter takes only one.--BUT, how about this (basically, all you need is an EXISTS).-- -- | the type for `return` says that the output world satisfies- -- whatever predicate the input world satisfied.-- return :: a -> IO a <P, {\_ _ w' -> (P w')}>-- -- | the type for `bind` says that its action requires as input a world that satisfies- -- Q (for SOME input world w0) and produces as output an R world.- (>>=) :: IO a <P, Q>- -> (x:a -> \exists w0:World. IO b<{\w -> (Q x w0 w)}, R>)- -> IO b<P, {\xb w w' -> \exists xa:a w0:World<Q xa w>.(R xb w0 w')}>----Basically, I am using exists in the same way as in the "compose"--https://github.com/ucsd-progsys/liquidhaskell/blob/master/tests/pos/funcomposition.hs--to name the intermediate worlds and results (after all, this seems-like a super fancy version of `.` ) -- may have not put them in the-right place...--Btw, the existential is also how the HOARE rule for strongest postcondition works,-if you recall:-- {P} x := e {exists x'. P[x'/x] /\ x = e[x'/x]}-----One of the hardest steps seem to type the monad function (>>=):---So, suppose we parameterize IO with two predicates a `Pre` and `Post` condition-- data IO a <Pre :: World -> Prop> <Post :: a -> World -> World -> Prop>--where `World` is some abstract type denoting the global machine state.-Now, it should be possible to give types like:-- (>>=) :: IO a <P, Q> -> (a -> IO b<Q, R>) -> IO b<P, R>- return :: a -> IO a <P, P>----My question is how do you make Q from a post-condition (Q :: a -> Word -> Word -> Prop)-to a pre-condition.-I guess you need to apply a value x :: a and a w :: Word to write (a -> IO b<Q x w, R>).--I think the problem is that the "correct" values x and w are not "in scope"---So assume-data IO a <P :: Word -> Prop, Q: a -> Word -> Word -> Prop> = IO (x:Word<P> -> (y:a, Word<Q y x>))--and you want to type--bind :: IO a <P,Q> -> (a -> IO b <Q x w, R>) -> IO b <P,R>-bind (IO m) k = IO $ \s -> case m s of (a, s') -> (unIO (k a)) s'--You have--IO m :: IO a <P. Q> - => m :: xx:Word <P> -> (y:a, Word <Q y xx>)--you can assume-s:: Word <P>--so-m s :: (y:a, Word <Q y s>)--k a :: IO b <Q x w, R>--uniIO (k a) :: z:Word <Q x w> -> (xx:b, Word <R xx z>)--and we want-(uniIO k a) s :: (xx:b , Word <R xx s>)--so basically we need-P => Q x w-to be able to make the final application---bind :: ST a <P,Q> -> (a -> ST b <Q x w, R>) -> ST b <P,R>-bind (ST f1) k = ST $ \s0 -> let (x, s1) = f1 s0 - ST f2 = k x- (y, s2) = f2 s1- in- (y, s2)---PROJECT: Using `Dynamic` + Refinements for Mixed Records-----------------------------------------------------------Haskell has a class (and related functions)-- toDyn :: (Typeable a) => a -> Dynamic- fromDyn :: (Typeable a) => Dynamic -> Maybe a--Q: How to encode *heterogeneous* maps like:-- d1 = { "name" : "Ranjit"- , "age" : 36- , "alive" : True- }-- and also:-- d2 = { "name" : "Jupiter"- , "position": 5- }-- so that you can write generic *duck-typed* functions like-- showName :: Dict -> String-- and write-- showName d1- showName d2-- or even-- map showName [d1, d2]--Step 1: Encode dictionary as vanilla Haskell type-- type Dict <Q :: String -> Dynamic -> Prop> = Map String Dynamic <Q>- empty :: Dict- put :: (Dynamic a) => String -> a -> Dict -> Dict- get :: (Dynamic a) => String -> Dict -> Dict--Step 2: **Create** dictionaries-- d1 = put "name" "RJ"- $ put "age" 36- $ put "alive" True- $ empty-- d1 = put "name" "Jupiter"- $ put "pos" 5- $ empty--Step 3: **Lookup** dictionaries-- showName :: Dict -> String- showName d = get "name" d-- -- TODO: how to support- showName :: Dict -> Dict- incrAge d = put "age" (n + 1) d- where- n = get "age" d-- -- TODO: how to support- concat :: Dict -> Dict -> Dict--Step 4: Can directly, without any casting nonsense, call-- showName d1- showName d2--Need to reflect *Haskell Type* (or at least, `TypeRep` values)-inside logic, so you can write measures like-- measure TypeOf :: a -> Type--and use it to define refinements like-- (TypeOf v = Int)--(TODO: too bad we don't have relational measures... or multi-param measures ... yet!)--which we can macro up thus.-- predicate HasType V T = (TypeOf V = T)-- predicate Fld K V N T = (K = N => (HasType V T))--Step 5: Refined Signatures for `Dict` API-- put :: (Dynamic a) => key:String- -> {value:a | (Q key value)}- -> d:Dict <Q /\ {\k _ -> k /= key}>- -> Dict <Q /\ {\k v -> (Fld k v key a)}>-- get :: (Dynamic a) => key:String- -> d:Dict <{\k v -> (Fld k v key a)}>- -> a--Step 6: Now, for example, we should be able to type our dictionaries as-- {-@ d1 :: Dict<Q1> @-}--where-- Q1 == \k v -> Fld k v "name" String /\- Fld k v "age" Int /\- Fld k v "alive" Bool --and-- {-@ d2 :: Dict<Q2> @-}--where-- Q2 == \k v -> Fld k v "name" String /\- Fld k v "pos" Int /\--**TODO:**--+ add support for `Type` inside logic- + needed for `TypeOf` measure, equality checks- + requires doing type-substitutions inside refinements--+ add support for- + update [isn't that just `put`?]- + concat--+ add support traversals (cf. *Ur*)- - Fold (over all fields, eg. to serialize into a String)- - Map? (transform all fields to serialize) toDB?- - Filter (takes a predicate that should only read valid columns of the record)---PROJECT: Equational Reasoning--------------------------------e.g. Type class laws.--Many type-classes come with a set of laws that instances are expected-to abide by, e.g.--```-fmap id == id--fmap (f . g) == fmap f . fmap g-```--```-mappend mempty x = x--mappend x mempty = x--mappend x (mappend y z) = mappend (mappend x y) z-```--**Strategy**--**1. Representing Proofs**--```-data Proof = Proof -- void, pure refinement--type Pf P = {v:Proof | P}--type Eq X Y = Pf (X == Y)-```--**2. Combining Proofs**--```-bound Imp P Q R = P => Q => R--eq, imp :: (Imp P Q R) => Pf P -> Pf Q -> Pf R--refl :: x:a -> Eq a x x-```--**3. Axiomatizing arithmetic**--```-add :: x:Int -> y:Int -> {z:Int | z = x + y} -> Eq (x + y) z-add x y z = auto-```---**Example 1: Arithmetic**--Lets drill in: how to represent the following "equational" proof in LH?--```- (1 + 2) + (3 + 4) -- e0-- { 1 + 2 == 3}-- == 3 + (3 + 4) -- e1-- { 3 + 4 == 7}-- == 3 + 7 -- e2-- { 3 + 7 == 10}-- == 10 -- e3-```--Now the above proof looks like this:--```-e0 :: Int-e0 = (1 + 2) + (3 + 4)--prop :: Eq e0 10-prop = (((refl e0 `imp` (add 1 2 3)) -- :: Eq e0 (3 + (3 + 4))-- `imp` (add 3 4 7)) -- :: Eq e0 (3 + 7)-- `imp` (add 3 7 10)) -- :: Eq e0 10 -```---**Example 2: Lists**--A more interesting example: Lets prove `prop_app_nil`:-- prop_app_nil: forall xs. append xs [] = xs--The definition of--```-append [] ys = ys-append (x:xs) ys = x : append xs ys-```--yields the *axioms*--```-append_nil :: ys:_ -> Eq (append [] ys) ys-append_cons :: x:_ -> xs:_ -> ys:_ -> Eq (append (x:xs) ys) (x : append xs ys)-```--Code on left, "equations" on right.--```-prop_app_nil :: xs:[a] -> Eq (append xs []) xs--prop_app_nil [] = refl (append [] []) - -- append [] []- `by` (append_nil []) -- { append_nil [] } - -- == [] --prop_app_nil (x:xs) = refl (append (x:xs) []) - -- append (x:xs) []- `by` (append_cons x xs []) -- { append_cons x xs [] }- -- == x : append xs []- `by` (prop_app_nil xs) -- { IH: prop_app xs }- -- == x : xs-```--**Example 4: Append Associates**---```-prop_app_assoc :: xs:_ -> ys:_ -> zs:_ ->- Eq ((xs ++ ys) ++ zs) (xs ++ (ys ++ zs))--prop_app_assoc [] ys zs- ([] ++ ys) ++ zs- { append_nil _ } - == ys ++ zs- { append_nil _ }- == [] ++ (ys ++ zs)--prop_app_assoc (x:xs) ys zs- ((x:xs) ++ ys) ++ zs- { append_cons _ _ _ } - == (x : (xs ++ ys)) ++ zs- { append_cons _ _ _ }- == x : ((xs ++ ys) ++ zs)- { prop_app_assoc _ _ _ }- == x : (xs ++ (ys ++ zs))- { append_cons _ _ _ }- == (x : xs) ++ (ys ++ zs)-```---**Example 4: Map Fusion**--Lets go fancier:--- forall xs. map (f . g) xs = (map f . map g) xs--Here's the classical (?) equational proof:--```-map (f . g) [] - { map_nil (f . g) }- == []- { map_nil f }- == map f []- { map_nil g }- == map f (map g [])- { dot f g }- == (map f . map g) []--map (f . g) (x:xs) - { map_cons (f . g) x xs }- == (f . g) x : map (f . g) xs- { map_dot f g xs }- == (f . g) x : (map f . map g) xs- { dot (map f) (map g) }- == (f . g) x : map f (map g xs)- { dot f g }- == f (g x) : map f (map g xs)- {map_cons f (g x) (map g xs) }- == map f (g x : map g xs)- {map_cons g x xs}- == map f (map g (x : xs))- { dot (map f) (map g) }- == (map f . map g) (x : xs)-```--Formalize thus (with functions/axioms)--```-map f [] = [] -- map_nil-map f (x:xs) = f x : map f xs -- map_cons--(f . g) x = f (g x) -- dot-```--Now, we formalize map-fusion as:--```-map_fusion :: f:_ -> g:_ -> xs:_ ->- Eq (map (f . g) xs) (map f . map g) xs--map_fusion f g [] = map_dot_nil f g-map_fusion f g (x:xs) = map_dot_cons f g x xs-```--The hard work happens in the two "lemmas"--```-map_dot_nil :: f:_ -> g:_ ->- Eq (map (f . g) []) ((map f . map g) [])-map_dot_nil f g- = refl (map (f . g) []) - -- map (f . g) []- `by` (map_nil (f . g))- -- == []- `by` (map_nil f)- -- == map f []- `by` (map_nil g)- -- == map f (map g [])- `by` (dot f g)- -- == (map f . map g) []-```--and--```-map_dot_cons :: f:_ -> g:_ -> x:_ -> xs:_ ->- Eq (map (f . g) (x:xs)) ((map f . map g) (x:xs))-map_dot_cons f g x xs- = refl (map (f . g) (x:xs))- -- map (f . g) (x : xs)- `by` (map_cons (f . g) x xs)- -- == (f . g) x : map (f . g) xs- `by` (map_dot f g xs)- -- == (f . g) x : (map f . map g) xs- `by` (dot (map f) (map g))- -- == (f . g) x : map f (map g xs)- `by` (dot f g)- -- == f (g x) : map f (map g xs)- `by` (map_cons f (g x) (map g xs))- -- == map f (g x : map g xs)- `by` (map_cons g x xs)- -- == map f (map g (x : xs))- `by` (dot (map f) (map g))- -- == (map f . map g) (x : xs)-```----GHC 7.10------------ **DONE** singleton type classes represented by newtype- - tried to work around by translating-- foo `cast` (co :: a -> b ~ Foo)-- to-- D:Foo foo-- but it still breaks when we don't have an LH class decl- - without LH class decl we never see D:Foo, so it doesn't go in CGEnv- - SOLUTION: put ALL visible dict constructors in CGEnv--- `cast`s are used more often and we seem to lose information..- - seems particularly problematic with ST--- srcloc annotations- - -g adds SourceNotes, but the html output is borked- - in particular, infix operators aren't annotated correctly (at all?)- - are we missing some SrcLocs??- - clearly not, if you look at the output of-- ghc -g -ddump-ds -dppr-ticks <file.hs>-- somewhere along our pipeline the ticks are either being dropped,- or the SrcSpans don't quite match the way they used to...--- termination metrics are required in a few places where they were not previously- - my guess is that ghc's behaviour for grouping functions in a `Rec` binder have changed-
@@ -1,9 +0,0 @@-rem Copy runtime DLLs --echo "" | stack exec -- where libstdc++-6.dll > lib.txt-echo "" | stack exec -- where libgcc_s_seh-1.dll >> lib.txt-echo "" | stack exec -- where libwinpthread-1.dll >> lib.txt--FOR /F %%I IN (lib.txt) DO copy /Y "%%I" .\--del /q lib.txt
@@ -1,57 +0,0 @@-platform: x64--init:-- git --version- -install:-# http://help.appveyor.com/discussions/problems/6312-curl-command-not-found-- set PATH=%PATH%;C:\Program Files\Git\mingw64\bin--# Update GIT submodules-- git submodule update --init --recursive--# Download latest stable Stack tool-- curl -sS -ostack.zip -L --insecure https://get.haskellstack.org/stable/windows-x86_64.zip-- 7z x stack.zip stack.exe-- stack --version--# Install Microsoft Z3 from NuGet-# - nuget install z3x64win -Version 4.8.7 -# - dotnet add C:\projects\liquidhaskell\ package Microsoft.Z3.x64 --version 4.8.7-# - set PATH=%PATH%;%cd%;%cd%\z3x64win.4.5.0.1\tools-# - z3 --version--# Download latest stable z3-- curl -sS -oz3.zip -L --insecure https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-win.zip-- 7z x z3.zip-- echo %CD%-- DIR-- set PATH=%PATH%;C:\projects\liquidhaskell\z3-4.8.7-x64-win\bin;C:\projects\liquidhaskell-- z3 --version---build_script:-# Build LiquidHaskell (the legacy executable)-# until https://gitlab.haskell.org/ghc/ghc/issues/17236 is fixed.-- echo "" | rm -rf .stack-work-- echo "" | stack --no-terminal build --ghc-options="-fexternal-interpreter" liquidhaskell:lib --flag liquidhaskell:no-plugin --copy-bins --local-bin-path .-- echo "" | stack --no-terminal build liquid-fixpoint:exe:fixpoint liquidhaskell:exe:liquid --flag liquidhaskell:no-plugin --copy-bins --local-bin-path .--# Copy runtime DLLs-- call appveyor-copy.bat--# Test if they are working-- fixpoint --version-- liquid --version--# ZIP execturable-- 7z a liquidhaskell.zip liquid.exe fixpoint.exe .\include\CoreToLogic.lg LICENSE LICENSE_Z3 libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll--# Run the tests (using the legacy executable)-test_script:-- echo "" | stack --no-terminal test liquidhaskell:liquidhaskell-parser --fast --flag liquidhaskell:no-plugin-- echo "" | stack --no-terminal test liquidhaskell:test --fast --flag liquidhaskell:no-plugin --ta="--liquid-runner \"stack --compiler=ghc-8.10.7 --silent exec -- liquid\"" --test-arguments "-p Micro"--artifacts:-- path: liquidhaskell.zip- name: LiquidHaskell
@@ -1,4 +0,0 @@-Changes:--[base/Data/List.hs]-findIndices: Change Int# to Int
@@ -1,279 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Control.Applicative--- Copyright : Conor McBride and Ross Paterson 2005--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ This module describes a structure intermediate between a functor and--- a monad (technically, a strong lax monoidal functor). Compared with--- monads, this interface lacks the full power of the binding operation--- '>>=', but------ * it has more instances.------ * it is sufficient for many uses, e.g. context-free parsing, or the--- 'Data.Traversable.Traversable' class.------ * instances can perform analysis of computations before they are--- executed, and thus produce shared optimizations.------ This interface was introduced for parsers by Niklas Röjemo, because--- it admits more sharing than the monadic interface. The names here are--- mostly based on parsing work by Doaitse Swierstra.------ For more details, see /Applicative Programming with Effects/,--- by Conor McBride and Ross Paterson, online at--- <http://www.soi.city.ac.uk/~ross/papers/Applicative.html>.--module Control.Applicative (- -- * Applicative functors- Applicative(..),- -- * Alternatives- Alternative(..),- -- * Instances- Const(..), WrappedMonad(..), WrappedArrow(..), ZipList(..),- -- * Utility functions- (<$>), (<$), (<**>),- liftA, liftA2, liftA3,- optional,- ) where--import Prelude hiding (id,(.))--import Control.Category-import Control.Arrow (Arrow(arr, (&&&)), ArrowZero(zeroArrow), ArrowPlus((<+>)))-import Control.Monad (liftM, ap, MonadPlus(..))-import Control.Monad.Instances ()-#ifndef __NHC__-import Control.Monad.ST.Safe (ST)-import qualified Control.Monad.ST.Lazy.Safe as Lazy (ST)-#endif-import Data.Functor ((<$>), (<$))-import Data.Monoid (Monoid(..))--#ifdef __GLASGOW_HASKELL__-import GHC.Conc (STM, retry, orElse)-#endif--infixl 3 <|>-infixl 4 <*>, <*, *>, <**>---- | A functor with application, providing operations to------ * embed pure expressions ('pure'), and------ * sequence computations and combine their results ('<*>').------ A minimal complete definition must include implementations of these--- functions satisfying the following laws:------ [/identity/]--- @'pure' 'id' '<*>' v = v@------ [/composition/]--- @'pure' (.) '<*>' u '<*>' v '<*>' w = u '<*>' (v '<*>' w)@------ [/homomorphism/]--- @'pure' f '<*>' 'pure' x = 'pure' (f x)@------ [/interchange/]--- @u '<*>' 'pure' y = 'pure' ('$' y) '<*>' u@------ The other methods have the following default definitions, which may--- be overridden with equivalent specialized implementations:------ @--- u '*>' v = 'pure' ('const' 'id') '<*>' u '<*>' v--- u '<*' v = 'pure' 'const' '<*>' u '<*>' v--- @------ As a consequence of these laws, the 'Functor' instance for @f@ will satisfy------ @--- 'fmap' f x = 'pure' f '<*>' x--- @------ If @f@ is also a 'Monad', it should satisfy @'pure' = 'return'@ and--- @('<*>') = 'ap'@ (which implies that 'pure' and '<*>' satisfy the--- applicative functor laws).--class Functor f => Applicative f where- -- | Lift a value.- pure :: a -> f a-- -- | Sequential application.- (<*>) :: f (a -> b) -> f a -> f b-- -- | Sequence actions, discarding the value of the first argument.- (*>) :: f a -> f b -> f b- (*>) = liftA2 (const id)-- -- | Sequence actions, discarding the value of the second argument.- (<*) :: f a -> f b -> f a- (<*) = liftA2 const---- | A monoid on applicative functors.------ Minimal complete definition: 'empty' and '<|>'.------ If defined, 'some' and 'many' should be the least solutions--- of the equations:------ * @some v = (:) '<$>' v '<*>' many v@------ * @many v = some v '<|>' 'pure' []@-class Applicative f => Alternative f where- -- | The identity of '<|>'- empty :: f a- -- | An associative binary operation- (<|>) :: f a -> f a -> f a-- -- | One or more.- some :: f a -> f [a]- some v = some_v- where- many_v = some_v <|> pure []- some_v = (:) <$> v <*> many_v-- -- | Zero or more.- many :: f a -> f [a]- many v = many_v- where- many_v = some_v <|> pure []- some_v = (:) <$> v <*> many_v---- instances for Prelude types--instance Applicative Maybe where- pure = return- (<*>) = ap--instance Alternative Maybe where- empty = Nothing- Nothing <|> p = p- Just x <|> _ = Just x--instance Applicative [] where- pure = return- (<*>) = ap--instance Alternative [] where- empty = []- (<|>) = (++)--instance Applicative IO where- pure = return- (<*>) = ap--#ifndef __NHC__-instance Applicative (ST s) where- pure = return- (<*>) = ap--instance Applicative (Lazy.ST s) where- pure = return- (<*>) = ap-#endif--#ifdef __GLASGOW_HASKELL__-instance Applicative STM where- pure = return- (<*>) = ap--instance Alternative STM where- empty = retry- (<|>) = orElse-#endif--instance Applicative ((->) a) where- pure = const- (<*>) f g x = f x (g x)--instance Monoid a => Applicative ((,) a) where- pure x = (mempty, x)- (u, f) <*> (v, x) = (u `mappend` v, f x)--instance Applicative (Either e) where- pure = Right- Left e <*> _ = Left e- Right f <*> r = fmap f r---- new instances--newtype Const a b = Const { getConst :: a }--instance Functor (Const m) where- fmap _ (Const v) = Const v--instance Monoid m => Applicative (Const m) where- pure _ = Const mempty- Const f <*> Const v = Const (f `mappend` v)--newtype WrappedMonad m a = WrapMonad { unwrapMonad :: m a }--instance Monad m => Functor (WrappedMonad m) where- fmap f (WrapMonad v) = WrapMonad (liftM f v)--instance Monad m => Applicative (WrappedMonad m) where- pure = WrapMonad . return- WrapMonad f <*> WrapMonad v = WrapMonad (f `ap` v)--instance MonadPlus m => Alternative (WrappedMonad m) where- empty = WrapMonad mzero- WrapMonad u <|> WrapMonad v = WrapMonad (u `mplus` v)--newtype WrappedArrow a b c = WrapArrow { unwrapArrow :: a b c }--instance Arrow a => Functor (WrappedArrow a b) where- fmap f (WrapArrow a) = WrapArrow (a >>> arr f)--instance Arrow a => Applicative (WrappedArrow a b) where- pure x = WrapArrow (arr (const x))- WrapArrow f <*> WrapArrow v = WrapArrow (f &&& v >>> arr (uncurry id))--instance (ArrowZero a, ArrowPlus a) => Alternative (WrappedArrow a b) where- empty = WrapArrow zeroArrow- WrapArrow u <|> WrapArrow v = WrapArrow (u <+> v)---- | Lists, but with an 'Applicative' functor based on zipping, so that------ @f '<$>' 'ZipList' xs1 '<*>' ... '<*>' 'ZipList' xsn = 'ZipList' (zipWithn f xs1 ... xsn)@----newtype ZipList a = ZipList { getZipList :: [a] }--instance Functor ZipList where- fmap f (ZipList xs) = ZipList (map f xs)--instance Applicative ZipList where- pure x = ZipList (repeat x)- ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)---- extra functions---- | A variant of '<*>' with the arguments reversed.-(<**>) :: Applicative f => f a -> f (a -> b) -> f b-(<**>) = liftA2 (flip ($))---- | Lift a function to actions.--- This function may be used as a value for `fmap` in a `Functor` instance.-liftA :: Applicative f => (a -> b) -> f a -> f b-liftA f a = pure f <*> a---- | Lift a binary function to actions.-liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c-liftA2 f a b = f <$> a <*> b---- | Lift a ternary function to actions.-liftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d-liftA3 f a b c = f <$> a <*> b <*> c---- | One or none.-optional :: Alternative f => f a -> f (Maybe a)-optional v = Just <$> v <|> pure Nothing
@@ -1,350 +0,0 @@-{-# LANGUAGE Trustworthy #-}--------------------------------------------------------------------------------- |--- Module : Control.Arrow--- Copyright : (c) Ross Paterson 2002--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Basic arrow definitions, based on--- * /Generalising Monads to Arrows/, by John Hughes,--- /Science of Computer Programming/ 37, pp67-111, May 2000.--- plus a couple of definitions ('returnA' and 'loop') from--- * /A New Notation for Arrows/, by Ross Paterson, in /ICFP 2001/,--- Firenze, Italy, pp229-240.--- These papers and more information on arrows can be found at--- <http://www.haskell.org/arrows/>.--module Control.Arrow (- -- * Arrows- Arrow(..), Kleisli(..),- -- ** Derived combinators- returnA,- (^>>), (>>^),- (>>>), (<<<), -- reexported- -- ** Right-to-left variants- (<<^), (^<<),- -- * Monoid operations- ArrowZero(..), ArrowPlus(..),- -- * Conditionals- ArrowChoice(..),- -- * Arrow application- ArrowApply(..), ArrowMonad(..), leftApp,- -- * Feedback- ArrowLoop(..)- ) where--import Prelude hiding (id,(.))--import Control.Monad-import Control.Monad.Fix-import Control.Category--infixr 5 <+>-infixr 3 ***-infixr 3 &&&-infixr 2 +++-infixr 2 |||-infixr 1 ^>>, >>^-infixr 1 ^<<, <<^---- | The basic arrow class.------ Minimal complete definition: 'arr' and 'first', satisfying the laws------ * @'arr' id = 'id'@------ * @'arr' (f >>> g) = 'arr' f >>> 'arr' g@------ * @'first' ('arr' f) = 'arr' ('first' f)@------ * @'first' (f >>> g) = 'first' f >>> 'first' g@------ * @'first' f >>> 'arr' 'fst' = 'arr' 'fst' >>> f@------ * @'first' f >>> 'arr' ('id' *** g) = 'arr' ('id' *** g) >>> 'first' f@------ * @'first' ('first' f) >>> 'arr' 'assoc' = 'arr' 'assoc' >>> 'first' f@------ where------ > assoc ((a,b),c) = (a,(b,c))------ The other combinators have sensible default definitions,--- which may be overridden for efficiency.--class Category a => Arrow a where-- -- | Lift a function to an arrow.- arr :: (b -> c) -> a b c-- -- | Send the first component of the input through the argument- -- arrow, and copy the rest unchanged to the output.- first :: a b c -> a (b,d) (c,d)-- -- | A mirror image of 'first'.- --- -- The default definition may be overridden with a more efficient- -- version if desired.- second :: a b c -> a (d,b) (d,c)- second f = arr swap >>> first f >>> arr swap- where- swap :: (x,y) -> (y,x)- swap ~(x,y) = (y,x)-- -- | Split the input between the two argument arrows and combine- -- their output. Note that this is in general not a functor.- --- -- The default definition may be overridden with a more efficient- -- version if desired.- (***) :: a b c -> a b' c' -> a (b,b') (c,c')- f *** g = first f >>> second g-- -- | Fanout: send the input to both argument arrows and combine- -- their output.- --- -- The default definition may be overridden with a more efficient- -- version if desired.- (&&&) :: a b c -> a b c' -> a b (c,c')- f &&& g = arr (\b -> (b,b)) >>> f *** g--{-# RULES-"compose/arr" forall f g .- (arr f) . (arr g) = arr (f . g)-"first/arr" forall f .- first (arr f) = arr (first f)-"second/arr" forall f .- second (arr f) = arr (second f)-"product/arr" forall f g .- arr f *** arr g = arr (f *** g)-"fanout/arr" forall f g .- arr f &&& arr g = arr (f &&& g)-"compose/first" forall f g .- (first f) . (first g) = first (f . g)-"compose/second" forall f g .- (second f) . (second g) = second (f . g)- #-}---- Ordinary functions are arrows.--instance Arrow (->) where- arr f = f- first f = f *** id- second f = id *** f--- (f *** g) ~(x,y) = (f x, g y)--- sorry, although the above defn is fully H'98, nhc98 can't parse it.- (***) f g ~(x,y) = (f x, g y)---- | Kleisli arrows of a monad.-newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }--instance Monad m => Category (Kleisli m) where- id = Kleisli return- (Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)--instance Monad m => Arrow (Kleisli m) where- arr f = Kleisli (return . f)- first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))- second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))---- | The identity arrow, which plays the role of 'return' in arrow notation.-returnA :: Arrow a => a b b-returnA = arr id---- | Precomposition with a pure function.-(^>>) :: Arrow a => (b -> c) -> a c d -> a b d-f ^>> a = arr f >>> a---- | Postcomposition with a pure function.-(>>^) :: Arrow a => a b c -> (c -> d) -> a b d-a >>^ f = a >>> arr f---- | Precomposition with a pure function (right-to-left variant).-(<<^) :: Arrow a => a c d -> (b -> c) -> a b d-a <<^ f = a <<< arr f---- | Postcomposition with a pure function (right-to-left variant).-(^<<) :: Arrow a => (c -> d) -> a b c -> a b d-f ^<< a = arr f <<< a--class Arrow a => ArrowZero a where- zeroArrow :: a b c--instance MonadPlus m => ArrowZero (Kleisli m) where- zeroArrow = Kleisli (\_ -> mzero)---- | A monoid on arrows.-class ArrowZero a => ArrowPlus a where- -- | An associative operation with identity 'zeroArrow'.- (<+>) :: a b c -> a b c -> a b c--instance MonadPlus m => ArrowPlus (Kleisli m) where- Kleisli f <+> Kleisli g = Kleisli (\x -> f x `mplus` g x)---- | Choice, for arrows that support it. This class underlies the--- @if@ and @case@ constructs in arrow notation.--- Minimal complete definition: 'left', satisfying the laws------ * @'left' ('arr' f) = 'arr' ('left' f)@------ * @'left' (f >>> g) = 'left' f >>> 'left' g@------ * @'left' f >>> 'arr' 'Left' = 'arr' 'Left' >>> f@------ * @'left' f >>> 'arr' ('id' +++ g) = 'arr' ('id' +++ g) >>> 'left' f@------ * @'left' ('left' f) >>> 'arr' 'assocsum' = 'arr' 'assocsum' >>> 'left' f@------ where------ > assocsum (Left (Left x)) = Left x--- > assocsum (Left (Right y)) = Right (Left y)--- > assocsum (Right z) = Right (Right z)------ The other combinators have sensible default definitions, which may--- be overridden for efficiency.--class Arrow a => ArrowChoice a where-- -- | Feed marked inputs through the argument arrow, passing the- -- rest through unchanged to the output.- left :: a b c -> a (Either b d) (Either c d)-- -- | A mirror image of 'left'.- --- -- The default definition may be overridden with a more efficient- -- version if desired.- right :: a b c -> a (Either d b) (Either d c)- right f = arr mirror >>> left f >>> arr mirror- where- mirror :: Either x y -> Either y x- mirror (Left x) = Right x- mirror (Right y) = Left y-- -- | Split the input between the two argument arrows, retagging- -- and merging their outputs.- -- Note that this is in general not a functor.- --- -- The default definition may be overridden with a more efficient- -- version if desired.- (+++) :: a b c -> a b' c' -> a (Either b b') (Either c c')- f +++ g = left f >>> right g-- -- | Fanin: Split the input between the two argument arrows and- -- merge their outputs.- --- -- The default definition may be overridden with a more efficient- -- version if desired.- (|||) :: a b d -> a c d -> a (Either b c) d- f ||| g = f +++ g >>> arr untag- where- untag (Left x) = x- untag (Right y) = y--{-# RULES-"left/arr" forall f .- left (arr f) = arr (left f)-"right/arr" forall f .- right (arr f) = arr (right f)-"sum/arr" forall f g .- arr f +++ arr g = arr (f +++ g)-"fanin/arr" forall f g .- arr f ||| arr g = arr (f ||| g)-"compose/left" forall f g .- left f . left g = left (f . g)-"compose/right" forall f g .- right f . right g = right (f . g)- #-}--instance ArrowChoice (->) where- left f = f +++ id- right f = id +++ f- f +++ g = (Left . f) ||| (Right . g)- (|||) = either--instance Monad m => ArrowChoice (Kleisli m) where- left f = f +++ arr id- right f = arr id +++ f- f +++ g = (f >>> arr Left) ||| (g >>> arr Right)- Kleisli f ||| Kleisli g = Kleisli (either f g)---- | Some arrows allow application of arrow inputs to other inputs.--- Instances should satisfy the following laws:------ * @'first' ('arr' (\\x -> 'arr' (\\y -> (x,y)))) >>> 'app' = 'id'@------ * @'first' ('arr' (g >>>)) >>> 'app' = 'second' g >>> 'app'@------ * @'first' ('arr' (>>> h)) >>> 'app' = 'app' >>> h@------ Such arrows are equivalent to monads (see 'ArrowMonad').--class Arrow a => ArrowApply a where- app :: a (a b c, b) c--instance ArrowApply (->) where- app (f,x) = f x--instance Monad m => ArrowApply (Kleisli m) where- app = Kleisli (\(Kleisli f, x) -> f x)---- | The 'ArrowApply' class is equivalent to 'Monad': any monad gives rise--- to a 'Kleisli' arrow, and any instance of 'ArrowApply' defines a monad.--newtype ArrowMonad a b = ArrowMonad (a () b)--instance ArrowApply a => Monad (ArrowMonad a) where- return x = ArrowMonad (arr (\_ -> x))- ArrowMonad m >>= f = ArrowMonad $- m >>> arr (\x -> let ArrowMonad h = f x in (h, ())) >>> app---- | Any instance of 'ArrowApply' can be made into an instance of--- 'ArrowChoice' by defining 'left' = 'leftApp'.--leftApp :: ArrowApply a => a b c -> a (Either b d) (Either c d)-leftApp f = arr ((\b -> (arr (\() -> b) >>> f >>> arr Left, ())) |||- (\d -> (arr (\() -> d) >>> arr Right, ()))) >>> app---- | The 'loop' operator expresses computations in which an output value--- is fed back as input, although the computation occurs only once.--- It underlies the @rec@ value recursion construct in arrow notation.--- 'loop' should satisfy the following laws:------ [/extension/]--- @'loop' ('arr' f) = 'arr' (\\ b -> 'fst' ('fix' (\\ (c,d) -> f (b,d))))@------ [/left tightening/]--- @'loop' ('first' h >>> f) = h >>> 'loop' f@------ [/right tightening/]--- @'loop' (f >>> 'first' h) = 'loop' f >>> h@------ [/sliding/]--- @'loop' (f >>> 'arr' ('id' *** k)) = 'loop' ('arr' ('id' *** k) >>> f)@------ [/vanishing/]--- @'loop' ('loop' f) = 'loop' ('arr' unassoc >>> f >>> 'arr' assoc)@------ [/superposing/]--- @'second' ('loop' f) = 'loop' ('arr' assoc >>> 'second' f >>> 'arr' unassoc)@------ where------ > assoc ((a,b),c) = (a,(b,c))--- > unassoc (a,(b,c)) = ((a,b),c)----class Arrow a => ArrowLoop a where- loop :: a (b,d) (c,d) -> a b c--instance ArrowLoop (->) where- loop f b = let (c,d) = f (b,d) in c---- | Beware that for many monads (those for which the '>>=' operation--- is strict) this instance will /not/ satisfy the right-tightening law--- required by the 'ArrowLoop' class.-instance MonadFix m => ArrowLoop (Kleisli m) where- loop (Kleisli f) = Kleisli (liftM fst . mfix . f')- where f' x y = f (x, snd y)
@@ -1,54 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Control.Category--- Copyright : (c) Ashley Yakeley 2007--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : ashley@semantic.org--- Stability : experimental--- Portability : portable---- http://hackage.haskell.org/trac/ghc/ticket/1773--module Control.Category where--import qualified Prelude--infixr 9 .-infixr 1 >>>, <<<---- | A class for categories.--- id and (.) must form a monoid.-class Category cat where- -- | the identity morphism- id :: cat a a-- -- | morphism composition- (.) :: cat b c -> cat a b -> cat a c--{-# RULES-"identity/left" forall p .- id . p = p-"identity/right" forall p .- p . id = p-"association" forall p q r .- (p . q) . r = p . (q . r)- #-}--instance Category (->) where- id = Prelude.id-#ifndef __HADDOCK__--- Haddock 1.x cannot parse this:- (.) = (Prelude..)-#endif---- | Right-to-left composition-(<<<) :: Category cat => cat b c -> cat a b -> cat a c-(<<<) = (.)---- | Left-to-right composition-(>>>) :: Category cat => cat a b -> cat b c -> cat a c-f >>> g = g . f
@@ -1,669 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , ForeignFunctionInterface- , MagicHash- , UnboxedTuples- , ScopedTypeVariables- #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}---------------------------------------------------------------------------------- |--- Module : Control.Concurrent--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (concurrency)------ A common interface to a collection of useful concurrency--- abstractions.-----------------------------------------------------------------------------------module Control.Concurrent (- -- * Concurrent Haskell-- -- $conc_intro-- -- * Basic concurrency operations-- ThreadId,-#ifdef __GLASGOW_HASKELL__- myThreadId,-#endif-- forkIO,-#ifdef __GLASGOW_HASKELL__- forkIOWithUnmask,- killThread,- throwTo,-#endif-- -- ** Threads with affinity- forkOn,- forkOnWithUnmask,- getNumCapabilities,- threadCapability,-- -- * Scheduling-- -- $conc_scheduling - yield, -- :: IO ()-- -- ** Blocking-- -- $blocking--#ifdef __GLASGOW_HASKELL__- -- ** Waiting- threadDelay, -- :: Int -> IO ()- threadWaitRead, -- :: Int -> IO ()- threadWaitWrite, -- :: Int -> IO ()-#endif-- -- * Communication abstractions-- module Control.Concurrent.MVar,- module Control.Concurrent.Chan,- module Control.Concurrent.QSem,- module Control.Concurrent.QSemN,- module Control.Concurrent.SampleVar,-- -- * Merging of streams-#ifndef __HUGS__- mergeIO, -- :: [a] -> [a] -> IO [a]- nmergeIO, -- :: [[a]] -> IO [a]-#endif- -- $merge--#ifdef __GLASGOW_HASKELL__- -- * Bound Threads- -- $boundthreads- rtsSupportsBoundThreads,- forkOS,- isCurrentThreadBound,- runInBoundThread,- runInUnboundThread,-#endif-- -- * GHC's implementation of concurrency-- -- |This section describes features specific to GHC's- -- implementation of Concurrent Haskell.-- -- ** Haskell threads and Operating System threads-- -- $osthreads-- -- ** Terminating the program-- -- $termination-- -- ** Pre-emption-- -- $preemption-- -- * Deprecated functions- forkIOUnmasked-- ) where--import Prelude--import Control.Exception.Base as Exception--#ifdef __GLASGOW_HASKELL__-import GHC.Exception-import GHC.Conc hiding (threadWaitRead, threadWaitWrite)-import qualified GHC.Conc-import GHC.IO ( IO(..), unsafeInterleaveIO, unsafeUnmask )-import GHC.IORef ( newIORef, readIORef, writeIORef )-import GHC.Base--import System.Posix.Types ( Fd )-import Foreign.StablePtr-import Foreign.C.Types-import Control.Monad ( when )--#ifdef mingw32_HOST_OS-import Foreign.C-import System.IO-#endif-#endif--#ifdef __HUGS__-import Hugs.ConcBase-#endif--import Control.Concurrent.MVar-import Control.Concurrent.Chan-import Control.Concurrent.QSem-import Control.Concurrent.QSemN-import Control.Concurrent.SampleVar--#ifdef __HUGS__-type ThreadId = ()-#endif--{- $conc_intro--The concurrency extension for Haskell is described in the paper-/Concurrent Haskell/-<http://www.haskell.org/ghc/docs/papers/concurrent-haskell.ps.gz>.--Concurrency is \"lightweight\", which means that both thread creation-and context switching overheads are extremely low. Scheduling of-Haskell threads is done internally in the Haskell runtime system, and-doesn't make use of any operating system-supplied thread packages.--However, if you want to interact with a foreign library that expects your-program to use the operating system-supplied thread package, you can do so-by using 'forkOS' instead of 'forkIO'.--Haskell threads can communicate via 'MVar's, a kind of synchronised-mutable variable (see "Control.Concurrent.MVar"). Several common-concurrency abstractions can be built from 'MVar's, and these are-provided by the "Control.Concurrent" library.-In GHC, threads may also communicate via exceptions.--}--{- $conc_scheduling-- Scheduling may be either pre-emptive or co-operative,- depending on the implementation of Concurrent Haskell (see below- for information related to specific compilers). In a co-operative- system, context switches only occur when you use one of the- primitives defined in this module. This means that programs such- as:---> main = forkIO (write 'a') >> write 'b'-> where write c = putChar c >> write c-- will print either @aaaaaaaaaaaaaa...@ or @bbbbbbbbbbbb...@,- instead of some random interleaving of @a@s and @b@s. In- practice, cooperative multitasking is sufficient for writing- simple graphical user interfaces. --}--{- $blocking-Different Haskell implementations have different characteristics with-regard to which operations block /all/ threads.--Using GHC without the @-threaded@ option, all foreign calls will block-all other Haskell threads in the system, although I\/O operations will-not. With the @-threaded@ option, only foreign calls with the @unsafe@-attribute will block all other threads.--Using Hugs, all I\/O operations and foreign calls will block all other-Haskell threads.--}--#ifndef __HUGS__-max_buff_size :: Int-max_buff_size = 1--mergeIO :: [a] -> [a] -> IO [a]-nmergeIO :: [[a]] -> IO [a]---- $merge--- The 'mergeIO' and 'nmergeIO' functions fork one thread for each--- input list that concurrently evaluates that list; the results are--- merged into a single output list. ------ Note: Hugs does not provide these functions, since they require--- preemptive multitasking.--mergeIO ls rs- = newEmptyMVar >>= \ tail_node ->- newMVar tail_node >>= \ tail_list ->- newQSem max_buff_size >>= \ e ->- newMVar 2 >>= \ branches_running ->- let- buff = (tail_list,e)- in- forkIO (suckIO branches_running buff ls) >>- forkIO (suckIO branches_running buff rs) >>- takeMVar tail_node >>= \ val ->- signalQSem e >>- return val--type Buffer a- = (MVar (MVar [a]), QSem)--suckIO :: MVar Int -> Buffer a -> [a] -> IO ()--suckIO branches_running buff@(tail_list,e) vs- = case vs of- [] -> takeMVar branches_running >>= \ val ->- if val == 1 then- takeMVar tail_list >>= \ node ->- putMVar node [] >>- putMVar tail_list node- else- putMVar branches_running (val-1)- (x:xs) ->- waitQSem e >>- takeMVar tail_list >>= \ node ->- newEmptyMVar >>= \ next_node ->- unsafeInterleaveIO (- takeMVar next_node >>= \ y ->- signalQSem e >>- return y) >>= \ next_node_val ->- putMVar node (x:next_node_val) >>- putMVar tail_list next_node >>- suckIO branches_running buff xs--nmergeIO lss- = let- len = length lss- in- newEmptyMVar >>= \ tail_node ->- newMVar tail_node >>= \ tail_list ->- newQSem max_buff_size >>= \ e ->- newMVar len >>= \ branches_running ->- let- buff = (tail_list,e)- in- mapIO (\ x -> forkIO (suckIO branches_running buff x)) lss >>- takeMVar tail_node >>= \ val ->- signalQSem e >>- return val- where- mapIO f xs = sequence (map f xs)-#endif /* __HUGS__ */--#ifdef __GLASGOW_HASKELL__--- ------------------------------------------------------------------------------ Bound Threads--{- $boundthreads- #boundthreads#--Support for multiple operating system threads and bound threads as described-below is currently only available in the GHC runtime system if you use the-/-threaded/ option when linking.--Other Haskell systems do not currently support multiple operating system threads.--A bound thread is a haskell thread that is /bound/ to an operating system-thread. While the bound thread is still scheduled by the Haskell run-time-system, the operating system thread takes care of all the foreign calls made-by the bound thread.--To a foreign library, the bound thread will look exactly like an ordinary-operating system thread created using OS functions like @pthread_create@-or @CreateThread@.--Bound threads can be created using the 'forkOS' function below. All foreign-exported functions are run in a bound thread (bound to the OS thread that-called the function). Also, the @main@ action of every Haskell program is-run in a bound thread.--Why do we need this? Because if a foreign library is called from a thread-created using 'forkIO', it won't have access to any /thread-local state/ - -state variables that have specific values for each OS thread-(see POSIX's @pthread_key_create@ or Win32's @TlsAlloc@). Therefore, some-libraries (OpenGL, for example) will not work from a thread created using-'forkIO'. They work fine in threads created using 'forkOS' or when called-from @main@ or from a @foreign export@.--In terms of performance, 'forkOS' (aka bound) threads are much more-expensive than 'forkIO' (aka unbound) threads, because a 'forkOS'-thread is tied to a particular OS thread, whereas a 'forkIO' thread-can be run by any OS thread. Context-switching between a 'forkOS'-thread and a 'forkIO' thread is many times more expensive than between-two 'forkIO' threads.--Note in particular that the main program thread (the thread running-@Main.main@) is always a bound thread, so for good concurrency-performance you should ensure that the main thread is not doing-repeated communication with other threads in the system. Typically-this means forking subthreads to do the work using 'forkIO', and-waiting for the results in the main thread.---}---- | 'True' if bound threads are supported.--- If @rtsSupportsBoundThreads@ is 'False', 'isCurrentThreadBound'--- will always return 'False' and both 'forkOS' and 'runInBoundThread' will--- fail.-foreign import ccall rtsSupportsBoundThreads :: Bool---{- | -Like 'forkIO', this sparks off a new thread to run the 'IO'-computation passed as the first argument, and returns the 'ThreadId'-of the newly created thread.--However, 'forkOS' creates a /bound/ thread, which is necessary if you-need to call foreign (non-Haskell) libraries that make use of-thread-local state, such as OpenGL (see "Control.Concurrent#boundthreads").--Using 'forkOS' instead of 'forkIO' makes no difference at all to the-scheduling behaviour of the Haskell runtime system. It is a common-misconception that you need to use 'forkOS' instead of 'forkIO' to-avoid blocking all the Haskell threads when making a foreign call;-this isn't the case. To allow foreign calls to be made without-blocking all the Haskell threads (with GHC), it is only necessary to-use the @-threaded@ option when linking your program, and to make sure-the foreign import is not marked @unsafe@.--}--forkOS :: IO () -> IO ThreadId--foreign export ccall forkOS_entry- :: StablePtr (IO ()) -> IO ()--foreign import ccall "forkOS_entry" forkOS_entry_reimported- :: StablePtr (IO ()) -> IO ()--forkOS_entry :: StablePtr (IO ()) -> IO ()-forkOS_entry stableAction = do- action <- deRefStablePtr stableAction- action--foreign import ccall forkOS_createThread- :: StablePtr (IO ()) -> IO CInt--failNonThreaded :: IO a-failNonThreaded = fail $ "RTS doesn't support multiple OS threads "- ++"(use ghc -threaded when linking)"--forkOS action0- | rtsSupportsBoundThreads = do- mv <- newEmptyMVar- b <- Exception.getMaskingState- let- -- async exceptions are masked in the child if they are masked- -- in the parent, as for forkIO (see #1048). forkOS_createThread- -- creates a thread with exceptions masked by default.- action1 = case b of- Unmasked -> unsafeUnmask action0- MaskedInterruptible -> action0- MaskedUninterruptible -> uninterruptibleMask_ action0-- action_plus = Exception.catch action1 childHandler-- entry <- newStablePtr (myThreadId >>= putMVar mv >> action_plus)- err <- forkOS_createThread entry- when (err /= 0) $ fail "Cannot create OS thread."- tid <- takeMVar mv- freeStablePtr entry- return tid- | otherwise = failNonThreaded---- | Returns 'True' if the calling thread is /bound/, that is, if it is--- safe to use foreign libraries that rely on thread-local state from the--- calling thread.-isCurrentThreadBound :: IO Bool-isCurrentThreadBound = IO $ \ s# ->- case isCurrentThreadBound# s# of- (# s2#, flg #) -> (# s2#, not (flg ==# 0#) #)---{- | -Run the 'IO' computation passed as the first argument. If the calling thread-is not /bound/, a bound thread is created temporarily. @runInBoundThread@-doesn't finish until the 'IO' computation finishes.--You can wrap a series of foreign function calls that rely on thread-local state-with @runInBoundThread@ so that you can use them without knowing whether the-current thread is /bound/.--}-runInBoundThread :: IO a -> IO a--runInBoundThread action- | rtsSupportsBoundThreads = do- bound <- isCurrentThreadBound- if bound- then action- else do- ref <- newIORef undefined- let action_plus = Exception.try action >>= writeIORef ref- bracket (newStablePtr action_plus)- freeStablePtr- (\cEntry -> forkOS_entry_reimported cEntry >> readIORef ref) >>=- unsafeResult- | otherwise = failNonThreaded--{- | -Run the 'IO' computation passed as the first argument. If the calling thread-is /bound/, an unbound thread is created temporarily using 'forkIO'.-@runInBoundThread@ doesn't finish until the 'IO' computation finishes.--Use this function /only/ in the rare case that you have actually observed a-performance loss due to the use of bound threads. A program that-doesn't need it's main thread to be bound and makes /heavy/ use of concurrency-(e.g. a web server), might want to wrap it's @main@ action in-@runInUnboundThread@.--Note that exceptions which are thrown to the current thread are thrown in turn-to the thread that is executing the given computation. This ensures there's-always a way of killing the forked thread.--}-runInUnboundThread :: IO a -> IO a--runInUnboundThread action = do- bound <- isCurrentThreadBound- if bound- then do- mv <- newEmptyMVar- mask $ \restore -> do- tid <- forkIO $ Exception.try (restore action) >>= putMVar mv- let wait = takeMVar mv `Exception.catch` \(e :: SomeException) ->- Exception.throwTo tid e >> wait- wait >>= unsafeResult- else action--unsafeResult :: Either SomeException a -> IO a-unsafeResult = either Exception.throwIO return-#endif /* __GLASGOW_HASKELL__ */--#ifdef __GLASGOW_HASKELL__--- ------------------------------------------------------------------------------ threadWaitRead/threadWaitWrite---- | Block the current thread until data is available to read on the--- given file descriptor (GHC only).------ This will throw an 'IOError' if the file descriptor was closed--- while this thread was blocked. To safely close a file descriptor--- that has been used with 'threadWaitRead', use--- 'GHC.Conc.closeFdWith'.-threadWaitRead :: Fd -> IO ()-threadWaitRead fd-#ifdef mingw32_HOST_OS- -- we have no IO manager implementing threadWaitRead on Windows.- -- fdReady does the right thing, but we have to call it in a- -- separate thread, otherwise threadWaitRead won't be interruptible,- -- and this only works with -threaded.- | threaded = withThread (waitFd fd 0)- | otherwise = case fd of- 0 -> do _ <- hWaitForInput stdin (-1)- return ()- -- hWaitForInput does work properly, but we can only- -- do this for stdin since we know its FD.- _ -> error "threadWaitRead requires -threaded on Windows, or use System.IO.hWaitForInput"-#else- = GHC.Conc.threadWaitRead fd-#endif---- | Block the current thread until data can be written to the--- given file descriptor (GHC only).------ This will throw an 'IOError' if the file descriptor was closed--- while this thread was blocked. To safely close a file descriptor--- that has been used with 'threadWaitWrite', use--- 'GHC.Conc.closeFdWith'.-threadWaitWrite :: Fd -> IO ()-threadWaitWrite fd-#ifdef mingw32_HOST_OS- | threaded = withThread (waitFd fd 1)- | otherwise = error "threadWaitWrite requires -threaded on Windows"-#else- = GHC.Conc.threadWaitWrite fd-#endif--#ifdef mingw32_HOST_OS-foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool--withThread :: IO a -> IO a-withThread io = do- m <- newEmptyMVar- _ <- mask_ $ forkIO $ try io >>= putMVar m- x <- takeMVar m- case x of- Right a -> return a- Left e -> throwIO (e :: IOException)--waitFd :: Fd -> CInt -> IO ()-waitFd fd write = do- throwErrnoIfMinus1_ "fdReady" $- fdReady (fromIntegral fd) write iNFINITE 0--iNFINITE :: CInt-iNFINITE = 0xFFFFFFFF -- urgh--foreign import ccall safe "fdReady"- fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt-#endif---- ------------------------------------------------------------------------------ More docs--{- $osthreads-- #osthreads# In GHC, threads created by 'forkIO' are lightweight threads, and- are managed entirely by the GHC runtime. Typically Haskell- threads are an order of magnitude or two more efficient (in- terms of both time and space) than operating system threads.-- The downside of having lightweight threads is that only one can- run at a time, so if one thread blocks in a foreign call, for- example, the other threads cannot continue. The GHC runtime- works around this by making use of full OS threads where- necessary. When the program is built with the @-threaded@- option (to link against the multithreaded version of the- runtime), a thread making a @safe@ foreign call will not block- the other threads in the system; another OS thread will take- over running Haskell threads until the original call returns.- The runtime maintains a pool of these /worker/ threads so that- multiple Haskell threads can be involved in external calls- simultaneously.-- The "System.IO" library manages multiplexing in its own way. On- Windows systems it uses @safe@ foreign calls to ensure that- threads doing I\/O operations don't block the whole runtime,- whereas on Unix systems all the currently blocked I\/O requests- are managed by a single thread (the /IO manager thread/) using- a mechanism such as @epoll@ or @kqueue@, depending on what is- provided by the host operating system.-- The runtime will run a Haskell thread using any of the available- worker OS threads. If you need control over which particular OS- thread is used to run a given Haskell thread, perhaps because- you need to call a foreign library that uses OS-thread-local- state, then you need bound threads (see "Control.Concurrent#boundthreads").-- If you don't use the @-threaded@ option, then the runtime does- not make use of multiple OS threads. Foreign calls will block- all other running Haskell threads until the call returns. The- "System.IO" library still does multiplexing, so there can be multiple- threads doing I\/O, and this is handled internally by the runtime using- @select@.--}--{- $termination-- In a standalone GHC program, only the main thread is- required to terminate in order for the process to terminate.- Thus all other forked threads will simply terminate at the same- time as the main thread (the terminology for this kind of- behaviour is \"daemonic threads\").-- If you want the program to wait for child threads to- finish before exiting, you need to program this yourself. A- simple mechanism is to have each child thread write to an- 'MVar' when it completes, and have the main- thread wait on all the 'MVar's before- exiting:--> myForkIO :: IO () -> IO (MVar ())-> myForkIO io = do-> mvar <- newEmptyMVar-> forkIO (io `finally` putMVar mvar ())-> return mvar-- Note that we use 'finally' from the- "Control.Exception" module to make sure that the- 'MVar' is written to even if the thread dies or- is killed for some reason.-- A better method is to keep a global list of all child- threads which we should wait for at the end of the program:--> children :: MVar [MVar ()]-> children = unsafePerformIO (newMVar [])-> -> waitForChildren :: IO ()-> waitForChildren = do-> cs <- takeMVar children-> case cs of-> [] -> return ()-> m:ms -> do-> putMVar children ms-> takeMVar m-> waitForChildren->-> forkChild :: IO () -> IO ThreadId-> forkChild io = do-> mvar <- newEmptyMVar-> childs <- takeMVar children-> putMVar children (mvar:childs)-> forkIO (io `finally` putMVar mvar ())->-> main =-> later waitForChildren $-> ...-- The main thread principle also applies to calls to Haskell from- outside, using @foreign export@. When the @foreign export@ed- function is invoked, it starts a new main thread, and it returns- when this main thread terminates. If the call causes new- threads to be forked, they may remain in the system after the- @foreign export@ed function has returned.--}--{- $preemption-- GHC implements pre-emptive multitasking: the execution of- threads are interleaved in a random fashion. More specifically,- a thread may be pre-empted whenever it allocates some memory,- which unfortunately means that tight loops which do no- allocation tend to lock out other threads (this only seems to- happen with pathological benchmark-style code, however).-- The rescheduling timer runs on a 20ms granularity by- default, but this may be altered using the- @-i\<n\>@ RTS option. After a rescheduling- \"tick\" the running thread is pre-empted as soon as- possible.-- One final note: the- @aaaa@ @bbbb@ example may not- work too well on GHC (see Scheduling, above), due- to the locking on a 'System.IO.Handle'. Only one thread- may hold the lock on a 'System.IO.Handle' at any one- time, so if a reschedule happens while a thread is holding the- lock, the other thread won't be able to run. The upshot is that- the switch from @aaaa@ to- @bbbbb@ happens infrequently. It can be- improved by lowering the reschedule tick period. We also have a- patch that causes a reschedule whenever a thread waiting on a- lock is woken up, but haven't found it to be useful for anything- other than this example :-)--}-#endif /* __GLASGOW_HASKELL__ */
@@ -1,156 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Control.Concurrent.Chan--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (concurrency)------ Unbounded channels.-----------------------------------------------------------------------------------module Control.Concurrent.Chan- ( - -- * The 'Chan' type- Chan, -- abstract-- -- * Operations- newChan, -- :: IO (Chan a)- writeChan, -- :: Chan a -> a -> IO ()- readChan, -- :: Chan a -> IO a- dupChan, -- :: Chan a -> IO (Chan a)- unGetChan, -- :: Chan a -> a -> IO ()- isEmptyChan, -- :: Chan a -> IO Bool-- -- * Stream interface- getChanContents, -- :: Chan a -> IO [a]- writeList2Chan, -- :: Chan a -> [a] -> IO ()- ) where--import Prelude--import System.IO.Unsafe ( unsafeInterleaveIO )-import Control.Concurrent.MVar-import Control.Exception (mask_)-import Data.Typeable--#include "Typeable.h"---- A channel is represented by two @MVar@s keeping track of the two ends--- of the channel contents,i.e., the read- and write ends. Empty @MVar@s--- are used to handle consumers trying to read from an empty channel.---- |'Chan' is an abstract type representing an unbounded FIFO channel.-data Chan a- = Chan (MVar (Stream a))- (MVar (Stream a)) -- Invariant: the Stream a is always an empty MVar- deriving Eq--INSTANCE_TYPEABLE1(Chan,chanTc,"Chan")--type Stream a = MVar (ChItem a)--data ChItem a = ChItem a (Stream a)---- See the Concurrent Haskell paper for a diagram explaining the--- how the different channel operations proceed.---- @newChan@ sets up the read and write end of a channel by initialising--- these two @MVar@s with an empty @MVar@.---- |Build and returns a new instance of 'Chan'.-newChan :: IO (Chan a)-newChan = do- hole <- newEmptyMVar- readVar <- newMVar hole- writeVar <- newMVar hole- return (Chan readVar writeVar)---- To put an element on a channel, a new hole at the write end is created.--- What was previously the empty @MVar@ at the back of the channel is then--- filled in with a new stream element holding the entered value and the--- new hole.---- |Write a value to a 'Chan'.-writeChan :: Chan a -> a -> IO ()-writeChan (Chan _ writeVar) val = do- new_hole <- newEmptyMVar- mask_ $ do- old_hole <- takeMVar writeVar- putMVar old_hole (ChItem val new_hole)- putMVar writeVar new_hole---- The reason we don't simply do this:------ modifyMVar_ writeVar $ \old_hole -> do--- putMVar old_hole (ChItem val new_hole)--- return new_hole------ is because if an asynchronous exception is received after the 'putMVar'--- completes and before modifyMVar_ installs the new value, it will set the--- Chan's write end to a filled hole.---- |Read the next value from the 'Chan'.-readChan :: Chan a -> IO a-readChan (Chan readVar _) = do- modifyMVar readVar $ \read_end -> do- (ChItem val new_read_end) <- readMVar read_end- -- Use readMVar here, not takeMVar,- -- else dupChan doesn't work- return (new_read_end, val)---- |Duplicate a 'Chan': the duplicate channel begins empty, but data written to--- either channel from then on will be available from both. Hence this creates--- a kind of broadcast channel, where data written by anyone is seen by--- everyone else.------ (Note that a duplicated channel is not equal to its original.--- So: @fmap (c /=) $ dupChan c@ returns @True@ for all @c@.)-dupChan :: Chan a -> IO (Chan a)-dupChan (Chan _ writeVar) = do- hole <- readMVar writeVar- newReadVar <- newMVar hole- return (Chan newReadVar writeVar)---- |Put a data item back onto a channel, where it will be the next item read.-unGetChan :: Chan a -> a -> IO ()-unGetChan (Chan readVar _) val = do- new_read_end <- newEmptyMVar- modifyMVar_ readVar $ \read_end -> do- putMVar new_read_end (ChItem val read_end)- return new_read_end-{-# DEPRECATED unGetChan "if you need this operation, use Control.Concurrent.STM.TChan instead. See http://hackage.haskell.org/trac/ghc/ticket/4154 for details" #-}---- |Returns 'True' if the supplied 'Chan' is empty.-isEmptyChan :: Chan a -> IO Bool-isEmptyChan (Chan readVar writeVar) = do- withMVar readVar $ \r -> do- w <- readMVar writeVar- let eq = r == w- eq `seq` return eq-{-# DEPRECATED isEmptyChan "if you need this operation, use Control.Concurrent.STM.TChan instead. See http://hackage.haskell.org/trac/ghc/ticket/4154 for details" #-}---- Operators for interfacing with functional streams.---- |Return a lazy list representing the contents of the supplied--- 'Chan', much like 'System.IO.hGetContents'.-getChanContents :: Chan a -> IO [a]-getChanContents ch- = unsafeInterleaveIO (do- x <- readChan ch- xs <- getChanContents ch- return (x:xs)- )---- |Write an entire list of items to a 'Chan'.-writeList2Chan :: Chan a -> [a] -> IO ()-writeList2Chan ch ls = sequence_ (map (writeChan ch) ls)
@@ -1,234 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Control.Concurrent.MVar--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (concurrency)------ An @'MVar' t@ is mutable location that is either empty or contains a--- value of type @t@. It has two fundamental operations: 'putMVar'--- which fills an 'MVar' if it is empty and blocks otherwise, and--- 'takeMVar' which empties an 'MVar' if it is full and blocks--- otherwise. They can be used in multiple different ways:------ 1. As synchronized mutable variables,--- 2. As channels, with 'takeMVar' and 'putMVar' as receive and send, and--- 3. As a binary semaphore @'MVar' ()@, with 'takeMVar' and 'putMVar' as--- wait and signal.------ They were introduced in the paper "Concurrent Haskell" by Simon--- Peyton Jones, Andrew Gordon and Sigbjorn Finne, though some details--- of their implementation have since then changed (in particular, a--- put on a full MVar used to error, but now merely blocks.)------ * Applicability------ 'MVar's offer more flexibility than 'IORef's, but less flexibility--- than 'STM'. They are appropriate for building synchronization--- primitives and performing simple interthread communication; however--- they are very simple and susceptible to race conditions, deadlocks or--- uncaught exceptions. Do not use them if you need perform larger--- atomic operations such as reading from multiple variables: use 'STM'--- instead.------ In particular, the "bigger" functions in this module ('readMVar',--- 'swapMVar', 'withMVar', 'modifyMVar_' and 'modifyMVar') are simply--- the composition of a 'takeMVar' followed by a 'putMVar' with--- exception safety.--- These only have atomicity guarantees if all other threads--- perform a 'takeMVar' before a 'putMVar' as well; otherwise, they may--- block.------ * Fairness------ No thread can be blocked indefinitely on an 'MVar' unless another--- thread holds that 'MVar' indefinitely. One usual implementation of--- this fairness guarantee is that threads blocked on an 'MVar' are--- served in a first-in-first-out fashion, but this is not guaranteed--- in the semantics.------ * Gotchas------ Like many other Haskell data structures, 'MVar's are lazy. This--- means that if you place an expensive unevaluated thunk inside an--- 'MVar', it will be evaluated by the thread that consumes it, not the--- thread that produced it. Be sure to 'evaluate' values to be placed--- in an 'MVar' to the appropriate normal form, or utilize a strict--- MVar provided by the strict-concurrency package.------ * Ordering------ 'MVar' operations are always observed to take place in the order--- they are written in the program, regardless of the memory model of--- the underlying machine. This is in contrast to 'IORef' operations--- which may appear out-of-order to another thread in some cases.------ * Example------ Consider the following concurrent data structure, a skip channel.--- This is a channel for an intermittent source of high bandwidth--- information (for example, mouse movement events.) Writing to the--- channel never blocks, and reading from the channel only returns the--- most recent value, or blocks if there are no new values. Multiple--- readers are supported with a @dupSkipChan@ operation.------ A skip channel is a pair of 'MVar's. The first 'MVar' contains the--- current value, and a list of semaphores that need to be notified--- when it changes. The second 'MVar' is a semaphore for this particular--- reader: it is full if there is a value in the channel that this--- reader has not read yet, and empty otherwise.------ @--- data SkipChan a = SkipChan (MVar (a, [MVar ()])) (MVar ())------ newSkipChan :: IO (SkipChan a)--- newSkipChan = do--- sem <- newEmptyMVar--- main <- newMVar (undefined, [sem])--- return (SkipChan main sem)------ putSkipChan :: SkipChan a -> a -> IO ()--- putSkipChan (SkipChan main _) v = do--- (_, sems) <- takeMVar main--- putMVar main (v, [])--- mapM_ (\sem -> putMVar sem ()) sems------ getSkipChan :: SkipChan a -> IO a--- getSkipChan (SkipChan main sem) = do--- takeMVar sem--- (v, sems) <- takeMVar main--- putMVar main (v, sem:sems)--- return v------ dupSkipChan :: SkipChan a -> IO (SkipChan a)--- dupSkipChan (SkipChan main _) = do--- sem <- newEmptyMVar--- (v, sems) <- takeMVar main--- putMVar main (v, sem:sems)--- return (SkipChan main sem)--- @------ This example was adapted from the original Concurrent Haskell paper.--- For more examples of 'MVar's being used to build higher-level--- synchronization primitives, see 'Control.Concurrent.Chan' and--- 'Control.Concurrent.QSem'.-----------------------------------------------------------------------------------module Control.Concurrent.MVar- (- -- * @MVar@s- MVar -- abstract- , newEmptyMVar -- :: IO (MVar a)- , newMVar -- :: a -> IO (MVar a)- , takeMVar -- :: MVar a -> IO a- , putMVar -- :: MVar a -> a -> IO ()- , readMVar -- :: MVar a -> IO a- , swapMVar -- :: MVar a -> a -> IO a- , tryTakeMVar -- :: MVar a -> IO (Maybe a)- , tryPutMVar -- :: MVar a -> a -> IO Bool- , isEmptyMVar -- :: MVar a -> IO Bool- , withMVar -- :: MVar a -> (a -> IO b) -> IO b- , modifyMVar_ -- :: MVar a -> (a -> IO a) -> IO ()- , modifyMVar -- :: MVar a -> (a -> IO (a,b)) -> IO b-#ifndef __HUGS__- , addMVarFinalizer -- :: MVar a -> IO () -> IO ()-#endif- ) where--#ifdef __HUGS__-import Hugs.ConcBase ( MVar, newEmptyMVar, newMVar, takeMVar, putMVar,- tryTakeMVar, tryPutMVar, isEmptyMVar,- )-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.MVar ( MVar, newEmptyMVar, newMVar, takeMVar, putMVar,- tryTakeMVar, tryPutMVar, isEmptyMVar, addMVarFinalizer- )-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Base-#else-import Prelude-#endif--import Control.Exception.Base--{-|- This is a combination of 'takeMVar' and 'putMVar'; ie. it takes the value- from the 'MVar', puts it back, and also returns it. This function- is atomic only if there are no other producers (i.e. threads calling- 'putMVar') for this 'MVar'.--}-readMVar :: MVar a -> IO a-readMVar m =- mask_ $ do- a <- takeMVar m- putMVar m a- return a--{-|- Take a value from an 'MVar', put a new value into the 'MVar' and- return the value taken. This function is atomic only if there are- no other producers for this 'MVar'.--}-swapMVar :: MVar a -> a -> IO a-swapMVar mvar new =- mask_ $ do- old <- takeMVar mvar- putMVar mvar new- return old--{-|- 'withMVar' is an exception-safe wrapper for operating on the contents- of an 'MVar'. This operation is exception-safe: it will replace the- original contents of the 'MVar' if an exception is raised (see- "Control.Exception"). However, it is only atomic if there are no- other producers for this 'MVar'.--}-{-# INLINE withMVar #-}--- inlining has been reported to have dramatic effects; see--- http://www.haskell.org//pipermail/haskell/2006-May/017907.html-withMVar :: MVar a -> (a -> IO b) -> IO b-withMVar m io =- mask $ \restore -> do- a <- takeMVar m- b <- restore (io a) `onException` putMVar m a- putMVar m a- return b--{-|- An exception-safe wrapper for modifying the contents of an 'MVar'.- Like 'withMVar', 'modifyMVar' will replace the original contents of- the 'MVar' if an exception is raised during the operation. This- function is only atomic if there are no other producers for this- 'MVar'.--}-{-# INLINE modifyMVar_ #-}-modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()-modifyMVar_ m io =- mask $ \restore -> do- a <- takeMVar m- a' <- restore (io a) `onException` putMVar m a- putMVar m a'--{-|- A slight variation on 'modifyMVar_' that allows a value to be- returned (@b@) in addition to the modified value of the 'MVar'.--}-{-# INLINE modifyMVar #-}-modifyMVar :: MVar a -> (a -> IO (a,b)) -> IO b-modifyMVar m io =- mask $ \restore -> do- a <- takeMVar m- (a',b) <- restore (io a) `onException` putMVar m a- putMVar m a'- return b
@@ -1,89 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Control.Concurrent.QSem--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (concurrency)------ Simple quantity semaphores.-----------------------------------------------------------------------------------module Control.Concurrent.QSem- ( -- * Simple Quantity Semaphores- QSem, -- abstract- newQSem, -- :: Int -> IO QSem- waitQSem, -- :: QSem -> IO ()- signalQSem -- :: QSem -> IO ()- ) where--import Prelude-import Control.Concurrent.MVar-import Control.Exception ( mask_ )-import Data.Typeable--#include "Typeable.h"---- General semaphores are also implemented readily in terms of shared--- @MVar@s, only have to catch the case when the semaphore is tried--- waited on when it is empty (==0). Implement this in the same way as--- shared variables are implemented - maintaining a list of @MVar@s--- representing threads currently waiting. The counter is a shared--- variable, ensuring the mutual exclusion on its access.---- |A 'QSem' is a simple quantity semaphore, in which the available--- \"quantity\" is always dealt with in units of one.-newtype QSem = QSem (MVar (Int, [MVar ()])) deriving Eq--INSTANCE_TYPEABLE0(QSem,qSemTc,"QSem")---- |Build a new 'QSem' with a supplied initial quantity.--- The initial quantity must be at least 0.-newQSem :: Int -> IO QSem-newQSem initial =- if initial < 0- then fail "newQSem: Initial quantity must be non-negative"- else do sem <- newMVar (initial, [])- return (QSem sem)---- |Wait for a unit to become available-waitQSem :: QSem -> IO ()-waitQSem (QSem sem) = mask_ $ do- (avail,blocked) <- takeMVar sem -- gain ex. access- if avail > 0 then- let avail' = avail-1- in avail' `seq` putMVar sem (avail',[])- else do- b <- newEmptyMVar- {-- Stuff the reader at the back of the queue,- so as to preserve waiting order. A signalling- process then only have to pick the MVar at the- front of the blocked list.-- The version of waitQSem given in the paper could- lead to starvation.- -}- putMVar sem (0, blocked++[b])- takeMVar b---- |Signal that a unit of the 'QSem' is available-signalQSem :: QSem -> IO ()-signalQSem (QSem sem) = mask_ $ do- (avail,blocked) <- takeMVar sem- case blocked of- [] -> let avail' = avail+1- in avail' `seq` putMVar sem (avail',blocked)-- (b:blocked') -> do- putMVar sem (0,blocked')- putMVar b ()
@@ -1,81 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Control.Concurrent.QSemN--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (concurrency)------ Quantity semaphores in which each thread may wait for an arbitrary--- \"amount\".-----------------------------------------------------------------------------------module Control.Concurrent.QSemN- ( -- * General Quantity Semaphores- QSemN, -- abstract- newQSemN, -- :: Int -> IO QSemN- waitQSemN, -- :: QSemN -> Int -> IO ()- signalQSemN -- :: QSemN -> Int -> IO ()- ) where--import Prelude--import Control.Concurrent.MVar-import Control.Exception ( mask_ )-import Data.Typeable--#include "Typeable.h"---- |A 'QSemN' is a quantity semaphore, in which the available--- \"quantity\" may be signalled or waited for in arbitrary amounts.-newtype QSemN = QSemN (MVar (Int,[(Int,MVar ())])) deriving Eq--INSTANCE_TYPEABLE0(QSemN,qSemNTc,"QSemN")---- |Build a new 'QSemN' with a supplied initial quantity.--- The initial quantity must be at least 0.-newQSemN :: Int -> IO QSemN-newQSemN initial =- if initial < 0- then fail "newQSemN: Initial quantity must be non-negative"- else do sem <- newMVar (initial, [])- return (QSemN sem)---- |Wait for the specified quantity to become available-waitQSemN :: QSemN -> Int -> IO ()-waitQSemN (QSemN sem) sz = mask_ $ do- (avail,blocked) <- takeMVar sem -- gain ex. access- let remaining = avail - sz- if remaining >= 0 then- -- discharging 'sz' still leaves the semaphore- -- in an 'unblocked' state.- putMVar sem (remaining,blocked)- else do- b <- newEmptyMVar- putMVar sem (avail, blocked++[(sz,b)])- takeMVar b---- |Signal that a given quantity is now available from the 'QSemN'.-signalQSemN :: QSemN -> Int -> IO ()-signalQSemN (QSemN sem) n = mask_ $ do- (avail,blocked) <- takeMVar sem- (avail',blocked') <- free (avail+n) blocked- avail' `seq` putMVar sem (avail',blocked')- where- free avail [] = return (avail,[])- free avail ((req,b):blocked)- | avail >= req = do- putMVar b ()- free (avail-req) blocked- | otherwise = do- (avail',blocked') <- free avail blocked- return (avail',(req,b):blocked')
@@ -1,136 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Control.Concurrent.SampleVar--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (concurrency)------ Sample variables-----------------------------------------------------------------------------------module Control.Concurrent.SampleVar- (- -- * Sample Variables- SampleVar, -- :: type _ =- - newEmptySampleVar, -- :: IO (SampleVar a)- newSampleVar, -- :: a -> IO (SampleVar a)- emptySampleVar, -- :: SampleVar a -> IO ()- readSampleVar, -- :: SampleVar a -> IO a- writeSampleVar, -- :: SampleVar a -> a -> IO ()- isEmptySampleVar, -- :: SampleVar a -> IO Bool-- ) where--import Prelude--import Control.Concurrent.MVar--import Control.Exception ( mask_ )--import Data.Functor ( (<$>) )--import Data.Typeable--#include "Typeable.h"---- |--- Sample variables are slightly different from a normal 'MVar':--- --- * Reading an empty 'SampleVar' causes the reader to block.--- (same as 'takeMVar' on empty 'MVar')--- --- * Reading a filled 'SampleVar' empties it and returns value.--- (same as 'takeMVar')--- --- * Writing to an empty 'SampleVar' fills it with a value, and--- potentially, wakes up a blocked reader (same as for 'putMVar' on--- empty 'MVar').------ * Writing to a filled 'SampleVar' overwrites the current value.--- (different from 'putMVar' on full 'MVar'.)--newtype SampleVar a = SampleVar ( MVar ( Int -- 1 == full- -- 0 == empty- -- <0 no of readers blocked- , MVar a- )- )- deriving (Eq)--INSTANCE_TYPEABLE1(SampleVar,sampleVarTc,"SampleVar")---- |Build a new, empty, 'SampleVar'-newEmptySampleVar :: IO (SampleVar a)-newEmptySampleVar = do- v <- newEmptyMVar- SampleVar <$> newMVar (0,v)---- |Build a 'SampleVar' with an initial value.-newSampleVar :: a -> IO (SampleVar a)-newSampleVar a = do- v <- newMVar a- SampleVar <$> newMVar (1,v)---- |If the SampleVar is full, leave it empty. Otherwise, do nothing.-emptySampleVar :: SampleVar a -> IO ()-emptySampleVar (SampleVar v) = mask_ $ do- s@(readers, var) <- takeMVar v- if readers > 0 then do- _ <- takeMVar var- putMVar v (0,var)- else- putMVar v s---- |Wait for a value to become available, then take it and return.-readSampleVar :: SampleVar a -> IO a-readSampleVar (SampleVar svar) = mask_ $ do------ filled => make empty and grab sample--- not filled => try to grab value, empty when read val.---- (readers,val) <- takeMVar svar- let readers' = readers-1- readers' `seq` putMVar svar (readers',val)- takeMVar val---- |Write a value into the 'SampleVar', overwriting any previous value that--- was there.-writeSampleVar :: SampleVar a -> a -> IO ()-writeSampleVar (SampleVar svar) v = mask_ $ do------ filled => overwrite--- not filled => fill, write val---- s@(readers,val) <- takeMVar svar- case readers of- 1 ->- swapMVar val v >>- putMVar svar s- _ ->- putMVar val v >>- let readers' = min 1 (readers+1)- in readers' `seq` putMVar svar (readers', val)---- | Returns 'True' if the 'SampleVar' is currently empty.------ Note that this function is only useful if you know that no other--- threads can be modifying the state of the 'SampleVar', because--- otherwise the state of the 'SampleVar' may have changed by the time--- you see the result of 'isEmptySampleVar'.----isEmptySampleVar :: SampleVar a -> IO Bool-isEmptySampleVar (SampleVar svar) = do- (readers, _) <- readMVar svar- return (readers <= 0)-
@@ -1,405 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ExistentialQuantification #-}---------------------------------------------------------------------------------- |--- Module : Control.Exception--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (extended exceptions)------ This module provides support for raising and catching both built-in--- and user-defined exceptions.------ In addition to exceptions thrown by 'IO' operations, exceptions may--- be thrown by pure code (imprecise exceptions) or by external events--- (asynchronous exceptions), but may only be caught in the 'IO' monad.--- For more details, see:------ * /A semantics for imprecise exceptions/, by Simon Peyton Jones,--- Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson,--- in /PLDI'99/.------ * /Asynchronous exceptions in Haskell/, by Simon Marlow, Simon Peyton--- Jones, Andy Moran and John Reppy, in /PLDI'01/.------ * /An Extensible Dynamically-Typed Hierarchy of Exceptions/,--- by Simon Marlow, in /Haskell '06/.-----------------------------------------------------------------------------------module Control.Exception (-- -- * The Exception type-#ifdef __HUGS__- SomeException,-#else- SomeException(..),-#endif- Exception(..), -- class- IOException, -- instance Eq, Ord, Show, Typeable, Exception- ArithException(..), -- instance Eq, Ord, Show, Typeable, Exception- ArrayException(..), -- instance Eq, Ord, Show, Typeable, Exception- AssertionFailed(..),- AsyncException(..), -- instance Eq, Ord, Show, Typeable, Exception--#if __GLASGOW_HASKELL__ || __HUGS__- NonTermination(..),- NestedAtomically(..),-#endif-#ifdef __NHC__- System.ExitCode(), -- instance Exception-#endif-- BlockedIndefinitelyOnMVar(..),- BlockedIndefinitelyOnSTM(..),- Deadlock(..),- NoMethodError(..),- PatternMatchFail(..),- RecConError(..),- RecSelError(..),- RecUpdError(..),- ErrorCall(..),-- -- * Throwing exceptions- throw,- throwIO,- ioError,-#ifdef __GLASGOW_HASKELL__- throwTo,-#endif-- -- * Catching Exceptions-- -- $catching-- -- ** Catching all exceptions-- -- $catchall-- -- ** The @catch@ functions- catch,- catches, Handler(..),- catchJust,-- -- ** The @handle@ functions- handle,- handleJust,-- -- ** The @try@ functions- try,- tryJust,-- -- ** The @evaluate@ function- evaluate,-- -- ** The @mapException@ function- mapException,-- -- * Asynchronous Exceptions-- -- $async-- -- ** Asynchronous exception control-- -- |The following functions allow a thread to control delivery of- -- asynchronous exceptions during a critical region.-- mask,-#ifndef __NHC__- mask_,- uninterruptibleMask,- uninterruptibleMask_,- MaskingState(..),- getMaskingState,- allowInterrupt,-#endif-- -- ** (deprecated) Asynchronous exception control-- block,- unblock,- blocked,-- -- *** Applying @mask@ to an exception handler-- -- $block_handler-- -- *** Interruptible operations-- -- $interruptible-- -- * Assertions-- assert,-- -- * Utilities-- bracket,- bracket_,- bracketOnError,-- finally,- onException,-- ) where--import Control.Exception.Base--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.IO (unsafeUnmask)-import Data.Maybe-#else-import Prelude hiding (catch)-#endif--#ifdef __NHC__-import System (ExitCode())-#endif---- | You need this when using 'catches'.-data Handler a = forall e . Exception e => Handler (e -> IO a)--{- |-Sometimes you want to catch two different sorts of exception. You could-do something like--> f = expr `catch` \ (ex :: ArithException) -> handleArith ex-> `catch` \ (ex :: IOException) -> handleIO ex--However, there are a couple of problems with this approach. The first is-that having two exception handlers is inefficient. However, the more-serious issue is that the second exception handler will catch exceptions-in the first, e.g. in the example above, if @handleArith@ throws an-@IOException@ then the second exception handler will catch it.--Instead, we provide a function 'catches', which would be used thus:--> f = expr `catches` [Handler (\ (ex :: ArithException) -> handleArith ex),-> Handler (\ (ex :: IOException) -> handleIO ex)]--}-catches :: IO a -> [Handler a] -> IO a-catches io handlers = io `catch` catchesHandler handlers--catchesHandler :: [Handler a] -> SomeException -> IO a-catchesHandler handlers e = foldr tryHandler (throw e) handlers- where tryHandler (Handler handler) res- = case fromException e of- Just e' -> handler e'- Nothing -> res---- -------------------------------------------------------------------------------- Catching exceptions--{- $catching--There are several functions for catching and examining-exceptions; all of them may only be used from within the-'IO' monad.--Here's a rule of thumb for deciding which catch-style function to-use:-- * If you want to do some cleanup in the event that an exception- is raised, use 'finally', 'bracket' or 'onException'.-- * To recover after an exception and do something else, the best- choice is to use one of the 'try' family.-- * ... unless you are recovering from an asynchronous exception, in which- case use 'catch' or 'catchJust'.--The difference between using 'try' and 'catch' for recovery is that in-'catch' the handler is inside an implicit 'block' (see \"Asynchronous-Exceptions\") which is important when catching asynchronous-exceptions, but when catching other kinds of exception it is-unnecessary. Furthermore it is possible to accidentally stay inside-the implicit 'block' by tail-calling rather than returning from the-handler, which is why we recommend using 'try' rather than 'catch' for-ordinary exception recovery.--A typical use of 'tryJust' for recovery looks like this:--> do r <- tryJust (guard . isDoesNotExistError) $ getEnv "HOME"-> case r of-> Left e -> ...-> Right home -> ...---}---- -------------------------------------------------------------------------------- Asynchronous exceptions---- | When invoked inside 'mask', this function allows a blocked--- asynchronous exception to be raised, if one exists. It is--- equivalent to performing an interruptible operation (see--- #interruptible#), but does not involve any actual blocking.------ When called outside 'mask', or inside 'uninterruptibleMask', this--- function has no effect.-allowInterrupt :: IO ()-allowInterrupt = unsafeUnmask $ return ()--{- $async-- #AsynchronousExceptions# Asynchronous exceptions are so-called because they arise due to-external influences, and can be raised at any point during execution.-'StackOverflow' and 'HeapOverflow' are two examples of-system-generated asynchronous exceptions.--The primary source of asynchronous exceptions, however, is-'throwTo':--> throwTo :: ThreadId -> Exception -> IO ()--'throwTo' (also 'Control.Concurrent.killThread') allows one-running thread to raise an arbitrary exception in another thread. The-exception is therefore asynchronous with respect to the target thread,-which could be doing anything at the time it receives the exception.-Great care should be taken with asynchronous exceptions; it is all too-easy to introduce race conditions by the over zealous use of-'throwTo'.--}--{- $block_handler-There\'s an implied 'mask' around every exception handler in a call-to one of the 'catch' family of functions. This is because that is-what you want most of the time - it eliminates a common race condition-in starting an exception handler, because there may be no exception-handler on the stack to handle another exception if one arrives-immediately. If asynchronous exceptions are masked on entering the-handler, though, we have time to install a new exception handler-before being interrupted. If this weren\'t the default, one would have-to write something like--> mask $ \restore ->-> catch (restore (...))-> (\e -> handler)--If you need to unblock asynchronous exceptions again in the exception-handler, 'restore' can be used there too.--Note that 'try' and friends /do not/ have a similar default, because-there is no exception handler in this case. Don't use 'try' for-recovering from an asynchronous exception.--}--{- $interruptible-- #interruptible#-Some operations are /interruptible/, which means that they can receive-asynchronous exceptions even in the scope of a 'mask'. Any function-which may itself block is defined as interruptible; this includes-'Control.Concurrent.MVar.takeMVar'-(but not 'Control.Concurrent.MVar.tryTakeMVar'),-and most operations which perform-some I\/O with the outside world. The reason for having-interruptible operations is so that we can write things like--> mask $ \restore -> do-> a <- takeMVar m-> catch (restore (...))-> (\e -> ...)--if the 'Control.Concurrent.MVar.takeMVar' was not interruptible,-then this particular-combination could lead to deadlock, because the thread itself would be-blocked in a state where it can\'t receive any asynchronous exceptions.-With 'Control.Concurrent.MVar.takeMVar' interruptible, however, we can be-safe in the knowledge that the thread can receive exceptions right up-until the point when the 'Control.Concurrent.MVar.takeMVar' succeeds.-Similar arguments apply for other interruptible operations like-'System.IO.openFile'.--It is useful to think of 'mask' not as a way to completely prevent-asynchronous exceptions, but as a way to switch from asynchronous mode-to polling mode. The main difficulty with asynchronous-exceptions is that they normally can occur anywhere, but within a-'mask' an asynchronous exception is only raised by operations that are-interruptible (or call other interruptible operations). In many cases-these operations may themselves raise exceptions, such as I\/O errors,-so the caller will usually be prepared to handle exceptions arising from the-operation anyway. To perfom an explicit poll for asynchronous exceptions-inside 'mask', use 'allowInterrupt'.--Sometimes it is too onerous to handle exceptions in the middle of a-critical piece of stateful code. There are three ways to handle this-kind of situation:-- * Use STM. Since a transaction is always either completely executed- or not at all, transactions are a good way to maintain invariants- over state in the presence of asynchronous (and indeed synchronous)- exceptions.-- * Use 'mask', and avoid interruptible operations. In order to do- this, we have to know which operations are interruptible. It is- impossible to know for any given library function whether it might- invoke an interruptible operation internally; so instead we give a- list of guaranteed-not-to-be-interruptible operations below.-- * Use 'uninterruptibleMask'. This is generally not recommended,- unless you can guarantee that any interruptible operations invoked- during the scope of 'uninterruptibleMask' can only ever block for- a short time. Otherwise, 'uninterruptibleMask' is a good way to- make your program deadlock and be unresponsive to user interrupts.--The following operations are guaranteed not to be interruptible:-- * operations on 'IORef' from "Data.IORef"- * STM transactions that do not use 'retry'- * everything from the @Foreign@ modules- * everything from @Control.Exception@- * @tryTakeMVar@, @tryPutMVar@, @isEmptyMVar@- * @takeMVar@ if the @MVar@ is definitely full, and conversely @putMVar@ if the @MVar@ is definitely empty- * @newEmptyMVar@, @newMVar@- * @forkIO@, @forkIOUnmasked@, @myThreadId@---}--{- $catchall--It is possible to catch all exceptions, by using the type 'SomeException':--> catch f (\e -> ... (e :: SomeException) ...)--HOWEVER, this is normally not what you want to do!--For example, suppose you want to read a file, but if it doesn't exist-then continue as if it contained \"\". You might be tempted to just-catch all exceptions and return \"\" in the handler. However, this has-all sorts of undesirable consequences. For example, if the user-presses control-C at just the right moment then the 'UserInterrupt'-exception will be caught, and the program will continue running under-the belief that the file contains \"\". Similarly, if another thread-tries to kill the thread reading the file then the 'ThreadKilled'-exception will be ignored.--Instead, you should only catch exactly the exceptions that you really-want. In this case, this would likely be more specific than even-\"any IO exception\"; a permissions error would likely also want to be-handled differently. Instead, you would probably want something like:--> e <- tryJust (guard . isDoesNotExistError) (readFile f)-> let str = either (const "") id e--There are occassions when you really do need to catch any sort of-exception. However, in most cases this is just so you can do some-cleaning up; you aren't actually interested in the exception itself.-For example, if you open a file then you want to close it again,-whether processing the file executes normally or throws an exception.-However, in these cases you can use functions like 'bracket', 'finally'-and 'onException', which never actually pass you the exception, but-just call the cleanup functions at the appropriate points.--But sometimes you really do need to catch any exception, and actually-see what the exception is. One example is at the very top-level of a-program, you may wish to catch any exception, print it to a logfile or-the screen, and then exit gracefully. For these cases, you can use-'catch' (or one of the other exception-catching functions) with the-'SomeException' type.--}-
@@ -1,735 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif--#include "Typeable.h"---------------------------------------------------------------------------------- |--- Module : Control.Exception.Base--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (extended exceptions)------ Extensible exceptions, except for multiple handlers.-----------------------------------------------------------------------------------module Control.Exception.Base (-- -- * The Exception type-#ifdef __HUGS__- SomeException,-#else- SomeException(..),-#endif- Exception(..),- IOException,- ArithException(..),- ArrayException(..),- AssertionFailed(..),- AsyncException(..),--#if __GLASGOW_HASKELL__ || __HUGS__- NonTermination(..),- NestedAtomically(..),-#endif-- BlockedIndefinitelyOnMVar(..),- BlockedIndefinitelyOnSTM(..),- Deadlock(..),- NoMethodError(..),- PatternMatchFail(..),- RecConError(..),- RecSelError(..),- RecUpdError(..),- ErrorCall(..),-- -- * Throwing exceptions- throwIO,- throw,- ioError,-#ifdef __GLASGOW_HASKELL__- throwTo,-#endif-- -- * Catching Exceptions-- -- ** The @catch@ functions- catch,- catchJust,-- -- ** The @handle@ functions- handle,- handleJust,-- -- ** The @try@ functions- try,- tryJust,- onException,-- -- ** The @evaluate@ function- evaluate,-- -- ** The @mapException@ function- mapException,-- -- * Asynchronous Exceptions-- -- ** Asynchronous exception control- mask,-#ifndef __NHC__- mask_,- uninterruptibleMask,- uninterruptibleMask_,- MaskingState(..),- getMaskingState,-#endif-- -- ** (deprecated) Asynchronous exception control-- block,- unblock,- blocked,-- -- * Assertions-- assert,-- -- * Utilities-- bracket,- bracket_,- bracketOnError,-- finally,--#ifdef __GLASGOW_HASKELL__- -- * Calls for GHC runtime- recSelError, recConError, irrefutPatError, runtimeError,- nonExhaustiveGuardsError, patError, noMethodBindingError,- absentError,- nonTermination, nestedAtomically,-#endif- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.IO hiding (bracket,finally,onException)-import GHC.IO.Exception-import GHC.Exception-import GHC.Show--- import GHC.Exception hiding ( Exception )-import GHC.Conc.Sync-#endif--#ifdef __HUGS__-import Prelude hiding (catch)-import Hugs.Prelude (ExitCode(..))-import Hugs.IOExts (unsafePerformIO)-import Hugs.Exception (SomeException(DynamicException, IOException,- ArithException, ArrayException, ExitException),- evaluate, IOException, ArithException, ArrayException)-import qualified Hugs.Exception-#endif--import Data.Dynamic-import Data.Either-import Data.Maybe--#ifdef __NHC__-import qualified IO as H'98 (catch)-import IO (bracket,ioError)-import DIOError -- defn of IOError type-import System (ExitCode())-import System.IO.Unsafe (unsafePerformIO)-import Unsafe.Coerce (unsafeCoerce)---- minimum needed for nhc98 to pretend it has Exceptions--{--data Exception = IOException IOException- | ArithException ArithException- | ArrayException ArrayException- | AsyncException AsyncException- | ExitException ExitCode- deriving Show--}-class ({-Typeable e,-} Show e) => Exception e where- toException :: e -> SomeException- fromException :: SomeException -> Maybe e--data SomeException = forall e . Exception e => SomeException e--INSTANCE_TYPEABLE0(SomeException,someExceptionTc,"SomeException")--instance Show SomeException where- showsPrec p (SomeException e) = showsPrec p e-instance Exception SomeException where- toException se = se- fromException = Just--type IOException = IOError-instance Exception IOError where- toException = SomeException- fromException (SomeException e) = Just (unsafeCoerce e)--instance Exception ExitCode where- toException = SomeException- fromException (SomeException e) = Just (unsafeCoerce e)--data ArithException-data ArrayException-data AsyncException-data AssertionFailed-data PatternMatchFail-data NoMethodError-data Deadlock-data BlockedIndefinitelyOnMVar-data BlockedIndefinitelyOnSTM-data ErrorCall-data RecConError-data RecSelError-data RecUpdError-instance Show ArithException-instance Show ArrayException-instance Show AsyncException-instance Show AssertionFailed-instance Show PatternMatchFail-instance Show NoMethodError-instance Show Deadlock-instance Show BlockedIndefinitelyOnMVar-instance Show BlockedIndefinitelyOnSTM-instance Show ErrorCall-instance Show RecConError-instance Show RecSelError-instance Show RecUpdError--catch :: Exception e- => IO a -- ^ The computation to run- -> (e -> IO a) -- ^ Handler to invoke if an exception is raised- -> IO a-catch io h = H'98.catch io (h . fromJust . fromException . toException)--throwIO :: Exception e => e -> IO a-throwIO = ioError . fromJust . fromException . toException--throw :: Exception e => e -> a-throw = unsafePerformIO . throwIO--evaluate :: a -> IO a-evaluate x = x `seq` return x--assert :: Bool -> a -> a-assert True x = x-assert False _ = throw (toException (UserError "" "Assertion failed"))--mask :: ((IO a-> IO a) -> IO a) -> IO a-mask action = action restore- where restore act = act--#endif--#ifdef __HUGS__-class (Typeable e, Show e) => Exception e where- toException :: e -> SomeException- fromException :: SomeException -> Maybe e-- toException e = DynamicException (toDyn e) (flip showsPrec e)- fromException (DynamicException dyn _) = fromDynamic dyn- fromException _ = Nothing--INSTANCE_TYPEABLE0(SomeException,someExceptionTc,"SomeException")-INSTANCE_TYPEABLE0(IOException,iOExceptionTc,"IOException")-INSTANCE_TYPEABLE0(ArithException,arithExceptionTc,"ArithException")-INSTANCE_TYPEABLE0(ArrayException,arrayExceptionTc,"ArrayException")-INSTANCE_TYPEABLE0(ExitCode,exitCodeTc,"ExitCode")-INSTANCE_TYPEABLE0(ErrorCall,errorCallTc,"ErrorCall")-INSTANCE_TYPEABLE0(AssertionFailed,assertionFailedTc,"AssertionFailed")-INSTANCE_TYPEABLE0(AsyncException,asyncExceptionTc,"AsyncException")-INSTANCE_TYPEABLE0(BlockedIndefinitelyOnMVar,blockedIndefinitelyOnMVarTc,"BlockedIndefinitelyOnMVar")-INSTANCE_TYPEABLE0(BlockedIndefinitelyOnSTM,blockedIndefinitelyOnSTM,"BlockedIndefinitelyOnSTM")-INSTANCE_TYPEABLE0(Deadlock,deadlockTc,"Deadlock")--instance Exception SomeException where- toException se = se- fromException = Just--instance Exception IOException where- toException = IOException- fromException (IOException e) = Just e- fromException _ = Nothing--instance Exception ArrayException where- toException = ArrayException- fromException (ArrayException e) = Just e- fromException _ = Nothing--instance Exception ArithException where- toException = ArithException- fromException (ArithException e) = Just e- fromException _ = Nothing--instance Exception ExitCode where- toException = ExitException- fromException (ExitException e) = Just e- fromException _ = Nothing--data ErrorCall = ErrorCall String--instance Show ErrorCall where- showsPrec _ (ErrorCall err) = showString err--instance Exception ErrorCall where- toException (ErrorCall s) = Hugs.Exception.ErrorCall s- fromException (Hugs.Exception.ErrorCall s) = Just (ErrorCall s)- fromException _ = Nothing--data BlockedIndefinitelyOnMVar = BlockedIndefinitelyOnMVar-data BlockedIndefinitelyOnSTM = BlockedIndefinitelyOnSTM-data Deadlock = Deadlock-data AssertionFailed = AssertionFailed String-data AsyncException- = StackOverflow- | HeapOverflow- | ThreadKilled- | UserInterrupt- deriving (Eq, Ord)--instance Show BlockedIndefinitelyOnMVar where- showsPrec _ BlockedIndefinitelyOnMVar = showString "thread blocked indefinitely"--instance Show BlockedIndefinitely where- showsPrec _ BlockedIndefinitely = showString "thread blocked indefinitely"--instance Show Deadlock where- showsPrec _ Deadlock = showString "<<deadlock>>"--instance Show AssertionFailed where- showsPrec _ (AssertionFailed err) = showString err--instance Show AsyncException where- showsPrec _ StackOverflow = showString "stack overflow"- showsPrec _ HeapOverflow = showString "heap overflow"- showsPrec _ ThreadKilled = showString "thread killed"- showsPrec _ UserInterrupt = showString "user interrupt"--instance Exception BlockedOnDeadMVar-instance Exception BlockedIndefinitely-instance Exception Deadlock-instance Exception AssertionFailed-instance Exception AsyncException--throw :: Exception e => e -> a-throw e = Hugs.Exception.throw (toException e)--throwIO :: Exception e => e -> IO a-throwIO e = Hugs.Exception.throwIO (toException e)-#endif--#ifndef __GLASGOW_HASKELL__--- Dummy definitions for implementations lacking asynchonous exceptions--block :: IO a -> IO a-block = id-unblock :: IO a -> IO a-unblock = id-blocked :: IO Bool-blocked = return False-#endif---------------------------------------------------------------------------------- Catching exceptions---- |This is the simplest of the exception-catching functions. It--- takes a single argument, runs it, and if an exception is raised--- the \"handler\" is executed, with the value of the exception passed as an--- argument. Otherwise, the result is returned as normal. For example:------ > catch (readFile f)--- > (\e -> do let err = show (e :: IOException)--- > hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err)--- > return "")------ Note that we have to give a type signature to @e@, or the program--- will not typecheck as the type is ambiguous. While it is possible--- to catch exceptions of any type, see the section \"Catching all--- exceptions\" (in "Control.Exception") for an explanation of the problems with doing so.------ For catching exceptions in pure (non-'IO') expressions, see the--- function 'evaluate'.------ Note that due to Haskell\'s unspecified evaluation order, an--- expression may throw one of several possible exceptions: consider--- the expression @(error \"urk\") + (1 \`div\` 0)@. Does--- the expression throw--- @ErrorCall \"urk\"@, or @DivideByZero@?------ The answer is \"it might throw either\"; the choice is--- non-deterministic. If you are catching any type of exception then you--- might catch either. If you are calling @catch@ with type--- @IO Int -> (ArithException -> IO Int) -> IO Int@ then the handler may--- get run with @DivideByZero@ as an argument, or an @ErrorCall \"urk\"@--- exception may be propogated further up. If you call it again, you--- might get a the opposite behaviour. This is ok, because 'catch' is an--- 'IO' computation.------ Note that the "Prelude" also exports a function called--- 'Prelude.catch' with a similar type to 'Control.Exception.catch',--- except that the "Prelude" version only catches the IO and user--- families of exceptions (as required by Haskell 98).------ We recommend either hiding the "Prelude" version of 'Prelude.catch'--- when importing "Control.Exception":------ > import Prelude hiding (catch)------ or importing "Control.Exception" qualified, to avoid name-clashes:------ > import qualified Control.Exception as C------ and then using @C.catch@----#ifndef __NHC__-catch :: Exception e- => IO a -- ^ The computation to run- -> (e -> IO a) -- ^ Handler to invoke if an exception is raised- -> IO a-#if __GLASGOW_HASKELL__-catch = catchException-#elif __HUGS__-catch m h = Hugs.Exception.catchException m h'- where h' e = case fromException e of- Just e' -> h e'- Nothing -> throwIO e-#endif-#endif---- | The function 'catchJust' is like 'catch', but it takes an extra--- argument which is an /exception predicate/, a function which--- selects which type of exceptions we\'re interested in.------ > catchJust (\e -> if isDoesNotExistErrorType (ioeGetErrorType e) then Just () else Nothing)--- > (readFile f)--- > (\_ -> do hPutStrLn stderr ("No such file: " ++ show f)--- > return "")------ Any other exceptions which are not matched by the predicate--- are re-raised, and may be caught by an enclosing--- 'catch', 'catchJust', etc.-catchJust- :: Exception e- => (e -> Maybe b) -- ^ Predicate to select exceptions- -> IO a -- ^ Computation to run- -> (b -> IO a) -- ^ Handler- -> IO a-catchJust p a handler = catch a handler'- where handler' e = case p e of- Nothing -> throwIO e- Just b -> handler b---- | A version of 'catch' with the arguments swapped around; useful in--- situations where the code for the handler is shorter. For example:------ > do handle (\NonTermination -> exitWith (ExitFailure 1)) $--- > ...-handle :: Exception e => (e -> IO a) -> IO a -> IO a-handle = flip catch---- | A version of 'catchJust' with the arguments swapped around (see--- 'handle').-handleJust :: Exception e => (e -> Maybe b) -> (b -> IO a) -> IO a -> IO a-handleJust p = flip (catchJust p)---------------------------------------------------------------------------------- 'mapException'---- | This function maps one exception into another as proposed in the--- paper \"A semantics for imprecise exceptions\".---- Notice that the usage of 'unsafePerformIO' is safe here.--mapException :: (Exception e1, Exception e2) => (e1 -> e2) -> a -> a-mapException f v = unsafePerformIO (catch (evaluate v)- (\x -> throwIO (f x)))---------------------------------------------------------------------------------- 'try' and variations.---- | Similar to 'catch', but returns an 'Either' result which is--- @('Right' a)@ if no exception of type @e@ was raised, or @('Left' ex)@--- if an exception of type @e@ was raised and its value is @ex@.--- If any other type of exception is raised than it will be propogated--- up to the next enclosing exception handler.------ > try a = catch (Right `liftM` a) (return . Left)------ Note that "System.IO.Error" also exports a function called--- 'System.IO.Error.try' with a similar type to 'Control.Exception.try',--- except that it catches only the IO and user families of exceptions--- (as required by the Haskell 98 @IO@ module).--try :: Exception e => IO a -> IO (Either e a)-try a = catch (a >>= \ v -> return (Right v)) (\e -> return (Left e))---- | A variant of 'try' that takes an exception predicate to select--- which exceptions are caught (c.f. 'catchJust'). If the exception--- does not match the predicate, it is re-thrown.-tryJust :: Exception e => (e -> Maybe b) -> IO a -> IO (Either b a)-tryJust p a = do- r <- try a- case r of- Right v -> return (Right v)- Left e -> case p e of- Nothing -> throwIO e- Just b -> return (Left b)---- | Like 'finally', but only performs the final action if there was an--- exception raised by the computation.-onException :: IO a -> IO b -> IO a-onException io what = io `catch` \e -> do _ <- what- throwIO (e :: SomeException)---------------------------------------------------------------------------------- Some Useful Functions---- | When you want to acquire a resource, do some work with it, and--- then release the resource, it is a good idea to use 'bracket',--- because 'bracket' will install the necessary exception handler to--- release the resource in the event that an exception is raised--- during the computation. If an exception is raised, then 'bracket' will--- re-raise the exception (after performing the release).------ A common example is opening a file:------ > bracket--- > (openFile "filename" ReadMode)--- > (hClose)--- > (\fileHandle -> do { ... })------ The arguments to 'bracket' are in this order so that we can partially apply--- it, e.g.:------ > withFile name mode = bracket (openFile name mode) hClose----#ifndef __NHC__-bracket- :: IO a -- ^ computation to run first (\"acquire resource\")- -> (a -> IO b) -- ^ computation to run last (\"release resource\")- -> (a -> IO c) -- ^ computation to run in-between- -> IO c -- returns the value from the in-between computation-bracket before after thing =- mask $ \restore -> do- a <- before- r <- restore (thing a) `onException` after a- _ <- after a- return r-#endif---- | A specialised variant of 'bracket' with just a computation to run--- afterward.----finally :: IO a -- ^ computation to run first- -> IO b -- ^ computation to run afterward (even if an exception- -- was raised)- -> IO a -- returns the value from the first computation-a `finally` sequel =- mask $ \restore -> do- r <- restore a `onException` sequel- _ <- sequel- return r---- | A variant of 'bracket' where the return value from the first computation--- is not required.-bracket_ :: IO a -> IO b -> IO c -> IO c-bracket_ before after thing = bracket before (const after) (const thing)---- | Like 'bracket', but only performs the final action if there was an--- exception raised by the in-between computation.-bracketOnError- :: IO a -- ^ computation to run first (\"acquire resource\")- -> (a -> IO b) -- ^ computation to run last (\"release resource\")- -> (a -> IO c) -- ^ computation to run in-between- -> IO c -- returns the value from the in-between computation-bracketOnError before after thing =- mask $ \restore -> do- a <- before- restore (thing a) `onException` after a--#if !(__GLASGOW_HASKELL__ || __NHC__)-assert :: Bool -> a -> a-assert True x = x-assert False _ = throw (AssertionFailed "")-#endif---------#if __GLASGOW_HASKELL__ || __HUGS__--- |A pattern match failed. The @String@ gives information about the--- source location of the pattern.-data PatternMatchFail = PatternMatchFail String-INSTANCE_TYPEABLE0(PatternMatchFail,patternMatchFailTc,"PatternMatchFail")--instance Show PatternMatchFail where- showsPrec _ (PatternMatchFail err) = showString err--#ifdef __HUGS__-instance Exception PatternMatchFail where- toException (PatternMatchFail err) = Hugs.Exception.PatternMatchFail err- fromException (Hugs.Exception.PatternMatchFail err) = Just (PatternMatchFail err)- fromException _ = Nothing-#else-instance Exception PatternMatchFail-#endif----------- |A record selector was applied to a constructor without the--- appropriate field. This can only happen with a datatype with--- multiple constructors, where some fields are in one constructor--- but not another. The @String@ gives information about the source--- location of the record selector.-data RecSelError = RecSelError String-INSTANCE_TYPEABLE0(RecSelError,recSelErrorTc,"RecSelError")--instance Show RecSelError where- showsPrec _ (RecSelError err) = showString err--#ifdef __HUGS__-instance Exception RecSelError where- toException (RecSelError err) = Hugs.Exception.RecSelError err- fromException (Hugs.Exception.RecSelError err) = Just (RecSelError err)- fromException _ = Nothing-#else-instance Exception RecSelError-#endif----------- |An uninitialised record field was used. The @String@ gives--- information about the source location where the record was--- constructed.-data RecConError = RecConError String-INSTANCE_TYPEABLE0(RecConError,recConErrorTc,"RecConError")--instance Show RecConError where- showsPrec _ (RecConError err) = showString err--#ifdef __HUGS__-instance Exception RecConError where- toException (RecConError err) = Hugs.Exception.RecConError err- fromException (Hugs.Exception.RecConError err) = Just (RecConError err)- fromException _ = Nothing-#else-instance Exception RecConError-#endif----------- |A record update was performed on a constructor without the--- appropriate field. This can only happen with a datatype with--- multiple constructors, where some fields are in one constructor--- but not another. The @String@ gives information about the source--- location of the record update.-data RecUpdError = RecUpdError String-INSTANCE_TYPEABLE0(RecUpdError,recUpdErrorTc,"RecUpdError")--instance Show RecUpdError where- showsPrec _ (RecUpdError err) = showString err--#ifdef __HUGS__-instance Exception RecUpdError where- toException (RecUpdError err) = Hugs.Exception.RecUpdError err- fromException (Hugs.Exception.RecUpdError err) = Just (RecUpdError err)- fromException _ = Nothing-#else-instance Exception RecUpdError-#endif----------- |A class method without a definition (neither a default definition,--- nor a definition in the appropriate instance) was called. The--- @String@ gives information about which method it was.-data NoMethodError = NoMethodError String-INSTANCE_TYPEABLE0(NoMethodError,noMethodErrorTc,"NoMethodError")--instance Show NoMethodError where- showsPrec _ (NoMethodError err) = showString err--#ifdef __HUGS__-instance Exception NoMethodError where- toException (NoMethodError err) = Hugs.Exception.NoMethodError err- fromException (Hugs.Exception.NoMethodError err) = Just (NoMethodError err)- fromException _ = Nothing-#else-instance Exception NoMethodError-#endif----------- |Thrown when the runtime system detects that the computation is--- guaranteed not to terminate. Note that there is no guarantee that--- the runtime system will notice whether any given computation is--- guaranteed to terminate or not.-data NonTermination = NonTermination-INSTANCE_TYPEABLE0(NonTermination,nonTerminationTc,"NonTermination")--instance Show NonTermination where- showsPrec _ NonTermination = showString "<<loop>>"--#ifdef __HUGS__-instance Exception NonTermination where- toException NonTermination = Hugs.Exception.NonTermination- fromException Hugs.Exception.NonTermination = Just NonTermination- fromException _ = Nothing-#else-instance Exception NonTermination-#endif----------- |Thrown when the program attempts to call @atomically@, from the @stm@--- package, inside another call to @atomically@.-data NestedAtomically = NestedAtomically-INSTANCE_TYPEABLE0(NestedAtomically,nestedAtomicallyTc,"NestedAtomically")--instance Show NestedAtomically where- showsPrec _ NestedAtomically = showString "Control.Concurrent.STM.atomically was nested"--instance Exception NestedAtomically---------#endif /* __GLASGOW_HASKELL__ || __HUGS__ */--#ifdef __GLASGOW_HASKELL__-recSelError, recConError, irrefutPatError, runtimeError,- nonExhaustiveGuardsError, patError, noMethodBindingError,- absentError- :: Addr# -> a -- All take a UTF8-encoded C string--recSelError s = throw (RecSelError ("No match in record selector "- ++ unpackCStringUtf8# s)) -- No location info unfortunately-runtimeError s = error (unpackCStringUtf8# s) -- No location info unfortunately-absentError s = error ("Oops! Entered absent arg " ++ unpackCStringUtf8# s)--nonExhaustiveGuardsError s = throw (PatternMatchFail (untangle s "Non-exhaustive guards in"))-irrefutPatError s = throw (PatternMatchFail (untangle s "Irrefutable pattern failed for pattern"))-recConError s = throw (RecConError (untangle s "Missing field in record construction"))-noMethodBindingError s = throw (NoMethodError (untangle s "No instance nor default method for class operation"))-patError s = throw (PatternMatchFail (untangle s "Non-exhaustive patterns in"))---- GHC's RTS calls this-nonTermination :: SomeException-nonTermination = toException NonTermination---- GHC's RTS calls this-nestedAtomically :: SomeException-nestedAtomically = toException NestedAtomically-#endif
@@ -1,372 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ The 'Functor', 'Monad' and 'MonadPlus' classes,--- with some useful operations on monads.--module Control.Monad- (- -- * Functor and monad classes-- Functor(fmap)- , Monad((>>=), (>>), return, fail)-- , MonadPlus ( -- class context: Monad- mzero -- :: (MonadPlus m) => m a- , mplus -- :: (MonadPlus m) => m a -> m a -> m a- )- -- * Functions-- -- ** Naming conventions- -- $naming-- -- ** Basic @Monad@ functions-- , mapM -- :: (Monad m) => (a -> m b) -> [a] -> m [b]- , mapM_ -- :: (Monad m) => (a -> m b) -> [a] -> m ()- , forM -- :: (Monad m) => [a] -> (a -> m b) -> m [b]- , forM_ -- :: (Monad m) => [a] -> (a -> m b) -> m ()- , sequence -- :: (Monad m) => [m a] -> m [a]- , sequence_ -- :: (Monad m) => [m a] -> m ()- , (=<<) -- :: (Monad m) => (a -> m b) -> m a -> m b- , (>=>) -- :: (Monad m) => (a -> m b) -> (b -> m c) -> (a -> m c)- , (<=<) -- :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)- , forever -- :: (Monad m) => m a -> m b- , void-- -- ** Generalisations of list functions-- , join -- :: (Monad m) => m (m a) -> m a- , msum -- :: (MonadPlus m) => [m a] -> m a- , mfilter -- :: (MonadPlus m) => (a -> Bool) -> m a -> m a- , filterM -- :: (Monad m) => (a -> m Bool) -> [a] -> m [a]- , mapAndUnzipM -- :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])- , zipWithM -- :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]- , zipWithM_ -- :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()- , foldM -- :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a - , foldM_ -- :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m ()- , replicateM -- :: (Monad m) => Int -> m a -> m [a]- , replicateM_ -- :: (Monad m) => Int -> m a -> m ()-- -- ** Conditional execution of monadic expressions-- , guard -- :: (MonadPlus m) => Bool -> m ()- , when -- :: (Monad m) => Bool -> m () -> m ()- , unless -- :: (Monad m) => Bool -> m () -> m ()-- -- ** Monadic lifting operators-- , liftM -- :: (Monad m) => (a -> b) -> (m a -> m b)- , liftM2 -- :: (Monad m) => (a -> b -> c) -> (m a -> m b -> m c)- , liftM3 -- :: ...- , liftM4 -- :: ...- , liftM5 -- :: ...-- , ap -- :: (Monad m) => m (a -> b) -> m a -> m b-- ) where--import Data.Maybe--#ifdef __GLASGOW_HASKELL__-import GHC.List-import GHC.Base-#endif--#ifdef __GLASGOW_HASKELL__-infixr 1 =<<---- -------------------------------------------------------------------------------- Prelude monad functions---- | Same as '>>=', but with the arguments interchanged.-{-# SPECIALISE (=<<) :: (a -> [b]) -> [a] -> [b] #-}-(=<<) :: Monad m => (a -> m b) -> m a -> m b-f =<< x = x >>= f---- | Evaluate each action in the sequence from left to right,--- and collect the results.-sequence :: Monad m => [m a] -> m [a] -{-# INLINE sequence #-}-sequence ms = foldr k (return []) ms- where- k m m' = do { x <- m; xs <- m'; return (x:xs) }---- | Evaluate each action in the sequence from left to right,--- and ignore the results.-sequence_ :: Monad m => [m a] -> m () -{-# INLINE sequence_ #-}-sequence_ ms = foldr (>>) (return ()) ms---- | @'mapM' f@ is equivalent to @'sequence' . 'map' f@.-mapM :: Monad m => (a -> m b) -> [a] -> m [b]-{-# INLINE mapM #-}-mapM f as = sequence (map f as)---- | @'mapM_' f@ is equivalent to @'sequence_' . 'map' f@.-mapM_ :: Monad m => (a -> m b) -> [a] -> m ()-{-# INLINE mapM_ #-}-mapM_ f as = sequence_ (map f as)--#endif /* __GLASGOW_HASKELL__ */---- -------------------------------------------------------------------------------- The MonadPlus class definition---- | Monads that also support choice and failure.-class Monad m => MonadPlus m where- -- | the identity of 'mplus'. It should also satisfy the equations- --- -- > mzero >>= f = mzero- -- > v >> mzero = mzero- --- mzero :: m a - -- | an associative operation- mplus :: m a -> m a -> m a--instance MonadPlus [] where- mzero = []- mplus = (++)--instance MonadPlus Maybe where- mzero = Nothing-- Nothing `mplus` ys = ys- xs `mplus` _ys = xs---- -------------------------------------------------------------------------------- Functions mandated by the Prelude---- | @'guard' b@ is @'return' ()@ if @b@ is 'True',--- and 'mzero' if @b@ is 'False'.-guard :: (MonadPlus m) => Bool -> m ()-guard True = return ()-guard False = mzero---- | This generalizes the list-based 'filter' function.--filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]-filterM _ [] = return []-filterM p (x:xs) = do- flg <- p x- ys <- filterM p xs- return (if flg then x:ys else ys)---- | 'forM' is 'mapM' with its arguments flipped-forM :: Monad m => [a] -> (a -> m b) -> m [b]-{-# INLINE forM #-}-forM = flip mapM---- | 'forM_' is 'mapM_' with its arguments flipped-forM_ :: Monad m => [a] -> (a -> m b) -> m ()-{-# INLINE forM_ #-}-forM_ = flip mapM_---- | This generalizes the list-based 'concat' function.--msum :: MonadPlus m => [m a] -> m a-{-# INLINE msum #-}-msum = foldr mplus mzero--infixr 1 <=<, >=>---- | Left-to-right Kleisli composition of monads.-(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)-f >=> g = \x -> f x >>= g---- | Right-to-left Kleisli composition of monads. @('>=>')@, with the arguments flipped-(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)-(<=<) = flip (>=>)---- | @'forever' act@ repeats the action infinitely.-forever :: (Monad m) => m a -> m b-{-# INLINABLE forever #-} -- See Note [Make forever INLINABLE]-forever a = a >> forever a--{- Note [Make forever INLINABLE]--If you say x = forever a-you'll get x = a >> a >> a >> a >> ... etc ...-and that can make a massive space leak (see Trac #5205)--In some monads, where (>>) is expensive, this might be the right-thing, but not in the IO monad. We want to specialise 'forever' for-the IO monad, so that eta expansion happens and there's no space leak.-To achieve this we must make forever INLINABLE, so that it'll get-specialised at call sites.--Still delicate, though, because it depends on optimisation. But there-really is a space/time tradeoff here, and only optimisation reveals-the "right" answer.--}---- | @'void' value@ discards or ignores the result of evaluation, such as the return value of an 'IO' action.-void :: Functor f => f a -> f ()-void = fmap (const ())---- -------------------------------------------------------------------------------- Other monad functions---- | The 'join' function is the conventional monad join operator. It is used to--- remove one level of monadic structure, projecting its bound argument into the--- outer level.-join :: (Monad m) => m (m a) -> m a-join x = x >>= id---- | The 'mapAndUnzipM' function maps its first argument over a list, returning--- the result as a pair of lists. This function is mainly used with complicated--- data structures or a state-transforming monad.-mapAndUnzipM :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])-mapAndUnzipM f xs = sequence (map f xs) >>= return . unzip---- | The 'zipWithM' function generalizes 'zipWith' to arbitrary monads.-zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]-zipWithM f xs ys = sequence (zipWith f xs ys)---- | 'zipWithM_' is the extension of 'zipWithM' which ignores the final result.-zipWithM_ :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()-zipWithM_ f xs ys = sequence_ (zipWith f xs ys)--{- | The 'foldM' function is analogous to 'foldl', except that its result is-encapsulated in a monad. Note that 'foldM' works from left-to-right over-the list arguments. This could be an issue where @('>>')@ and the `folded-function' are not commutative.---> foldM f a1 [x1, x2, ..., xm]--== --> do-> a2 <- f a1 x1-> a3 <- f a2 x2-> ...-> f am xm--If right-to-left evaluation is required, the input list should be reversed.--}--foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a-foldM _ a [] = return a-foldM f a (x:xs) = f a x >>= \fax -> foldM f fax xs---- | Like 'foldM', but discards the result.-foldM_ :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m ()-foldM_ f a xs = foldM f a xs >> return ()---- | @'replicateM' n act@ performs the action @n@ times,--- gathering the results.-replicateM :: (Monad m) => Int -> m a -> m [a]-replicateM n x = sequence (replicate n x)---- | Like 'replicateM', but discards the result.-replicateM_ :: (Monad m) => Int -> m a -> m ()-replicateM_ n x = sequence_ (replicate n x)--{- | Conditional execution of monadic expressions. For example, --> when debug (putStr "Debugging\n")--will output the string @Debugging\\n@ if the Boolean value @debug@ is 'True',-and otherwise do nothing.--}--when :: (Monad m) => Bool -> m () -> m ()-when p s = if p then s else return ()---- | The reverse of 'when'.--unless :: (Monad m) => Bool -> m () -> m ()-unless p s = if p then return () else s---- | Promote a function to a monad.-liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r-liftM f m1 = do { x1 <- m1; return (f x1) }---- | Promote a function to a monad, scanning the monadic arguments from--- left to right. For example,------ > liftM2 (+) [0,1] [0,2] = [0,2,1,3]--- > liftM2 (+) (Just 1) Nothing = Nothing----liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r-liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }---- | Promote a function to a monad, scanning the monadic arguments from--- left to right (cf. 'liftM2').-liftM3 :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r-liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }---- | Promote a function to a monad, scanning the monadic arguments from--- left to right (cf. 'liftM2').-liftM4 :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r-liftM4 f m1 m2 m3 m4 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; return (f x1 x2 x3 x4) }---- | Promote a function to a monad, scanning the monadic arguments from--- left to right (cf. 'liftM2').-liftM5 :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r-liftM5 f m1 m2 m3 m4 m5 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; x5 <- m5; return (f x1 x2 x3 x4 x5) }--{- | In many situations, the 'liftM' operations can be replaced by uses of-'ap', which promotes function application. --> return f `ap` x1 `ap` ... `ap` xn--is equivalent to --> liftMn f x1 x2 ... xn---}--ap :: (Monad m) => m (a -> b) -> m a -> m b-ap = liftM2 id----- -------------------------------------------------------------------------------- Other MonadPlus functions---- | Direct 'MonadPlus' equivalent of 'filter'--- @'filter'@ = @(mfilter:: (a -> Bool) -> [a] -> [a]@--- applicable to any 'MonadPlus', for example--- @mfilter odd (Just 1) == Just 1@--- @mfilter odd (Just 2) == Nothing@--mfilter :: (MonadPlus m) => (a -> Bool) -> m a -> m a-mfilter p ma = do- a <- ma- if p a then return a else mzero--{- $naming--The functions in this library use the following naming conventions: --* A postfix \'@M@\' always stands for a function in the Kleisli category:- The monad type constructor @m@ is added to function results- (modulo currying) and nowhere else. So, for example, --> filter :: (a -> Bool) -> [a] -> [a]-> filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]--* A postfix \'@_@\' changes the result type from @(m a)@ to @(m ())@.- Thus, for example: --> sequence :: Monad m => [m a] -> m [a] -> sequence_ :: Monad m => [m a] -> m () --* A prefix \'@m@\' generalizes an existing function to a monadic form.- Thus, for example: --> sum :: Num a => [a] -> a-> msum :: MonadPlus m => [m a] -> m a---}
@@ -1,98 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.Fix--- Copyright : (c) Andy Gill 2001,--- (c) Oregon Graduate Institute of Science and Technology, 2002--- License : BSD-style (see the file libraries/base/LICENSE)--- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Monadic fixpoints.------ For a detailed discussion, see Levent Erkok's thesis,--- /Value Recursion in Monadic Computations/, Oregon Graduate Institute, 2002.-----------------------------------------------------------------------------------module Control.Monad.Fix (- MonadFix(- mfix -- :: (a -> m a) -> m a- ),- fix -- :: (a -> a) -> a- ) where--import Prelude-import System.IO-import Control.Monad.Instances ()-import Data.Function (fix)-#ifdef __HUGS__-import Hugs.Prelude (MonadFix(mfix))-#endif-#if defined(__GLASGOW_HASKELL__)-import GHC.ST-#endif--#ifndef __HUGS__--- | Monads having fixed points with a \'knot-tying\' semantics.--- Instances of 'MonadFix' should satisfy the following laws:------ [/purity/]--- @'mfix' ('return' . h) = 'return' ('fix' h)@------ [/left shrinking/ (or /tightening/)]--- @'mfix' (\\x -> a >>= \\y -> f x y) = a >>= \\y -> 'mfix' (\\x -> f x y)@------ [/sliding/]--- @'mfix' ('Control.Monad.liftM' h . f) = 'Control.Monad.liftM' h ('mfix' (f . h))@,--- for strict @h@.------ [/nesting/]--- @'mfix' (\\x -> 'mfix' (\\y -> f x y)) = 'mfix' (\\x -> f x x)@------ This class is used in the translation of the recursive @do@ notation--- supported by GHC and Hugs.-class (Monad m) => MonadFix m where- -- | The fixed point of a monadic computation.- -- @'mfix' f@ executes the action @f@ only once, with the eventual- -- output fed back as the input. Hence @f@ should not be strict,- -- for then @'mfix' f@ would diverge.- mfix :: (a -> m a) -> m a-#endif /* !__HUGS__ */---- Instances of MonadFix for Prelude monads---- Maybe:-instance MonadFix Maybe where- mfix f = let a = f (unJust a) in a- where unJust (Just x) = x- unJust Nothing = error "mfix Maybe: Nothing"---- List:-instance MonadFix [] where- mfix f = case fix (f . head) of- [] -> []- (x:_) -> x : mfix (tail . f)---- IO:-instance MonadFix IO where- mfix = fixIO ---- Prelude types with Monad instances in Control.Monad.Instances--instance MonadFix ((->) r) where- mfix f = \ r -> let a = f a r in a--instance MonadFix (Either e) where- mfix f = let a = f (unRight a) in a- where unRight (Right x) = x- unRight (Left _) = error "mfix Either: Left"--#if defined(__GLASGOW_HASKELL__)-instance MonadFix (ST s) where- mfix = fixST-#endif-
@@ -1,41 +0,0 @@-{-# LANGUAGE Safe #-}-{-# OPTIONS_NHC98 --prelude #-}--- This module deliberately declares orphan instances:-{-# OPTIONS_GHC -fno-warn-orphans #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.Instances--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ 'Functor' and 'Monad' instances for @(->) r@ and--- 'Functor' instances for @(,) a@ and @'Either' a@.--module Control.Monad.Instances (Functor(..),Monad(..)) where--import Prelude--instance Functor ((->) r) where- fmap = (.)--instance Monad ((->) r) where- return = const- f >>= k = \ r -> k (f r) r--instance Functor ((,) a) where- fmap f (x,y) = (x, f y)--instance Functor (Either a) where- fmap _ (Left x) = Left x- fmap f (Right y) = Right (f y)--instance Monad (Either e) where- return = Right- Left l >>= _ = Left l- Right r >>= k = k r-
@@ -1,53 +0,0 @@-{-# LANGUAGE Unsafe #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (requires universal quantification for runST)------ This library provides support for /strict/ state threads, as--- described in the PLDI \'94 paper by John Launchbury and Simon Peyton--- Jones /Lazy Functional State Threads/.-----------------------------------------------------------------------------------module Control.Monad.ST (- -- * The 'ST' Monad- ST, -- abstract, instance of Functor, Monad, Typeable.- runST, -- :: (forall s. ST s a) -> a- fixST, -- :: (a -> ST s a) -> ST s a-- -- * Converting 'ST' to 'IO'- RealWorld, -- abstract- stToIO, -- :: ST RealWorld a -> IO a-- -- * Unsafe Functions- unsafeInterleaveST,- unsafeIOToST,- unsafeSTToIO- ) where--import Control.Monad.ST.Safe-import qualified Control.Monad.ST.Unsafe as U--{-# DEPRECATED unsafeInterleaveST, unsafeIOToST, unsafeSTToIO- "Please import from Control.Monad.ST.Unsafe instead; This will be removed in the next release"- #-}--{-# INLINE unsafeInterleaveST #-}-unsafeInterleaveST :: ST s a -> ST s a-unsafeInterleaveST = U.unsafeInterleaveST--{-# INLINE unsafeIOToST #-}-unsafeIOToST :: IO a -> ST s a-unsafeIOToST = U.unsafeIOToST--{-# INLINE unsafeSTToIO #-}-unsafeSTToIO :: ST s a -> IO a-unsafeSTToIO = U.unsafeSTToIO-
@@ -1,73 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Imp--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (requires universal quantification for runST)------ This library provides support for /strict/ state threads, as--- described in the PLDI \'94 paper by John Launchbury and Simon Peyton--- Jones /Lazy Functional State Threads/.------------------------------------------------------------------------------------- #hide-module Control.Monad.ST.Imp (- -- * The 'ST' Monad- ST, -- abstract, instance of Functor, Monad, Typeable.- runST, -- :: (forall s. ST s a) -> a- fixST, -- :: (a -> ST s a) -> ST s a-- -- * Converting 'ST' to 'IO'- RealWorld, -- abstract- stToIO, -- :: ST RealWorld a -> IO a-- -- * Unsafe operations- unsafeInterleaveST, -- :: ST s a -> ST s a- unsafeIOToST, -- :: IO a -> ST s a- unsafeSTToIO -- :: ST s a -> IO a- ) where--#if defined(__GLASGOW_HASKELL__)-import Control.Monad.Fix ()-#else-import Control.Monad.Fix-#endif--#include "Typeable.h"--#if defined(__GLASGOW_HASKELL__)-import GHC.ST ( ST, runST, fixST, unsafeInterleaveST )-import GHC.Base ( RealWorld )-import GHC.IO ( stToIO, unsafeIOToST, unsafeSTToIO )-#elif defined(__HUGS__)-import Data.Typeable-import Hugs.ST-import qualified Hugs.LazyST as LazyST-#endif--#if defined(__HUGS__)-INSTANCE_TYPEABLE2(ST,sTTc,"ST")-INSTANCE_TYPEABLE0(RealWorld,realWorldTc,"RealWorld")--fixST :: (a -> ST s a) -> ST s a-fixST f = LazyST.lazyToStrictST (LazyST.fixST (LazyST.strictToLazyST . f))--unsafeInterleaveST :: ST s a -> ST s a-unsafeInterleaveST =- LazyST.lazyToStrictST . LazyST.unsafeInterleaveST . LazyST.strictToLazyST-#endif--#if !defined(__GLASGOW_HASKELL__)-instance MonadFix (ST s) where- mfix = fixST-#endif--
@@ -1,51 +0,0 @@-{-# LANGUAGE Unsafe #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Lazy--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (requires universal quantification for runST)------ This module presents an identical interface to "Control.Monad.ST",--- except that the monad delays evaluation of state operations until--- a value depending on them is required.-----------------------------------------------------------------------------------module Control.Monad.ST.Lazy (- -- * The 'ST' monad- ST,- runST,- fixST,-- -- * Converting between strict and lazy 'ST'- strictToLazyST, lazyToStrictST,-- -- * Converting 'ST' To 'IO'- RealWorld,- stToIO,-- -- * Unsafe Functions- unsafeInterleaveST,- unsafeIOToST- ) where--import Control.Monad.ST.Lazy.Safe-import qualified Control.Monad.ST.Lazy.Unsafe as U--{-# DEPRECATED unsafeInterleaveST, unsafeIOToST- "Please import from Control.Monad.ST.Lazy.Unsafe instead; This will be removed in the next release"- #-}--{-# INLINE unsafeInterleaveST #-}-unsafeInterleaveST :: ST s a -> ST s a-unsafeInterleaveST = U.unsafeInterleaveST--{-# INLINE unsafeIOToST #-}-unsafeIOToST :: IO a -> ST s a-unsafeIOToST = U.unsafeIOToST-
@@ -1,161 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, MagicHash, UnboxedTuples, Rank2Types #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Lazy.Imp--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (requires universal quantification for runST)------ This module presents an identical interface to "Control.Monad.ST",--- except that the monad delays evaluation of state operations until--- a value depending on them is required.------------------------------------------------------------------------------------- #hide-module Control.Monad.ST.Lazy.Imp (- -- * The 'ST' monad- ST,- runST,- fixST,-- -- * Converting between strict and lazy 'ST'- strictToLazyST, lazyToStrictST,-- -- * Converting 'ST' To 'IO'- RealWorld,- stToIO,-- -- * Unsafe operations- unsafeInterleaveST,- unsafeIOToST- ) where--import Prelude--import Control.Monad.Fix--import qualified Control.Monad.ST.Safe as ST-import qualified Control.Monad.ST.Unsafe as ST--#ifdef __GLASGOW_HASKELL__-import qualified GHC.ST as GHC.ST-import GHC.Base-#endif--#ifdef __HUGS__-import Hugs.LazyST-#endif--#ifdef __GLASGOW_HASKELL__--- | The lazy state-transformer monad.--- A computation of type @'ST' s a@ transforms an internal state indexed--- by @s@, and returns a value of type @a@.--- The @s@ parameter is either------ * an unstantiated type variable (inside invocations of 'runST'), or------ * 'RealWorld' (inside invocations of 'stToIO').------ It serves to keep the internal states of different invocations of--- 'runST' separate from each other and from invocations of 'stToIO'.------ The '>>=' and '>>' operations are not strict in the state. For example,------ @'runST' (writeSTRef _|_ v >>= readSTRef _|_ >> return 2) = 2@-newtype ST s a = ST (State s -> (a, State s))-data State s = S# (State# s)--instance Functor (ST s) where- fmap f m = ST $ \ s ->- let - ST m_a = m- (r,new_s) = m_a s- in- (f r,new_s)--instance Monad (ST s) where-- return a = ST $ \ s -> (a,s)- m >> k = m >>= \ _ -> k-- (ST m) >>= k- = ST $ \ s ->- let- (r,new_s) = m s- ST k_a = k r- in- k_a new_s--{-# NOINLINE runST #-}--- | Return the value computed by a state transformer computation.--- The @forall@ ensures that the internal state used by the 'ST'--- computation is inaccessible to the rest of the program.-runST :: (forall s. ST s a) -> a-runST st = case st of ST the_st -> let (r,_) = the_st (S# realWorld#) in r---- | Allow the result of a state transformer computation to be used (lazily)--- inside the computation.--- Note that if @f@ is strict, @'fixST' f = _|_@.-fixST :: (a -> ST s a) -> ST s a-fixST m = ST (\ s -> - let - ST m_r = m r- (r,s') = m_r s- in- (r,s'))-#endif--instance MonadFix (ST s) where- mfix = fixST---- ------------------------------------------------------------------------------ Strict <--> Lazy--#ifdef __GLASGOW_HASKELL__-{-|-Convert a strict 'ST' computation into a lazy one. The strict state-thread passed to 'strictToLazyST' is not performed until the result of-the lazy state thread it returns is demanded.--}-strictToLazyST :: ST.ST s a -> ST s a-strictToLazyST m = ST $ \s ->- let - pr = case s of { S# s# -> GHC.ST.liftST m s# }- r = case pr of { GHC.ST.STret _ v -> v }- s' = case pr of { GHC.ST.STret s2# _ -> S# s2# }- in- (r, s')--{-| -Convert a lazy 'ST' computation into a strict one.--}-lazyToStrictST :: ST s a -> ST.ST s a-lazyToStrictST (ST m) = GHC.ST.ST $ \s ->- case (m (S# s)) of (a, S# s') -> (# s', a #)-#endif---- | A monad transformer embedding lazy state transformers in the 'IO'--- monad. The 'RealWorld' parameter indicates that the internal state--- used by the 'ST' computation is a special one supplied by the 'IO'--- monad, and thus distinct from those used by invocations of 'runST'.-stToIO :: ST RealWorld a -> IO a-stToIO = ST.stToIO . lazyToStrictST---- ------------------------------------------------------------------------------ Strict <--> Lazy--#ifdef __GLASGOW_HASKELL__-unsafeInterleaveST :: ST s a -> ST s a-unsafeInterleaveST = strictToLazyST . ST.unsafeInterleaveST . lazyToStrictST-#endif--unsafeIOToST :: IO a -> ST s a-unsafeIOToST = strictToLazyST . ST.unsafeIOToST-
@@ -1,36 +0,0 @@-{-# LANGUAGE Trustworthy #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Lazy.Safe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (requires universal quantification for runST)------ This module presents an identical interface to "Control.Monad.ST",--- except that the monad delays evaluation of state operations until--- a value depending on them is required.------ Safe API only.-----------------------------------------------------------------------------------module Control.Monad.ST.Lazy.Safe (- -- * The 'ST' monad- ST,- runST,- fixST,-- -- * Converting between strict and lazy 'ST'- strictToLazyST, lazyToStrictST,-- -- * Converting 'ST' To 'IO'- RealWorld,- stToIO,- ) where--import Control.Monad.ST.Lazy.Imp-
@@ -1,28 +0,0 @@-{-# LANGUAGE Unsafe #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Lazy.Unsafe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (requires universal quantification for runST)------ This module presents an identical interface to "Control.Monad.ST",--- except that the monad delays evaluation of state operations until--- a value depending on them is required.------ Unsafe API.-----------------------------------------------------------------------------------module Control.Monad.ST.Lazy.Unsafe (- -- * Unsafe operations- unsafeInterleaveST,- unsafeIOToST- ) where--import Control.Monad.ST.Lazy.Imp-
@@ -1,33 +0,0 @@-{-# LANGUAGE Trustworthy #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Safe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (requires universal quantification for runST)------ This library provides support for /strict/ state threads, as--- described in the PLDI \'94 paper by John Launchbury and Simon Peyton--- Jones /Lazy Functional State Threads/.------ Safe API Only.-----------------------------------------------------------------------------------module Control.Monad.ST.Safe (- -- * The 'ST' Monad- ST, -- abstract, instance of Functor, Monad, Typeable.- runST, -- :: (forall s. ST s a) -> a- fixST, -- :: (a -> ST s a) -> ST s a-- -- * Converting 'ST' to 'IO'- RealWorld, -- abstract- stToIO, -- :: ST RealWorld a -> IO a- ) where--import Control.Monad.ST.Imp-
@@ -1,20 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Strict--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (requires universal quantification for runST)------ The strict ST monad (re-export of "Control.Monad.ST")-----------------------------------------------------------------------------------module Control.Monad.ST.Strict (- module Control.Monad.ST- ) where--import Control.Monad.ST-
@@ -1,29 +0,0 @@-{-# LANGUAGE Unsafe #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.ST.Unsafe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (requires universal quantification for runST)------ This library provides support for /strict/ state threads, as--- described in the PLDI \'94 paper by John Launchbury and Simon Peyton--- Jones /Lazy Functional State Threads/.------ Unsafe API.-----------------------------------------------------------------------------------module Control.Monad.ST.Unsafe (- -- * Unsafe operations- unsafeInterleaveST,- unsafeIOToST,- unsafeSTToIO- ) where--import Control.Monad.ST.Imp-
@@ -1,55 +0,0 @@-{-# LANGUAGE Safe #-}---------------------------------------------------------------------------------- |--- Module : Control.Monad.Zip--- Copyright : (c) Nils Schweinsberg 2011,--- (c) George Giorgidze 2011--- (c) University Tuebingen 2011--- License : BSD-style (see the file libraries/base/LICENSE)--- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Monadic zipping (used for monad comprehensions)-----------------------------------------------------------------------------------module Control.Monad.Zip where--import Prelude-import Control.Monad (liftM)---- | `MonadZip` type class. Minimal definition: `mzip` or `mzipWith`------ Instances should satisfy the laws:------ * Naturality :------ > liftM (f *** g) (mzip ma mb) = mzip (liftM f ma) (liftM g mb)------ * Information Preservation:------ > liftM (const ()) ma = liftM (const ()) mb--- > ==>--- > munzip (mzip ma mb) = (ma, mb)----class Monad m => MonadZip m where-- mzip :: m a -> m b -> m (a,b)- mzip = mzipWith (,)-- mzipWith :: (a -> b -> c) -> m a -> m b -> m c- mzipWith f ma mb = liftM (uncurry f) (mzip ma mb)-- munzip :: m (a,b) -> (m a, m b)- munzip mab = (liftM fst mab, liftM snd mab)- -- munzip is a member of the class because sometimes- -- you can implement it more efficiently than the- -- above default code. See Trac #4370 comment by giorgidze--instance MonadZip [] where- mzip = zip- mzipWith = zipWith- munzip = unzip-
@@ -1,806 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , ForeignFunctionInterface- , ExistentialQuantification- #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif--#include "Typeable.h"---------------------------------------------------------------------------------- |--- Module : Control.OldException--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (extended exceptions)------ This module provides support for raising and catching both built-in--- and user-defined exceptions.------ In addition to exceptions thrown by 'IO' operations, exceptions may--- be thrown by pure code (imprecise exceptions) or by external events--- (asynchronous exceptions), but may only be caught in the 'IO' monad.--- For more details, see:------ * /A semantics for imprecise exceptions/, by Simon Peyton Jones,--- Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson,--- in /PLDI'99/.------ * /Asynchronous exceptions in Haskell/, by Simon Marlow, Simon Peyton--- Jones, Andy Moran and John Reppy, in /PLDI'01/.-----------------------------------------------------------------------------------module Control.OldException {-# DEPRECATED "Future versions of base will not support the old exceptions style. Please switch to extensible exceptions." #-} (-- -- * The Exception type- Exception(..), -- instance Eq, Ord, Show, Typeable- New.IOException, -- instance Eq, Ord, Show, Typeable- New.ArithException(..), -- instance Eq, Ord, Show, Typeable- New.ArrayException(..), -- instance Eq, Ord, Show, Typeable- New.AsyncException(..), -- instance Eq, Ord, Show, Typeable-- -- * Throwing exceptions- throwIO, -- :: Exception -> IO a- throw, -- :: Exception -> a- ioError, -- :: IOError -> IO a-#ifdef __GLASGOW_HASKELL__- -- XXX Need to restrict the type of this:- New.throwTo, -- :: ThreadId -> Exception -> a-#endif-- -- * Catching Exceptions-- -- |There are several functions for catching and examining- -- exceptions; all of them may only be used from within the- -- 'IO' monad.-- -- ** The @catch@ functions- catch, -- :: IO a -> (Exception -> IO a) -> IO a- catchJust, -- :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a-- -- ** The @handle@ functions- handle, -- :: (Exception -> IO a) -> IO a -> IO a- handleJust,-- :: (Exception -> Maybe b) -> (b -> IO a) -> IO a -> IO a-- -- ** The @try@ functions- try, -- :: IO a -> IO (Either Exception a)- tryJust, -- :: (Exception -> Maybe b) -> a -> IO (Either b a)-- -- ** The @evaluate@ function- evaluate, -- :: a -> IO a-- -- ** The @mapException@ function- mapException, -- :: (Exception -> Exception) -> a -> a-- -- ** Exception predicates- - -- $preds-- ioErrors, -- :: Exception -> Maybe IOError- arithExceptions, -- :: Exception -> Maybe ArithException- errorCalls, -- :: Exception -> Maybe String- dynExceptions, -- :: Exception -> Maybe Dynamic- assertions, -- :: Exception -> Maybe String- asyncExceptions, -- :: Exception -> Maybe AsyncException- userErrors, -- :: Exception -> Maybe String-- -- * Dynamic exceptions-- -- $dynamic- throwDyn, -- :: Typeable ex => ex -> b-#ifdef __GLASGOW_HASKELL__- throwDynTo, -- :: Typeable ex => ThreadId -> ex -> b-#endif- catchDyn, -- :: Typeable ex => IO a -> (ex -> IO a) -> IO a- - -- * Asynchronous Exceptions-- -- $async-- -- ** Asynchronous exception control-- -- |The following two functions allow a thread to control delivery of- -- asynchronous exceptions during a critical region.-- block, -- :: IO a -> IO a- unblock, -- :: IO a -> IO a-- -- *** Applying @block@ to an exception handler-- -- $block_handler-- -- *** Interruptible operations-- -- $interruptible-- -- * Assertions-- assert, -- :: Bool -> a -> a-- -- * Utilities-- bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO ()- bracket_, -- :: IO a -> IO b -> IO c -> IO ()- bracketOnError,-- finally, -- :: IO a -> IO b -> IO a- -#ifdef __GLASGOW_HASKELL__- setUncaughtExceptionHandler, -- :: (Exception -> IO ()) -> IO ()- getUncaughtExceptionHandler -- :: IO (Exception -> IO ())-#endif- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Show--- import GHC.IO ( IO )-import GHC.IO.Handle.FD ( stdout )-import qualified GHC.IO as New-import qualified GHC.IO.Exception as New-import GHC.Conc hiding (setUncaughtExceptionHandler,- getUncaughtExceptionHandler)-import Data.IORef ( IORef, newIORef, readIORef, writeIORef )-import Foreign.C.String ( CString, withCString )-import GHC.IO.Handle ( hFlush )-#endif--#ifdef __HUGS__-import Prelude hiding (catch)-import Hugs.Prelude as New (ExitCode(..))-#endif--import qualified Control.Exception as New-import Control.Exception ( toException, fromException, throw, block, unblock, mask, evaluate, throwIO )-import System.IO.Error hiding ( catch, try )-import System.IO.Unsafe (unsafePerformIO)-import Data.Dynamic-import Data.Either-import Data.Maybe--#ifdef __NHC__-import System.IO.Error (catch, ioError)-import IO (bracket)-import DIOError -- defn of IOError type---- minimum needed for nhc98 to pretend it has Exceptions-type Exception = IOError-type IOException = IOError-data ArithException-data ArrayException-data AsyncException--throwIO :: Exception -> IO a-throwIO = ioError-throw :: Exception -> a-throw = unsafePerformIO . throwIO--evaluate :: a -> IO a-evaluate x = x `seq` return x--ioErrors :: Exception -> Maybe IOError-ioErrors e = Just e-arithExceptions :: Exception -> Maybe ArithException-arithExceptions = const Nothing-errorCalls :: Exception -> Maybe String-errorCalls = const Nothing-dynExceptions :: Exception -> Maybe Dynamic-dynExceptions = const Nothing-assertions :: Exception -> Maybe String-assertions = const Nothing-asyncExceptions :: Exception -> Maybe AsyncException-asyncExceptions = const Nothing-userErrors :: Exception -> Maybe String-userErrors (UserError _ s) = Just s-userErrors _ = Nothing--block :: IO a -> IO a-block = id-unblock :: IO a -> IO a-unblock = id--assert :: Bool -> a -> a-assert True x = x-assert False _ = throw (UserError "" "Assertion failed")-#endif---------------------------------------------------------------------------------- Catching exceptions---- |This is the simplest of the exception-catching functions. It--- takes a single argument, runs it, and if an exception is raised--- the \"handler\" is executed, with the value of the exception passed as an--- argument. Otherwise, the result is returned as normal. For example:------ > catch (openFile f ReadMode) --- > (\e -> hPutStr stderr ("Couldn't open "++f++": " ++ show e))------ For catching exceptions in pure (non-'IO') expressions, see the--- function 'evaluate'.------ Note that due to Haskell\'s unspecified evaluation order, an--- expression may return one of several possible exceptions: consider--- the expression @error \"urk\" + 1 \`div\` 0@. Does--- 'catch' execute the handler passing--- @ErrorCall \"urk\"@, or @ArithError DivideByZero@?------ The answer is \"either\": 'catch' makes a--- non-deterministic choice about which exception to catch. If you--- call it again, you might get a different exception back. This is--- ok, because 'catch' is an 'IO' computation.------ Note that 'catch' catches all types of exceptions, and is generally--- used for \"cleaning up\" before passing on the exception using--- 'throwIO'. It is not good practice to discard the exception and--- continue, without first checking the type of the exception (it--- might be a 'ThreadKilled', for example). In this case it is usually better--- to use 'catchJust' and select the kinds of exceptions to catch.------ Also note that the "Prelude" also exports a function called--- 'Prelude.catch' with a similar type to 'Control.OldException.catch',--- except that the "Prelude" version only catches the IO and user--- families of exceptions (as required by Haskell 98). ------ We recommend either hiding the "Prelude" version of 'Prelude.catch'--- when importing "Control.OldException": ------ > import Prelude hiding (catch)------ or importing "Control.OldException" qualified, to avoid name-clashes:------ > import qualified Control.OldException as C------ and then using @C.catch@-----catch :: IO a -- ^ The computation to run- -> (Exception -> IO a) -- ^ Handler to invoke if an exception is raised- -> IO a--- note: bundling the exceptions is done in the New.Exception--- instance of Exception; see below.-catch = New.catch---- | The function 'catchJust' is like 'catch', but it takes an extra--- argument which is an /exception predicate/, a function which--- selects which type of exceptions we\'re interested in. There are--- some predefined exception predicates for useful subsets of--- exceptions: 'ioErrors', 'arithExceptions', and so on. For example,--- to catch just calls to the 'error' function, we could use------ > result <- catchJust errorCalls thing_to_try handler------ Any other exceptions which are not matched by the predicate--- are re-raised, and may be caught by an enclosing--- 'catch' or 'catchJust'.-catchJust- :: (Exception -> Maybe b) -- ^ Predicate to select exceptions- -> IO a -- ^ Computation to run- -> (b -> IO a) -- ^ Handler- -> IO a-catchJust p a handler = catch a handler'- where handler' e = case p e of - Nothing -> throw e- Just b -> handler b---- | A version of 'catch' with the arguments swapped around; useful in--- situations where the code for the handler is shorter. For example:------ > do handle (\e -> exitWith (ExitFailure 1)) $--- > ...-handle :: (Exception -> IO a) -> IO a -> IO a-handle = flip catch---- | A version of 'catchJust' with the arguments swapped around (see--- 'handle').-handleJust :: (Exception -> Maybe b) -> (b -> IO a) -> IO a -> IO a-handleJust p = flip (catchJust p)---------------------------------------------------------------------------------- 'mapException'---- | This function maps one exception into another as proposed in the--- paper \"A semantics for imprecise exceptions\".---- Notice that the usage of 'unsafePerformIO' is safe here.--mapException :: (Exception -> Exception) -> a -> a-mapException f v = unsafePerformIO (catch (evaluate v)- (\x -> throw (f x)))---------------------------------------------------------------------------------- 'try' and variations.---- | Similar to 'catch', but returns an 'Either' result which is--- @('Right' a)@ if no exception was raised, or @('Left' e)@ if an--- exception was raised and its value is @e@.------ > try a = catch (Right `liftM` a) (return . Left)------ Note: as with 'catch', it is only polite to use this variant if you intend--- to re-throw the exception after performing whatever cleanup is needed.--- Otherwise, 'tryJust' is generally considered to be better.------ Also note that "System.IO.Error" also exports a function called--- 'System.IO.Error.try' with a similar type to 'Control.OldException.try',--- except that it catches only the IO and user families of exceptions--- (as required by the Haskell 98 @IO@ module).--try :: IO a -> IO (Either Exception a)-try a = catch (a >>= \ v -> return (Right v)) (\e -> return (Left e))---- | A variant of 'try' that takes an exception predicate to select--- which exceptions are caught (c.f. 'catchJust'). If the exception--- does not match the predicate, it is re-thrown.-tryJust :: (Exception -> Maybe b) -> IO a -> IO (Either b a)-tryJust p a = do- r <- try a- case r of- Right v -> return (Right v)- Left e -> case p e of- Nothing -> throw e- Just b -> return (Left b)---------------------------------------------------------------------------------- Dynamic exceptions---- $dynamic--- #DynamicExceptions# Because the 'Exception' datatype is not extensible, there is an--- interface for throwing and catching exceptions of type 'Dynamic'--- (see "Data.Dynamic") which allows exception values of any type in--- the 'Typeable' class to be thrown and caught.---- | Raise any value as an exception, provided it is in the--- 'Typeable' class.-throwDyn :: Typeable exception => exception -> b-#ifdef __NHC__-throwDyn exception = throw (UserError "" "dynamic exception")-#else-throwDyn exception = throw (DynException (toDyn exception))-#endif--#ifdef __GLASGOW_HASKELL__--- | A variant of 'throwDyn' that throws the dynamic exception to an--- arbitrary thread (GHC only: c.f. 'throwTo').-throwDynTo :: Typeable exception => ThreadId -> exception -> IO ()-throwDynTo t exception = New.throwTo t (DynException (toDyn exception))-#endif /* __GLASGOW_HASKELL__ */---- | Catch dynamic exceptions of the required type. All other--- exceptions are re-thrown, including dynamic exceptions of the wrong--- type.------ When using dynamic exceptions it is advisable to define a new--- datatype to use for your exception type, to avoid possible clashes--- with dynamic exceptions used in other libraries.----catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a-#ifdef __NHC__-catchDyn m k = m -- can't catch dyn exceptions in nhc98-#else-catchDyn m k = New.catch m handler- where handler ex = case ex of- (DynException dyn) ->- case fromDynamic dyn of- Just exception -> k exception- Nothing -> throw ex- _ -> throw ex-#endif---------------------------------------------------------------------------------- Exception Predicates---- $preds--- These pre-defined predicates may be used as the first argument to--- 'catchJust', 'tryJust', or 'handleJust' to select certain common--- classes of exceptions.-#ifndef __NHC__-ioErrors :: Exception -> Maybe IOError-arithExceptions :: Exception -> Maybe New.ArithException-errorCalls :: Exception -> Maybe String-assertions :: Exception -> Maybe String-dynExceptions :: Exception -> Maybe Dynamic-asyncExceptions :: Exception -> Maybe New.AsyncException-userErrors :: Exception -> Maybe String--ioErrors (IOException e) = Just e-ioErrors _ = Nothing--arithExceptions (ArithException e) = Just e-arithExceptions _ = Nothing--errorCalls (ErrorCall e) = Just e-errorCalls _ = Nothing--assertions (AssertionFailed e) = Just e-assertions _ = Nothing--dynExceptions (DynException e) = Just e-dynExceptions _ = Nothing--asyncExceptions (AsyncException e) = Just e-asyncExceptions _ = Nothing--userErrors (IOException e) | isUserError e = Just (ioeGetErrorString e)-userErrors _ = Nothing-#endif--------------------------------------------------------------------------------- Some Useful Functions---- | When you want to acquire a resource, do some work with it, and--- then release the resource, it is a good idea to use 'bracket',--- because 'bracket' will install the necessary exception handler to--- release the resource in the event that an exception is raised--- during the computation. If an exception is raised, then 'bracket' will --- re-raise the exception (after performing the release).------ A common example is opening a file:------ > bracket--- > (openFile "filename" ReadMode)--- > (hClose)--- > (\handle -> do { ... })------ The arguments to 'bracket' are in this order so that we can partially apply --- it, e.g.:------ > withFile name mode = bracket (openFile name mode) hClose----#ifndef __NHC__-bracket - :: IO a -- ^ computation to run first (\"acquire resource\")- -> (a -> IO b) -- ^ computation to run last (\"release resource\")- -> (a -> IO c) -- ^ computation to run in-between- -> IO c -- returns the value from the in-between computation-bracket before after thing =- mask $ \restore -> do- a <- before - r <- catch - (restore (thing a))- (\e -> do { _ <- after a; throw e })- _ <- after a- return r-#endif---- | A specialised variant of 'bracket' with just a computation to run--- afterward.--- -finally :: IO a -- ^ computation to run first- -> IO b -- ^ computation to run afterward (even if an exception - -- was raised)- -> IO a -- returns the value from the first computation-a `finally` sequel =- mask $ \restore -> do- r <- catch - (restore a)- (\e -> do { _ <- sequel; throw e })- _ <- sequel- return r---- | A variant of 'bracket' where the return value from the first computation--- is not required.-bracket_ :: IO a -> IO b -> IO c -> IO c-bracket_ before after thing = bracket before (const after) (const thing)---- | Like bracket, but only performs the final action if there was an --- exception raised by the in-between computation.-bracketOnError- :: IO a -- ^ computation to run first (\"acquire resource\")- -> (a -> IO b) -- ^ computation to run last (\"release resource\")- -> (a -> IO c) -- ^ computation to run in-between- -> IO c -- returns the value from the in-between computation-bracketOnError before after thing =- mask $ \restore -> do- a <- before - catch - (restore (thing a))- (\e -> do { _ <- after a; throw e })---- -------------------------------------------------------------------------------- Asynchronous exceptions--{- $async-- #AsynchronousExceptions# Asynchronous exceptions are so-called because they arise due to-external influences, and can be raised at any point during execution.-'StackOverflow' and 'HeapOverflow' are two examples of-system-generated asynchronous exceptions.--The primary source of asynchronous exceptions, however, is-'throwTo':--> throwTo :: ThreadId -> Exception -> IO ()--'throwTo' (also 'throwDynTo' and 'Control.Concurrent.killThread') allows one-running thread to raise an arbitrary exception in another thread. The-exception is therefore asynchronous with respect to the target thread,-which could be doing anything at the time it receives the exception.-Great care should be taken with asynchronous exceptions; it is all too-easy to introduce race conditions by the over zealous use of-'throwTo'.--}--{- $block_handler-There\'s an implied 'mask_' around every exception handler in a call-to one of the 'catch' family of functions. This is because that is-what you want most of the time - it eliminates a common race condition-in starting an exception handler, because there may be no exception-handler on the stack to handle another exception if one arrives-immediately. If asynchronous exceptions are blocked on entering the-handler, though, we have time to install a new exception handler-before being interrupted. If this weren\'t the default, one would have-to write something like--> mask $ \restore ->-> catch (restore (...))-> (\e -> handler)--If you need to unblock asynchronous exceptions again in the exception-handler, just use 'unblock' as normal.--Note that 'try' and friends /do not/ have a similar default, because-there is no exception handler in this case. If you want to use 'try'-in an asynchronous-exception-safe way, you will need to use-'mask'.--}--{- $interruptible--Some operations are /interruptible/, which means that they can receive-asynchronous exceptions even in the scope of a 'mask'. Any function-which may itself block is defined as interruptible; this includes-'Control.Concurrent.MVar.takeMVar'-(but not 'Control.Concurrent.MVar.tryTakeMVar'),-and most operations which perform-some I\/O with the outside world. The reason for having-interruptible operations is so that we can write things like--> mask $ \restore -> do-> a <- takeMVar m-> catch (restore (...))-> (\e -> ...)--if the 'Control.Concurrent.MVar.takeMVar' was not interruptible,-then this particular-combination could lead to deadlock, because the thread itself would be-blocked in a state where it can\'t receive any asynchronous exceptions.-With 'Control.Concurrent.MVar.takeMVar' interruptible, however, we can be-safe in the knowledge that the thread can receive exceptions right up-until the point when the 'Control.Concurrent.MVar.takeMVar' succeeds.-Similar arguments apply for other interruptible operations like-'System.IO.openFile'.--}--#if !(__GLASGOW_HASKELL__ || __NHC__)-assert :: Bool -> a -> a-assert True x = x-assert False _ = throw (AssertionFailed "")-#endif---#ifdef __GLASGOW_HASKELL__-{-# NOINLINE uncaughtExceptionHandler #-}-uncaughtExceptionHandler :: IORef (Exception -> IO ())-uncaughtExceptionHandler = unsafePerformIO (newIORef defaultHandler)- where- defaultHandler :: Exception -> IO ()- defaultHandler ex = do- (hFlush stdout) `New.catchAny` (\ _ -> return ())- let msg = case ex of- Deadlock -> "no threads to run: infinite loop or deadlock?"- ErrorCall s -> s- other -> showsPrec 0 other ""- withCString "%s" $ \cfmt ->- withCString msg $ \cmsg ->- errorBelch cfmt cmsg---- don't use errorBelch() directly, because we cannot call varargs functions--- using the FFI.-foreign import ccall unsafe "HsBase.h errorBelch2"- errorBelch :: CString -> CString -> IO ()--setUncaughtExceptionHandler :: (Exception -> IO ()) -> IO ()-setUncaughtExceptionHandler = writeIORef uncaughtExceptionHandler--getUncaughtExceptionHandler :: IO (Exception -> IO ())-getUncaughtExceptionHandler = readIORef uncaughtExceptionHandler-#endif---- --------------------------------------------------------------------------- Exception datatype and operations---- |The type of exceptions. Every kind of system-generated exception--- has a constructor in the 'Exception' type, and values of other--- types may be injected into 'Exception' by coercing them to--- 'Data.Dynamic.Dynamic' (see the section on Dynamic Exceptions:--- "Control.OldException\#DynamicExceptions").-data Exception- = ArithException New.ArithException- -- ^Exceptions raised by arithmetic- -- operations. (NOTE: GHC currently does not throw- -- 'ArithException's except for 'DivideByZero').- | ArrayException New.ArrayException- -- ^Exceptions raised by array-related- -- operations. (NOTE: GHC currently does not throw- -- 'ArrayException's).- | AssertionFailed String- -- ^This exception is thrown by the- -- 'assert' operation when the condition- -- fails. The 'String' argument contains the- -- location of the assertion in the source program.- | AsyncException New.AsyncException- -- ^Asynchronous exceptions (see section on Asynchronous Exceptions: "Control.OldException\#AsynchronousExceptions").- | BlockedOnDeadMVar- -- ^The current thread was executing a call to- -- 'Control.Concurrent.MVar.takeMVar' that could never return,- -- because there are no other references to this 'MVar'.- | BlockedIndefinitely- -- ^The current thread was waiting to retry an atomic memory transaction- -- that could never become possible to complete because there are no other- -- threads referring to any of the TVars involved.- | NestedAtomically- -- ^The runtime detected an attempt to nest one STM transaction- -- inside another one, presumably due to the use of - -- 'unsafePeformIO' with 'atomically'.- | Deadlock- -- ^There are no runnable threads, so the program is- -- deadlocked. The 'Deadlock' exception is- -- raised in the main thread only (see also: "Control.Concurrent").- | DynException Dynamic- -- ^Dynamically typed exceptions (see section on Dynamic Exceptions: "Control.OldException\#DynamicExceptions").- | ErrorCall String- -- ^The 'ErrorCall' exception is thrown by 'error'. The 'String'- -- argument of 'ErrorCall' is the string passed to 'error' when it was- -- called.- | ExitException New.ExitCode- -- ^The 'ExitException' exception is thrown by 'System.Exit.exitWith' (and- -- 'System.Exit.exitFailure'). The 'ExitCode' argument is the value passed - -- to 'System.Exit.exitWith'. An unhandled 'ExitException' exception in the- -- main thread will cause the program to be terminated with the given - -- exit code.- | IOException New.IOException- -- ^These are the standard IO exceptions generated by- -- Haskell\'s @IO@ operations. See also "System.IO.Error".- | NoMethodError String- -- ^An attempt was made to invoke a class method which has- -- no definition in this instance, and there was no default- -- definition given in the class declaration. GHC issues a- -- warning when you compile an instance which has missing- -- methods.- | NonTermination- -- ^The current thread is stuck in an infinite loop. This- -- exception may or may not be thrown when the program is- -- non-terminating.- | PatternMatchFail String- -- ^A pattern matching failure. The 'String' argument should contain a- -- descriptive message including the function name, source file- -- and line number.- | RecConError String- -- ^An attempt was made to evaluate a field of a record- -- for which no value was given at construction time. The- -- 'String' argument gives the location of the- -- record construction in the source program.- | RecSelError String- -- ^A field selection was attempted on a constructor that- -- doesn\'t have the requested field. This can happen with- -- multi-constructor records when one or more fields are- -- missing from some of the constructors. The- -- 'String' argument gives the location of the- -- record selection in the source program.- | RecUpdError String- -- ^An attempt was made to update a field in a record,- -- where the record doesn\'t have the requested field. This can- -- only occur with multi-constructor records, when one or more- -- fields are missing from some of the constructors. The- -- 'String' argument gives the location of the- -- record update in the source program.-INSTANCE_TYPEABLE0(Exception,exceptionTc,"Exception")---- helper type for simplifying the type casting logic below-data Caster = forall e . New.Exception e => Caster (e -> Exception)--instance New.Exception Exception where- -- We need to collect all the sorts of exceptions that used to be- -- bundled up into the Exception type, and rebundle them for- -- legacy handlers.- fromException exc0 = foldr tryCast Nothing casters where- tryCast (Caster f) e = case fromException exc0 of- Just exc -> Just (f exc)- _ -> e- casters =- [Caster (\exc -> ArithException exc),- Caster (\exc -> ArrayException exc),- Caster (\(New.AssertionFailed err) -> AssertionFailed err),- Caster (\exc -> AsyncException exc),- Caster (\New.BlockedIndefinitelyOnMVar -> BlockedOnDeadMVar),- Caster (\New.BlockedIndefinitelyOnSTM -> BlockedIndefinitely),- Caster (\New.NestedAtomically -> NestedAtomically),- Caster (\New.Deadlock -> Deadlock),- Caster (\exc -> DynException exc),- Caster (\(New.ErrorCall err) -> ErrorCall err),- Caster (\exc -> ExitException exc),- Caster (\exc -> IOException exc),- Caster (\(New.NoMethodError err) -> NoMethodError err),- Caster (\New.NonTermination -> NonTermination),- Caster (\(New.PatternMatchFail err) -> PatternMatchFail err),- Caster (\(New.RecConError err) -> RecConError err),- Caster (\(New.RecSelError err) -> RecSelError err),- Caster (\(New.RecUpdError err) -> RecUpdError err),- -- Anything else gets taken as a Dynamic exception. It's- -- important that we put all exceptions into the old Exception- -- type somehow, or throwing a new exception wouldn't cause- -- the cleanup code for bracket, finally etc to happen.- Caster (\exc -> DynException (toDyn (exc :: New.SomeException)))]-- -- Unbundle exceptions.- toException (ArithException exc) = toException exc- toException (ArrayException exc) = toException exc- toException (AssertionFailed err) = toException (New.AssertionFailed err)- toException (AsyncException exc) = toException exc- toException BlockedOnDeadMVar = toException New.BlockedIndefinitelyOnMVar- toException BlockedIndefinitely = toException New.BlockedIndefinitelyOnSTM- toException NestedAtomically = toException New.NestedAtomically- toException Deadlock = toException New.Deadlock- -- If a dynamic exception is a SomeException then resurrect it, so- -- that bracket, catch+throw etc rethrow the same exception even- -- when the exception is in the new style.- -- If it's not a SomeException, then just throw the Dynamic.- toException (DynException exc) = case fromDynamic exc of- Just exc' -> exc'- Nothing -> toException exc- toException (ErrorCall err) = toException (New.ErrorCall err)- toException (ExitException exc) = toException exc- toException (IOException exc) = toException exc- toException (NoMethodError err) = toException (New.NoMethodError err)- toException NonTermination = toException New.NonTermination- toException (PatternMatchFail err) = toException (New.PatternMatchFail err)- toException (RecConError err) = toException (New.RecConError err)- toException (RecSelError err) = toException (New.RecSelError err)- toException (RecUpdError err) = toException (New.RecUpdError err)--instance Show Exception where- showsPrec _ (IOException err) = shows err- showsPrec _ (ArithException err) = shows err- showsPrec _ (ArrayException err) = shows err- showsPrec _ (ErrorCall err) = showString err- showsPrec _ (ExitException err) = showString "exit: " . shows err- showsPrec _ (NoMethodError err) = showString err- showsPrec _ (PatternMatchFail err) = showString err- showsPrec _ (RecSelError err) = showString err- showsPrec _ (RecConError err) = showString err- showsPrec _ (RecUpdError err) = showString err- showsPrec _ (AssertionFailed err) = showString err- showsPrec _ (DynException err) = showString "exception :: " . showsTypeRep (dynTypeRep err)- showsPrec _ (AsyncException e) = shows e- showsPrec p BlockedOnDeadMVar = showsPrec p New.BlockedIndefinitelyOnMVar- showsPrec p BlockedIndefinitely = showsPrec p New.BlockedIndefinitelyOnSTM- showsPrec p NestedAtomically = showsPrec p New.NestedAtomically- showsPrec p NonTermination = showsPrec p New.NonTermination- showsPrec p Deadlock = showsPrec p New.Deadlock--instance Eq Exception where- IOException e1 == IOException e2 = e1 == e2- ArithException e1 == ArithException e2 = e1 == e2- ArrayException e1 == ArrayException e2 = e1 == e2- ErrorCall e1 == ErrorCall e2 = e1 == e2- ExitException e1 == ExitException e2 = e1 == e2- NoMethodError e1 == NoMethodError e2 = e1 == e2- PatternMatchFail e1 == PatternMatchFail e2 = e1 == e2- RecSelError e1 == RecSelError e2 = e1 == e2- RecConError e1 == RecConError e2 = e1 == e2- RecUpdError e1 == RecUpdError e2 = e1 == e2- AssertionFailed e1 == AssertionFailed e2 = e1 == e2- DynException _ == DynException _ = False -- incomparable- AsyncException e1 == AsyncException e2 = e1 == e2- BlockedOnDeadMVar == BlockedOnDeadMVar = True- NonTermination == NonTermination = True- NestedAtomically == NestedAtomically = True- Deadlock == Deadlock = True- _ == _ = False-
@@ -1,410 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, BangPatterns, MagicHash #-}---------------------------------------------------------------------------------- |--- Module : Data.Bits--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ This module defines bitwise operations for signed and unsigned--- integers. Instances of the class 'Bits' for the 'Int' and--- 'Integer' types are available from this module, and instances for--- explicitly sized integral types are available from the--- "Data.Int" and "Data.Word" modules.-----------------------------------------------------------------------------------module Data.Bits ( - Bits(- (.&.), (.|.), xor, -- :: a -> a -> a- complement, -- :: a -> a- shift, -- :: a -> Int -> a- rotate, -- :: a -> Int -> a- bit, -- :: Int -> a- setBit, -- :: a -> Int -> a- clearBit, -- :: a -> Int -> a- complementBit, -- :: a -> Int -> a- testBit, -- :: a -> Int -> Bool- bitSize, -- :: a -> Int- isSigned, -- :: a -> Bool- shiftL, shiftR, -- :: a -> Int -> a- unsafeShiftL, unsafeShiftR, -- :: a -> Int -> a- rotateL, rotateR, -- :: a -> Int -> a- popCount -- :: a -> Int- )-- -- instance Bits Int- -- instance Bits Integer- ) where---- Defines the @Bits@ class containing bit-based operations.--- See library document for details on the semantics of the--- individual operations.--#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)-#include "MachDeps.h"-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Num-import GHC.Base-#endif--#ifdef __HUGS__-import Hugs.Bits-#endif--infixl 8 `shift`, `rotate`, `shiftL`, `shiftR`, `rotateL`, `rotateR`-infixl 7 .&.-infixl 6 `xor`-infixl 5 .|.--{-| -The 'Bits' class defines bitwise operations over integral types.--* Bits are numbered from 0 with bit 0 being the least- significant bit.--Minimal complete definition: '.&.', '.|.', 'xor', 'complement',-('shift' or ('shiftL' and 'shiftR')), ('rotate' or ('rotateL' and 'rotateR')),-'bitSize' and 'isSigned'.--}-class (Eq a, Num a) => Bits a where- -- | Bitwise \"and\"- (.&.) :: a -> a -> a-- -- | Bitwise \"or\"- (.|.) :: a -> a -> a-- -- | Bitwise \"xor\"- xor :: a -> a -> a-- {-| Reverse all the bits in the argument -}- complement :: a -> a-- {-| @'shift' x i@ shifts @x@ left by @i@ bits if @i@ is positive,- or right by @-i@ bits otherwise.- Right shifts perform sign extension on signed number types;- i.e. they fill the top bits with 1 if the @x@ is negative- and with 0 otherwise.-- An instance can define either this unified 'shift' or 'shiftL' and- 'shiftR', depending on which is more convenient for the type in- question. -}- shift :: a -> Int -> a-- x `shift` i | i<0 = x `shiftR` (-i)- | i>0 = x `shiftL` i- | otherwise = x-- {-| @'rotate' x i@ rotates @x@ left by @i@ bits if @i@ is positive,- or right by @-i@ bits otherwise.-- For unbounded types like 'Integer', 'rotate' is equivalent to 'shift'.-- An instance can define either this unified 'rotate' or 'rotateL' and- 'rotateR', depending on which is more convenient for the type in- question. -}- rotate :: a -> Int -> a-- x `rotate` i | i<0 = x `rotateR` (-i)- | i>0 = x `rotateL` i- | otherwise = x-- {-- -- Rotation can be implemented in terms of two shifts, but care is- -- needed for negative values. This suggested implementation assumes- -- 2's-complement arithmetic. It is commented out because it would- -- require an extra context (Ord a) on the signature of 'rotate'.- x `rotate` i | i<0 && isSigned x && x<0- = let left = i+bitSize x in- ((x `shift` i) .&. complement ((-1) `shift` left))- .|. (x `shift` left)- | i<0 = (x `shift` i) .|. (x `shift` (i+bitSize x))- | i==0 = x- | i>0 = (x `shift` i) .|. (x `shift` (i-bitSize x))- -}-- -- | @bit i@ is a value with the @i@th bit set and all other bits clear- bit :: Int -> a-- -- | @x \`setBit\` i@ is the same as @x .|. bit i@- setBit :: a -> Int -> a-- -- | @x \`clearBit\` i@ is the same as @x .&. complement (bit i)@- clearBit :: a -> Int -> a-- -- | @x \`complementBit\` i@ is the same as @x \`xor\` bit i@- complementBit :: a -> Int -> a-- -- | Return 'True' if the @n@th bit of the argument is 1- testBit :: a -> Int -> Bool-- {-| Return the number of bits in the type of the argument. The actual- value of the argument is ignored. The function 'bitSize' is- undefined for types that do not have a fixed bitsize, like 'Integer'.- -}- bitSize :: a -> Int-- {-| Return 'True' if the argument is a signed type. The actual- value of the argument is ignored -}- isSigned :: a -> Bool-- {-# INLINE bit #-}- {-# INLINE setBit #-}- {-# INLINE clearBit #-}- {-# INLINE complementBit #-}- {-# INLINE testBit #-}- bit i = 1 `shiftL` i- x `setBit` i = x .|. bit i- x `clearBit` i = x .&. complement (bit i)- x `complementBit` i = x `xor` bit i- x `testBit` i = (x .&. bit i) /= 0-- {-| Shift the argument left by the specified number of bits- (which must be non-negative).-- An instance can define either this and 'shiftR' or the unified- 'shift', depending on which is more convenient for the type in- question. -}- shiftL :: a -> Int -> a- {-# INLINE shiftL #-}- x `shiftL` i = x `shift` i-- {-| Shift the argument left by the specified number of bits. The- result is undefined for negative shift amounts and shift amounts- greater or equal to the 'bitSize'.-- Defaults to 'shiftL' unless defined explicitly by an instance. -}- unsafeShiftL :: a -> Int -> a- {-# INLINE unsafeShiftL #-}- x `unsafeShiftL` i = x `shiftL` i-- {-| Shift the first argument right by the specified number of bits. The- result is undefined for negative shift amounts and shift amounts- greater or equal to the 'bitSize'.-- Right shifts perform sign extension on signed number types;- i.e. they fill the top bits with 1 if the @x@ is negative- and with 0 otherwise.-- An instance can define either this and 'shiftL' or the unified- 'shift', depending on which is more convenient for the type in- question. -}- shiftR :: a -> Int -> a- {-# INLINE shiftR #-}- x `shiftR` i = x `shift` (-i)-- {-| Shift the first argument right by the specified number of bits, which- must be non-negative an smaller than the number of bits in the type.-- Right shifts perform sign extension on signed number types;- i.e. they fill the top bits with 1 if the @x@ is negative- and with 0 otherwise.-- Defaults to 'shiftR' unless defined explicitly by an instance. -}- unsafeShiftR :: a -> Int -> a- {-# INLINE unsafeShiftR #-}- x `unsafeShiftR` i = x `shiftR` i-- {-| Rotate the argument left by the specified number of bits- (which must be non-negative).-- An instance can define either this and 'rotateR' or the unified- 'rotate', depending on which is more convenient for the type in- question. -}- rotateL :: a -> Int -> a- {-# INLINE rotateL #-}- x `rotateL` i = x `rotate` i-- {-| Rotate the argument right by the specified number of bits- (which must be non-negative).-- An instance can define either this and 'rotateL' or the unified- 'rotate', depending on which is more convenient for the type in- question. -}- rotateR :: a -> Int -> a- {-# INLINE rotateR #-}- x `rotateR` i = x `rotate` (-i)-- {-| Return the number of set bits in the argument. This number is- known as the population count or the Hamming weight. -}- popCount :: a -> Int- popCount = go 0- where- go !c 0 = c- go c w = go (c+1) (w .&. (w - 1)) -- clear the least significant bit set- {-# INLINABLE popCount #-}- {- This implementation is intentionally naive. Instances are- expected to override it with something optimized for their- size. -}--instance Bits Int where- {-# INLINE shift #-}--#ifdef __GLASGOW_HASKELL__- (I# x#) .&. (I# y#) = I# (word2Int# (int2Word# x# `and#` int2Word# y#))-- (I# x#) .|. (I# y#) = I# (word2Int# (int2Word# x# `or#` int2Word# y#))-- (I# x#) `xor` (I# y#) = I# (word2Int# (int2Word# x# `xor#` int2Word# y#))-- complement (I# x#) = I# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))-- (I# x#) `shift` (I# i#)- | i# >=# 0# = I# (x# `iShiftL#` i#)- | otherwise = I# (x# `iShiftRA#` negateInt# i#)- (I# x#) `shiftL` (I# i#) = I# (x# `iShiftL#` i#)- (I# x#) `unsafeShiftL` (I# i#) = I# (x# `uncheckedIShiftL#` i#)- (I# x#) `shiftR` (I# i#) = I# (x# `iShiftRA#` i#)- (I# x#) `unsafeShiftR` (I# i#) = I# (x# `uncheckedIShiftRA#` i#)-- {-# INLINE rotate #-} -- See Note [Constant folding for rotate]- (I# x#) `rotate` (I# i#) =- I# (word2Int# ((x'# `uncheckedShiftL#` i'#) `or#`- (x'# `uncheckedShiftRL#` (wsib -# i'#))))- where- !x'# = int2Word# x#- !i'# = word2Int# (int2Word# i# `and#` int2Word# (wsib -# 1#))- !wsib = WORD_SIZE_IN_BITS# {- work around preprocessor problem (??) -}- bitSize _ = WORD_SIZE_IN_BITS-- popCount (I# x#) = I# (word2Int# (popCnt# (int2Word# x#)))--#else /* !__GLASGOW_HASKELL__ */--#ifdef __HUGS__- (.&.) = primAndInt- (.|.) = primOrInt- xor = primXorInt- complement = primComplementInt- shift = primShiftInt- bit = primBitInt- testBit = primTestInt- bitSize _ = SIZEOF_HSINT*8-#elif defined(__NHC__)- (.&.) = nhc_primIntAnd- (.|.) = nhc_primIntOr- xor = nhc_primIntXor- complement = nhc_primIntCompl- shiftL = nhc_primIntLsh- shiftR = nhc_primIntRsh- bitSize _ = 32-#endif /* __NHC__ */-- x `rotate` i- | i<0 && x<0 = let left = i+bitSize x in- ((x `shift` i) .&. complement ((-1) `shift` left))- .|. (x `shift` left)- | i<0 = (x `shift` i) .|. (x `shift` (i+bitSize x))- | i==0 = x- | i>0 = (x `shift` i) .|. (x `shift` (i-bitSize x))--#endif /* !__GLASGOW_HASKELL__ */-- isSigned _ = True--#ifdef __NHC__-foreign import ccall nhc_primIntAnd :: Int -> Int -> Int-foreign import ccall nhc_primIntOr :: Int -> Int -> Int-foreign import ccall nhc_primIntXor :: Int -> Int -> Int-foreign import ccall nhc_primIntLsh :: Int -> Int -> Int-foreign import ccall nhc_primIntRsh :: Int -> Int -> Int-foreign import ccall nhc_primIntCompl :: Int -> Int-#endif /* __NHC__ */--instance Bits Integer where-#if defined(__GLASGOW_HASKELL__)- (.&.) = andInteger- (.|.) = orInteger- xor = xorInteger- complement = complementInteger- shift x i@(I# i#) | i >= 0 = shiftLInteger x i#- | otherwise = shiftRInteger x (negateInt# i#)-#else- -- reduce bitwise binary operations to special cases we can handle-- x .&. y | x<0 && y<0 = complement (complement x `posOr` complement y)- | otherwise = x `posAnd` y- - x .|. y | x<0 || y<0 = complement (complement x `posAnd` complement y)- | otherwise = x `posOr` y- - x `xor` y | x<0 && y<0 = complement x `posXOr` complement y- | x<0 = complement (complement x `posXOr` y)- | y<0 = complement (x `posXOr` complement y)- | otherwise = x `posXOr` y-- -- assuming infinite 2's-complement arithmetic- complement a = -1 - a- shift x i | i >= 0 = x * 2^i- | otherwise = x `div` 2^(-i)-#endif-- rotate x i = shift x i -- since an Integer never wraps around-- bitSize _ = error "Data.Bits.bitSize(Integer)"- isSigned _ = True--#if !defined(__GLASGOW_HASKELL__)--- Crude implementation of bitwise operations on Integers: convert them--- to finite lists of Ints (least significant first), zip and convert--- back again.---- posAnd requires at least one argument non-negative--- posOr and posXOr require both arguments non-negative--posAnd, posOr, posXOr :: Integer -> Integer -> Integer-posAnd x y = fromInts $ zipWith (.&.) (toInts x) (toInts y)-posOr x y = fromInts $ longZipWith (.|.) (toInts x) (toInts y)-posXOr x y = fromInts $ longZipWith xor (toInts x) (toInts y)--longZipWith :: (a -> a -> a) -> [a] -> [a] -> [a]-longZipWith f xs [] = xs-longZipWith f [] ys = ys-longZipWith f (x:xs) (y:ys) = f x y:longZipWith f xs ys--toInts :: Integer -> [Int]-toInts n- | n == 0 = []- | otherwise = mkInt (n `mod` numInts):toInts (n `div` numInts)- where mkInt n | n > toInteger(maxBound::Int) = fromInteger (n-numInts)- | otherwise = fromInteger n--fromInts :: [Int] -> Integer-fromInts = foldr catInt 0- where catInt d n = (if d<0 then n+1 else n)*numInts + toInteger d--numInts = toInteger (maxBound::Int) - toInteger (minBound::Int) + 1-#endif /* !__GLASGOW_HASKELL__ */--{- Note [Constant folding for rotate]- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The INLINE on the Int instance of rotate enables it to be constant-folded. For example:- sumU . mapU (`rotate` 3) . replicateU 10000000 $ (7 :: Int)-goes to:- Main.$wfold =- \ (ww_sO7 :: Int#) (ww1_sOb :: Int#) ->- case ww1_sOb of wild_XM {- __DEFAULT -> Main.$wfold (+# ww_sO7 56) (+# wild_XM 1);- 10000000 -> ww_sO7-whereas before it was left as a call to $wrotate.--All other Bits instances seem to inline well enough on their-own to enable constant folding; for example 'shift':- sumU . mapU (`shift` 3) . replicateU 10000000 $ (7 :: Int)- goes to:- Main.$wfold =- \ (ww_sOb :: Int#) (ww1_sOf :: Int#) ->- case ww1_sOf of wild_XM {- __DEFAULT -> Main.$wfold (+# ww_sOb 56) (+# wild_XM 1);- 10000000 -> ww_sOb- }--} -
@@ -1,42 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Bool--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The 'Bool' type and related functions.-----------------------------------------------------------------------------------module Data.Bool (- -- * Booleans- Bool(..),- -- ** Operations - (&&), -- :: Bool -> Bool -> Bool- (||), -- :: Bool -> Bool -> Bool- not, -- :: Bool -> Bool- otherwise, -- :: Bool- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-#endif--#ifdef __NHC__-import Prelude-import Prelude- ( Bool(..)- , (&&)- , (||)- , not- , otherwise- )-#endif-
@@ -1,210 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Char--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ The Char type and associated operations.-----------------------------------------------------------------------------------module Data.Char- (- Char-- -- * Character classification- -- | Unicode characters are divided into letters, numbers, marks,- -- punctuation, symbols, separators (including spaces) and others- -- (including control characters).- , isControl, isSpace- , isLower, isUpper, isAlpha, isAlphaNum, isPrint- , isDigit, isOctDigit, isHexDigit- , isLetter, isMark, isNumber, isPunctuation, isSymbol, isSeparator-- -- ** Subranges- , isAscii, isLatin1- , isAsciiUpper, isAsciiLower-- -- ** Unicode general categories- , GeneralCategory(..), generalCategory-- -- * Case conversion- , toUpper, toLower, toTitle -- :: Char -> Char-- -- * Single digit characters- , digitToInt -- :: Char -> Int- , intToDigit -- :: Int -> Char-- -- * Numeric representations- , ord -- :: Char -> Int- , chr -- :: Int -> Char-- -- * String representations- , showLitChar -- :: Char -> ShowS- , lexLitChar -- :: ReadS String- , readLitChar -- :: ReadS Char - ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Arr (Ix)-import GHC.Real (fromIntegral)-import GHC.Show-import GHC.Read (Read, readLitChar, lexLitChar)-import GHC.Unicode-import GHC.Num-import GHC.Enum-#endif--#ifdef __HUGS__-import Hugs.Prelude (Ix)-import Hugs.Char-#endif--#ifdef __NHC__-import Prelude-import Prelude(Char,String)-import Char-import Ix-import NHC.FFI (CInt)-foreign import ccall unsafe "WCsubst.h u_gencat" wgencat :: CInt -> CInt-#endif---- | Convert a single digit 'Char' to the corresponding 'Int'. --- This function fails unless its argument satisfies 'isHexDigit',--- but recognises both upper and lower-case hexadecimal digits--- (i.e. @\'0\'@..@\'9\'@, @\'a\'@..@\'f\'@, @\'A\'@..@\'F\'@).-digitToInt :: Char -> Int-digitToInt c- | isDigit c = ord c - ord '0'- | c >= 'a' && c <= 'f' = ord c - ord 'a' + 10- | c >= 'A' && c <= 'F' = ord c - ord 'A' + 10- | otherwise = error ("Char.digitToInt: not a digit " ++ show c) -- sigh--#ifndef __GLASGOW_HASKELL__-isAsciiUpper, isAsciiLower :: Char -> Bool-isAsciiLower c = c >= 'a' && c <= 'z'-isAsciiUpper c = c >= 'A' && c <= 'Z'-#endif---- | Unicode General Categories (column 2 of the UnicodeData table)--- in the order they are listed in the Unicode standard.--data GeneralCategory- = UppercaseLetter -- ^ Lu: Letter, Uppercase- | LowercaseLetter -- ^ Ll: Letter, Lowercase- | TitlecaseLetter -- ^ Lt: Letter, Titlecase- | ModifierLetter -- ^ Lm: Letter, Modifier- | OtherLetter -- ^ Lo: Letter, Other- | NonSpacingMark -- ^ Mn: Mark, Non-Spacing- | SpacingCombiningMark -- ^ Mc: Mark, Spacing Combining- | EnclosingMark -- ^ Me: Mark, Enclosing- | DecimalNumber -- ^ Nd: Number, Decimal- | LetterNumber -- ^ Nl: Number, Letter- | OtherNumber -- ^ No: Number, Other- | ConnectorPunctuation -- ^ Pc: Punctuation, Connector- | DashPunctuation -- ^ Pd: Punctuation, Dash- | OpenPunctuation -- ^ Ps: Punctuation, Open- | ClosePunctuation -- ^ Pe: Punctuation, Close- | InitialQuote -- ^ Pi: Punctuation, Initial quote- | FinalQuote -- ^ Pf: Punctuation, Final quote- | OtherPunctuation -- ^ Po: Punctuation, Other- | MathSymbol -- ^ Sm: Symbol, Math- | CurrencySymbol -- ^ Sc: Symbol, Currency- | ModifierSymbol -- ^ Sk: Symbol, Modifier- | OtherSymbol -- ^ So: Symbol, Other- | Space -- ^ Zs: Separator, Space- | LineSeparator -- ^ Zl: Separator, Line- | ParagraphSeparator -- ^ Zp: Separator, Paragraph- | Control -- ^ Cc: Other, Control- | Format -- ^ Cf: Other, Format- | Surrogate -- ^ Cs: Other, Surrogate- | PrivateUse -- ^ Co: Other, Private Use- | NotAssigned -- ^ Cn: Other, Not Assigned- deriving (Eq, Ord, Enum, Read, Show, Bounded, Ix)---- | The Unicode general category of the character.-generalCategory :: Char -> GeneralCategory-#if defined(__GLASGOW_HASKELL__) || defined(__NHC__)-generalCategory c = toEnum $ fromIntegral $ wgencat $ fromIntegral $ ord c-#endif-#ifdef __HUGS__-generalCategory c = toEnum (primUniGenCat c)-#endif---- derived character classifiers---- | Selects alphabetic Unicode characters (lower-case, upper-case and--- title-case letters, plus letters of caseless scripts and modifiers letters).--- This function is equivalent to 'Data.Char.isAlpha'.-isLetter :: Char -> Bool-isLetter c = case generalCategory c of- UppercaseLetter -> True- LowercaseLetter -> True- TitlecaseLetter -> True- ModifierLetter -> True- OtherLetter -> True- _ -> False---- | Selects Unicode mark characters, e.g. accents and the like, which--- combine with preceding letters.-isMark :: Char -> Bool-isMark c = case generalCategory c of- NonSpacingMark -> True- SpacingCombiningMark -> True- EnclosingMark -> True- _ -> False---- | Selects Unicode numeric characters, including digits from various--- scripts, Roman numerals, etc.-isNumber :: Char -> Bool-isNumber c = case generalCategory c of- DecimalNumber -> True- LetterNumber -> True- OtherNumber -> True- _ -> False---- | Selects Unicode punctuation characters, including various kinds--- of connectors, brackets and quotes.-isPunctuation :: Char -> Bool-isPunctuation c = case generalCategory c of- ConnectorPunctuation -> True- DashPunctuation -> True- OpenPunctuation -> True- ClosePunctuation -> True- InitialQuote -> True- FinalQuote -> True- OtherPunctuation -> True- _ -> False---- | Selects Unicode symbol characters, including mathematical and--- currency symbols.-isSymbol :: Char -> Bool-isSymbol c = case generalCategory c of- MathSymbol -> True- CurrencySymbol -> True- ModifierSymbol -> True- OtherSymbol -> True- _ -> False---- | Selects Unicode space and separator characters.-isSeparator :: Char -> Bool-isSeparator c = case generalCategory c of- Space -> True- LineSeparator -> True- ParagraphSeparator -> True- _ -> False--#ifdef __NHC__--- dummy implementation-toTitle :: Char -> Char-toTitle = toUpper-#endif-
@@ -1,206 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, DeriveDataTypeable #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Complex--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Complex numbers.-----------------------------------------------------------------------------------module Data.Complex- (- -- * Rectangular form- Complex((:+))-- , realPart -- :: (RealFloat a) => Complex a -> a- , imagPart -- :: (RealFloat a) => Complex a -> a- -- * Polar form- , mkPolar -- :: (RealFloat a) => a -> a -> Complex a- , cis -- :: (RealFloat a) => a -> Complex a- , polar -- :: (RealFloat a) => Complex a -> (a,a)- , magnitude -- :: (RealFloat a) => Complex a -> a- , phase -- :: (RealFloat a) => Complex a -> a- -- * Conjugate- , conjugate -- :: (RealFloat a) => Complex a -> Complex a-- -- Complex instances:- --- -- (RealFloat a) => Eq (Complex a)- -- (RealFloat a) => Read (Complex a)- -- (RealFloat a) => Show (Complex a)- -- (RealFloat a) => Num (Complex a)- -- (RealFloat a) => Fractional (Complex a)- -- (RealFloat a) => Floating (Complex a)-- ) where--import Prelude--import Data.Typeable-#ifdef __GLASGOW_HASKELL__-import Data.Data (Data)-#endif--#ifdef __HUGS__-import Hugs.Prelude(Num(fromInt), Fractional(fromDouble))-#endif--infix 6 :+---- -------------------------------------------------------------------------------- The Complex type---- | Complex numbers are an algebraic type.------ For a complex number @z@, @'abs' z@ is a number with the magnitude of @z@,--- but oriented in the positive real direction, whereas @'signum' z@--- has the phase of @z@, but unit magnitude.-data Complex a- = !a :+ !a -- ^ forms a complex number from its real and imaginary- -- rectangular components.-# if __GLASGOW_HASKELL__- deriving (Eq, Show, Read, Data)-# else- deriving (Eq, Show, Read)-# endif---- -------------------------------------------------------------------------------- Functions over Complex---- | Extracts the real part of a complex number.-realPart :: (RealFloat a) => Complex a -> a-realPart (x :+ _) = x---- | Extracts the imaginary part of a complex number.-imagPart :: (RealFloat a) => Complex a -> a-imagPart (_ :+ y) = y---- | The conjugate of a complex number.-{-# SPECIALISE conjugate :: Complex Double -> Complex Double #-}-conjugate :: (RealFloat a) => Complex a -> Complex a-conjugate (x:+y) = x :+ (-y)---- | Form a complex number from polar components of magnitude and phase.-{-# SPECIALISE mkPolar :: Double -> Double -> Complex Double #-}-mkPolar :: (RealFloat a) => a -> a -> Complex a-mkPolar r theta = r * cos theta :+ r * sin theta---- | @'cis' t@ is a complex value with magnitude @1@--- and phase @t@ (modulo @2*'pi'@).-{-# SPECIALISE cis :: Double -> Complex Double #-}-cis :: (RealFloat a) => a -> Complex a-cis theta = cos theta :+ sin theta---- | The function 'polar' takes a complex number and--- returns a (magnitude, phase) pair in canonical form:--- the magnitude is nonnegative, and the phase in the range @(-'pi', 'pi']@;--- if the magnitude is zero, then so is the phase.-{-# SPECIALISE polar :: Complex Double -> (Double,Double) #-}-polar :: (RealFloat a) => Complex a -> (a,a)-polar z = (magnitude z, phase z)---- | The nonnegative magnitude of a complex number.-{-# SPECIALISE magnitude :: Complex Double -> Double #-}-magnitude :: (RealFloat a) => Complex a -> a-magnitude (x:+y) = scaleFloat k- (sqrt (sqr (scaleFloat mk x) + sqr (scaleFloat mk y)))- where k = max (exponent x) (exponent y)- mk = - k- sqr z = z * z---- | The phase of a complex number, in the range @(-'pi', 'pi']@.--- If the magnitude is zero, then so is the phase.-{-# SPECIALISE phase :: Complex Double -> Double #-}-phase :: (RealFloat a) => Complex a -> a-phase (0 :+ 0) = 0 -- SLPJ July 97 from John Peterson-phase (x:+y) = atan2 y x----- -------------------------------------------------------------------------------- Instances of Complex--#include "Typeable.h"-INSTANCE_TYPEABLE1(Complex,complexTc,"Complex")--instance (RealFloat a) => Num (Complex a) where- {-# SPECIALISE instance Num (Complex Float) #-}- {-# SPECIALISE instance Num (Complex Double) #-}- (x:+y) + (x':+y') = (x+x') :+ (y+y')- (x:+y) - (x':+y') = (x-x') :+ (y-y')- (x:+y) * (x':+y') = (x*x'-y*y') :+ (x*y'+y*x')- negate (x:+y) = negate x :+ negate y- abs z = magnitude z :+ 0- signum (0:+0) = 0- signum z@(x:+y) = x/r :+ y/r where r = magnitude z- fromInteger n = fromInteger n :+ 0-#ifdef __HUGS__- fromInt n = fromInt n :+ 0-#endif--instance (RealFloat a) => Fractional (Complex a) where- {-# SPECIALISE instance Fractional (Complex Float) #-}- {-# SPECIALISE instance Fractional (Complex Double) #-}- (x:+y) / (x':+y') = (x*x''+y*y'') / d :+ (y*x''-x*y'') / d- where x'' = scaleFloat k x'- y'' = scaleFloat k y'- k = - max (exponent x') (exponent y')- d = x'*x'' + y'*y''-- fromRational a = fromRational a :+ 0-#ifdef __HUGS__- fromDouble a = fromDouble a :+ 0-#endif--instance (RealFloat a) => Floating (Complex a) where- {-# SPECIALISE instance Floating (Complex Float) #-}- {-# SPECIALISE instance Floating (Complex Double) #-}- pi = pi :+ 0- exp (x:+y) = expx * cos y :+ expx * sin y- where expx = exp x- log z = log (magnitude z) :+ phase z-- sqrt (0:+0) = 0- sqrt z@(x:+y) = u :+ (if y < 0 then -v else v)- where (u,v) = if x < 0 then (v',u') else (u',v')- v' = abs y / (u'*2)- u' = sqrt ((magnitude z + abs x) / 2)-- sin (x:+y) = sin x * cosh y :+ cos x * sinh y- cos (x:+y) = cos x * cosh y :+ (- sin x * sinh y)- tan (x:+y) = (sinx*coshy:+cosx*sinhy)/(cosx*coshy:+(-sinx*sinhy))- where sinx = sin x- cosx = cos x- sinhy = sinh y- coshy = cosh y-- sinh (x:+y) = cos y * sinh x :+ sin y * cosh x- cosh (x:+y) = cos y * cosh x :+ sin y * sinh x- tanh (x:+y) = (cosy*sinhx:+siny*coshx)/(cosy*coshx:+siny*sinhx)- where siny = sin y- cosy = cos y- sinhx = sinh x- coshx = cosh x-- asin z@(x:+y) = y':+(-x')- where (x':+y') = log (((-y):+x) + sqrt (1 - z*z))- acos z = y'':+(-x'')- where (x'':+y'') = log (z + ((-y'):+x'))- (x':+y') = sqrt (1 - z*z)- atan z@(x:+y) = y':+(-x')- where (x':+y') = log (((1-y):+x) / sqrt (1+z*z))-- asinh z = log (z + sqrt (1+z*z))- acosh z = log (z + (z+1) * sqrt ((z-1)/(z+1)))- atanh z = 0.5 * log ((1.0+z) / (1.0-z))-
@@ -1,1339 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, Rank2Types, ScopedTypeVariables #-}---------------------------------------------------------------------------------- |--- Module : Data.Data--- Copyright : (c) The University of Glasgow, CWI 2001--2004--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (local universal quantification)------ \"Scrap your boilerplate\" --- Generic programming in Haskell.--- See <http://www.cs.vu.nl/boilerplate/>. This module provides--- the 'Data' class with its primitives for generic programming, along--- with instances for many datatypes. It corresponds to a merge between--- the previous "Data.Generics.Basics" and almost all of --- "Data.Generics.Instances". The instances that are not present--- in this module were moved to the @Data.Generics.Instances@ module--- in the @syb@ package.------ For more information, please visit the new--- SYB wiki: <http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB>.-----------------------------------------------------------------------------------module Data.Data (-- -- * Module Data.Typeable re-exported for convenience- module Data.Typeable,-- -- * The Data class for processing constructor applications- Data(- gfoldl, -- :: ... -> a -> c a- gunfold, -- :: ... -> Constr -> c a- toConstr, -- :: a -> Constr- dataTypeOf, -- :: a -> DataType- dataCast1, -- mediate types and unary type constructors- dataCast2, -- mediate types and binary type constructors- -- Generic maps defined in terms of gfoldl - gmapT,- gmapQ,- gmapQl,- gmapQr,- gmapQi,- gmapM,- gmapMp,- gmapMo- ),-- -- * Datatype representations- DataType, -- abstract, instance of: Show- -- ** Constructors- mkDataType, -- :: String -> [Constr] -> DataType- mkIntType, -- :: String -> DataType- mkFloatType, -- :: String -> DataType- mkStringType, -- :: String -> DataType- mkCharType, -- :: String -> DataType- mkNoRepType, -- :: String -> DataType- mkNorepType, -- :: String -> DataType- -- ** Observers- dataTypeName, -- :: DataType -> String- DataRep(..), -- instance of: Eq, Show- dataTypeRep, -- :: DataType -> DataRep- -- ** Convenience functions- repConstr, -- :: DataType -> ConstrRep -> Constr- isAlgType, -- :: DataType -> Bool- dataTypeConstrs,-- :: DataType -> [Constr]- indexConstr, -- :: DataType -> ConIndex -> Constr- maxConstrIndex, -- :: DataType -> ConIndex- isNorepType, -- :: DataType -> Bool-- -- * Data constructor representations- Constr, -- abstract, instance of: Eq, Show- ConIndex, -- alias for Int, start at 1- Fixity(..), -- instance of: Eq, Show- -- ** Constructors- mkConstr, -- :: DataType -> String -> Fixity -> Constr- mkIntConstr, -- :: DataType -> Integer -> Constr- mkFloatConstr, -- :: DataType -> Double -> Constr- mkIntegralConstr,-- :: (Integral a) => DataType -> a -> Constr- mkRealConstr, -- :: (Real a) => DataType -> a -> Constr- mkStringConstr, -- :: DataType -> String -> Constr- mkCharConstr, -- :: DataType -> Char -> Constr- -- ** Observers- constrType, -- :: Constr -> DataType- ConstrRep(..), -- instance of: Eq, Show- constrRep, -- :: Constr -> ConstrRep- constrFields, -- :: Constr -> [String]- constrFixity, -- :: Constr -> Fixity- -- ** Convenience function: algebraic data types- constrIndex, -- :: Constr -> ConIndex- -- ** From strings to constructors and vice versa: all data types- showConstr, -- :: Constr -> String- readConstr, -- :: DataType -> String -> Maybe Constr-- -- * Convenience functions: take type constructors apart- tyconUQname, -- :: String -> String- tyconModule, -- :: String -> String-- -- * Generic operations defined in terms of 'gunfold'- fromConstr, -- :: Constr -> a- fromConstrB, -- :: ... -> Constr -> a- fromConstrM -- :: Monad m => ... -> Constr -> m a-- ) where-----------------------------------------------------------------------------------import Prelude -- necessary to get dependencies right--import Data.Typeable-import Data.Maybe-import Control.Monad---- Imports for the instances-import Data.Int -- So we can give Data instance for Int8, ...-import Data.Word -- So we can give Data instance for Word8, ...-#ifdef __GLASGOW_HASKELL__-import GHC.Real( Ratio(..) ) -- So we can give Data instance for Ratio---import GHC.IOBase -- So we can give Data instance for IO, Handle-import GHC.Ptr -- So we can give Data instance for Ptr-import GHC.ForeignPtr -- So we can give Data instance for ForeignPtr---import GHC.Stable -- So we can give Data instance for StablePtr---import GHC.ST -- So we can give Data instance for ST---import GHC.Conc -- So we can give Data instance for MVar & Co.-import GHC.Arr -- So we can give Data instance for Array-#else-# ifdef __HUGS__-import Hugs.Prelude( Ratio(..) )-# endif-import Foreign.Ptr-import Foreign.ForeignPtr-import Data.Array-#endif--#include "Typeable.h"---------------------------------------------------------------------------------------- The Data class------------------------------------------------------------------------------------{- |-The 'Data' class comprehends a fundamental primitive 'gfoldl' for-folding over constructor applications, say terms. This primitive can-be instantiated in several ways to map over the immediate subterms-of a term; see the @gmap@ combinators later in this class. Indeed, a-generic programmer does not necessarily need to use the ingenious gfoldl-primitive but rather the intuitive @gmap@ combinators. The 'gfoldl'-primitive is completed by means to query top-level constructors, to-turn constructor representations into proper terms, and to list all-possible datatype constructors. This completion allows us to serve-generic programming scenarios like read, show, equality, term generation.--The combinators 'gmapT', 'gmapQ', 'gmapM', etc are all provided with-default definitions in terms of 'gfoldl', leaving open the opportunity-to provide datatype-specific definitions.-(The inclusion of the @gmap@ combinators as members of class 'Data'-allows the programmer or the compiler to derive specialised, and maybe-more efficient code per datatype. /Note/: 'gfoldl' is more higher-order-than the @gmap@ combinators. This is subject to ongoing benchmarking-experiments. It might turn out that the @gmap@ combinators will be-moved out of the class 'Data'.)--Conceptually, the definition of the @gmap@ combinators in terms of the-primitive 'gfoldl' requires the identification of the 'gfoldl' function-arguments. Technically, we also need to identify the type constructor-@c@ for the construction of the result type from the folded term type.--In the definition of @gmapQ@/x/ combinators, we use phantom type-constructors for the @c@ in the type of 'gfoldl' because the result type-of a query does not involve the (polymorphic) type of the term argument.-In the definition of 'gmapQl' we simply use the plain constant type-constructor because 'gfoldl' is left-associative anyway and so it is-readily suited to fold a left-associative binary operation over the-immediate subterms. In the definition of gmapQr, extra effort is-needed. We use a higher-order accumulation trick to mediate between-left-associative constructor application vs. right-associative binary-operation (e.g., @(:)@). When the query is meant to compute a value-of type @r@, then the result type withing generic folding is @r -> r@.-So the result of folding is a function to which we finally pass the-right unit.--With the @-XDeriveDataTypeable@ option, GHC can generate instances of the-'Data' class automatically. For example, given the declaration--> data T a b = C1 a b | C2 deriving (Typeable, Data)--GHC will generate an instance that is equivalent to--> instance (Data a, Data b) => Data (T a b) where-> gfoldl k z (C1 a b) = z C1 `k` a `k` b-> gfoldl k z C2 = z C2->-> gunfold k z c = case constrIndex c of-> 1 -> k (k (z C1))-> 2 -> z C2->-> toConstr (C1 _ _) = con_C1-> toConstr C2 = con_C2->-> dataTypeOf _ = ty_T->-> con_C1 = mkConstr ty_T "C1" [] Prefix-> con_C2 = mkConstr ty_T "C2" [] Prefix-> ty_T = mkDataType "Module.T" [con_C1, con_C2]--This is suitable for datatypes that are exported transparently.---}--class Typeable a => Data a where-- -- | Left-associative fold operation for constructor applications.- --- -- The type of 'gfoldl' is a headache, but operationally it is a simple- -- generalisation of a list fold.- --- -- The default definition for 'gfoldl' is @'const' 'id'@, which is- -- suitable for abstract datatypes with no substructures.- gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)- -- ^ defines how nonempty constructor applications are- -- folded. It takes the folded tail of the constructor- -- application and its head, i.e., an immediate subterm,- -- and combines them in some way.- -> (forall g. g -> c g)- -- ^ defines how the empty constructor application is- -- folded, like the neutral \/ start element for list- -- folding.- -> a- -- ^ structure to be folded.- -> c a- -- ^ result, with a type defined in terms of @a@, but- -- variability is achieved by means of type constructor- -- @c@ for the construction of the actual result type.-- -- See the 'Data' instances in this file for an illustration of 'gfoldl'.-- gfoldl _ z = z-- -- | Unfolding constructor applications- gunfold :: (forall b r. Data b => c (b -> r) -> c r)- -> (forall r. r -> c r)- -> Constr- -> c a-- -- | Obtaining the constructor from a given datum.- -- For proper terms, this is meant to be the top-level constructor.- -- Primitive datatypes are here viewed as potentially infinite sets of- -- values (i.e., constructors).- toConstr :: a -> Constr--- -- | The outer type constructor of the type- dataTypeOf :: a -> DataType---------------------------------------------------------------------------------------- Mediate types and type constructors------------------------------------------------------------------------------------ -- | Mediate types and unary type constructors.- -- In 'Data' instances of the form @T a@, 'dataCast1' should be defined- -- as 'gcast1'.- --- -- The default definition is @'const' 'Nothing'@, which is appropriate- -- for non-unary type constructors.- dataCast1 :: Typeable1 t- => (forall d. Data d => c (t d))- -> Maybe (c a)- dataCast1 _ = Nothing-- -- | Mediate types and binary type constructors.- -- In 'Data' instances of the form @T a b@, 'dataCast2' should be- -- defined as 'gcast2'.- --- -- The default definition is @'const' 'Nothing'@, which is appropriate- -- for non-binary type constructors.- dataCast2 :: Typeable2 t- => (forall d e. (Data d, Data e) => c (t d e))- -> Maybe (c a)- dataCast2 _ = Nothing---------------------------------------------------------------------------------------- Typical generic maps defined in terms of gfoldl------------------------------------------------------------------------------------- -- | A generic transformation that maps over the immediate subterms- --- -- The default definition instantiates the type constructor @c@ in the- -- type of 'gfoldl' to an identity datatype constructor, using the- -- isomorphism pair as injection and projection.- gmapT :: (forall b. Data b => b -> b) -> a -> a-- -- Use an identity datatype constructor ID (see below)- -- to instantiate the type constructor c in the type of gfoldl,- -- and perform injections ID and projections unID accordingly.- --- gmapT f x0 = unID (gfoldl k ID x0)- where- k :: Data d => ID (d->b) -> d -> ID b- k (ID c) x = ID (c (f x))--- -- | A generic query with a left-associative binary operator- gmapQl :: forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r- gmapQl o r f = unCONST . gfoldl k z- where- k :: Data d => CONST r (d->b) -> d -> CONST r b- k c x = CONST $ (unCONST c) `o` f x- z :: g -> CONST r g- z _ = CONST r-- -- | A generic query with a right-associative binary operator- gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r- gmapQr o r0 f x0 = unQr (gfoldl k (const (Qr id)) x0) r0- where- k :: Data d => Qr r (d->b) -> d -> Qr r b- k (Qr c) x = Qr (\r -> c (f x `o` r))--- -- | A generic query that processes the immediate subterms and returns a list- -- of results. The list is given in the same order as originally specified- -- in the declaratoin of the data constructors.- gmapQ :: (forall d. Data d => d -> u) -> a -> [u]- gmapQ f = gmapQr (:) [] f--- -- | A generic query that processes one child by index (zero-based)- gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> a -> u- gmapQi i f x = case gfoldl k z x of { Qi _ q -> fromJust q }- where- k :: Data d => Qi u (d -> b) -> d -> Qi u b- k (Qi i' q) a = Qi (i'+1) (if i==i' then Just (f a) else q)- z :: g -> Qi q g- z _ = Qi 0 Nothing--- -- | A generic monadic transformation that maps over the immediate subterms- --- -- The default definition instantiates the type constructor @c@ in- -- the type of 'gfoldl' to the monad datatype constructor, defining- -- injection and projection using 'return' and '>>='.- gmapM :: forall m. Monad m => (forall d. Data d => d -> m d) -> a -> m a-- -- Use immediately the monad datatype constructor - -- to instantiate the type constructor c in the type of gfoldl,- -- so injection and projection is done by return and >>=.- -- - gmapM f = gfoldl k return- where- k :: Data d => m (d -> b) -> d -> m b- k c x = do c' <- c- x' <- f x- return (c' x')--- -- | Transformation of at least one immediate subterm does not fail- gmapMp :: forall m. MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a--{---The type constructor that we use here simply keeps track of the fact-if we already succeeded for an immediate subterm; see Mp below. To-this end, we couple the monadic computation with a Boolean.---}-- gmapMp f x = unMp (gfoldl k z x) >>= \(x',b) ->- if b then return x' else mzero- where- z :: g -> Mp m g- z g = Mp (return (g,False))- k :: Data d => Mp m (d -> b) -> d -> Mp m b- k (Mp c) y- = Mp ( c >>= \(h, b) ->- (f y >>= \y' -> return (h y', True))- `mplus` return (h y, b)- )-- -- | Transformation of one immediate subterm with success- gmapMo :: forall m. MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a--{---We use the same pairing trick as for gmapMp, -i.e., we use an extra Bool component to keep track of the -fact whether an immediate subterm was processed successfully.-However, we cut of mapping over subterms once a first subterm-was transformed successfully.---}-- gmapMo f x = unMp (gfoldl k z x) >>= \(x',b) ->- if b then return x' else mzero- where- z :: g -> Mp m g- z g = Mp (return (g,False))- k :: Data d => Mp m (d -> b) -> d -> Mp m b- k (Mp c) y- = Mp ( c >>= \(h,b) -> if b- then return (h y, b)- else (f y >>= \y' -> return (h y',True))- `mplus` return (h y, b)- )----- | The identity type constructor needed for the definition of gmapT-newtype ID x = ID { unID :: x }----- | The constant type constructor needed for the definition of gmapQl-newtype CONST c a = CONST { unCONST :: c }----- | Type constructor for adding counters to queries-data Qi q a = Qi Int (Maybe q)----- | The type constructor used in definition of gmapQr-newtype Qr r a = Qr { unQr :: r -> r }----- | The type constructor used in definition of gmapMp-newtype Mp m x = Mp { unMp :: m (x, Bool) }---------------------------------------------------------------------------------------- Generic unfolding--------------------------------------------------------------------------------------- | Build a term skeleton-fromConstr :: Data a => Constr -> a-fromConstr = fromConstrB (error "Data.Data.fromConstr")----- | Build a term and use a generic function for subterms-fromConstrB :: Data a- => (forall d. Data d => d)- -> Constr- -> a-fromConstrB f = unID . gunfold k z- where- k :: forall b r. Data b => ID (b -> r) -> ID r- k c = ID (unID c f)- - z :: forall r. r -> ID r- z = ID----- | Monadic variation on 'fromConstrB'-fromConstrM :: forall m a. (Monad m, Data a)- => (forall d. Data d => m d)- -> Constr- -> m a-fromConstrM f = gunfold k z- where- k :: forall b r. Data b => m (b -> r) -> m r- k c = do { c' <- c; b <- f; return (c' b) }-- z :: forall r. r -> m r- z = return---------------------------------------------------------------------------------------- Datatype and constructor representations------------------------------------------------------------------------------------------ | Representation of datatypes.--- A package of constructor representations with names of type and module.----data DataType = DataType- { tycon :: String- , datarep :: DataRep- }-- deriving Show---- | Representation of constructors. Note that equality on constructors--- with different types may not work -- i.e. the constructors for 'False' and--- 'Nothing' may compare equal.-data Constr = Constr- { conrep :: ConstrRep- , constring :: String- , confields :: [String] -- for AlgRep only- , confixity :: Fixity -- for AlgRep only- , datatype :: DataType- }--instance Show Constr where- show = constring----- | Equality of constructors-instance Eq Constr where- c == c' = constrRep c == constrRep c'----- | Public representation of datatypes-data DataRep = AlgRep [Constr]- | IntRep- | FloatRep- | CharRep- | NoRep-- deriving (Eq,Show)--- The list of constructors could be an array, a balanced tree, or others.----- | Public representation of constructors-data ConstrRep = AlgConstr ConIndex- | IntConstr Integer- | FloatConstr Rational- | CharConstr Char-- deriving (Eq,Show)----- | Unique index for datatype constructors,--- counting from 1 in the order they are given in the program text.-type ConIndex = Int----- | Fixity of constructors-data Fixity = Prefix- | Infix -- Later: add associativity and precedence-- deriving (Eq,Show)--------------------------------------------------------------------------------------- Observers for datatype representations--------------------------------------------------------------------------------------- | Gets the type constructor including the module-dataTypeName :: DataType -> String-dataTypeName = tycon------ | Gets the public presentation of a datatype-dataTypeRep :: DataType -> DataRep-dataTypeRep = datarep----- | Gets the datatype of a constructor-constrType :: Constr -> DataType-constrType = datatype----- | Gets the public presentation of constructors-constrRep :: Constr -> ConstrRep-constrRep = conrep----- | Look up a constructor by its representation-repConstr :: DataType -> ConstrRep -> Constr-repConstr dt cr =- case (dataTypeRep dt, cr) of- (AlgRep cs, AlgConstr i) -> cs !! (i-1)- (IntRep, IntConstr i) -> mkIntConstr dt i- (FloatRep, FloatConstr f) -> mkRealConstr dt f- (CharRep, CharConstr c) -> mkCharConstr dt c- _ -> error "Data.Data.repConstr"---------------------------------------------------------------------------------------- Representations of algebraic data types--------------------------------------------------------------------------------------- | Constructs an algebraic datatype-mkDataType :: String -> [Constr] -> DataType-mkDataType str cs = DataType- { tycon = str- , datarep = AlgRep cs- }----- | Constructs a constructor-mkConstr :: DataType -> String -> [String] -> Fixity -> Constr-mkConstr dt str fields fix =- Constr- { conrep = AlgConstr idx- , constring = str- , confields = fields- , confixity = fix- , datatype = dt- }- where- idx = head [ i | (c,i) <- dataTypeConstrs dt `zip` [1..],- showConstr c == str ]----- | Gets the constructors of an algebraic datatype-dataTypeConstrs :: DataType -> [Constr]-dataTypeConstrs dt = case datarep dt of- (AlgRep cons) -> cons- _ -> error "Data.Data.dataTypeConstrs"----- | Gets the field labels of a constructor. The list of labels--- is returned in the same order as they were given in the original --- constructor declaration.-constrFields :: Constr -> [String]-constrFields = confields----- | Gets the fixity of a constructor-constrFixity :: Constr -> Fixity-constrFixity = confixity---------------------------------------------------------------------------------------- From strings to constr's and vice versa: all data types--- ------------------------------------------------------------------------------------ | Gets the string for a constructor-showConstr :: Constr -> String-showConstr = constring----- | Lookup a constructor via a string-readConstr :: DataType -> String -> Maybe Constr-readConstr dt str =- case dataTypeRep dt of- AlgRep cons -> idx cons- IntRep -> mkReadCon (\i -> (mkPrimCon dt str (IntConstr i)))- FloatRep -> mkReadCon ffloat- CharRep -> mkReadCon (\c -> (mkPrimCon dt str (CharConstr c)))- NoRep -> Nothing- where-- -- Read a value and build a constructor- mkReadCon :: Read t => (t -> Constr) -> Maybe Constr- mkReadCon f = case (reads str) of- [(t,"")] -> Just (f t)- _ -> Nothing-- -- Traverse list of algebraic datatype constructors- idx :: [Constr] -> Maybe Constr- idx cons = let fit = filter ((==) str . showConstr) cons- in if fit == []- then Nothing- else Just (head fit)-- ffloat :: Double -> Constr- ffloat = mkPrimCon dt str . FloatConstr . toRational-------------------------------------------------------------------------------------- Convenience funtions: algebraic data types--------------------------------------------------------------------------------------- | Test for an algebraic type-isAlgType :: DataType -> Bool-isAlgType dt = case datarep dt of- (AlgRep _) -> True- _ -> False----- | Gets the constructor for an index (algebraic datatypes only)-indexConstr :: DataType -> ConIndex -> Constr-indexConstr dt idx = case datarep dt of- (AlgRep cs) -> cs !! (idx-1)- _ -> error "Data.Data.indexConstr"----- | Gets the index of a constructor (algebraic datatypes only)-constrIndex :: Constr -> ConIndex-constrIndex con = case constrRep con of- (AlgConstr idx) -> idx- _ -> error "Data.Data.constrIndex"----- | Gets the maximum constructor index of an algebraic datatype-maxConstrIndex :: DataType -> ConIndex-maxConstrIndex dt = case dataTypeRep dt of- AlgRep cs -> length cs- _ -> error "Data.Data.maxConstrIndex"---------------------------------------------------------------------------------------- Representation of primitive types--------------------------------------------------------------------------------------- | Constructs the 'Int' type-mkIntType :: String -> DataType-mkIntType = mkPrimType IntRep----- | Constructs the 'Float' type-mkFloatType :: String -> DataType-mkFloatType = mkPrimType FloatRep----- | This function is now deprecated. Please use 'mkCharType' instead.-{-# DEPRECATED mkStringType "Use mkCharType instead" #-}-mkStringType :: String -> DataType-mkStringType = mkCharType---- | Constructs the 'Char' type-mkCharType :: String -> DataType-mkCharType = mkPrimType CharRep----- | Helper for 'mkIntType', 'mkFloatType', 'mkStringType'-mkPrimType :: DataRep -> String -> DataType-mkPrimType dr str = DataType- { tycon = str- , datarep = dr- }----- Makes a constructor for primitive types-mkPrimCon :: DataType -> String -> ConstrRep -> Constr-mkPrimCon dt str cr = Constr- { datatype = dt- , conrep = cr- , constring = str- , confields = error "Data.Data.confields"- , confixity = error "Data.Data.confixity"- }---- | This function is now deprecated. Please use 'mkIntegralConstr' instead.-{-# DEPRECATED mkIntConstr "Use mkIntegralConstr instead" #-}-mkIntConstr :: DataType -> Integer -> Constr-mkIntConstr = mkIntegralConstr--mkIntegralConstr :: (Integral a, Show a) => DataType -> a -> Constr-mkIntegralConstr dt i = case datarep dt of- IntRep -> mkPrimCon dt (show i) (IntConstr (toInteger i))- _ -> error "Data.Data.mkIntegralConstr"---- | This function is now deprecated. Please use 'mkRealConstr' instead.-{-# DEPRECATED mkFloatConstr "Use mkRealConstr instead" #-}-mkFloatConstr :: DataType -> Double -> Constr-mkFloatConstr dt = mkRealConstr dt . toRational--mkRealConstr :: (Real a, Show a) => DataType -> a -> Constr-mkRealConstr dt f = case datarep dt of- FloatRep -> mkPrimCon dt (show f) (FloatConstr (toRational f))- _ -> error "Data.Data.mkRealConstr"---- | This function is now deprecated. Please use 'mkCharConstr' instead.-{-# DEPRECATED mkStringConstr "Use mkCharConstr instead" #-}-mkStringConstr :: DataType -> String -> Constr-mkStringConstr dt str =- case datarep dt of- CharRep -> case str of- [c] -> mkPrimCon dt (show c) (CharConstr c)- _ -> error "Data.Data.mkStringConstr: input String must contain a single character"- _ -> error "Data.Data.mkStringConstr"---- | Makes a constructor for 'Char'.-mkCharConstr :: DataType -> Char -> Constr-mkCharConstr dt c = case datarep dt of- CharRep -> mkPrimCon dt (show c) (CharConstr c)- _ -> error "Data.Data.mkCharConstr"--------------------------------------------------------------------------------------- Non-representations for non-presentable types--------------------------------------------------------------------------------------- | Deprecated version (misnamed)-{-# DEPRECATED mkNorepType "Use mkNoRepType instead" #-}-mkNorepType :: String -> DataType-mkNorepType str = DataType- { tycon = str- , datarep = NoRep- }---- | Constructs a non-representation for a non-presentable type-mkNoRepType :: String -> DataType-mkNoRepType str = DataType- { tycon = str- , datarep = NoRep- }---- | Test for a non-representable type-isNorepType :: DataType -> Bool-isNorepType dt = case datarep dt of- NoRep -> True- _ -> False---------------------------------------------------------------------------------------- Convenience for qualified type constructors--------------------------------------------------------------------------------------- | Gets the unqualified type constructor:--- drop *.*.*... before name----tyconUQname :: String -> String-tyconUQname x = let x' = dropWhile (not . (==) '.') x- in if x' == [] then x else tyconUQname (tail x')----- | Gets the module of a type constructor:--- take *.*.*... before name-tyconModule :: String -> String-tyconModule x = let (a,b) = break ((==) '.') x- in if b == ""- then b- else a ++ tyconModule' (tail b)- where- tyconModule' y = let y' = tyconModule y- in if y' == "" then "" else ('.':y')------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Instances of the Data class for Prelude-like types.--- We define top-level definitions for representations.-------------------------------------------------------------------------------------falseConstr :: Constr-falseConstr = mkConstr boolDataType "False" [] Prefix-trueConstr :: Constr-trueConstr = mkConstr boolDataType "True" [] Prefix--boolDataType :: DataType-boolDataType = mkDataType "Prelude.Bool" [falseConstr,trueConstr]--instance Data Bool where- toConstr False = falseConstr- toConstr True = trueConstr- gunfold _ z c = case constrIndex c of- 1 -> z False- 2 -> z True- _ -> error "Data.Data.gunfold(Bool)"- dataTypeOf _ = boolDataType-----------------------------------------------------------------------------------charType :: DataType-charType = mkCharType "Prelude.Char"--instance Data Char where- toConstr x = mkCharConstr charType x- gunfold _ z c = case constrRep c of- (CharConstr x) -> z x- _ -> error "Data.Data.gunfold(Char)"- dataTypeOf _ = charType-----------------------------------------------------------------------------------floatType :: DataType-floatType = mkFloatType "Prelude.Float"--instance Data Float where- toConstr = mkRealConstr floatType- gunfold _ z c = case constrRep c of- (FloatConstr x) -> z (realToFrac x)- _ -> error "Data.Data.gunfold(Float)"- dataTypeOf _ = floatType-----------------------------------------------------------------------------------doubleType :: DataType-doubleType = mkFloatType "Prelude.Double"--instance Data Double where- toConstr = mkRealConstr doubleType- gunfold _ z c = case constrRep c of- (FloatConstr x) -> z (realToFrac x)- _ -> error "Data.Data.gunfold(Double)"- dataTypeOf _ = doubleType-----------------------------------------------------------------------------------intType :: DataType-intType = mkIntType "Prelude.Int"--instance Data Int where- toConstr x = mkIntConstr intType (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Int)"- dataTypeOf _ = intType-----------------------------------------------------------------------------------integerType :: DataType-integerType = mkIntType "Prelude.Integer"--instance Data Integer where- toConstr = mkIntConstr integerType- gunfold _ z c = case constrRep c of- (IntConstr x) -> z x- _ -> error "Data.Data.gunfold(Integer)"- dataTypeOf _ = integerType-----------------------------------------------------------------------------------int8Type :: DataType-int8Type = mkIntType "Data.Int.Int8"--instance Data Int8 where- toConstr x = mkIntConstr int8Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Int8)"- dataTypeOf _ = int8Type-----------------------------------------------------------------------------------int16Type :: DataType-int16Type = mkIntType "Data.Int.Int16"--instance Data Int16 where- toConstr x = mkIntConstr int16Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Int16)"- dataTypeOf _ = int16Type-----------------------------------------------------------------------------------int32Type :: DataType-int32Type = mkIntType "Data.Int.Int32"--instance Data Int32 where- toConstr x = mkIntConstr int32Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Int32)"- dataTypeOf _ = int32Type-----------------------------------------------------------------------------------int64Type :: DataType-int64Type = mkIntType "Data.Int.Int64"--instance Data Int64 where- toConstr x = mkIntConstr int64Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Int64)"- dataTypeOf _ = int64Type-----------------------------------------------------------------------------------wordType :: DataType-wordType = mkIntType "Data.Word.Word"--instance Data Word where- toConstr x = mkIntConstr wordType (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Word)"- dataTypeOf _ = wordType-----------------------------------------------------------------------------------word8Type :: DataType-word8Type = mkIntType "Data.Word.Word8"--instance Data Word8 where- toConstr x = mkIntConstr word8Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Word8)"- dataTypeOf _ = word8Type-----------------------------------------------------------------------------------word16Type :: DataType-word16Type = mkIntType "Data.Word.Word16"--instance Data Word16 where- toConstr x = mkIntConstr word16Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Word16)"- dataTypeOf _ = word16Type-----------------------------------------------------------------------------------word32Type :: DataType-word32Type = mkIntType "Data.Word.Word32"--instance Data Word32 where- toConstr x = mkIntConstr word32Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Word32)"- dataTypeOf _ = word32Type-----------------------------------------------------------------------------------word64Type :: DataType-word64Type = mkIntType "Data.Word.Word64"--instance Data Word64 where- toConstr x = mkIntConstr word64Type (fromIntegral x)- gunfold _ z c = case constrRep c of- (IntConstr x) -> z (fromIntegral x)- _ -> error "Data.Data.gunfold(Word64)"- dataTypeOf _ = word64Type-----------------------------------------------------------------------------------ratioConstr :: Constr-ratioConstr = mkConstr ratioDataType ":%" [] Infix--ratioDataType :: DataType-ratioDataType = mkDataType "GHC.Real.Ratio" [ratioConstr]--instance (Data a, Integral a) => Data (Ratio a) where- gfoldl k z (a :% b) = z (:%) `k` a `k` b- toConstr _ = ratioConstr- gunfold k z c | constrIndex c == 1 = k (k (z (:%)))- gunfold _ _ _ = error "Data.Data.gunfold(Ratio)"- dataTypeOf _ = ratioDataType-----------------------------------------------------------------------------------nilConstr :: Constr-nilConstr = mkConstr listDataType "[]" [] Prefix-consConstr :: Constr-consConstr = mkConstr listDataType "(:)" [] Infix--listDataType :: DataType-listDataType = mkDataType "Prelude.[]" [nilConstr,consConstr]--instance Data a => Data [a] where- gfoldl _ z [] = z []- gfoldl f z (x:xs) = z (:) `f` x `f` xs- toConstr [] = nilConstr- toConstr (_:_) = consConstr- gunfold k z c = case constrIndex c of- 1 -> z []- 2 -> k (k (z (:)))- _ -> error "Data.Data.gunfold(List)"- dataTypeOf _ = listDataType- dataCast1 f = gcast1 f------- The gmaps are given as an illustration.--- This shows that the gmaps for lists are different from list maps.---- gmapT _ [] = []- gmapT f (x:xs) = (f x:f xs)- gmapQ _ [] = []- gmapQ f (x:xs) = [f x,f xs]- gmapM _ [] = return []- gmapM f (x:xs) = f x >>= \x' -> f xs >>= \xs' -> return (x':xs')-----------------------------------------------------------------------------------nothingConstr :: Constr-nothingConstr = mkConstr maybeDataType "Nothing" [] Prefix-justConstr :: Constr-justConstr = mkConstr maybeDataType "Just" [] Prefix--maybeDataType :: DataType-maybeDataType = mkDataType "Prelude.Maybe" [nothingConstr,justConstr]--instance Data a => Data (Maybe a) where- gfoldl _ z Nothing = z Nothing- gfoldl f z (Just x) = z Just `f` x- toConstr Nothing = nothingConstr- toConstr (Just _) = justConstr- gunfold k z c = case constrIndex c of- 1 -> z Nothing- 2 -> k (z Just)- _ -> error "Data.Data.gunfold(Maybe)"- dataTypeOf _ = maybeDataType- dataCast1 f = gcast1 f-----------------------------------------------------------------------------------ltConstr :: Constr-ltConstr = mkConstr orderingDataType "LT" [] Prefix-eqConstr :: Constr-eqConstr = mkConstr orderingDataType "EQ" [] Prefix-gtConstr :: Constr-gtConstr = mkConstr orderingDataType "GT" [] Prefix--orderingDataType :: DataType-orderingDataType = mkDataType "Prelude.Ordering" [ltConstr,eqConstr,gtConstr]--instance Data Ordering where- gfoldl _ z LT = z LT- gfoldl _ z EQ = z EQ- gfoldl _ z GT = z GT- toConstr LT = ltConstr- toConstr EQ = eqConstr- toConstr GT = gtConstr- gunfold _ z c = case constrIndex c of- 1 -> z LT- 2 -> z EQ- 3 -> z GT- _ -> error "Data.Data.gunfold(Ordering)"- dataTypeOf _ = orderingDataType-----------------------------------------------------------------------------------leftConstr :: Constr-leftConstr = mkConstr eitherDataType "Left" [] Prefix--rightConstr :: Constr-rightConstr = mkConstr eitherDataType "Right" [] Prefix--eitherDataType :: DataType-eitherDataType = mkDataType "Prelude.Either" [leftConstr,rightConstr]--instance (Data a, Data b) => Data (Either a b) where- gfoldl f z (Left a) = z Left `f` a- gfoldl f z (Right a) = z Right `f` a- toConstr (Left _) = leftConstr- toConstr (Right _) = rightConstr- gunfold k z c = case constrIndex c of- 1 -> k (z Left)- 2 -> k (z Right)- _ -> error "Data.Data.gunfold(Either)"- dataTypeOf _ = eitherDataType- dataCast2 f = gcast2 f-----------------------------------------------------------------------------------tuple0Constr :: Constr-tuple0Constr = mkConstr tuple0DataType "()" [] Prefix--tuple0DataType :: DataType-tuple0DataType = mkDataType "Prelude.()" [tuple0Constr]--instance Data () where- toConstr () = tuple0Constr- gunfold _ z c | constrIndex c == 1 = z ()- gunfold _ _ _ = error "Data.Data.gunfold(unit)"- dataTypeOf _ = tuple0DataType-----------------------------------------------------------------------------------tuple2Constr :: Constr-tuple2Constr = mkConstr tuple2DataType "(,)" [] Infix--tuple2DataType :: DataType-tuple2DataType = mkDataType "Prelude.(,)" [tuple2Constr]--instance (Data a, Data b) => Data (a,b) where- gfoldl f z (a,b) = z (,) `f` a `f` b- toConstr (_,_) = tuple2Constr- gunfold k z c | constrIndex c == 1 = k (k (z (,)))- gunfold _ _ _ = error "Data.Data.gunfold(tup2)"- dataTypeOf _ = tuple2DataType- dataCast2 f = gcast2 f-----------------------------------------------------------------------------------tuple3Constr :: Constr-tuple3Constr = mkConstr tuple3DataType "(,,)" [] Infix--tuple3DataType :: DataType-tuple3DataType = mkDataType "Prelude.(,,)" [tuple3Constr]--instance (Data a, Data b, Data c) => Data (a,b,c) where- gfoldl f z (a,b,c) = z (,,) `f` a `f` b `f` c- toConstr (_,_,_) = tuple3Constr- gunfold k z c | constrIndex c == 1 = k (k (k (z (,,))))- gunfold _ _ _ = error "Data.Data.gunfold(tup3)"- dataTypeOf _ = tuple3DataType-----------------------------------------------------------------------------------tuple4Constr :: Constr-tuple4Constr = mkConstr tuple4DataType "(,,,)" [] Infix--tuple4DataType :: DataType-tuple4DataType = mkDataType "Prelude.(,,,)" [tuple4Constr]--instance (Data a, Data b, Data c, Data d)- => Data (a,b,c,d) where- gfoldl f z (a,b,c,d) = z (,,,) `f` a `f` b `f` c `f` d- toConstr (_,_,_,_) = tuple4Constr- gunfold k z c = case constrIndex c of- 1 -> k (k (k (k (z (,,,)))))- _ -> error "Data.Data.gunfold(tup4)"- dataTypeOf _ = tuple4DataType-----------------------------------------------------------------------------------tuple5Constr :: Constr-tuple5Constr = mkConstr tuple5DataType "(,,,,)" [] Infix--tuple5DataType :: DataType-tuple5DataType = mkDataType "Prelude.(,,,,)" [tuple5Constr]--instance (Data a, Data b, Data c, Data d, Data e)- => Data (a,b,c,d,e) where- gfoldl f z (a,b,c,d,e) = z (,,,,) `f` a `f` b `f` c `f` d `f` e- toConstr (_,_,_,_,_) = tuple5Constr- gunfold k z c = case constrIndex c of- 1 -> k (k (k (k (k (z (,,,,))))))- _ -> error "Data.Data.gunfold(tup5)"- dataTypeOf _ = tuple5DataType-----------------------------------------------------------------------------------tuple6Constr :: Constr-tuple6Constr = mkConstr tuple6DataType "(,,,,,)" [] Infix--tuple6DataType :: DataType-tuple6DataType = mkDataType "Prelude.(,,,,,)" [tuple6Constr]--instance (Data a, Data b, Data c, Data d, Data e, Data f)- => Data (a,b,c,d,e,f) where- gfoldl f z (a,b,c,d,e,f') = z (,,,,,) `f` a `f` b `f` c `f` d `f` e `f` f'- toConstr (_,_,_,_,_,_) = tuple6Constr- gunfold k z c = case constrIndex c of- 1 -> k (k (k (k (k (k (z (,,,,,)))))))- _ -> error "Data.Data.gunfold(tup6)"- dataTypeOf _ = tuple6DataType-----------------------------------------------------------------------------------tuple7Constr :: Constr-tuple7Constr = mkConstr tuple7DataType "(,,,,,,)" [] Infix--tuple7DataType :: DataType-tuple7DataType = mkDataType "Prelude.(,,,,,,)" [tuple7Constr]--instance (Data a, Data b, Data c, Data d, Data e, Data f, Data g)- => Data (a,b,c,d,e,f,g) where- gfoldl f z (a,b,c,d,e,f',g) =- z (,,,,,,) `f` a `f` b `f` c `f` d `f` e `f` f' `f` g- toConstr (_,_,_,_,_,_,_) = tuple7Constr- gunfold k z c = case constrIndex c of- 1 -> k (k (k (k (k (k (k (z (,,,,,,))))))))- _ -> error "Data.Data.gunfold(tup7)"- dataTypeOf _ = tuple7DataType-----------------------------------------------------------------------------------instance Typeable a => Data (Ptr a) where- toConstr _ = error "Data.Data.toConstr(Ptr)"- gunfold _ _ = error "Data.Data.gunfold(Ptr)"- dataTypeOf _ = mkNoRepType "GHC.Ptr.Ptr"-----------------------------------------------------------------------------------instance Typeable a => Data (ForeignPtr a) where- toConstr _ = error "Data.Data.toConstr(ForeignPtr)"- gunfold _ _ = error "Data.Data.gunfold(ForeignPtr)"- dataTypeOf _ = mkNoRepType "GHC.ForeignPtr.ForeignPtr"------------------------------------------------------------------------------------ The Data instance for Array preserves data abstraction at the cost of --- inefficiency. We omit reflection services for the sake of data abstraction.-instance (Typeable a, Data b, Ix a) => Data (Array a b)- where- gfoldl f z a = z (listArray (bounds a)) `f` (elems a)- toConstr _ = error "Data.Data.toConstr(Array)"- gunfold _ _ = error "Data.Data.gunfold(Array)"- dataTypeOf _ = mkNoRepType "Data.Array.Array"-
@@ -1,171 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Dynamic--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The Dynamic interface provides basic support for dynamic types.--- --- Operations for injecting values of arbitrary type into--- a dynamically typed value, Dynamic, are provided, together--- with operations for converting dynamic values into a concrete--- (monomorphic) type.--- --------------------------------------------------------------------------------module Data.Dynamic- (-- -- Module Data.Typeable re-exported for convenience- module Data.Typeable,-- -- * The @Dynamic@ type- Dynamic, -- abstract, instance of: Show, Typeable-- -- * Converting to and from @Dynamic@- toDyn, -- :: Typeable a => a -> Dynamic- fromDyn, -- :: Typeable a => Dynamic -> a -> a- fromDynamic, -- :: Typeable a => Dynamic -> Maybe a- - -- * Applying functions of dynamic type- dynApply,- dynApp,- dynTypeRep-- ) where---import Data.Typeable-import Data.Maybe-import Unsafe.Coerce--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Show-import GHC.Exception-#endif--#ifdef __HUGS__-import Hugs.Prelude-import Hugs.IO-import Hugs.IORef-import Hugs.IOExts-#endif--#ifdef __NHC__-import NHC.IOExtras (IORef,newIORef,readIORef,writeIORef,unsafePerformIO)-#endif--#include "Typeable.h"--------------------------------------------------------------------- The type Dynamic-------------------------------------------------------------------{-|- A value of type 'Dynamic' is an object encapsulated together with its type.-- A 'Dynamic' may only represent a monomorphic value; an attempt to- create a value of type 'Dynamic' from a polymorphically-typed- expression will result in an ambiguity error (see 'toDyn').-- 'Show'ing a value of type 'Dynamic' returns a pretty-printed representation- of the object\'s type; useful for debugging.--}-#ifndef __HUGS__-data Dynamic = Dynamic TypeRep Obj-#endif--INSTANCE_TYPEABLE0(Dynamic,dynamicTc,"Dynamic")--instance Show Dynamic where- -- the instance just prints the type representation.- showsPrec _ (Dynamic t _) = - showString "<<" . - showsPrec 0 t . - showString ">>"--#ifdef __GLASGOW_HASKELL__--- here so that it isn't an orphan:-instance Exception Dynamic-#endif--#ifdef __GLASGOW_HASKELL__-type Obj = Any- -- Use GHC's primitive 'Any' type to hold the dynamically typed value.- --- -- In GHC's new eval/apply execution model this type must not look- -- like a data type. If it did, GHC would use the constructor convention - -- when evaluating it, and this will go wrong if the object is really a - -- function. Using Any forces GHC to use- -- a fallback convention for evaluating it that works for all types.-#elif !defined(__HUGS__)-data Obj = Obj-#endif---- | Converts an arbitrary value into an object of type 'Dynamic'. ------ The type of the object must be an instance of 'Typeable', which--- ensures that only monomorphically-typed objects may be converted to--- 'Dynamic'. To convert a polymorphic object into 'Dynamic', give it--- a monomorphic type signature. For example:------ > toDyn (id :: Int -> Int)----toDyn :: Typeable a => a -> Dynamic-toDyn v = Dynamic (typeOf v) (unsafeCoerce v)---- | Converts a 'Dynamic' object back into an ordinary Haskell value of--- the correct type. See also 'fromDynamic'.-fromDyn :: Typeable a- => Dynamic -- ^ the dynamically-typed object- -> a -- ^ a default value - -> a -- ^ returns: the value of the first argument, if- -- it has the correct type, otherwise the value of- -- the second argument.-fromDyn (Dynamic t v) def- | typeOf def == t = unsafeCoerce v- | otherwise = def---- | Converts a 'Dynamic' object back into an ordinary Haskell value of--- the correct type. See also 'fromDyn'.-fromDynamic- :: Typeable a- => Dynamic -- ^ the dynamically-typed object- -> Maybe a -- ^ returns: @'Just' a@, if the dynamically-typed- -- object has the correct type (and @a@ is its value), - -- or 'Nothing' otherwise.-fromDynamic (Dynamic t v) =- case unsafeCoerce v of - r | t == typeOf r -> Just r- | otherwise -> Nothing---- (f::(a->b)) `dynApply` (x::a) = (f a)::b-dynApply :: Dynamic -> Dynamic -> Maybe Dynamic-dynApply (Dynamic t1 f) (Dynamic t2 x) =- case funResultTy t1 t2 of- Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x))- Nothing -> Nothing--dynApp :: Dynamic -> Dynamic -> Dynamic-dynApp f x = case dynApply f x of - Just r -> r- Nothing -> error ("Type error in dynamic application.\n" ++- "Can't apply function " ++ show f ++- " to argument " ++ show x)--dynTypeRep :: Dynamic -> TypeRep-dynTypeRep (Dynamic tr _) = tr -
@@ -1,100 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Either--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The Either type, and associated operations.-----------------------------------------------------------------------------------module Data.Either (- Either(..),- either, -- :: (a -> c) -> (b -> c) -> Either a b -> c- lefts, -- :: [Either a b] -> [a]- rights, -- :: [Either a b] -> [b]- partitionEithers, -- :: [Either a b] -> ([a],[b])- ) where--#include "Typeable.h"--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Show-import GHC.Read-#endif--import Data.Typeable-import GHC.Generics (Generic)--#ifdef __GLASGOW_HASKELL__-{---- just for testing-import Test.QuickCheck--}--{-|--The 'Either' type represents values with two possibilities: a value of-type @'Either' a b@ is either @'Left' a@ or @'Right' b@.--The 'Either' type is sometimes used to represent a value which is-either correct or an error; by convention, the 'Left' constructor is-used to hold an error value and the 'Right' constructor is used to-hold a correct value (mnemonic: \"right\" also means \"correct\").--}-data Either a b = Left a | Right b- deriving (Eq, Ord, Read, Show, Generic)---- | Case analysis for the 'Either' type.--- If the value is @'Left' a@, apply the first function to @a@;--- if it is @'Right' b@, apply the second function to @b@.-either :: (a -> c) -> (b -> c) -> Either a b -> c-either f _ (Left x) = f x-either _ g (Right y) = g y-#endif /* __GLASGOW_HASKELL__ */--INSTANCE_TYPEABLE2(Either,eitherTc,"Either")---- | Extracts from a list of 'Either' all the 'Left' elements--- All the 'Left' elements are extracted in order.--lefts :: [Either a b] -> [a]-lefts x = [a | Left a <- x]---- | Extracts from a list of 'Either' all the 'Right' elements--- All the 'Right' elements are extracted in order.--rights :: [Either a b] -> [b]-rights x = [a | Right a <- x]---- | Partitions a list of 'Either' into two lists--- All the 'Left' elements are extracted, in order, to the first--- component of the output. Similarly the 'Right' elements are extracted--- to the second component of the output.--partitionEithers :: [Either a b] -> ([a],[b])-partitionEithers = foldr (either left right) ([],[])- where- left a ~(l, r) = (a:l, r)- right a ~(l, r) = (l, a:r)--{--{--------------------------------------------------------------------- Testing---------------------------------------------------------------------}-prop_partitionEithers :: [Either Int Int] -> Bool-prop_partitionEithers x =- partitionEithers x == (lefts x, rights x)--}-
@@ -1,25 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Eq--- Copyright : (c) The University of Glasgow 2005--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ Equality-----------------------------------------------------------------------------------module Data.Eq (- Eq(..),- ) where--#if __GLASGOW_HASKELL__-import GHC.Base-#endif-
@@ -1,249 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-{-# OPTIONS -Wall -fno-warn-unused-binds #-}-#ifndef __NHC__-{-# LANGUAGE DeriveDataTypeable #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Fixed--- Copyright : (c) Ashley Yakeley 2005, 2006, 2009--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : Ashley Yakeley <ashley@semantic.org>--- Stability : experimental--- Portability : portable------ This module defines a \"Fixed\" type for fixed-precision arithmetic.--- The parameter to Fixed is any type that's an instance of HasResolution.--- HasResolution has a single method that gives the resolution of the Fixed type.------ This module also contains generalisations of div, mod, and divmod to work--- with any Real instance.-----------------------------------------------------------------------------------module Data.Fixed-(- div',mod',divMod',-- Fixed,HasResolution(..),- showFixed,- E0,Uni,- E1,Deci,- E2,Centi,- E3,Milli,- E6,Micro,- E9,Nano,- E12,Pico-) where--import Prelude -- necessary to get dependencies right-import Data.Char-import Data.List-#ifndef __NHC__-import Data.Typeable-import Data.Data-#endif--#ifndef __NHC__-default () -- avoid any defaulting shenanigans-#endif---- | generalisation of 'div' to any instance of Real-div' :: (Real a,Integral b) => a -> a -> b-div' n d = floor ((toRational n) / (toRational d))---- | generalisation of 'divMod' to any instance of Real-divMod' :: (Real a,Integral b) => a -> a -> (b,a)-divMod' n d = (f,n - (fromIntegral f) * d) where- f = div' n d---- | generalisation of 'mod' to any instance of Real-mod' :: (Real a) => a -> a -> a-mod' n d = n - (fromInteger f) * d where- f = div' n d---- | The type parameter should be an instance of 'HasResolution'.-newtype Fixed a = MkFixed Integer-#ifndef __NHC__- deriving (Eq,Ord,Typeable)-#else- deriving (Eq,Ord)-#endif--#ifndef __NHC__--- We do this because the automatically derived Data instance requires (Data a) context.--- Our manual instance has the more general (Typeable a) context.-tyFixed :: DataType-tyFixed = mkDataType "Data.Fixed.Fixed" [conMkFixed]-conMkFixed :: Constr-conMkFixed = mkConstr tyFixed "MkFixed" [] Prefix-instance (Typeable a) => Data (Fixed a) where- gfoldl k z (MkFixed a) = k (z MkFixed) a- gunfold k z _ = k (z MkFixed)- dataTypeOf _ = tyFixed- toConstr _ = conMkFixed-#endif--class HasResolution a where- resolution :: p a -> Integer--withType :: (p a -> f a) -> f a-withType foo = foo undefined--withResolution :: (HasResolution a) => (Integer -> f a) -> f a-withResolution foo = withType (foo . resolution)--instance Enum (Fixed a) where- succ (MkFixed a) = MkFixed (succ a)- pred (MkFixed a) = MkFixed (pred a)- toEnum = MkFixed . toEnum- fromEnum (MkFixed a) = fromEnum a- enumFrom (MkFixed a) = fmap MkFixed (enumFrom a)- enumFromThen (MkFixed a) (MkFixed b) = fmap MkFixed (enumFromThen a b)- enumFromTo (MkFixed a) (MkFixed b) = fmap MkFixed (enumFromTo a b)- enumFromThenTo (MkFixed a) (MkFixed b) (MkFixed c) = fmap MkFixed (enumFromThenTo a b c)--instance (HasResolution a) => Num (Fixed a) where- (MkFixed a) + (MkFixed b) = MkFixed (a + b)- (MkFixed a) - (MkFixed b) = MkFixed (a - b)- fa@(MkFixed a) * (MkFixed b) = MkFixed (div (a * b) (resolution fa))- negate (MkFixed a) = MkFixed (negate a)- abs (MkFixed a) = MkFixed (abs a)- signum (MkFixed a) = fromInteger (signum a)- fromInteger i = withResolution (\res -> MkFixed (i * res))--instance (HasResolution a) => Real (Fixed a) where- toRational fa@(MkFixed a) = (toRational a) / (toRational (resolution fa))--instance (HasResolution a) => Fractional (Fixed a) where- fa@(MkFixed a) / (MkFixed b) = MkFixed (div (a * (resolution fa)) b)- recip fa@(MkFixed a) = MkFixed (div (res * res) a) where- res = resolution fa- fromRational r = withResolution (\res -> MkFixed (floor (r * (toRational res))))--instance (HasResolution a) => RealFrac (Fixed a) where- properFraction a = (i,a - (fromIntegral i)) where- i = truncate a- truncate f = truncate (toRational f)- round f = round (toRational f)- ceiling f = ceiling (toRational f)- floor f = floor (toRational f)--chopZeros :: Integer -> String-chopZeros 0 = ""-chopZeros a | mod a 10 == 0 = chopZeros (div a 10)-chopZeros a = show a---- only works for positive a-showIntegerZeros :: Bool -> Int -> Integer -> String-showIntegerZeros True _ 0 = ""-showIntegerZeros chopTrailingZeros digits a = replicate (digits - length s) '0' ++ s' where- s = show a- s' = if chopTrailingZeros then chopZeros a else s--withDot :: String -> String-withDot "" = ""-withDot s = '.':s---- | First arg is whether to chop off trailing zeros-showFixed :: (HasResolution a) => Bool -> Fixed a -> String-showFixed chopTrailingZeros fa@(MkFixed a) | a < 0 = "-" ++ (showFixed chopTrailingZeros (asTypeOf (MkFixed (negate a)) fa))-showFixed chopTrailingZeros fa@(MkFixed a) = (show i) ++ (withDot (showIntegerZeros chopTrailingZeros digits fracNum)) where- res = resolution fa- (i,d) = divMod a res- -- enough digits to be unambiguous- digits = ceiling (logBase 10 (fromInteger res) :: Double)- maxnum = 10 ^ digits- fracNum = div (d * maxnum) res--readsFixed :: (HasResolution a) => ReadS (Fixed a)-readsFixed = readsSigned- where readsSigned ('-' : xs) = [ (negate x, rest)- | (x, rest) <- readsUnsigned xs ]- readsSigned xs = readsUnsigned xs- readsUnsigned xs = case span isDigit xs of- ([], _) -> []- (is, xs') ->- let i = fromInteger (read is)- in case xs' of- '.' : xs'' ->- case span isDigit xs'' of- ([], _) -> []- (js, xs''') ->- let j = fromInteger (read js)- l = genericLength js :: Integer- in [(i + (j / (10 ^ l)), xs''')]- _ -> [(i, xs')]--instance (HasResolution a) => Show (Fixed a) where- show = showFixed False--instance (HasResolution a) => Read (Fixed a) where- readsPrec _ = readsFixed--data E0 = E0-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E0 where- resolution _ = 1--- | resolution of 1, this works the same as Integer-type Uni = Fixed E0--data E1 = E1-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E1 where- resolution _ = 10--- | resolution of 10^-1 = .1-type Deci = Fixed E1--data E2 = E2-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E2 where- resolution _ = 100--- | resolution of 10^-2 = .01, useful for many monetary currencies-type Centi = Fixed E2--data E3 = E3-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E3 where- resolution _ = 1000--- | resolution of 10^-3 = .001-type Milli = Fixed E3--data E6 = E6-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E6 where- resolution _ = 1000000--- | resolution of 10^-6 = .000001-type Micro = Fixed E6--data E9 = E9-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E9 where- resolution _ = 1000000000--- | resolution of 10^-9 = .000000001-type Nano = Fixed E9--data E12 = E12-#ifndef __NHC__- deriving (Typeable)-#endif-instance HasResolution E12 where- resolution _ = 1000000000000--- | resolution of 10^-12 = .000000000001-type Pico = Fixed E12-
@@ -1,325 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Foldable--- Copyright : Ross Paterson 2005--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Class of data structures that can be folded to a summary value.------ Many of these functions generalize "Prelude", "Control.Monad" and--- "Data.List" functions of the same names from lists to any 'Foldable'--- functor. To avoid ambiguity, either import those modules hiding--- these names or qualify uses of these function names with an alias--- for this module.-----------------------------------------------------------------------------------module Data.Foldable (- -- * Folds- Foldable(..),- -- ** Special biased folds- foldr',- foldl',- foldrM,- foldlM,- -- ** Folding actions- -- *** Applicative actions- traverse_,- for_,- sequenceA_,- asum,- -- *** Monadic actions- mapM_,- forM_,- sequence_,- msum,- -- ** Specialized folds- toList,- concat,- concatMap,- and,- or,- any,- all,- sum,- product,- maximum,- maximumBy,- minimum,- minimumBy,- -- ** Searches- elem,- notElem,- find- ) where--import Prelude hiding (foldl, foldr, foldl1, foldr1, mapM_, sequence_,- elem, notElem, concat, concatMap, and, or, any, all,- sum, product, maximum, minimum)-import qualified Prelude (foldl, foldr, foldl1, foldr1)-import Control.Applicative-import Control.Monad (MonadPlus(..))-import Data.Maybe (fromMaybe, listToMaybe)-import Data.Monoid--#ifdef __NHC__-import Control.Arrow (ArrowZero(..)) -- work around nhc98 typechecker problem-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Exts (build)-#endif--#if defined(__GLASGOW_HASKELL__)-import GHC.Arr-#elif defined(__HUGS__)-import Hugs.Array-#elif defined(__NHC__)-import Array-#endif---- | Data structures that can be folded.------ Minimal complete definition: 'foldMap' or 'foldr'.------ For example, given a data type------ > data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)------ a suitable instance would be------ > instance Foldable Tree where--- > foldMap f Empty = mempty--- > foldMap f (Leaf x) = f x--- > foldMap f (Node l k r) = foldMap f l `mappend` f k `mappend` foldMap f r------ This is suitable even for abstract types, as the monoid is assumed--- to satisfy the monoid laws. Alternatively, one could define @foldr@:------ > instance Foldable Tree where--- > foldr f z Empty = z--- > foldr f z (Leaf x) = f x z--- > foldr f z (Node l k r) = foldr f (f k (foldr f z r)) l----class Foldable t where- -- | Combine the elements of a structure using a monoid.- fold :: Monoid m => t m -> m- fold = foldMap id-- -- | Map each element of the structure to a monoid,- -- and combine the results.- foldMap :: Monoid m => (a -> m) -> t a -> m- foldMap f = foldr (mappend . f) mempty-- -- | Right-associative fold of a structure.- --- -- @'foldr' f z = 'Prelude.foldr' f z . 'toList'@- foldr :: (a -> b -> b) -> b -> t a -> b- foldr f z t = appEndo (foldMap (Endo . f) t) z-- -- | Left-associative fold of a structure.- --- -- @'foldl' f z = 'Prelude.foldl' f z . 'toList'@- foldl :: (a -> b -> a) -> a -> t b -> a- foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z-- -- | A variant of 'foldr' that has no base case,- -- and thus may only be applied to non-empty structures.- --- -- @'foldr1' f = 'Prelude.foldr1' f . 'toList'@- foldr1 :: (a -> a -> a) -> t a -> a- foldr1 f xs = fromMaybe (error "foldr1: empty structure")- (foldr mf Nothing xs)- where- mf x Nothing = Just x- mf x (Just y) = Just (f x y)-- -- | A variant of 'foldl' that has no base case,- -- and thus may only be applied to non-empty structures.- --- -- @'foldl1' f = 'Prelude.foldl1' f . 'toList'@- foldl1 :: (a -> a -> a) -> t a -> a- foldl1 f xs = fromMaybe (error "foldl1: empty structure")- (foldl mf Nothing xs)- where- mf Nothing y = Just y- mf (Just x) y = Just (f x y)---- instances for Prelude types--instance Foldable Maybe where- foldr _ z Nothing = z- foldr f z (Just x) = f x z-- foldl _ z Nothing = z- foldl f z (Just x) = f z x--instance Foldable [] where- foldr = Prelude.foldr- foldl = Prelude.foldl- foldr1 = Prelude.foldr1- foldl1 = Prelude.foldl1--instance Ix i => Foldable (Array i) where- foldr f z = Prelude.foldr f z . elems- foldl f z = Prelude.foldl f z . elems- foldr1 f = Prelude.foldr1 f . elems- foldl1 f = Prelude.foldl1 f . elems---- | Fold over the elements of a structure,--- associating to the right, but strictly.-foldr' :: Foldable t => (a -> b -> b) -> b -> t a -> b-foldr' f z0 xs = foldl f' id xs z0- where f' k x z = k $! f x z---- | Monadic fold over the elements of a structure,--- associating to the right, i.e. from right to left.-foldrM :: (Foldable t, Monad m) => (a -> b -> m b) -> b -> t a -> m b-foldrM f z0 xs = foldl f' return xs z0- where f' k x z = f x z >>= k---- | Fold over the elements of a structure,--- associating to the left, but strictly.-foldl' :: Foldable t => (a -> b -> a) -> a -> t b -> a-foldl' f z0 xs = foldr f' id xs z0- where f' x k z = k $! f z x---- | Monadic fold over the elements of a structure,--- associating to the left, i.e. from left to right.-foldlM :: (Foldable t, Monad m) => (a -> b -> m a) -> a -> t b -> m a-foldlM f z0 xs = foldr f' return xs z0- where f' x k z = f z x >>= k---- | Map each element of a structure to an action, evaluate--- these actions from left to right, and ignore the results.-traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()-traverse_ f = foldr ((*>) . f) (pure ())---- | 'for_' is 'traverse_' with its arguments flipped.-for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()-{-# INLINE for_ #-}-for_ = flip traverse_---- | Map each element of a structure to a monadic action, evaluate--- these actions from left to right, and ignore the results.-mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()-mapM_ f = foldr ((>>) . f) (return ())---- | 'forM_' is 'mapM_' with its arguments flipped.-forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()-{-# INLINE forM_ #-}-forM_ = flip mapM_---- | Evaluate each action in the structure from left to right,--- and ignore the results.-sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f ()-sequenceA_ = foldr (*>) (pure ())---- | Evaluate each monadic action in the structure from left to right,--- and ignore the results.-sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()-sequence_ = foldr (>>) (return ())---- | The sum of a collection of actions, generalizing 'concat'.-asum :: (Foldable t, Alternative f) => t (f a) -> f a-{-# INLINE asum #-}-asum = foldr (<|>) empty---- | The sum of a collection of actions, generalizing 'concat'.-msum :: (Foldable t, MonadPlus m) => t (m a) -> m a-{-# INLINE msum #-}-msum = foldr mplus mzero---- These use foldr rather than foldMap to avoid repeated concatenation.---- | List of elements of a structure.-toList :: Foldable t => t a -> [a]-{-# INLINE toList #-}-#ifdef __GLASGOW_HASKELL__-toList t = build (\ c n -> foldr c n t)-#else-toList = foldr (:) []-#endif---- | The concatenation of all the elements of a container of lists.-concat :: Foldable t => t [a] -> [a]-concat = fold---- | Map a function over all the elements of a container and concatenate--- the resulting lists.-concatMap :: Foldable t => (a -> [b]) -> t a -> [b]-concatMap = foldMap---- | 'and' returns the conjunction of a container of Bools. For the--- result to be 'True', the container must be finite; 'False', however,--- results from a 'False' value finitely far from the left end.-and :: Foldable t => t Bool -> Bool-and = getAll . foldMap All---- | 'or' returns the disjunction of a container of Bools. For the--- result to be 'False', the container must be finite; 'True', however,--- results from a 'True' value finitely far from the left end.-or :: Foldable t => t Bool -> Bool-or = getAny . foldMap Any---- | Determines whether any element of the structure satisfies the predicate.-any :: Foldable t => (a -> Bool) -> t a -> Bool-any p = getAny . foldMap (Any . p)---- | Determines whether all elements of the structure satisfy the predicate.-all :: Foldable t => (a -> Bool) -> t a -> Bool-all p = getAll . foldMap (All . p)---- | The 'sum' function computes the sum of the numbers of a structure.-sum :: (Foldable t, Num a) => t a -> a-sum = getSum . foldMap Sum---- | The 'product' function computes the product of the numbers of a structure.-product :: (Foldable t, Num a) => t a -> a-product = getProduct . foldMap Product---- | The largest element of a non-empty structure.-maximum :: (Foldable t, Ord a) => t a -> a-maximum = foldr1 max---- | The largest element of a non-empty structure with respect to the--- given comparison function.-maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a-maximumBy cmp = foldr1 max'- where max' x y = case cmp x y of- GT -> x- _ -> y---- | The least element of a non-empty structure.-minimum :: (Foldable t, Ord a) => t a -> a-minimum = foldr1 min---- | The least element of a non-empty structure with respect to the--- given comparison function.-minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a-minimumBy cmp = foldr1 min'- where min' x y = case cmp x y of- GT -> y- _ -> x---- | Does the element occur in the structure?-elem :: (Foldable t, Eq a) => a -> t a -> Bool-elem = any . (==)---- | 'notElem' is the negation of 'elem'.-notElem :: (Foldable t, Eq a) => a -> t a -> Bool-notElem x = not . elem x---- | The 'find' function takes a predicate and a structure and returns--- the leftmost element of the structure matching the predicate, or--- 'Nothing' if there is no such element.-find :: Foldable t => (a -> Bool) -> t a -> Maybe a-find p = listToMaybe . concatMap (\ x -> if p x then [x] else [])-
@@ -1,88 +0,0 @@-{-# LANGUAGE Safe #-}---------------------------------------------------------------------------------- |--- Module : Data.Function--- Copyright : Nils Anders Danielsson 2006--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Simple combinators working solely on and with functions.-----------------------------------------------------------------------------------module Data.Function- ( -- * "Prelude" re-exports- id, const, (.), flip, ($)- -- * Other combinators- , fix- , on- ) where--import Prelude--infixl 0 `on`---- | @'fix' f@ is the least fixed point of the function @f@,--- i.e. the least defined @x@ such that @f x = x@.-fix :: (a -> a) -> a-fix f = let x = f x in x---- | @(*) \`on\` f = \\x y -> f x * f y@.------ Typical usage: @'Data.List.sortBy' ('compare' \`on\` 'fst')@.------ Algebraic properties:------ * @(*) \`on\` 'id' = (*)@ (if @(*) ∉ {⊥, 'const' ⊥}@)------ * @((*) \`on\` f) \`on\` g = (*) \`on\` (f . g)@------ * @'flip' on f . 'flip' on g = 'flip' on (g . f)@---- Proofs (so that I don't have to edit the test-suite):---- (*) `on` id--- =--- \x y -> id x * id y--- =--- \x y -> x * y--- = { If (*) /= _|_ or const _|_. }--- (*)---- (*) `on` f `on` g--- =--- ((*) `on` f) `on` g--- =--- \x y -> ((*) `on` f) (g x) (g y)--- =--- \x y -> (\x y -> f x * f y) (g x) (g y)--- =--- \x y -> f (g x) * f (g y)--- =--- \x y -> (f . g) x * (f . g) y--- =--- (*) `on` (f . g)--- =--- (*) `on` f . g---- flip on f . flip on g--- =--- (\h (*) -> (*) `on` h) f . (\h (*) -> (*) `on` h) g--- =--- (\(*) -> (*) `on` f) . (\(*) -> (*) `on` g)--- =--- \(*) -> (*) `on` g `on` f--- = { See above. }--- \(*) -> (*) `on` g . f--- =--- (\h (*) -> (*) `on` h) (g . f)--- =--- flip on (g . f)--on :: (b -> b -> c) -> (a -> b) -> a -> a -> c-(.*.) `on` f = \x y -> f x .*. f y-
@@ -1,36 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Functor--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Functors: uniform action over a parameterized type, generalizing the--- 'map' function on lists.--module Data.Functor- (- Functor(fmap),- (<$),- (<$>),- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base (Functor(..))-#else-(<$) :: Functor f => a -> f b -> f a-(<$) = fmap . const-#endif--infixl 4 <$>---- | An infix synonym for 'fmap'.-(<$>) :: Functor f => (a -> b) -> f a -> f b-(<$>) = fmap-
@@ -1,534 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# OPTIONS_GHC -funbox-strict-fields -fno-warn-name-shadowing #-}---------------------------------------------------------------------------------- |--- Module : Data.HashTable--- Copyright : (c) The University of Glasgow 2003--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An implementation of extensible hash tables, as described in--- Per-Ake Larson, /Dynamic Hash Tables/, CACM 31(4), April 1988,--- pp. 446--457. The implementation is also derived from the one--- in GHC's runtime system (@ghc\/rts\/Hash.{c,h}@).-----------------------------------------------------------------------------------module Data.HashTable (- -- * Basic hash table operations- HashTable, new, newHint, insert, delete, lookup, update,- -- * Converting to and from lists- fromList, toList,- -- * Hash functions- -- $hash_functions- hashInt, hashString,- prime,- -- * Diagnostics- longestChain- ) where---- This module is imported by Data.Dynamic, which is pretty low down in the--- module hierarchy, so don't import "high-level" modules--#ifdef __GLASGOW_HASKELL__-import GHC.Base-#else-import Prelude hiding ( lookup )-#endif-import Data.Tuple ( fst )-import Data.Bits-import Data.Maybe-import Data.List ( maximumBy, length, concat, foldl', partition )-import Data.Int ( Int32 )--#if defined(__GLASGOW_HASKELL__)-import GHC.Num-import GHC.Real ( fromIntegral )-import GHC.Show ( Show(..) )-import GHC.Int ( Int64 )--import GHC.IO-import GHC.IOArray-import GHC.IORef-#else-import Data.Char ( ord )-import Data.IORef ( IORef, newIORef, readIORef, writeIORef )-import System.IO.Unsafe ( unsafePerformIO )-import Data.Int ( Int64 )-# if defined(__HUGS__)-import Hugs.IOArray ( IOArray, newIOArray,- unsafeReadIOArray, unsafeWriteIOArray )-# elif defined(__NHC__)-import NHC.IOExtras ( IOArray, newIOArray, readIOArray, writeIOArray )-# endif-#endif-import Control.Monad ( mapM, mapM_, sequence_ )----------------------------------------------------------------------------iNSTRUMENTED :: Bool-iNSTRUMENTED = False---------------------------------------------------------------------------readHTArray :: HTArray a -> Int32 -> IO a-writeMutArray :: MutArray a -> Int32 -> a -> IO ()-newMutArray :: (Int32, Int32) -> a -> IO (MutArray a)-newMutArray = newIOArray-type MutArray a = IOArray Int32 a-type HTArray a = MutArray a-#if defined(DEBUG) || defined(__NHC__)-readHTArray = readIOArray-writeMutArray = writeIOArray-#else-readHTArray arr i = unsafeReadIOArray arr (fromIntegral i)-writeMutArray arr i x = unsafeWriteIOArray arr (fromIntegral i) x-#endif--data HashTable key val = HashTable {- cmp :: !(key -> key -> Bool),- hash_fn :: !(key -> Int32),- tab :: !(IORef (HT key val))- }--- TODO: the IORef should really be an MVar.--data HT key val- = HT {- kcount :: !Int32, -- Total number of keys.- bmask :: !Int32,- buckets :: !(HTArray [(key,val)])- }---- --------------------------------------------------------------- Instrumentation for performance tuning---- This ought to be roundly ignored after optimization when--- iNSTRUMENTED=False.---- STRICT version of modifyIORef!-modifyIORef :: IORef a -> (a -> a) -> IO ()-modifyIORef r f = do- v <- readIORef r- let z = f v in z `seq` writeIORef r z--data HashData = HD {- tables :: !Integer,- insertions :: !Integer,- lookups :: !Integer,- totBuckets :: !Integer,- maxEntries :: !Int32,- maxChain :: !Int,- maxBuckets :: !Int32-} deriving (Eq, Show)--{-# NOINLINE hashData #-}-hashData :: IORef HashData-hashData = unsafePerformIO (newIORef (HD { tables=0, insertions=0, lookups=0,- totBuckets=0, maxEntries=0,- maxChain=0, maxBuckets=tABLE_MIN } ))--instrument :: (HashData -> HashData) -> IO ()-instrument i | iNSTRUMENTED = modifyIORef hashData i- | otherwise = return ()--recordNew :: IO ()-recordNew = instrument rec- where rec hd@HD{ tables=t, totBuckets=b } =- hd{ tables=t+1, totBuckets=b+fromIntegral tABLE_MIN }--recordIns :: Int32 -> Int32 -> [a] -> IO ()-recordIns i sz bkt = instrument rec- where rec hd@HD{ insertions=ins, maxEntries=mx, maxChain=mc } =- hd{ insertions=ins+fromIntegral i, maxEntries=mx `max` sz,- maxChain=mc `max` length bkt }--recordResize :: Int32 -> Int32 -> IO ()-recordResize older newer = instrument rec- where rec hd@HD{ totBuckets=b, maxBuckets=mx } =- hd{ totBuckets=b+fromIntegral (newer-older),- maxBuckets=mx `max` newer }--recordLookup :: IO ()-recordLookup = instrument lkup- where lkup hd@HD{ lookups=l } = hd{ lookups=l+1 }---- stats :: IO String--- stats = fmap show $ readIORef hashData---- ------------------------------------------------------------------------------- Sample hash functions---- $hash_functions------ This implementation of hash tables uses the low-order /n/ bits of the hash--- value for a key, where /n/ varies as the hash table grows. A good hash--- function therefore will give an even distribution regardless of /n/.------ If your keyspace is integrals such that the low-order bits between--- keys are highly variable, then you could get away with using 'fromIntegral'--- as the hash function.------ We provide some sample hash functions for 'Int' and 'String' below.--golden :: Int32-golden = 1013904242 -- = round ((sqrt 5 - 1) * 2^32) :: Int32--- was -1640531527 = round ((sqrt 5 - 1) * 2^31) :: Int32--- but that has bad mulHi properties (even adding 2^32 to get its inverse)--- Whereas the above works well and contains no hash duplications for--- [-32767..65536]--hashInt32 :: Int32 -> Int32-hashInt32 x = mulHi x golden + x---- | A sample (and useful) hash function for Int and Int32,--- implemented by extracting the uppermost 32 bits of the 64-bit--- result of multiplying by a 33-bit constant. The constant is from--- Knuth, derived from the golden ratio:------ > golden = round ((sqrt 5 - 1) * 2^32)------ We get good key uniqueness on small inputs--- (a problem with previous versions):--- (length $ group $ sort $ map hashInt [-32767..65536]) == 65536 + 32768----hashInt :: Int -> Int32-hashInt x = hashInt32 (fromIntegral x)---- hi 32 bits of a x-bit * 32 bit -> 64-bit multiply-mulHi :: Int32 -> Int32 -> Int32-mulHi a b = fromIntegral (r `shiftR` 32)- where r :: Int64- r = fromIntegral a * fromIntegral b---- | A sample hash function for Strings. We keep multiplying by the--- golden ratio and adding. The implementation is:------ > hashString = foldl' f golden--- > where f m c = fromIntegral (ord c) * magic + hashInt32 m--- > magic = 0xdeadbeef------ Where hashInt32 works just as hashInt shown above.------ Knuth argues that repeated multiplication by the golden ratio--- will minimize gaps in the hash space, and thus it's a good choice--- for combining together multiple keys to form one.------ Here we know that individual characters c are often small, and this--- produces frequent collisions if we use ord c alone. A--- particular problem are the shorter low ASCII and ISO-8859-1--- character strings. We pre-multiply by a magic twiddle factor to--- obtain a good distribution. In fact, given the following test:------ > testp :: Int32 -> Int--- > testp k = (n - ) . length . group . sort . map hs . take n $ ls--- > where ls = [] : [c : l | l <- ls, c <- ['\0'..'\xff']]--- > hs = foldl' f golden--- > f m c = fromIntegral (ord c) * k + hashInt32 m--- > n = 100000------ We discover that testp magic = 0.--hashString :: String -> Int32-hashString = foldl' f golden- where f m c = fromIntegral (ord c) * magic + hashInt32 m- magic = 0xdeadbeef---- | A prime larger than the maximum hash table size-prime :: Int32-prime = 33554467---- -------------------------------------------------------------------------------- Parameters--tABLE_MAX :: Int32-tABLE_MAX = 32 * 1024 * 1024 -- Maximum size of hash table-tABLE_MIN :: Int32-tABLE_MIN = 8--hLOAD :: Int32-hLOAD = 7 -- Maximum average load of a single hash bucket--hYSTERESIS :: Int32-hYSTERESIS = 64 -- entries to ignore in load computation--{- Hysteresis favors long association-list-like behavior for small tables. -}---- -------------------------------------------------------------------------------- Creating a new hash table---- | Creates a new hash table. The following property should hold for the @eq@--- and @hash@ functions passed to 'new':------ > eq A B => hash A == hash B----new- :: (key -> key -> Bool) -- ^ @eq@: An equality comparison on keys- -> (key -> Int32) -- ^ @hash@: A hash function on keys- -> IO (HashTable key val) -- ^ Returns: an empty hash table--new cmpr hash = do- recordNew- -- make a new hash table with a single, empty, segment- let mask = tABLE_MIN-1- bkts <- newMutArray (0,mask) []-- let- kcnt = 0- ht = HT { buckets=bkts, kcount=kcnt, bmask=mask }-- table <- newIORef ht- return (HashTable { tab=table, hash_fn=hash, cmp=cmpr })--{- - bitTwiddleSameAs takes as arguments positive Int32s less than maxBound/2 and - returns the smallest power of 2 that is greater than or equal to the - argument.- http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2--}-bitTwiddleSameAs :: Int32 -> Int32-bitTwiddleSameAs v0 = - let v1 = v0-1- v2 = v1 .|. (v1`shiftR`1)- v3 = v2 .|. (v2`shiftR`2)- v4 = v3 .|. (v3`shiftR`4)- v5 = v4 .|. (v4`shiftR`8)- v6 = v5 .|. (v5`shiftR`16)- in v6+1--{-- powerOver takes as arguments Int32s and returns the smallest power of 2 - that is greater than or equal to the argument if that power of 2 is - within [tABLE_MIN,tABLE_MAX]--}-powerOver :: Int32 -> Int32-powerOver n = - if n <= tABLE_MIN- then tABLE_MIN- else if n >= tABLE_MAX- then tABLE_MAX- else bitTwiddleSameAs n ---- | Creates a new hash table with the given minimum size.-newHint- :: (key -> key -> Bool) -- ^ @eq@: An equality comparison on keys- -> (key -> Int32) -- ^ @hash@: A hash function on keys- -> Int -- ^ @minSize@: initial table size- -> IO (HashTable key val) -- ^ Returns: an empty hash table--newHint cmpr hash minSize = do- recordNew- -- make a new hash table with a single, empty, segment- let mask = powerOver $ fromIntegral minSize- bkts <- newMutArray (0,mask) []-- let- kcnt = 0- ht = HT { buckets=bkts, kcount=kcnt, bmask=mask }-- table <- newIORef ht- return (HashTable { tab=table, hash_fn=hash, cmp=cmpr })---- -------------------------------------------------------------------------------- Inserting a key\/value pair into the hash table---- | Inserts a key\/value mapping into the hash table.------ Note that 'insert' doesn't remove the old entry from the table ---- the behaviour is like an association list, where 'lookup' returns--- the most-recently-inserted mapping for a key in the table. The--- reason for this is to keep 'insert' as efficient as possible. If--- you need to update a mapping, then we provide 'update'.----insert :: HashTable key val -> key -> val -> IO ()--insert ht key val =- updatingBucket CanInsert (\bucket -> ((key,val):bucket, 1, ())) ht key----- --------------------------------------------------------------- The core of the implementation is lurking down here, in findBucket,--- updatingBucket, and expandHashTable.--tooBig :: Int32 -> Int32 -> Bool-tooBig k b = k-hYSTERESIS > hLOAD * b---- index of bucket within table.-bucketIndex :: Int32 -> Int32 -> Int32-bucketIndex mask h = h .&. mask---- find the bucket in which the key belongs.--- returns (key equality, bucket index, bucket)------ This rather grab-bag approach gives enough power to do pretty much--- any bucket-finding thing you might want to do. We rely on inlining--- to throw away the stuff we don't want. I'm proud to say that this--- plus updatingBucket below reduce most of the other definitions to a--- few lines of code, while actually speeding up the hashtable--- implementation when compared with a version which does everything--- from scratch.-{-# INLINE findBucket #-}-findBucket :: HashTable key val -> key -> IO (HT key val, Int32, [(key,val)])-findBucket HashTable{ tab=ref, hash_fn=hash} key = do- table@HT{ buckets=bkts, bmask=b } <- readIORef ref- let indx = bucketIndex b (hash key)- bucket <- readHTArray bkts indx- return (table, indx, bucket)--data Inserts = CanInsert- | Can'tInsert- deriving (Eq)---- updatingBucket is the real workhorse of all single-element table--- updates. It takes a hashtable and a key, along with a function--- describing what to do with the bucket in which that key belongs. A--- flag indicates whether this function may perform table insertions.--- The function returns the new contents of the bucket, the number of--- bucket entries inserted (negative if entries were deleted), and a--- value which becomes the return value for the function as a whole.--- The table sizing is enforced here, calling out to expandSubTable as--- necessary.---- This function is intended to be inlined and specialized for every--- calling context (eg every provided bucketFn).-{-# INLINE updatingBucket #-}--updatingBucket :: Inserts -> ([(key,val)] -> ([(key,val)], Int32, a)) ->- HashTable key val -> key ->- IO a-updatingBucket canEnlarge bucketFn- ht@HashTable{ tab=ref, hash_fn=hash } key = do- (table@HT{ kcount=k, buckets=bkts, bmask=b },- indx, bckt) <- findBucket ht key- (bckt', inserts, result) <- return $ bucketFn bckt- let k' = k + inserts- table1 = table { kcount=k' }- writeMutArray bkts indx bckt'- table2 <- if canEnlarge == CanInsert && inserts > 0 then do- recordIns inserts k' bckt'- if tooBig k' b- then expandHashTable hash table1- else return table1- else return table1- writeIORef ref table2- return result--expandHashTable :: (key -> Int32) -> HT key val -> IO (HT key val)-expandHashTable hash table@HT{ buckets=bkts, bmask=mask } = do- let- oldsize = mask + 1- newmask = mask + mask + 1- recordResize oldsize (newmask+1)- --- if newmask > tABLE_MAX-1- then return table- else do- --- newbkts <- newMutArray (0,newmask) []-- let- splitBucket oldindex = do- bucket <- readHTArray bkts oldindex- let (oldb,newb) =- partition ((oldindex==). bucketIndex newmask . hash . fst) bucket- writeMutArray newbkts oldindex oldb- writeMutArray newbkts (oldindex + oldsize) newb- mapM_ splitBucket [0..mask]-- return ( table{ buckets=newbkts, bmask=newmask } )---- -------------------------------------------------------------------------------- Deleting a mapping from the hash table---- Remove a key from a bucket-deleteBucket :: (key -> Bool) -> [(key,val)] -> ([(key, val)], Int32, ())-deleteBucket _ [] = ([],0,())-deleteBucket del (pair@(k,_):bucket) =- case deleteBucket del bucket of- (bucket', dels, _) | del k -> dels' `seq` (bucket', dels', ())- | otherwise -> (pair:bucket', dels, ())- where dels' = dels - 1---- | Remove an entry from the hash table.-delete :: HashTable key val -> key -> IO ()--delete ht@HashTable{ cmp=eq } key =- updatingBucket Can'tInsert (deleteBucket (eq key)) ht key---- -------------------------------------------------------------------------------- Updating a mapping in the hash table---- | Updates an entry in the hash table, returning 'True' if there was--- already an entry for this key, or 'False' otherwise. After 'update'--- there will always be exactly one entry for the given key in the table.------ 'insert' is more efficient than 'update' if you don't care about--- multiple entries, or you know for sure that multiple entries can't--- occur. However, 'update' is more efficient than 'delete' followed--- by 'insert'.-update :: HashTable key val -> key -> val -> IO Bool--update ht@HashTable{ cmp=eq } key val =- updatingBucket CanInsert- (\bucket -> let (bucket', dels, _) = deleteBucket (eq key) bucket- in ((key,val):bucket', 1+dels, dels/=0))- ht key---- -------------------------------------------------------------------------------- Looking up an entry in the hash table---- | Looks up the value of a key in the hash table.-lookup :: HashTable key val -> key -> IO (Maybe val)--lookup ht@HashTable{ cmp=eq } key = do- recordLookup- (_, _, bucket) <- findBucket ht key- let firstHit (k,v) r | eq key k = Just v- | otherwise = r- return (foldr firstHit Nothing bucket)---- -------------------------------------------------------------------------------- Converting to/from lists---- | Convert a list of key\/value pairs into a hash table. Equality on keys--- is taken from the Eq instance for the key type.----fromList :: (Eq key) => (key -> Int32) -> [(key,val)] -> IO (HashTable key val)-fromList hash list = do- table <- new (==) hash- sequence_ [ insert table k v | (k,v) <- list ]- return table---- | Converts a hash table to a list of key\/value pairs.----toList :: HashTable key val -> IO [(key,val)]-toList = mapReduce id concat--{-# INLINE mapReduce #-}-mapReduce :: ([(key,val)] -> r) -> ([r] -> r) -> HashTable key val -> IO r-mapReduce m r HashTable{ tab=ref } = do- HT{ buckets=bckts, bmask=b } <- readIORef ref- fmap r (mapM (fmap m . readHTArray bckts) [0..b])---- -------------------------------------------------------------------------------- Diagnostics---- | This function is useful for determining whether your hash--- function is working well for your data set. It returns the longest--- chain of key\/value pairs in the hash table for which all the keys--- hash to the same bucket. If this chain is particularly long (say,--- longer than 14 elements or so), then it might be a good idea to try--- a different hash function.----longestChain :: HashTable key val -> IO [(key,val)]-longestChain = mapReduce id (maximumBy lengthCmp)- where lengthCmp (_:x)(_:y) = lengthCmp x y- lengthCmp [] [] = EQ- lengthCmp [] _ = LT- lengthCmp _ [] = GT-
@@ -1,141 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash, UnboxedTuples #-}---------------------------------------------------------------------------------- |--- Module : Data.IORef--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Mutable references in the IO monad.-----------------------------------------------------------------------------------module Data.IORef- ( - -- * IORefs- IORef, -- abstract, instance of: Eq, Typeable- newIORef, -- :: a -> IO (IORef a)- readIORef, -- :: IORef a -> IO a- writeIORef, -- :: IORef a -> a -> IO ()- modifyIORef, -- :: IORef a -> (a -> a) -> IO ()- atomicModifyIORef, -- :: IORef a -> (a -> (a,b)) -> IO b--#if !defined(__PARALLEL_HASKELL__) && defined(__GLASGOW_HASKELL__)- mkWeakIORef, -- :: IORef a -> IO () -> IO (Weak (IORef a))-#endif- -- ** Memory Model-- -- $memmodel-- ) where--#ifdef __HUGS__-import Hugs.IORef-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.STRef-import GHC.IORef hiding (atomicModifyIORef)-import qualified GHC.IORef-#if !defined(__PARALLEL_HASKELL__)-import GHC.Weak-#endif-#endif /* __GLASGOW_HASKELL__ */--#ifdef __NHC__-import NHC.IOExtras- ( IORef- , newIORef- , readIORef- , writeIORef- , excludeFinalisers- )-#endif--#if defined(__GLASGOW_HASKELL__) && !defined(__PARALLEL_HASKELL__)--- |Make a 'Weak' pointer to an 'IORef', using the second argument as a finalizer--- to run when 'IORef' is garbage-collected-mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a))-mkWeakIORef r@(IORef (STRef r#)) f = IO $ \s ->- case mkWeak# r# r f s of (# s1, w #) -> (# s1, Weak w #)-#endif---- |Mutate the contents of an 'IORef'-modifyIORef :: IORef a -> (a -> a) -> IO ()-modifyIORef ref f = readIORef ref >>= writeIORef ref . f----- |Atomically modifies the contents of an 'IORef'.------ This function is useful for using 'IORef' in a safe way in a multithreaded--- program. If you only have one 'IORef', then using 'atomicModifyIORef' to--- access and modify it will prevent race conditions.------ Extending the atomicity to multiple 'IORef's is problematic, so it--- is recommended that if you need to do anything more complicated--- then using 'Control.Concurrent.MVar.MVar' instead is a good idea.----atomicModifyIORef :: IORef a -> (a -> (a,b)) -> IO b-#if defined(__GLASGOW_HASKELL__)-atomicModifyIORef = GHC.IORef.atomicModifyIORef--#elif defined(__HUGS__)-atomicModifyIORef = plainModifyIORef -- Hugs has no preemption- where plainModifyIORef r f = do- a <- readIORef r- case f a of (a',b) -> writeIORef r a' >> return b-#elif defined(__NHC__)-atomicModifyIORef r f =- excludeFinalisers $ do- a <- readIORef r- let (a',b) = f a- writeIORef r a'- return b-#endif--{- $memmodel-- In a concurrent program, 'IORef' operations may appear out-of-order- to another thread, depending on the memory model of the underlying- processor architecture. For example, on x86, loads can move ahead- of stores, so in the following example:--> maybePrint :: IORef Bool -> IORef Bool -> IO ()-> maybePrint myRef yourRef = do-> writeIORef myRef True-> yourVal <- readIORef yourRef-> unless yourVal $ putStrLn "critical section"->-> main :: IO ()-> main = do-> r1 <- newIORef False-> r2 <- newIORef False-> forkIO $ maybePrint r1 r2-> forkIO $ maybePrint r2 r1-> threadDelay 1000000-- it is possible that the string @"critical section"@ is printed- twice, even though there is no interleaving of the operations of the- two threads that allows that outcome. The memory model of x86- allows 'readIORef' to happen before the earlier 'writeIORef'.-- The implementation is required to ensure that reordering of memory- operations cannot cause type-correct code to go wrong. In- particular, when inspecting the value read from an 'IORef', the- memory writes that created that value must have occurred from the- point of view of the current therad.-- 'atomicModifyIORef' acts as a barrier to reordering. Multiple- 'atomicModifyIORef' operations occur in strict program order. An- 'atomicModifyIORef' is never observed to take place ahead of any- earlier (in program order) 'IORef' operations, or after any later- 'IORef' operations.---}-
@@ -1,68 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Int--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Signed integer types-----------------------------------------------------------------------------------module Data.Int- ( - -- * Signed integer types- Int,- Int8, Int16, Int32, Int64,-- -- * Notes-- -- $notes- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base ( Int )-import GHC.Int ( Int8, Int16, Int32, Int64 )-#endif--#ifdef __HUGS__-import Hugs.Int ( Int8, Int16, Int32, Int64 )-#endif--#ifdef __NHC__-import Prelude-import Prelude (Int)-import NHC.FFI (Int8, Int16, Int32, Int64)-import NHC.SizedTypes (Int8, Int16, Int32, Int64) -- instances of Bits-#endif--{- $notes--* All arithmetic is performed modulo 2^n, where @n@ is the number of- bits in the type.--* For coercing between any two integer types, use 'Prelude.fromIntegral',- which is specialized for all the common cases so should be fast- enough. Coercing word types (see "Data.Word") to and from integer- types preserves representation, not sign.--* The rules that hold for 'Prelude.Enum' instances over a- bounded type such as 'Int' (see the section of the- Haskell report dealing with arithmetic sequences) also hold for the- 'Prelude.Enum' instances over the various- 'Int' types defined here.--* Right and left shifts by amounts greater than or equal to the width- of the type result in either zero or -1, depending on the sign of- the value being shifted. This is contrary to the behaviour in C,- which is undefined; a common interpretation is to truncate the shift- count to the width of the type, for example @1 \<\< 32- == 1@ in some C implementations.--}-
@@ -1,78 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Ix--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ The 'Ix' class is used to map a contiguous subrange of values in--- type onto integers. It is used primarily for array indexing--- (see the array package).--- --------------------------------------------------------------------------------module Data.Ix- (- -- * The 'Ix' class- Ix- ( range -- :: (Ix a) => (a,a) -> [a]- , index -- :: (Ix a) => (a,a) -> a -> Int- , inRange -- :: (Ix a) => (a,a) -> a -> Bool- , rangeSize -- :: (Ix a) => (a,a) -> Int- )- -- Ix instances:- --- -- Ix Char- -- Ix Int- -- Ix Integer- -- Ix Bool- -- Ix Ordering- -- Ix ()- -- (Ix a, Ix b) => Ix (a, b)- -- ...-- -- * Deriving Instances of 'Ix'- -- | Derived instance declarations for the class 'Ix' are only possible- -- for enumerations (i.e. datatypes having only nullary constructors)- -- and single-constructor datatypes, including arbitrarily large tuples,- -- whose constituent types are instances of 'Ix'. - -- - -- * For an enumeration, the nullary constructors are assumed to be- -- numbered left-to-right with the indices being 0 to n-1 inclusive. This- -- is the same numbering defined by the 'Enum' class. For example, given- -- the datatype: - -- - -- > data Colour = Red | Orange | Yellow | Green | Blue | Indigo | Violet- -- - -- we would have: - -- - -- > range (Yellow,Blue) == [Yellow,Green,Blue]- -- > index (Yellow,Blue) Green == 1- -- > inRange (Yellow,Blue) Red == False- -- - -- * For single-constructor datatypes, the derived instance declarations- -- are as shown for tuples in Figure 1- -- <http://www.haskell.org/onlinelibrary/ix.html#prelude-index>.-- ) where---- import Prelude--#ifdef __GLASGOW_HASKELL__-import GHC.Arr-#endif--#ifdef __HUGS__-import Hugs.Prelude( Ix(..) )-#endif--#ifdef __NHC__-import Ix (Ix(..))-#endif-
@@ -1,1170 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}---------------------------------------------------------------------------------- |--- Module : Data.List--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ Operations on lists.-----------------------------------------------------------------------------------module Data.List- (-#ifdef __NHC__- [] (..)- ,-#endif-- -- * Basic functions-- (++) -- :: [a] -> [a] -> [a]- , head -- :: [a] -> a- , last -- :: [a] -> a- , tail -- :: [a] -> [a]- , init -- :: [a] -> [a]- , null -- :: [a] -> Bool- , length -- :: [a] -> Int-- -- * List transformations- , map -- :: (a -> b) -> [a] -> [b]- , reverse -- :: [a] -> [a]-- , intersperse -- :: a -> [a] -> [a]- , intercalate -- :: [a] -> [[a]] -> [a]- , transpose -- :: [[a]] -> [[a]]- - , subsequences -- :: [a] -> [[a]]- , permutations -- :: [a] -> [[a]]-- -- * Reducing lists (folds)-- , foldl -- :: (a -> b -> a) -> a -> [b] -> a- , foldl' -- :: (a -> b -> a) -> a -> [b] -> a- , foldl1 -- :: (a -> a -> a) -> [a] -> a- , foldl1' -- :: (a -> a -> a) -> [a] -> a- , foldr -- :: (a -> b -> b) -> b -> [a] -> b- , foldr1 -- :: (a -> a -> a) -> [a] -> a-- -- ** Special folds-- , concat -- :: [[a]] -> [a]- , concatMap -- :: (a -> [b]) -> [a] -> [b]- , and -- :: [Bool] -> Bool- , or -- :: [Bool] -> Bool- , any -- :: (a -> Bool) -> [a] -> Bool- , all -- :: (a -> Bool) -> [a] -> Bool- , sum -- :: (Num a) => [a] -> a- , product -- :: (Num a) => [a] -> a- , maximum -- :: (Ord a) => [a] -> a- , minimum -- :: (Ord a) => [a] -> a-- -- * Building lists-- -- ** Scans- , scanl -- :: (a -> b -> a) -> a -> [b] -> [a]- , scanl1 -- :: (a -> a -> a) -> [a] -> [a]- , scanr -- :: (a -> b -> b) -> b -> [a] -> [b]- , scanr1 -- :: (a -> a -> a) -> [a] -> [a]-- -- ** Accumulating maps- , mapAccumL -- :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])- , mapAccumR -- :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])-- -- ** Infinite lists- , iterate -- :: (a -> a) -> a -> [a]- , repeat -- :: a -> [a]- , replicate -- :: Int -> a -> [a]- , cycle -- :: [a] -> [a]-- -- ** Unfolding- , unfoldr -- :: (b -> Maybe (a, b)) -> b -> [a]-- -- * Sublists-- -- ** Extracting sublists- , take -- :: Int -> [a] -> [a]- , drop -- :: Int -> [a] -> [a]- , splitAt -- :: Int -> [a] -> ([a], [a])-- , takeWhile -- :: (a -> Bool) -> [a] -> [a]- , dropWhile -- :: (a -> Bool) -> [a] -> [a]- , dropWhileEnd -- :: (a -> Bool) -> [a] -> [a]- , span -- :: (a -> Bool) -> [a] -> ([a], [a])- , break -- :: (a -> Bool) -> [a] -> ([a], [a])-- , stripPrefix -- :: Eq a => [a] -> [a] -> Maybe [a]-- , group -- :: Eq a => [a] -> [[a]]-- , inits -- :: [a] -> [[a]]- , tails -- :: [a] -> [[a]]-- -- ** Predicates- , isPrefixOf -- :: (Eq a) => [a] -> [a] -> Bool- , isSuffixOf -- :: (Eq a) => [a] -> [a] -> Bool- , isInfixOf -- :: (Eq a) => [a] -> [a] -> Bool-- -- * Searching lists-- -- ** Searching by equality- , elem -- :: a -> [a] -> Bool- , notElem -- :: a -> [a] -> Bool- , lookup -- :: (Eq a) => a -> [(a,b)] -> Maybe b-- -- ** Searching with a predicate- , find -- :: (a -> Bool) -> [a] -> Maybe a- , filter -- :: (a -> Bool) -> [a] -> [a]- , partition -- :: (a -> Bool) -> [a] -> ([a], [a])-- -- * Indexing lists- -- | These functions treat a list @xs@ as a indexed collection,- -- with indices ranging from 0 to @'length' xs - 1@.-- , (!!) -- :: [a] -> Int -> a-- , elemIndex -- :: (Eq a) => a -> [a] -> Maybe Int- , elemIndices -- :: (Eq a) => a -> [a] -> [Int]-- , findIndex -- :: (a -> Bool) -> [a] -> Maybe Int- , findIndices -- :: (a -> Bool) -> [a] -> [Int]-- -- * Zipping and unzipping lists-- , zip -- :: [a] -> [b] -> [(a,b)]- , zip3- , zip4, zip5, zip6, zip7-- , zipWith -- :: (a -> b -> c) -> [a] -> [b] -> [c]- , zipWith3- , zipWith4, zipWith5, zipWith6, zipWith7-- , unzip -- :: [(a,b)] -> ([a],[b])- , unzip3- , unzip4, unzip5, unzip6, unzip7-- -- * Special lists-- -- ** Functions on strings- , lines -- :: String -> [String]- , words -- :: String -> [String]- , unlines -- :: [String] -> String- , unwords -- :: [String] -> String-- -- ** \"Set\" operations-- , nub -- :: (Eq a) => [a] -> [a]-- , delete -- :: (Eq a) => a -> [a] -> [a]- , (\\) -- :: (Eq a) => [a] -> [a] -> [a]-- , union -- :: (Eq a) => [a] -> [a] -> [a]- , intersect -- :: (Eq a) => [a] -> [a] -> [a]-- -- ** Ordered lists- , sort -- :: (Ord a) => [a] -> [a]- , insert -- :: (Ord a) => a -> [a] -> [a]-- -- * Generalized functions-- -- ** The \"@By@\" operations- -- | By convention, overloaded functions have a non-overloaded- -- counterpart whose name is suffixed with \`@By@\'.- --- -- It is often convenient to use these functions together with- -- 'Data.Function.on', for instance @'sortBy' ('compare'- -- \`on\` 'fst')@.-- -- *** User-supplied equality (replacing an @Eq@ context)- -- | The predicate is assumed to define an equivalence.- , nubBy -- :: (a -> a -> Bool) -> [a] -> [a]- , deleteBy -- :: (a -> a -> Bool) -> a -> [a] -> [a]- , deleteFirstsBy -- :: (a -> a -> Bool) -> [a] -> [a] -> [a]- , unionBy -- :: (a -> a -> Bool) -> [a] -> [a] -> [a]- , intersectBy -- :: (a -> a -> Bool) -> [a] -> [a] -> [a]- , groupBy -- :: (a -> a -> Bool) -> [a] -> [[a]]-- -- *** User-supplied comparison (replacing an @Ord@ context)- -- | The function is assumed to define a total ordering.- , sortBy -- :: (a -> a -> Ordering) -> [a] -> [a]- , insertBy -- :: (a -> a -> Ordering) -> a -> [a] -> [a]- , maximumBy -- :: (a -> a -> Ordering) -> [a] -> a- , minimumBy -- :: (a -> a -> Ordering) -> [a] -> a-- -- ** The \"@generic@\" operations- -- | The prefix \`@generic@\' indicates an overloaded function that- -- is a generalized version of a "Prelude" function.-- , genericLength -- :: (Integral a) => [b] -> a- , genericTake -- :: (Integral a) => a -> [b] -> [b]- , genericDrop -- :: (Integral a) => a -> [b] -> [b]- , genericSplitAt -- :: (Integral a) => a -> [b] -> ([b], [b])- , genericIndex -- :: (Integral a) => [b] -> a -> b- , genericReplicate -- :: (Integral a) => a -> b -> [b]-- ) where--#ifdef __NHC__-import Prelude-#endif--import Data.Maybe-import Data.Char ( isSpace )--#ifdef __GLASGOW_HASKELL__-import GHC.Num-import GHC.Real-import GHC.List-import GHC.Base-#endif--infix 5 \\ -- comment to fool cpp---- -------------------------------------------------------------------------------- List functions---- | The 'dropWhileEnd' function drops the largest suffix of a list--- in which the given predicate holds for all elements. For example:------ > dropWhileEnd isSpace "foo\n" == "foo"--- > dropWhileEnd isSpace "foo bar" == "foo bar"--- > dropWhileEnd isSpace ("foo\n" ++ undefined) == "foo" ++ undefined--dropWhileEnd :: (a -> Bool) -> [a] -> [a]-dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []---- | The 'stripPrefix' function drops the given prefix from a list.--- It returns 'Nothing' if the list did not start with the prefix--- given, or 'Just' the list after the prefix, if it does.------ > stripPrefix "foo" "foobar" == Just "bar"--- > stripPrefix "foo" "foo" == Just ""--- > stripPrefix "foo" "barfoo" == Nothing--- > stripPrefix "foo" "barfoobaz" == Nothing-stripPrefix :: Eq a => [a] -> [a] -> Maybe [a]-stripPrefix [] ys = Just ys-stripPrefix (x:xs) (y:ys)- | x == y = stripPrefix xs ys-stripPrefix _ _ = Nothing---- | The 'elemIndex' function returns the index of the first element--- in the given list which is equal (by '==') to the query element,--- or 'Nothing' if there is no such element.-elemIndex :: Eq a => a -> [a] -> Maybe Int-elemIndex x = findIndex (x==)---- | The 'elemIndices' function extends 'elemIndex', by returning the--- indices of all elements equal to the query element, in ascending order.-elemIndices :: Eq a => a -> [a] -> [Int]-elemIndices x = findIndices (x==)---- | The 'find' function takes a predicate and a list and returns the--- first element in the list matching the predicate, or 'Nothing' if--- there is no such element.-find :: (a -> Bool) -> [a] -> Maybe a-find p = listToMaybe . filter p---- | The 'findIndex' function takes a predicate and a list and returns--- the index of the first element in the list satisfying the predicate,--- or 'Nothing' if there is no such element.-findIndex :: (a -> Bool) -> [a] -> Maybe Int-findIndex p = listToMaybe . findIndices p---- | The 'findIndices' function extends 'findIndex', by returning the--- indices of all elements satisfying the predicate, in ascending order.-findIndices :: (a -> Bool) -> [a] -> [Int]--#if defined(USE_REPORT_PRELUDE) || !defined(__GLASGOW_HASKELL__)-findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]-#else--- Efficient definition-findIndices p ls = loop 0 ls- where- loop _ [] = []- loop n (x:xs) | p x = n : loop (n + 1) xs- | otherwise = loop (n + 1) xs-#endif /* USE_REPORT_PRELUDE */---- | The 'isPrefixOf' function takes two lists and returns 'True'--- iff the first list is a prefix of the second.-isPrefixOf :: (Eq a) => [a] -> [a] -> Bool-isPrefixOf [] _ = True-isPrefixOf _ [] = False-isPrefixOf (x:xs) (y:ys)= x == y && isPrefixOf xs ys---- | The 'isSuffixOf' function takes two lists and returns 'True'--- iff the first list is a suffix of the second.--- Both lists must be finite.-isSuffixOf :: (Eq a) => [a] -> [a] -> Bool-isSuffixOf x y = reverse x `isPrefixOf` reverse y---- | The 'isInfixOf' function takes two lists and returns 'True'--- iff the first list is contained, wholly and intact,--- anywhere within the second.------ Example:------ >isInfixOf "Haskell" "I really like Haskell." == True--- >isInfixOf "Ial" "I really like Haskell." == False-isInfixOf :: (Eq a) => [a] -> [a] -> Bool-isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack)---- | /O(n^2)/. The 'nub' function removes duplicate elements from a list.--- In particular, it keeps only the first occurrence of each element.--- (The name 'nub' means \`essence\'.)--- It is a special case of 'nubBy', which allows the programmer to supply--- their own equality test.-nub :: (Eq a) => [a] -> [a]-#ifdef USE_REPORT_PRELUDE-nub = nubBy (==)-#else--- stolen from HBC-nub l = nub' l [] -- '- where- nub' [] _ = [] -- '- nub' (x:xs) ls -- '- | x `elem` ls = nub' xs ls -- '- | otherwise = x : nub' xs (x:ls) -- '-#endif---- | The 'nubBy' function behaves just like 'nub', except it uses a--- user-supplied equality predicate instead of the overloaded '=='--- function.-nubBy :: (a -> a -> Bool) -> [a] -> [a]-#ifdef USE_REPORT_PRELUDE-nubBy eq [] = []-nubBy eq (x:xs) = x : nubBy eq (filter (\ y -> not (eq x y)) xs)-#else-nubBy eq l = nubBy' l []- where- nubBy' [] _ = []- nubBy' (y:ys) xs- | elem_by eq y xs = nubBy' ys xs- | otherwise = y : nubBy' ys (y:xs)---- Not exported:--- Note that we keep the call to `eq` with arguments in the--- same order as in the reference implementation--- 'xs' is the list of things we've seen so far, --- 'y' is the potential new element-elem_by :: (a -> a -> Bool) -> a -> [a] -> Bool-elem_by _ _ [] = False-elem_by eq y (x:xs) = y `eq` x || elem_by eq y xs-#endif----- | 'delete' @x@ removes the first occurrence of @x@ from its list argument.--- For example,------ > delete 'a' "banana" == "bnana"------ It is a special case of 'deleteBy', which allows the programmer to--- supply their own equality test.--delete :: (Eq a) => a -> [a] -> [a]-delete = deleteBy (==)---- | The 'deleteBy' function behaves like 'delete', but takes a--- user-supplied equality predicate.-deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]-deleteBy _ _ [] = []-deleteBy eq x (y:ys) = if x `eq` y then ys else y : deleteBy eq x ys---- | The '\\' function is list difference (non-associative).--- In the result of @xs@ '\\' @ys@, the first occurrence of each element of--- @ys@ in turn (if any) has been removed from @xs@. Thus------ > (xs ++ ys) \\ xs == ys.------ It is a special case of 'deleteFirstsBy', which allows the programmer--- to supply their own equality test.--(\\) :: (Eq a) => [a] -> [a] -> [a]-(\\) = foldl (flip delete)---- | The 'union' function returns the list union of the two lists.--- For example,------ > "dog" `union` "cow" == "dogcw"------ Duplicates, and elements of the first list, are removed from the--- the second list, but if the first list contains duplicates, so will--- the result.--- It is a special case of 'unionBy', which allows the programmer to supply--- their own equality test.--union :: (Eq a) => [a] -> [a] -> [a]-union = unionBy (==)---- | The 'unionBy' function is the non-overloaded version of 'union'.-unionBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]-unionBy eq xs ys = xs ++ foldl (flip (deleteBy eq)) (nubBy eq ys) xs---- | The 'intersect' function takes the list intersection of two lists.--- For example,------ > [1,2,3,4] `intersect` [2,4,6,8] == [2,4]------ If the first list contains duplicates, so will the result.------ > [1,2,2,3,4] `intersect` [6,4,4,2] == [2,2,4]------ It is a special case of 'intersectBy', which allows the programmer to--- supply their own equality test.--intersect :: (Eq a) => [a] -> [a] -> [a]-intersect = intersectBy (==)---- | The 'intersectBy' function is the non-overloaded version of 'intersect'.-intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]-intersectBy _ [] _ = []-intersectBy _ _ [] = []-intersectBy eq xs ys = [x | x <- xs, any (eq x) ys]---- | The 'intersperse' function takes an element and a list and--- \`intersperses\' that element between the elements of the list.--- For example,------ > intersperse ',' "abcde" == "a,b,c,d,e"--intersperse :: a -> [a] -> [a]-intersperse _ [] = []-intersperse sep (x:xs) = x : prependToAll sep xs----- Not exported:--- We want to make every element in the 'intersperse'd list available--- as soon as possible to avoid space leaks. Experiments suggested that--- a separate top-level helper is more efficient than a local worker.-prependToAll :: a -> [a] -> [a]-prependToAll _ [] = []-prependToAll sep (x:xs) = sep : x : prependToAll sep xs---- | 'intercalate' @xs xss@ is equivalent to @('concat' ('intersperse' xs xss))@.--- It inserts the list @xs@ in between the lists in @xss@ and concatenates the--- result.-intercalate :: [a] -> [[a]] -> [a]-intercalate xs xss = concat (intersperse xs xss)---- | The 'transpose' function transposes the rows and columns of its argument.--- For example,------ > transpose [[1,2,3],[4,5,6]] == [[1,4],[2,5],[3,6]]--{-@ measure sumLens :: [[a]] -> GHC.Types.Int- sumLens ([]) = 0- sumLens (c:cs) = (len c) + (sumLens cs)- @-}-{-@ invariant {v:[[a]] | (sumLens v) >= 0} @-}-{-@ qualif SumLensEq(v:List List a, x:List List a): (sumLens v) = (sumLens x) @-}-{-@ qualif SumLensEq(v:List List a, x:List a): (sumLens v) = (len x) @-}-{-@ qualif SumLensLe(v:List List a, x:List List a): (sumLens v) <= (sumLens x) @-}--{-@ transpose :: xs:[[a]] -> [[a]] / [(sumLens xs)+(len xs)] @-}-transpose :: [[a]] -> [[a]]-transpose [] = []-transpose ([] : xss) = transpose xss-transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])---- | The 'partition' function takes a predicate a list and returns--- the pair of lists of elements which do and do not satisfy the--- predicate, respectively; i.e.,------ > partition p xs == (filter p xs, filter (not . p) xs)--partition :: (a -> Bool) -> [a] -> ([a],[a])-{-# INLINE partition #-}-partition p xs = foldr (select p) ([],[]) xs--select :: (a -> Bool) -> a -> ([a], [a]) -> ([a], [a])-select p x ~(ts,fs) | p x = (x:ts,fs)- | otherwise = (ts, x:fs)---- | The 'mapAccumL' function behaves like a combination of 'map' and--- 'foldl'; it applies a function to each element of a list, passing--- an accumulating parameter from left to right, and returning a final--- value of this accumulator together with the new list.-mapAccumL :: (acc -> x -> (acc, y)) -- Function of elt of input list- -- and accumulator, returning new- -- accumulator and elt of result list- -> acc -- Initial accumulator - -> [x] -- Input list- -> (acc, [y]) -- Final accumulator and result list-mapAccumL _ s [] = (s, [])-mapAccumL f s (x:xs) = (s'',y:ys)- where (s', y ) = f s x- (s'',ys) = mapAccumL f s' xs---- | The 'mapAccumR' function behaves like a combination of 'map' and--- 'foldr'; it applies a function to each element of a list, passing--- an accumulating parameter from right to left, and returning a final--- value of this accumulator together with the new list.-mapAccumR :: (acc -> x -> (acc, y)) -- Function of elt of input list- -- and accumulator, returning new- -- accumulator and elt of result list- -> acc -- Initial accumulator- -> [x] -- Input list- -> (acc, [y]) -- Final accumulator and result list-mapAccumR _ s [] = (s, [])-mapAccumR f s (x:xs) = (s'', y:ys)- where (s'',y ) = f s' x- (s', ys) = mapAccumR f s xs---- | The 'insert' function takes an element and a list and inserts the--- element into the list at the last position where it is still less--- than or equal to the next element. In particular, if the list--- is sorted before the call, the result will also be sorted.--- It is a special case of 'insertBy', which allows the programmer to--- supply their own comparison function.-insert :: Ord a => a -> [a] -> [a]-insert e ls = insertBy (compare) e ls---- | The non-overloaded version of 'insert'.-insertBy :: (a -> a -> Ordering) -> a -> [a] -> [a]-insertBy _ x [] = [x]-insertBy cmp x ys@(y:ys')- = case cmp x y of- GT -> y : insertBy cmp x ys'- _ -> x : ys--#ifdef __GLASGOW_HASKELL__---- | 'maximum' returns the maximum value from a list,--- which must be non-empty, finite, and of an ordered type.--- It is a special case of 'Data.List.maximumBy', which allows the--- programmer to supply their own comparison function.-{-@ maximum :: (Ord a) => {v:[a]|(len v) > 0} -> a @-}-maximum :: (Ord a) => [a] -> a-maximum [] = errorEmptyList "maximum"-maximum xs = foldl1 max xs--{-# RULES- "maximumInt" maximum = (strictMaximum :: [Int] -> Int);- "maximumInteger" maximum = (strictMaximum :: [Integer] -> Integer)- #-}---- We can't make the overloaded version of maximum strict without--- changing its semantics (max might not be strict), but we can for--- the version specialised to 'Int'.-{-@ strictMaximum :: (Ord a) => {v:[a]|(len v) > 0} -> a @-}-strictMaximum :: (Ord a) => [a] -> a-strictMaximum [] = errorEmptyList "maximum"-strictMaximum xs = foldl1' max xs---- | 'minimum' returns the minimum value from a list,--- which must be non-empty, finite, and of an ordered type.--- It is a special case of 'Data.List.minimumBy', which allows the--- programmer to supply their own comparison function.-{-@ minimum :: (Ord a) => {v:[a]|(len v) > 0} -> a @-}-minimum :: (Ord a) => [a] -> a-minimum [] = errorEmptyList "minimum"-minimum xs = foldl1 min xs--{-# RULES- "minimumInt" minimum = (strictMinimum :: [Int] -> Int);- "minimumInteger" minimum = (strictMinimum :: [Integer] -> Integer)- #-}--{-@ strictMinimum :: (Ord a) => {v:[a]| (len v) > 0 } -> a @-}-strictMinimum :: (Ord a) => [a] -> a-strictMinimum [] = errorEmptyList "minimum"-strictMinimum xs = foldl1' min xs--#endif /* __GLASGOW_HASKELL__ */---- | The 'maximumBy' function takes a comparison function and a list--- and returns the greatest element of the list by the comparison function.--- The list must be finite and non-empty.-maximumBy :: (a -> a -> Ordering) -> [a] -> a-maximumBy _ [] = error "List.maximumBy: empty list"-maximumBy cmp xs = foldl1 maxBy xs- where- maxBy x y = case cmp x y of- GT -> x- _ -> y---- | The 'minimumBy' function takes a comparison function and a list--- and returns the least element of the list by the comparison function.--- The list must be finite and non-empty.-minimumBy :: (a -> a -> Ordering) -> [a] -> a-minimumBy _ [] = error "List.minimumBy: empty list"-minimumBy cmp xs = foldl1 minBy xs- where- minBy x y = case cmp x y of- GT -> y- _ -> x---- | The 'genericLength' function is an overloaded version of 'length'. In--- particular, instead of returning an 'Int', it returns any type which is--- an instance of 'Num'. It is, however, less efficient than 'length'.-genericLength :: (Num i) => [b] -> i-genericLength [] = 0-genericLength (_:l) = 1 + genericLength l--{-# RULES- "genericLengthInt" genericLength = (strictGenericLength :: [a] -> Int);- "genericLengthInteger" genericLength = (strictGenericLength :: [a] -> Integer);- #-}--{-@ strictGenericLength :: (Num i) => [b] -> i @-}-strictGenericLength :: (Num i) => [b] -> i-strictGenericLength l = gl l 0- where- gl [] a = a- gl (_:xs) a = let a' = a + 1 in a' `seq` gl xs a'---- | The 'genericTake' function is an overloaded version of 'take', which--- accepts any 'Integral' value as the number of elements to take.-genericTake :: (Integral i) => i -> [a] -> [a]-genericTake n _ | n <= 0 = []-genericTake _ [] = []-genericTake n (x:xs) = x : genericTake (n-1) xs---- | The 'genericDrop' function is an overloaded version of 'drop', which--- accepts any 'Integral' value as the number of elements to drop.-genericDrop :: (Integral i) => i -> [a] -> [a]-genericDrop n xs | n <= 0 = xs-genericDrop _ [] = []-genericDrop n (_:xs) = genericDrop (n-1) xs----- | The 'genericSplitAt' function is an overloaded version of 'splitAt', which--- accepts any 'Integral' value as the position at which to split.-genericSplitAt :: (Integral i) => i -> [b] -> ([b],[b])-genericSplitAt n xs | n <= 0 = ([],xs)-genericSplitAt _ [] = ([],[])-genericSplitAt n (x:xs) = (x:xs',xs'') where- (xs',xs'') = genericSplitAt (n-1) xs---- | The 'genericIndex' function is an overloaded version of '!!', which--- accepts any 'Integral' value as the index.-genericIndex :: (Integral a) => [b] -> a -> b-genericIndex (x:_) 0 = x-genericIndex (_:xs) n- | n > 0 = genericIndex xs (n-1)- | otherwise = error "List.genericIndex: negative argument."-genericIndex _ _ = error "List.genericIndex: index too large."---- | The 'genericReplicate' function is an overloaded version of 'replicate',--- which accepts any 'Integral' value as the number of repetitions to make.-genericReplicate :: (Integral i) => i -> a -> [a]-genericReplicate n x = genericTake n (repeat x)---- | The 'zip4' function takes four lists and returns a list of--- quadruples, analogous to 'zip'.-zip4 :: [a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]-zip4 = zipWith4 (,,,)---- | The 'zip5' function takes five lists and returns a list of--- five-tuples, analogous to 'zip'.-zip5 :: [a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]-zip5 = zipWith5 (,,,,)---- | The 'zip6' function takes six lists and returns a list of six-tuples,--- analogous to 'zip'.-zip6 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] ->- [(a,b,c,d,e,f)]-zip6 = zipWith6 (,,,,,)---- | The 'zip7' function takes seven lists and returns a list of--- seven-tuples, analogous to 'zip'.-zip7 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] ->- [g] -> [(a,b,c,d,e,f,g)]-zip7 = zipWith7 (,,,,,,)---- | The 'zipWith4' function takes a function which combines four--- elements, as well as four lists and returns a list of their point-wise--- combination, analogous to 'zipWith'.-zipWith4 :: (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]-zipWith4 z (a:as) (b:bs) (c:cs) (d:ds)- = z a b c d : zipWith4 z as bs cs ds-zipWith4 _ _ _ _ _ = []---- | The 'zipWith5' function takes a function which combines five--- elements, as well as five lists and returns a list of their point-wise--- combination, analogous to 'zipWith'.-zipWith5 :: (a->b->c->d->e->f) ->- [a]->[b]->[c]->[d]->[e]->[f]-zipWith5 z (a:as) (b:bs) (c:cs) (d:ds) (e:es)- = z a b c d e : zipWith5 z as bs cs ds es-zipWith5 _ _ _ _ _ _ = []---- | The 'zipWith6' function takes a function which combines six--- elements, as well as six lists and returns a list of their point-wise--- combination, analogous to 'zipWith'.-zipWith6 :: (a->b->c->d->e->f->g) ->- [a]->[b]->[c]->[d]->[e]->[f]->[g]-zipWith6 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs)- = z a b c d e f : zipWith6 z as bs cs ds es fs-zipWith6 _ _ _ _ _ _ _ = []---- | The 'zipWith7' function takes a function which combines seven--- elements, as well as seven lists and returns a list of their point-wise--- combination, analogous to 'zipWith'.-zipWith7 :: (a->b->c->d->e->f->g->h) ->- [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]-zipWith7 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs)- = z a b c d e f g : zipWith7 z as bs cs ds es fs gs-zipWith7 _ _ _ _ _ _ _ _ = []---- | The 'unzip4' function takes a list of quadruples and returns four--- lists, analogous to 'unzip'.-unzip4 :: [(a,b,c,d)] -> ([a],[b],[c],[d])-unzip4 = foldr (\(a,b,c,d) ~(as,bs,cs,ds) ->- (a:as,b:bs,c:cs,d:ds))- ([],[],[],[])---- | The 'unzip5' function takes a list of five-tuples and returns five--- lists, analogous to 'unzip'.-unzip5 :: [(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])-unzip5 = foldr (\(a,b,c,d,e) ~(as,bs,cs,ds,es) ->- (a:as,b:bs,c:cs,d:ds,e:es))- ([],[],[],[],[])---- | The 'unzip6' function takes a list of six-tuples and returns six--- lists, analogous to 'unzip'.-unzip6 :: [(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])-unzip6 = foldr (\(a,b,c,d,e,f) ~(as,bs,cs,ds,es,fs) ->- (a:as,b:bs,c:cs,d:ds,e:es,f:fs))- ([],[],[],[],[],[])---- | The 'unzip7' function takes a list of seven-tuples and returns--- seven lists, analogous to 'unzip'.-unzip7 :: [(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])-unzip7 = foldr (\(a,b,c,d,e,f,g) ~(as,bs,cs,ds,es,fs,gs) ->- (a:as,b:bs,c:cs,d:ds,e:es,f:fs,g:gs))- ([],[],[],[],[],[],[])----- | The 'deleteFirstsBy' function takes a predicate and two lists and--- returns the first list with the first occurrence of each element of--- the second list removed.-deleteFirstsBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]-deleteFirstsBy eq = foldl (flip (deleteBy eq))---- | The 'group' function takes a list and returns a list of lists such--- that the concatenation of the result is equal to the argument. Moreover,--- each sublist in the result contains only equal elements. For example,------ > group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]------ It is a special case of 'groupBy', which allows the programmer to supply--- their own equality test.-group :: Eq a => [a] -> [[a]]-group = groupBy (==)---- | The 'groupBy' function is the non-overloaded version of 'group'.-groupBy :: (a -> a -> Bool) -> [a] -> [[a]]-groupBy _ [] = []-groupBy eq (x:xs) = (x:ys) : groupBy eq zs- where (ys,zs) = span (eq x) xs---- | The 'inits' function returns all initial segments of the argument,--- shortest first. For example,------ > inits "abc" == ["","a","ab","abc"]------ Note that 'inits' has the following strictness property:--- @inits _|_ = [] : _|_@-{-@ inits :: [a] -> {v:[[a]] | (len v) > 0} @-}-inits :: [a] -> [[a]]-inits xs = [] : case xs of- [] -> []- x : xs' -> map (x :) (inits xs')---- | The 'tails' function returns all final segments of the argument,--- longest first. For example,------ > tails "abc" == ["abc", "bc", "c",""]------ Note that 'tails' has the following strictness property:--- @tails _|_ = _|_ : _|_@-tails :: [a] -> [[a]]-tails xs = xs : case xs of- [] -> []- _ : xs' -> tails xs'---- | The 'subsequences' function returns the list of all subsequences of the argument.------ > subsequences "abc" == ["","a","b","ab","c","ac","bc","abc"]-subsequences :: [a] -> [[a]]-subsequences xs = [] : nonEmptySubsequences xs---- | The 'nonEmptySubsequences' function returns the list of all subsequences of the argument,--- except for the empty list.------ > nonEmptySubsequences "abc" == ["a","b","ab","c","ac","bc","abc"]-nonEmptySubsequences :: [a] -> [[a]]-nonEmptySubsequences [] = []-nonEmptySubsequences (x:xs) = [x] : foldr f [] (nonEmptySubsequences xs)- where f ys r = ys : (x : ys) : r----- | The 'permutations' function returns the list of all permutations of the argument.------ > permutations "abc" == ["abc","bac","cba","bca","cab","acb"]--{-@ permutations :: ts:[a] -> [[a]] / [(len ts), 1, 0] @-}-permutations :: [a] -> [[a]]-permutations xs0 = xs0 : perms xs0 []---{-@ perms :: ts:[a] -> is:[a] -> [[a]] / [((len ts)+(len is)), 0, (len ts)] @-}-perms :: [a] -> [a] -> [[a]]-perms [] _ = []-perms (t:ts) is = foldr interleave (perms ts (t:is)) (permutations is)- where interleave xs r = let (_,zs) = interleave' id xs r in zs- interleave' _ [] r = (ts, r)- interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:)) ys r- in (y:us, f (t:y:us) : zs)------------------------------------------------------------------------------------ Quick Sort algorithm taken from HBC's QSort library.---- | The 'sort' function implements a stable sorting algorithm.--- It is a special case of 'sortBy', which allows the programmer to supply--- their own comparison function.-sort :: (Ord a) => [a] -> [a]---- | The 'sortBy' function is the non-overloaded version of 'sort'.-sortBy :: (a -> a -> Ordering) -> [a] -> [a]--#ifdef USE_REPORT_PRELUDE-sort = sortBy compare-sortBy cmp = foldr (insertBy cmp) []-#else--{--GHC's mergesort replaced by a better implementation, 24/12/2009.-This code originally contributed to the nhc12 compiler by Thomas Nordin-in 2002. Rumoured to have been based on code by Lennart Augustsson, e.g.- http://www.mail-archive.com/haskell@haskell.org/msg01822.html-and possibly to bear similarities to a 1982 paper by Richard O'Keefe:-"A smooth applicative merge sort".--Benchmarks show it to be often 2x the speed of the previous implementation.-Fixes ticket http://hackage.haskell.org/trac/ghc/ticket/2143--}--{-@ type OList a = [a] @-}--sort = sortBy compare-sortBy cmp xs = mergeAll cmp $ sequences xs 0- where- {-@ decrease sequences 1 2 @-}- {- LIQUID WITNESS -}- sequences (a:b:xs) (_::Int)- | a `cmp` b == GT = descending b [a] xs 1- | otherwise = ascending b (a:) xs 1- sequences xs _ = [xs]-- {-@ decrease descending 3 4 @-}- {- LIQUID WITNESS -}- descending a as (b:bs) (_::Int)- | a `cmp` b == GT = descending b (a:as) bs 1 - descending a as bs _ = (a:as): sequences bs 0-- {-@ decrease ascending 3 4 @-}- {- LIQUID WITNESS -}- ascending a as (b:bs) (_::Int)- | a `cmp` b /= GT = ascending b (\ys -> as (a:ys)) bs 1- ascending a as bs _ = as [a]: sequences bs 0--mergeAll cmp [] = []-mergeAll cmp [x] = x-mergeAll cmp xs = mergeAll cmp (mergePairs cmp xs)--{-@ mergePairs :: (a -> a -> Ordering)- -> xss:[(OList a)] - -> {v:[(OList a)] | (if ((len xss) > 1) then ((len v) < (len xss)) else ((len v) = (len xss) ))}- @-}-mergePairs :: (a -> a -> Ordering) -> [[a]] -> [[a]]-mergePairs cmp (a:b:xs) = merge cmp a b: mergePairs cmp xs-mergePairs cmp xs = xs--{-@ merge :: (a -> a -> Ordering) - -> xs:(OList a) - -> ys:(OList a)- -> {v:(OList a) | (len v) = ((len xs) + (len ys))} - / [(len xs) + (len ys)] - @-}-merge :: (a -> a -> Ordering) -> [a] -> [a] -> [a] -merge cmp as@(a:as') bs@(b:bs')- | a `cmp` b == GT = b:merge cmp as bs'- | otherwise = a:merge cmp as' bs-merge _ [] bs = bs-merge _ as [] = as--{--sortBy cmp l = mergesort cmp l-sort l = mergesort compare l--Quicksort replaced by mergesort, 14/5/2002.--From: Ian Lynagh <igloo@earth.li>--I am curious as to why the List.sort implementation in GHC is a-quicksort algorithm rather than an algorithm that guarantees n log n-time in the worst case? I have attached a mergesort implementation along-with a few scripts to time it's performance, the results of which are-shown below (* means it didn't finish successfully - in all cases this-was due to a stack overflow).--If I heap profile the random_list case with only 10000 then I see-random_list peaks at using about 2.5M of memory, whereas in the same-program using List.sort it uses only 100k.--Input style Input length Sort data Sort alg User time-stdin 10000 random_list sort 2.82-stdin 10000 random_list mergesort 2.96-stdin 10000 sorted sort 31.37-stdin 10000 sorted mergesort 1.90-stdin 10000 revsorted sort 31.21-stdin 10000 revsorted mergesort 1.88-stdin 100000 random_list sort *-stdin 100000 random_list mergesort *-stdin 100000 sorted sort *-stdin 100000 sorted mergesort *-stdin 100000 revsorted sort *-stdin 100000 revsorted mergesort *-func 10000 random_list sort 0.31-func 10000 random_list mergesort 0.91-func 10000 sorted sort 19.09-func 10000 sorted mergesort 0.15-func 10000 revsorted sort 19.17-func 10000 revsorted mergesort 0.16-func 100000 random_list sort 3.85-func 100000 random_list mergesort *-func 100000 sorted sort 5831.47-func 100000 sorted mergesort 2.23-func 100000 revsorted sort 5872.34-func 100000 revsorted mergesort 2.24--mergesort :: (a -> a -> Ordering) -> [a] -> [a]-mergesort cmp = mergesort' cmp . map wrap--mergesort' :: (a -> a -> Ordering) -> [[a]] -> [a]-mergesort' _ [] = []-mergesort' _ [xs] = xs-mergesort' cmp xss = mergesort' cmp (merge_pairs cmp xss)--merge_pairs :: (a -> a -> Ordering) -> [[a]] -> [[a]]-merge_pairs _ [] = []-merge_pairs _ [xs] = [xs]-merge_pairs cmp (xs:ys:xss) = merge cmp xs ys : merge_pairs cmp xss--merge :: (a -> a -> Ordering) -> [a] -> [a] -> [a]-merge _ [] ys = ys-merge _ xs [] = xs-merge cmp (x:xs) (y:ys)- = case x `cmp` y of- GT -> y : merge cmp (x:xs) ys- _ -> x : merge cmp xs (y:ys)--wrap :: a -> [a]-wrap x = [x]----OLDER: qsort version---- qsort is stable and does not concatenate.-qsort :: (a -> a -> Ordering) -> [a] -> [a] -> [a]-qsort _ [] r = r-qsort _ [x] r = x:r-qsort cmp (x:xs) r = qpart cmp x xs [] [] r---- qpart partitions and sorts the sublists-qpart :: (a -> a -> Ordering) -> a -> [a] -> [a] -> [a] -> [a] -> [a]-qpart cmp x [] rlt rge r =- -- rlt and rge are in reverse order and must be sorted with an- -- anti-stable sorting- rqsort cmp rlt (x:rqsort cmp rge r)-qpart cmp x (y:ys) rlt rge r =- case cmp x y of- GT -> qpart cmp x ys (y:rlt) rge r- _ -> qpart cmp x ys rlt (y:rge) r---- rqsort is as qsort but anti-stable, i.e. reverses equal elements-rqsort :: (a -> a -> Ordering) -> [a] -> [a] -> [a]-rqsort _ [] r = r-rqsort _ [x] r = x:r-rqsort cmp (x:xs) r = rqpart cmp x xs [] [] r--rqpart :: (a -> a -> Ordering) -> a -> [a] -> [a] -> [a] -> [a] -> [a]-rqpart cmp x [] rle rgt r =- qsort cmp rle (x:qsort cmp rgt r)-rqpart cmp x (y:ys) rle rgt r =- case cmp y x of- GT -> rqpart cmp x ys rle (y:rgt) r- _ -> rqpart cmp x ys (y:rle) rgt r--}--#endif /* USE_REPORT_PRELUDE */---- | The 'unfoldr' function is a \`dual\' to 'foldr': while 'foldr'--- reduces a list to a summary value, 'unfoldr' builds a list from--- a seed value. The function takes the element and returns 'Nothing'--- if it is done producing the list or returns 'Just' @(a,b)@, in which--- case, @a@ is a prepended to the list and @b@ is used as the next--- element in a recursive call. For example,------ > iterate f == unfoldr (\x -> Just (x, f x))------ In some cases, 'unfoldr' can undo a 'foldr' operation:------ > unfoldr f' (foldr f z xs) == xs------ if the following holds:------ > f' (f x y) = Just (x,y)--- > f' z = Nothing------ A simple use of unfoldr:------ > unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10--- > [10,9,8,7,6,5,4,3,2,1]------ LIQUID TERMINATION : --- this function can not termination, eg f x = Just (b, b+1) -{-@ lazy Data.List.unfoldr @-}-unfoldr :: (b -> Maybe (a, b)) -> b -> [a]-unfoldr f b =- case f b of- Just (a,new_b) -> a : unfoldr f new_b- Nothing -> []---- -------------------------------------------------------------------------------- | A strict version of 'foldl'.-foldl' :: (a -> b -> a) -> a -> [b] -> a-#ifdef __GLASGOW_HASKELL__-foldl' f z0 xs0 = lgo z0 xs0- where lgo z [] = z- lgo z (x:xs) = let z' = f z x in z' `seq` lgo z' xs-#else-foldl' f a [] = a-foldl' f a (x:xs) = let a' = f a x in a' `seq` foldl' f a' xs-#endif---#ifdef __GLASGOW_HASKELL__--- | 'foldl1' is a variant of 'foldl' that has no starting value argument,--- and thus must be applied to non-empty lists.-{-@ foldl1 :: (a -> a -> a) -> {v:[a] | (len v) > 0} -> a @-}-foldl1 :: (a -> a -> a) -> [a] -> a-foldl1 f (x:xs) = foldl f x xs-foldl1 _ [] = errorEmptyList "foldl1"-#endif /* __GLASGOW_HASKELL__ */---- | A strict version of 'foldl1'-{-@ foldl1' :: (a -> a -> a) -> {v:[a] | (len v) > 0} -> a @-}-foldl1' :: (a -> a -> a) -> [a] -> a-foldl1' f (x:xs) = foldl' f x xs-foldl1' _ [] = errorEmptyList "foldl1'"--#ifdef __GLASGOW_HASKELL__--- -------------------------------------------------------------------------------- List sum and product--{-# SPECIALISE sum :: [Int] -> Int #-}-{-# SPECIALISE sum :: [Integer] -> Integer #-}-{-# SPECIALISE product :: [Int] -> Int #-}-{-# SPECIALISE product :: [Integer] -> Integer #-}--- | The 'sum' function computes the sum of a finite list of numbers.-sum :: (Num a) => [a] -> a--- | The 'product' function computes the product of a finite list of numbers.-product :: (Num a) => [a] -> a-#ifdef USE_REPORT_PRELUDE-sum = foldl (+) 0-product = foldl (*) 1-#else-sum l = sum' l 0- where- sum' [] a = a- sum' (x:xs) a = sum' xs (a+x)-product l = prod l 1- where- prod [] a = a- prod (x:xs) a = prod xs (a*x)-#endif---- -------------------------------------------------------------------------------- Functions on strings---- | 'lines' breaks a string up into a list of strings at newline--- characters. The resulting strings do not contain newlines.-lines :: String -> [String]-lines "" = []-#ifdef __GLASGOW_HASKELL__--- Somehow GHC doesn't detect the selector thunks in the below code,--- so s' keeps a reference to the first line via the pair and we have--- a space leak (cf. #4334).--- So we need to make GHC see the selector thunks with a trick.-lines s = cons (case break (== '\n') s of- (l, s') -> (l, case s' of- [] -> []- _:s'' -> lines s''))- where- cons ~(h, t) = h : t-#else-lines s = let (l, s') = break (== '\n') s- in l : case s' of- [] -> []- (_:s'') -> lines s''-#endif---- | 'unlines' is an inverse operation to 'lines'.--- It joins lines, after appending a terminating newline to each.-unlines :: [String] -> String-#ifdef USE_REPORT_PRELUDE-unlines = concatMap (++ "\n")-#else--- HBC version (stolen)--- here's a more efficient version-unlines [] = []-unlines (l:ls) = l ++ '\n' : unlines ls-#endif---- | 'words' breaks a string up into a list of words, which were delimited--- by white space.-{-@ lazy words @-}---LIQUID TODO: this function terminates because dropWhile guarantees that--- the first character of s' will not be a space, therefore--- w will not be empty and s'' < s.-words :: String -> [String]-words s = case dropWhile {-partain:Char.-}isSpace s of- "" -> []- s' -> w : words s''- where (w, s'') =- break {-partain:Char.-}isSpace s'---- | 'unwords' is an inverse operation to 'words'.--- It joins words with separating spaces.-unwords :: [String] -> String-#ifdef USE_REPORT_PRELUDE-unwords [] = ""-unwords ws = foldr1 (\w s -> w ++ ' ':s) ws-#else--- HBC version (stolen)--- here's a more efficient version-unwords [] = ""-unwords [w] = w-unwords (w:ws) = w ++ ' ' : unwords ws-#endif--#else /* !__GLASGOW_HASKELL__ */--errorEmptyList :: String -> a-errorEmptyList fun =- error ("Prelude." ++ fun ++ ": empty list")--#endif /* !__GLASGOW_HASKELL__ */-
@@ -1,151 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, DeriveGeneric #-}---------------------------------------------------------------------------------- |--- Module : Data.Maybe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ The Maybe type, and associated operations.-----------------------------------------------------------------------------------module Data.Maybe- (- Maybe(Nothing,Just)-- instance of: Eq, Ord, Show, Read,- -- Functor, Monad, MonadPlus-- , maybe -- :: b -> (a -> b) -> Maybe a -> b-- , isJust -- :: Maybe a -> Bool- , isNothing -- :: Maybe a -> Bool- , fromJust -- :: Maybe a -> a- , fromMaybe -- :: a -> Maybe a -> a- , listToMaybe -- :: [a] -> Maybe a- , maybeToList -- :: Maybe a -> [a]- , catMaybes -- :: [Maybe a] -> [a]- , mapMaybe -- :: (a -> Maybe b) -> [a] -> [b]- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Generics (Generic)-#endif--#ifdef __NHC__-import Prelude-import Prelude (Maybe(..), maybe)-import Maybe- ( isJust- , isNothing- , fromJust- , fromMaybe- , listToMaybe- , maybeToList- , catMaybes- , mapMaybe- )-#else--#ifndef __HUGS__--- ------------------------------------------------------------------------------ The Maybe type, and instances---- | The 'Maybe' type encapsulates an optional value. A value of type--- @'Maybe' a@ either contains a value of type @a@ (represented as @'Just' a@), --- or it is empty (represented as 'Nothing'). Using 'Maybe' is a good way to --- deal with errors or exceptional cases without resorting to drastic--- measures such as 'error'.------ The 'Maybe' type is also a monad. It is a simple kind of error--- monad, where all errors are represented by 'Nothing'. A richer--- error monad can be built using the 'Data.Either.Either' type.--data Maybe a = Nothing | Just a- deriving (Eq, Ord, Generic)--instance Functor Maybe where- fmap _ Nothing = Nothing- fmap f (Just a) = Just (f a)--instance Monad Maybe where- (Just x) >>= k = k x- Nothing >>= _ = Nothing-- (Just _) >> k = k- Nothing >> _ = Nothing-- return = Just---- ------------------------------------------------------------------------------ Functions over Maybe---- | The 'maybe' function takes a default value, a function, and a 'Maybe'--- value. If the 'Maybe' value is 'Nothing', the function returns the--- default value. Otherwise, it applies the function to the value inside--- the 'Just' and returns the result.-maybe :: b -> (a -> b) -> Maybe a -> b-maybe n _ Nothing = n-maybe _ f (Just x) = f x-#endif /* __HUGS__ */---- | The 'isJust' function returns 'True' iff its argument is of the--- form @Just _@.-isJust :: Maybe a -> Bool-isJust Nothing = False-isJust _ = True---- | The 'isNothing' function returns 'True' iff its argument is 'Nothing'.-isNothing :: Maybe a -> Bool-isNothing Nothing = True-isNothing _ = False---- | The 'fromJust' function extracts the element out of a 'Just' and--- throws an error if its argument is 'Nothing'.-fromJust :: Maybe a -> a-fromJust Nothing = error "Maybe.fromJust: Nothing" -- yuck-fromJust (Just x) = x---- | The 'fromMaybe' function takes a default value and a 'Maybe'--- value. If the 'Maybe' is 'Nothing', it returns the default values;--- otherwise, it returns the value contained in the 'Maybe'.-fromMaybe :: a -> Maybe a -> a-fromMaybe d x = case x of {Nothing -> d;Just v -> v}---- | The 'maybeToList' function returns an empty list when given--- 'Nothing' or a singleton list when not given 'Nothing'.-maybeToList :: Maybe a -> [a]-maybeToList Nothing = []-maybeToList (Just x) = [x]---- | The 'listToMaybe' function returns 'Nothing' on an empty list--- or @'Just' a@ where @a@ is the first element of the list.-listToMaybe :: [a] -> Maybe a-listToMaybe [] = Nothing-listToMaybe (a:_) = Just a---- | The 'catMaybes' function takes a list of 'Maybe's and returns--- a list of all the 'Just' values. -catMaybes :: [Maybe a] -> [a]-catMaybes ls = [x | Just x <- ls]---- | The 'mapMaybe' function is a version of 'map' which can throw--- out elements. In particular, the functional argument returns--- something of type @'Maybe' b@. If this is 'Nothing', no element--- is added on to the result list. If it just @'Just' b@, then @b@ is--- included in the result list.-mapMaybe :: (a -> Maybe b) -> [a] -> [b]-mapMaybe _ [] = []-mapMaybe f (x:xs) =- let rs = mapMaybe f xs in- case f x of- Nothing -> rs- Just r -> r:rs--#endif /* else not __NHC__ */-
@@ -1,288 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Monoid--- Copyright : (c) Andy Gill 2001,--- (c) Oregon Graduate Institute of Science and Technology, 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ A class for monoids (types with an associative binary operation that--- has an identity) with various general-purpose instances.-----------------------------------------------------------------------------------module Data.Monoid (- -- * Monoid typeclass- Monoid(..),- (<>),- Dual(..),- Endo(..),- -- * Bool wrappers- All(..),- Any(..),- -- * Num wrappers- Sum(..),- Product(..),- -- * Maybe wrappers- -- $MaybeExamples- First(..),- Last(..)- ) where---- Push down the module in the dependency hierarchy.-#if defined(__GLASGOW_HASKELL__)-import GHC.Base hiding (Any)-import GHC.Enum-import GHC.Num-import GHC.Read-import GHC.Show-import Data.Maybe-#else-import Prelude-#endif--{---- just for testing-import Data.Maybe-import Test.QuickCheck--- -}---- ------------------------------------------------------------------------------ | The class of monoids (types with an associative binary operation that--- has an identity). Instances should satisfy the following laws:------ * @mappend mempty x = x@------ * @mappend x mempty = x@------ * @mappend x (mappend y z) = mappend (mappend x y) z@------ * @mconcat = 'foldr' mappend mempty@------ The method names refer to the monoid of lists under concatenation,--- but there are many other instances.------ Minimal complete definition: 'mempty' and 'mappend'.------ Some types can be viewed as a monoid in more than one way,--- e.g. both addition and multiplication on numbers.--- In such cases we often define @newtype@s and make those instances--- of 'Monoid', e.g. 'Sum' and 'Product'.--class Monoid a where- mempty :: a- -- ^ Identity of 'mappend'- mappend :: a -> a -> a- -- ^ An associative operation- mconcat :: [a] -> a-- -- ^ Fold a list using the monoid.- -- For most types, the default definition for 'mconcat' will be- -- used, but the function is included in the class definition so- -- that an optimized version can be provided for specific types.-- mconcat = foldr mappend mempty--infixr 6 <>---- | An infix synonym for 'mappend'.-(<>) :: Monoid m => m -> m -> m-(<>) = mappend-{-# INLINE (<>) #-}---- Monoid instances.--instance Monoid [a] where- mempty = []- mappend = (++)--instance Monoid b => Monoid (a -> b) where- mempty _ = mempty- mappend f g x = f x `mappend` g x--instance Monoid () where- -- Should it be strict?- mempty = ()- _ `mappend` _ = ()- mconcat _ = ()--instance (Monoid a, Monoid b) => Monoid (a,b) where- mempty = (mempty, mempty)- (a1,b1) `mappend` (a2,b2) =- (a1 `mappend` a2, b1 `mappend` b2)--instance (Monoid a, Monoid b, Monoid c) => Monoid (a,b,c) where- mempty = (mempty, mempty, mempty)- (a1,b1,c1) `mappend` (a2,b2,c2) =- (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2)--instance (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a,b,c,d) where- mempty = (mempty, mempty, mempty, mempty)- (a1,b1,c1,d1) `mappend` (a2,b2,c2,d2) =- (a1 `mappend` a2, b1 `mappend` b2,- c1 `mappend` c2, d1 `mappend` d2)--instance (Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) =>- Monoid (a,b,c,d,e) where- mempty = (mempty, mempty, mempty, mempty, mempty)- (a1,b1,c1,d1,e1) `mappend` (a2,b2,c2,d2,e2) =- (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2,- d1 `mappend` d2, e1 `mappend` e2)---- lexicographical ordering-instance Monoid Ordering where- mempty = EQ- LT `mappend` _ = LT- EQ `mappend` y = y- GT `mappend` _ = GT---- | The dual of a monoid, obtained by swapping the arguments of 'mappend'.-newtype Dual a = Dual { getDual :: a }- deriving (Eq, Ord, Read, Show, Bounded)--instance Monoid a => Monoid (Dual a) where- mempty = Dual mempty- Dual x `mappend` Dual y = Dual (y `mappend` x)---- | The monoid of endomorphisms under composition.-newtype Endo a = Endo { appEndo :: a -> a }--instance Monoid (Endo a) where- mempty = Endo id- Endo f `mappend` Endo g = Endo (f . g)---- | Boolean monoid under conjunction.-newtype All = All { getAll :: Bool }- deriving (Eq, Ord, Read, Show, Bounded)--instance Monoid All where- mempty = All True- All x `mappend` All y = All (x && y)---- | Boolean monoid under disjunction.-newtype Any = Any { getAny :: Bool }- deriving (Eq, Ord, Read, Show, Bounded)--instance Monoid Any where- mempty = Any False- Any x `mappend` Any y = Any (x || y)---- | Monoid under addition.-newtype Sum a = Sum { getSum :: a }- deriving (Eq, Ord, Read, Show, Bounded)--instance Num a => Monoid (Sum a) where- mempty = Sum 0- Sum x `mappend` Sum y = Sum (x + y)---- | Monoid under multiplication.-newtype Product a = Product { getProduct :: a }- deriving (Eq, Ord, Read, Show, Bounded)--instance Num a => Monoid (Product a) where- mempty = Product 1- Product x `mappend` Product y = Product (x * y)---- $MaybeExamples--- To implement @find@ or @findLast@ on any 'Foldable':------ @--- findLast :: Foldable t => (a -> Bool) -> t a -> Maybe a--- findLast pred = getLast . foldMap (\x -> if pred x--- then Last (Just x)--- else Last Nothing)--- @------ Much of Data.Map's interface can be implemented with--- Data.Map.alter. Some of the rest can be implemented with a new--- @alterA@ function and either 'First' or 'Last':------ > alterA :: (Applicative f, Ord k) =>--- > (Maybe a -> f (Maybe a)) -> k -> Map k a -> f (Map k a)--- >--- > instance Monoid a => Applicative ((,) a) -- from Control.Applicative------ @--- insertLookupWithKey :: Ord k => (k -> v -> v -> v) -> k -> v--- -> Map k v -> (Maybe v, Map k v)--- insertLookupWithKey combine key value =--- Arrow.first getFirst . alterA doChange key--- where--- doChange Nothing = (First Nothing, Just value)--- doChange (Just oldValue) =--- (First (Just oldValue),--- Just (combine key value oldValue))--- @---- | Lift a semigroup into 'Maybe' forming a 'Monoid' according to--- <http://en.wikipedia.org/wiki/Monoid>: \"Any semigroup @S@ may be--- turned into a monoid simply by adjoining an element @e@ not in @S@--- and defining @e*e = e@ and @e*s = s = s*e@ for all @s ∈ S@.\" Since--- there is no \"Semigroup\" typeclass providing just 'mappend', we--- use 'Monoid' instead.-instance Monoid a => Monoid (Maybe a) where- mempty = Nothing- Nothing `mappend` m = m- m `mappend` Nothing = m- Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)----- | Maybe monoid returning the leftmost non-Nothing value.-newtype First a = First { getFirst :: Maybe a }-#ifndef __HADDOCK__- deriving (Eq, Ord, Read, Show)-#else /* __HADDOCK__ */-instance Eq a => Eq (First a)-instance Ord a => Ord (First a)-instance Read a => Read (First a)-instance Show a => Show (First a)-#endif--instance Monoid (First a) where- mempty = First Nothing- r@(First (Just _)) `mappend` _ = r- First Nothing `mappend` r = r---- | Maybe monoid returning the rightmost non-Nothing value.-newtype Last a = Last { getLast :: Maybe a }-#ifndef __HADDOCK__- deriving (Eq, Ord, Read, Show)-#else /* __HADDOCK__ */-instance Eq a => Eq (Last a)-instance Ord a => Ord (Last a)-instance Read a => Read (Last a)-instance Show a => Show (Last a)-#endif--instance Monoid (Last a) where- mempty = Last Nothing- _ `mappend` r@(Last (Just _)) = r- r `mappend` Last Nothing = r--{--{--------------------------------------------------------------------- Testing---------------------------------------------------------------------}-instance Arbitrary a => Arbitrary (Maybe a) where- arbitrary = oneof [return Nothing, Just `fmap` arbitrary]--prop_mconcatMaybe :: [Maybe [Int]] -> Bool-prop_mconcatMaybe x =- fromMaybe [] (mconcat x) == mconcat (catMaybes x)--prop_mconcatFirst :: [Maybe Int] -> Bool-prop_mconcatFirst x =- getFirst (mconcat (map First x)) == listToMaybe (catMaybes x)-prop_mconcatLast :: [Maybe Int] -> Bool-prop_mconcatLast x =- getLast (mconcat (map Last x)) == listLastToMaybe (catMaybes x)- where listLastToMaybe [] = Nothing- listLastToMaybe lst = Just (last lst)--- -}-
@@ -1,37 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Ord--- Copyright : (c) The University of Glasgow 2005--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ Orderings-----------------------------------------------------------------------------------module Data.Ord (- Ord(..),- Ordering(..),- comparing,- ) where--#if __GLASGOW_HASKELL__-import GHC.Base-#endif---- | --- > comparing p x y = compare (p x) (p y)------ Useful combinator for use in conjunction with the @xxxBy@ family--- of functions from "Data.List", for example:------ > ... sortBy (comparing fst) ...-comparing :: (Ord a) => (b -> a) -> b -> b -> Ordering-comparing p x y = compare (p x) (p y)-
@@ -1,98 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Ratio--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ Standard functions on rational numbers-----------------------------------------------------------------------------------module Data.Ratio- ( Ratio- , Rational- , (%) -- :: (Integral a) => a -> a -> Ratio a- , numerator -- :: (Integral a) => Ratio a -> a- , denominator -- :: (Integral a) => Ratio a -> a- , approxRational -- :: (RealFrac a) => a -> a -> Rational-- -- Ratio instances: - -- (Integral a) => Eq (Ratio a)- -- (Integral a) => Ord (Ratio a)- -- (Integral a) => Num (Ratio a)- -- (Integral a) => Real (Ratio a)- -- (Integral a) => Fractional (Ratio a)- -- (Integral a) => RealFrac (Ratio a)- -- (Integral a) => Enum (Ratio a)- -- (Read a, Integral a) => Read (Ratio a)- -- (Integral a) => Show (Ratio a)-- ) where--import Prelude--#ifdef __GLASGOW_HASKELL__-import GHC.Real -- The basic defns for Ratio-#endif--#ifdef __HUGS__-import Hugs.Prelude(Ratio(..), (%), numerator, denominator)-#endif--#ifdef __NHC__-import Ratio (Ratio(..), (%), numerator, denominator, approxRational)-#else---- -------------------------------------------------------------------------------- approxRational---- | 'approxRational', applied to two real fractional numbers @x@ and @epsilon@,--- returns the simplest rational number within @epsilon@ of @x@.--- A rational number @y@ is said to be /simpler/ than another @y'@ if------ * @'abs' ('numerator' y) <= 'abs' ('numerator' y')@, and------ * @'denominator' y <= 'denominator' y'@.------ Any real interval contains a unique simplest rational;--- in particular, note that @0\/1@ is the simplest rational of all.---- Implementation details: Here, for simplicity, we assume a closed rational--- interval. If such an interval includes at least one whole number, then--- the simplest rational is the absolutely least whole number. Otherwise,--- the bounds are of the form q%1 + r%d and q%1 + r'%d', where abs r < d--- and abs r' < d', and the simplest rational is q%1 + the reciprocal of--- the simplest rational between d'%r' and d%r.--approxRational :: (RealFrac a) => a -> a -> Rational-approxRational rat eps = simplest (rat-eps) (rat+eps)- where simplest x y | y < x = simplest y x- | x == y = xr- | x > 0 = simplest' n d n' d'- | y < 0 = - simplest' (-n') d' (-n) d- | otherwise = 0 :% 1- where xr = toRational x- n = numerator xr- d = denominator xr- nd' = toRational y- n' = numerator nd'- d' = denominator nd'-- simplest' n d n' d' -- assumes 0 < n%d < n'%d'- | r == 0 = q :% 1- | q /= q' = (q+1) :% 1- | otherwise = (q*n''+d'') :% n''- where (q,r) = quotRem n d- (q',r') = quotRem n' d'- nd'' = simplest' d' r' d r- n'' = numerator nd''- d'' = denominator nd''-#endif-
@@ -1,45 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.STRef--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (uses Control.Monad.ST)------ Mutable references in the (strict) ST monad.-----------------------------------------------------------------------------------module Data.STRef (- -- * STRefs- STRef, -- abstract, instance Eq- newSTRef, -- :: a -> ST s (STRef s a)- readSTRef, -- :: STRef s a -> ST s a- writeSTRef, -- :: STRef s a -> a -> ST s ()- modifySTRef -- :: STRef s a -> (a -> a) -> ST s ()- ) where--import Prelude--#ifdef __GLASGOW_HASKELL__-import GHC.ST-import GHC.STRef-#endif--#ifdef __HUGS__-import Hugs.ST-import Data.Typeable--#include "Typeable.h"-INSTANCE_TYPEABLE2(STRef,stRefTc,"STRef")-#endif---- |Mutate the contents of an 'STRef'-modifySTRef :: STRef s a -> (a -> a) -> ST s ()-modifySTRef ref f = writeSTRef ref . f =<< readSTRef ref-
@@ -1,39 +0,0 @@-{-# LANGUAGE Safe #-}---------------------------------------------------------------------------------- |--- Module : Data.STRef.Lazy--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (uses Control.Monad.ST.Lazy)------ Mutable references in the lazy ST monad.-----------------------------------------------------------------------------------module Data.STRef.Lazy (- -- * STRefs- ST.STRef, -- abstract, instance Eq- newSTRef, -- :: a -> ST s (STRef s a)- readSTRef, -- :: STRef s a -> ST s a- writeSTRef, -- :: STRef s a -> a -> ST s ()- modifySTRef -- :: STRef s a -> (a -> a) -> ST s ()- ) where--import Control.Monad.ST.Lazy.Safe-import qualified Data.STRef as ST-import Prelude--newSTRef :: a -> ST s (ST.STRef s a)-readSTRef :: ST.STRef s a -> ST s a-writeSTRef :: ST.STRef s a -> a -> ST s ()-modifySTRef :: ST.STRef s a -> (a -> a) -> ST s ()--newSTRef = strictToLazyST . ST.newSTRef-readSTRef = strictToLazyST . ST.readSTRef-writeSTRef r a = strictToLazyST (ST.writeSTRef r a)-modifySTRef r f = strictToLazyST (ST.modifySTRef r f)-
@@ -1,22 +0,0 @@-{-# LANGUAGE Safe #-}---------------------------------------------------------------------------------- |--- Module : Data.STRef.Strict--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (uses Control.Monad.ST.Strict)------ Mutable references in the (strict) ST monad (re-export of "Data.STRef")-----------------------------------------------------------------------------------module Data.STRef.Strict (- module Data.STRef- ) where--import Data.STRef-
@@ -1,44 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, FlexibleInstances #-}---------------------------------------------------------------------------------- |--- Module : Data.String--- Copyright : (c) The University of Glasgow 2007--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The @String@ type and associated operations.-----------------------------------------------------------------------------------module Data.String (- String- , IsString(..)-- -- * Functions on strings- , lines- , words- , unlines- , unwords- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-#endif--import Data.List (lines, words, unlines, unwords)---- | Class for string-like datastructures; used by the overloaded string--- extension (-foverloaded-strings in GHC).-class IsString a where- fromString :: String -> a--#ifndef __NHC__-instance IsString [Char] where- fromString xs = xs-#endif-
@@ -1,199 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Traversable--- Copyright : Conor McBride and Ross Paterson 2005--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Class of data structures that can be traversed from left to right,--- performing an action on each element.------ See also------ * /Applicative Programming with Effects/,--- by Conor McBride and Ross Paterson, online at--- <http://www.soi.city.ac.uk/~ross/papers/Applicative.html>.------ * /The Essence of the Iterator Pattern/,--- by Jeremy Gibbons and Bruno Oliveira,--- in /Mathematically-Structured Functional Programming/, 2006, and online at--- <http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/#iterator>.------ Note that the functions 'mapM' and 'sequence' generalize "Prelude"--- functions of the same names from lists to any 'Traversable' functor.--- To avoid ambiguity, either import the "Prelude" hiding these names--- or qualify uses of these function names with an alias for this module.-----------------------------------------------------------------------------------module Data.Traversable (- Traversable(..),- for,- forM,- mapAccumL,- mapAccumR,- fmapDefault,- foldMapDefault,- ) where--import Prelude hiding (mapM, sequence, foldr)-import qualified Prelude (mapM, foldr)-import Control.Applicative-import Data.Foldable (Foldable())-import Data.Monoid (Monoid)--#if defined(__GLASGOW_HASKELL__)-import GHC.Arr-#elif defined(__HUGS__)-import Hugs.Array-#elif defined(__NHC__)-import Array-#endif---- | Functors representing data structures that can be traversed from--- left to right.------ Minimal complete definition: 'traverse' or 'sequenceA'.------ Instances are similar to 'Functor', e.g. given a data type------ > data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)------ a suitable instance would be------ > instance Traversable Tree where--- > traverse f Empty = pure Empty--- > traverse f (Leaf x) = Leaf <$> f x--- > traverse f (Node l k r) = Node <$> traverse f l <*> f k <*> traverse f r------ This is suitable even for abstract types, as the laws for '<*>'--- imply a form of associativity.------ The superclass instances should satisfy the following:------ * In the 'Functor' instance, 'fmap' should be equivalent to traversal--- with the identity applicative functor ('fmapDefault').------ * In the 'Foldable' instance, 'Data.Foldable.foldMap' should be--- equivalent to traversal with a constant applicative functor--- ('foldMapDefault').----class (Functor t, Foldable t) => Traversable t where- -- | Map each element of a structure to an action, evaluate- -- these actions from left to right, and collect the results.- traverse :: Applicative f => (a -> f b) -> t a -> f (t b)- traverse f = sequenceA . fmap f-- -- | Evaluate each action in the structure from left to right,- -- and collect the results.- sequenceA :: Applicative f => t (f a) -> f (t a)- sequenceA = traverse id-- -- | Map each element of a structure to a monadic action, evaluate- -- these actions from left to right, and collect the results.- mapM :: Monad m => (a -> m b) -> t a -> m (t b)- mapM f = unwrapMonad . traverse (WrapMonad . f)-- -- | Evaluate each monadic action in the structure from left to right,- -- and collect the results.- sequence :: Monad m => t (m a) -> m (t a)- sequence = mapM id---- instances for Prelude types--instance Traversable Maybe where- traverse _ Nothing = pure Nothing- traverse f (Just x) = Just <$> f x--instance Traversable [] where- {-# INLINE traverse #-} -- so that traverse can fuse- traverse f = Prelude.foldr cons_f (pure [])- where cons_f x ys = (:) <$> f x <*> ys-- mapM = Prelude.mapM--instance Ix i => Traversable (Array i) where- traverse f arr = listArray (bounds arr) `fmap` traverse f (elems arr)---- general functions---- | 'for' is 'traverse' with its arguments flipped.-for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)-{-# INLINE for #-}-for = flip traverse---- | 'forM' is 'mapM' with its arguments flipped.-forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)-{-# INLINE forM #-}-forM = flip mapM---- left-to-right state transformer-newtype StateL s a = StateL { runStateL :: s -> (s, a) }--instance Functor (StateL s) where- fmap f (StateL k) = StateL $ \ s -> let (s', v) = k s in (s', f v)--instance Applicative (StateL s) where- pure x = StateL (\ s -> (s, x))- StateL kf <*> StateL kv = StateL $ \ s ->- let (s', f) = kf s- (s'', v) = kv s'- in (s'', f v)---- |The 'mapAccumL' function behaves like a combination of 'fmap'--- and 'foldl'; it applies a function to each element of a structure,--- passing an accumulating parameter from left to right, and returning--- a final value of this accumulator together with the new structure.-mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)-mapAccumL f s t = runStateL (traverse (StateL . flip f) t) s---- right-to-left state transformer-newtype StateR s a = StateR { runStateR :: s -> (s, a) }--instance Functor (StateR s) where- fmap f (StateR k) = StateR $ \ s -> let (s', v) = k s in (s', f v)--instance Applicative (StateR s) where- pure x = StateR (\ s -> (s, x))- StateR kf <*> StateR kv = StateR $ \ s ->- let (s', v) = kv s- (s'', f) = kf s'- in (s'', f v)---- |The 'mapAccumR' function behaves like a combination of 'fmap'--- and 'foldr'; it applies a function to each element of a structure,--- passing an accumulating parameter from right to left, and returning--- a final value of this accumulator together with the new structure.-mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)-mapAccumR f s t = runStateR (traverse (StateR . flip f) t) s---- | This function may be used as a value for `fmap` in a `Functor`--- instance, provided that 'traverse' is defined. (Using--- `fmapDefault` with a `Traversable` instance defined only by--- 'sequenceA' will result in infinite recursion.)-fmapDefault :: Traversable t => (a -> b) -> t a -> t b-{-# INLINE fmapDefault #-}-fmapDefault f = getId . traverse (Id . f)---- | This function may be used as a value for `Data.Foldable.foldMap`--- in a `Foldable` instance.-foldMapDefault :: (Traversable t, Monoid m) => (a -> m) -> t a -> m-foldMapDefault f = getConst . traverse (Const . f)---- local instances--newtype Id a = Id { getId :: a }--instance Functor Id where- fmap f (Id x) = Id (f x)--instance Applicative Id where- pure = Id- Id f <*> Id x = Id (f x)-
@@ -1,109 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}--- XXX -fno-warn-unused-imports needed for the GHC.Tuple import below. Sigh.---------------------------------------------------------------------------------- |--- Module : Data.Tuple--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The tuple data types, and associated functions.-----------------------------------------------------------------------------------module Data.Tuple- ( fst -- :: (a,b) -> a- , snd -- :: (a,b) -> a- , curry -- :: ((a, b) -> c) -> a -> b -> c- , uncurry -- :: (a -> b -> c) -> ((a, b) -> c)- , swap -- :: (a,b) -> (b,a)-#ifdef __NHC__- , (,)(..)- , (,,)(..)- , (,,,)(..)- , (,,,,)(..)- , (,,,,,)(..)- , (,,,,,,)(..)- , (,,,,,,,)(..)- , (,,,,,,,,)(..)- , (,,,,,,,,,)(..)- , (,,,,,,,,,,)(..)- , (,,,,,,,,,,,)(..)- , (,,,,,,,,,,,,)(..)- , (,,,,,,,,,,,,,)(..)- , (,,,,,,,,,,,,,,)(..)-#endif- )- where--#ifdef __GLASGOW_HASKELL__--import GHC.Base--- We need to depend on GHC.Base so that--- a) so that we get GHC.Classes, GHC.Types---- b) so that GHC.Base.inline is available, which is used--- when expanding instance declarations--import GHC.Tuple--- We must import GHC.Tuple, to ensure sure that the--- data constructors of `(,)' are in scope when we do--- the standalone deriving instance for Eq (a,b) etc--#endif /* __GLASGOW_HASKELL__ */--#ifdef __NHC__-import Prelude-import Prelude- ( (,)(..)- , (,,)(..)- , (,,,)(..)- , (,,,,)(..)- , (,,,,,)(..)- , (,,,,,,)(..)- , (,,,,,,,)(..)- , (,,,,,,,,)(..)- , (,,,,,,,,,)(..)- , (,,,,,,,,,,)(..)- , (,,,,,,,,,,,)(..)- , (,,,,,,,,,,,,)(..)- , (,,,,,,,,,,,,,)(..)- , (,,,,,,,,,,,,,,)(..)- -- nhc98's prelude only supplies tuple instances up to size 15- , fst, snd- , curry, uncurry- )-#endif--default () -- Double isn't available yet---- ------------------------------------------------------------------------------ Standard functions over tuples--#if !defined(__HUGS__) && !defined(__NHC__)--- | Extract the first component of a pair.-fst :: (a,b) -> a-fst (x,_) = x---- | Extract the second component of a pair.-snd :: (a,b) -> b-snd (_,y) = y---- | 'curry' converts an uncurried function to a curried function.-curry :: ((a, b) -> c) -> a -> b -> c-curry f x y = f (x, y)---- | 'uncurry' converts a curried function to a function on pairs.-uncurry :: (a -> b -> c) -> ((a, b) -> c)-uncurry f p = f (fst p) (snd p)-#endif /* neither __HUGS__ nor __NHC__ */---- | Swap the components of a pair.-swap :: (a,b) -> (b,a)-swap (a,b) = (b,a)
@@ -1,212 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , OverlappingInstances- , ScopedTypeVariables- , ForeignFunctionInterface- , FlexibleInstances- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---- The -XOverlappingInstances flag allows the user to over-ride--- the instances for Typeable given here. In particular, we provide an instance--- instance ... => Typeable (s a) --- But a user might want to say--- instance ... => Typeable (MyType a b)---------------------------------------------------------------------------------- |--- Module : Data.Typeable--- Copyright : (c) The University of Glasgow, CWI 2001--2004--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The 'Typeable' class reifies types to some extent by associating type--- representations to types. These type representations can be compared,--- and one can in turn define a type-safe cast operation. To this end,--- an unsafe cast is guarded by a test for type (representation)--- equivalence. The module "Data.Dynamic" uses Typeable for an--- implementation of dynamics. The module "Data.Data" uses Typeable--- and type-safe cast (but not dynamics) to support the \"Scrap your--- boilerplate\" style of generic programming.-----------------------------------------------------------------------------------module Data.Typeable- (-- -- * The Typeable class- Typeable( typeOf ), -- :: a -> TypeRep-- -- * Type-safe cast- cast, -- :: (Typeable a, Typeable b) => a -> Maybe b- gcast, -- a generalisation of cast-- -- * Type representations- TypeRep, -- abstract, instance of: Eq, Show, Typeable- showsTypeRep,-- TyCon, -- abstract, instance of: Eq, Show, Typeable- tyConString, -- :: TyCon -> String- tyConPackage, -- :: TyCon -> String- tyConModule, -- :: TyCon -> String- tyConName, -- :: TyCon -> String-- -- * Construction of type representations- mkTyCon, -- :: String -> TyCon- mkTyCon3, -- :: String -> String -> String -> TyCon- mkTyConApp, -- :: TyCon -> [TypeRep] -> TypeRep- mkAppTy, -- :: TypeRep -> TypeRep -> TypeRep- mkFunTy, -- :: TypeRep -> TypeRep -> TypeRep-- -- * Observation of type representations- splitTyConApp, -- :: TypeRep -> (TyCon, [TypeRep])- funResultTy, -- :: TypeRep -> TypeRep -> Maybe TypeRep- typeRepTyCon, -- :: TypeRep -> TyCon- typeRepArgs, -- :: TypeRep -> [TypeRep]- typeRepKey, -- :: TypeRep -> IO TypeRepKey- TypeRepKey, -- abstract, instance of Eq, Ord-- -- * The other Typeable classes- -- | /Note:/ The general instances are provided for GHC only.- Typeable1( typeOf1 ), -- :: t a -> TypeRep- Typeable2( typeOf2 ), -- :: t a b -> TypeRep- Typeable3( typeOf3 ), -- :: t a b c -> TypeRep- Typeable4( typeOf4 ), -- :: t a b c d -> TypeRep- Typeable5( typeOf5 ), -- :: t a b c d e -> TypeRep- Typeable6( typeOf6 ), -- :: t a b c d e f -> TypeRep- Typeable7( typeOf7 ), -- :: t a b c d e f g -> TypeRep- gcast1, -- :: ... => c (t a) -> Maybe (c (t' a))- gcast2, -- :: ... => c (t a b) -> Maybe (c (t' a b))-- -- * Default instances- -- | /Note:/ These are not needed by GHC, for which these instances- -- are generated by general instance declarations.- typeOfDefault, -- :: (Typeable1 t, Typeable a) => t a -> TypeRep- typeOf1Default, -- :: (Typeable2 t, Typeable a) => t a b -> TypeRep- typeOf2Default, -- :: (Typeable3 t, Typeable a) => t a b c -> TypeRep- typeOf3Default, -- :: (Typeable4 t, Typeable a) => t a b c d -> TypeRep- typeOf4Default, -- :: (Typeable5 t, Typeable a) => t a b c d e -> TypeRep- typeOf5Default, -- :: (Typeable6 t, Typeable a) => t a b c d e f -> TypeRep- typeOf6Default -- :: (Typeable7 t, Typeable a) => t a b c d e f g -> TypeRep-- ) where--import Data.Typeable.Internal hiding (mkTyCon)--import Unsafe.Coerce-import Data.Maybe--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Err (undefined)--import GHC.Fingerprint.Type-import {-# SOURCE #-} GHC.Fingerprint- -- loop: GHC.Fingerprint -> Foreign.Ptr -> Data.Typeable- -- Better to break the loop here, because we want non-SOURCE imports- -- of Data.Typeable as much as possible so we can optimise the derived- -- instances.--#endif--#ifdef __HUGS__-import Hugs.Prelude ( Key(..), TypeRep(..), TyCon(..), Ratio,- Handle, Ptr, FunPtr, ForeignPtr, StablePtr )-import Hugs.IORef ( IORef, newIORef, readIORef, writeIORef )-import Hugs.IOExts ( unsafePerformIO )- -- For the Typeable instance-import Hugs.Array ( Array )-import Hugs.IOArray-import Hugs.ConcBase ( MVar )-#endif--#ifdef __NHC__-import NHC.IOExtras (IOArray,IORef,newIORef,readIORef,writeIORef,unsafePerformIO)-import IO (Handle)-import Ratio (Ratio)- -- For the Typeable instance-import NHC.FFI ( Ptr,FunPtr,StablePtr,ForeignPtr )-import Array ( Array )-#endif--#include "Typeable.h"--{-# DEPRECATED typeRepKey "TypeRep itself is now an instance of Ord" #-}--- | (DEPRECATED) Returns a unique key associated with a 'TypeRep'.--- This function is deprecated because 'TypeRep' itself is now an--- instance of 'Ord', so mappings can be made directly with 'TypeRep'--- as the key.----typeRepKey :: TypeRep -> IO TypeRepKey-typeRepKey (TypeRep f _ _) = return (TypeRepKey f)-- -- - -- let fTy = mkTyCon "Foo" in show (mkTyConApp (mkTyCon ",,")- -- [fTy,fTy,fTy])- -- - -- returns "(Foo,Foo,Foo)"- --- -- The TypeRep Show instance promises to print tuple types- -- correctly. Tuple type constructors are specified by a - -- sequence of commas, e.g., (mkTyCon ",,,,") returns- -- the 5-tuple tycon.--newtype TypeRepKey = TypeRepKey Fingerprint- deriving (Eq,Ord)------------------- Construction -----------------------{-# DEPRECATED mkTyCon "either derive Typeable, or use mkTyCon3 instead" #-}--- | Backwards-compatible API-mkTyCon :: String -- ^ unique string- -> TyCon -- ^ A unique 'TyCon' object-mkTyCon name = TyCon (fingerprintString name) "" "" name--------------------------------------------------------------------- Type-safe cast--------------------------------------------------------------------- | The type-safe cast operation-cast :: (Typeable a, Typeable b) => a -> Maybe b-cast x = r- where- r = if typeOf x == typeOf (fromJust r)- then Just $ unsafeCoerce x- else Nothing---- | A flexible variation parameterised in a type constructor-gcast :: (Typeable a, Typeable b) => c a -> Maybe (c b)-gcast x = r- where- r = if typeOf (getArg x) == typeOf (getArg (fromJust r))- then Just $ unsafeCoerce x- else Nothing- getArg :: c x -> x - getArg = undefined---- | Cast for * -> *-gcast1 :: (Typeable1 t, Typeable1 t') => c (t a) -> Maybe (c (t' a)) -gcast1 x = r- where- r = if typeOf1 (getArg x) == typeOf1 (getArg (fromJust r))- then Just $ unsafeCoerce x- else Nothing- getArg :: c x -> x - getArg = undefined---- | Cast for * -> * -> *-gcast2 :: (Typeable2 t, Typeable2 t') => c (t a b) -> Maybe (c (t' a b)) -gcast2 x = r- where- r = if typeOf2 (getArg x) == typeOf2 (getArg (fromJust r))- then Just $ unsafeCoerce x- else Nothing- getArg :: c x -> x - getArg = undefined-
@@ -1,10 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Typeable (Typeable, mkTyConApp, cast) where--import Data.Maybe-import {-# SOURCE #-} Data.Typeable.Internal--cast :: (Typeable a, Typeable b) => a -> Maybe b-
@@ -1,570 +0,0 @@-{-# LANGUAGE Unsafe #-}---------------------------------------------------------------------------------- |--- Module : Data.Typeable.Internal--- Copyright : (c) The University of Glasgow, CWI 2001--2011--- License : BSD-style (see the file libraries/base/LICENSE)--- --- The representations of the types TyCon and TypeRep, and the--- function mkTyCon which is used by derived instances of Typeable to--- construct a TyCon.-----------------------------------------------------------------------------------{-# LANGUAGE CPP- , NoImplicitPrelude- , OverlappingInstances- , ScopedTypeVariables- , FlexibleInstances- , MagicHash #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif--module Data.Typeable.Internal (- TypeRep(..),- TyCon(..),- mkTyCon,- mkTyCon3,- mkTyConApp,- mkAppTy,- typeRepTyCon,- typeOfDefault,- typeOf1Default,- typeOf2Default,- typeOf3Default,- typeOf4Default,- typeOf5Default,- typeOf6Default,- Typeable(..),- Typeable1(..),- Typeable2(..),- Typeable3(..),- Typeable4(..),- Typeable5(..),- Typeable6(..),- Typeable7(..),- mkFunTy,- splitTyConApp,- funResultTy,- typeRepArgs,- showsTypeRep,- tyConString,-#if defined(__GLASGOW_HASKELL__)- listTc, funTc-#endif- ) where--import GHC.Base-import GHC.Word-import GHC.Show-import GHC.Err (undefined)-import Data.Maybe-import Data.List-import GHC.Num-import GHC.Real-import GHC.IORef-import GHC.IOArray-import GHC.MVar-import GHC.ST ( ST )-import GHC.STRef ( STRef )-import GHC.Ptr ( Ptr, FunPtr )-import GHC.Stable-import GHC.Arr ( Array, STArray )-import Data.Int--import GHC.Fingerprint.Type-import {-# SOURCE #-} GHC.Fingerprint- -- loop: GHC.Fingerprint -> Foreign.Ptr -> Data.Typeable- -- Better to break the loop here, because we want non-SOURCE imports- -- of Data.Typeable as much as possible so we can optimise the derived- -- instances.---- | A concrete representation of a (monomorphic) type. 'TypeRep'--- supports reasonably efficient equality.-data TypeRep = TypeRep {-# UNPACK #-} !Fingerprint TyCon [TypeRep]---- Compare keys for equality-instance Eq TypeRep where- (TypeRep k1 _ _) == (TypeRep k2 _ _) = k1 == k2--instance Ord TypeRep where- (TypeRep k1 _ _) <= (TypeRep k2 _ _) = k1 <= k2---- | An abstract representation of a type constructor. 'TyCon' objects can--- be built using 'mkTyCon'.-data TyCon = TyCon {- tyConHash :: {-# UNPACK #-} !Fingerprint,- tyConPackage :: String,- tyConModule :: String,- tyConName :: String- }--instance Eq TyCon where- (TyCon t1 _ _ _) == (TyCon t2 _ _ _) = t1 == t2--instance Ord TyCon where- (TyCon k1 _ _ _) <= (TyCon k2 _ _ _) = k1 <= k2------------------- Construction ----------------------#include "MachDeps.h"---- mkTyCon is an internal function to make it easier for GHC to--- generate derived instances. GHC precomputes the MD5 hash for the--- TyCon and passes it as two separate 64-bit values to mkTyCon. The--- TyCon for a derived Typeable instance will end up being statically--- allocated.--#if WORD_SIZE_IN_BITS < 64-mkTyCon :: Word64# -> Word64# -> String -> String -> String -> TyCon-#else-mkTyCon :: Word# -> Word# -> String -> String -> String -> TyCon-#endif-mkTyCon high# low# pkg modl name- = TyCon (Fingerprint (W64# high#) (W64# low#)) pkg modl name---- | Applies a type constructor to a sequence of types-mkTyConApp :: TyCon -> [TypeRep] -> TypeRep-mkTyConApp tc@(TyCon tc_k _ _ _) []- = TypeRep tc_k tc [] -- optimisation: all derived Typeable instances- -- end up here, and it helps generate smaller- -- code for derived Typeable.-mkTyConApp tc@(TyCon tc_k _ _ _) args- = TypeRep (fingerprintFingerprints (tc_k : arg_ks)) tc args- where- arg_ks = [k | TypeRep k _ _ <- args]---- | A special case of 'mkTyConApp', which applies the function --- type constructor to a pair of types.-mkFunTy :: TypeRep -> TypeRep -> TypeRep-mkFunTy f a = mkTyConApp funTc [f,a]---- | Splits a type constructor application-splitTyConApp :: TypeRep -> (TyCon,[TypeRep])-splitTyConApp (TypeRep _ tc trs) = (tc,trs)---- | Applies a type to a function type. Returns: @'Just' u@ if the--- first argument represents a function of type @t -> u@ and the--- second argument represents a function of type @t@. Otherwise,--- returns 'Nothing'.-funResultTy :: TypeRep -> TypeRep -> Maybe TypeRep-funResultTy trFun trArg- = case splitTyConApp trFun of- (tc, [t1,t2]) | tc == funTc && t1 == trArg -> Just t2- _ -> Nothing---- | Adds a TypeRep argument to a TypeRep.-mkAppTy :: TypeRep -> TypeRep -> TypeRep-mkAppTy (TypeRep tr_k tc trs) arg_tr- = let (TypeRep arg_k _ _) = arg_tr- in TypeRep (fingerprintFingerprints [tr_k,arg_k]) tc (trs++[arg_tr])---- | Builds a 'TyCon' object representing a type constructor. An--- implementation of "Data.Typeable" should ensure that the following holds:------ > A==A' ^ B==B' ^ C==C' ==> mkTyCon A B C == mkTyCon A' B' C'--------mkTyCon3 :: String -- ^ package name- -> String -- ^ module name- -> String -- ^ the name of the type constructor- -> TyCon -- ^ A unique 'TyCon' object-mkTyCon3 pkg modl name =- TyCon (fingerprintString (unwords [pkg, modl, name])) pkg modl name------------------- Observation ------------------------- | Observe the type constructor of a type representation-typeRepTyCon :: TypeRep -> TyCon-typeRepTyCon (TypeRep _ tc _) = tc---- | Observe the argument types of a type representation-typeRepArgs :: TypeRep -> [TypeRep]-typeRepArgs (TypeRep _ _ args) = args---- | Observe string encoding of a type representation-{-# DEPRECATED tyConString "renamed to tyConName; tyConModule and tyConPackage are also available." #-}-tyConString :: TyCon -> String-tyConString = tyConName--------------------------------------------------------------------- The Typeable class and friends-------------------------------------------------------------------{- Note [Memoising typeOf]-~~~~~~~~~~~~~~~~~~~~~~~~~~-IMPORTANT: we don't want to recalculate the type-rep once per-call to the dummy argument. This is what went wrong in Trac #3245-So we help GHC by manually keeping the 'rep' *outside* the value -lambda, thus- - typeOfDefault :: forall t a. (Typeable1 t, Typeable a) => t a -> TypeRep- typeOfDefault = \_ -> rep- where- rep = typeOf1 (undefined :: t a) `mkAppTy` - typeOf (undefined :: a)--Notice the crucial use of scoped type variables here!--}---- | The class 'Typeable' allows a concrete representation of a type to--- be calculated.-class Typeable a where- typeOf :: a -> TypeRep- -- ^ Takes a value of type @a@ and returns a concrete representation- -- of that type. The /value/ of the argument should be ignored by- -- any instance of 'Typeable', so that it is safe to pass 'undefined' as- -- the argument.---- | Variant for unary type constructors-class Typeable1 t where- typeOf1 :: t a -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable' instance from any 'Typeable1' instance.-typeOfDefault :: forall t a. (Typeable1 t, Typeable a) => t a -> TypeRep-typeOfDefault = \_ -> rep- where- rep = typeOf1 (undefined :: t a) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable' instance from any 'Typeable1' instance.-typeOfDefault :: (Typeable1 t, Typeable a) => t a -> TypeRep-typeOfDefault x = typeOf1 x `mkAppTy` typeOf (argType x)- where- argType :: t a -> a- argType = undefined-#endif---- | Variant for binary type constructors-class Typeable2 t where- typeOf2 :: t a b -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable1' instance from any 'Typeable2' instance.-typeOf1Default :: forall t a b. (Typeable2 t, Typeable a) => t a b -> TypeRep-typeOf1Default = \_ -> rep - where- rep = typeOf2 (undefined :: t a b) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable1' instance from any 'Typeable2' instance.-typeOf1Default :: (Typeable2 t, Typeable a) => t a b -> TypeRep-typeOf1Default x = typeOf2 x `mkAppTy` typeOf (argType x)- where- argType :: t a b -> a- argType = undefined-#endif---- | Variant for 3-ary type constructors-class Typeable3 t where- typeOf3 :: t a b c -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable2' instance from any 'Typeable3' instance.-typeOf2Default :: forall t a b c. (Typeable3 t, Typeable a) => t a b c -> TypeRep-typeOf2Default = \_ -> rep - where- rep = typeOf3 (undefined :: t a b c) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable2' instance from any 'Typeable3' instance.-typeOf2Default :: (Typeable3 t, Typeable a) => t a b c -> TypeRep-typeOf2Default x = typeOf3 x `mkAppTy` typeOf (argType x)- where- argType :: t a b c -> a- argType = undefined-#endif---- | Variant for 4-ary type constructors-class Typeable4 t where- typeOf4 :: t a b c d -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable3' instance from any 'Typeable4' instance.-typeOf3Default :: forall t a b c d. (Typeable4 t, Typeable a) => t a b c d -> TypeRep-typeOf3Default = \_ -> rep- where- rep = typeOf4 (undefined :: t a b c d) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable3' instance from any 'Typeable4' instance.-typeOf3Default :: (Typeable4 t, Typeable a) => t a b c d -> TypeRep-typeOf3Default x = typeOf4 x `mkAppTy` typeOf (argType x)- where- argType :: t a b c d -> a- argType = undefined-#endif- --- | Variant for 5-ary type constructors-class Typeable5 t where- typeOf5 :: t a b c d e -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable4' instance from any 'Typeable5' instance.-typeOf4Default :: forall t a b c d e. (Typeable5 t, Typeable a) => t a b c d e -> TypeRep-typeOf4Default = \_ -> rep - where- rep = typeOf5 (undefined :: t a b c d e) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable4' instance from any 'Typeable5' instance.-typeOf4Default :: (Typeable5 t, Typeable a) => t a b c d e -> TypeRep-typeOf4Default x = typeOf5 x `mkAppTy` typeOf (argType x)- where- argType :: t a b c d e -> a- argType = undefined-#endif---- | Variant for 6-ary type constructors-class Typeable6 t where- typeOf6 :: t a b c d e f -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable5' instance from any 'Typeable6' instance.-typeOf5Default :: forall t a b c d e f. (Typeable6 t, Typeable a) => t a b c d e f -> TypeRep-typeOf5Default = \_ -> rep- where- rep = typeOf6 (undefined :: t a b c d e f) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable5' instance from any 'Typeable6' instance.-typeOf5Default :: (Typeable6 t, Typeable a) => t a b c d e f -> TypeRep-typeOf5Default x = typeOf6 x `mkAppTy` typeOf (argType x)- where- argType :: t a b c d e f -> a- argType = undefined-#endif---- | Variant for 7-ary type constructors-class Typeable7 t where- typeOf7 :: t a b c d e f g -> TypeRep--#ifdef __GLASGOW_HASKELL__--- | For defining a 'Typeable6' instance from any 'Typeable7' instance.-typeOf6Default :: forall t a b c d e f g. (Typeable7 t, Typeable a) => t a b c d e f g -> TypeRep-typeOf6Default = \_ -> rep- where- rep = typeOf7 (undefined :: t a b c d e f g) `mkAppTy` - typeOf (undefined :: a)- -- Note [Memoising typeOf]-#else--- | For defining a 'Typeable6' instance from any 'Typeable7' instance.-typeOf6Default :: (Typeable7 t, Typeable a) => t a b c d e f g -> TypeRep-typeOf6Default x = typeOf7 x `mkAppTy` typeOf (argType x)- where- argType :: t a b c d e f g -> a- argType = undefined-#endif--#ifdef __GLASGOW_HASKELL__--- Given a @Typeable@/n/ instance for an /n/-ary type constructor,--- define the instances for partial applications.--- Programmers using non-GHC implementations must do this manually--- for each type constructor.--- (The INSTANCE_TYPEABLE/n/ macros in Typeable.h include this.)---- | One Typeable instance for all Typeable1 instances-instance (Typeable1 s, Typeable a)- => Typeable (s a) where- typeOf = typeOfDefault---- | One Typeable1 instance for all Typeable2 instances-instance (Typeable2 s, Typeable a)- => Typeable1 (s a) where- typeOf1 = typeOf1Default---- | One Typeable2 instance for all Typeable3 instances-instance (Typeable3 s, Typeable a)- => Typeable2 (s a) where- typeOf2 = typeOf2Default---- | One Typeable3 instance for all Typeable4 instances-instance (Typeable4 s, Typeable a)- => Typeable3 (s a) where- typeOf3 = typeOf3Default---- | One Typeable4 instance for all Typeable5 instances-instance (Typeable5 s, Typeable a)- => Typeable4 (s a) where- typeOf4 = typeOf4Default---- | One Typeable5 instance for all Typeable6 instances-instance (Typeable6 s, Typeable a)- => Typeable5 (s a) where- typeOf5 = typeOf5Default---- | One Typeable6 instance for all Typeable7 instances-instance (Typeable7 s, Typeable a)- => Typeable6 (s a) where- typeOf6 = typeOf6Default--#endif /* __GLASGOW_HASKELL__ */------------------- Showing TypeReps ----------------------instance Show TypeRep where- showsPrec p (TypeRep _ tycon tys) =- case tys of- [] -> showsPrec p tycon- [x] | tycon == listTc -> showChar '[' . shows x . showChar ']'- [a,r] | tycon == funTc -> showParen (p > 8) $- showsPrec 9 a .- showString " -> " .- showsPrec 8 r- xs | isTupleTyCon tycon -> showTuple xs- | otherwise ->- showParen (p > 9) $- showsPrec p tycon . - showChar ' ' . - showArgs tys--showsTypeRep :: TypeRep -> ShowS-showsTypeRep = shows--instance Show TyCon where- showsPrec _ t = showString (tyConName t)--isTupleTyCon :: TyCon -> Bool-isTupleTyCon (TyCon _ _ _ ('(':',':_)) = True-isTupleTyCon _ = False---- Some (Show.TypeRep) helpers:--showArgs :: Show a => [a] -> ShowS-showArgs [] = id-showArgs [a] = showsPrec 10 a-showArgs (a:as) = showsPrec 10 a . showString " " . showArgs as --showTuple :: [TypeRep] -> ShowS-showTuple args = showChar '('- . (foldr (.) id $ intersperse (showChar ',') - $ map (showsPrec 10) args)- . showChar ')'--#if defined(__GLASGOW_HASKELL__)-listTc :: TyCon-listTc = typeRepTyCon (typeOf [()])--funTc :: TyCon-funTc = mkTyCon3 "ghc-prim" "GHC.Types" "->"-#endif--------------------------------------------------------------------- Instances of the Typeable classes for Prelude types-------------------------------------------------------------------#include "Typeable.h"--INSTANCE_TYPEABLE0((),unitTc,"()")-INSTANCE_TYPEABLE1([],listTc,"[]")-INSTANCE_TYPEABLE1(Maybe,maybeTc,"Maybe")-INSTANCE_TYPEABLE1(Ratio,ratioTc,"Ratio")-#if defined(__GLASGOW_HASKELL__)-{--TODO: Deriving this instance fails with:-libraries/base/Data/Typeable.hs:589:1:- Can't make a derived instance of `Typeable2 (->)':- The last argument of the instance must be a data or newtype application- In the stand-alone deriving instance for `Typeable2 (->)'--}-instance Typeable2 (->) where { typeOf2 _ = mkTyConApp funTc [] }-#else-INSTANCE_TYPEABLE2((->),funTc,"->")-#endif-INSTANCE_TYPEABLE1(IO,ioTc,"IO")--#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)--- Types defined in GHC.MVar-INSTANCE_TYPEABLE1(MVar,mvarTc,"MVar" )-#endif--INSTANCE_TYPEABLE2(Array,arrayTc,"Array")-INSTANCE_TYPEABLE2(IOArray,iOArrayTc,"IOArray")--#ifdef __GLASGOW_HASKELL__--- Hugs has these too, but their Typeable<n> instances are defined--- elsewhere to keep this module within Haskell 98.--- This is important because every invocation of runhugs or ffihugs--- uses this module via Data.Dynamic.-INSTANCE_TYPEABLE2(ST,stTc,"ST")-INSTANCE_TYPEABLE2(STRef,stRefTc,"STRef")-INSTANCE_TYPEABLE3(STArray,sTArrayTc,"STArray")-#endif--#ifndef __NHC__-INSTANCE_TYPEABLE2((,),pairTc,"(,)")-INSTANCE_TYPEABLE3((,,),tup3Tc,"(,,)")-INSTANCE_TYPEABLE4((,,,),tup4Tc,"(,,,)")-INSTANCE_TYPEABLE5((,,,,),tup5Tc,"(,,,,)")-INSTANCE_TYPEABLE6((,,,,,),tup6Tc,"(,,,,,)")-INSTANCE_TYPEABLE7((,,,,,,),tup7Tc,"(,,,,,,)")-#endif /* __NHC__ */--INSTANCE_TYPEABLE1(Ptr,ptrTc,"Ptr")-INSTANCE_TYPEABLE1(FunPtr,funPtrTc,"FunPtr")-#ifndef __GLASGOW_HASKELL__-INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")-#endif-INSTANCE_TYPEABLE1(StablePtr,stablePtrTc,"StablePtr")-INSTANCE_TYPEABLE1(IORef,iORefTc,"IORef")--------------------------------------------------------------- Generate Typeable instances for standard datatypes-------------------------------------------------------------INSTANCE_TYPEABLE0(Bool,boolTc,"Bool")-INSTANCE_TYPEABLE0(Char,charTc,"Char")-INSTANCE_TYPEABLE0(Float,floatTc,"Float")-INSTANCE_TYPEABLE0(Double,doubleTc,"Double")-INSTANCE_TYPEABLE0(Int,intTc,"Int")-#ifndef __NHC__-INSTANCE_TYPEABLE0(Word,wordTc,"Word" )-#endif-INSTANCE_TYPEABLE0(Integer,integerTc,"Integer")-INSTANCE_TYPEABLE0(Ordering,orderingTc,"Ordering")-#ifndef __GLASGOW_HASKELL__-INSTANCE_TYPEABLE0(Handle,handleTc,"Handle")-#endif--INSTANCE_TYPEABLE0(Int8,int8Tc,"Int8")-INSTANCE_TYPEABLE0(Int16,int16Tc,"Int16")-INSTANCE_TYPEABLE0(Int32,int32Tc,"Int32")-INSTANCE_TYPEABLE0(Int64,int64Tc,"Int64")--INSTANCE_TYPEABLE0(Word8,word8Tc,"Word8" )-INSTANCE_TYPEABLE0(Word16,word16Tc,"Word16")-INSTANCE_TYPEABLE0(Word32,word32Tc,"Word32")-INSTANCE_TYPEABLE0(Word64,word64Tc,"Word64")--INSTANCE_TYPEABLE0(TyCon,tyconTc,"TyCon")-INSTANCE_TYPEABLE0(TypeRep,typeRepTc,"TypeRep")--#ifdef __GLASGOW_HASKELL__-{--TODO: This can't be derived currently:-libraries/base/Data/Typeable.hs:674:1:- Can't make a derived instance of `Typeable RealWorld':- The last argument of the instance must be a data or newtype application- In the stand-alone deriving instance for `Typeable RealWorld'--}-realWorldTc :: TyCon; \-realWorldTc = mkTyCon3 "ghc-prim" "GHC.Types" "RealWorld"; \-instance Typeable RealWorld where { typeOf _ = mkTyConApp realWorldTc [] }--#endif
@@ -1,28 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}--module Data.Typeable.Internal (- Typeable(typeOf),- TypeRep,- TyCon,- mkTyCon,- mkTyConApp- ) where--import GHC.Base--data TypeRep-data TyCon--#include "MachDeps.h"--#if WORD_SIZE_IN_BITS < 64-mkTyCon :: Word64# -> Word64# -> String -> String -> String -> TyCon-#else-mkTyCon :: Word# -> Word# -> String -> String -> String -> TyCon-#endif--mkTyConApp :: TyCon -> [TypeRep] -> TypeRep--class Typeable a where- typeOf :: a -> TypeRep
@@ -1,78 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}--#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE MagicHash, DeriveDataTypeable #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Unique--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable------ An abstract interface to a unique symbol generator.-----------------------------------------------------------------------------------module Data.Unique (- -- * Unique objects- Unique, -- instance (Eq, Ord)- newUnique, -- :: IO Unique- hashUnique -- :: Unique -> Int- ) where--import Prelude--import System.IO.Unsafe (unsafePerformIO)--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Num-import GHC.Conc-import Data.Typeable-#endif---- | An abstract unique object. Objects of type 'Unique' may be--- compared for equality and ordering and hashed into 'Int'.-newtype Unique = Unique Integer deriving (Eq,Ord-#ifdef __GLASGOW_HASKELL__- ,Typeable-#endif- )--uniqSource :: TVar Integer-uniqSource = unsafePerformIO (newTVarIO 0)-{-# NOINLINE uniqSource #-}---- | Creates a new object of type 'Unique'. The value returned will--- not compare equal to any other value of type 'Unique' returned by--- previous calls to 'newUnique'. There is no limit on the number of--- times 'newUnique' may be called.-newUnique :: IO Unique-newUnique = atomically $ do- val <- readTVar uniqSource- let next = val+1- writeTVar uniqSource $! next- return (Unique next)---- SDM (18/3/2010): changed from MVar to STM. This fixes--- 1. there was no async exception protection--- 2. there was a space leak (now new value is strict)--- 3. using atomicModifyIORef would be slightly quicker, but can--- suffer from adverse scheduling issues (see #3838)--- 4. also, the STM version is faster.---- | Hashes a 'Unique' into an 'Int'. Two 'Unique's may hash to the--- same value, although in practice this is unlikely. The 'Int'--- returned makes a good hash key.-hashUnique :: Unique -> Int-#if defined(__GLASGOW_HASKELL__)-hashUnique (Unique i) = I# (hashInteger i)-#else-hashUnique (Unique u) = fromInteger (u `mod` (toInteger (maxBound :: Int) + 1))-#endif
@@ -1,147 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, DeriveDataTypeable #-}---------------------------------------------------------------------------------- |--- Module : Data.Version--- Copyright : (c) The University of Glasgow 2004--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable (local universal quantification in ReadP)------ A general library for representation and manipulation of versions.--- --- Versioning schemes are many and varied, so the version--- representation provided by this library is intended to be a--- compromise between complete generality, where almost no common--- functionality could reasonably be provided, and fixing a particular--- versioning scheme, which would probably be too restrictive.--- --- So the approach taken here is to provide a representation which--- subsumes many of the versioning schemes commonly in use, and we--- provide implementations of 'Eq', 'Ord' and conversion to\/from 'String'--- which will be appropriate for some applications, but not all.-----------------------------------------------------------------------------------module Data.Version (- -- * The @Version@ type- Version(..),- -- * A concrete representation of @Version@- showVersion, parseVersion,- ) where--import Prelude -- necessary to get dependencies right---- These #ifdefs are necessary because this code might be compiled as--- part of ghc/lib/compat, and hence might be compiled by an older version--- of GHC. In which case, we might need to pick up ReadP from --- Distribution.Compat.ReadP, because the version in --- Text.ParserCombinators.ReadP doesn't have all the combinators we need.-#if __GLASGOW_HASKELL__ || __HUGS__ || __NHC__-import Text.ParserCombinators.ReadP-#else-import Distribution.Compat.ReadP-#endif--#if !__GLASGOW_HASKELL__-import Data.Typeable ( Typeable, TyCon, mkTyCon, mkTyConApp )-#else-import Data.Typeable ( Typeable )-#endif--import Data.List ( intersperse, sort )-import Control.Monad ( liftM )-import Data.Char ( isDigit, isAlphaNum )--{- |-A 'Version' represents the version of a software entity. --An instance of 'Eq' is provided, which implements exact equality-modulo reordering of the tags in the 'versionTags' field.--An instance of 'Ord' is also provided, which gives lexicographic-ordering on the 'versionBranch' fields (i.e. 2.1 > 2.0, 1.2.3 > 1.2.2,-etc.). This is expected to be sufficient for many uses, but note that-you may need to use a more specific ordering for your versioning-scheme. For example, some versioning schemes may include pre-releases-which have tags @\"pre1\"@, @\"pre2\"@, and so on, and these would need to-be taken into account when determining ordering. In some cases, date-ordering may be more appropriate, so the application would have to-look for @date@ tags in the 'versionTags' field and compare those.-The bottom line is, don't always assume that 'compare' and other 'Ord'-operations are the right thing for every 'Version'.--Similarly, concrete representations of versions may differ. One-possible concrete representation is provided (see 'showVersion' and-'parseVersion'), but depending on the application a different concrete-representation may be more appropriate.--}-data Version = - Version { versionBranch :: [Int],- -- ^ The numeric branch for this version. This reflects the- -- fact that most software versions are tree-structured; there- -- is a main trunk which is tagged with versions at various- -- points (1,2,3...), and the first branch off the trunk after- -- version 3 is 3.1, the second branch off the trunk after- -- version 3 is 3.2, and so on. The tree can be branched- -- arbitrarily, just by adding more digits.- -- - -- We represent the branch as a list of 'Int', so- -- version 3.2.1 becomes [3,2,1]. Lexicographic ordering- -- (i.e. the default instance of 'Ord' for @[Int]@) gives- -- the natural ordering of branches.-- versionTags :: [String] -- really a bag- -- ^ A version can be tagged with an arbitrary list of strings.- -- The interpretation of the list of tags is entirely dependent- -- on the entity that this version applies to.- }- deriving (Read,Show-#if __GLASGOW_HASKELL__- ,Typeable-#endif- )--#if !__GLASGOW_HASKELL__-versionTc :: TyCon-versionTc = mkTyCon "Version"--instance Typeable Version where- typeOf _ = mkTyConApp versionTc []-#endif--instance Eq Version where- v1 == v2 = versionBranch v1 == versionBranch v2 - && sort (versionTags v1) == sort (versionTags v2)- -- tags may be in any order--instance Ord Version where- v1 `compare` v2 = versionBranch v1 `compare` versionBranch v2---- -------------------------------------------------------------------------------- A concrete representation of 'Version'---- | Provides one possible concrete representation for 'Version'. For--- a version with 'versionBranch' @= [1,2,3]@ and 'versionTags' --- @= [\"tag1\",\"tag2\"]@, the output will be @1.2.3-tag1-tag2@.----showVersion :: Version -> String-showVersion (Version branch tags)- = concat (intersperse "." (map show branch)) ++ - concatMap ('-':) tags---- | A parser for versions in the format produced by 'showVersion'.----#if __GLASGOW_HASKELL__ || __HUGS__-parseVersion :: ReadP Version-#elif __NHC__-parseVersion :: ReadPN r Version-#else-parseVersion :: ReadP r Version-#endif-parseVersion = do branch <- sepBy1 (liftM read $ munch1 isDigit) (char '.')- tags <- many (char '-' >> munch1 isAlphaNum)- return Version{versionBranch=branch, versionTags=tags}
@@ -1,71 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Data.Word--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Unsigned integer types.-----------------------------------------------------------------------------------module Data.Word- (- -- * Unsigned integral types-- Word,- Word8, Word16, Word32, Word64,-- -- * Notes-- -- $notes- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Word-#endif--#ifdef __HUGS__-import Hugs.Word-#endif--#ifdef __NHC__-import NHC.FFI (Word8, Word16, Word32, Word64)-import NHC.SizedTypes (Word8, Word16, Word32, Word64) -- instances of Bits-type Word = Word32-#endif--{- $notes--* All arithmetic is performed modulo 2^n, where n is the number of- bits in the type. One non-obvious consequence of this is that 'Prelude.negate'- should /not/ raise an error on negative arguments.--* For coercing between any two integer types, use- 'Prelude.fromIntegral', which is specialized for all the- common cases so should be fast enough. Coercing word types to and- from integer types preserves representation, not sign.--* It would be very natural to add a type @Natural@ providing an unbounded - size unsigned integer, just as 'Prelude.Integer' provides unbounded- size signed integers. We do not do that yet since there is no demand- for it.--* The rules that hold for 'Prelude.Enum' instances over a bounded type- such as 'Prelude.Int' (see the section of the Haskell report dealing- with arithmetic sequences) also hold for the 'Prelude.Enum' instances- over the various 'Word' types defined here.--* Right and left shifts by amounts greater than or equal to the width- of the type result in a zero result. This is contrary to the- behaviour in C, which is undefined; a common interpretation is to- truncate the shift count to the width of the type, for example @1 \<\<- 32 == 1@ in some C implementations. --}-
@@ -1,181 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, ForeignFunctionInterface, MagicHash, UnboxedTuples #-}---------------------------------------------------------------------------------- |--- Module : Debug.Trace--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Functions for tracing and monitoring execution.------ These can be useful for investigating bugs or performance problems.--- They should /not/ be used in production code.-----------------------------------------------------------------------------------module Debug.Trace (- -- * Tracing- -- $tracing- trace, -- :: String -> a -> a- traceShow,- traceStack,- traceIO, -- :: String -> IO ()- putTraceMsg,-- -- * Eventlog tracing- -- $eventlog_tracing- traceEvent,- traceEventIO,- ) where--import Prelude-import System.IO.Unsafe-import Control.Monad--#ifdef __GLASGOW_HASKELL__-import Foreign.C.String-import GHC.Base-import qualified GHC.Foreign-import GHC.IO.Encoding-import GHC.Ptr-import GHC.Stack-#else-import System.IO (hPutStrLn,stderr)-#endif---- $tracing------ The 'trace', 'traceShow' and 'traceIO' functions print messages to an output--- stream. They are intended for \"printf debugging\", that is: tracing the flow--- of execution and printing interesting values.---- The usual output stream is 'System.IO.stderr'. For Windows GUI applications--- (that have no stderr) the output is directed to the Windows debug console.--- Some implementations of these functions may decorate the string that\'s--- output to indicate that you\'re tracing.---- | The 'traceIO' function outputs the trace message from the IO monad.--- This sequences the output with respect to other IO actions.----traceIO :: String -> IO ()-traceIO msg = do-#ifndef __GLASGOW_HASKELL__- hPutStrLn stderr msg-#else- withCString "%s\n" $ \cfmt ->- withCString msg $ \cmsg ->- debugBelch cfmt cmsg---- don't use debugBelch() directly, because we cannot call varargs functions--- using the FFI.-foreign import ccall unsafe "HsBase.h debugBelch2"- debugBelch :: CString -> CString -> IO ()-#endif----- | Deprecated. Use 'traceIO'.-putTraceMsg :: String -> IO ()-putTraceMsg = traceIO-{-# DEPRECATED putTraceMsg "Use Debug.Trace.traceIO" #-}---{-# NOINLINE trace #-}-{-|-The 'trace' function outputs the trace message given as its first argument,-before returning the second argument as its result.--For example, this returns the value of @f x@ but first outputs the message.--> trace ("calling f with x = " ++ show x) (f x)--The 'trace' function should /only/ be used for debugging, or for monitoring-execution. The function is not referentially transparent: its type indicates-that it is a pure function but it has the side effect of outputting the-trace message.--}-trace :: String -> a -> a-trace string expr = unsafePerformIO $ do- traceIO string- return expr--{-|-Like 'trace', but uses 'show' on the argument to convert it to a 'String'.--This makes it convenient for printing the values of interesting variables or-expressions inside a function. For example here we print the value of the-variables @x@ and @z@:--> f x y =-> traceShow (x, z) $ result-> where-> z = ...-> ...--}-traceShow :: (Show a) => a -> b -> b-traceShow = trace . show----- $eventlog_tracing------ Eventlog tracing is a performance profiling system. These functions emit--- extra events into the eventlog. In combination with eventlog profiling--- tools these functions can be used for monitoring execution and--- investigating performance problems.------ Currently only GHC provides eventlog profiling, see the GHC user guide for--- details on how to use it. These function exists for other Haskell--- implementations but no events are emitted. Note that the string message is--- always evaluated, whether or not profiling is available or enabled.--{-# NOINLINE traceEvent #-}--- | The 'traceEvent' function behaves like 'trace' with the difference that--- the message is emitted to the eventlog, if eventlog profiling is available--- and enabled at runtime.------ It is suitable for use in pure code. In an IO context use 'traceEventIO'--- instead.------ Note that when using GHC's SMP runtime, it is possible (but rare) to get--- duplicate events emitted if two CPUs simultaneously evaluate the same thunk--- that uses 'traceEvent'.----traceEvent :: String -> a -> a-traceEvent msg expr = unsafeDupablePerformIO $ do- traceEventIO msg- return expr---- | The 'traceEventIO' function emits a message to the eventlog, if eventlog--- profiling is available and enabled at runtime.------ Compared to 'traceEvent', 'traceEventIO' sequences the event with respect to--- other IO actions.----traceEventIO :: String -> IO ()-#ifdef __GLASGOW_HASKELL__-traceEventIO msg =- GHC.Foreign.withCString utf8 msg $ \(Ptr p) -> IO $ \s ->- case traceEvent# p s of s' -> (# s', () #)-#else-traceEventIO msg = (return $! length msg) >> return ()-#endif---- | like 'trace', but additionally prints a call stack if one is--- available.------ In the current GHC implementation, the call stack is only--- available if the program was compiled with @-prof@; otherwise--- 'traceStack' behaves exactly like 'trace'. Entries in the call--- stack correspond to @SCC@ annotations, so it is a good idea to use--- @-fprof-auto@ or @-fprof-auto-calls@ to add SCC annotations automatically.----traceStack :: String -> a -> a-traceStack str expr = unsafePerformIO $ do- traceIO str- stack <- currentCallStack- when (not (null stack)) $ traceIO (renderStack stack)- return expr
@@ -1,55 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ A collection of data types, classes, and functions for interfacing--- with another programming language.-----------------------------------------------------------------------------------module Foreign- ( module Data.Bits- , module Data.Int- , module Data.Word- , module Foreign.Ptr- , module Foreign.ForeignPtr- , module Foreign.StablePtr- , module Foreign.Storable- , module Foreign.Marshal-- -- * Unsafe Functions-- -- | 'unsafePerformIO' is exported here for backwards- -- compatibility reasons only. For doing local marshalling in- -- the FFI, use 'unsafeLocalState'. For other uses, see- -- 'System.IO.Unsafe.unsafePerformIO'.- , unsafePerformIO- ) where--import Data.Bits-import Data.Int-import Data.Word-import Foreign.Ptr-import Foreign.ForeignPtr-import Foreign.StablePtr-import Foreign.Storable-import Foreign.Marshal--import GHC.IO (IO)-import qualified GHC.IO (unsafePerformIO)--{-# DEPRECATED unsafePerformIO "Use System.IO.Unsafe.unsafePerformIO instead; This function will be removed in the next release" #-}--{-# INLINE unsafePerformIO #-}-unsafePerformIO :: IO a -> a-unsafePerformIO = GHC.IO.unsafePerformIO-
@@ -1,27 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.C--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Bundles the C specific FFI library functionality-----------------------------------------------------------------------------------module Foreign.C- ( module Foreign.C.Types- , module Foreign.C.String- , module Foreign.C.Error- ) where--import Foreign.C.Types-import Foreign.C.String-import Foreign.C.Error-
@@ -1,619 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ForeignFunctionInterface #-}-{-# OPTIONS_GHC -#include "HsBase.h" #-}---------------------------------------------------------------------------------- |--- Module : Foreign.C.Error--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ C-specific Marshalling support: Handling of C \"errno\" error codes.-----------------------------------------------------------------------------------module Foreign.C.Error (-- -- * Haskell representations of @errno@ values-- Errno(..), -- instance: Eq-- -- ** Common @errno@ symbols- -- | Different operating systems and\/or C libraries often support- -- different values of @errno@. This module defines the common values,- -- but due to the open definition of 'Errno' users may add definitions- -- which are not predefined.- eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, - eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, - eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, - eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, - eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, - eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, - eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, - eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, - eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, - eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, - ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, - eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, - eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, - eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,-- -- ** 'Errno' functions- -- :: Errno- isValidErrno, -- :: Errno -> Bool-- -- access to the current thread's "errno" value- --- getErrno, -- :: IO Errno- resetErrno, -- :: IO ()-- -- conversion of an "errno" value into IO error- --- errnoToIOError, -- :: String -- location- -- -> Errno -- errno- -- -> Maybe Handle -- handle- -- -> Maybe String -- filename- -- -> IOError-- -- throw current "errno" value- --- throwErrno, -- :: String -> IO a-- -- ** Guards for IO operations that may fail-- throwErrnoIf, -- :: (a -> Bool) -> String -> IO a -> IO a- throwErrnoIf_, -- :: (a -> Bool) -> String -> IO a -> IO ()- throwErrnoIfRetry, -- :: (a -> Bool) -> String -> IO a -> IO a- throwErrnoIfRetry_, -- :: (a -> Bool) -> String -> IO a -> IO ()- throwErrnoIfMinus1, -- :: Num a - -- => String -> IO a -> IO a- throwErrnoIfMinus1_, -- :: Num a - -- => String -> IO a -> IO ()- throwErrnoIfMinus1Retry,- -- :: Num a - -- => String -> IO a -> IO a- throwErrnoIfMinus1Retry_, - -- :: Num a - -- => String -> IO a -> IO ()- throwErrnoIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)- throwErrnoIfNullRetry,-- :: String -> IO (Ptr a) -> IO (Ptr a)-- throwErrnoIfRetryMayBlock, - throwErrnoIfRetryMayBlock_,- throwErrnoIfMinus1RetryMayBlock,- throwErrnoIfMinus1RetryMayBlock_, - throwErrnoIfNullRetryMayBlock,-- throwErrnoPath,- throwErrnoPathIf,- throwErrnoPathIf_,- throwErrnoPathIfNull,- throwErrnoPathIfMinus1,- throwErrnoPathIfMinus1_,-) where----- this is were we get the CONST_XXX definitions from that configure--- calculated for us----#ifndef __NHC__-#include "HsBaseConfig.h"-#endif--import Foreign.Ptr-import Foreign.C.Types-import Foreign.C.String-import Foreign.Marshal.Error ( void )-import Data.Maybe--#if __GLASGOW_HASKELL__-import GHC.IO-import GHC.IO.Exception-import GHC.IO.Handle.Types-import GHC.Num-import GHC.Base-#elif __HUGS__-import Hugs.Prelude ( Handle, IOError, ioError )-import System.IO.Unsafe ( unsafePerformIO )-#else-import System.IO ( Handle )-import System.IO.Error ( IOError, ioError )-import System.IO.Unsafe ( unsafePerformIO )-import Foreign.Storable ( Storable(poke,peek) )-#endif--#ifdef __HUGS__-{-# CFILES cbits/PrelIOUtils.c #-}-#endif----- "errno" type--- ---------------- | Haskell representation for @errno@ values.--- The implementation is deliberately exposed, to allow users to add--- their own definitions of 'Errno' values.--newtype Errno = Errno CInt--instance Eq Errno where- errno1@(Errno no1) == errno2@(Errno no2) - | isValidErrno errno1 && isValidErrno errno2 = no1 == no2- | otherwise = False---- common "errno" symbols----eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN, - eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED, - eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT, - eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ, - eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK, - eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH, - eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK, - eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS, - eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO, - eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL, - ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE, - eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN, - eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT, - eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV :: Errno------ the cCONST_XXX identifiers are cpp symbols whose value is computed by--- configure ----eOK = Errno 0-#ifdef __NHC__-#include "Errno.hs"-#else-e2BIG = Errno (CONST_E2BIG)-eACCES = Errno (CONST_EACCES)-eADDRINUSE = Errno (CONST_EADDRINUSE)-eADDRNOTAVAIL = Errno (CONST_EADDRNOTAVAIL)-eADV = Errno (CONST_EADV)-eAFNOSUPPORT = Errno (CONST_EAFNOSUPPORT)-eAGAIN = Errno (CONST_EAGAIN)-eALREADY = Errno (CONST_EALREADY)-eBADF = Errno (CONST_EBADF)-eBADMSG = Errno (CONST_EBADMSG)-eBADRPC = Errno (CONST_EBADRPC)-eBUSY = Errno (CONST_EBUSY)-eCHILD = Errno (CONST_ECHILD)-eCOMM = Errno (CONST_ECOMM)-eCONNABORTED = Errno (CONST_ECONNABORTED)-eCONNREFUSED = Errno (CONST_ECONNREFUSED)-eCONNRESET = Errno (CONST_ECONNRESET)-eDEADLK = Errno (CONST_EDEADLK)-eDESTADDRREQ = Errno (CONST_EDESTADDRREQ)-eDIRTY = Errno (CONST_EDIRTY)-eDOM = Errno (CONST_EDOM)-eDQUOT = Errno (CONST_EDQUOT)-eEXIST = Errno (CONST_EEXIST)-eFAULT = Errno (CONST_EFAULT)-eFBIG = Errno (CONST_EFBIG)-eFTYPE = Errno (CONST_EFTYPE)-eHOSTDOWN = Errno (CONST_EHOSTDOWN)-eHOSTUNREACH = Errno (CONST_EHOSTUNREACH)-eIDRM = Errno (CONST_EIDRM)-eILSEQ = Errno (CONST_EILSEQ)-eINPROGRESS = Errno (CONST_EINPROGRESS)-eINTR = Errno (CONST_EINTR)-eINVAL = Errno (CONST_EINVAL)-eIO = Errno (CONST_EIO)-eISCONN = Errno (CONST_EISCONN)-eISDIR = Errno (CONST_EISDIR)-eLOOP = Errno (CONST_ELOOP)-eMFILE = Errno (CONST_EMFILE)-eMLINK = Errno (CONST_EMLINK)-eMSGSIZE = Errno (CONST_EMSGSIZE)-eMULTIHOP = Errno (CONST_EMULTIHOP)-eNAMETOOLONG = Errno (CONST_ENAMETOOLONG)-eNETDOWN = Errno (CONST_ENETDOWN)-eNETRESET = Errno (CONST_ENETRESET)-eNETUNREACH = Errno (CONST_ENETUNREACH)-eNFILE = Errno (CONST_ENFILE)-eNOBUFS = Errno (CONST_ENOBUFS)-eNODATA = Errno (CONST_ENODATA)-eNODEV = Errno (CONST_ENODEV)-eNOENT = Errno (CONST_ENOENT)-eNOEXEC = Errno (CONST_ENOEXEC)-eNOLCK = Errno (CONST_ENOLCK)-eNOLINK = Errno (CONST_ENOLINK)-eNOMEM = Errno (CONST_ENOMEM)-eNOMSG = Errno (CONST_ENOMSG)-eNONET = Errno (CONST_ENONET)-eNOPROTOOPT = Errno (CONST_ENOPROTOOPT)-eNOSPC = Errno (CONST_ENOSPC)-eNOSR = Errno (CONST_ENOSR)-eNOSTR = Errno (CONST_ENOSTR)-eNOSYS = Errno (CONST_ENOSYS)-eNOTBLK = Errno (CONST_ENOTBLK)-eNOTCONN = Errno (CONST_ENOTCONN)-eNOTDIR = Errno (CONST_ENOTDIR)-eNOTEMPTY = Errno (CONST_ENOTEMPTY)-eNOTSOCK = Errno (CONST_ENOTSOCK)-eNOTTY = Errno (CONST_ENOTTY)-eNXIO = Errno (CONST_ENXIO)-eOPNOTSUPP = Errno (CONST_EOPNOTSUPP)-ePERM = Errno (CONST_EPERM)-ePFNOSUPPORT = Errno (CONST_EPFNOSUPPORT)-ePIPE = Errno (CONST_EPIPE)-ePROCLIM = Errno (CONST_EPROCLIM)-ePROCUNAVAIL = Errno (CONST_EPROCUNAVAIL)-ePROGMISMATCH = Errno (CONST_EPROGMISMATCH)-ePROGUNAVAIL = Errno (CONST_EPROGUNAVAIL)-ePROTO = Errno (CONST_EPROTO)-ePROTONOSUPPORT = Errno (CONST_EPROTONOSUPPORT)-ePROTOTYPE = Errno (CONST_EPROTOTYPE)-eRANGE = Errno (CONST_ERANGE)-eREMCHG = Errno (CONST_EREMCHG)-eREMOTE = Errno (CONST_EREMOTE)-eROFS = Errno (CONST_EROFS)-eRPCMISMATCH = Errno (CONST_ERPCMISMATCH)-eRREMOTE = Errno (CONST_ERREMOTE)-eSHUTDOWN = Errno (CONST_ESHUTDOWN)-eSOCKTNOSUPPORT = Errno (CONST_ESOCKTNOSUPPORT)-eSPIPE = Errno (CONST_ESPIPE)-eSRCH = Errno (CONST_ESRCH)-eSRMNT = Errno (CONST_ESRMNT)-eSTALE = Errno (CONST_ESTALE)-eTIME = Errno (CONST_ETIME)-eTIMEDOUT = Errno (CONST_ETIMEDOUT)-eTOOMANYREFS = Errno (CONST_ETOOMANYREFS)-eTXTBSY = Errno (CONST_ETXTBSY)-eUSERS = Errno (CONST_EUSERS)-eWOULDBLOCK = Errno (CONST_EWOULDBLOCK)-eXDEV = Errno (CONST_EXDEV)-#endif---- | Yield 'True' if the given 'Errno' value is valid on the system.--- This implies that the 'Eq' instance of 'Errno' is also system dependent--- as it is only defined for valid values of 'Errno'.----isValidErrno :: Errno -> Bool------ the configure script sets all invalid "errno"s to -1----isValidErrno (Errno errno) = errno /= -1----- access to the current thread's "errno" value--- ------------------------------------------------ | Get the current value of @errno@ in the current thread.----getErrno :: IO Errno---- We must call a C function to get the value of errno in general. On--- threaded systems, errno is hidden behind a C macro so that each OS--- thread gets its own copy.-#ifdef __NHC__-getErrno = do e <- peek _errno; return (Errno e)-foreign import ccall unsafe "errno.h &errno" _errno :: Ptr CInt-#else-getErrno = do e <- get_errno; return (Errno e)-foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO CInt-#endif---- | Reset the current thread\'s @errno@ value to 'eOK'.----resetErrno :: IO ()---- Again, setting errno has to be done via a C function.-#ifdef __NHC__-resetErrno = poke _errno 0-#else-resetErrno = set_errno 0-foreign import ccall unsafe "HsBase.h __hscore_set_errno" set_errno :: CInt -> IO ()-#endif---- throw current "errno" value--- ------------------------------- | Throw an 'IOError' corresponding to the current value of 'getErrno'.----throwErrno :: String -- ^ textual description of the error location- -> IO a-throwErrno loc =- do- errno <- getErrno- ioError (errnoToIOError loc errno Nothing Nothing)----- guards for IO operations that may fail--- ------------------------------------------ | Throw an 'IOError' corresponding to the current value of 'getErrno'--- if the result value of the 'IO' action meets the given predicate.----throwErrnoIf :: (a -> Bool) -- ^ predicate to apply to the result value- -- of the 'IO' operation- -> String -- ^ textual description of the location- -> IO a -- ^ the 'IO' operation to be executed- -> IO a-throwErrnoIf pred loc f = - do- res <- f- if pred res then throwErrno loc else return res---- | as 'throwErrnoIf', but discards the result of the 'IO' action after--- error handling.----throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO ()-throwErrnoIf_ pred loc f = void $ throwErrnoIf pred loc f---- | as 'throwErrnoIf', but retry the 'IO' action when it yields the--- error code 'eINTR' - this amounts to the standard retry loop for--- interrupted POSIX system calls.----throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a-throwErrnoIfRetry pred loc f = - do- res <- f- if pred res- then do- err <- getErrno- if err == eINTR- then throwErrnoIfRetry pred loc f- else throwErrno loc- else return res---- | as 'throwErrnoIfRetry', but additionally if the operation --- yields the error code 'eAGAIN' or 'eWOULDBLOCK', an alternative--- action is executed before retrying.----throwErrnoIfRetryMayBlock- :: (a -> Bool) -- ^ predicate to apply to the result value- -- of the 'IO' operation- -> String -- ^ textual description of the location- -> IO a -- ^ the 'IO' operation to be executed- -> IO b -- ^ action to execute before retrying if- -- an immediate retry would block- -> IO a-throwErrnoIfRetryMayBlock pred loc f on_block = - do- res <- f- if pred res- then do- err <- getErrno- if err == eINTR- then throwErrnoIfRetryMayBlock pred loc f on_block- else if err == eWOULDBLOCK || err == eAGAIN- then do _ <- on_block- throwErrnoIfRetryMayBlock pred loc f on_block- else throwErrno loc- else return res---- | as 'throwErrnoIfRetry', but discards the result.----throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()-throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f---- | as 'throwErrnoIfRetryMayBlock', but discards the result.----throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()-throwErrnoIfRetryMayBlock_ pred loc f on_block - = void $ throwErrnoIfRetryMayBlock pred loc f on_block---- | Throw an 'IOError' corresponding to the current value of 'getErrno'--- if the 'IO' action returns a result of @-1@.----throwErrnoIfMinus1 :: (Eq a, Num a) => String -> IO a -> IO a-throwErrnoIfMinus1 = throwErrnoIf (== -1)---- | as 'throwErrnoIfMinus1', but discards the result.----throwErrnoIfMinus1_ :: (Eq a, Num a) => String -> IO a -> IO ()-throwErrnoIfMinus1_ = throwErrnoIf_ (== -1)---- | Throw an 'IOError' corresponding to the current value of 'getErrno'--- if the 'IO' action returns a result of @-1@, but retries in case of--- an interrupted operation.----throwErrnoIfMinus1Retry :: (Eq a, Num a) => String -> IO a -> IO a-throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1)---- | as 'throwErrnoIfMinus1', but discards the result.----throwErrnoIfMinus1Retry_ :: (Eq a, Num a) => String -> IO a -> IO ()-throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1)---- | as 'throwErrnoIfMinus1Retry', but checks for operations that would block.----throwErrnoIfMinus1RetryMayBlock :: (Eq a, Num a)- => String -> IO a -> IO b -> IO a-throwErrnoIfMinus1RetryMayBlock = throwErrnoIfRetryMayBlock (== -1)---- | as 'throwErrnoIfMinus1RetryMayBlock', but discards the result.----throwErrnoIfMinus1RetryMayBlock_ :: (Eq a, Num a)- => String -> IO a -> IO b -> IO ()-throwErrnoIfMinus1RetryMayBlock_ = throwErrnoIfRetryMayBlock_ (== -1)---- | Throw an 'IOError' corresponding to the current value of 'getErrno'--- if the 'IO' action returns 'nullPtr'.----throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)-throwErrnoIfNull = throwErrnoIf (== nullPtr)---- | Throw an 'IOError' corresponding to the current value of 'getErrno'--- if the 'IO' action returns 'nullPtr',--- but retry in case of an interrupted operation.----throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)-throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr)---- | as 'throwErrnoIfNullRetry', but checks for operations that would block.----throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)-throwErrnoIfNullRetryMayBlock = throwErrnoIfRetryMayBlock (== nullPtr)---- | as 'throwErrno', but exceptions include the given path when appropriate.----throwErrnoPath :: String -> FilePath -> IO a-throwErrnoPath loc path =- do- errno <- getErrno- ioError (errnoToIOError loc errno Nothing (Just path))---- | as 'throwErrnoIf', but exceptions include the given path when--- appropriate.----throwErrnoPathIf :: (a -> Bool) -> String -> FilePath -> IO a -> IO a-throwErrnoPathIf pred loc path f =- do- res <- f- if pred res then throwErrnoPath loc path else return res---- | as 'throwErrnoIf_', but exceptions include the given path when--- appropriate.----throwErrnoPathIf_ :: (a -> Bool) -> String -> FilePath -> IO a -> IO ()-throwErrnoPathIf_ pred loc path f = void $ throwErrnoPathIf pred loc path f---- | as 'throwErrnoIfNull', but exceptions include the given path when--- appropriate.----throwErrnoPathIfNull :: String -> FilePath -> IO (Ptr a) -> IO (Ptr a)-throwErrnoPathIfNull = throwErrnoPathIf (== nullPtr)---- | as 'throwErrnoIfMinus1', but exceptions include the given path when--- appropriate.----throwErrnoPathIfMinus1 :: (Eq a, Num a) => String -> FilePath -> IO a -> IO a-throwErrnoPathIfMinus1 = throwErrnoPathIf (== -1)---- | as 'throwErrnoIfMinus1_', but exceptions include the given path when--- appropriate.----throwErrnoPathIfMinus1_ :: (Eq a, Num a) => String -> FilePath -> IO a -> IO ()-throwErrnoPathIfMinus1_ = throwErrnoPathIf_ (== -1)---- conversion of an "errno" value into IO error--- ------------------------------------------------ | Construct an 'IOError' based on the given 'Errno' value.--- The optional information can be used to improve the accuracy of--- error messages.----errnoToIOError :: String -- ^ the location where the error occurred- -> Errno -- ^ the error number- -> Maybe Handle -- ^ optional handle associated with the error- -> Maybe String -- ^ optional filename associated with the error- -> IOError-errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do- str <- strerror errno >>= peekCString-#if __GLASGOW_HASKELL__- return (IOError maybeHdl errType loc str (Just errno') maybeName)- where- Errno errno' = errno- errType- | errno == eOK = OtherError- | errno == e2BIG = ResourceExhausted- | errno == eACCES = PermissionDenied- | errno == eADDRINUSE = ResourceBusy- | errno == eADDRNOTAVAIL = UnsupportedOperation- | errno == eADV = OtherError- | errno == eAFNOSUPPORT = UnsupportedOperation- | errno == eAGAIN = ResourceExhausted- | errno == eALREADY = AlreadyExists- | errno == eBADF = InvalidArgument- | errno == eBADMSG = InappropriateType- | errno == eBADRPC = OtherError- | errno == eBUSY = ResourceBusy- | errno == eCHILD = NoSuchThing- | errno == eCOMM = ResourceVanished- | errno == eCONNABORTED = OtherError- | errno == eCONNREFUSED = NoSuchThing- | errno == eCONNRESET = ResourceVanished- | errno == eDEADLK = ResourceBusy- | errno == eDESTADDRREQ = InvalidArgument- | errno == eDIRTY = UnsatisfiedConstraints- | errno == eDOM = InvalidArgument- | errno == eDQUOT = PermissionDenied- | errno == eEXIST = AlreadyExists- | errno == eFAULT = OtherError- | errno == eFBIG = PermissionDenied- | errno == eFTYPE = InappropriateType- | errno == eHOSTDOWN = NoSuchThing- | errno == eHOSTUNREACH = NoSuchThing- | errno == eIDRM = ResourceVanished- | errno == eILSEQ = InvalidArgument- | errno == eINPROGRESS = AlreadyExists- | errno == eINTR = Interrupted- | errno == eINVAL = InvalidArgument- | errno == eIO = HardwareFault- | errno == eISCONN = AlreadyExists- | errno == eISDIR = InappropriateType- | errno == eLOOP = InvalidArgument- | errno == eMFILE = ResourceExhausted- | errno == eMLINK = ResourceExhausted- | errno == eMSGSIZE = ResourceExhausted- | errno == eMULTIHOP = UnsupportedOperation- | errno == eNAMETOOLONG = InvalidArgument- | errno == eNETDOWN = ResourceVanished- | errno == eNETRESET = ResourceVanished- | errno == eNETUNREACH = NoSuchThing- | errno == eNFILE = ResourceExhausted- | errno == eNOBUFS = ResourceExhausted- | errno == eNODATA = NoSuchThing- | errno == eNODEV = UnsupportedOperation- | errno == eNOENT = NoSuchThing- | errno == eNOEXEC = InvalidArgument- | errno == eNOLCK = ResourceExhausted- | errno == eNOLINK = ResourceVanished- | errno == eNOMEM = ResourceExhausted- | errno == eNOMSG = NoSuchThing- | errno == eNONET = NoSuchThing- | errno == eNOPROTOOPT = UnsupportedOperation- | errno == eNOSPC = ResourceExhausted- | errno == eNOSR = ResourceExhausted- | errno == eNOSTR = InvalidArgument- | errno == eNOSYS = UnsupportedOperation- | errno == eNOTBLK = InvalidArgument- | errno == eNOTCONN = InvalidArgument- | errno == eNOTDIR = InappropriateType- | errno == eNOTEMPTY = UnsatisfiedConstraints- | errno == eNOTSOCK = InvalidArgument- | errno == eNOTTY = IllegalOperation- | errno == eNXIO = NoSuchThing- | errno == eOPNOTSUPP = UnsupportedOperation- | errno == ePERM = PermissionDenied- | errno == ePFNOSUPPORT = UnsupportedOperation- | errno == ePIPE = ResourceVanished- | errno == ePROCLIM = PermissionDenied- | errno == ePROCUNAVAIL = UnsupportedOperation- | errno == ePROGMISMATCH = ProtocolError- | errno == ePROGUNAVAIL = UnsupportedOperation- | errno == ePROTO = ProtocolError- | errno == ePROTONOSUPPORT = ProtocolError- | errno == ePROTOTYPE = ProtocolError- | errno == eRANGE = UnsupportedOperation- | errno == eREMCHG = ResourceVanished- | errno == eREMOTE = IllegalOperation- | errno == eROFS = PermissionDenied- | errno == eRPCMISMATCH = ProtocolError- | errno == eRREMOTE = IllegalOperation- | errno == eSHUTDOWN = IllegalOperation- | errno == eSOCKTNOSUPPORT = UnsupportedOperation- | errno == eSPIPE = UnsupportedOperation- | errno == eSRCH = NoSuchThing- | errno == eSRMNT = UnsatisfiedConstraints- | errno == eSTALE = ResourceVanished- | errno == eTIME = TimeExpired- | errno == eTIMEDOUT = TimeExpired- | errno == eTOOMANYREFS = ResourceExhausted- | errno == eTXTBSY = ResourceBusy- | errno == eUSERS = ResourceExhausted- | errno == eWOULDBLOCK = OtherError- | errno == eXDEV = UnsupportedOperation- | otherwise = OtherError-#else- return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))-#endif--foreign import ccall unsafe "string.h" strerror :: Errno -> IO (Ptr CChar)-
@@ -1,544 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.C.String--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Utilities for primitive marshalling of C strings.------ The marshalling converts each Haskell character, representing a Unicode--- code point, to one or more bytes in a manner that, by default, is--- determined by the current locale. As a consequence, no guarantees--- can be made about the relative length of a Haskell string and its--- corresponding C string, and therefore all the marshalling routines--- include memory allocation. The translation between Unicode and the--- encoding of the current locale may be lossy.-----------------------------------------------------------------------------------module Foreign.C.String ( -- representation of strings in C- -- * C strings-- CString, -- = Ptr CChar- CStringLen, -- = (Ptr CChar, Int)-- -- ** Using a locale-dependent encoding--#ifndef __GLASGOW_HASKELL__- -- | Currently these functions are identical to their @CAString@ counterparts;- -- eventually they will use an encoding determined by the current locale.-#else- -- | These functions are different from their @CAString@ counterparts- -- in that they will use an encoding determined by the current locale,- -- rather than always assuming ASCII.-#endif-- -- conversion of C strings into Haskell strings- --- peekCString, -- :: CString -> IO String- peekCStringLen, -- :: CStringLen -> IO String-- -- conversion of Haskell strings into C strings- --- newCString, -- :: String -> IO CString- newCStringLen, -- :: String -> IO CStringLen-- -- conversion of Haskell strings into C strings using temporary storage- --- withCString, -- :: String -> (CString -> IO a) -> IO a- withCStringLen, -- :: String -> (CStringLen -> IO a) -> IO a-- charIsRepresentable, -- :: Char -> IO Bool-- -- ** Using 8-bit characters-- -- | These variants of the above functions are for use with C libraries- -- that are ignorant of Unicode. These functions should be used with- -- care, as a loss of information can occur.-- castCharToCChar, -- :: Char -> CChar- castCCharToChar, -- :: CChar -> Char-- castCharToCUChar, -- :: Char -> CUChar- castCUCharToChar, -- :: CUChar -> Char- castCharToCSChar, -- :: Char -> CSChar- castCSCharToChar, -- :: CSChar -> Char-- peekCAString, -- :: CString -> IO String- peekCAStringLen, -- :: CStringLen -> IO String- newCAString, -- :: String -> IO CString- newCAStringLen, -- :: String -> IO CStringLen- withCAString, -- :: String -> (CString -> IO a) -> IO a- withCAStringLen, -- :: String -> (CStringLen -> IO a) -> IO a-- -- * C wide strings-- -- | These variants of the above functions are for use with C libraries- -- that encode Unicode using the C @wchar_t@ type in a system-dependent- -- way. The only encodings supported are- --- -- * UTF-32 (the C compiler defines @__STDC_ISO_10646__@), or- --- -- * UTF-16 (as used on Windows systems).-- CWString, -- = Ptr CWchar- CWStringLen, -- = (Ptr CWchar, Int)-- peekCWString, -- :: CWString -> IO String- peekCWStringLen, -- :: CWStringLen -> IO String- newCWString, -- :: String -> IO CWString- newCWStringLen, -- :: String -> IO CWStringLen- withCWString, -- :: String -> (CWString -> IO a) -> IO a- withCWStringLen, -- :: String -> (CWStringLen -> IO a) -> IO a-- ) where--import Foreign.Marshal.Array-import Foreign.C.Types-import Foreign.Ptr-import Foreign.Storable--import Data.Word--#ifdef __GLASGOW_HASKELL__-import Control.Monad--import GHC.List-import GHC.Real-import GHC.Num-import GHC.Base--import {-# SOURCE #-} GHC.IO.Encoding-import qualified GHC.Foreign as GHC-#else-import Data.Char ( chr, ord )-#define unsafeChr chr-#endif---------------------------------------------------------------------------------- Strings---- representation of strings in C--- ---------------------------------- | A C string is a reference to an array of C characters terminated by NUL.-type CString = Ptr CChar---- | A string with explicit length information in bytes instead of a--- terminating NUL (allowing NUL characters in the middle of the string).-type CStringLen = (Ptr CChar, Int)---- exported functions--- ------------------------ * the following routines apply the default conversion when converting the--- C-land character encoding into the Haskell-land character encoding---- | Marshal a NUL terminated C string into a Haskell string.----peekCString :: CString -> IO String-#ifndef __GLASGOW_HASKELL__-peekCString = peekCAString-#else-peekCString s = getForeignEncoding >>= flip GHC.peekCString s-#endif---- | Marshal a C string with explicit length into a Haskell string.----peekCStringLen :: CStringLen -> IO String-#ifndef __GLASGOW_HASKELL__-peekCStringLen = peekCAStringLen-#else-peekCStringLen s = getForeignEncoding >>= flip GHC.peekCStringLen s-#endif---- | Marshal a Haskell string into a NUL terminated C string.------ * the Haskell string may /not/ contain any NUL characters------ * new storage is allocated for the C string and must be--- explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCString :: String -> IO CString-#ifndef __GLASGOW_HASKELL__-newCString = newCAString-#else-newCString s = getForeignEncoding >>= flip GHC.newCString s-#endif---- | Marshal a Haskell string into a C string (ie, character array) with--- explicit length information.------ * new storage is allocated for the C string and must be--- explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCStringLen :: String -> IO CStringLen-#ifndef __GLASGOW_HASKELL__-newCStringLen = newCAStringLen-#else-newCStringLen s = getForeignEncoding >>= flip GHC.newCStringLen s-#endif---- | Marshal a Haskell string into a NUL terminated C string using temporary--- storage.------ * the Haskell string may /not/ contain any NUL characters------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCString :: String -> (CString -> IO a) -> IO a-#ifndef __GLASGOW_HASKELL__-withCString = withCAString-#else-withCString s f = getForeignEncoding >>= \enc -> GHC.withCString enc s f-#endif---- | Marshal a Haskell string into a C string (ie, character array)--- in temporary storage, with explicit length information.------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCStringLen :: String -> (CStringLen -> IO a) -> IO a-#ifndef __GLASGOW_HASKELL__-withCStringLen = withCAStringLen-#else-withCStringLen s f = getForeignEncoding >>= \enc -> GHC.withCStringLen enc s f-#endif---#ifndef __GLASGOW_HASKELL__--- | Determines whether a character can be accurately encoded in a 'CString'.--- Unrepresentable characters are converted to @\'?\'@.------ Currently only Latin-1 characters are representable.-charIsRepresentable :: Char -> IO Bool-charIsRepresentable c = return (ord c < 256)-#else--- -- | Determines whether a character can be accurately encoded in a 'CString'.--- -- Unrepresentable characters are converted to '?' or their nearest visual equivalent.-charIsRepresentable :: Char -> IO Bool-charIsRepresentable c = getForeignEncoding >>= flip GHC.charIsRepresentable c-#endif---- single byte characters--- ---------------------------- ** NOTE: These routines don't handle conversions! **---- | Convert a C byte, representing a Latin-1 character, to the corresponding--- Haskell character.-castCCharToChar :: CChar -> Char-castCCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))---- | Convert a Haskell character to a C character.--- This function is only safe on the first 256 characters.-castCharToCChar :: Char -> CChar-castCharToCChar ch = fromIntegral (ord ch)---- | Convert a C @unsigned char@, representing a Latin-1 character, to--- the corresponding Haskell character.-castCUCharToChar :: CUChar -> Char-castCUCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))---- | Convert a Haskell character to a C @unsigned char@.--- This function is only safe on the first 256 characters.-castCharToCUChar :: Char -> CUChar-castCharToCUChar ch = fromIntegral (ord ch)---- | Convert a C @signed char@, representing a Latin-1 character, to the--- corresponding Haskell character.-castCSCharToChar :: CSChar -> Char-castCSCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))---- | Convert a Haskell character to a C @signed char@.--- This function is only safe on the first 256 characters.-castCharToCSChar :: Char -> CSChar-castCharToCSChar ch = fromIntegral (ord ch)---- | Marshal a NUL terminated C string into a Haskell string.----peekCAString :: CString -> IO String-#ifndef __GLASGOW_HASKELL__-peekCAString cp = do- cs <- peekArray0 nUL cp- return (cCharsToChars cs)-#else-peekCAString cp = do- l <- lengthArray0 nUL cp- if l <= 0 then return "" else loop "" (l-1)- where- loop s i = do- xval <- peekElemOff cp i- let val = castCCharToChar xval- val `seq` if i <= 0 then return (val:s) else loop (val:s) (i-1)-#endif---- | Marshal a C string with explicit length into a Haskell string.----peekCAStringLen :: CStringLen -> IO String-#ifndef __GLASGOW_HASKELL__-peekCAStringLen (cp, len) = do- cs <- peekArray len cp- return (cCharsToChars cs)-#else-peekCAStringLen (cp, len) - | len <= 0 = return "" -- being (too?) nice.- | otherwise = loop [] (len-1)- where- loop acc i = do- xval <- peekElemOff cp i- let val = castCCharToChar xval- -- blow away the coercion ASAP.- if (val `seq` (i == 0))- then return (val:acc)- else loop (val:acc) (i-1)-#endif---- | Marshal a Haskell string into a NUL terminated C string.------ * the Haskell string may /not/ contain any NUL characters------ * new storage is allocated for the C string and must be--- explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCAString :: String -> IO CString-#ifndef __GLASGOW_HASKELL__-newCAString = newArray0 nUL . charsToCChars-#else-newCAString str = do- ptr <- mallocArray0 (length str)- let- go [] n = pokeElemOff ptr n nUL- go (c:cs) n = do pokeElemOff ptr n (castCharToCChar c); go cs (n+1)- go str 0- return ptr-#endif---- | Marshal a Haskell string into a C string (ie, character array) with--- explicit length information.------ * new storage is allocated for the C string and must be--- explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCAStringLen :: String -> IO CStringLen-#ifndef __GLASGOW_HASKELL__-newCAStringLen str = newArrayLen (charsToCChars str)-#else-newCAStringLen str = do- ptr <- mallocArray0 len- let- go [] n = n `seq` return () -- make it strict in n- go (c:cs) n = do pokeElemOff ptr n (castCharToCChar c); go cs (n+1)- go str 0- return (ptr, len)- where- len = length str-#endif---- | Marshal a Haskell string into a NUL terminated C string using temporary--- storage.------ * the Haskell string may /not/ contain any NUL characters------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCAString :: String -> (CString -> IO a) -> IO a-#ifndef __GLASGOW_HASKELL__-withCAString = withArray0 nUL . charsToCChars-#else-withCAString str f =- allocaArray0 (length str) $ \ptr ->- let- go [] n = pokeElemOff ptr n nUL- go (c:cs) n = do pokeElemOff ptr n (castCharToCChar c); go cs (n+1)- in do- go str 0- f ptr-#endif---- | Marshal a Haskell string into a C string (ie, character array)--- in temporary storage, with explicit length information.------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCAStringLen :: String -> (CStringLen -> IO a) -> IO a-withCAStringLen str f =-#ifndef __GLASGOW_HASKELL__- withArrayLen (charsToCChars str) $ \ len ptr -> f (ptr, len)-#else- allocaArray len $ \ptr ->- let- go [] n = n `seq` return () -- make it strict in n- go (c:cs) n = do pokeElemOff ptr n (castCharToCChar c); go cs (n+1)- in do- go str 0- f (ptr,len)- where- len = length str-#endif---- auxiliary definitions--- -------------------------- C's end of string character----nUL :: CChar-nUL = 0---- allocate an array to hold the list and pair it with the number of elements-newArrayLen :: Storable a => [a] -> IO (Ptr a, Int)-newArrayLen xs = do- a <- newArray xs- return (a, length xs)--#ifndef __GLASGOW_HASKELL__--- cast [CChar] to [Char]----cCharsToChars :: [CChar] -> [Char]-cCharsToChars xs = map castCCharToChar xs---- cast [Char] to [CChar]----charsToCChars :: [Char] -> [CChar]-charsToCChars xs = map castCharToCChar xs-#endif---------------------------------------------------------------------------------- Wide strings---- representation of wide strings in C--- --------------------------------------- | A C wide string is a reference to an array of C wide characters--- terminated by NUL.-type CWString = Ptr CWchar---- | A wide character string with explicit length information in 'CWchar's--- instead of a terminating NUL (allowing NUL characters in the middle--- of the string).-type CWStringLen = (Ptr CWchar, Int)---- | Marshal a NUL terminated C wide string into a Haskell string.----peekCWString :: CWString -> IO String-peekCWString cp = do- cs <- peekArray0 wNUL cp- return (cWcharsToChars cs)---- | Marshal a C wide string with explicit length into a Haskell string.----peekCWStringLen :: CWStringLen -> IO String-peekCWStringLen (cp, len) = do- cs <- peekArray len cp- return (cWcharsToChars cs)---- | Marshal a Haskell string into a NUL terminated C wide string.------ * the Haskell string may /not/ contain any NUL characters------ * new storage is allocated for the C wide string and must--- be explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCWString :: String -> IO CWString-newCWString = newArray0 wNUL . charsToCWchars---- | Marshal a Haskell string into a C wide string (ie, wide character array)--- with explicit length information.------ * new storage is allocated for the C wide string and must--- be explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCWStringLen :: String -> IO CWStringLen-newCWStringLen str = newArrayLen (charsToCWchars str)---- | Marshal a Haskell string into a NUL terminated C wide string using--- temporary storage.------ * the Haskell string may /not/ contain any NUL characters------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCWString :: String -> (CWString -> IO a) -> IO a-withCWString = withArray0 wNUL . charsToCWchars---- | Marshal a Haskell string into a C wide string (i.e. wide--- character array) in temporary storage, with explicit length--- information.------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCWStringLen :: String -> (CWStringLen -> IO a) -> IO a-withCWStringLen str f =- withArrayLen (charsToCWchars str) $ \ len ptr -> f (ptr, len)---- auxiliary definitions--- ------------------------wNUL :: CWchar-wNUL = 0--cWcharsToChars :: [CWchar] -> [Char]-charsToCWchars :: [Char] -> [CWchar]--#ifdef mingw32_HOST_OS---- On Windows, wchar_t is 16 bits wide and CWString uses the UTF-16 encoding.---- coding errors generate Chars in the surrogate range-cWcharsToChars = map chr . fromUTF16 . map fromIntegral- where- fromUTF16 (c1:c2:wcs)- | 0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff =- ((c1 - 0xd800)*0x400 + (c2 - 0xdc00) + 0x10000) : fromUTF16 wcs- fromUTF16 (c:wcs) = c : fromUTF16 wcs- fromUTF16 [] = []--charsToCWchars = foldr utf16Char [] . map ord- where- utf16Char c wcs- | c < 0x10000 = fromIntegral c : wcs- | otherwise = let c' = c - 0x10000 in- fromIntegral (c' `div` 0x400 + 0xd800) :- fromIntegral (c' `mod` 0x400 + 0xdc00) : wcs--#else /* !mingw32_HOST_OS */--cWcharsToChars xs = map castCWcharToChar xs-charsToCWchars xs = map castCharToCWchar xs---- These conversions only make sense if __STDC_ISO_10646__ is defined--- (meaning that wchar_t is ISO 10646, aka Unicode)--castCWcharToChar :: CWchar -> Char-castCWcharToChar ch = chr (fromIntegral ch )--castCharToCWchar :: Char -> CWchar-castCharToCWchar ch = fromIntegral (ord ch)--#endif /* !mingw32_HOST_OS */-
@@ -1,334 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , MagicHash- , GeneralizedNewtypeDeriving- #-}-{-# OPTIONS_GHC -fno-warn-unused-binds #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif--- XXX -fno-warn-unused-binds stops us warning about unused constructors,--- but really we should just remove them if we don't want them---------------------------------------------------------------------------------- |--- Module : Foreign.C.Types--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Mapping of C types to corresponding Haskell types.-----------------------------------------------------------------------------------module Foreign.C.Types- ( -- * Representations of C types- -- $ctypes-- -- ** Integral types- -- | These types are are represented as @newtype@s of- -- types in "Data.Int" and "Data.Word", and are instances of- -- 'Prelude.Eq', 'Prelude.Ord', 'Prelude.Num', 'Prelude.Read',- -- 'Prelude.Show', 'Prelude.Enum', 'Typeable', 'Storable',- -- 'Prelude.Bounded', 'Prelude.Real', 'Prelude.Integral' and- -- 'Bits'.- CChar(..), CSChar(..), CUChar(..)- , CShort(..), CUShort(..), CInt(..), CUInt(..)- , CLong(..), CULong(..)- , CPtrdiff(..), CSize(..), CWchar(..), CSigAtomic(..)- , CLLong(..), CULLong(..)- , CIntPtr(..), CUIntPtr(..), CIntMax(..), CUIntMax(..)-- -- ** Numeric types- -- | These types are are represented as @newtype@s of basic- -- foreign types, and are instances of- -- 'Prelude.Eq', 'Prelude.Ord', 'Prelude.Num', 'Prelude.Read',- -- 'Prelude.Show', 'Prelude.Enum', 'Typeable' and 'Storable'.- , CClock(..), CTime(..), CUSeconds(..), CSUSeconds(..)-- -- extracted from CTime, because we don't want this comment in- -- the Haskell 2010 report:-- -- | To convert 'CTime' to 'Data.Time.UTCTime', use the following formula:- --- -- > posixSecondsToUTCTime (realToFrac :: POSIXTime)- ---- -- ** Floating types- -- | These types are are represented as @newtype@s of- -- 'Prelude.Float' and 'Prelude.Double', and are instances of- -- 'Prelude.Eq', 'Prelude.Ord', 'Prelude.Num', 'Prelude.Read',- -- 'Prelude.Show', 'Prelude.Enum', 'Typeable', 'Storable',- -- 'Prelude.Real', 'Prelude.Fractional', 'Prelude.Floating',- -- 'Prelude.RealFrac' and 'Prelude.RealFloat'.- , CFloat(..), CDouble(..)--- GHC doesn't support CLDouble yet-#ifndef __GLASGOW_HASKELL__- , CLDouble(..)-#endif- -- ** Other types-- -- Instances of: Eq and Storable- , CFile, CFpos, CJmpBuf- ) where--#ifndef __NHC__--import Foreign.Storable-import Data.Bits ( Bits(..) )-import Data.Int ( Int8, Int16, Int32, Int64 )-import Data.Word ( Word8, Word16, Word32, Word64 )-import {-# SOURCE #-} Data.Typeable- -- loop: Data.Typeable -> Data.List -> Data.Char -> GHC.Unicode- -- -> Foreign.C.Type--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Float-import GHC.Enum-import GHC.Real-import GHC.Show-import GHC.Read-import GHC.Num-#else-import Control.Monad ( liftM )-#endif--#ifdef __HUGS__-import Hugs.Ptr ( castPtr )-#endif--#include "HsBaseConfig.h"-#include "CTypes.h"---- | Haskell type representing the C @char@ type.-INTEGRAL_TYPE(CChar,tyConCChar,"CChar",HTYPE_CHAR)--- | Haskell type representing the C @signed char@ type.-INTEGRAL_TYPE(CSChar,tyConCSChar,"CSChar",HTYPE_SIGNED_CHAR)--- | Haskell type representing the C @unsigned char@ type.-INTEGRAL_TYPE(CUChar,tyConCUChar,"CUChar",HTYPE_UNSIGNED_CHAR)---- | Haskell type representing the C @short@ type.-INTEGRAL_TYPE(CShort,tyConCShort,"CShort",HTYPE_SHORT)--- | Haskell type representing the C @unsigned short@ type.-INTEGRAL_TYPE(CUShort,tyConCUShort,"CUShort",HTYPE_UNSIGNED_SHORT)---- | Haskell type representing the C @int@ type.-INTEGRAL_TYPE(CInt,tyConCInt,"CInt",HTYPE_INT)--- | Haskell type representing the C @unsigned int@ type.-INTEGRAL_TYPE(CUInt,tyConCUInt,"CUInt",HTYPE_UNSIGNED_INT)---- | Haskell type representing the C @long@ type.-INTEGRAL_TYPE(CLong,tyConCLong,"CLong",HTYPE_LONG)--- | Haskell type representing the C @unsigned long@ type.-INTEGRAL_TYPE(CULong,tyConCULong,"CULong",HTYPE_UNSIGNED_LONG)---- | Haskell type representing the C @long long@ type.-INTEGRAL_TYPE(CLLong,tyConCLLong,"CLLong",HTYPE_LONG_LONG)--- | Haskell type representing the C @unsigned long long@ type.-INTEGRAL_TYPE(CULLong,tyConCULLong,"CULLong",HTYPE_UNSIGNED_LONG_LONG)--{-# RULES-"fromIntegral/a->CChar" fromIntegral = \x -> CChar (fromIntegral x)-"fromIntegral/a->CSChar" fromIntegral = \x -> CSChar (fromIntegral x)-"fromIntegral/a->CUChar" fromIntegral = \x -> CUChar (fromIntegral x)-"fromIntegral/a->CShort" fromIntegral = \x -> CShort (fromIntegral x)-"fromIntegral/a->CUShort" fromIntegral = \x -> CUShort (fromIntegral x)-"fromIntegral/a->CInt" fromIntegral = \x -> CInt (fromIntegral x)-"fromIntegral/a->CUInt" fromIntegral = \x -> CUInt (fromIntegral x)-"fromIntegral/a->CLong" fromIntegral = \x -> CLong (fromIntegral x)-"fromIntegral/a->CULong" fromIntegral = \x -> CULong (fromIntegral x)-"fromIntegral/a->CLLong" fromIntegral = \x -> CLLong (fromIntegral x)-"fromIntegral/a->CULLong" fromIntegral = \x -> CULLong (fromIntegral x)--"fromIntegral/CChar->a" fromIntegral = \(CChar x) -> fromIntegral x-"fromIntegral/CSChar->a" fromIntegral = \(CSChar x) -> fromIntegral x-"fromIntegral/CUChar->a" fromIntegral = \(CUChar x) -> fromIntegral x-"fromIntegral/CShort->a" fromIntegral = \(CShort x) -> fromIntegral x-"fromIntegral/CUShort->a" fromIntegral = \(CUShort x) -> fromIntegral x-"fromIntegral/CInt->a" fromIntegral = \(CInt x) -> fromIntegral x-"fromIntegral/CUInt->a" fromIntegral = \(CUInt x) -> fromIntegral x-"fromIntegral/CLong->a" fromIntegral = \(CLong x) -> fromIntegral x-"fromIntegral/CULong->a" fromIntegral = \(CULong x) -> fromIntegral x-"fromIntegral/CLLong->a" fromIntegral = \(CLLong x) -> fromIntegral x-"fromIntegral/CULLong->a" fromIntegral = \(CULLong x) -> fromIntegral x- #-}---- | Haskell type representing the C @float@ type.-FLOATING_TYPE(CFloat,tyConCFloat,"CFloat",HTYPE_FLOAT)--- | Haskell type representing the C @double@ type.-FLOATING_TYPE(CDouble,tyConCDouble,"CDouble",HTYPE_DOUBLE)--- GHC doesn't support CLDouble yet-#ifndef __GLASGOW_HASKELL__--- HACK: Currently no long double in the FFI, so we simply re-use double--- | Haskell type representing the C @long double@ type.-FLOATING_TYPE(CLDouble,tyConCLDouble,"CLDouble",HTYPE_DOUBLE)-#endif--{-# RULES-"realToFrac/a->CFloat" realToFrac = \x -> CFloat (realToFrac x)-"realToFrac/a->CDouble" realToFrac = \x -> CDouble (realToFrac x)--"realToFrac/CFloat->a" realToFrac = \(CFloat x) -> realToFrac x-"realToFrac/CDouble->a" realToFrac = \(CDouble x) -> realToFrac x- #-}---- GHC doesn't support CLDouble yet--- "realToFrac/a->CLDouble" realToFrac = \x -> CLDouble (realToFrac x)--- "realToFrac/CLDouble->a" realToFrac = \(CLDouble x) -> realToFrac x---- | Haskell type representing the C @ptrdiff_t@ type.-INTEGRAL_TYPE(CPtrdiff,tyConCPtrdiff,"CPtrdiff",HTYPE_PTRDIFF_T)--- | Haskell type representing the C @size_t@ type.-INTEGRAL_TYPE(CSize,tyConCSize,"CSize",HTYPE_SIZE_T)--- | Haskell type representing the C @wchar_t@ type.-INTEGRAL_TYPE(CWchar,tyConCWchar,"CWchar",HTYPE_WCHAR_T)--- | Haskell type representing the C @sig_atomic_t@ type.-INTEGRAL_TYPE(CSigAtomic,tyConCSigAtomic,"CSigAtomic",HTYPE_SIG_ATOMIC_T)--{-# RULES-"fromIntegral/a->CPtrdiff" fromIntegral = \x -> CPtrdiff (fromIntegral x)-"fromIntegral/a->CSize" fromIntegral = \x -> CSize (fromIntegral x)-"fromIntegral/a->CWchar" fromIntegral = \x -> CWchar (fromIntegral x)-"fromIntegral/a->CSigAtomic" fromIntegral = \x -> CSigAtomic (fromIntegral x)--"fromIntegral/CPtrdiff->a" fromIntegral = \(CPtrdiff x) -> fromIntegral x-"fromIntegral/CSize->a" fromIntegral = \(CSize x) -> fromIntegral x-"fromIntegral/CWchar->a" fromIntegral = \(CWchar x) -> fromIntegral x-"fromIntegral/CSigAtomic->a" fromIntegral = \(CSigAtomic x) -> fromIntegral x- #-}---- | Haskell type representing the C @clock_t@ type.-ARITHMETIC_TYPE(CClock,tyConCClock,"CClock",HTYPE_CLOCK_T)--- | Haskell type representing the C @time_t@ type.-ARITHMETIC_TYPE(CTime,tyConCTime,"CTime",HTYPE_TIME_T)--- | Haskell type representing the C @useconds_t@ type.-ARITHMETIC_TYPE(CUSeconds,tyConCUSeconds,"CUSeconds",HTYPE_USECONDS_T)--- | Haskell type representing the C @suseconds_t@ type.-ARITHMETIC_TYPE(CSUSeconds,tyConCSUSeconds,"CSUSeconds",HTYPE_SUSECONDS_T)---- FIXME: Implement and provide instances for Eq and Storable--- | Haskell type representing the C @FILE@ type.-data CFile = CFile--- | Haskell type representing the C @fpos_t@ type.-data CFpos = CFpos--- | Haskell type representing the C @jmp_buf@ type.-data CJmpBuf = CJmpBuf--INTEGRAL_TYPE(CIntPtr,tyConCIntPtr,"CIntPtr",HTYPE_INTPTR_T)-INTEGRAL_TYPE(CUIntPtr,tyConCUIntPtr,"CUIntPtr",HTYPE_UINTPTR_T)-INTEGRAL_TYPE(CIntMax,tyConCIntMax,"CIntMax",HTYPE_INTMAX_T)-INTEGRAL_TYPE(CUIntMax,tyConCUIntMax,"CUIntMax",HTYPE_UINTMAX_T)--{-# RULES-"fromIntegral/a->CIntPtr" fromIntegral = \x -> CIntPtr (fromIntegral x)-"fromIntegral/a->CUIntPtr" fromIntegral = \x -> CUIntPtr (fromIntegral x)-"fromIntegral/a->CIntMax" fromIntegral = \x -> CIntMax (fromIntegral x)-"fromIntegral/a->CUIntMax" fromIntegral = \x -> CUIntMax (fromIntegral x)- #-}---- C99 types which are still missing include:--- wint_t, wctrans_t, wctype_t--{- $ctypes--These types are needed to accurately represent C function prototypes,-in order to access C library interfaces in Haskell. The Haskell system-is not required to represent those types exactly as C does, but the-following guarantees are provided concerning a Haskell type @CT@-representing a C type @t@:--* If a C function prototype has @t@ as an argument or result type, the- use of @CT@ in the corresponding position in a foreign declaration- permits the Haskell program to access the full range of values encoded- by the C type; and conversely, any Haskell value for @CT@ has a valid- representation in C.--* @'sizeOf' ('Prelude.undefined' :: CT)@ will yield the same value as- @sizeof (t)@ in C.--* @'alignment' ('Prelude.undefined' :: CT)@ matches the alignment- constraint enforced by the C implementation for @t@.--* The members 'peek' and 'poke' of the 'Storable' class map all values- of @CT@ to the corresponding value of @t@ and vice versa.--* When an instance of 'Prelude.Bounded' is defined for @CT@, the values- of 'Prelude.minBound' and 'Prelude.maxBound' coincide with @t_MIN@- and @t_MAX@ in C.--* When an instance of 'Prelude.Eq' or 'Prelude.Ord' is defined for @CT@,- the predicates defined by the type class implement the same relation- as the corresponding predicate in C on @t@.--* When an instance of 'Prelude.Num', 'Prelude.Read', 'Prelude.Integral',- 'Prelude.Fractional', 'Prelude.Floating', 'Prelude.RealFrac', or- 'Prelude.RealFloat' is defined for @CT@, the arithmetic operations- defined by the type class implement the same function as the- corresponding arithmetic operations (if available) in C on @t@.--* When an instance of 'Bits' is defined for @CT@, the bitwise operation- defined by the type class implement the same function as the- corresponding bitwise operation in C on @t@.---}--#else /* __NHC__ */--import NHC.FFI- ( CChar(..), CSChar(..), CUChar(..)- , CShort(..), CUShort(..), CInt(..), CUInt(..)- , CLong(..), CULong(..), CLLong(..), CULLong(..)- , CPtrdiff(..), CSize(..), CWchar(..), CSigAtomic(..)- , CClock(..), CTime(..), CUSeconds(..), CSUSeconds(..)- , CFloat(..), CDouble(..), CLDouble(..)- , CIntPtr(..), CUIntPtr(..), CIntMax(..), CUIntMax(..)- , CFile, CFpos, CJmpBuf- , Storable(..)- )-import Data.Bits-import NHC.SizedTypes--#define INSTANCE_BITS(T) \-instance Bits T where { \- (T x) .&. (T y) = T (x .&. y) ; \- (T x) .|. (T y) = T (x .|. y) ; \- (T x) `xor` (T y) = T (x `xor` y) ; \- complement (T x) = T (complement x) ; \- shift (T x) n = T (shift x n) ; \- rotate (T x) n = T (rotate x n) ; \- bit n = T (bit n) ; \- setBit (T x) n = T (setBit x n) ; \- clearBit (T x) n = T (clearBit x n) ; \- complementBit (T x) n = T (complementBit x n) ; \- testBit (T x) n = testBit x n ; \- bitSize (T x) = bitSize x ; \- isSigned (T x) = isSigned x ; \- popCount (T x) = popCount x }--INSTANCE_BITS(CChar)-INSTANCE_BITS(CSChar)-INSTANCE_BITS(CUChar)-INSTANCE_BITS(CShort)-INSTANCE_BITS(CUShort)-INSTANCE_BITS(CInt)-INSTANCE_BITS(CUInt)-INSTANCE_BITS(CLong)-INSTANCE_BITS(CULong)-INSTANCE_BITS(CLLong)-INSTANCE_BITS(CULLong)-INSTANCE_BITS(CPtrdiff)-INSTANCE_BITS(CWchar)-INSTANCE_BITS(CSigAtomic)-INSTANCE_BITS(CSize)-INSTANCE_BITS(CIntPtr)-INSTANCE_BITS(CUIntPtr)-INSTANCE_BITS(CIntMax)-INSTANCE_BITS(CUIntMax)--#endif-
@@ -1,54 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Concurrent--- Copyright : (c) The University of Glasgow 2003--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : non-portable (requires concurrency)------ FFI datatypes and operations that use or require concurrency (GHC only).-----------------------------------------------------------------------------------module Foreign.Concurrent- (- -- * Concurrency-based 'ForeignPtr' operations-- -- | These functions generalize their namesakes in the portable- -- "Foreign.ForeignPtr" module by allowing arbitrary 'IO' actions- -- as finalizers. These finalizers necessarily run in a separate- -- thread, cf. /Destructors, Finalizers and Synchronization/,- -- by Hans Boehm, /POPL/, 2003.-- newForeignPtr,- addForeignPtrFinalizer,- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.IO ( IO )-import GHC.Ptr ( Ptr )-import GHC.ForeignPtr ( ForeignPtr )-import qualified GHC.ForeignPtr--newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)--- ^Turns a plain memory reference into a foreign object by associating--- a finalizer - given by the monadic operation - with the reference.--- The finalizer will be executed after the last reference to the--- foreign object is dropped. There is no guarantee of promptness, and--- in fact there is no guarantee that the finalizer will eventually--- run at all.-newForeignPtr = GHC.ForeignPtr.newConcForeignPtr--addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO ()--- ^This function adds a finalizer to the given 'ForeignPtr'.--- The finalizer will run after the last reference to the foreign object--- is dropped, but /before/ all previously registered finalizers for the--- same object.-addForeignPtrFinalizer = GHC.ForeignPtr.addForeignPtrConcFinalizer-#endif-
@@ -1,64 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : Foreign.ForeignPtr--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ The 'ForeignPtr' type and operations. This module is part of the--- Foreign Function Interface (FFI) and will usually be imported via--- the "Foreign" module.-----------------------------------------------------------------------------------module Foreign.ForeignPtr ( - -- * Finalised data pointers- ForeignPtr- , FinalizerPtr-#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)- , FinalizerEnvPtr-#endif- -- ** Basic operations- , newForeignPtr- , newForeignPtr_- , addForeignPtrFinalizer-#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)- , newForeignPtrEnv- , addForeignPtrFinalizerEnv-#endif- , withForeignPtr--#ifdef __GLASGOW_HASKELL__- , finalizeForeignPtr-#endif-- -- ** Low-level operations- , touchForeignPtr- , castForeignPtr-- -- ** Allocating managed memory- , mallocForeignPtr- , mallocForeignPtrBytes- , mallocForeignPtrArray- , mallocForeignPtrArray0- -- ** Unsafe low-level operations- , unsafeForeignPtrToPtr- ) where--import Foreign.ForeignPtr.Safe--import Foreign.Ptr ( Ptr )-import qualified Foreign.ForeignPtr.Unsafe as U--{-# DEPRECATED unsafeForeignPtrToPtr "Use Foreign.ForeignPtr.Unsafe.unsafeForeignPtrToPtr instead; This function will be removed in the next release" #-}-{-# INLINE unsafeForeignPtrToPtr #-}-unsafeForeignPtrToPtr :: ForeignPtr a -> Ptr a-unsafeForeignPtrToPtr = U.unsafeForeignPtrToPtr-
@@ -1,182 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : Foreign.ForeignPtr.Imp--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ The 'ForeignPtr' type and operations. This module is part of the--- Foreign Function Interface (FFI) and will usually be imported via--- the "Foreign" module.-----------------------------------------------------------------------------------module Foreign.ForeignPtr.Imp- ( - -- * Finalised data pointers- ForeignPtr- , FinalizerPtr-#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)- , FinalizerEnvPtr-#endif- -- ** Basic operations- , newForeignPtr- , newForeignPtr_- , addForeignPtrFinalizer-#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)- , newForeignPtrEnv- , addForeignPtrFinalizerEnv-#endif- , withForeignPtr--#ifdef __GLASGOW_HASKELL__- , finalizeForeignPtr-#endif-- -- ** Low-level operations- , unsafeForeignPtrToPtr- , touchForeignPtr- , castForeignPtr-- -- ** Allocating managed memory- , mallocForeignPtr- , mallocForeignPtrBytes- , mallocForeignPtrArray- , mallocForeignPtrArray0- ) - where--import Foreign.Ptr--#ifdef __NHC__-import NHC.FFI- ( ForeignPtr- , FinalizerPtr- , newForeignPtr- , newForeignPtr_- , addForeignPtrFinalizer- , withForeignPtr- , unsafeForeignPtrToPtr- , touchForeignPtr- , castForeignPtr- , Storable(sizeOf)- , malloc, mallocBytes, finalizerFree- )-#endif--#ifdef __HUGS__-import Hugs.ForeignPtr-#endif--#ifndef __NHC__-import Foreign.Storable ( Storable(sizeOf) )-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Num-import GHC.Err ( undefined )-import GHC.ForeignPtr-#endif--#if !defined(__NHC__) && !defined(__GLASGOW_HASKELL__)-import Foreign.Marshal.Alloc ( malloc, mallocBytes, finalizerFree )--instance Eq (ForeignPtr a) where - p == q = unsafeForeignPtrToPtr p == unsafeForeignPtrToPtr q--instance Ord (ForeignPtr a) where - compare p q = compare (unsafeForeignPtrToPtr p) (unsafeForeignPtrToPtr q)--instance Show (ForeignPtr a) where- showsPrec p f = showsPrec p (unsafeForeignPtrToPtr f)-#endif---#ifndef __NHC__-newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)--- ^Turns a plain memory reference into a foreign pointer, and--- associates a finalizer with the reference. The finalizer will be--- executed after the last reference to the foreign object is dropped.--- There is no guarantee of promptness, however the finalizer will be--- executed before the program exits.-newForeignPtr finalizer p- = do fObj <- newForeignPtr_ p- addForeignPtrFinalizer finalizer fObj- return fObj--withForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b--- ^This is a way to look at the pointer living inside a--- foreign object. This function takes a function which is--- applied to that pointer. The resulting 'IO' action is then--- executed. The foreign object is kept alive at least during--- the whole action, even if it is not used directly--- inside. Note that it is not safe to return the pointer from--- the action and use it after the action completes. All uses--- of the pointer should be inside the--- 'withForeignPtr' bracket. The reason for--- this unsafeness is the same as for--- 'unsafeForeignPtrToPtr' below: the finalizer--- may run earlier than expected, because the compiler can only--- track usage of the 'ForeignPtr' object, not--- a 'Ptr' object made from it.------ This function is normally used for marshalling data to--- or from the object pointed to by the--- 'ForeignPtr', using the operations from the--- 'Storable' class.-withForeignPtr fo io- = do r <- io (unsafeForeignPtrToPtr fo)- touchForeignPtr fo- return r-#endif /* ! __NHC__ */--#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)--- | This variant of 'newForeignPtr' adds a finalizer that expects an--- environment in addition to the finalized pointer. The environment--- that will be passed to the finalizer is fixed by the second argument to--- 'newForeignPtrEnv'.-newForeignPtrEnv ::- FinalizerEnvPtr env a -> Ptr env -> Ptr a -> IO (ForeignPtr a)-newForeignPtrEnv finalizer env p- = do fObj <- newForeignPtr_ p- addForeignPtrFinalizerEnv finalizer env fObj- return fObj-#endif /* __HUGS__ */--#ifndef __GLASGOW_HASKELL__-mallocForeignPtr :: Storable a => IO (ForeignPtr a)-mallocForeignPtr = do- r <- malloc- newForeignPtr finalizerFree r--mallocForeignPtrBytes :: Int -> IO (ForeignPtr a)-mallocForeignPtrBytes n = do- r <- mallocBytes n- newForeignPtr finalizerFree r-#endif /* !__GLASGOW_HASKELL__ */---- | This function is similar to 'Foreign.Marshal.Array.mallocArray',--- but yields a memory area that has a finalizer attached that releases--- the memory area. As with 'mallocForeignPtr', it is not guaranteed that--- the block of memory was allocated by 'Foreign.Marshal.Alloc.malloc'.-mallocForeignPtrArray :: Storable a => Int -> IO (ForeignPtr a)-mallocForeignPtrArray = doMalloc undefined- where- doMalloc :: Storable b => b -> Int -> IO (ForeignPtr b)- doMalloc dummy size = mallocForeignPtrBytes (size * sizeOf dummy)---- | This function is similar to 'Foreign.Marshal.Array.mallocArray0',--- but yields a memory area that has a finalizer attached that releases--- the memory area. As with 'mallocForeignPtr', it is not guaranteed that--- the block of memory was allocated by 'Foreign.Marshal.Alloc.malloc'.-mallocForeignPtrArray0 :: Storable a => Int -> IO (ForeignPtr a)-mallocForeignPtrArray0 size = mallocForeignPtrArray (size + 1)-
@@ -1,55 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.ForeignPtr.Safe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ The 'ForeignPtr' type and operations. This module is part of the--- Foreign Function Interface (FFI) and will usually be imported via--- the "Foreign" module.------ Safe API Only.-----------------------------------------------------------------------------------module Foreign.ForeignPtr.Safe (- -- * Finalised data pointers- ForeignPtr- , FinalizerPtr-#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)- , FinalizerEnvPtr-#endif- -- ** Basic operations- , newForeignPtr- , newForeignPtr_- , addForeignPtrFinalizer-#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)- , newForeignPtrEnv- , addForeignPtrFinalizerEnv-#endif- , withForeignPtr--#ifdef __GLASGOW_HASKELL__- , finalizeForeignPtr-#endif-- -- ** Low-level operations- , touchForeignPtr- , castForeignPtr-- -- ** Allocating managed memory- , mallocForeignPtr- , mallocForeignPtrBytes- , mallocForeignPtrArray- , mallocForeignPtrArray0- ) where--import Foreign.ForeignPtr.Imp-
@@ -1,28 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.ForeignPtr.Unsafe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ The 'ForeignPtr' type and operations. This module is part of the--- Foreign Function Interface (FFI) and will usually be imported via--- the "Foreign" module.------ Unsafe API Only.-----------------------------------------------------------------------------------module Foreign.ForeignPtr.Unsafe (- -- ** Unsafe low-level operations- unsafeForeignPtrToPtr,- ) where--import Foreign.ForeignPtr.Imp-
@@ -1,58 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal--- Copyright : (c) The FFI task force 2003--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Marshalling support-----------------------------------------------------------------------------------module Foreign.Marshal- (- -- | The module "Foreign.Marshal" re-exports the safe content in the- -- @Foreign.Marshal@ hierarchy:- module Foreign.Marshal.Safe- -- | and provides one function:- , unsafeLocalState- ) where--import Foreign.Marshal.Safe--#ifdef __GLASGOW_HASKELL__-import GHC.IO-#else-import System.IO.Unsafe-#endif--{- |-Sometimes an external entity is a pure function, except that it passes-arguments and/or results via pointers. The function-@unsafeLocalState@ permits the packaging of such entities as pure-functions. --The only IO operations allowed in the IO action passed to-@unsafeLocalState@ are (a) local allocation (@alloca@, @allocaBytes@-and derived operations such as @withArray@ and @withCString@), and (b)-pointer operations (@Foreign.Storable@ and @Foreign.Ptr@) on the-pointers to local storage, and (c) foreign functions whose only-observable effect is to read and/or write the locally allocated-memory. Passing an IO operation that does not obey these rules-results in undefined behaviour.--It is expected that this operation will be-replaced in a future revision of Haskell.--}-{-# DEPRECATED unsafeLocalState- "Please import from Foreign.Marshall.Unsafe instead; This will be removed in the next release"- #-}-unsafeLocalState :: IO a -> a-unsafeLocalState = unsafePerformIO-
@@ -1,248 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , MagicHash- , UnboxedTuples- , ForeignFunctionInterface- #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Alloc--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ The module "Foreign.Marshal.Alloc" provides operations to allocate and--- deallocate blocks of raw memory (i.e., unstructured chunks of memory--- outside of the area maintained by the Haskell storage manager). These--- memory blocks are commonly used to pass compound data structures to--- foreign functions or to provide space in which compound result values--- are obtained from foreign functions.--- --- If any of the allocation functions fails, an exception is thrown.--- In some cases, memory exhaustion may mean the process is terminated.--- If 'free' or 'reallocBytes' is applied to a memory area--- that has been allocated with 'alloca' or 'allocaBytes', the--- behaviour is undefined. Any further access to memory areas allocated with--- 'alloca' or 'allocaBytes', after the computation that was passed to--- the allocation function has terminated, leads to undefined behaviour. Any--- further access to the memory area referenced by a pointer passed to--- 'realloc', 'reallocBytes', or 'free' entails undefined--- behaviour.--- --- All storage allocated by functions that allocate based on a /size in bytes/--- must be sufficiently aligned for any of the basic foreign types--- that fits into the newly allocated storage. All storage allocated by--- functions that allocate based on a specific type must be sufficiently--- aligned for that type. Array allocation routines need to obey the same--- alignment constraints for each array element.-----------------------------------------------------------------------------------module Foreign.Marshal.Alloc (- -- * Memory allocation- -- ** Local allocation- alloca, -- :: Storable a => (Ptr a -> IO b) -> IO b- allocaBytes, -- :: Int -> (Ptr a -> IO b) -> IO b- allocaBytesAligned, -- :: Int -> Int -> (Ptr a -> IO b) -> IO b-- -- ** Dynamic allocation- malloc, -- :: Storable a => IO (Ptr a)- mallocBytes, -- :: Int -> IO (Ptr a)-- realloc, -- :: Storable b => Ptr a -> IO (Ptr b)- reallocBytes, -- :: Ptr a -> Int -> IO (Ptr a)-- free, -- :: Ptr a -> IO ()- finalizerFree -- :: FinalizerPtr a-) where--import Data.Maybe-import Foreign.C.Types ( CSize(..) )-import Foreign.Storable ( Storable(sizeOf,alignment) )--#ifndef __GLASGOW_HASKELL__-import Foreign.Ptr ( Ptr, nullPtr, FunPtr )-#endif--#ifdef __GLASGOW_HASKELL__-import Foreign.ForeignPtr ( FinalizerPtr )-import GHC.IO.Exception-import GHC.Real-import GHC.Ptr-import GHC.Err-import GHC.Base-#elif defined(__NHC__)-import NHC.FFI ( FinalizerPtr, CInt(..) )-import IO ( bracket )-#else-import Control.Exception.Base ( bracket )-#endif--#ifdef __HUGS__-import Hugs.Prelude ( IOException(IOError),- IOErrorType(ResourceExhausted) )-import Hugs.ForeignPtr ( FinalizerPtr )-#endif----- exported functions--- ---------------------- |Allocate a block of memory that is sufficient to hold values of type--- @a@. The size of the area allocated is determined by the 'sizeOf'--- method from the instance of 'Storable' for the appropriate type.------ The memory may be deallocated using 'free' or 'finalizerFree' when--- no longer required.----{-# INLINE malloc #-}-malloc :: Storable a => IO (Ptr a)-malloc = doMalloc undefined- where- doMalloc :: Storable b => b -> IO (Ptr b)- doMalloc dummy = mallocBytes (sizeOf dummy)---- |Allocate a block of memory of the given number of bytes.--- The block of memory is sufficiently aligned for any of the basic--- foreign types that fits into a memory block of the allocated size.------ The memory may be deallocated using 'free' or 'finalizerFree' when--- no longer required.----mallocBytes :: Int -> IO (Ptr a)-mallocBytes size = failWhenNULL "malloc" (_malloc (fromIntegral size))---- |@'alloca' f@ executes the computation @f@, passing as argument--- a pointer to a temporarily allocated block of memory sufficient to--- hold values of type @a@.------ The memory is freed when @f@ terminates (either normally or via an--- exception), so the pointer passed to @f@ must /not/ be used after this.----{-# INLINE alloca #-}-alloca :: Storable a => (Ptr a -> IO b) -> IO b-alloca = doAlloca undefined- where- doAlloca :: Storable a' => a' -> (Ptr a' -> IO b') -> IO b'- doAlloca dummy = allocaBytesAligned (sizeOf dummy) (alignment dummy)---- |@'allocaBytes' n f@ executes the computation @f@, passing as argument--- a pointer to a temporarily allocated block of memory of @n@ bytes.--- The block of memory is sufficiently aligned for any of the basic--- foreign types that fits into a memory block of the allocated size.------ The memory is freed when @f@ terminates (either normally or via an--- exception), so the pointer passed to @f@ must /not/ be used after this.----#ifdef __GLASGOW_HASKELL__-allocaBytes :: Int -> (Ptr a -> IO b) -> IO b-allocaBytes (I# size) action = IO $ \ s0 ->- case newPinnedByteArray# size s0 of { (# s1, mbarr# #) ->- case unsafeFreezeByteArray# mbarr# s1 of { (# s2, barr# #) ->- let addr = Ptr (byteArrayContents# barr#) in- case action addr of { IO action' ->- case action' s2 of { (# s3, r #) ->- case touch# barr# s3 of { s4 ->- (# s4, r #)- }}}}}--allocaBytesAligned :: Int -> Int -> (Ptr a -> IO b) -> IO b-allocaBytesAligned (I# size) (I# align) action = IO $ \ s0 ->- case newAlignedPinnedByteArray# size align s0 of { (# s1, mbarr# #) ->- case unsafeFreezeByteArray# mbarr# s1 of { (# s2, barr# #) ->- let addr = Ptr (byteArrayContents# barr#) in- case action addr of { IO action' ->- case action' s2 of { (# s3, r #) ->- case touch# barr# s3 of { s4 ->- (# s4, r #)- }}}}}-#else-allocaBytes :: Int -> (Ptr a -> IO b) -> IO b-allocaBytes size = bracket (mallocBytes size) free--allocaBytesAligned :: Int -> Int -> (Ptr a -> IO b) -> IO b-allocaBytesAligned size align = allocaBytes size -- wrong-#endif---- |Resize a memory area that was allocated with 'malloc' or 'mallocBytes'--- to the size needed to store values of type @b@. The returned pointer--- may refer to an entirely different memory area, but will be suitably--- aligned to hold values of type @b@. The contents of the referenced--- memory area will be the same as of the original pointer up to the--- minimum of the original size and the size of values of type @b@.------ If the argument to 'realloc' is 'nullPtr', 'realloc' behaves like--- 'malloc'.----realloc :: Storable b => Ptr a -> IO (Ptr b)-realloc = doRealloc undefined- where- doRealloc :: Storable b' => b' -> Ptr a' -> IO (Ptr b')- doRealloc dummy ptr = let- size = fromIntegral (sizeOf dummy)- in- failWhenNULL "realloc" (_realloc ptr size)---- |Resize a memory area that was allocated with 'malloc' or 'mallocBytes'--- to the given size. The returned pointer may refer to an entirely--- different memory area, but will be sufficiently aligned for any of the--- basic foreign types that fits into a memory block of the given size.--- The contents of the referenced memory area will be the same as of--- the original pointer up to the minimum of the original size and the--- given size.------ If the pointer argument to 'reallocBytes' is 'nullPtr', 'reallocBytes'--- behaves like 'malloc'. If the requested size is 0, 'reallocBytes'--- behaves like 'free'.----reallocBytes :: Ptr a -> Int -> IO (Ptr a)-reallocBytes ptr 0 = do free ptr; return nullPtr-reallocBytes ptr size = - failWhenNULL "realloc" (_realloc ptr (fromIntegral size))---- |Free a block of memory that was allocated with 'malloc',--- 'mallocBytes', 'realloc', 'reallocBytes', 'Foreign.Marshal.Utils.new'--- or any of the @new@/X/ functions in "Foreign.Marshal.Array" or--- "Foreign.C.String".----free :: Ptr a -> IO ()-free = _free----- auxilliary routines--- ----------------------- asserts that the pointer returned from the action in the second argument is--- non-null----failWhenNULL :: String -> IO (Ptr a) -> IO (Ptr a)-failWhenNULL name f = do- addr <- f- if addr == nullPtr-#if __GLASGOW_HASKELL__- then ioError (IOError Nothing ResourceExhausted name - "out of memory" Nothing Nothing)-#elif __HUGS__- then ioError (IOError Nothing ResourceExhausted name - "out of memory" Nothing)-#else- then ioError (userError (name++": out of memory"))-#endif- else return addr---- basic C routines needed for memory allocation----foreign import ccall unsafe "stdlib.h malloc" _malloc :: CSize -> IO (Ptr a)-foreign import ccall unsafe "stdlib.h realloc" _realloc :: Ptr a -> CSize -> IO (Ptr b)-foreign import ccall unsafe "stdlib.h free" _free :: Ptr a -> IO ()---- | A pointer to a foreign function equivalent to 'free', which may be--- used as a finalizer (cf 'Foreign.ForeignPtr.ForeignPtr') for storage--- allocated with 'malloc', 'mallocBytes', 'realloc' or 'reallocBytes'.-foreign import ccall unsafe "stdlib.h &free" finalizerFree :: FinalizerPtr a-
@@ -1,280 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Array--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Marshalling support: routines allocating, storing, and retrieving Haskell--- lists that are represented as arrays in the foreign language-----------------------------------------------------------------------------------module Foreign.Marshal.Array (- -- * Marshalling arrays-- -- ** Allocation- --- mallocArray, -- :: Storable a => Int -> IO (Ptr a)- mallocArray0, -- :: Storable a => Int -> IO (Ptr a)-- allocaArray, -- :: Storable a => Int -> (Ptr a -> IO b) -> IO b- allocaArray0, -- :: Storable a => Int -> (Ptr a -> IO b) -> IO b-- reallocArray, -- :: Storable a => Ptr a -> Int -> IO (Ptr a)- reallocArray0, -- :: Storable a => Ptr a -> Int -> IO (Ptr a)-- -- ** Marshalling- --- peekArray, -- :: Storable a => Int -> Ptr a -> IO [a]- peekArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO [a]-- pokeArray, -- :: Storable a => Ptr a -> [a] -> IO ()- pokeArray0, -- :: Storable a => a -> Ptr a -> [a] -> IO ()-- -- ** Combined allocation and marshalling- --- newArray, -- :: Storable a => [a] -> IO (Ptr a)- newArray0, -- :: Storable a => a -> [a] -> IO (Ptr a)-- withArray, -- :: Storable a => [a] -> (Ptr a -> IO b) -> IO b- withArray0, -- :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b-- withArrayLen, -- :: Storable a => [a] -> (Int -> Ptr a -> IO b) -> IO b- withArrayLen0, -- :: Storable a => a -> [a] -> (Int -> Ptr a -> IO b) -> IO b-- -- ** Copying-- -- | (argument order: destination, source)- copyArray, -- :: Storable a => Ptr a -> Ptr a -> Int -> IO ()- moveArray, -- :: Storable a => Ptr a -> Ptr a -> Int -> IO ()-- -- ** Finding the length- --- lengthArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO Int-- -- ** Indexing- --- advancePtr, -- :: Storable a => Ptr a -> Int -> Ptr a-) where--import Foreign.Ptr (Ptr, plusPtr)-import Foreign.Storable (Storable(alignment,sizeOf,peekElemOff,pokeElemOff))-import Foreign.Marshal.Alloc (mallocBytes, allocaBytesAligned, reallocBytes)-import Foreign.Marshal.Utils (copyBytes, moveBytes)--#ifdef __GLASGOW_HASKELL__-import GHC.Num-import GHC.List-import GHC.Err-import GHC.Base-#else-import Control.Monad (zipWithM_)-#endif---- allocation--- -------------- |Allocate storage for the given number of elements of a storable type--- (like 'Foreign.Marshal.Alloc.malloc', but for multiple elements).----mallocArray :: Storable a => Int -> IO (Ptr a)-mallocArray = doMalloc undefined- where- doMalloc :: Storable a' => a' -> Int -> IO (Ptr a')- doMalloc dummy size = mallocBytes (size * sizeOf dummy)---- |Like 'mallocArray', but add an extra position to hold a special--- termination element.----mallocArray0 :: Storable a => Int -> IO (Ptr a)-mallocArray0 size = mallocArray (size + 1)---- |Temporarily allocate space for the given number of elements--- (like 'Foreign.Marshal.Alloc.alloca', but for multiple elements).----allocaArray :: Storable a => Int -> (Ptr a -> IO b) -> IO b-allocaArray = doAlloca undefined- where- doAlloca :: Storable a' => a' -> Int -> (Ptr a' -> IO b') -> IO b'- doAlloca dummy size = allocaBytesAligned (size * sizeOf dummy)- (alignment dummy)---- |Like 'allocaArray', but add an extra position to hold a special--- termination element.----allocaArray0 :: Storable a => Int -> (Ptr a -> IO b) -> IO b-allocaArray0 size = allocaArray (size + 1)-{-# INLINE allocaArray0 #-}- -- needed to get allocaArray to inline into withCString, for unknown- -- reasons --SDM 23/4/2010, see #4004 for benchmark---- |Adjust the size of an array----reallocArray :: Storable a => Ptr a -> Int -> IO (Ptr a)-reallocArray = doRealloc undefined- where- doRealloc :: Storable a' => a' -> Ptr a' -> Int -> IO (Ptr a')- doRealloc dummy ptr size = reallocBytes ptr (size * sizeOf dummy)---- |Adjust the size of an array including an extra position for the end marker.----reallocArray0 :: Storable a => Ptr a -> Int -> IO (Ptr a)-reallocArray0 ptr size = reallocArray ptr (size + 1)----- marshalling--- --------------- |Convert an array of given length into a Haskell list. The implementation--- is tail-recursive and so uses constant stack space.----peekArray :: Storable a => Int -> Ptr a -> IO [a]-peekArray size ptr | size <= 0 = return []- | otherwise = f (size-1) []- where- f 0 acc = do e <- peekElemOff ptr 0; return (e:acc)- f n acc = do e <- peekElemOff ptr n; f (n-1) (e:acc)- --- |Convert an array terminated by the given end marker into a Haskell list----peekArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO [a]-peekArray0 marker ptr = do- size <- lengthArray0 marker ptr- peekArray size ptr---- |Write the list elements consecutive into memory----pokeArray :: Storable a => Ptr a -> [a] -> IO ()-#ifndef __GLASGOW_HASKELL__-pokeArray ptr vals = zipWithM_ (pokeElemOff ptr) [0..] vals-#else-pokeArray ptr vals0 = go vals0 0#- where go [] _ = return ()- go (val:vals) n# = do pokeElemOff ptr (I# n#) val; go vals (n# +# 1#)-#endif---- |Write the list elements consecutive into memory and terminate them with the--- given marker element----pokeArray0 :: Storable a => a -> Ptr a -> [a] -> IO ()-#ifndef __GLASGOW_HASKELL__-pokeArray0 marker ptr vals = do- pokeArray ptr vals- pokeElemOff ptr (length vals) marker-#else-pokeArray0 marker ptr vals0 = go vals0 0#- where go [] n# = pokeElemOff ptr (I# n#) marker- go (val:vals) n# = do pokeElemOff ptr (I# n#) val; go vals (n# +# 1#)-#endif----- combined allocation and marshalling--- --------------------------------------- |Write a list of storable elements into a newly allocated, consecutive--- sequence of storable values--- (like 'Foreign.Marshal.Utils.new', but for multiple elements).----newArray :: Storable a => [a] -> IO (Ptr a)-newArray vals = do- ptr <- mallocArray (length vals)- pokeArray ptr vals- return ptr---- |Write a list of storable elements into a newly allocated, consecutive--- sequence of storable values, where the end is fixed by the given end marker----newArray0 :: Storable a => a -> [a] -> IO (Ptr a)-newArray0 marker vals = do- ptr <- mallocArray0 (length vals)- pokeArray0 marker ptr vals- return ptr---- |Temporarily store a list of storable values in memory--- (like 'Foreign.Marshal.Utils.with', but for multiple elements).----withArray :: Storable a => [a] -> (Ptr a -> IO b) -> IO b-withArray vals = withArrayLen vals . const---- |Like 'withArray', but the action gets the number of values--- as an additional parameter----withArrayLen :: Storable a => [a] -> (Int -> Ptr a -> IO b) -> IO b-withArrayLen vals f =- allocaArray len $ \ptr -> do- pokeArray ptr vals- res <- f len ptr- return res- where- len = length vals---- |Like 'withArray', but a terminator indicates where the array ends----withArray0 :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b-withArray0 marker vals = withArrayLen0 marker vals . const---- |Like 'withArrayLen', but a terminator indicates where the array ends----withArrayLen0 :: Storable a => a -> [a] -> (Int -> Ptr a -> IO b) -> IO b-withArrayLen0 marker vals f =- allocaArray0 len $ \ptr -> do- pokeArray0 marker ptr vals- res <- f len ptr- return res- where- len = length vals----- copying (argument order: destination, source)--- ----------- |Copy the given number of elements from the second array (source) into the--- first array (destination); the copied areas may /not/ overlap----copyArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()-copyArray = doCopy undefined- where- doCopy :: Storable a' => a' -> Ptr a' -> Ptr a' -> Int -> IO ()- doCopy dummy dest src size = copyBytes dest src (size * sizeOf dummy)---- |Copy the given number of elements from the second array (source) into the--- first array (destination); the copied areas /may/ overlap----moveArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()-moveArray = doMove undefined- where- doMove :: Storable a' => a' -> Ptr a' -> Ptr a' -> Int -> IO ()- doMove dummy dest src size = moveBytes dest src (size * sizeOf dummy)----- finding the length--- ---------------------- |Return the number of elements in an array, excluding the terminator----lengthArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO Int-lengthArray0 marker ptr = loop 0- where- loop i = do- val <- peekElemOff ptr i- if val == marker then return i else loop (i+1)----- indexing--- ------------ |Advance a pointer into an array by the given number of elements----advancePtr :: Storable a => Ptr a -> Int -> Ptr a-advancePtr = doAdvance undefined- where- doAdvance :: Storable a' => a' -> Ptr a' -> Int -> Ptr a'- doAdvance dummy ptr i = ptr `plusPtr` (i * sizeOf dummy)-
@@ -1,86 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Error--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Routines for testing return values and raising a 'userError' exception--- in case of values indicating an error state.-----------------------------------------------------------------------------------module Foreign.Marshal.Error (- throwIf, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO a- throwIf_, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO ()- throwIfNeg, -- :: (Ord a, Num a) - -- => (a -> String) -> IO a -> IO a- throwIfNeg_, -- :: (Ord a, Num a)- -- => (a -> String) -> IO a -> IO ()- throwIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)-- -- Discard return value- --- void -- IO a -> IO ()-) where--import Foreign.Ptr--#ifdef __GLASGOW_HASKELL__-#ifdef __HADDOCK__-import Data.Bool-import System.IO.Error-#endif-import GHC.Base-import GHC.Num-import GHC.IO.Exception-#endif---- exported functions--- ---------------------- |Execute an 'IO' action, throwing a 'userError' if the predicate yields--- 'True' when applied to the result returned by the 'IO' action.--- If no exception is raised, return the result of the computation.----throwIf :: (a -> Bool) -- ^ error condition on the result of the 'IO' action- -> (a -> String) -- ^ computes an error message from erroneous results- -- of the 'IO' action- -> IO a -- ^ the 'IO' action to be executed- -> IO a-throwIf pred msgfct act = - do- res <- act- (if pred res then ioError . userError . msgfct else return) res---- |Like 'throwIf', but discarding the result----throwIf_ :: (a -> Bool) -> (a -> String) -> IO a -> IO ()-throwIf_ pred msgfct act = void $ throwIf pred msgfct act---- |Guards against negative result values----throwIfNeg :: (Ord a, Num a) => (a -> String) -> IO a -> IO a-throwIfNeg = throwIf (< 0)---- |Like 'throwIfNeg', but discarding the result----throwIfNeg_ :: (Ord a, Num a) => (a -> String) -> IO a -> IO ()-throwIfNeg_ = throwIf_ (< 0)---- |Guards against null pointers----throwIfNull :: String -> IO (Ptr a) -> IO (Ptr a)-throwIfNull = throwIf (== nullPtr) . const---- |Discard the return value of an 'IO' action----void :: IO a -> IO ()-void act = act >> return ()-
@@ -1,212 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}------------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Pool--- Copyright : (c) Sven Panne 2002-2004--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : sven.panne@aedion.de--- Stability : provisional--- Portability : portable------ This module contains support for pooled memory management. Under this scheme,--- (re-)allocations belong to a given pool, and everything in a pool is--- deallocated when the pool itself is deallocated. This is useful when--- 'Foreign.Marshal.Alloc.alloca' with its implicit allocation and deallocation--- is not flexible enough, but explicit uses of 'Foreign.Marshal.Alloc.malloc'--- and 'free' are too awkward.--------------------------------------------------------------------------------------module Foreign.Marshal.Pool (- -- * Pool management- Pool,- newPool, -- :: IO Pool- freePool, -- :: Pool -> IO ()- withPool, -- :: (Pool -> IO b) -> IO b-- -- * (Re-)Allocation within a pool- pooledMalloc, -- :: Storable a => Pool -> IO (Ptr a)- pooledMallocBytes, -- :: Pool -> Int -> IO (Ptr a)-- pooledRealloc, -- :: Storable a => Pool -> Ptr a -> IO (Ptr a)- pooledReallocBytes, -- :: Pool -> Ptr a -> Int -> IO (Ptr a)-- pooledMallocArray, -- :: Storable a => Pool -> Int -> IO (Ptr a)- pooledMallocArray0, -- :: Storable a => Pool -> Int -> IO (Ptr a)-- pooledReallocArray, -- :: Storable a => Pool -> Ptr a -> Int -> IO (Ptr a)- pooledReallocArray0, -- :: Storable a => Pool -> Ptr a -> Int -> IO (Ptr a)-- -- * Combined allocation and marshalling- pooledNew, -- :: Storable a => Pool -> a -> IO (Ptr a)- pooledNewArray, -- :: Storable a => Pool -> [a] -> IO (Ptr a)- pooledNewArray0 -- :: Storable a => Pool -> a -> [a] -> IO (Ptr a)-) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base ( Int, Monad(..), (.), not )-import GHC.Err ( undefined )-import GHC.Exception ( throw )-import GHC.IO ( IO, mask, catchAny )-import GHC.IORef ( IORef, newIORef, readIORef, writeIORef )-import GHC.List ( elem, length )-import GHC.Num ( Num(..) )-#else-import Data.IORef ( IORef, newIORef, readIORef, writeIORef )-#if defined(__NHC__)-import IO ( bracket )-#else-import Control.Exception.Base ( bracket )-#endif-#endif--import Control.Monad ( liftM )-import Data.List ( delete )-import Foreign.Marshal.Alloc ( mallocBytes, reallocBytes, free )-import Foreign.Marshal.Array ( pokeArray, pokeArray0 )-import Foreign.Marshal.Error ( throwIf )-import Foreign.Ptr ( Ptr, castPtr )-import Foreign.Storable ( Storable(sizeOf, poke) )-------------------------------------------------------------------------------------- To avoid non-H98 stuff like existentially quantified data constructors, we--- simply use pointers to () below. Not very nice, but...---- | A memory pool.--newtype Pool = Pool (IORef [Ptr ()])---- | Allocate a fresh memory pool.--newPool :: IO Pool-newPool = liftM Pool (newIORef [])---- | Deallocate a memory pool and everything which has been allocated in the--- pool itself.--freePool :: Pool -> IO ()-freePool (Pool pool) = readIORef pool >>= freeAll- where freeAll [] = return ()- freeAll (p:ps) = free p >> freeAll ps---- | Execute an action with a fresh memory pool, which gets automatically--- deallocated (including its contents) after the action has finished.--withPool :: (Pool -> IO b) -> IO b-#ifdef __GLASGOW_HASKELL__-withPool act = -- ATTENTION: cut-n-paste from Control.Exception below!- mask (\restore -> do- pool <- newPool- val <- catchAny- (restore (act pool))- (\e -> do freePool pool; throw e)- freePool pool- return val)-#else-withPool = bracket newPool freePool-#endif-------------------------------------------------------------------------------------- | Allocate space for storable type in the given pool. The size of the area--- allocated is determined by the 'sizeOf' method from the instance of--- 'Storable' for the appropriate type.--pooledMalloc :: Storable a => Pool -> IO (Ptr a)-pooledMalloc = pm undefined- where- pm :: Storable a' => a' -> Pool -> IO (Ptr a')- pm dummy pool = pooledMallocBytes pool (sizeOf dummy)---- | Allocate the given number of bytes of storage in the pool.--pooledMallocBytes :: Pool -> Int -> IO (Ptr a)-pooledMallocBytes (Pool pool) size = do- ptr <- mallocBytes size- ptrs <- readIORef pool- writeIORef pool (ptr:ptrs)- return (castPtr ptr)---- | Adjust the storage area for an element in the pool to the given size of--- the required type.--pooledRealloc :: Storable a => Pool -> Ptr a -> IO (Ptr a)-pooledRealloc = pr undefined- where- pr :: Storable a' => a' -> Pool -> Ptr a' -> IO (Ptr a')- pr dummy pool ptr = pooledReallocBytes pool ptr (sizeOf dummy)---- | Adjust the storage area for an element in the pool to the given size.--pooledReallocBytes :: Pool -> Ptr a -> Int -> IO (Ptr a)-pooledReallocBytes (Pool pool) ptr size = do- let cPtr = castPtr ptr- _ <- throwIf (not . (cPtr `elem`)) (\_ -> "pointer not in pool") (readIORef pool)- newPtr <- reallocBytes cPtr size- ptrs <- readIORef pool- writeIORef pool (newPtr : delete cPtr ptrs)- return (castPtr newPtr)---- | Allocate storage for the given number of elements of a storable type in the--- pool.--pooledMallocArray :: Storable a => Pool -> Int -> IO (Ptr a)-pooledMallocArray = pma undefined- where- pma :: Storable a' => a' -> Pool -> Int -> IO (Ptr a')- pma dummy pool size = pooledMallocBytes pool (size * sizeOf dummy)---- | Allocate storage for the given number of elements of a storable type in the--- pool, but leave room for an extra element to signal the end of the array.--pooledMallocArray0 :: Storable a => Pool -> Int -> IO (Ptr a)-pooledMallocArray0 pool size =- pooledMallocArray pool (size + 1)---- | Adjust the size of an array in the given pool.--pooledReallocArray :: Storable a => Pool -> Ptr a -> Int -> IO (Ptr a)-pooledReallocArray = pra undefined- where- pra :: Storable a' => a' -> Pool -> Ptr a' -> Int -> IO (Ptr a')- pra dummy pool ptr size = pooledReallocBytes pool ptr (size * sizeOf dummy)---- | Adjust the size of an array with an end marker in the given pool.--pooledReallocArray0 :: Storable a => Pool -> Ptr a -> Int -> IO (Ptr a)-pooledReallocArray0 pool ptr size =- pooledReallocArray pool ptr (size + 1)-------------------------------------------------------------------------------------- | Allocate storage for a value in the given pool and marshal the value into--- this storage.--pooledNew :: Storable a => Pool -> a -> IO (Ptr a)-pooledNew pool val = do- ptr <- pooledMalloc pool- poke ptr val- return ptr---- | Allocate consecutive storage for a list of values in the given pool and--- marshal these values into it.--pooledNewArray :: Storable a => Pool -> [a] -> IO (Ptr a)-pooledNewArray pool vals = do- ptr <- pooledMallocArray pool (length vals)- pokeArray ptr vals- return ptr---- | Allocate consecutive storage for a list of values in the given pool and--- marshal these values into it, terminating the end with the given marker.--pooledNewArray0 :: Storable a => Pool -> a -> [a] -> IO (Ptr a)-pooledNewArray0 pool marker vals = do- ptr <- pooledMallocArray0 pool (length vals)- pokeArray0 marker ptr vals- return ptr-
@@ -1,36 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Safe--- Copyright : (c) The FFI task force 2003--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Marshalling support------ Safe API Only.-----------------------------------------------------------------------------------module Foreign.Marshal.Safe- (- -- | The module "Foreign.Marshal.Safe" re-exports the other modules in the- -- @Foreign.Marshal@ hierarchy:- module Foreign.Marshal.Alloc- , module Foreign.Marshal.Array- , module Foreign.Marshal.Error- , module Foreign.Marshal.Pool- , module Foreign.Marshal.Utils- ) where--import Foreign.Marshal.Alloc-import Foreign.Marshal.Array-import Foreign.Marshal.Error-import Foreign.Marshal.Pool-import Foreign.Marshal.Utils-
@@ -1,49 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Unsafe--- Copyright : (c) The FFI task force 2003--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Marshalling support. Unsafe API.-----------------------------------------------------------------------------------module Foreign.Marshal.Unsafe (- -- * Unsafe functions- unsafeLocalState- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.IO-#else-import System.IO.Unsafe-#endif--{- |-Sometimes an external entity is a pure function, except that it passes-arguments and/or results via pointers. The function-@unsafeLocalState@ permits the packaging of such entities as pure-functions. --The only IO operations allowed in the IO action passed to-@unsafeLocalState@ are (a) local allocation (@alloca@, @allocaBytes@-and derived operations such as @withArray@ and @withCString@), and (b)-pointer operations (@Foreign.Storable@ and @Foreign.Ptr@) on the-pointers to local storage, and (c) foreign functions whose only-observable effect is to read and/or write the locally allocated-memory. Passing an IO operation that does not obey these rules-results in undefined behaviour.--It is expected that this operation will be-replaced in a future revision of Haskell.--}-unsafeLocalState :: IO a -> a-unsafeLocalState = unsafeDupablePerformIO-
@@ -1,181 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ForeignFunctionInterface #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Marshal.Utils--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ Utilities for primitive marshaling-----------------------------------------------------------------------------------module Foreign.Marshal.Utils (- -- * General marshalling utilities-- -- ** Combined allocation and marshalling- --- with, -- :: Storable a => a -> (Ptr a -> IO b) -> IO b- new, -- :: Storable a => a -> IO (Ptr a)-- -- ** Marshalling of Boolean values (non-zero corresponds to 'True')- --- fromBool, -- :: Num a => Bool -> a- toBool, -- :: Num a => a -> Bool-- -- ** Marshalling of Maybe values- --- maybeNew, -- :: ( a -> IO (Ptr a))- -- -> (Maybe a -> IO (Ptr a))- maybeWith, -- :: ( a -> (Ptr b -> IO c) -> IO c)- -- -> (Maybe a -> (Ptr b -> IO c) -> IO c)- maybePeek, -- :: (Ptr a -> IO b )- -- -> (Ptr a -> IO (Maybe b))-- -- ** Marshalling lists of storable objects- --- withMany, -- :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res-- -- ** Haskellish interface to memcpy and memmove- -- | (argument order: destination, source)- --- copyBytes, -- :: Ptr a -> Ptr a -> Int -> IO ()- moveBytes, -- :: Ptr a -> Ptr a -> Int -> IO ()-) where--import Data.Maybe-import Foreign.Ptr ( Ptr, nullPtr )-import Foreign.Storable ( Storable(poke) )-import Foreign.C.Types ( CSize(..) )-import Foreign.Marshal.Alloc ( malloc, alloca )--#ifdef __GLASGOW_HASKELL__-import GHC.Real ( fromIntegral )-import GHC.Num-import GHC.Base-#endif--#ifdef __NHC__-import Foreign.C.Types ( CInt(..) )-#endif---- combined allocation and marshalling--- --------------------------------------- |Allocate a block of memory and marshal a value into it--- (the combination of 'malloc' and 'poke').--- The size of the area allocated is determined by the 'Foreign.Storable.sizeOf'--- method from the instance of 'Storable' for the appropriate type.------ The memory may be deallocated using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree' when no longer required.----new :: Storable a => a -> IO (Ptr a)-new val = - do - ptr <- malloc- poke ptr val- return ptr---- |@'with' val f@ executes the computation @f@, passing as argument--- a pointer to a temporarily allocated block of memory into which--- @val@ has been marshalled (the combination of 'alloca' and 'poke').------ The memory is freed when @f@ terminates (either normally or via an--- exception), so the pointer passed to @f@ must /not/ be used after this.----with :: Storable a => a -> (Ptr a -> IO b) -> IO b-with val f =- alloca $ \ptr -> do- poke ptr val- res <- f ptr- return res----- marshalling of Boolean values (non-zero corresponds to 'True')--- --------------------------------- |Convert a Haskell 'Bool' to its numeric representation----fromBool :: Num a => Bool -> a-fromBool False = 0-fromBool True = 1---- |Convert a Boolean in numeric representation to a Haskell value----toBool :: (Eq a, Num a) => a -> Bool-toBool = (/= 0)----- marshalling of Maybe values--- ------------------------------- |Allocate storage and marshal a storable value wrapped into a 'Maybe'------ * the 'nullPtr' is used to represent 'Nothing'----maybeNew :: ( a -> IO (Ptr b))- -> (Maybe a -> IO (Ptr b))-maybeNew = maybe (return nullPtr)---- |Converts a @withXXX@ combinator into one marshalling a value wrapped--- into a 'Maybe', using 'nullPtr' to represent 'Nothing'.----maybeWith :: ( a -> (Ptr b -> IO c) -> IO c) - -> (Maybe a -> (Ptr b -> IO c) -> IO c)-maybeWith = maybe ($ nullPtr)---- |Convert a peek combinator into a one returning 'Nothing' if applied to a--- 'nullPtr' ----maybePeek :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)-maybePeek peek ptr | ptr == nullPtr = return Nothing- | otherwise = do a <- peek ptr; return (Just a)----- marshalling lists of storable objects--- ----------------------------------------- |Replicates a @withXXX@ combinator over a list of objects, yielding a list of--- marshalled objects----withMany :: (a -> (b -> res) -> res) -- withXXX combinator for one object- -> [a] -- storable objects- -> ([b] -> res) -- action on list of marshalled obj.s- -> res-withMany _ [] f = f []-withMany withFoo (x:xs) f = withFoo x $ \x' ->- withMany withFoo xs (\xs' -> f (x':xs'))----- Haskellish interface to memcpy and memmove--- ---------------------------------------------- |Copies the given number of bytes from the second area (source) into the--- first (destination); the copied areas may /not/ overlap----copyBytes :: Ptr a -> Ptr a -> Int -> IO ()-copyBytes dest src size = do _ <- memcpy dest src (fromIntegral size)- return ()---- |Copies the given number of bytes from the second area (source) into the--- first (destination); the copied areas /may/ overlap----moveBytes :: Ptr a -> Ptr a -> Int -> IO ()-moveBytes dest src size = do _ <- memmove dest src (fromIntegral size)- return ()----- auxilliary routines--- ----------------------- |Basic C routines needed for memory copying----foreign import ccall unsafe "string.h" memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)-foreign import ccall unsafe "string.h" memmove :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)-
@@ -1,165 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , ForeignFunctionInterface- , MagicHash- , GeneralizedNewtypeDeriving- #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : Foreign.Ptr--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ This module provides typed pointers to foreign data. It is part--- of the Foreign Function Interface (FFI) and will normally be--- imported via the "Foreign" module.-----------------------------------------------------------------------------------module Foreign.Ptr (-- -- * Data pointers-- Ptr, -- data Ptr a- nullPtr, -- :: Ptr a- castPtr, -- :: Ptr a -> Ptr b- plusPtr, -- :: Ptr a -> Int -> Ptr b- alignPtr, -- :: Ptr a -> Int -> Ptr a- minusPtr, -- :: Ptr a -> Ptr b -> Int-- -- * Function pointers-- FunPtr, -- data FunPtr a- nullFunPtr, -- :: FunPtr a- castFunPtr, -- :: FunPtr a -> FunPtr b- castFunPtrToPtr, -- :: FunPtr a -> Ptr b- castPtrToFunPtr, -- :: Ptr a -> FunPtr b-- freeHaskellFunPtr, -- :: FunPtr a -> IO ()- -- Free the function pointer created by foreign export dynamic.--#ifndef __NHC__- -- * Integral types with lossless conversion to and from pointers- IntPtr,- ptrToIntPtr,- intPtrToPtr,- WordPtr,- ptrToWordPtr,- wordPtrToPtr-#endif- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Ptr-import GHC.Base-import GHC.Num-import GHC.Read-import GHC.Real-import GHC.Show-import GHC.Enum-import GHC.Word ( Word(..) )--import Data.Word-#else-import Control.Monad ( liftM )-import Foreign.C.Types-#endif--import Data.Bits-import Data.Typeable-import Foreign.Storable ( Storable(..) )--#ifdef __NHC__-import NHC.FFI- ( Ptr- , nullPtr- , castPtr- , plusPtr- , alignPtr- , minusPtr- , FunPtr- , nullFunPtr- , castFunPtr- , castFunPtrToPtr- , castPtrToFunPtr- , freeHaskellFunPtr- )-#endif--#ifdef __HUGS__-import Hugs.Ptr-#endif--#ifdef __GLASGOW_HASKELL__--- | Release the storage associated with the given 'FunPtr', which--- must have been obtained from a wrapper stub. This should be called--- whenever the return value from a foreign import wrapper function is--- no longer required; otherwise, the storage it uses will leak.-foreign import ccall unsafe "freeHaskellFunctionPtr"- freeHaskellFunPtr :: FunPtr a -> IO ()-#endif--#ifndef __NHC__-# include "HsBaseConfig.h"-# include "CTypes.h"--# ifdef __GLASGOW_HASKELL__--- | An unsigned integral type that can be losslessly converted to and from--- @Ptr@. This type is also compatible with the C99 type @uintptr_t@, and--- can be marshalled to and from that type safely.-INTEGRAL_TYPE(WordPtr,tyConWordPtr,"WordPtr",Word)- -- Word and Int are guaranteed pointer-sized in GHC---- | A signed integral type that can be losslessly converted to and from--- @Ptr@. This type is also compatible with the C99 type @intptr_t@, and--- can be marshalled to and from that type safely.-INTEGRAL_TYPE(IntPtr,tyConIntPtr,"IntPtr",Int)- -- Word and Int are guaranteed pointer-sized in GHC---- | casts a @Ptr@ to a @WordPtr@-ptrToWordPtr :: Ptr a -> WordPtr-ptrToWordPtr (Ptr a#) = WordPtr (W# (int2Word# (addr2Int# a#)))---- | casts a @WordPtr@ to a @Ptr@-wordPtrToPtr :: WordPtr -> Ptr a-wordPtrToPtr (WordPtr (W# w#)) = Ptr (int2Addr# (word2Int# w#))---- | casts a @Ptr@ to an @IntPtr@-ptrToIntPtr :: Ptr a -> IntPtr-ptrToIntPtr (Ptr a#) = IntPtr (I# (addr2Int# a#))---- | casts an @IntPtr@ to a @Ptr@-intPtrToPtr :: IntPtr -> Ptr a-intPtrToPtr (IntPtr (I# i#)) = Ptr (int2Addr# i#)--# else /* !__GLASGOW_HASKELL__ */--INTEGRAL_TYPE(WordPtr,tyConWordPtr,"WordPtr",CUIntPtr)-INTEGRAL_TYPE(IntPtr,tyConIntPtr,"IntPtr",CIntPtr)--{-# CFILES cbits/PrelIOUtils.c #-}--foreign import ccall unsafe "__hscore_to_uintptr"- ptrToWordPtr :: Ptr a -> WordPtr--foreign import ccall unsafe "__hscore_from_uintptr"- wordPtrToPtr :: WordPtr -> Ptr a--foreign import ccall unsafe "__hscore_to_intptr"- ptrToIntPtr :: Ptr a -> IntPtr--foreign import ccall unsafe "__hscore_from_intptr"- intPtrToPtr :: IntPtr -> Ptr a--# endif /* !__GLASGOW_HASKELL__ */-#endif /* !__NHC_ */-
@@ -1,40 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.Safe--- Copyright : (c) The FFI task force 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ A collection of data types, classes, and functions for interfacing--- with another programming language.------ Safe API Only.-----------------------------------------------------------------------------------module Foreign.Safe- ( module Data.Bits- , module Data.Int- , module Data.Word- , module Foreign.Ptr- , module Foreign.ForeignPtr.Safe- , module Foreign.StablePtr- , module Foreign.Storable- , module Foreign.Marshal.Safe- ) where--import Data.Bits-import Data.Int-import Data.Word-import Foreign.Ptr-import Foreign.ForeignPtr.Safe-import Foreign.StablePtr-import Foreign.Storable-import Foreign.Marshal.Safe-
@@ -1,64 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Foreign.StablePtr--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ This module is part of the Foreign Function Interface (FFI) and will usually--- be imported via the module "Foreign".------------------------------------------------------------------------------------module Foreign.StablePtr- ( -- * Stable references to Haskell values- StablePtr -- abstract- , newStablePtr -- :: a -> IO (StablePtr a)- , deRefStablePtr -- :: StablePtr a -> IO a- , freeStablePtr -- :: StablePtr a -> IO ()- , castStablePtrToPtr -- :: StablePtr a -> Ptr ()- , castPtrToStablePtr -- :: Ptr () -> StablePtr a- , -- ** The C-side interface-- -- $cinterface- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Stable-#endif--#ifdef __HUGS__-import Hugs.StablePtr-#endif--#ifdef __NHC__-import NHC.FFI- ( StablePtr- , newStablePtr- , deRefStablePtr- , freeStablePtr- , castStablePtrToPtr- , castPtrToStablePtr- )-#endif---- $cinterface------ The following definition is available to C programs inter-operating with--- Haskell code when including the header @HsFFI.h@.------ > typedef void *HsStablePtr; /* C representation of a StablePtr */------ Note that no assumptions may be made about the values representing stable--- pointers. In fact, they need not even be valid memory addresses. The only--- guarantee provided is that if they are passed back to Haskell land, the--- function 'deRefStablePtr' will be able to reconstruct the--- Haskell value referred to by the stable pointer.-
@@ -1,287 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ScopedTypeVariables #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE BangPatterns #-}-#endif---------------------------------------------------------------------------------- |--- Module : Foreign.Storable--- Copyright : (c) The FFI task force 2001--- License : see libraries/base/LICENSE--- --- Maintainer : ffi@haskell.org--- Stability : provisional--- Portability : portable------ The module "Foreign.Storable" provides most elementary support for--- marshalling and is part of the language-independent portion of the--- Foreign Function Interface (FFI), and will normally be imported via--- the "Foreign" module.-----------------------------------------------------------------------------------module Foreign.Storable- ( Storable(- sizeOf, -- :: a -> Int- alignment, -- :: a -> Int- peekElemOff, -- :: Ptr a -> Int -> IO a- pokeElemOff, -- :: Ptr a -> Int -> a -> IO ()- peekByteOff, -- :: Ptr b -> Int -> IO a- pokeByteOff, -- :: Ptr b -> Int -> a -> IO ()- peek, -- :: Ptr a -> IO a- poke) -- :: Ptr a -> a -> IO ()- ) where---#ifdef __NHC__-import NHC.FFI (Storable(..),Ptr,FunPtr,StablePtr- ,Int8,Int16,Int32,Int64,Word8,Word16,Word32,Word64)-#else--import Control.Monad ( liftM )--#include "MachDeps.h"-#include "HsBaseConfig.h"--#ifdef __GLASGOW_HASKELL__-import GHC.Storable-import GHC.Stable ( StablePtr )-import GHC.IO() -- Instance Monad IO-import GHC.Num-import GHC.Int-import GHC.Word-import GHC.Ptr-import GHC.Err-import GHC.Base-import GHC.Fingerprint.Type-import Data.Bits-import GHC.Real-#else-import Data.Int-import Data.Word-import Foreign.StablePtr-#endif--#ifdef __HUGS__-import Hugs.Prelude-import Hugs.Ptr-import Hugs.Storable-#endif--{- |-The member functions of this class facilitate writing values of-primitive types to raw memory (which may have been allocated with the-above mentioned routines) and reading values from blocks of raw-memory. The class, furthermore, includes support for computing the-storage requirements and alignment restrictions of storable types.--Memory addresses are represented as values of type @'Ptr' a@, for some-@a@ which is an instance of class 'Storable'. The type argument to-'Ptr' helps provide some valuable type safety in FFI code (you can\'t-mix pointers of different types without an explicit cast), while-helping the Haskell type system figure out which marshalling method is-needed for a given pointer.--All marshalling between Haskell and a foreign language ultimately-boils down to translating Haskell data structures into the binary-representation of a corresponding data structure of the foreign-language and vice versa. To code this marshalling in Haskell, it is-necessary to manipulate primitive data types stored in unstructured-memory blocks. The class 'Storable' facilitates this manipulation on-all types for which it is instantiated, which are the standard basic-types of Haskell, the fixed size @Int@ types ('Int8', 'Int16',-'Int32', 'Int64'), the fixed size @Word@ types ('Word8', 'Word16',-'Word32', 'Word64'), 'StablePtr', all types from "Foreign.C.Types",-as well as 'Ptr'.--Minimal complete definition: 'sizeOf', 'alignment', one of 'peek',-'peekElemOff' and 'peekByteOff', and one of 'poke', 'pokeElemOff' and-'pokeByteOff'.--}--class Storable a where-- sizeOf :: a -> Int- -- ^ Computes the storage requirements (in bytes) of the argument.- -- The value of the argument is not used.-- alignment :: a -> Int- -- ^ Computes the alignment constraint of the argument. An- -- alignment constraint @x@ is fulfilled by any address divisible- -- by @x@. The value of the argument is not used.-- peekElemOff :: Ptr a -> Int -> IO a- -- ^ Read a value from a memory area regarded as an array- -- of values of the same kind. The first argument specifies- -- the start address of the array and the second the index into- -- the array (the first element of the array has index- -- @0@). The following equality holds,- -- - -- > peekElemOff addr idx = IOExts.fixIO $ \result ->- -- > peek (addr `plusPtr` (idx * sizeOf result))- --- -- Note that this is only a specification, not- -- necessarily the concrete implementation of the- -- function.-- pokeElemOff :: Ptr a -> Int -> a -> IO ()- -- ^ Write a value to a memory area regarded as an array of- -- values of the same kind. The following equality holds:- -- - -- > pokeElemOff addr idx x = - -- > poke (addr `plusPtr` (idx * sizeOf x)) x-- peekByteOff :: Ptr b -> Int -> IO a- -- ^ Read a value from a memory location given by a base- -- address and offset. The following equality holds:- --- -- > peekByteOff addr off = peek (addr `plusPtr` off)-- pokeByteOff :: Ptr b -> Int -> a -> IO ()- -- ^ Write a value to a memory location given by a base- -- address and offset. The following equality holds:- --- -- > pokeByteOff addr off x = poke (addr `plusPtr` off) x- - peek :: Ptr a -> IO a- -- ^ Read a value from the given memory location.- --- -- Note that the peek and poke functions might require properly- -- aligned addresses to function correctly. This is architecture- -- dependent; thus, portable code should ensure that when peeking or- -- poking values of some type @a@, the alignment- -- constraint for @a@, as given by the function- -- 'alignment' is fulfilled.-- poke :: Ptr a -> a -> IO ()- -- ^ Write the given value to the given memory location. Alignment- -- restrictions might apply; see 'peek'.- - -- circular default instances-#ifdef __GLASGOW_HASKELL__- peekElemOff = peekElemOff_ undefined- where peekElemOff_ :: a -> Ptr a -> Int -> IO a- peekElemOff_ undef ptr off = peekByteOff ptr (off * sizeOf undef)-#else- peekElemOff ptr off = peekByteOff ptr (off * sizeOfPtr ptr undefined)-#endif- pokeElemOff ptr off val = pokeByteOff ptr (off * sizeOf val) val-- peekByteOff ptr off = peek (ptr `plusPtr` off)- pokeByteOff ptr off = poke (ptr `plusPtr` off)-- peek ptr = peekElemOff ptr 0- poke ptr = pokeElemOff ptr 0--#ifndef __GLASGOW_HASKELL__-sizeOfPtr :: Storable a => Ptr a -> a -> Int-sizeOfPtr px x = sizeOf x-#endif---- System-dependent, but rather obvious instances--instance Storable Bool where- sizeOf _ = sizeOf (undefined::HTYPE_INT)- alignment _ = alignment (undefined::HTYPE_INT)- peekElemOff p i = liftM (/= (0::HTYPE_INT)) $ peekElemOff (castPtr p) i- pokeElemOff p i x = pokeElemOff (castPtr p) i (if x then 1 else 0::HTYPE_INT)--#define STORABLE(T,size,align,read,write) \-instance Storable (T) where { \- sizeOf _ = size; \- alignment _ = align; \- peekElemOff = read; \- pokeElemOff = write }--#ifdef __GLASGOW_HASKELL__-STORABLE(Char,SIZEOF_INT32,ALIGNMENT_INT32,- readWideCharOffPtr,writeWideCharOffPtr)-#elif defined(__HUGS__)-STORABLE(Char,SIZEOF_HSCHAR,ALIGNMENT_HSCHAR,- readCharOffPtr,writeCharOffPtr)-#endif--STORABLE(Int,SIZEOF_HSINT,ALIGNMENT_HSINT,- readIntOffPtr,writeIntOffPtr)--#ifndef __NHC__-STORABLE(Word,SIZEOF_HSWORD,ALIGNMENT_HSWORD,- readWordOffPtr,writeWordOffPtr)-#endif--STORABLE((Ptr a),SIZEOF_HSPTR,ALIGNMENT_HSPTR,- readPtrOffPtr,writePtrOffPtr)--STORABLE((FunPtr a),SIZEOF_HSFUNPTR,ALIGNMENT_HSFUNPTR,- readFunPtrOffPtr,writeFunPtrOffPtr)--STORABLE((StablePtr a),SIZEOF_HSSTABLEPTR,ALIGNMENT_HSSTABLEPTR,- readStablePtrOffPtr,writeStablePtrOffPtr)--STORABLE(Float,SIZEOF_HSFLOAT,ALIGNMENT_HSFLOAT,- readFloatOffPtr,writeFloatOffPtr)--STORABLE(Double,SIZEOF_HSDOUBLE,ALIGNMENT_HSDOUBLE,- readDoubleOffPtr,writeDoubleOffPtr)--STORABLE(Word8,SIZEOF_WORD8,ALIGNMENT_WORD8,- readWord8OffPtr,writeWord8OffPtr)--STORABLE(Word16,SIZEOF_WORD16,ALIGNMENT_WORD16,- readWord16OffPtr,writeWord16OffPtr)--STORABLE(Word32,SIZEOF_WORD32,ALIGNMENT_WORD32,- readWord32OffPtr,writeWord32OffPtr)--STORABLE(Word64,SIZEOF_WORD64,ALIGNMENT_WORD64,- readWord64OffPtr,writeWord64OffPtr)--STORABLE(Int8,SIZEOF_INT8,ALIGNMENT_INT8,- readInt8OffPtr,writeInt8OffPtr)--STORABLE(Int16,SIZEOF_INT16,ALIGNMENT_INT16,- readInt16OffPtr,writeInt16OffPtr)--STORABLE(Int32,SIZEOF_INT32,ALIGNMENT_INT32,- readInt32OffPtr,writeInt32OffPtr)--STORABLE(Int64,SIZEOF_INT64,ALIGNMENT_INT64,- readInt64OffPtr,writeInt64OffPtr)--#endif---- XXX: here to avoid orphan instance in GHC.Fingerprint-#ifdef __GLASGOW_HASKELL__-instance Storable Fingerprint where- sizeOf _ = 16- alignment _ = 8- peek = peekFingerprint- poke = pokeFingerprint---- peek/poke in fixed BIG-endian 128-bit format-peekFingerprint :: Ptr Fingerprint -> IO Fingerprint-peekFingerprint p0 = do- let peekW64 :: Ptr Word8 -> Int -> Word64 -> IO Word64- peekW64 _ 0 !i = return i- peekW64 !p !n !i = do- w8 <- peek p- peekW64 (p `plusPtr` 1) (n-1) - ((i `shiftL` 8) .|. fromIntegral w8)-- high <- peekW64 (castPtr p0) 8 0- low <- peekW64 (castPtr p0 `plusPtr` 8) 8 0- return (Fingerprint high low)--pokeFingerprint :: Ptr Fingerprint -> Fingerprint -> IO ()-pokeFingerprint p0 (Fingerprint high low) = do- let pokeW64 :: Ptr Word8 -> Int -> Word64 -> IO ()- pokeW64 _ 0 _ = return ()- pokeW64 p !n !i = do- pokeElemOff p (n-1) (fromIntegral i)- pokeW64 p (n-1) (i `shiftR` 8)-- pokeW64 (castPtr p0) 8 high- pokeW64 (castPtr p0 `plusPtr` 8) 8 low-#endif-
@@ -1,844 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude, NoBangPatterns, MagicHash, UnboxedTuples #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Arr--- Copyright : (c) The University of Glasgow, 1994-2000--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ GHC\'s array implementation.--- ---------------------------------------------------------------------------------- #hide-module GHC.Arr (- Ix(..), Array(..), STArray(..),-- indexError, hopelessIndexError,- arrEleBottom, array, listArray,- (!), safeRangeSize, negRange, safeIndex, badSafeIndex,- bounds, numElements, numElementsSTArray, indices, elems,- assocs, accumArray, adjust, (//), accum,- amap, ixmap,- eqArray, cmpArray, cmpIntArray,- newSTArray, boundsSTArray,- readSTArray, writeSTArray,- freezeSTArray, thawSTArray,-- -- * Unsafe operations- fill, done,- unsafeArray, unsafeArray',- lessSafeIndex, unsafeAt, unsafeReplace,- unsafeAccumArray, unsafeAccumArray', unsafeAccum,- unsafeReadSTArray, unsafeWriteSTArray,- unsafeFreezeSTArray, unsafeThawSTArray,- ) where--import GHC.Enum-import GHC.Num-import GHC.ST-import GHC.Base-import GHC.List-import GHC.Show--infixl 9 !, //--default ()-\end{code}---%*********************************************************-%* *-\subsection{The @Ix@ class}-%* *-%*********************************************************--\begin{code}--- | The 'Ix' class is used to map a contiguous subrange of values in--- a type onto integers. It is used primarily for array indexing--- (see the array package).------ The first argument @(l,u)@ of each of these operations is a pair--- specifying the lower and upper bounds of a contiguous subrange of values.------ An implementation is entitled to assume the following laws about these--- operations:------ * @'inRange' (l,u) i == 'elem' i ('range' (l,u))@ @ @------ * @'range' (l,u) '!!' 'index' (l,u) i == i@, when @'inRange' (l,u) i@------ * @'map' ('index' (l,u)) ('range' (l,u))) == [0..'rangeSize' (l,u)-1]@ @ @------ * @'rangeSize' (l,u) == 'length' ('range' (l,u))@ @ @------ Minimal complete instance: 'range', 'index' and 'inRange'.----class (Ord a) => Ix a where- -- | The list of values in the subrange defined by a bounding pair.- range :: (a,a) -> [a]- -- | The position of a subscript in the subrange.- index :: (a,a) -> a -> Int- -- | Like 'index', but without checking that the value is in range.- unsafeIndex :: (a,a) -> a -> Int- -- | Returns 'True' the given subscript lies in the range defined- -- the bounding pair.- inRange :: (a,a) -> a -> Bool- -- | The size of the subrange defined by a bounding pair.- rangeSize :: (a,a) -> Int- -- | like 'rangeSize', but without checking that the upper bound is- -- in range.- unsafeRangeSize :: (a,a) -> Int-- -- Must specify one of index, unsafeIndex-- -- 'index' is typically over-ridden in instances, with essentially- -- the same code, but using indexError instead of hopelessIndexError- -- Reason: we have 'Show' at the instances- {-# INLINE index #-} -- See Note [Inlining index]- index b i | inRange b i = unsafeIndex b i - | otherwise = hopelessIndexError-- unsafeIndex b i = index b i-- rangeSize b@(_l,h) | inRange b h = unsafeIndex b h + 1- | otherwise = 0 -- This case is only here to- -- check for an empty range- -- NB: replacing (inRange b h) by (l <= h) fails for- -- tuples. E.g. (1,2) <= (2,1) but the range is empty-- unsafeRangeSize b@(_l,h) = unsafeIndex b h + 1-\end{code}--Note that the following is NOT right- rangeSize (l,h) | l <= h = index b h + 1- | otherwise = 0--Because it might be the case that l<h, but the range-is nevertheless empty. Consider- ((1,2),(2,1))-Here l<h, but the second index ranges from 2..1 and-hence is empty--%*********************************************************-%* *-\subsection{Instances of @Ix@}-%* *-%*********************************************************--Note [Inlining index]-~~~~~~~~~~~~~~~~~~~~~-We inline the 'index' operation, -- * Partly because it generates much faster code - (although bigger); see Trac #1216-- * Partly because it exposes the bounds checks to the simplifier which- might help a big.--If you make a per-instance index method, you may consider inlining it.--Note [Double bounds-checking of index values]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When you index an array, a!x, there are two possible bounds checks we might make:-- (A) Check that (inRange (bounds a) x) holds. -- (A) is checked in the method for 'index'-- (B) Check that (index (bounds a) x) lies in the range 0..n, - where n is the size of the underlying array-- (B) is checked in the top-level function (!), in safeIndex.--Of course it *should* be the case that (A) holds iff (B) holds, but that -is a property of the particular instances of index, bounds, and inRange,-so GHC cannot guarantee it.-- * If you do (A) and not (B), then you might get a seg-fault, - by indexing at some bizarre location. Trac #1610-- * If you do (B) but not (A), you may get no complaint when you index- an array out of its semantic bounds. Trac #2120--At various times we have had (A) and not (B), or (B) and not (A); both-led to complaints. So now we implement *both* checks (Trac #2669).--For 1-d, 2-d, and 3-d arrays of Int we have specialised instances to avoid this.--Note [Out-of-bounds error messages]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The default method for 'index' generates hoplelessIndexError, because-Ix doesn't have Show as a superclass. For particular base types we-can do better, so we override the default method for index.--\begin{code}--- Abstract these errors from the relevant index functions so that--- the guts of the function will be small enough to inline.--{-# NOINLINE indexError #-}-indexError :: Show a => (a,a) -> a -> String -> b-indexError rng i tp- = error (showString "Ix{" . showString tp . showString "}.index: Index " .- showParen True (showsPrec 0 i) .- showString " out of range " $- showParen True (showsPrec 0 rng) "")--hopelessIndexError :: Int -- Try to use 'indexError' instead!-hopelessIndexError = error "Error in array index"-------------------------------------------------------------------------instance Ix Char where- {-# INLINE range #-}- range (m,n) = [m..n]-- {-# INLINE unsafeIndex #-}- unsafeIndex (m,_n) i = fromEnum i - fromEnum m-- {-# INLINE index #-} -- See Note [Out-of-bounds error messages]- -- and Note [Inlining index]- index b i | inRange b i = unsafeIndex b i- | otherwise = indexError b i "Char"-- inRange (m,n) i = m <= i && i <= n-------------------------------------------------------------------------instance Ix Int where- {-# INLINE range #-}- -- The INLINE stops the build in the RHS from getting inlined,- -- so that callers can fuse with the result of range- range (m,n) = [m..n]-- {-# INLINE unsafeIndex #-}- unsafeIndex (m,_n) i = i - m-- {-# INLINE index #-} -- See Note [Out-of-bounds error messages]- -- and Note [Inlining index]- index b i | inRange b i = unsafeIndex b i- | otherwise = indexError b i "Int"-- {-# INLINE inRange #-}- inRange (I# m,I# n) (I# i) = m <=# i && i <=# n-------------------------------------------------------------------------instance Ix Integer where- {-# INLINE range #-}- range (m,n) = [m..n]-- {-# INLINE unsafeIndex #-}- unsafeIndex (m,_n) i = fromInteger (i - m)-- {-# INLINE index #-} -- See Note [Out-of-bounds error messages]- -- and Note [Inlining index]- index b i | inRange b i = unsafeIndex b i- | otherwise = indexError b i "Integer"-- inRange (m,n) i = m <= i && i <= n-------------------------------------------------------------------------instance Ix Bool where -- as derived- {-# INLINE range #-}- range (m,n) = [m..n]-- {-# INLINE unsafeIndex #-}- unsafeIndex (l,_) i = fromEnum i - fromEnum l-- {-# INLINE index #-} -- See Note [Out-of-bounds error messages]- -- and Note [Inlining index]- index b i | inRange b i = unsafeIndex b i- | otherwise = indexError b i "Bool"-- inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u-------------------------------------------------------------------------instance Ix Ordering where -- as derived- {-# INLINE range #-}- range (m,n) = [m..n]-- {-# INLINE unsafeIndex #-}- unsafeIndex (l,_) i = fromEnum i - fromEnum l-- {-# INLINE index #-} -- See Note [Out-of-bounds error messages]- -- and Note [Inlining index]- index b i | inRange b i = unsafeIndex b i- | otherwise = indexError b i "Ordering"-- inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u-------------------------------------------------------------------------instance Ix () where- {-# INLINE range #-}- range ((), ()) = [()]- {-# INLINE unsafeIndex #-}- unsafeIndex ((), ()) () = 0- {-# INLINE inRange #-}- inRange ((), ()) () = True-- {-# INLINE index #-} -- See Note [Inlining index]- index b i = unsafeIndex b i-------------------------------------------------------------------------instance (Ix a, Ix b) => Ix (a, b) where -- as derived- {-# SPECIALISE instance Ix (Int,Int) #-}-- {-# INLINE range #-}- range ((l1,l2),(u1,u2)) =- [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]-- {-# INLINE unsafeIndex #-}- unsafeIndex ((l1,l2),(u1,u2)) (i1,i2) =- unsafeIndex (l1,u1) i1 * unsafeRangeSize (l2,u2) + unsafeIndex (l2,u2) i2-- {-# INLINE inRange #-}- inRange ((l1,l2),(u1,u2)) (i1,i2) =- inRange (l1,u1) i1 && inRange (l2,u2) i2-- -- Default method for index-------------------------------------------------------------------------instance (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3) where- {-# SPECIALISE instance Ix (Int,Int,Int) #-}-- range ((l1,l2,l3),(u1,u2,u3)) =- [(i1,i2,i3) | i1 <- range (l1,u1),- i2 <- range (l2,u2),- i3 <- range (l3,u3)]-- unsafeIndex ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =- unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (- unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (- unsafeIndex (l1,u1) i1))-- inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =- inRange (l1,u1) i1 && inRange (l2,u2) i2 &&- inRange (l3,u3) i3-- -- Default method for index-------------------------------------------------------------------------instance (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4) where- range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =- [(i1,i2,i3,i4) | i1 <- range (l1,u1),- i2 <- range (l2,u2),- i3 <- range (l3,u3),- i4 <- range (l4,u4)]-- unsafeIndex ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =- unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (- unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (- unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (- unsafeIndex (l1,u1) i1)))-- inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =- inRange (l1,u1) i1 && inRange (l2,u2) i2 &&- inRange (l3,u3) i3 && inRange (l4,u4) i4-- -- Default method for index--instance (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5) where- range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =- [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),- i2 <- range (l2,u2),- i3 <- range (l3,u3),- i4 <- range (l4,u4),- i5 <- range (l5,u5)]-- unsafeIndex ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =- unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (- unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (- unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (- unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (- unsafeIndex (l1,u1) i1))))-- inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =- inRange (l1,u1) i1 && inRange (l2,u2) i2 &&- inRange (l3,u3) i3 && inRange (l4,u4) i4 && - inRange (l5,u5) i5-- -- Default method for index-\end{code}--%*********************************************************-%* *-\subsection{The @Array@ types}-%* *-%*********************************************************--\begin{code}--- | The type of immutable non-strict (boxed) arrays--- with indices in @i@ and elements in @e@.-data Array i e- = Array !i -- the lower bound, l- !i -- the upper bound, u- !Int -- a cache of (rangeSize (l,u))- -- used to make sure an index is- -- really in range- (Array# e) -- The actual elements---- | Mutable, boxed, non-strict arrays in the 'ST' monad. The type--- arguments are as follows:------ * @s@: the state variable argument for the 'ST' type------ * @i@: the index type of the array (should be an instance of 'Ix')------ * @e@: the element type of the array.----data STArray s i e- = STArray !i -- the lower bound, l- !i -- the upper bound, u- !Int -- a cache of (rangeSize (l,u))- -- used to make sure an index is- -- really in range- (MutableArray# s e) -- The actual elements- -- No Ix context for STArray. They are stupid,- -- and force an Ix context on the equality instance.---- Just pointer equality on mutable arrays:-instance Eq (STArray s i e) where- STArray _ _ _ arr1# == STArray _ _ _ arr2# =- sameMutableArray# arr1# arr2#-\end{code}---%*********************************************************-%* *-\subsection{Operations on immutable arrays}-%* *-%*********************************************************--\begin{code}-{-# NOINLINE arrEleBottom #-}-arrEleBottom :: a-arrEleBottom = error "(Array.!): undefined array element"---- | Construct an array with the specified bounds and containing values--- for given indices within these bounds.------ The array is undefined (i.e. bottom) if any index in the list is--- out of bounds. The Haskell 98 Report further specifies that if any--- two associations in the list have the same index, the value at that--- index is undefined (i.e. bottom). However in GHC's implementation,--- the value at such an index is the value part of the last association--- with that index in the list.------ Because the indices must be checked for these errors, 'array' is--- strict in the bounds argument and in the indices of the association--- list, but non-strict in the values. Thus, recurrences such as the--- following are possible:------ > a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i <- [2..100]])------ Not every index within the bounds of the array need appear in the--- association list, but the values associated with indices that do not--- appear will be undefined (i.e. bottom).------ If, in any dimension, the lower bound is greater than the upper bound,--- then the array is legal, but empty. Indexing an empty array always--- gives an array-bounds error, but 'bounds' still yields the bounds--- with which the array was constructed.-{-# INLINE array #-}-array :: Ix i- => (i,i) -- ^ a pair of /bounds/, each of the index type- -- of the array. These bounds are the lowest and- -- highest indices in the array, in that order.- -- For example, a one-origin vector of length- -- '10' has bounds '(1,10)', and a one-origin '10'- -- by '10' matrix has bounds '((1,1),(10,10))'.- -> [(i, e)] -- ^ a list of /associations/ of the form- -- (/index/, /value/). Typically, this list will- -- be expressed as a comprehension. An- -- association '(i, x)' defines the value of- -- the array at index 'i' to be 'x'.- -> Array i e-array (l,u) ies- = let n = safeRangeSize (l,u)- in unsafeArray' (l,u) n- [(safeIndex (l,u) n i, e) | (i, e) <- ies]--{-# INLINE unsafeArray #-}-unsafeArray :: Ix i => (i,i) -> [(Int, e)] -> Array i e-unsafeArray b ies = unsafeArray' b (rangeSize b) ies--{-# INLINE unsafeArray' #-}-unsafeArray' :: Ix i => (i,i) -> Int -> [(Int, e)] -> Array i e-unsafeArray' (l,u) n@(I# n#) ies = runST (ST $ \s1# ->- case newArray# n# arrEleBottom s1# of- (# s2#, marr# #) ->- foldr (fill marr#) (done l u n marr#) ies s2#)--{-# INLINE fill #-}-fill :: MutableArray# s e -> (Int, e) -> STRep s a -> STRep s a--- NB: put the \s after the "=" so that 'fill' --- inlines when applied to three args -fill marr# (I# i#, e) next - = \s1# -> case writeArray# marr# i# e s1# of - s2# -> next s2# --{-# INLINE done #-}-done :: Ix i => i -> i -> Int -> MutableArray# s e -> STRep s (Array i e)--- See NB on 'fill'-done l u n marr# - = \s1# -> case unsafeFreezeArray# marr# s1# of- (# s2#, arr# #) -> (# s2#, Array l u n arr# #)---- This is inefficient and I'm not sure why:--- listArray (l,u) es = unsafeArray (l,u) (zip [0 .. rangeSize (l,u) - 1] es)--- The code below is better. It still doesn't enable foldr/build--- transformation on the list of elements; I guess it's impossible--- using mechanisms currently available.---- | Construct an array from a pair of bounds and a list of values in--- index order.-{-# INLINE listArray #-}-listArray :: Ix i => (i,i) -> [e] -> Array i e-listArray (l,u) es = runST (ST $ \s1# ->- case safeRangeSize (l,u) of { n@(I# n#) ->- case newArray# n# arrEleBottom s1# of { (# s2#, marr# #) ->- let fillFromList i# xs s3# | i# ==# n# = s3#- | otherwise = case xs of- [] -> s3#- y:ys -> case writeArray# marr# i# y s3# of { s4# ->- fillFromList (i# +# 1#) ys s4# } in- case fillFromList 0# es s2# of { s3# ->- done l u n marr# s3# }}})---- | The value at the given index in an array.-{-# INLINE (!) #-}-(!) :: Ix i => Array i e -> i -> e-arr@(Array l u n _) ! i = unsafeAt arr $ safeIndex (l,u) n i--{-# INLINE safeRangeSize #-}-safeRangeSize :: Ix i => (i, i) -> Int-safeRangeSize (l,u) = let r = rangeSize (l, u)- in if r < 0 then negRange- else r---- Don't inline this error message everywhere!!-negRange :: Int -- Uninformative, but Ix does not provide Show-negRange = error "Negative range size"--{-# INLINE[1] safeIndex #-}--- See Note [Double bounds-checking of index values]--- Inline *after* (!) so the rules can fire-safeIndex :: Ix i => (i, i) -> Int -> i -> Int-safeIndex (l,u) n i = let i' = index (l,u) i- in if (0 <= i') && (i' < n)- then i'- else badSafeIndex i' n---- See Note [Double bounds-checking of index values]-{-# RULES-"safeIndex/I" safeIndex = lessSafeIndex :: (Int,Int) -> Int -> Int -> Int-"safeIndex/(I,I)" safeIndex = lessSafeIndex :: ((Int,Int),(Int,Int)) -> Int -> (Int,Int) -> Int-"safeIndex/(I,I,I)" safeIndex = lessSafeIndex :: ((Int,Int,Int),(Int,Int,Int)) -> Int -> (Int,Int,Int) -> Int- #-}--lessSafeIndex :: Ix i => (i, i) -> Int -> i -> Int--- See Note [Double bounds-checking of index values]--- Do only (A), the semantic check-lessSafeIndex (l,u) _ i = index (l,u) i ---- Don't inline this long error message everywhere!!-badSafeIndex :: Int -> Int -> Int-badSafeIndex i' n = error ("Error in array index; " ++ show i' ++- " not in range [0.." ++ show n ++ ")")--{-# INLINE unsafeAt #-}-unsafeAt :: Ix i => Array i e -> Int -> e-unsafeAt (Array _ _ _ arr#) (I# i#) =- case indexArray# arr# i# of (# e #) -> e---- | The bounds with which an array was constructed.-{-# INLINE bounds #-}-bounds :: Ix i => Array i e -> (i,i)-bounds (Array l u _ _) = (l,u)---- | The number of elements in the array.-{-# INLINE numElements #-}-numElements :: Ix i => Array i e -> Int-numElements (Array _ _ n _) = n---- | The list of indices of an array in ascending order.-{-# INLINE indices #-}-indices :: Ix i => Array i e -> [i]-indices (Array l u _ _) = range (l,u)---- | The list of elements of an array in index order.-{-# INLINE elems #-}-elems :: Ix i => Array i e -> [e]-elems arr@(Array _ _ n _) =- [unsafeAt arr i | i <- [0 .. n - 1]]---- | The list of associations of an array in index order.-{-# INLINE assocs #-}-assocs :: Ix i => Array i e -> [(i, e)]-assocs arr@(Array l u _ _) =- [(i, arr ! i) | i <- range (l,u)]---- | The 'accumArray' function deals with repeated indices in the association--- list using an /accumulating function/ which combines the values of--- associations with the same index.--- For example, given a list of values of some index type, @hist@--- produces a histogram of the number of occurrences of each index within--- a specified range:------ > hist :: (Ix a, Num b) => (a,a) -> [a] -> Array a b--- > hist bnds is = accumArray (+) 0 bnds [(i, 1) | i<-is, inRange bnds i]------ If the accumulating function is strict, then 'accumArray' is strict in--- the values, as well as the indices, in the association list. Thus,--- unlike ordinary arrays built with 'array', accumulated arrays should--- not in general be recursive.-{-# INLINE accumArray #-}-accumArray :: Ix i- => (e -> a -> e) -- ^ accumulating function- -> e -- ^ initial value- -> (i,i) -- ^ bounds of the array- -> [(i, a)] -- ^ association list- -> Array i e-accumArray f initial (l,u) ies =- let n = safeRangeSize (l,u)- in unsafeAccumArray' f initial (l,u) n- [(safeIndex (l,u) n i, e) | (i, e) <- ies]--{-# INLINE unsafeAccumArray #-}-unsafeAccumArray :: Ix i => (e -> a -> e) -> e -> (i,i) -> [(Int, a)] -> Array i e-unsafeAccumArray f initial b ies = unsafeAccumArray' f initial b (rangeSize b) ies--{-# INLINE unsafeAccumArray' #-}-unsafeAccumArray' :: Ix i => (e -> a -> e) -> e -> (i,i) -> Int -> [(Int, a)] -> Array i e-unsafeAccumArray' f initial (l,u) n@(I# n#) ies = runST (ST $ \s1# ->- case newArray# n# initial s1# of { (# s2#, marr# #) ->- foldr (adjust f marr#) (done l u n marr#) ies s2# })--{-# INLINE adjust #-}-adjust :: (e -> a -> e) -> MutableArray# s e -> (Int, a) -> STRep s b -> STRep s b--- See NB on 'fill'-adjust f marr# (I# i#, new) next- = \s1# -> case readArray# marr# i# s1# of- (# s2#, old #) ->- case writeArray# marr# i# (f old new) s2# of- s3# -> next s3#---- | Constructs an array identical to the first argument except that it has--- been updated by the associations in the right argument.--- For example, if @m@ is a 1-origin, @n@ by @n@ matrix, then------ > m//[((i,i), 0) | i <- [1..n]]------ is the same matrix, except with the diagonal zeroed.------ Repeated indices in the association list are handled as for 'array':--- Haskell 98 specifies that the resulting array is undefined (i.e. bottom),--- but GHC's implementation uses the last association for each index.-{-# INLINE (//) #-}-(//) :: Ix i => Array i e -> [(i, e)] -> Array i e-arr@(Array l u n _) // ies =- unsafeReplace arr [(safeIndex (l,u) n i, e) | (i, e) <- ies]--{-# INLINE unsafeReplace #-}-unsafeReplace :: Ix i => Array i e -> [(Int, e)] -> Array i e-unsafeReplace arr ies = runST (do- STArray l u n marr# <- thawSTArray arr- ST (foldr (fill marr#) (done l u n marr#) ies))---- | @'accum' f@ takes an array and an association list and accumulates--- pairs from the list into the array with the accumulating function @f@.--- Thus 'accumArray' can be defined using 'accum':------ > accumArray f z b = accum f (array b [(i, z) | i <- range b])----{-# INLINE accum #-}-accum :: Ix i => (e -> a -> e) -> Array i e -> [(i, a)] -> Array i e-accum f arr@(Array l u n _) ies =- unsafeAccum f arr [(safeIndex (l,u) n i, e) | (i, e) <- ies]--{-# INLINE unsafeAccum #-}-unsafeAccum :: Ix i => (e -> a -> e) -> Array i e -> [(Int, a)] -> Array i e-unsafeAccum f arr ies = runST (do- STArray l u n marr# <- thawSTArray arr- ST (foldr (adjust f marr#) (done l u n marr#) ies))--{-# INLINE amap #-}-amap :: Ix i => (a -> b) -> Array i a -> Array i b-amap f arr@(Array l u n _) =- unsafeArray' (l,u) n [(i, f (unsafeAt arr i)) | i <- [0 .. n - 1]]---- | 'ixmap' allows for transformations on array indices.--- It may be thought of as providing function composition on the right--- with the mapping that the original array embodies.------ A similar transformation of array values may be achieved using 'fmap'--- from the 'Array' instance of the 'Functor' class.-{-# INLINE ixmap #-}-ixmap :: (Ix i, Ix j) => (i,i) -> (i -> j) -> Array j e -> Array i e-ixmap (l,u) f arr =- array (l,u) [(i, arr ! f i) | i <- range (l,u)]--{-# INLINE eqArray #-}-eqArray :: (Ix i, Eq e) => Array i e -> Array i e -> Bool-eqArray arr1@(Array l1 u1 n1 _) arr2@(Array l2 u2 n2 _) =- if n1 == 0 then n2 == 0 else- l1 == l2 && u1 == u2 &&- and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. n1 - 1]]--{-# INLINE cmpArray #-}-cmpArray :: (Ix i, Ord e) => Array i e -> Array i e -> Ordering-cmpArray arr1 arr2 = compare (assocs arr1) (assocs arr2)--{-# INLINE cmpIntArray #-}-cmpIntArray :: Ord e => Array Int e -> Array Int e -> Ordering-cmpIntArray arr1@(Array l1 u1 n1 _) arr2@(Array l2 u2 n2 _) =- if n1 == 0 then- if n2 == 0 then EQ else LT- else if n2 == 0 then GT- else case compare l1 l2 of- EQ -> foldr cmp (compare u1 u2) [0 .. (n1 `min` n2) - 1]- other -> other- where- cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of- EQ -> rest- other -> other--{-# RULES "cmpArray/Int" cmpArray = cmpIntArray #-}-\end{code}---%*********************************************************-%* *-\subsection{Array instances}-%* *-%*********************************************************--\begin{code}-instance Ix i => Functor (Array i) where- fmap = amap--instance (Ix i, Eq e) => Eq (Array i e) where- (==) = eqArray--instance (Ix i, Ord e) => Ord (Array i e) where- compare = cmpArray--instance (Ix a, Show a, Show b) => Show (Array a b) where- showsPrec p a =- showParen (p > appPrec) $- showString "array " .- showsPrec appPrec1 (bounds a) .- showChar ' ' .- showsPrec appPrec1 (assocs a)- -- Precedence of 'array' is the precedence of application---- The Read instance is in GHC.Read-\end{code}---%*********************************************************-%* *-\subsection{Operations on mutable arrays}-%* *-%*********************************************************--Idle ADR question: What's the tradeoff here between flattening these-datatypes into @STArray ix ix (MutableArray# s elt)@ and using-it as is? As I see it, the former uses slightly less heap and-provides faster access to the individual parts of the bounds while the-code used has the benefit of providing a ready-made @(lo, hi)@ pair as-required by many array-related functions. Which wins? Is the-difference significant (probably not).--Idle AJG answer: When I looked at the outputted code (though it was 2-years ago) it seems like you often needed the tuple, and we build-it frequently. Now we've got the overloading specialiser things-might be different, though.--\begin{code}-{-# INLINE newSTArray #-}-newSTArray :: Ix i => (i,i) -> e -> ST s (STArray s i e)-newSTArray (l,u) initial = ST $ \s1# ->- case safeRangeSize (l,u) of { n@(I# n#) ->- case newArray# n# initial s1# of { (# s2#, marr# #) ->- (# s2#, STArray l u n marr# #) }}--{-# INLINE boundsSTArray #-}-boundsSTArray :: STArray s i e -> (i,i) -boundsSTArray (STArray l u _ _) = (l,u)--{-# INLINE numElementsSTArray #-}-numElementsSTArray :: STArray s i e -> Int-numElementsSTArray (STArray _ _ n _) = n--{-# INLINE readSTArray #-}-readSTArray :: Ix i => STArray s i e -> i -> ST s e-readSTArray marr@(STArray l u n _) i =- unsafeReadSTArray marr (safeIndex (l,u) n i)--{-# INLINE unsafeReadSTArray #-}-unsafeReadSTArray :: Ix i => STArray s i e -> Int -> ST s e-unsafeReadSTArray (STArray _ _ _ marr#) (I# i#)- = ST $ \s1# -> readArray# marr# i# s1#--{-# INLINE writeSTArray #-}-writeSTArray :: Ix i => STArray s i e -> i -> e -> ST s () -writeSTArray marr@(STArray l u n _) i e =- unsafeWriteSTArray marr (safeIndex (l,u) n i) e--{-# INLINE unsafeWriteSTArray #-}-unsafeWriteSTArray :: Ix i => STArray s i e -> Int -> e -> ST s () -unsafeWriteSTArray (STArray _ _ _ marr#) (I# i#) e = ST $ \s1# ->- case writeArray# marr# i# e s1# of- s2# -> (# s2#, () #)-\end{code}---%*********************************************************-%* *-\subsection{Moving between mutable and immutable}-%* *-%*********************************************************--\begin{code}-freezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)-freezeSTArray (STArray l u n@(I# n#) marr#) = ST $ \s1# ->- case newArray# n# arrEleBottom s1# of { (# s2#, marr'# #) ->- let copy i# s3# | i# ==# n# = s3#- | otherwise =- case readArray# marr# i# s3# of { (# s4#, e #) ->- case writeArray# marr'# i# e s4# of { s5# ->- copy (i# +# 1#) s5# }} in- case copy 0# s2# of { s3# ->- case unsafeFreezeArray# marr'# s3# of { (# s4#, arr# #) ->- (# s4#, Array l u n arr# #) }}}--{-# INLINE unsafeFreezeSTArray #-}-unsafeFreezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)-unsafeFreezeSTArray (STArray l u n marr#) = ST $ \s1# ->- case unsafeFreezeArray# marr# s1# of { (# s2#, arr# #) ->- (# s2#, Array l u n arr# #) }--thawSTArray :: Ix i => Array i e -> ST s (STArray s i e)-thawSTArray (Array l u n@(I# n#) arr#) = ST $ \s1# ->- case newArray# n# arrEleBottom s1# of { (# s2#, marr# #) ->- let copy i# s3# | i# ==# n# = s3#- | otherwise =- case indexArray# arr# i# of { (# e #) ->- case writeArray# marr# i# e s3# of { s4# ->- copy (i# +# 1#) s4# }} in- case copy 0# s2# of { s3# ->- (# s3#, STArray l u n marr# #) }}--{-# INLINE unsafeThawSTArray #-}-unsafeThawSTArray :: Ix i => Array i e -> ST s (STArray s i e)-unsafeThawSTArray (Array l u n arr#) = ST $ \s1# ->- case unsafeThawArray# arr# s1# of { (# s2#, marr# #) ->- (# s2#, STArray l u n marr# #) }-\end{code}
@@ -1,831 +0,0 @@-\section[GHC.Base]{Module @GHC.Base@}--The overall structure of the GHC Prelude is a bit tricky.-- a) We want to avoid "orphan modules", i.e. ones with instance- decls that don't belong either to a tycon or a class- defined in the same module-- b) We want to avoid giant modules--So the rough structure is as follows, in (linearised) dependency order---GHC.Prim Has no implementation. It defines built-in things, and- by importing it you bring them into scope.- The source file is GHC.Prim.hi-boot, which is just- copied to make GHC.Prim.hi--GHC.Base Classes: Eq, Ord, Functor, Monad- Types: list, (), Int, Bool, Ordering, Char, String--Data.Tuple Types: tuples, plus instances for GHC.Base classes--GHC.Show Class: Show, plus instances for GHC.Base/GHC.Tup types--GHC.Enum Class: Enum, plus instances for GHC.Base/GHC.Tup types--Data.Maybe Type: Maybe, plus instances for GHC.Base classes--GHC.List List functions--GHC.Num Class: Num, plus instances for Int- Type: Integer, plus instances for all classes so far (Eq, Ord, Num, Show)-- Integer is needed here because it is mentioned in the signature- of 'fromInteger' in class Num--GHC.Real Classes: Real, Integral, Fractional, RealFrac- plus instances for Int, Integer- Types: Ratio, Rational- plus intances for classes so far-- Rational is needed here because it is mentioned in the signature- of 'toRational' in class Real--GHC.ST The ST monad, instances and a few helper functions--Ix Classes: Ix, plus instances for Int, Bool, Char, Integer, Ordering, tuples--GHC.Arr Types: Array, MutableArray, MutableVar-- Arrays are used by a function in GHC.Float--GHC.Float Classes: Floating, RealFloat- Types: Float, Double, plus instances of all classes so far-- This module contains everything to do with floating point.- It is a big module (900 lines)- With a bit of luck, many modules can be compiled without ever reading GHC.Float.hi---Other Prelude modules are much easier with fewer complex dependencies.--\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , BangPatterns- , ExplicitForAll- , MagicHash- , UnboxedTuples- , ExistentialQuantification- , Rank2Types- #-}--- -fno-warn-orphans is needed for things like:--- Orphan rule: "x# -# x#" ALWAYS forall x# :: Int# -# x# x# = 0-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Base--- Copyright : (c) The University of Glasgow, 1992-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Basic data types and classes.--- --------------------------------------------------------------------------------#include "MachDeps.h"---- #hide-module GHC.Base- (- module GHC.Base,- module GHC.Classes,- module GHC.CString,- module GHC.Types,- module GHC.Prim, -- Re-export GHC.Prim and GHC.Err, to avoid lots- module GHC.Err -- of people having to import it explicitly- ) - where--import GHC.Types-import GHC.Classes-import GHC.CString-import GHC.Prim-import {-# SOURCE #-} GHC.Show-import {-# SOURCE #-} GHC.Err---- This is not strictly speaking required by this module, but is an--- implicit dependency whenever () or tuples are mentioned, so adding it--- as an import here helps to get the dependencies right in the new--- build system.-import GHC.Tuple ()--- Likewise we need Integer when deriving things like Eq instances, and--- this is a convenient place to force it to be built-import GHC.Integer ()--infixr 9 .-infixr 5 ++-infixl 4 <$-infixl 1 >>, >>=-infixr 0 $--default () -- Double isn't available yet-\end{code}---%*********************************************************-%* *-\subsection{DEBUGGING STUFF}-%* (for use when compiling GHC.Base itself doesn't work)-%* *-%*********************************************************--\begin{code}-{--data Bool = False | True-data Ordering = LT | EQ | GT -data Char = C# Char#-type String = [Char]-data Int = I# Int#-data () = ()-data [] a = MkNil--not True = False-(&&) True True = True-otherwise = True--build = error "urk"-foldr = error "urk"--}-\end{code}---%*********************************************************-%* *-\subsection{Monadic classes @Functor@, @Monad@ }-%* *-%*********************************************************--\begin{code}-{- | The 'Functor' class is used for types that can be mapped over.-Instances of 'Functor' should satisfy the following laws:--> fmap id == id-> fmap (f . g) == fmap f . fmap g--The instances of 'Functor' for lists, 'Data.Maybe.Maybe' and 'System.IO.IO'-satisfy these laws.--}--class Functor f where- fmap :: (a -> b) -> f a -> f b-- -- | Replace all locations in the input with the same value.- -- The default definition is @'fmap' . 'const'@, but this may be- -- overridden with a more efficient version.- (<$) :: a -> f b -> f a- (<$) = fmap . const--{- | The 'Monad' class defines the basic operations over a /monad/,-a concept from a branch of mathematics known as /category theory/.-From the perspective of a Haskell programmer, however, it is best to-think of a monad as an /abstract datatype/ of actions.-Haskell's @do@ expressions provide a convenient syntax for writing-monadic expressions.--Minimal complete definition: '>>=' and 'return'.--Instances of 'Monad' should satisfy the following laws:--> return a >>= k == k a-> m >>= return == m-> m >>= (\x -> k x >>= h) == (m >>= k) >>= h--Instances of both 'Monad' and 'Functor' should additionally satisfy the law:--> fmap f xs == xs >>= return . f--The instances of 'Monad' for lists, 'Data.Maybe.Maybe' and 'System.IO.IO'-defined in the "Prelude" satisfy these laws.--}--class Monad m where- -- | Sequentially compose two actions, passing any value produced- -- by the first as an argument to the second.- (>>=) :: forall a b. m a -> (a -> m b) -> m b- -- | Sequentially compose two actions, discarding any value produced- -- by the first, like sequencing operators (such as the semicolon)- -- in imperative languages.- (>>) :: forall a b. m a -> m b -> m b- -- Explicit for-alls so that we know what order to- -- give type arguments when desugaring-- -- | Inject a value into the monadic type.- return :: a -> m a- -- | Fail with a message. This operation is not part of the- -- mathematical definition of a monad, but is invoked on pattern-match- -- failure in a @do@ expression.- fail :: String -> m a-- {-# INLINE (>>) #-}- m >> k = m >>= \_ -> k- fail s = error s-\end{code}---%*********************************************************-%* *-\subsection{The list type}-%* *-%*********************************************************--\begin{code}-instance Functor [] where- fmap = map--instance Monad [] where- m >>= k = foldr ((++) . k) [] m- m >> k = foldr ((++) . (\ _ -> k)) [] m- return x = [x]-\end{code}--A few list functions that appear here because they are used here.-The rest of the prelude list functions are in GHC.List.--------------------------------------------------- foldr/build/augment------------------------------------------------ -\begin{code}--- | 'foldr', applied to a binary operator, a starting value (typically--- the right-identity of the operator), and a list, reduces the list--- using the binary operator, from right to left:------ > foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)--foldr :: (a -> b -> b) -> b -> [a] -> b--- foldr _ z [] = z--- foldr f z (x:xs) = f x (foldr f z xs)-{-# INLINE [0] foldr #-}--- Inline only in the final stage, after the foldr/cons rule has had a chance--- Also note that we inline it when it has *two* parameters, which are the --- ones we are keen about specialising!-foldr k z = go- where- go [] = z- go (y:ys) = y `k` go ys---- | A list producer that can be fused with 'foldr'.--- This function is merely------ > build g = g (:) []------ but GHC's simplifier will transform an expression of the form--- @'foldr' k z ('build' g)@, which may arise after inlining, to @g k z@,--- which avoids producing an intermediate list.--build :: forall a. (forall b. (a -> b -> b) -> b -> b) -> [a]-{-# INLINE [1] build #-}- -- The INLINE is important, even though build is tiny,- -- because it prevents [] getting inlined in the version that- -- appears in the interface file. If [] *is* inlined, it- -- won't match with [] appearing in rules in an importing module.- --- -- The "1" says to inline in phase 1--build g = g (:) []---- | A list producer that can be fused with 'foldr'.--- This function is merely------ > augment g xs = g (:) xs------ but GHC's simplifier will transform an expression of the form--- @'foldr' k z ('augment' g xs)@, which may arise after inlining, to--- @g k ('foldr' k z xs)@, which avoids producing an intermediate list.--augment :: forall a. (forall b. (a->b->b) -> b -> b) -> [a] -> [a]-{-# INLINE [1] augment #-}-augment g xs = g (:) xs--{-# RULES-"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) . - foldr k z (build g) = g k z--"foldr/augment" forall k z xs (g::forall b. (a->b->b) -> b -> b) . - foldr k z (augment g xs) = g k (foldr k z xs)--"foldr/id" foldr (:) [] = \x -> x-"foldr/app" [1] forall ys. foldr (:) ys = \xs -> xs ++ ys- -- Only activate this from phase 1, because that's- -- when we disable the rule that expands (++) into foldr---- The foldr/cons rule looks nice, but it can give disastrously--- bloated code when commpiling--- array (a,b) [(1,2), (2,2), (3,2), ...very long list... ]--- i.e. when there are very very long literal lists--- So I've disabled it for now. We could have special cases--- for short lists, I suppose.--- "foldr/cons" forall k z x xs. foldr k z (x:xs) = k x (foldr k z xs)--"foldr/single" forall k z x. foldr k z [x] = k x z-"foldr/nil" forall k z. foldr k z [] = z --"augment/build" forall (g::forall b. (a->b->b) -> b -> b)- (h::forall b. (a->b->b) -> b -> b) .- augment g (build h) = build (\c n -> g c (h c n))-"augment/nil" forall (g::forall b. (a->b->b) -> b -> b) .- augment g [] = build g- #-}---- This rule is true, but not (I think) useful:--- augment g (augment h t) = augment (\cn -> g c (h c n)) t-\end{code}---------------------------------------------------- map -------------------------------------------------\begin{code}--- | 'map' @f xs@ is the list obtained by applying @f@ to each element--- of @xs@, i.e.,------ > map f [x1, x2, ..., xn] == [f x1, f x2, ..., f xn]--- > map f [x1, x2, ...] == [f x1, f x2, ...]--map :: (a -> b) -> [a] -> [b]-map _ [] = []-map f (x:xs) = f x : map f xs---- Note eta expanded-mapFB :: (elt -> lst -> lst) -> (a -> elt) -> a -> lst -> lst-{-# INLINE [0] mapFB #-}-mapFB c f = \x ys -> c (f x) ys---- The rules for map work like this.--- --- Up to (but not including) phase 1, we use the "map" rule to--- rewrite all saturated applications of map with its build/fold --- form, hoping for fusion to happen.--- In phase 1 and 0, we switch off that rule, inline build, and--- switch on the "mapList" rule, which rewrites the foldr/mapFB--- thing back into plain map. ------ It's important that these two rules aren't both active at once --- (along with build's unfolding) else we'd get an infinite loop --- in the rules. Hence the activation control below.------ The "mapFB" rule optimises compositions of map.------ This same pattern is followed by many other functions: --- e.g. append, filter, iterate, repeat, etc.--{-# RULES-"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)-"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f-"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f.g) - #-}-\end{code}---------------------------------------------------- append ------------------------------------------------\begin{code}--- | Append two lists, i.e.,------ > [x1, ..., xm] ++ [y1, ..., yn] == [x1, ..., xm, y1, ..., yn]--- > [x1, ..., xm] ++ [y1, ...] == [x1, ..., xm, y1, ...]------ If the first list is not finite, the result is the first list.--(++) :: [a] -> [a] -> [a]-(++) [] ys = ys-(++) (x:xs) ys = x : xs ++ ys--{-# RULES-"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys- #-}--\end{code}---%*********************************************************-%* *-\subsection{Type @Bool@}-%* *-%*********************************************************--\begin{code}--- |'otherwise' is defined as the value 'True'. It helps to make--- guards more readable. eg.------ > f x | x < 0 = ...--- > | otherwise = ...-otherwise :: Bool-otherwise = True-\end{code}--%*********************************************************-%* *-\subsection{Type @Char@ and @String@}-%* *-%*********************************************************--\begin{code}--- | A 'String' is a list of characters. String constants in Haskell are values--- of type 'String'.----type String = [Char]--{-# RULES-"x# `eqChar#` x#" forall x#. x# `eqChar#` x# = True-"x# `neChar#` x#" forall x#. x# `neChar#` x# = False-"x# `gtChar#` x#" forall x#. x# `gtChar#` x# = False-"x# `geChar#` x#" forall x#. x# `geChar#` x# = True-"x# `leChar#` x#" forall x#. x# `leChar#` x# = True-"x# `ltChar#` x#" forall x#. x# `ltChar#` x# = False- #-}---- | The 'Prelude.toEnum' method restricted to the type 'Data.Char.Char'.-chr :: Int -> Char-chr i@(I# i#)- | int2Word# i# `leWord#` int2Word# 0x10FFFF# = C# (chr# i#)- | otherwise- = error ("Prelude.chr: bad argument: " ++ showSignedInt (I# 9#) i "")--unsafeChr :: Int -> Char-unsafeChr (I# i#) = C# (chr# i#)---- | The 'Prelude.fromEnum' method restricted to the type 'Data.Char.Char'.-ord :: Char -> Int-ord (C# c#) = I# (ord# c#)-\end{code}--String equality is used when desugaring pattern-matches against strings.--\begin{code}-eqString :: String -> String -> Bool-eqString [] [] = True-eqString (c1:cs1) (c2:cs2) = c1 == c2 && cs1 `eqString` cs2-eqString _ _ = False--{-# RULES "eqString" (==) = eqString #-}--- eqString also has a BuiltInRule in PrelRules.lhs:--- eqString (unpackCString# (Lit s1)) (unpackCString# (Lit s2) = s1==s2-\end{code}---%*********************************************************-%* *-\subsection{Type @Int@}-%* *-%*********************************************************--\begin{code}-zeroInt, oneInt, twoInt, maxInt, minInt :: Int-zeroInt = I# 0#-oneInt = I# 1#-twoInt = I# 2#--{- Seems clumsy. Should perhaps put minInt and MaxInt directly into MachDeps.h -}-#if WORD_SIZE_IN_BITS == 31-minInt = I# (-0x40000000#)-maxInt = I# 0x3FFFFFFF#-#elif WORD_SIZE_IN_BITS == 32-minInt = I# (-0x80000000#)-maxInt = I# 0x7FFFFFFF#-#else -minInt = I# (-0x8000000000000000#)-maxInt = I# 0x7FFFFFFFFFFFFFFF#-#endif-\end{code}---%*********************************************************-%* *-\subsection{The function type}-%* *-%*********************************************************--\begin{code}--- | Identity function.-id :: a -> a-id x = x---- | The call '(lazy e)' means the same as 'e', but 'lazy' has a --- magical strictness property: it is lazy in its first argument, --- even though its semantics is strict.-lazy :: a -> a-lazy x = x--- Implementation note: its strictness and unfolding are over-ridden--- by the definition in MkId.lhs; in both cases to nothing at all.--- That way, 'lazy' does not get inlined, and the strictness analyser--- sees it as lazy. Then the worker/wrapper phase inlines it.--- Result: happiness---- Assertion function. This simply ignores its boolean argument.--- The compiler may rewrite it to @('assertError' line)@.---- | If the first argument evaluates to 'True', then the result is the--- second argument. Otherwise an 'AssertionFailed' exception is raised,--- containing a 'String' with the source file and line number of the--- call to 'assert'.------ Assertions can normally be turned on or off with a compiler flag--- (for GHC, assertions are normally on unless optimisation is turned on --- with @-O@ or the @-fignore-asserts@--- option is given). When assertions are turned off, the first--- argument to 'assert' is ignored, and the second argument is--- returned as the result.---- SLPJ: in 5.04 etc 'assert' is in GHC.Prim,--- but from Template Haskell onwards it's simply--- defined here in Base.lhs-assert :: Bool -> a -> a-assert _pred r = r--breakpoint :: a -> a-breakpoint r = r--breakpointCond :: Bool -> a -> a-breakpointCond _ r = r--data Opaque = forall a. O a---- | Constant function.-const :: a -> b -> a-const x _ = x---- | Function composition.-{-# INLINE (.) #-}--- Make sure it has TWO args only on the left, so that it inlines--- when applied to two functions, even if there is no final argument-(.) :: (b -> c) -> (a -> b) -> a -> c-(.) f g = \x -> f (g x)---- | @'flip' f@ takes its (first) two arguments in the reverse order of @f@.-flip :: (a -> b -> c) -> b -> a -> c-flip f x y = f y x---- | Application operator. This operator is redundant, since ordinary--- application @(f x)@ means the same as @(f '$' x)@. However, '$' has--- low, right-associative binding precedence, so it sometimes allows--- parentheses to be omitted; for example:------ > f $ g $ h x = f (g (h x))------ It is also useful in higher-order situations, such as @'map' ('$' 0) xs@,--- or @'Data.List.zipWith' ('$') fs xs@.-{-# INLINE ($) #-}-($) :: (a -> b) -> a -> b-f $ x = f x---- | @'until' p f@ yields the result of applying @f@ until @p@ holds.-until :: (a -> Bool) -> (a -> a) -> a -> a-until p f x | p x = x- | otherwise = until p f (f x)---- | 'asTypeOf' is a type-restricted version of 'const'. It is usually--- used as an infix operator, and its typing forces its first argument--- (which is usually overloaded) to have the same type as the second.-asTypeOf :: a -> a -> a-asTypeOf = const-\end{code}--%*********************************************************-%* *-\subsection{@Functor@ and @Monad@ instances for @IO@}-%* *-%*********************************************************--\begin{code}-instance Functor IO where- fmap f x = x >>= (return . f)--instance Monad IO where- {-# INLINE return #-}- {-# INLINE (>>) #-}- {-# INLINE (>>=) #-}- m >> k = m >>= \ _ -> k- return = returnIO- (>>=) = bindIO--returnIO :: a -> IO a-returnIO x = IO $ \ s -> (# s, x #)--bindIO :: IO a -> (a -> IO b) -> IO b-bindIO (IO m) k = IO $ \ s -> case m s of (# new_s, a #) -> unIO (k a) new_s--thenIO :: IO a -> IO b -> IO b-thenIO (IO m) k = IO $ \ s -> case m s of (# new_s, _ #) -> unIO k new_s--unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))-unIO (IO a) = a-\end{code}--%*********************************************************-%* *-\subsection{@getTag@}-%* *-%*********************************************************--Returns the 'tag' of a constructor application; this function is used-by the deriving code for Eq, Ord and Enum.--The primitive dataToTag# requires an evaluated constructor application-as its argument, so we provide getTag as a wrapper that performs the-evaluation before calling dataToTag#. We could have dataToTag#-evaluate its argument, but we prefer to do it this way because (a)-dataToTag# can be an inline primop if it doesn't need to do any-evaluation, and (b) we want to expose the evaluation to the-simplifier, because it might be possible to eliminate the evaluation-in the case when the argument is already known to be evaluated.--\begin{code}-{-# INLINE getTag #-}-getTag :: a -> Int#-getTag x = x `seq` dataToTag# x-\end{code}--%*********************************************************-%* *-\subsection{Numeric primops}-%* *-%*********************************************************--\begin{code}-divInt# :: Int# -> Int# -> Int#-x# `divInt#` y#- -- Be careful NOT to overflow if we do any additional arithmetic- -- on the arguments... the following previous version of this- -- code has problems with overflow:--- | (x# ># 0#) && (y# <# 0#) = ((x# -# y#) -# 1#) `quotInt#` y#--- | (x# <# 0#) && (y# ># 0#) = ((x# -# y#) +# 1#) `quotInt#` y#- | (x# ># 0#) && (y# <# 0#) = ((x# -# 1#) `quotInt#` y#) -# 1#- | (x# <# 0#) && (y# ># 0#) = ((x# +# 1#) `quotInt#` y#) -# 1#- | otherwise = x# `quotInt#` y#--modInt# :: Int# -> Int# -> Int#-x# `modInt#` y#- | (x# ># 0#) && (y# <# 0#) ||- (x# <# 0#) && (y# ># 0#) = if r# /=# 0# then r# +# y# else 0#- | otherwise = r#- where- !r# = x# `remInt#` y#-\end{code}--Definitions of the boxed PrimOps; these will be-used in the case of partial applications, etc.--\begin{code}-{-# INLINE plusInt #-}-{-# INLINE minusInt #-}-{-# INLINE timesInt #-}-{-# INLINE quotInt #-}-{-# INLINE remInt #-}-{-# INLINE negateInt #-}--plusInt, minusInt, timesInt, quotInt, remInt, divInt, modInt :: Int -> Int -> Int-(I# x) `plusInt` (I# y) = I# (x +# y)-(I# x) `minusInt` (I# y) = I# (x -# y)-(I# x) `timesInt` (I# y) = I# (x *# y)-(I# x) `quotInt` (I# y) = I# (x `quotInt#` y)-(I# x) `remInt` (I# y) = I# (x `remInt#` y)-(I# x) `divInt` (I# y) = I# (x `divInt#` y)-(I# x) `modInt` (I# y) = I# (x `modInt#` y)--{-# RULES-"x# +# 0#" forall x#. x# +# 0# = x#-"0# +# x#" forall x#. 0# +# x# = x#-"x# -# 0#" forall x#. x# -# 0# = x#-"x# -# x#" forall x#. x# -# x# = 0#-"x# *# 0#" forall x#. x# *# 0# = 0#-"0# *# x#" forall x#. 0# *# x# = 0#-"x# *# 1#" forall x#. x# *# 1# = x#-"1# *# x#" forall x#. 1# *# x# = x#- #-}--negateInt :: Int -> Int-negateInt (I# x) = I# (negateInt# x)--{-# RULES-"x# ># x#" forall x#. x# ># x# = False-"x# >=# x#" forall x#. x# >=# x# = True-"x# ==# x#" forall x#. x# ==# x# = True-"x# /=# x#" forall x#. x# /=# x# = False-"x# <# x#" forall x#. x# <# x# = False-"x# <=# x#" forall x#. x# <=# x# = True- #-}--{-# RULES-"plusFloat x 0.0" forall x#. plusFloat# x# 0.0# = x#-"plusFloat 0.0 x" forall x#. plusFloat# 0.0# x# = x#-"minusFloat x 0.0" forall x#. minusFloat# x# 0.0# = x#-"timesFloat x 1.0" forall x#. timesFloat# x# 1.0# = x#-"timesFloat 1.0 x" forall x#. timesFloat# 1.0# x# = x#-"divideFloat x 1.0" forall x#. divideFloat# x# 1.0# = x#- #-}--{-# RULES-"plusDouble x 0.0" forall x#. (+##) x# 0.0## = x#-"plusDouble 0.0 x" forall x#. (+##) 0.0## x# = x#-"minusDouble x 0.0" forall x#. (-##) x# 0.0## = x#-"timesDouble x 1.0" forall x#. (*##) x# 1.0## = x#-"timesDouble 1.0 x" forall x#. (*##) 1.0## x# = x#-"divideDouble x 1.0" forall x#. (/##) x# 1.0## = x#- #-}--{--We'd like to have more rules, but for example:--This gives wrong answer (0) for NaN - NaN (should be NaN):- "minusDouble x x" forall x#. (-##) x# x# = 0.0##--This gives wrong answer (0) for 0 * NaN (should be NaN):- "timesDouble 0.0 x" forall x#. (*##) 0.0## x# = 0.0##--This gives wrong answer (0) for NaN * 0 (should be NaN):- "timesDouble x 0.0" forall x#. (*##) x# 0.0## = 0.0##--These are tested by num014.--Similarly for Float (#5178):--"minusFloat x x" forall x#. minusFloat# x# x# = 0.0#-"timesFloat0.0 x" forall x#. timesFloat# 0.0# x# = 0.0#-"timesFloat x 0.0" forall x#. timesFloat# x# 0.0# = 0.0#--}---- Wrappers for the shift operations. The uncheckedShift# family are--- undefined when the amount being shifted by is greater than the size--- in bits of Int#, so these wrappers perform a check and return--- either zero or -1 appropriately.------ Note that these wrappers still produce undefined results when the--- second argument (the shift amount) is negative.---- | Shift the argument left by the specified number of bits--- (which must be non-negative).-shiftL# :: Word# -> Int# -> Word#-a `shiftL#` b | b >=# WORD_SIZE_IN_BITS# = int2Word# 0#- | otherwise = a `uncheckedShiftL#` b---- | Shift the argument right by the specified number of bits--- (which must be non-negative).-shiftRL# :: Word# -> Int# -> Word#-a `shiftRL#` b | b >=# WORD_SIZE_IN_BITS# = int2Word# 0#- | otherwise = a `uncheckedShiftRL#` b---- | Shift the argument left by the specified number of bits--- (which must be non-negative).-iShiftL# :: Int# -> Int# -> Int#-a `iShiftL#` b | b >=# WORD_SIZE_IN_BITS# = 0#- | otherwise = a `uncheckedIShiftL#` b---- | Shift the argument right (signed) by the specified number of bits--- (which must be non-negative).-iShiftRA# :: Int# -> Int# -> Int#-a `iShiftRA#` b | b >=# WORD_SIZE_IN_BITS# = if a <# 0# then (-1#) else 0#- | otherwise = a `uncheckedIShiftRA#` b---- | Shift the argument right (unsigned) by the specified number of bits--- (which must be non-negative).-iShiftRL# :: Int# -> Int# -> Int#-a `iShiftRL#` b | b >=# WORD_SIZE_IN_BITS# = 0#- | otherwise = a `uncheckedIShiftRL#` b--#if WORD_SIZE_IN_BITS == 32-{-# RULES-"narrow32Int#" forall x#. narrow32Int# x# = x#-"narrow32Word#" forall x#. narrow32Word# x# = x#- #-}-#endif--{-# RULES-"int2Word2Int" forall x#. int2Word# (word2Int# x#) = x#-"word2Int2Word" forall x#. word2Int# (int2Word# x#) = x#- #-}----- Rules for C strings (the functions themselves are now in GHC.CString)-{-# RULES-"unpack" [~1] forall a . unpackCString# a = build (unpackFoldrCString# a)-"unpack-list" [1] forall a . unpackFoldrCString# a (:) [] = unpackCString# a-"unpack-append" forall a n . unpackFoldrCString# a (:) n = unpackAppendCString# a n---- There's a built-in rule (in PrelRules.lhs) for--- unpackFoldr "foo" c (unpackFoldr "baz" c n) = unpackFoldr "foobaz" c n-- #-}-\end{code}---#ifdef __HADDOCK__-\begin{code}--- | A special argument for the 'Control.Monad.ST.ST' type constructor,--- indexing a state embedded in the 'Prelude.IO' monad by--- 'Control.Monad.ST.stToIO'.-data RealWorld-\end{code}-#endif-
@@ -1,118 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}-{-# OPTIONS_HADDOCK not-home #-}---------------------------------------------------------------------------------- |--- Module : GHC.Conc--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Basic concurrency stuff.--- ---------------------------------------------------------------------------------- No: #hide, because bits of this module are exposed by the stm package.--- However, we don't want this module to be the home location for the--- bits it exports, we'd rather have Control.Concurrent and the other--- higher level modules be the home. Hence:--#include "Typeable.h"---- #not-home-module GHC.Conc- ( ThreadId(..)-- -- * Forking and suchlike- , forkIO -- :: IO a -> IO ThreadId- , forkIOUnmasked- , forkIOWithUnmask- , forkOn- , forkOnIO -- :: Int -> IO a -> IO ThreadId- , forkOnIOUnmasked- , forkOnWithUnmask- , numCapabilities -- :: Int- , getNumCapabilities -- :: IO Int- , setNumCapabilities -- :: Int -> IO ()- , getNumProcessors -- :: IO Int- , numSparks -- :: IO Int- , childHandler -- :: Exception -> IO ()- , myThreadId -- :: IO ThreadId- , killThread -- :: ThreadId -> IO ()- , throwTo -- :: ThreadId -> Exception -> IO ()- , par -- :: a -> b -> b- , pseq -- :: a -> b -> b- , runSparks- , yield -- :: IO ()- , labelThread -- :: ThreadId -> String -> IO ()-- , ThreadStatus(..), BlockReason(..)- , threadStatus -- :: ThreadId -> IO ThreadStatus- , threadCapability-- -- * Waiting- , threadDelay -- :: Int -> IO ()- , registerDelay -- :: Int -> IO (TVar Bool)- , threadWaitRead -- :: Int -> IO ()- , threadWaitWrite -- :: Int -> IO ()- , closeFdWith -- :: (Fd -> IO ()) -> Fd -> IO ()-- -- * TVars- , STM(..)- , atomically -- :: STM a -> IO a- , retry -- :: STM a- , orElse -- :: STM a -> STM a -> STM a- , throwSTM -- :: Exception e => e -> STM a- , catchSTM -- :: Exception e => STM a -> (e -> STM a) -> STM a- , alwaysSucceeds -- :: STM a -> STM ()- , always -- :: STM Bool -> STM ()- , TVar(..)- , newTVar -- :: a -> STM (TVar a)- , newTVarIO -- :: a -> STM (TVar a)- , readTVar -- :: TVar a -> STM a- , readTVarIO -- :: TVar a -> IO a- , writeTVar -- :: a -> TVar a -> STM ()- , unsafeIOToSTM -- :: IO a -> STM a-- -- * Miscellaneous- , withMVar-#ifdef mingw32_HOST_OS- , asyncRead -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)- , asyncWrite -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)- , asyncDoProc -- :: FunPtr (Ptr a -> IO Int) -> Ptr a -> IO Int-- , asyncReadBA -- :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int, Int)- , asyncWriteBA -- :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int, Int)-#endif--#ifndef mingw32_HOST_OS- , Signal, HandlerFun, setHandler, runHandlers-#endif-- , ensureIOManagerIsRunning--#ifdef mingw32_HOST_OS- , ConsoleEvent(..)- , win32ConsoleHandler- , toWin32ConsoleEvent-#endif- , setUncaughtExceptionHandler -- :: (Exception -> IO ()) -> IO ()- , getUncaughtExceptionHandler -- :: IO (Exception -> IO ())-- , reportError, reportStackOverflow- ) where--import GHC.Conc.IO-import GHC.Conc.Sync--#ifndef mingw32_HOST_OS-import GHC.Conc.Signal-#endif--\end{code}
@@ -1,159 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , MagicHash- , UnboxedTuples- , ForeignFunctionInterface- #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}-{-# OPTIONS_HADDOCK not-home #-}---------------------------------------------------------------------------------- |--- Module : GHC.Conc.IO--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Basic concurrency stuff.------------------------------------------------------------------------------------- No: #hide, because bits of this module are exposed by the stm package.--- However, we don't want this module to be the home location for the--- bits it exports, we'd rather have Control.Concurrent and the other--- higher level modules be the home. Hence:--#include "Typeable.h"---- #not-home-module GHC.Conc.IO- ( ensureIOManagerIsRunning-- -- * Waiting- , threadDelay -- :: Int -> IO ()- , registerDelay -- :: Int -> IO (TVar Bool)- , threadWaitRead -- :: Int -> IO ()- , threadWaitWrite -- :: Int -> IO ()- , closeFdWith -- :: (Fd -> IO ()) -> Fd -> IO ()--#ifdef mingw32_HOST_OS- , asyncRead -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)- , asyncWrite -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)- , asyncDoProc -- :: FunPtr (Ptr a -> IO Int) -> Ptr a -> IO Int-- , asyncReadBA -- :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int, Int)- , asyncWriteBA -- :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int, Int)-- , ConsoleEvent(..)- , win32ConsoleHandler- , toWin32ConsoleEvent-#endif- ) where--import Foreign-import GHC.Base-import GHC.Conc.Sync as Sync-import GHC.Real ( fromIntegral )-import System.Posix.Types--#ifdef mingw32_HOST_OS-import qualified GHC.Conc.Windows as Windows-import GHC.Conc.Windows (asyncRead, asyncWrite, asyncDoProc, asyncReadBA,- asyncWriteBA, ConsoleEvent(..), win32ConsoleHandler,- toWin32ConsoleEvent)-#else-import qualified GHC.Event.Thread as Event-#endif--ensureIOManagerIsRunning :: IO ()-#ifndef mingw32_HOST_OS-ensureIOManagerIsRunning = Event.ensureIOManagerIsRunning-#else-ensureIOManagerIsRunning = Windows.ensureIOManagerIsRunning-#endif---- | Block the current thread until data is available to read on the--- given file descriptor (GHC only).------ This will throw an 'IOError' if the file descriptor was closed--- while this thread was blocked. To safely close a file descriptor--- that has been used with 'threadWaitRead', use 'closeFdWith'.-threadWaitRead :: Fd -> IO ()-threadWaitRead fd-#ifndef mingw32_HOST_OS- | threaded = Event.threadWaitRead fd-#endif- | otherwise = IO $ \s ->- case fromIntegral fd of { I# fd# ->- case waitRead# fd# s of { s' -> (# s', () #)- }}---- | Block the current thread until data can be written to the--- given file descriptor (GHC only).------ This will throw an 'IOError' if the file descriptor was closed--- while this thread was blocked. To safely close a file descriptor--- that has been used with 'threadWaitWrite', use 'closeFdWith'.-threadWaitWrite :: Fd -> IO ()-threadWaitWrite fd-#ifndef mingw32_HOST_OS- | threaded = Event.threadWaitWrite fd-#endif- | otherwise = IO $ \s ->- case fromIntegral fd of { I# fd# ->- case waitWrite# fd# s of { s' -> (# s', () #)- }}---- | Close a file descriptor in a concurrency-safe way (GHC only). If--- you are using 'threadWaitRead' or 'threadWaitWrite' to perform--- blocking I\/O, you /must/ use this function to close file--- descriptors, or blocked threads may not be woken.------ Any threads that are blocked on the file descriptor via--- 'threadWaitRead' or 'threadWaitWrite' will be unblocked by having--- IO exceptions thrown.-closeFdWith :: (Fd -> IO ()) -- ^ Low-level action that performs the real close.- -> Fd -- ^ File descriptor to close.- -> IO ()-closeFdWith close fd-#ifndef mingw32_HOST_OS- | threaded = Event.closeFdWith close fd-#endif- | otherwise = close fd---- | Suspends the current thread for a given number of microseconds--- (GHC only).------ There is no guarantee that the thread will be rescheduled promptly--- when the delay has expired, but the thread will never continue to--- run /earlier/ than specified.----threadDelay :: Int -> IO ()-threadDelay time-#ifdef mingw32_HOST_OS- | threaded = Windows.threadDelay time-#else- | threaded = Event.threadDelay time-#endif- | otherwise = IO $ \s ->- case time of { I# time# ->- case delay# time# s of { s' -> (# s', () #)- }}---- | Set the value of returned TVar to True after a given number of--- microseconds. The caveats associated with threadDelay also apply.----registerDelay :: Int -> IO (TVar Bool)-registerDelay usecs-#ifdef mingw32_HOST_OS- | threaded = Windows.registerDelay usecs-#else- | threaded = Event.registerDelay usecs-#endif- | otherwise = error "registerDelay: requires -threaded"--foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool
@@ -1,91 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, ForeignFunctionInterface #-}--module GHC.Conc.Signal- ( Signal- , HandlerFun- , setHandler- , runHandlers- ) where--import Control.Concurrent.MVar (MVar, newMVar, withMVar)-import Data.Dynamic (Dynamic)-import Data.Maybe (Maybe(..))-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (ForeignPtr)-import Foreign.StablePtr (castPtrToStablePtr, castStablePtrToPtr,- deRefStablePtr, freeStablePtr, newStablePtr)-import Foreign.Ptr (Ptr, castPtr)-import GHC.Arr (inRange)-import GHC.Base-import GHC.Conc.Sync (forkIO)-import GHC.IO (mask_, unsafePerformIO)-import GHC.IOArray (IOArray, boundsIOArray, newIOArray,- unsafeReadIOArray, unsafeWriteIOArray)-import GHC.Real (fromIntegral)-import GHC.Word (Word8)----------------------------------------------------------------------------- Signal handling--type Signal = CInt--maxSig :: Int-maxSig = 64--type HandlerFun = ForeignPtr Word8 -> IO ()---- Lock used to protect concurrent access to signal_handlers. Symptom--- of this race condition is GHC bug #1922, although that bug was on--- Windows a similar bug also exists on Unix.-signal_handlers :: MVar (IOArray Int (Maybe (HandlerFun,Dynamic)))-signal_handlers = unsafePerformIO $ do- arr <- newIOArray (0, maxSig) Nothing- m <- newMVar arr- sharedCAF m getOrSetGHCConcSignalSignalHandlerStore-{-# NOINLINE signal_handlers #-}--foreign import ccall unsafe "getOrSetGHCConcSignalSignalHandlerStore"- getOrSetGHCConcSignalSignalHandlerStore :: Ptr a -> IO (Ptr a)--setHandler :: Signal -> Maybe (HandlerFun, Dynamic)- -> IO (Maybe (HandlerFun, Dynamic))-setHandler sig handler = do- let int = fromIntegral sig- withMVar signal_handlers $ \arr ->- if not (inRange (boundsIOArray arr) int)- then error "GHC.Conc.setHandler: signal out of range"- else do old <- unsafeReadIOArray arr int- unsafeWriteIOArray arr int handler- return old--runHandlers :: ForeignPtr Word8 -> Signal -> IO ()-runHandlers p_info sig = do- let int = fromIntegral sig- withMVar signal_handlers $ \arr ->- if not (inRange (boundsIOArray arr) int)- then return ()- else do handler <- unsafeReadIOArray arr int- case handler of- Nothing -> return ()- Just (f,_) -> do _ <- forkIO (f p_info)- return ()---- Machinery needed to ensure that we only have one copy of certain--- CAFs in this module even when the base package is present twice, as--- it is when base is dynamically loaded into GHCi. The RTS keeps--- track of the single true value of the CAF, so even when the CAFs in--- the dynamically-loaded base package are reverted, nothing bad--- happens.----sharedCAF :: a -> (Ptr a -> IO (Ptr a)) -> IO a-sharedCAF a get_or_set =- mask_ $ do- stable_ref <- newStablePtr a- let ref = castPtr (castStablePtrToPtr stable_ref)- ref2 <- get_or_set ref- if ref == ref2- then return a- else do freeStablePtr stable_ref- deRefStablePtr (castPtrToStablePtr (castPtr ref2))-
@@ -1,816 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , BangPatterns- , MagicHash- , UnboxedTuples- , UnliftedFFITypes- , ForeignFunctionInterface- , DeriveDataTypeable- , StandaloneDeriving- , RankNTypes- #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}-{-# OPTIONS_HADDOCK not-home #-}---------------------------------------------------------------------------------- |--- Module : GHC.Conc.Sync--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Basic concurrency stuff.------------------------------------------------------------------------------------- No: #hide, because bits of this module are exposed by the stm package.--- However, we don't want this module to be the home location for the--- bits it exports, we'd rather have Control.Concurrent and the other--- higher level modules be the home. Hence:--#include "Typeable.h"---- #not-home-module GHC.Conc.Sync- ( ThreadId(..)-- -- * Forking and suchlike- , forkIO -- :: IO a -> IO ThreadId- , forkIOUnmasked- , forkIOWithUnmask- , forkOn -- :: Int -> IO a -> IO ThreadId- , forkOnIO -- DEPRECATED- , forkOnIOUnmasked- , forkOnWithUnmask- , numCapabilities -- :: Int- , getNumCapabilities -- :: IO Int- , setNumCapabilities -- :: Int -> IO ()- , getNumProcessors -- :: IO Int- , numSparks -- :: IO Int- , childHandler -- :: Exception -> IO ()- , myThreadId -- :: IO ThreadId- , killThread -- :: ThreadId -> IO ()- , throwTo -- :: ThreadId -> Exception -> IO ()- , par -- :: a -> b -> b- , pseq -- :: a -> b -> b- , runSparks- , yield -- :: IO ()- , labelThread -- :: ThreadId -> String -> IO ()-- , ThreadStatus(..), BlockReason(..)- , threadStatus -- :: ThreadId -> IO ThreadStatus- , threadCapability-- -- * TVars- , STM(..)- , atomically -- :: STM a -> IO a- , retry -- :: STM a- , orElse -- :: STM a -> STM a -> STM a- , throwSTM -- :: Exception e => e -> STM a- , catchSTM -- :: Exception e => STM a -> (e -> STM a) -> STM a- , alwaysSucceeds -- :: STM a -> STM ()- , always -- :: STM Bool -> STM ()- , TVar(..)- , newTVar -- :: a -> STM (TVar a)- , newTVarIO -- :: a -> STM (TVar a)- , readTVar -- :: TVar a -> STM a- , readTVarIO -- :: TVar a -> IO a- , writeTVar -- :: a -> TVar a -> STM ()- , unsafeIOToSTM -- :: IO a -> STM a-- -- * Miscellaneous- , withMVar- , modifyMVar_-- , setUncaughtExceptionHandler -- :: (Exception -> IO ()) -> IO ()- , getUncaughtExceptionHandler -- :: IO (Exception -> IO ())-- , reportError, reportStackOverflow-- , sharedCAF- ) where--import Foreign hiding (unsafePerformIO)-import Foreign.C--#ifdef mingw32_HOST_OS-import Data.Typeable-#endif--#ifndef mingw32_HOST_OS-import Data.Dynamic-#endif-import Control.Monad-import Data.Maybe--import GHC.Base-import {-# SOURCE #-} GHC.IO.Handle ( hFlush )-import {-# SOURCE #-} GHC.IO.Handle.FD ( stdout )-import GHC.IO-import GHC.IO.Exception-import GHC.Exception-import GHC.IORef-import GHC.MVar-import GHC.Real ( fromIntegral )-import GHC.Pack ( packCString# )-import GHC.Show ( Show(..), showString )--infixr 0 `par`, `pseq`-\end{code}--%************************************************************************-%* *-\subsection{@ThreadId@, @par@, and @fork@}-%* *-%************************************************************************--\begin{code}-data ThreadId = ThreadId ThreadId# deriving( Typeable )--- ToDo: data ThreadId = ThreadId (Weak ThreadId#)--- But since ThreadId# is unlifted, the Weak type must use open--- type variables.-{- ^-A 'ThreadId' is an abstract type representing a handle to a thread.-'ThreadId' is an instance of 'Eq', 'Ord' and 'Show', where-the 'Ord' instance implements an arbitrary total ordering over-'ThreadId's. The 'Show' instance lets you convert an arbitrary-valued-'ThreadId' to string form; showing a 'ThreadId' value is occasionally-useful when debugging or diagnosing the behaviour of a concurrent-program.--/Note/: in GHC, if you have a 'ThreadId', you essentially have-a pointer to the thread itself. This means the thread itself can\'t be-garbage collected until you drop the 'ThreadId'.-This misfeature will hopefully be corrected at a later date.--/Note/: Hugs does not provide any operations on other threads;-it defines 'ThreadId' as a synonym for ().--}--instance Show ThreadId where- showsPrec d t =- showString "ThreadId " .- showsPrec d (getThreadId (id2TSO t))--foreign import ccall unsafe "rts_getThreadId" getThreadId :: ThreadId# -> CInt--id2TSO :: ThreadId -> ThreadId#-id2TSO (ThreadId t) = t--foreign import ccall unsafe "cmp_thread" cmp_thread :: ThreadId# -> ThreadId# -> CInt--- Returns -1, 0, 1--cmpThread :: ThreadId -> ThreadId -> Ordering-cmpThread t1 t2 =- case cmp_thread (id2TSO t1) (id2TSO t2) of- -1 -> LT- 0 -> EQ- _ -> GT -- must be 1--instance Eq ThreadId where- t1 == t2 =- case t1 `cmpThread` t2 of- EQ -> True- _ -> False--instance Ord ThreadId where- compare = cmpThread--{- |-Sparks off a new thread to run the 'IO' computation passed as the-first argument, and returns the 'ThreadId' of the newly created-thread.--The new thread will be a lightweight thread; if you want to use a foreign-library that uses thread-local storage, use 'Control.Concurrent.forkOS' instead.--GHC note: the new thread inherits the /masked/ state of the parent-(see 'Control.Exception.mask').--The newly created thread has an exception handler that discards the-exceptions 'BlockedIndefinitelyOnMVar', 'BlockedIndefinitelyOnSTM', and-'ThreadKilled', and passes all other exceptions to the uncaught-exception handler.--}-forkIO :: IO () -> IO ThreadId-forkIO action = IO $ \ s ->- case (fork# action_plus s) of (# s1, tid #) -> (# s1, ThreadId tid #)- where- action_plus = catchException action childHandler--{-# DEPRECATED forkIOUnmasked "use forkIOWithUnmask instead" #-}--- | This function is deprecated; use 'forkIOWIthUnmask' instead-forkIOUnmasked :: IO () -> IO ThreadId-forkIOUnmasked io = forkIO (unsafeUnmask io)---- | Like 'forkIO', but the child thread is passed a function that can--- be used to unmask asynchronous exceptions. This function is--- typically used in the following way------ > ... mask_ $ forkIOWithUnmask $ \unmask ->--- > catch (unmask ...) handler------ so that the exception handler in the child thread is established--- with asynchronous exceptions masked, meanwhile the main body of--- the child thread is executed in the unmasked state.------ Note that the unmask function passed to the child thread should--- only be used in that thread; the behaviour is undefined if it is--- invoked in a different thread.----forkIOWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId-forkIOWithUnmask io = forkIO (io unsafeUnmask)--{- |-Like 'forkIO', but lets you specify on which processor the thread-should run. Unlike a `forkIO` thread, a thread created by `forkOn`-will stay on the same processor for its entire lifetime (`forkIO`-threads can migrate between processors according to the scheduling-policy). `forkOn` is useful for overriding the scheduling policy when-you know in advance how best to distribute the threads.--The `Int` argument specifies a /capability number/ (see-'getNumCapabilities'). Typically capabilities correspond to physical-processors, but the exact behaviour is implementation-dependent. The-value passed to 'forkOn' is interpreted modulo the total number of-capabilities as returned by 'getNumCapabilities'.--GHC note: the number of capabilities is specified by the @+RTS -N@-option when the program is started. Capabilities can be fixed to-actual processor cores with @+RTS -qa@ if the underlying operating-system supports that, although in practice this is usually unnecessary-(and may actually degrade perforamnce in some cases - experimentation-is recommended).--}-forkOn :: Int -> IO () -> IO ThreadId-forkOn (I# cpu) action = IO $ \ s ->- case (forkOn# cpu action_plus s) of (# s1, tid #) -> (# s1, ThreadId tid #)- where- action_plus = catchException action childHandler--{-# DEPRECATED forkOnIO "renamed to forkOn" #-}--- | This function is deprecated; use 'forkOn' instead-forkOnIO :: Int -> IO () -> IO ThreadId-forkOnIO = forkOn--{-# DEPRECATED forkOnIOUnmasked "use forkOnWithUnmask instead" #-}--- | This function is deprecated; use 'forkOnWIthUnmask' instead-forkOnIOUnmasked :: Int -> IO () -> IO ThreadId-forkOnIOUnmasked cpu io = forkOn cpu (unsafeUnmask io)---- | Like 'forkIOWithUnmask', but the child thread is pinned to the--- given CPU, as with 'forkOn'.-forkOnWithUnmask :: Int -> ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId-forkOnWithUnmask cpu io = forkOn cpu (io unsafeUnmask)---- | the value passed to the @+RTS -N@ flag. This is the number of--- Haskell threads that can run truly simultaneously at any given--- time, and is typically set to the number of physical processor cores on--- the machine.------ Strictly speaking it is better to use 'getNumCapabilities', because--- the number of capabilities might vary at runtime.----numCapabilities :: Int-numCapabilities = unsafePerformIO $ getNumCapabilities--{- |-Returns the number of Haskell threads that can run truly-simultaneously (on separate physical processors) at any given time.-The number passed to `forkOn` is interpreted modulo this-value.--An implementation in which Haskell threads are mapped directly to-OS threads might return the number of physical processor cores in-the machine, and 'forkOn' would be implemented using the OS's-affinity facilities. An implementation that schedules Haskell-threads onto a smaller number of OS threads (like GHC) would return-the number of such OS threads that can be running simultaneously.--GHC notes: this returns the number passed as the argument to the-@+RTS -N@ flag. In current implementations, the value is fixed-when the program starts and never changes, but it is possible that-in the future the number of capabilities might vary at runtime.--}-getNumCapabilities :: IO Int-getNumCapabilities = do- n <- peek n_capabilities- return (fromIntegral n)--{- |-Set the number of Haskell threads that can run truly simultaneously-(on separate physical processors) at any given time.--GHC notes: in the current implementation, the value may only be-/increased/, not decreased, by calling 'setNumCapabilities'. The-initial value is given by the @+RTS -N@ flag, and the current value-may be obtained using 'getNumCapabilities'.--}-setNumCapabilities :: Int -> IO ()-setNumCapabilities i = c_setNumCapabilities (fromIntegral i)--foreign import ccall safe "setNumCapabilities"- c_setNumCapabilities :: CUInt -> IO ()--getNumProcessors :: IO Int-getNumProcessors = fmap fromIntegral c_getNumberOfProcessors--foreign import ccall unsafe "getNumberOfProcessors"- c_getNumberOfProcessors :: IO CUInt---- | Returns the number of sparks currently in the local spark pool-numSparks :: IO Int-numSparks = IO $ \s -> case numSparks# s of (# s', n #) -> (# s', I# n #)--#if defined(mingw32_HOST_OS) && defined(__PIC__)-foreign import ccall "_imp__n_capabilities" n_capabilities :: Ptr CInt-#else-foreign import ccall "&n_capabilities" n_capabilities :: Ptr CInt-#endif-childHandler :: SomeException -> IO ()-childHandler err = catchException (real_handler err) childHandler--real_handler :: SomeException -> IO ()-real_handler se@(SomeException ex) =- -- ignore thread GC and killThread exceptions:- case cast ex of- Just BlockedIndefinitelyOnMVar -> return ()- _ -> case cast ex of- Just BlockedIndefinitelyOnSTM -> return ()- _ -> case cast ex of- Just ThreadKilled -> return ()- _ -> case cast ex of- -- report all others:- Just StackOverflow -> reportStackOverflow- _ -> reportError se--{- | 'killThread' raises the 'ThreadKilled' exception in the given-thread (GHC only).--> killThread tid = throwTo tid ThreadKilled---}-killThread :: ThreadId -> IO ()-killThread tid = throwTo tid ThreadKilled--{- | 'throwTo' raises an arbitrary exception in the target thread (GHC only).--'throwTo' does not return until the exception has been raised in the-target thread.-The calling thread can thus be certain that the target-thread has received the exception. This is a useful property to know-when dealing with race conditions: eg. if there are two threads that-can kill each other, it is guaranteed that only one of the threads-will get to kill the other.--Whatever work the target thread was doing when the exception was-raised is not lost: the computation is suspended until required by-another thread.--If the target thread is currently making a foreign call, then the-exception will not be raised (and hence 'throwTo' will not return)-until the call has completed. This is the case regardless of whether-the call is inside a 'mask' or not. However, in GHC a foreign call-can be annotated as @interruptible@, in which case a 'throwTo' will-cause the RTS to attempt to cause the call to return; see the GHC-documentation for more details.--Important note: the behaviour of 'throwTo' differs from that described in-the paper \"Asynchronous exceptions in Haskell\"-(<http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm>).-In the paper, 'throwTo' is non-blocking; but the library implementation adopts-a more synchronous design in which 'throwTo' does not return until the exception-is received by the target thread. The trade-off is discussed in Section 9 of the paper.-Like any blocking operation, 'throwTo' is therefore interruptible (see Section 5.3 of-the paper). Unlike other interruptible operations, however, 'throwTo'-is /always/ interruptible, even if it does not actually block.--There is no guarantee that the exception will be delivered promptly,-although the runtime will endeavour to ensure that arbitrary-delays don't occur. In GHC, an exception can only be raised when a-thread reaches a /safe point/, where a safe point is where memory-allocation occurs. Some loops do not perform any memory allocation-inside the loop and therefore cannot be interrupted by a 'throwTo'.--If the target of 'throwTo' is the calling thread, then the behaviour-is the same as 'Control.Exception.throwIO', except that the exception-is thrown as an asynchronous exception. This means that if there is-an enclosing pure computation, which would be the case if the current-IO operation is inside 'unsafePerformIO' or 'unsafeInterleaveIO', that-computation is not permanently replaced by the exception, but is-suspended as if it had received an asynchronous exception.--Note that if 'throwTo' is called with the current thread as the-target, the exception will be thrown even if the thread is currently-inside 'mask' or 'uninterruptibleMask'.- -}-throwTo :: Exception e => ThreadId -> e -> IO ()-throwTo (ThreadId tid) ex = IO $ \ s ->- case (killThread# tid (toException ex) s) of s1 -> (# s1, () #)---- | Returns the 'ThreadId' of the calling thread (GHC only).-myThreadId :: IO ThreadId-myThreadId = IO $ \s ->- case (myThreadId# s) of (# s1, tid #) -> (# s1, ThreadId tid #)----- |The 'yield' action allows (forces, in a co-operative multitasking--- implementation) a context-switch to any other currently runnable--- threads (if any), and is occasionally useful when implementing--- concurrency abstractions.-yield :: IO ()-yield = IO $ \s ->- case (yield# s) of s1 -> (# s1, () #)--{- | 'labelThread' stores a string as identifier for this thread if-you built a RTS with debugging support. This identifier will be used in-the debugging output to make distinction of different threads easier-(otherwise you only have the thread state object\'s address in the heap).--Other applications like the graphical Concurrent Haskell Debugger-(<http://www.informatik.uni-kiel.de/~fhu/chd/>) may choose to overload-'labelThread' for their purposes as well.--}--labelThread :: ThreadId -> String -> IO ()-labelThread (ThreadId t) str = IO $ \ s ->- let !ps = packCString# str- !adr = byteArrayContents# ps in- case (labelThread# t adr s) of s1 -> (# s1, () #)---- Nota Bene: 'pseq' used to be 'seq'--- but 'seq' is now defined in PrelGHC------ "pseq" is defined a bit weirdly (see below)------ The reason for the strange "lazy" call is that--- it fools the compiler into thinking that pseq and par are non-strict in--- their second argument (even if it inlines pseq at the call site).--- If it thinks pseq is strict in "y", then it often evaluates--- "y" before "x", which is totally wrong.--{-# INLINE pseq #-}-pseq :: a -> b -> b-pseq x y = x `seq` lazy y--{-# INLINE par #-}-par :: a -> b -> b-par x y = case (par# x) of { _ -> lazy y }---- | Internal function used by the RTS to run sparks.-runSparks :: IO ()-runSparks = IO loop- where loop s = case getSpark# s of- (# s', n, p #) ->- if n ==# 0# then (# s', () #)- else p `seq` loop s'--data BlockReason- = BlockedOnMVar- -- ^blocked on on 'MVar'- | BlockedOnBlackHole- -- ^blocked on a computation in progress by another thread- | BlockedOnException- -- ^blocked in 'throwTo'- | BlockedOnSTM- -- ^blocked in 'retry' in an STM transaction- | BlockedOnForeignCall- -- ^currently in a foreign call- | BlockedOnOther- -- ^blocked on some other resource. Without @-threaded@,- -- I\/O and 'threadDelay' show up as 'BlockedOnOther', with @-threaded@- -- they show up as 'BlockedOnMVar'.- deriving (Eq,Ord,Show)---- | The current status of a thread-data ThreadStatus- = ThreadRunning- -- ^the thread is currently runnable or running- | ThreadFinished- -- ^the thread has finished- | ThreadBlocked BlockReason- -- ^the thread is blocked on some resource- | ThreadDied- -- ^the thread received an uncaught exception- deriving (Eq,Ord,Show)--threadStatus :: ThreadId -> IO ThreadStatus-threadStatus (ThreadId t) = IO $ \s ->- case threadStatus# t s of- (# s', stat, _cap, _locked #) -> (# s', mk_stat (I# stat) #)- where- -- NB. keep these in sync with includes/Constants.h- mk_stat 0 = ThreadRunning- mk_stat 1 = ThreadBlocked BlockedOnMVar- mk_stat 2 = ThreadBlocked BlockedOnBlackHole- mk_stat 6 = ThreadBlocked BlockedOnSTM- mk_stat 10 = ThreadBlocked BlockedOnForeignCall- mk_stat 11 = ThreadBlocked BlockedOnForeignCall- mk_stat 12 = ThreadBlocked BlockedOnException- mk_stat 16 = ThreadFinished- mk_stat 17 = ThreadDied- mk_stat _ = ThreadBlocked BlockedOnOther---- | returns the number of the capability on which the thread is currently--- running, and a boolean indicating whether the thread is locked to--- that capability or not. A thread is locked to a capability if it--- was created with @forkOn@.-threadCapability :: ThreadId -> IO (Int, Bool)-threadCapability (ThreadId t) = IO $ \s ->- case threadStatus# t s of- (# s', _, cap#, locked# #) -> (# s', (I# cap#, locked# /=# 0#) #)-\end{code}---%************************************************************************-%* *-\subsection[stm]{Transactional heap operations}-%* *-%************************************************************************--TVars are shared memory locations which support atomic memory-transactions.--\begin{code}--- |A monad supporting atomic memory transactions.-newtype STM a = STM (State# RealWorld -> (# State# RealWorld, a #))--unSTM :: STM a -> (State# RealWorld -> (# State# RealWorld, a #))-unSTM (STM a) = a--INSTANCE_TYPEABLE1(STM,stmTc,"STM")--instance Functor STM where- fmap f x = x >>= (return . f)--instance Monad STM where- {-# INLINE return #-}- {-# INLINE (>>) #-}- {-# INLINE (>>=) #-}- m >> k = thenSTM m k- return x = returnSTM x- m >>= k = bindSTM m k--bindSTM :: STM a -> (a -> STM b) -> STM b-bindSTM (STM m) k = STM ( \s ->- case m s of- (# new_s, a #) -> unSTM (k a) new_s- )--thenSTM :: STM a -> STM b -> STM b-thenSTM (STM m) k = STM ( \s ->- case m s of- (# new_s, _ #) -> unSTM k new_s- )--returnSTM :: a -> STM a-returnSTM x = STM (\s -> (# s, x #))--instance MonadPlus STM where- mzero = retry- mplus = orElse---- | Unsafely performs IO in the STM monad. Beware: this is a highly--- dangerous thing to do.------ * The STM implementation will often run transactions multiple--- times, so you need to be prepared for this if your IO has any--- side effects.------ * The STM implementation will abort transactions that are known to--- be invalid and need to be restarted. This may happen in the middle--- of `unsafeIOToSTM`, so make sure you don't acquire any resources--- that need releasing (exception handlers are ignored when aborting--- the transaction). That includes doing any IO using Handles, for--- example. Getting this wrong will probably lead to random deadlocks.------ * The transaction may have seen an inconsistent view of memory when--- the IO runs. Invariants that you expect to be true throughout--- your program may not be true inside a transaction, due to the--- way transactions are implemented. Normally this wouldn't be visible--- to the programmer, but using `unsafeIOToSTM` can expose it.----unsafeIOToSTM :: IO a -> STM a-unsafeIOToSTM (IO m) = STM m---- |Perform a series of STM actions atomically.------ You cannot use 'atomically' inside an 'unsafePerformIO' or 'unsafeInterleaveIO'.--- Any attempt to do so will result in a runtime error. (Reason: allowing--- this would effectively allow a transaction inside a transaction, depending--- on exactly when the thunk is evaluated.)------ However, see 'newTVarIO', which can be called inside 'unsafePerformIO',--- and which allows top-level TVars to be allocated.--atomically :: STM a -> IO a-atomically (STM m) = IO (\s -> (atomically# m) s )---- |Retry execution of the current memory transaction because it has seen--- values in TVars which mean that it should not continue (e.g. the TVars--- represent a shared buffer that is now empty). The implementation may--- block the thread until one of the TVars that it has read from has been--- udpated. (GHC only)-retry :: STM a-retry = STM $ \s# -> retry# s#---- |Compose two alternative STM actions (GHC only). If the first action--- completes without retrying then it forms the result of the orElse.--- Otherwise, if the first action retries, then the second action is--- tried in its place. If both actions retry then the orElse as a--- whole retries.-orElse :: STM a -> STM a -> STM a-orElse (STM m) e = STM $ \s -> catchRetry# m (unSTM e) s---- | A variant of 'throw' that can only be used within the 'STM' monad.------ Throwing an exception in @STM@ aborts the transaction and propagates the--- exception.------ Although 'throwSTM' has a type that is an instance of the type of 'throw', the--- two functions are subtly different:------ > throw e `seq` x ===> throw e--- > throwSTM e `seq` x ===> x------ The first example will cause the exception @e@ to be raised,--- whereas the second one won\'t. In fact, 'throwSTM' will only cause--- an exception to be raised when it is used within the 'STM' monad.--- The 'throwSTM' variant should be used in preference to 'throw' to--- raise an exception within the 'STM' monad because it guarantees--- ordering with respect to other 'STM' operations, whereas 'throw'--- does not.-throwSTM :: Exception e => e -> STM a-throwSTM e = STM $ raiseIO# (toException e)---- |Exception handling within STM actions.-catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a-catchSTM (STM m) handler = STM $ catchSTM# m handler'- where- handler' e = case fromException e of- Just e' -> unSTM (handler e')- Nothing -> raiseIO# e---- | Low-level primitive on which always and alwaysSucceeds are built.--- checkInv differs form these in that (i) the invariant is not--- checked when checkInv is called, only at the end of this and--- subsequent transcations, (ii) the invariant failure is indicated--- by raising an exception.-checkInv :: STM a -> STM ()-checkInv (STM m) = STM (\s -> (check# m) s)---- | alwaysSucceeds adds a new invariant that must be true when passed--- to alwaysSucceeds, at the end of the current transaction, and at--- the end of every subsequent transaction. If it fails at any--- of those points then the transaction violating it is aborted--- and the exception raised by the invariant is propagated.-alwaysSucceeds :: STM a -> STM ()-alwaysSucceeds i = do ( i >> retry ) `orElse` ( return () )- checkInv i---- | always is a variant of alwaysSucceeds in which the invariant is--- expressed as an STM Bool action that must return True. Returning--- False or raising an exception are both treated as invariant failures.-always :: STM Bool -> STM ()-always i = alwaysSucceeds ( do v <- i- if (v) then return () else ( error "Transactional invariant violation" ) )---- |Shared memory locations that support atomic memory transactions.-data TVar a = TVar (TVar# RealWorld a)--INSTANCE_TYPEABLE1(TVar,tvarTc,"TVar")--instance Eq (TVar a) where- (TVar tvar1#) == (TVar tvar2#) = sameTVar# tvar1# tvar2#---- |Create a new TVar holding a value supplied-newTVar :: a -> STM (TVar a)-newTVar val = STM $ \s1# ->- case newTVar# val s1# of- (# s2#, tvar# #) -> (# s2#, TVar tvar# #)---- |@IO@ version of 'newTVar'. This is useful for creating top-level--- 'TVar's using 'System.IO.Unsafe.unsafePerformIO', because using--- 'atomically' inside 'System.IO.Unsafe.unsafePerformIO' isn't--- possible.-newTVarIO :: a -> IO (TVar a)-newTVarIO val = IO $ \s1# ->- case newTVar# val s1# of- (# s2#, tvar# #) -> (# s2#, TVar tvar# #)---- |Return the current value stored in a TVar.--- This is equivalent to------ > readTVarIO = atomically . readTVar------ but works much faster, because it doesn't perform a complete--- transaction, it just reads the current value of the 'TVar'.-readTVarIO :: TVar a -> IO a-readTVarIO (TVar tvar#) = IO $ \s# -> readTVarIO# tvar# s#---- |Return the current value stored in a TVar-readTVar :: TVar a -> STM a-readTVar (TVar tvar#) = STM $ \s# -> readTVar# tvar# s#---- |Write the supplied value into a TVar-writeTVar :: TVar a -> a -> STM ()-writeTVar (TVar tvar#) val = STM $ \s1# ->- case writeTVar# tvar# val s1# of- s2# -> (# s2#, () #)--\end{code}--MVar utilities--\begin{code}-withMVar :: MVar a -> (a -> IO b) -> IO b-withMVar m io =- mask $ \restore -> do- a <- takeMVar m- b <- catchAny (restore (io a))- (\e -> do putMVar m a; throw e)- putMVar m a- return b--modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()-modifyMVar_ m io =- mask $ \restore -> do- a <- takeMVar m- a' <- catchAny (restore (io a))- (\e -> do putMVar m a; throw e)- putMVar m a'- return ()-\end{code}--%************************************************************************-%* *-\subsection{Thread waiting}-%* *-%************************************************************************--\begin{code}---- Machinery needed to ensureb that we only have one copy of certain--- CAFs in this module even when the base package is present twice, as--- it is when base is dynamically loaded into GHCi. The RTS keeps--- track of the single true value of the CAF, so even when the CAFs in--- the dynamically-loaded base package are reverted, nothing bad--- happens.----sharedCAF :: a -> (Ptr a -> IO (Ptr a)) -> IO a-sharedCAF a get_or_set =- mask_ $ do- stable_ref <- newStablePtr a- let ref = castPtr (castStablePtrToPtr stable_ref)- ref2 <- get_or_set ref- if ref==ref2- then return a- else do freeStablePtr stable_ref- deRefStablePtr (castPtrToStablePtr (castPtr ref2))--reportStackOverflow :: IO ()-reportStackOverflow = callStackOverflowHook--reportError :: SomeException -> IO ()-reportError ex = do- handler <- getUncaughtExceptionHandler- handler ex---- SUP: Are the hooks allowed to re-enter Haskell land? If so, remove--- the unsafe below.-foreign import ccall unsafe "stackOverflow"- callStackOverflowHook :: IO ()--{-# NOINLINE uncaughtExceptionHandler #-}-uncaughtExceptionHandler :: IORef (SomeException -> IO ())-uncaughtExceptionHandler = unsafePerformIO (newIORef defaultHandler)- where- defaultHandler :: SomeException -> IO ()- defaultHandler se@(SomeException ex) = do- (hFlush stdout) `catchAny` (\ _ -> return ())- let msg = case cast ex of- Just Deadlock -> "no threads to run: infinite loop or deadlock?"- _ -> case cast ex of- Just (ErrorCall s) -> s- _ -> showsPrec 0 se ""- withCString "%s" $ \cfmt ->- withCString msg $ \cmsg ->- errorBelch cfmt cmsg---- don't use errorBelch() directly, because we cannot call varargs functions--- using the FFI.-foreign import ccall unsafe "HsBase.h errorBelch2"- errorBelch :: CString -> CString -> IO ()--setUncaughtExceptionHandler :: (SomeException -> IO ()) -> IO ()-setUncaughtExceptionHandler = writeIORef uncaughtExceptionHandler--getUncaughtExceptionHandler :: IO (SomeException -> IO ())-getUncaughtExceptionHandler = readIORef uncaughtExceptionHandler--\end{code}
@@ -1,327 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples, ForeignFunctionInterface,- DeriveDataTypeable #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}-{-# OPTIONS_HADDOCK not-home #-}---------------------------------------------------------------------------------- |--- Module : GHC.Conc.Windows--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Windows I/O manager------------------------------------------------------------------------------------- #not-home-module GHC.Conc.Windows- ( ensureIOManagerIsRunning-- -- * Waiting- , threadDelay- , registerDelay-- -- * Miscellaneous- , asyncRead -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)- , asyncWrite -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)- , asyncDoProc -- :: FunPtr (Ptr a -> IO Int) -> Ptr a -> IO Int-- , asyncReadBA -- :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int, Int)- , asyncWriteBA -- :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int, Int)-- , ConsoleEvent(..)- , win32ConsoleHandler- , toWin32ConsoleEvent- ) where--import Control.Monad-import Data.Bits (shiftR)-import Data.Maybe (Maybe(..))-import Data.Typeable-import GHC.Base-import GHC.Conc.Sync-import GHC.Enum (Enum)-import GHC.IO (unsafePerformIO)-import GHC.IORef-import GHC.MVar-import GHC.Num (Num(..))-import GHC.Ptr-import GHC.Read (Read)-import GHC.Real (div, fromIntegral)-import GHC.Show (Show)-import GHC.Word (Word32, Word64)-import GHC.Windows---- ------------------------------------------------------------------------------- Thread waiting---- Note: threadWaitRead and threadWaitWrite aren't really functional--- on Win32, but left in there because lib code (still) uses them (the manner--- in which they're used doesn't cause problems on a Win32 platform though.)--asyncRead :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)-asyncRead (I# fd) (I# isSock) (I# len) (Ptr buf) =- IO $ \s -> case asyncRead# fd isSock len buf s of- (# s', len#, err# #) -> (# s', (I# len#, I# err#) #)--asyncWrite :: Int -> Int -> Int -> Ptr a -> IO (Int, Int)-asyncWrite (I# fd) (I# isSock) (I# len) (Ptr buf) =- IO $ \s -> case asyncWrite# fd isSock len buf s of- (# s', len#, err# #) -> (# s', (I# len#, I# err#) #)--asyncDoProc :: FunPtr (Ptr a -> IO Int) -> Ptr a -> IO Int-asyncDoProc (FunPtr proc) (Ptr param) =- -- the 'length' value is ignored; simplifies implementation of- -- the async*# primops to have them all return the same result.- IO $ \s -> case asyncDoProc# proc param s of- (# s', _len#, err# #) -> (# s', I# err# #)---- to aid the use of these primops by the IO Handle implementation,--- provide the following convenience funs:---- this better be a pinned byte array!-asyncReadBA :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int,Int)-asyncReadBA fd isSock len off bufB =- asyncRead fd isSock len ((Ptr (byteArrayContents# (unsafeCoerce# bufB))) `plusPtr` off)--asyncWriteBA :: Int -> Int -> Int -> Int -> MutableByteArray# RealWorld -> IO (Int,Int)-asyncWriteBA fd isSock len off bufB =- asyncWrite fd isSock len ((Ptr (byteArrayContents# (unsafeCoerce# bufB))) `plusPtr` off)---- ------------------------------------------------------------------------------- Threaded RTS implementation of threadDelay---- | Suspends the current thread for a given number of microseconds--- (GHC only).------ There is no guarantee that the thread will be rescheduled promptly--- when the delay has expired, but the thread will never continue to--- run /earlier/ than specified.----threadDelay :: Int -> IO ()-threadDelay time- | threaded = waitForDelayEvent time- | otherwise = IO $ \s ->- case time of { I# time# ->- case delay# time# s of { s' -> (# s', () #)- }}---- | Set the value of returned TVar to True after a given number of--- microseconds. The caveats associated with threadDelay also apply.----registerDelay :: Int -> IO (TVar Bool)-registerDelay usecs- | threaded = waitForDelayEventSTM usecs- | otherwise = error "registerDelay: requires -threaded"--foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool--waitForDelayEvent :: Int -> IO ()-waitForDelayEvent usecs = do- m <- newEmptyMVar- target <- calculateTarget usecs- atomicModifyIORef pendingDelays (\xs -> (Delay target m : xs, ()))- prodServiceThread- takeMVar m---- Delays for use in STM-waitForDelayEventSTM :: Int -> IO (TVar Bool)-waitForDelayEventSTM usecs = do- t <- atomically $ newTVar False- target <- calculateTarget usecs- atomicModifyIORef pendingDelays (\xs -> (DelaySTM target t : xs, ()))- prodServiceThread- return t--calculateTarget :: Int -> IO USecs-calculateTarget usecs = do- now <- getUSecOfDay- return $ now + (fromIntegral usecs)--data DelayReq- = Delay {-# UNPACK #-} !USecs {-# UNPACK #-} !(MVar ())- | DelaySTM {-# UNPACK #-} !USecs {-# UNPACK #-} !(TVar Bool)--{-# NOINLINE pendingDelays #-}-pendingDelays :: IORef [DelayReq]-pendingDelays = unsafePerformIO $ do- m <- newIORef []- sharedCAF m getOrSetGHCConcWindowsPendingDelaysStore--foreign import ccall unsafe "getOrSetGHCConcWindowsPendingDelaysStore"- getOrSetGHCConcWindowsPendingDelaysStore :: Ptr a -> IO (Ptr a)--{-# NOINLINE ioManagerThread #-}-ioManagerThread :: MVar (Maybe ThreadId)-ioManagerThread = unsafePerformIO $ do- m <- newMVar Nothing- sharedCAF m getOrSetGHCConcWindowsIOManagerThreadStore--foreign import ccall unsafe "getOrSetGHCConcWindowsIOManagerThreadStore"- getOrSetGHCConcWindowsIOManagerThreadStore :: Ptr a -> IO (Ptr a)--ensureIOManagerIsRunning :: IO ()-ensureIOManagerIsRunning- | threaded = startIOManagerThread- | otherwise = return ()--startIOManagerThread :: IO ()-startIOManagerThread = do- modifyMVar_ ioManagerThread $ \old -> do- let create = do t <- forkIO ioManager; return (Just t)- case old of- Nothing -> create- Just t -> do- s <- threadStatus t- case s of- ThreadFinished -> create- ThreadDied -> create- _other -> return (Just t)--insertDelay :: DelayReq -> [DelayReq] -> [DelayReq]-insertDelay d [] = [d]-insertDelay d1 ds@(d2 : rest)- | delayTime d1 <= delayTime d2 = d1 : ds- | otherwise = d2 : insertDelay d1 rest--delayTime :: DelayReq -> USecs-delayTime (Delay t _) = t-delayTime (DelaySTM t _) = t--type USecs = Word64--foreign import ccall unsafe "getUSecOfDay"- getUSecOfDay :: IO USecs--{-# NOINLINE prodding #-}-prodding :: IORef Bool-prodding = unsafePerformIO $ do- r <- newIORef False- sharedCAF r getOrSetGHCConcWindowsProddingStore--foreign import ccall unsafe "getOrSetGHCConcWindowsProddingStore"- getOrSetGHCConcWindowsProddingStore :: Ptr a -> IO (Ptr a)--prodServiceThread :: IO ()-prodServiceThread = do- -- NB. use atomicModifyIORef here, otherwise there are race- -- conditions in which prodding is left at True but the server is- -- blocked in select().- was_set <- atomicModifyIORef prodding $ \b -> (True,b)- unless was_set wakeupIOManager---- ------------------------------------------------------------------------------- Windows IO manager thread--ioManager :: IO ()-ioManager = do- wakeup <- c_getIOManagerEvent- service_loop wakeup []--service_loop :: HANDLE -- read end of pipe- -> [DelayReq] -- current delay requests- -> IO ()--service_loop wakeup old_delays = do- -- pick up new delay requests- new_delays <- atomicModifyIORef pendingDelays (\a -> ([],a))- let delays = foldr insertDelay old_delays new_delays-- now <- getUSecOfDay- (delays', timeout) <- getDelay now delays-- r <- c_WaitForSingleObject wakeup timeout- case r of- 0xffffffff -> do throwGetLastError "service_loop"- 0 -> do- r2 <- c_readIOManagerEvent- exit <-- case r2 of- _ | r2 == io_MANAGER_WAKEUP -> return False- _ | r2 == io_MANAGER_DIE -> return True- 0 -> return False -- spurious wakeup- _ -> do start_console_handler (r2 `shiftR` 1); return False- unless exit $ service_cont wakeup delays'-- _other -> service_cont wakeup delays' -- probably timeout--service_cont :: HANDLE -> [DelayReq] -> IO ()-service_cont wakeup delays = do- r <- atomicModifyIORef prodding (\_ -> (False,False))- r `seq` return () -- avoid space leak- service_loop wakeup delays---- must agree with rts/win32/ThrIOManager.c-io_MANAGER_WAKEUP, io_MANAGER_DIE :: Word32-io_MANAGER_WAKEUP = 0xffffffff-io_MANAGER_DIE = 0xfffffffe--data ConsoleEvent- = ControlC- | Break- | Close- -- these are sent to Services only.- | Logoff- | Shutdown- deriving (Eq, Ord, Enum, Show, Read, Typeable)--start_console_handler :: Word32 -> IO ()-start_console_handler r =- case toWin32ConsoleEvent r of- Just x -> withMVar win32ConsoleHandler $ \handler -> do- _ <- forkIO (handler x)- return ()- Nothing -> return ()--toWin32ConsoleEvent :: (Eq a, Num a) => a -> Maybe ConsoleEvent-toWin32ConsoleEvent ev =- case ev of- 0 {- CTRL_C_EVENT-} -> Just ControlC- 1 {- CTRL_BREAK_EVENT-} -> Just Break- 2 {- CTRL_CLOSE_EVENT-} -> Just Close- 5 {- CTRL_LOGOFF_EVENT-} -> Just Logoff- 6 {- CTRL_SHUTDOWN_EVENT-} -> Just Shutdown- _ -> Nothing--win32ConsoleHandler :: MVar (ConsoleEvent -> IO ())-win32ConsoleHandler = unsafePerformIO (newMVar (error "win32ConsoleHandler"))--wakeupIOManager :: IO ()-wakeupIOManager = c_sendIOManagerEvent io_MANAGER_WAKEUP---- Walk the queue of pending delays, waking up any that have passed--- and return the smallest delay to wait for. The queue of pending--- delays is kept ordered.-getDelay :: USecs -> [DelayReq] -> IO ([DelayReq], DWORD)-getDelay _ [] = return ([], iNFINITE)-getDelay now all@(d : rest)- = case d of- Delay time m | now >= time -> do- putMVar m ()- getDelay now rest- DelaySTM time t | now >= time -> do- atomically $ writeTVar t True- getDelay now rest- _otherwise ->- -- delay is in millisecs for WaitForSingleObject- let micro_seconds = delayTime d - now- milli_seconds = (micro_seconds + 999) `div` 1000- in return (all, fromIntegral milli_seconds)--foreign import ccall unsafe "getIOManagerEvent" -- in the RTS (ThrIOManager.c)- c_getIOManagerEvent :: IO HANDLE--foreign import ccall unsafe "readIOManagerEvent" -- in the RTS (ThrIOManager.c)- c_readIOManagerEvent :: IO Word32--foreign import ccall unsafe "sendIOManagerEvent" -- in the RTS (ThrIOManager.c)- c_sendIOManagerEvent :: Word32 -> IO ()--foreign import stdcall "WaitForSingleObject"- c_WaitForSingleObject :: HANDLE -> DWORD -> IO DWORD-
@@ -1,158 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, ForeignFunctionInterface #-}---------------------------------------------------------------------------------- |--- Module : GHC.ConsoleHandler--- Copyright : (c) The University of Glasgow--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ NB. the contents of this module are only available on Windows.------ Installing Win32 console handlers.--- --------------------------------------------------------------------------------module GHC.ConsoleHandler-#if !defined(mingw32_HOST_OS) && !defined(__HADDOCK__)- where-#else /* whole file */- ( Handler(..)- , installHandler- , ConsoleEvent(..)- , flushConsole- ) where--{--#include "rts/Signals.h"--Note: this #include is inside a Haskell comment- but it brings into scope some #defines- that are used by CPP below (eg STG_SIG_DFL).- Having it in a comment means that there's no- danger that C-like crap will be misunderstood- by GHC--}--import Foreign-import Foreign.C-import GHC.IO.FD-import GHC.IO.Exception-import GHC.IO.Handle.Types-import GHC.IO.Handle.Internals-import GHC.Conc-import Control.Concurrent.MVar-import Data.Typeable--data Handler- = Default- | Ignore- | Catch (ConsoleEvent -> IO ())---- | Allows Windows console events to be caught and handled. To--- handle a console event, call 'installHandler' passing the--- appropriate 'Handler' value. When the event is received, if the--- 'Handler' value is @Catch f@, then a new thread will be spawned by--- the system to execute @f e@, where @e@ is the 'ConsoleEvent' that--- was received.------ Note that console events can only be received by an application--- running in a Windows console. Certain environments that look like consoles--- do not support console events, these include:------ * Cygwin shells with @CYGWIN=tty@ set (if you don't set @CYGWIN=tty@,--- then a Cygwin shell behaves like a Windows console).--- * Cygwin xterm and rxvt windows--- * MSYS rxvt windows------ In order for your application to receive console events, avoid running--- it in one of these environments.----installHandler :: Handler -> IO Handler-installHandler handler- | threaded =- modifyMVar win32ConsoleHandler $ \old_h -> do- (new_h,rc) <-- case handler of- Default -> do- r <- rts_installHandler STG_SIG_DFL nullPtr- return (no_handler, r)- Ignore -> do- r <- rts_installHandler STG_SIG_IGN nullPtr- return (no_handler, r)- Catch h -> do- r <- rts_installHandler STG_SIG_HAN nullPtr- return (h, r)- prev_handler <-- case rc of- STG_SIG_DFL -> return Default- STG_SIG_IGN -> return Ignore- STG_SIG_HAN -> return (Catch old_h)- _ -> error "installHandler: Bad threaded rc value"- return (new_h, prev_handler)-- | otherwise =- alloca $ \ p_sp -> do- rc <-- case handler of- Default -> rts_installHandler STG_SIG_DFL p_sp- Ignore -> rts_installHandler STG_SIG_IGN p_sp- Catch h -> do- v <- newStablePtr (toHandler h)- poke p_sp v- rts_installHandler STG_SIG_HAN p_sp- case rc of- STG_SIG_DFL -> return Default- STG_SIG_IGN -> return Ignore- STG_SIG_HAN -> do- osptr <- peek p_sp- oldh <- deRefStablePtr osptr- -- stable pointer is no longer in use, free it.- freeStablePtr osptr- return (Catch (\ ev -> oldh (fromConsoleEvent ev)))- _ -> error "installHandler: Bad non-threaded rc value"- where- fromConsoleEvent ev =- case ev of- ControlC -> 0 {- CTRL_C_EVENT-}- Break -> 1 {- CTRL_BREAK_EVENT-}- Close -> 2 {- CTRL_CLOSE_EVENT-}- Logoff -> 5 {- CTRL_LOGOFF_EVENT-}- Shutdown -> 6 {- CTRL_SHUTDOWN_EVENT-}-- toHandler hdlr ev = do- case toWin32ConsoleEvent ev of- -- see rts/win32/ConsoleHandler.c for comments as to why- -- rts_ConsoleHandlerDone is called here.- Just x -> hdlr x >> rts_ConsoleHandlerDone ev- Nothing -> return () -- silently ignore..-- no_handler = error "win32ConsoleHandler"--foreign import ccall "rtsSupportsBoundThreads" threaded :: Bool--foreign import ccall unsafe "RtsExternal.h rts_InstallConsoleEvent" - rts_installHandler :: CInt -> Ptr (StablePtr (CInt -> IO ())) -> IO CInt-foreign import ccall unsafe "RtsExternal.h rts_ConsoleHandlerDone"- rts_ConsoleHandlerDone :: CInt -> IO ()---flushConsole :: Handle -> IO ()-flushConsole h =- wantReadableHandle_ "flushConsole" h $ \ Handle__{haDevice=dev} ->- case cast dev of- Nothing -> ioException $- IOError (Just h) IllegalOperation "flushConsole"- "handle is not a file descriptor" Nothing Nothing- Just fd -> do- throwErrnoIfMinus1Retry_ "flushConsole" $- flush_console_fd (fdFD fd)--foreign import ccall unsafe "consUtils.h flush_input_console__"- flush_console_fd :: CInt -> IO CInt--#endif /* mingw32_HOST_OS */
@@ -1,12 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}--module GHC.Constants where--import Prelude---- We use stage1 here, because that's guaranteed to exist-#include "../../../compiler/stage1/ghc_boot_platform.h"--#include "../../../includes/HaskellConstants.hs"-
@@ -1,44 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , Rank2Types- , ExistentialQuantification- #-}---------------------------------------------------------------------------------- |--- Module : GHC.Desugar--- Copyright : (c) The University of Glasgow, 2007--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Support code for desugaring in GHC--- ---------------------------------------------------------------------------------- #hide-module GHC.Desugar ((>>>), AnnotationWrapper(..), toAnnotationWrapper) where--import Control.Arrow (Arrow(..))-import Control.Category ((.))-import Data.Data (Data)---- A version of Control.Category.>>> overloaded on Arrow-#ifndef __HADDOCK__-(>>>) :: forall arr. Arrow arr => forall a b c. arr a b -> arr b c -> arr a c-#endif--- NB: the type of this function is the "shape" that GHC expects--- in tcInstClassOp. So don't put all the foralls at the front! --- Yes, this is a bit grotesque, but heck it works and the whole--- arrows stuff needs reworking anyway!-f >>> g = g . f---- A wrapper data type that lets the typechecker get at the appropriate dictionaries for an annotation-data AnnotationWrapper = forall a. (Data a) => AnnotationWrapper a--toAnnotationWrapper :: (Data a) => a -> AnnotationWrapper-toAnnotationWrapper what = AnnotationWrapper what-
@@ -1,699 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, BangPatterns, MagicHash #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Enum--- Copyright : (c) The University of Glasgow, 1992-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ The 'Enum' and 'Bounded' classes.--- ---------------------------------------------------------------------------------- #hide-module GHC.Enum(- Bounded(..), Enum(..),- boundedEnumFrom, boundedEnumFromThen,- toEnumError, fromEnumError, succError, predError,-- -- Instances for Bounded and Enum: (), Char, Int-- ) where--import GHC.Base-import GHC.Integer-import GHC.Num-import GHC.Show-import Data.Tuple () -- for dependencies-default () -- Double isn't available yet-\end{code}---%*********************************************************-%* *-\subsection{Class declarations}-%* *-%*********************************************************--\begin{code}--- | The 'Bounded' class is used to name the upper and lower limits of a--- type. 'Ord' is not a superclass of 'Bounded' since types that are not--- totally ordered may also have upper and lower bounds.------ The 'Bounded' class may be derived for any enumeration type;--- 'minBound' is the first constructor listed in the @data@ declaration--- and 'maxBound' is the last.--- 'Bounded' may also be derived for single-constructor datatypes whose--- constituent types are in 'Bounded'.--class Bounded a where- minBound, maxBound :: a---- | Class 'Enum' defines operations on sequentially ordered types.------ The @enumFrom@... methods are used in Haskell's translation of--- arithmetic sequences.------ Instances of 'Enum' may be derived for any enumeration type (types--- whose constructors have no fields). The nullary constructors are--- assumed to be numbered left-to-right by 'fromEnum' from @0@ through @n-1@.--- See Chapter 10 of the /Haskell Report/ for more details.--- --- For any type that is an instance of class 'Bounded' as well as 'Enum',--- the following should hold:------ * The calls @'succ' 'maxBound'@ and @'pred' 'minBound'@ should result in--- a runtime error.--- --- * 'fromEnum' and 'toEnum' should give a runtime error if the --- result value is not representable in the result type.--- For example, @'toEnum' 7 :: 'Bool'@ is an error.------ * 'enumFrom' and 'enumFromThen' should be defined with an implicit bound,--- thus:------ > enumFrom x = enumFromTo x maxBound--- > enumFromThen x y = enumFromThenTo x y bound--- > where--- > bound | fromEnum y >= fromEnum x = maxBound--- > | otherwise = minBound----class Enum a where- -- | the successor of a value. For numeric types, 'succ' adds 1.- succ :: a -> a- -- | the predecessor of a value. For numeric types, 'pred' subtracts 1.- pred :: a -> a- -- | Convert from an 'Int'.- toEnum :: Int -> a- -- | Convert to an 'Int'.- -- It is implementation-dependent what 'fromEnum' returns when- -- applied to a value that is too large to fit in an 'Int'.- fromEnum :: a -> Int-- -- | Used in Haskell's translation of @[n..]@.- enumFrom :: a -> [a]- -- | Used in Haskell's translation of @[n,n'..]@.- enumFromThen :: a -> a -> [a]- -- | Used in Haskell's translation of @[n..m]@.- enumFromTo :: a -> a -> [a]- -- | Used in Haskell's translation of @[n,n'..m]@.- enumFromThenTo :: a -> a -> a -> [a]-- succ = toEnum . (`plusInt` oneInt) . fromEnum- pred = toEnum . (`minusInt` oneInt) . fromEnum- enumFrom x = map toEnum [fromEnum x ..]- enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]- enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]- enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]---- Default methods for bounded enumerations-boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]-boundedEnumFrom n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]--boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]-boundedEnumFromThen n1 n2 - | i_n2 >= i_n1 = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]- | otherwise = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]- where- i_n1 = fromEnum n1- i_n2 = fromEnum n2-\end{code}--\begin{code}---------------------------------------------------------------------------- Helper functions---------------------------------------------------------------------------{-# NOINLINE toEnumError #-}-toEnumError :: (Show a) => String -> Int -> (a,a) -> b-toEnumError inst_ty i bnds =- error $ "Enum.toEnum{" ++ inst_ty ++ "}: tag (" ++- show i ++- ") is outside of bounds " ++- show bnds--{-# NOINLINE fromEnumError #-}-fromEnumError :: (Show a) => String -> a -> b-fromEnumError inst_ty x =- error $ "Enum.fromEnum{" ++ inst_ty ++ "}: value (" ++- show x ++- ") is outside of Int's bounds " ++- show (minBound::Int, maxBound::Int)--{-# NOINLINE succError #-}-succError :: String -> a-succError inst_ty =- error $ "Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound"--{-# NOINLINE predError #-}-predError :: String -> a-predError inst_ty =- error $ "Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound"-\end{code}---%*********************************************************-%* *-\subsection{Tuples}-%* *-%*********************************************************--\begin{code}-instance Bounded () where- minBound = ()- maxBound = ()--instance Enum () where- succ _ = error "Prelude.Enum.().succ: bad argument"- pred _ = error "Prelude.Enum.().pred: bad argument"-- toEnum x | x == zeroInt = ()- | otherwise = error "Prelude.Enum.().toEnum: bad argument"-- fromEnum () = zeroInt- enumFrom () = [()]- enumFromThen () () = let many = ():many in many- enumFromTo () () = [()]- enumFromThenTo () () () = let many = ():many in many-\end{code}--\begin{code}--- Report requires instances up to 15-instance (Bounded a, Bounded b) => Bounded (a,b) where- minBound = (minBound, minBound)- maxBound = (maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c) => Bounded (a,b,c) where- minBound = (minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d) => Bounded (a,b,c,d) where- minBound = (minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e) => Bounded (a,b,c,d,e) where- minBound = (minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f)- => Bounded (a,b,c,d,e,f) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g)- => Bounded (a,b,c,d,e,f,g) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h)- => Bounded (a,b,c,d,e,f,g,h) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i)- => Bounded (a,b,c,d,e,f,g,h,i) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i, Bounded j)- => Bounded (a,b,c,d,e,f,g,h,i,j) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i, Bounded j, Bounded k)- => Bounded (a,b,c,d,e,f,g,h,i,j,k) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i, Bounded j, Bounded k, Bounded l)- => Bounded (a,b,c,d,e,f,g,h,i,j,k,l) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m)- => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound, maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded n)- => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound, minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)--instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,- Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded n, Bounded o)- => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where- minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,- minBound, minBound, minBound, minBound, minBound, minBound, minBound)- maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,- maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)-\end{code}---%*********************************************************-%* *-\subsection{Type @Bool@}-%* *-%*********************************************************--\begin{code}-instance Bounded Bool where- minBound = False- maxBound = True--instance Enum Bool where- succ False = True- succ True = error "Prelude.Enum.Bool.succ: bad argument"-- pred True = False- pred False = error "Prelude.Enum.Bool.pred: bad argument"-- toEnum n | n == zeroInt = False- | n == oneInt = True- | otherwise = error "Prelude.Enum.Bool.toEnum: bad argument"-- fromEnum False = zeroInt- fromEnum True = oneInt-- -- Use defaults for the rest- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen-\end{code}--%*********************************************************-%* *-\subsection{Type @Ordering@}-%* *-%*********************************************************--\begin{code}-instance Bounded Ordering where- minBound = LT- maxBound = GT--instance Enum Ordering where- succ LT = EQ- succ EQ = GT- succ GT = error "Prelude.Enum.Ordering.succ: bad argument"-- pred GT = EQ- pred EQ = LT- pred LT = error "Prelude.Enum.Ordering.pred: bad argument"-- toEnum n | n == zeroInt = LT- | n == oneInt = EQ- | n == twoInt = GT- toEnum _ = error "Prelude.Enum.Ordering.toEnum: bad argument"-- fromEnum LT = zeroInt- fromEnum EQ = oneInt- fromEnum GT = twoInt-- -- Use defaults for the rest- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen-\end{code}--%*********************************************************-%* *-\subsection{Type @Char@}-%* *-%*********************************************************--\begin{code}-instance Bounded Char where- minBound = '\0'- maxBound = '\x10FFFF'--instance Enum Char where- succ (C# c#)- | not (ord# c# ==# 0x10FFFF#) = C# (chr# (ord# c# +# 1#))- | otherwise = error ("Prelude.Enum.Char.succ: bad argument")- pred (C# c#)- | not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))- | otherwise = error ("Prelude.Enum.Char.pred: bad argument")-- toEnum = chr- fromEnum = ord-- {-# INLINE enumFrom #-}- enumFrom (C# x) = eftChar (ord# x) 0x10FFFF#- -- Blarg: technically I guess enumFrom isn't strict!-- {-# INLINE enumFromTo #-}- enumFromTo (C# x) (C# y) = eftChar (ord# x) (ord# y)- - {-# INLINE enumFromThen #-}- enumFromThen (C# x1) (C# x2) = efdChar (ord# x1) (ord# x2)- - {-# INLINE enumFromThenTo #-}- enumFromThenTo (C# x1) (C# x2) (C# y) = efdtChar (ord# x1) (ord# x2) (ord# y)--{-# RULES-"eftChar" [~1] forall x y. eftChar x y = build (\c n -> eftCharFB c n x y)-"efdChar" [~1] forall x1 x2. efdChar x1 x2 = build (\ c n -> efdCharFB c n x1 x2)-"efdtChar" [~1] forall x1 x2 l. efdtChar x1 x2 l = build (\ c n -> efdtCharFB c n x1 x2 l)-"eftCharList" [1] eftCharFB (:) [] = eftChar-"efdCharList" [1] efdCharFB (:) [] = efdChar-"efdtCharList" [1] efdtCharFB (:) [] = efdtChar- #-}----- We can do better than for Ints because we don't--- have hassles about arithmetic overflow at maxBound-{-# INLINE [0] eftCharFB #-}-eftCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> a-eftCharFB c n x0 y = go x0- where- go x | x ># y = n- | otherwise = C# (chr# x) `c` go (x +# 1#)--eftChar :: Int# -> Int# -> String-eftChar x y | x ># y = []- | otherwise = C# (chr# x) : eftChar (x +# 1#) y----- For enumFromThenTo we give up on inlining-{-# NOINLINE [0] efdCharFB #-}-efdCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> a-efdCharFB c n x1 x2- | delta >=# 0# = go_up_char_fb c n x1 delta 0x10FFFF#- | otherwise = go_dn_char_fb c n x1 delta 0#- where- !delta = x2 -# x1--efdChar :: Int# -> Int# -> String-efdChar x1 x2- | delta >=# 0# = go_up_char_list x1 delta 0x10FFFF#- | otherwise = go_dn_char_list x1 delta 0#- where- !delta = x2 -# x1--{-# NOINLINE [0] efdtCharFB #-}-efdtCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> Int# -> a-efdtCharFB c n x1 x2 lim- | delta >=# 0# = go_up_char_fb c n x1 delta lim- | otherwise = go_dn_char_fb c n x1 delta lim- where- !delta = x2 -# x1--efdtChar :: Int# -> Int# -> Int# -> String-efdtChar x1 x2 lim- | delta >=# 0# = go_up_char_list x1 delta lim- | otherwise = go_dn_char_list x1 delta lim- where- !delta = x2 -# x1--go_up_char_fb :: (Char -> a -> a) -> a -> Int# -> Int# -> Int# -> a-go_up_char_fb c n x0 delta lim- = go_up x0- where- go_up x | x ># lim = n- | otherwise = C# (chr# x) `c` go_up (x +# delta)--go_dn_char_fb :: (Char -> a -> a) -> a -> Int# -> Int# -> Int# -> a-go_dn_char_fb c n x0 delta lim- = go_dn x0- where- go_dn x | x <# lim = n- | otherwise = C# (chr# x) `c` go_dn (x +# delta)--go_up_char_list :: Int# -> Int# -> Int# -> String-go_up_char_list x0 delta lim- = go_up x0- where- go_up x | x ># lim = []- | otherwise = C# (chr# x) : go_up (x +# delta)--go_dn_char_list :: Int# -> Int# -> Int# -> String-go_dn_char_list x0 delta lim- = go_dn x0- where- go_dn x | x <# lim = []- | otherwise = C# (chr# x) : go_dn (x +# delta)-\end{code}---%*********************************************************-%* *-\subsection{Type @Int@}-%* *-%*********************************************************--Be careful about these instances. - (a) remember that you have to count down as well as up e.g. [13,12..0]- (b) be careful of Int overflow- (c) remember that Int is bounded, so [1..] terminates at maxInt--Also NB that the Num class isn't available in this module.- -\begin{code}-instance Bounded Int where- minBound = minInt- maxBound = maxInt--instance Enum Int where- succ x - | x == maxBound = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"- | otherwise = x `plusInt` oneInt- pred x- | x == minBound = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"- | otherwise = x `minusInt` oneInt-- toEnum x = x- fromEnum x = x-- {-# INLINE enumFrom #-}- enumFrom (I# x) = eftInt x maxInt#- where !(I# maxInt#) = maxInt- -- Blarg: technically I guess enumFrom isn't strict!-- {-# INLINE enumFromTo #-}- enumFromTo (I# x) (I# y) = eftInt x y-- {-# INLINE enumFromThen #-}- enumFromThen (I# x1) (I# x2) = efdInt x1 x2-- {-# INLINE enumFromThenTo #-}- enumFromThenTo (I# x1) (I# x2) (I# y) = efdtInt x1 x2 y----------------------------------------------------------- eftInt and eftIntFB deal with [a..b], which is the --- most common form, so we take a lot of care--- In particular, we have rules for deforestation--{-# RULES-"eftInt" [~1] forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)-"eftIntList" [1] eftIntFB (:) [] = eftInt- #-}--eftInt :: Int# -> Int# -> [Int]--- [x1..x2]-eftInt x0 y | x0 ># y = []- | otherwise = go x0- where- go x = I# x : if x ==# y then [] else go (x +# 1#)--{-# INLINE [0] eftIntFB #-}-eftIntFB :: (Int -> r -> r) -> r -> Int# -> Int# -> r-eftIntFB c n x0 y | x0 ># y = n - | otherwise = go x0- where- go x = I# x `c` if x ==# y then n else go (x +# 1#)- -- Watch out for y=maxBound; hence ==, not >- -- Be very careful not to have more than one "c"- -- so that when eftInfFB is inlined we can inline- -- whatever is bound to "c"----------------------------------------------------------- efdInt and efdtInt deal with [a,b..] and [a,b..c].--- The code is more complicated because of worries about Int overflow.--{-# RULES-"efdtInt" [~1] forall x1 x2 y.- efdtInt x1 x2 y = build (\ c n -> efdtIntFB c n x1 x2 y)-"efdtIntUpList" [1] efdtIntFB (:) [] = efdtInt- #-}--efdInt :: Int# -> Int# -> [Int]--- [x1,x2..maxInt]-efdInt x1 x2 - | x2 >=# x1 = case maxInt of I# y -> efdtIntUp x1 x2 y- | otherwise = case minInt of I# y -> efdtIntDn x1 x2 y--efdtInt :: Int# -> Int# -> Int# -> [Int]--- [x1,x2..y]-efdtInt x1 x2 y- | x2 >=# x1 = efdtIntUp x1 x2 y- | otherwise = efdtIntDn x1 x2 y--{-# INLINE [0] efdtIntFB #-}-efdtIntFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r-efdtIntFB c n x1 x2 y- | x2 >=# x1 = efdtIntUpFB c n x1 x2 y- | otherwise = efdtIntDnFB c n x1 x2 y---- Requires x2 >= x1-efdtIntUp :: Int# -> Int# -> Int# -> [Int]-efdtIntUp x1 x2 y -- Be careful about overflow!- | y <# x2 = if y <# x1 then [] else [I# x1]- | otherwise = -- Common case: x1 <= x2 <= y- let !delta = x2 -# x1 -- >= 0- !y' = y -# delta -- x1 <= y' <= y; hence y' is representable-- -- Invariant: x <= y- -- Note that: z <= y' => z + delta won't overflow- -- so we are guaranteed not to overflow if/when we recurse- go_up x | x ># y' = [I# x]- | otherwise = I# x : go_up (x +# delta)- in I# x1 : go_up x2---- Requires x2 >= x1-efdtIntUpFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r-efdtIntUpFB c n x1 x2 y -- Be careful about overflow!- | y <# x2 = if y <# x1 then n else I# x1 `c` n- | otherwise = -- Common case: x1 <= x2 <= y- let !delta = x2 -# x1 -- >= 0- !y' = y -# delta -- x1 <= y' <= y; hence y' is representable-- -- Invariant: x <= y- -- Note that: z <= y' => z + delta won't overflow- -- so we are guaranteed not to overflow if/when we recurse- go_up x | x ># y' = I# x `c` n- | otherwise = I# x `c` go_up (x +# delta)- in I# x1 `c` go_up x2---- Requires x2 <= x1-efdtIntDn :: Int# -> Int# -> Int# -> [Int]-efdtIntDn x1 x2 y -- Be careful about underflow!- | y ># x2 = if y ># x1 then [] else [I# x1]- | otherwise = -- Common case: x1 >= x2 >= y- let !delta = x2 -# x1 -- <= 0- !y' = y -# delta -- y <= y' <= x1; hence y' is representable-- -- Invariant: x >= y- -- Note that: z >= y' => z + delta won't underflow- -- so we are guaranteed not to underflow if/when we recurse- go_dn x | x <# y' = [I# x]- | otherwise = I# x : go_dn (x +# delta)- in I# x1 : go_dn x2---- Requires x2 <= x1-efdtIntDnFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r-efdtIntDnFB c n x1 x2 y -- Be careful about underflow!- | y ># x2 = if y ># x1 then n else I# x1 `c` n- | otherwise = -- Common case: x1 >= x2 >= y- let !delta = x2 -# x1 -- <= 0- !y' = y -# delta -- y <= y' <= x1; hence y' is representable-- -- Invariant: x >= y- -- Note that: z >= y' => z + delta won't underflow- -- so we are guaranteed not to underflow if/when we recurse- go_dn x | x <# y' = I# x `c` n- | otherwise = I# x `c` go_dn (x +# delta)- in I# x1 `c` go_dn x2-\end{code}---%*********************************************************-%* *-\subsection{The @Integer@ instance for @Enum@}-%* *-%*********************************************************--\begin{code}-instance Enum Integer where- succ x = x + 1- pred x = x - 1- toEnum (I# n) = smallInteger n- fromEnum n = I# (integerToInt n)-- {-# INLINE enumFrom #-}- {-# INLINE enumFromThen #-}- {-# INLINE enumFromTo #-}- {-# INLINE enumFromThenTo #-}- enumFrom x = enumDeltaInteger x 1- enumFromThen x y = enumDeltaInteger x (y-x)- enumFromTo x lim = enumDeltaToInteger x 1 lim- enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim--{-# RULES-"enumDeltaInteger" [~1] forall x y. enumDeltaInteger x y = build (\c _ -> enumDeltaIntegerFB c x y)-"efdtInteger" [~1] forall x y l.enumDeltaToInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l)-"enumDeltaInteger" [1] enumDeltaIntegerFB (:) = enumDeltaInteger-"enumDeltaToInteger" [1] enumDeltaToIntegerFB (:) [] = enumDeltaToInteger- #-}--enumDeltaIntegerFB :: (Integer -> b -> b) -> Integer -> Integer -> b-enumDeltaIntegerFB c x d = x `seq` (x `c` enumDeltaIntegerFB c (x+d) d)--enumDeltaInteger :: Integer -> Integer -> [Integer]-enumDeltaInteger x d = x `seq` (x : enumDeltaInteger (x+d) d)--- strict accumulator, so--- head (drop 1000000 [1 .. ]--- works--{-# NOINLINE [0] enumDeltaToIntegerFB #-}--- Don't inline this until RULE "enumDeltaToInteger" has had a chance to fire-enumDeltaToIntegerFB :: (Integer -> a -> a) -> a- -> Integer -> Integer -> Integer -> a-enumDeltaToIntegerFB c n x delta lim- | delta >= 0 = up_fb c n x delta lim- | otherwise = dn_fb c n x delta lim--enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer]-enumDeltaToInteger x delta lim- | delta >= 0 = up_list x delta lim- | otherwise = dn_list x delta lim--up_fb :: (Integer -> a -> a) -> a -> Integer -> Integer -> Integer -> a-up_fb c n x0 delta lim = go (x0 :: Integer)- where- go x | x > lim = n- | otherwise = x `c` go (x+delta)-dn_fb :: (Integer -> a -> a) -> a -> Integer -> Integer -> Integer -> a-dn_fb c n x0 delta lim = go (x0 :: Integer)- where- go x | x < lim = n- | otherwise = x `c` go (x+delta)--up_list :: Integer -> Integer -> Integer -> [Integer]-up_list x0 delta lim = go (x0 :: Integer)- where- go x | x > lim = []- | otherwise = x : go (x+delta)-dn_list :: Integer -> Integer -> Integer -> [Integer]-dn_list x0 delta lim = go (x0 :: Integer)- where- go x | x < lim = []- | otherwise = x : go (x+delta)-\end{code}-
@@ -1,53 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, ForeignFunctionInterface #-}--module GHC.Environment (getFullArgs) where--import Prelude-import Foreign-import Foreign.C--#ifdef mingw32_HOST_OS-import GHC.IO (finally)-import GHC.Windows---- Ignore the arguments to hs_init on Windows for the sake of Unicode compat-getFullArgs :: IO [String]-getFullArgs = do- p_arg_string <- c_GetCommandLine- alloca $ \p_argc -> do- p_argv <- c_CommandLineToArgv p_arg_string p_argc- if p_argv == nullPtr- then throwGetLastError "getFullArgs"- else flip finally (c_LocalFree p_argv) $ do- argc <- peek p_argc- p_argvs <- peekArray (fromIntegral argc) p_argv- mapM peekCWString p_argvs--foreign import stdcall unsafe "windows.h GetCommandLineW"- c_GetCommandLine :: IO (Ptr CWString)--foreign import stdcall unsafe "windows.h CommandLineToArgvW"- c_CommandLineToArgv :: Ptr CWString -> Ptr CInt -> IO (Ptr CWString)--foreign import stdcall unsafe "Windows.h LocalFree"- c_LocalFree :: Ptr a -> IO (Ptr a)-#else-import Control.Monad--import GHC.IO.Encoding-import qualified GHC.Foreign as GHC--getFullArgs :: IO [String]-getFullArgs =- alloca $ \ p_argc ->- alloca $ \ p_argv -> do- getFullProgArgv p_argc p_argv- p <- fromIntegral `liftM` peek p_argc- argv <- peek p_argv- enc <- getFileSystemEncoding- peekArray (p - 1) (advancePtr argv 1) >>= mapM (GHC.peekCString enc)--foreign import ccall unsafe "getFullProgArgv"- getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()-#endif
@@ -1,91 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Err--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ The "GHC.Err" module defines the code for the wired-in error functions,--- which have a special type in the compiler (with \"open tyvars\").--- --- We cannot define these functions in a module where they might be used--- (e.g., "GHC.Base"), because the magical wired-in type will get confused--- with what the typechecker figures out.--- ---------------------------------------------------------------------------------- #hide-module GHC.Err- (- absentErr -- :: a- , divZeroError -- :: a- , overflowError -- :: a-- , error -- :: String -> a-- , undefined -- :: a- ) where--#ifndef __HADDOCK__-import GHC.Types-import GHC.Exception-#endif-\end{code}--%*********************************************************-%* *-\subsection{Error-ish functions}-%* *-%*********************************************************--\begin{code}--- | 'error' stops execution and displays an error message.-error :: [Char] -> a-error s = throw (ErrorCall s)---- | A special case of 'error'.--- It is expected that compilers will recognize this and insert error--- messages which are more appropriate to the context in which 'undefined'--- appears. --undefined :: a-undefined = error "Prelude.undefined"-\end{code}--%*********************************************************-%* *-\subsection{Compiler generated errors + local utils}-%* *-%*********************************************************--Used for compiler-generated error message;-encoding saves bytes of string junk.--\begin{code}-absentErr :: a--absentErr = error "Oops! The program has entered an `absent' argument!\n"-\end{code}--Divide by zero and arithmetic overflow.-We put them here because they are needed relatively early-in the libraries before the Exception type has been defined yet.--\begin{code}-{-# NOINLINE divZeroError #-}-divZeroError :: a-divZeroError = throw DivideByZero--{-# NOINLINE overflowError #-}-overflowError :: a-overflowError = throw Overflow-\end{code}-
@@ -1,22 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}-------------------------------------------------------------------------------- Ghc.Err.hs-boot------------------------------------------------------------------------------module GHC.Err( error ) where---- The type signature for 'error' is a gross hack.--- First, we can't give an accurate type for error, because it mentions --- an open type variable.--- Second, we can't even say error :: [Char] -> a, because Char is defined--- in GHC.Base, and that would make Err.lhs-boot mutually recursive --- with GHC.Base.--- Fortunately it doesn't matter what type we give here because the --- compiler will use its wired-in version. But we have--- to mention 'error' so that it gets exported from this .hi-boot--- file.-error :: a-\end{code}
@@ -1,48 +0,0 @@-{-# LANGUAGE Trustworthy #-}---- ------------------------------------------------------------------------------- | This module provides scalable event notification for file--- descriptors and timeouts.------ This module should be considered GHC internal.------ ------------------------------------------------------------------------------module GHC.Event- ( -- * Types- EventManager-- -- * Creation- , new- , getSystemEventManager-- -- * Running- , loop-- -- ** Stepwise running- , step- , shutdown-- -- * Registering interest in I/O events- , Event- , evtRead- , evtWrite- , IOCallback- , FdKey(keyFd)- , registerFd- , registerFd_- , unregisterFd- , unregisterFd_- , closeFd-- -- * Registering interest in timeout events- , TimeoutCallback- , TimeoutKey- , registerTimeout- , updateTimeout- , unregisterTimeout- ) where--import GHC.Event.Manager-import GHC.Event.Thread (getSystemEventManager)-
@@ -1,315 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE BangPatterns, CPP, ForeignFunctionInterface, NoImplicitPrelude #-}--module GHC.Event.Array- (- Array- , capacity- , clear- , concat- , copy- , duplicate- , empty- , ensureCapacity- , findIndex- , forM_- , length- , loop- , new- , removeAt- , snoc- , unsafeLoad- , unsafeRead- , unsafeWrite- , useAsPtr- ) where--import Control.Monad hiding (forM_)-import Data.Bits ((.|.), shiftR)-import Data.IORef (IORef, atomicModifyIORef, newIORef, readIORef, writeIORef)-import Data.Maybe-import Foreign.C.Types (CSize(..))-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr, nullPtr, plusPtr)-import Foreign.Storable (Storable(..))-import GHC.Base-import GHC.Err (undefined)-import GHC.ForeignPtr (mallocPlainForeignPtrBytes, newForeignPtr_)-import GHC.Num (Num(..))-import GHC.Real (fromIntegral)-import GHC.Show (show)--#include "MachDeps.h"--#define BOUNDS_CHECKING 1--#if defined(BOUNDS_CHECKING)--- This fugly hack is brought by GHC's apparent reluctance to deal--- with MagicHash and UnboxedTuples when inferring types. Eek!-#define CHECK_BOUNDS(_func_,_len_,_k_) \-if (_k_) < 0 || (_k_) >= (_len_) then error ("GHC.Event.Array." ++ (_func_) ++ ": bounds error, index " ++ show (_k_) ++ ", capacity " ++ show (_len_)) else-#else-#define CHECK_BOUNDS(_func_,_len_,_k_)-#endif---- Invariant: size <= capacity-newtype Array a = Array (IORef (AC a))---- The actual array content.-data AC a = AC- !(ForeignPtr a) -- Elements- !Int -- Number of elements (length)- !Int -- Maximum number of elements (capacity)--empty :: IO (Array a)-empty = do- p <- newForeignPtr_ nullPtr- Array `fmap` newIORef (AC p 0 0)--allocArray :: Storable a => Int -> IO (ForeignPtr a)-allocArray n = allocHack undefined- where- allocHack :: Storable a => a -> IO (ForeignPtr a)- allocHack dummy = mallocPlainForeignPtrBytes (n * sizeOf dummy)--reallocArray :: Storable a => ForeignPtr a -> Int -> Int -> IO (ForeignPtr a)-reallocArray p newSize oldSize = reallocHack undefined p- where- reallocHack :: Storable a => a -> ForeignPtr a -> IO (ForeignPtr a)- reallocHack dummy src = do- let size = sizeOf dummy- dst <- mallocPlainForeignPtrBytes (newSize * size)- withForeignPtr src $ \s ->- when (s /= nullPtr && oldSize > 0) .- withForeignPtr dst $ \d -> do- _ <- memcpy d s (fromIntegral (oldSize * size))- return ()- return dst--new :: Storable a => Int -> IO (Array a)-new c = do- es <- allocArray cap- fmap Array (newIORef (AC es 0 cap))- where- cap = firstPowerOf2 c--duplicate :: Storable a => Array a -> IO (Array a)-duplicate a = dupHack undefined a- where- dupHack :: Storable b => b -> Array b -> IO (Array b)- dupHack dummy (Array ref) = do- AC es len cap <- readIORef ref- ary <- allocArray cap- withForeignPtr ary $ \dest ->- withForeignPtr es $ \src -> do- _ <- memcpy dest src (fromIntegral (len * sizeOf dummy))- return ()- Array `fmap` newIORef (AC ary len cap)--length :: Array a -> IO Int-length (Array ref) = do- AC _ len _ <- readIORef ref- return len--capacity :: Array a -> IO Int-capacity (Array ref) = do- AC _ _ cap <- readIORef ref- return cap--unsafeRead :: Storable a => Array a -> Int -> IO a-unsafeRead (Array ref) ix = do- AC es _ cap <- readIORef ref- CHECK_BOUNDS("unsafeRead",cap,ix)- withForeignPtr es $ \p ->- peekElemOff p ix--unsafeWrite :: Storable a => Array a -> Int -> a -> IO ()-unsafeWrite (Array ref) ix a = do- ac <- readIORef ref- unsafeWrite' ac ix a--unsafeWrite' :: Storable a => AC a -> Int -> a -> IO ()-unsafeWrite' (AC es _ cap) ix a = do- CHECK_BOUNDS("unsafeWrite'",cap,ix)- withForeignPtr es $ \p ->- pokeElemOff p ix a--unsafeLoad :: Storable a => Array a -> (Ptr a -> Int -> IO Int) -> IO Int-unsafeLoad (Array ref) load = do- AC es _ cap <- readIORef ref- len' <- withForeignPtr es $ \p -> load p cap- writeIORef ref (AC es len' cap)- return len'--ensureCapacity :: Storable a => Array a -> Int -> IO ()-ensureCapacity (Array ref) c = do- ac@(AC _ _ cap) <- readIORef ref- ac'@(AC _ _ cap') <- ensureCapacity' ac c- when (cap' /= cap) $- writeIORef ref ac'--ensureCapacity' :: Storable a => AC a -> Int -> IO (AC a)-ensureCapacity' ac@(AC es len cap) c = do- if c > cap- then do- es' <- reallocArray es cap' cap- return (AC es' len cap')- else- return ac- where- cap' = firstPowerOf2 c--useAsPtr :: Array a -> (Ptr a -> Int -> IO b) -> IO b-useAsPtr (Array ref) f = do- AC es len _ <- readIORef ref- withForeignPtr es $ \p -> f p len--snoc :: Storable a => Array a -> a -> IO ()-snoc (Array ref) e = do- ac@(AC _ len _) <- readIORef ref- let len' = len + 1- ac'@(AC es _ cap) <- ensureCapacity' ac len'- unsafeWrite' ac' len e- writeIORef ref (AC es len' cap)--clear :: Storable a => Array a -> IO ()-clear (Array ref) = do- !_ <- atomicModifyIORef ref $ \(AC es _ cap) ->- let e = AC es 0 cap in (e, e)- return ()--forM_ :: Storable a => Array a -> (a -> IO ()) -> IO ()-forM_ ary g = forHack ary g undefined- where- forHack :: Storable b => Array b -> (b -> IO ()) -> b -> IO ()- forHack (Array ref) f dummy = do- AC es len _ <- readIORef ref- let size = sizeOf dummy- offset = len * size- withForeignPtr es $ \p -> do- let go n | n >= offset = return ()- | otherwise = do- f =<< peek (p `plusPtr` n)- go (n + size)- go 0--loop :: Storable a => Array a -> b -> (b -> a -> IO (b,Bool)) -> IO ()-loop ary z g = loopHack ary z g undefined- where- loopHack :: Storable b => Array b -> c -> (c -> b -> IO (c,Bool)) -> b- -> IO ()- loopHack (Array ref) y f dummy = do- AC es len _ <- readIORef ref- let size = sizeOf dummy- offset = len * size- withForeignPtr es $ \p -> do- let go n k- | n >= offset = return ()- | otherwise = do- (k',cont) <- f k =<< peek (p `plusPtr` n)- when cont $ go (n + size) k'- go 0 y--findIndex :: Storable a => (a -> Bool) -> Array a -> IO (Maybe (Int,a))-findIndex = findHack undefined- where- findHack :: Storable b => b -> (b -> Bool) -> Array b -> IO (Maybe (Int,b))- findHack dummy p (Array ref) = do- AC es len _ <- readIORef ref- let size = sizeOf dummy- offset = len * size- withForeignPtr es $ \ptr ->- let go !n !i- | n >= offset = return Nothing- | otherwise = do- val <- peek (ptr `plusPtr` n)- if p val- then return $ Just (i, val)- else go (n + size) (i + 1)- in go 0 0--concat :: Storable a => Array a -> Array a -> IO ()-concat (Array d) (Array s) = do- da@(AC _ dlen _) <- readIORef d- sa@(AC _ slen _) <- readIORef s- writeIORef d =<< copy' da dlen sa 0 slen---- | Copy part of the source array into the destination array. The--- destination array is resized if not large enough.-copy :: Storable a => Array a -> Int -> Array a -> Int -> Int -> IO ()-copy (Array d) dstart (Array s) sstart maxCount = do- da <- readIORef d- sa <- readIORef s- writeIORef d =<< copy' da dstart sa sstart maxCount---- | Copy part of the source array into the destination array. The--- destination array is resized if not large enough.-copy' :: Storable a => AC a -> Int -> AC a -> Int -> Int -> IO (AC a)-copy' d dstart s sstart maxCount = copyHack d s undefined- where- copyHack :: Storable b => AC b -> AC b -> b -> IO (AC b)- copyHack dac@(AC _ oldLen _) (AC src slen _) dummy = do- when (maxCount < 0 || dstart < 0 || dstart > oldLen || sstart < 0 ||- sstart > slen) $ error "copy: bad offsets or lengths"- let size = sizeOf dummy- count = min maxCount (slen - sstart)- if count == 0- then return dac- else do- AC dst dlen dcap <- ensureCapacity' dac (dstart + count)- withForeignPtr dst $ \dptr ->- withForeignPtr src $ \sptr -> do- _ <- memcpy (dptr `plusPtr` (dstart * size))- (sptr `plusPtr` (sstart * size))- (fromIntegral (count * size))- return $ AC dst (max dlen (dstart + count)) dcap--removeAt :: Storable a => Array a -> Int -> IO ()-removeAt a i = removeHack a undefined- where- removeHack :: Storable b => Array b -> b -> IO ()- removeHack (Array ary) dummy = do- AC fp oldLen cap <- readIORef ary- when (i < 0 || i >= oldLen) $ error "removeAt: invalid index"- let size = sizeOf dummy- newLen = oldLen - 1- when (newLen > 0 && i < newLen) .- withForeignPtr fp $ \ptr -> do- _ <- memmove (ptr `plusPtr` (size * i))- (ptr `plusPtr` (size * (i+1)))- (fromIntegral (size * (newLen-i)))- return ()- writeIORef ary (AC fp newLen cap)--{-The firstPowerOf2 function works by setting all bits on the right-hand-side of the most significant flagged bit to 1, and then incrementing-the entire value at the end so it "rolls over" to the nearest power of-two.--}---- | Computes the next-highest power of two for a particular integer,--- @n@. If @n@ is already a power of two, returns @n@. If @n@ is--- zero, returns zero, even though zero is not a power of two.-firstPowerOf2 :: Int -> Int-firstPowerOf2 !n =- let !n1 = n - 1- !n2 = n1 .|. (n1 `shiftR` 1)- !n3 = n2 .|. (n2 `shiftR` 2)- !n4 = n3 .|. (n3 `shiftR` 4)- !n5 = n4 .|. (n4 `shiftR` 8)- !n6 = n5 .|. (n5 `shiftR` 16)-#if WORD_SIZE_IN_BITS == 32- in n6 + 1-#elif WORD_SIZE_IN_BITS == 64- !n7 = n6 .|. (n6 `shiftR` 32)- in n7 + 1-#else-# error firstPowerOf2 not defined on this architecture-#endif--foreign import ccall unsafe "string.h memcpy"- memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)--foreign import ccall unsafe "string.h memmove"- memmove :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)-
@@ -1,50 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, BangPatterns, ForeignFunctionInterface, CApiFFI #-}--module GHC.Event.Clock (getCurrentTime) where--#include <sys/time.h>--import Foreign (Ptr, Storable(..), nullPtr, with)-import Foreign.C.Error (throwErrnoIfMinus1_)-import Foreign.C.Types-import GHC.Base-import GHC.Err-import GHC.Num-import GHC.Real---- TODO: Implement this for Windows.---- | Return the current time, in seconds since Jan. 1, 1970.-getCurrentTime :: IO Double-getCurrentTime = do- tv <- with (CTimeval 0 0) $ \tvptr -> do- throwErrnoIfMinus1_ "gettimeofday" (gettimeofday tvptr nullPtr)- peek tvptr- let !t = realToFrac (sec tv) + realToFrac (usec tv) / 1000000.0- return t----------------------------------------------------------------------------- FFI binding--data CTimeval = CTimeval- { sec :: {-# UNPACK #-} !CTime- , usec :: {-# UNPACK #-} !CSUSeconds- }--instance Storable CTimeval where- sizeOf _ = #size struct timeval- alignment _ = alignment (undefined :: CLong)-- peek ptr = do- sec' <- #{peek struct timeval, tv_sec} ptr- usec' <- #{peek struct timeval, tv_usec} ptr- return $ CTimeval sec' usec'-- poke ptr tv = do- #{poke struct timeval, tv_sec} ptr (sec tv)- #{poke struct timeval, tv_usec} ptr (usec tv)--foreign import capi unsafe "HsBase.h gettimeofday" gettimeofday- :: Ptr CTimeval -> Ptr () -> IO CInt-
@@ -1,216 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP- , ForeignFunctionInterface- , NoImplicitPrelude- , ScopedTypeVariables- , BangPatterns- #-}--module GHC.Event.Control- (- -- * Managing the IO manager- Signal- , ControlMessage(..)- , Control- , newControl- , closeControl- -- ** Control message reception- , readControlMessage- -- *** File descriptors- , controlReadFd- , wakeupReadFd- -- ** Control message sending- , sendWakeup- , sendDie- -- * Utilities- , setNonBlockingFD- ) where--#include "EventConfig.h"--import Control.Monad (when)-import Foreign.ForeignPtr (ForeignPtr)-import GHC.Base-import GHC.Conc.Signal (Signal)-import GHC.Real (fromIntegral)-import GHC.Show (Show)-import GHC.Word (Word8)-import Foreign.C.Error (throwErrnoIfMinus1_)-import Foreign.C.Types (CInt(..), CSize(..))-import Foreign.ForeignPtr (mallocForeignPtrBytes, withForeignPtr)-import Foreign.Marshal (alloca, allocaBytes)-import Foreign.Marshal.Array (allocaArray)-import Foreign.Ptr (castPtr)-import Foreign.Storable (peek, peekElemOff, poke)-import System.Posix.Internals (c_close, c_pipe, c_read, c_write,- setCloseOnExec, setNonBlockingFD)-import System.Posix.Types (Fd)--#if defined(HAVE_EVENTFD)-import Data.Word (Word64)-import Foreign.C.Error (throwErrnoIfMinus1)-#else-import Foreign.C.Error (eAGAIN, eWOULDBLOCK, getErrno, throwErrno)-#endif--data ControlMessage = CMsgWakeup- | CMsgDie- | CMsgSignal {-# UNPACK #-} !(ForeignPtr Word8)- {-# UNPACK #-} !Signal- deriving (Eq, Show)---- | The structure used to tell the IO manager thread what to do.-data Control = W {- controlReadFd :: {-# UNPACK #-} !Fd- , controlWriteFd :: {-# UNPACK #-} !Fd-#if defined(HAVE_EVENTFD)- , controlEventFd :: {-# UNPACK #-} !Fd-#else- , wakeupReadFd :: {-# UNPACK #-} !Fd- , wakeupWriteFd :: {-# UNPACK #-} !Fd-#endif- } deriving (Show)--#if defined(HAVE_EVENTFD)-wakeupReadFd :: Control -> Fd-wakeupReadFd = controlEventFd-{-# INLINE wakeupReadFd #-}-#endif--setNonBlock :: CInt -> IO ()-setNonBlock fd =-#if __GLASGOW_HASKELL__ >= 611- setNonBlockingFD fd True-#else- setNonBlockingFD fd-#endif---- | Create the structure (usually a pipe) used for waking up the IO--- manager thread from another thread.-newControl :: IO Control-newControl = allocaArray 2 $ \fds -> do- let createPipe = do- throwErrnoIfMinus1_ "pipe" $ c_pipe fds- rd <- peekElemOff fds 0- wr <- peekElemOff fds 1- -- The write end must be non-blocking, since we may need to- -- poke the event manager from a signal handler.- setNonBlock wr- setCloseOnExec rd- setCloseOnExec wr- return (rd, wr)- (ctrl_rd, ctrl_wr) <- createPipe- c_setIOManagerControlFd ctrl_wr-#if defined(HAVE_EVENTFD)- ev <- throwErrnoIfMinus1 "eventfd" $ c_eventfd 0 0- setNonBlock ev- setCloseOnExec ev- c_setIOManagerWakeupFd ev-#else- (wake_rd, wake_wr) <- createPipe- c_setIOManagerWakeupFd wake_wr-#endif- return W { controlReadFd = fromIntegral ctrl_rd- , controlWriteFd = fromIntegral ctrl_wr-#if defined(HAVE_EVENTFD)- , controlEventFd = fromIntegral ev-#else- , wakeupReadFd = fromIntegral wake_rd- , wakeupWriteFd = fromIntegral wake_wr-#endif- }---- | Close the control structure used by the IO manager thread.-closeControl :: Control -> IO ()-closeControl w = do- _ <- c_close . fromIntegral . controlReadFd $ w- _ <- c_close . fromIntegral . controlWriteFd $ w-#if defined(HAVE_EVENTFD)- _ <- c_close . fromIntegral . controlEventFd $ w-#else- _ <- c_close . fromIntegral . wakeupReadFd $ w- _ <- c_close . fromIntegral . wakeupWriteFd $ w-#endif- return ()--io_MANAGER_WAKEUP, io_MANAGER_DIE :: Word8-io_MANAGER_WAKEUP = 0xff-io_MANAGER_DIE = 0xfe--foreign import ccall "__hscore_sizeof_siginfo_t"- sizeof_siginfo_t :: CSize--readControlMessage :: Control -> Fd -> IO ControlMessage-readControlMessage ctrl fd- | fd == wakeupReadFd ctrl = allocaBytes wakeupBufferSize $ \p -> do- throwErrnoIfMinus1_ "readWakeupMessage" $- c_read (fromIntegral fd) p (fromIntegral wakeupBufferSize)- return CMsgWakeup- | otherwise =- alloca $ \p -> do- throwErrnoIfMinus1_ "readControlMessage" $- c_read (fromIntegral fd) p 1- s <- peek p- case s of- -- Wakeup messages shouldn't be sent on the control- -- file descriptor but we handle them anyway.- _ | s == io_MANAGER_WAKEUP -> return CMsgWakeup- _ | s == io_MANAGER_DIE -> return CMsgDie- _ -> do -- Signal- fp <- mallocForeignPtrBytes (fromIntegral sizeof_siginfo_t)- withForeignPtr fp $ \p_siginfo -> do- r <- c_read (fromIntegral fd) (castPtr p_siginfo)- sizeof_siginfo_t- when (r /= fromIntegral sizeof_siginfo_t) $- error "failed to read siginfo_t"- let !s' = fromIntegral s- return $ CMsgSignal fp s'-- where wakeupBufferSize =-#if defined(HAVE_EVENTFD)- 8-#else- 4096-#endif--sendWakeup :: Control -> IO ()-#if defined(HAVE_EVENTFD)-sendWakeup c = alloca $ \p -> do- poke p (1 :: Word64)- throwErrnoIfMinus1_ "sendWakeup" $- c_write (fromIntegral (controlEventFd c)) (castPtr p) 8-#else-sendWakeup c = do- n <- sendMessage (wakeupWriteFd c) CMsgWakeup- case n of- _ | n /= -1 -> return ()- | otherwise -> do- errno <- getErrno- when (errno /= eAGAIN && errno /= eWOULDBLOCK) $- throwErrno "sendWakeup"-#endif--sendDie :: Control -> IO ()-sendDie c = throwErrnoIfMinus1_ "sendDie" $- sendMessage (controlWriteFd c) CMsgDie--sendMessage :: Fd -> ControlMessage -> IO Int-sendMessage fd msg = alloca $ \p -> do- case msg of- CMsgWakeup -> poke p io_MANAGER_WAKEUP- CMsgDie -> poke p io_MANAGER_DIE- CMsgSignal _fp _s -> error "Signals can only be sent from within the RTS"- fromIntegral `fmap` c_write (fromIntegral fd) p 1--#if defined(HAVE_EVENTFD)-foreign import ccall unsafe "sys/eventfd.h eventfd"- c_eventfd :: CInt -> CInt -> IO CInt-#endif---- Used to tell the RTS how it can send messages to the I/O manager.-foreign import ccall "setIOManagerControlFd"- c_setIOManagerControlFd :: CInt -> IO ()--foreign import ccall "setIOManagerWakeupFd"- c_setIOManagerWakeupFd :: CInt -> IO ()-
@@ -1,211 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , ForeignFunctionInterface- , GeneralizedNewtypeDeriving- , NoImplicitPrelude- , BangPatterns- #-}---------------------------------------------------------------------------------- |--- A binding to the epoll I/O event notification facility------ epoll is a variant of poll that can be used either as an edge-triggered or--- a level-triggered interface and scales well to large numbers of watched file--- descriptors.------ epoll decouples monitor an fd from the process of registering it.-----------------------------------------------------------------------------------module GHC.Event.EPoll- (- new- , available- ) where--import qualified GHC.Event.Internal as E--#include "EventConfig.h"-#if !defined(HAVE_EPOLL)-import GHC.Base--new :: IO E.Backend-new = error "EPoll back end not implemented for this platform"--available :: Bool-available = False-{-# INLINE available #-}-#else--#include <sys/epoll.h>--import Control.Monad (when)-import Data.Bits (Bits, (.|.), (.&.))-import Data.Monoid (Monoid(..))-import Data.Word (Word32)-import Foreign.C.Error (throwErrnoIfMinus1, throwErrnoIfMinus1_)-import Foreign.C.Types (CInt(..))-import Foreign.Marshal.Utils (with)-import Foreign.Ptr (Ptr)-import Foreign.Storable (Storable(..))-import GHC.Base-import GHC.Err (undefined)-import GHC.Num (Num(..))-import GHC.Real (ceiling, fromIntegral)-import GHC.Show (Show)-import System.Posix.Internals (c_close)-import System.Posix.Internals (setCloseOnExec)-import System.Posix.Types (Fd(..))--import qualified GHC.Event.Array as A-import GHC.Event.Internal (Timeout(..))--available :: Bool-available = True-{-# INLINE available #-}--data EPoll = EPoll {- epollFd :: {-# UNPACK #-} !EPollFd- , epollEvents :: {-# UNPACK #-} !(A.Array Event)- }---- | Create a new epoll backend.-new :: IO E.Backend-new = do- epfd <- epollCreate- evts <- A.new 64- let !be = E.backend poll modifyFd delete (EPoll epfd evts)- return be--delete :: EPoll -> IO ()-delete be = do- _ <- c_close . fromEPollFd . epollFd $ be- return ()---- | Change the set of events we are interested in for a given file--- descriptor.-modifyFd :: EPoll -> Fd -> E.Event -> E.Event -> IO ()-modifyFd ep fd oevt nevt = with (Event (fromEvent nevt) fd) $- epollControl (epollFd ep) op fd- where op | oevt == mempty = controlOpAdd- | nevt == mempty = controlOpDelete- | otherwise = controlOpModify---- | Select a set of file descriptors which are ready for I/O--- operations and call @f@ for all ready file descriptors, passing the--- events that are ready.-poll :: EPoll -- ^ state- -> Timeout -- ^ timeout in milliseconds- -> (Fd -> E.Event -> IO ()) -- ^ I/O callback- -> IO ()-poll ep timeout f = do- let events = epollEvents ep-- -- Will return zero if the system call was interupted, in which case- -- we just return (and try again later.)- n <- A.unsafeLoad events $ \es cap ->- epollWait (epollFd ep) es cap $ fromTimeout timeout-- when (n > 0) $ do- A.forM_ events $ \e -> f (eventFd e) (toEvent (eventTypes e))- cap <- A.capacity events- when (cap == n) $ A.ensureCapacity events (2 * cap)--newtype EPollFd = EPollFd {- fromEPollFd :: CInt- } deriving (Eq, Show)--data Event = Event {- eventTypes :: EventType- , eventFd :: Fd- } deriving (Show)--instance Storable Event where- sizeOf _ = #size struct epoll_event- alignment _ = alignment (undefined :: CInt)-- peek ptr = do- ets <- #{peek struct epoll_event, events} ptr- ed <- #{peek struct epoll_event, data.fd} ptr- let !ev = Event (EventType ets) ed- return ev-- poke ptr e = do- #{poke struct epoll_event, events} ptr (unEventType $ eventTypes e)- #{poke struct epoll_event, data.fd} ptr (eventFd e)--newtype ControlOp = ControlOp CInt--#{enum ControlOp, ControlOp- , controlOpAdd = EPOLL_CTL_ADD- , controlOpModify = EPOLL_CTL_MOD- , controlOpDelete = EPOLL_CTL_DEL- }--newtype EventType = EventType {- unEventType :: Word32- } deriving (Show, Eq, Num, Bits)--#{enum EventType, EventType- , epollIn = EPOLLIN- , epollOut = EPOLLOUT- , epollErr = EPOLLERR- , epollHup = EPOLLHUP- }---- | Create a new epoll context, returning a file descriptor associated with the context.--- The fd may be used for subsequent calls to this epoll context.------ The size parameter to epoll_create is a hint about the expected number of handles.------ The file descriptor returned from epoll_create() should be destroyed via--- a call to close() after polling is finished----epollCreate :: IO EPollFd-epollCreate = do- fd <- throwErrnoIfMinus1 "epollCreate" $- c_epoll_create 256 -- argument is ignored- setCloseOnExec fd- let !epollFd' = EPollFd fd- return epollFd'--epollControl :: EPollFd -> ControlOp -> Fd -> Ptr Event -> IO ()-epollControl (EPollFd epfd) (ControlOp op) (Fd fd) event =- throwErrnoIfMinus1_ "epollControl" $ c_epoll_ctl epfd op fd event--epollWait :: EPollFd -> Ptr Event -> Int -> Int -> IO Int-epollWait (EPollFd epfd) events numEvents timeout =- fmap fromIntegral .- E.throwErrnoIfMinus1NoRetry "epollWait" $- c_epoll_wait epfd events (fromIntegral numEvents) (fromIntegral timeout)--fromEvent :: E.Event -> EventType-fromEvent e = remap E.evtRead epollIn .|.- remap E.evtWrite epollOut- where remap evt to- | e `E.eventIs` evt = to- | otherwise = 0--toEvent :: EventType -> E.Event-toEvent e = remap (epollIn .|. epollErr .|. epollHup) E.evtRead `mappend`- remap (epollOut .|. epollErr .|. epollHup) E.evtWrite- where remap evt to- | e .&. evt /= 0 = to- | otherwise = mempty--fromTimeout :: Timeout -> Int-fromTimeout Forever = -1-fromTimeout (Timeout s) = ceiling $ 1000 * s--foreign import ccall unsafe "sys/epoll.h epoll_create"- c_epoll_create :: CInt -> IO CInt--foreign import ccall unsafe "sys/epoll.h epoll_ctl"- c_epoll_ctl :: CInt -> CInt -> CInt -> Ptr Event -> IO CInt--foreign import ccall safe "sys/epoll.h epoll_wait"- c_epoll_wait :: CInt -> Ptr Event -> CInt -> CInt -> IO CInt--#endif /* defined(HAVE_EPOLL) */-
@@ -1,378 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, MagicHash, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : GHC.Event.IntMap--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from integer keys to values.------ Since many function names (but not the type name) clash with--- "Prelude" names, this module is usually imported @qualified@, e.g.------ > import Data.IntMap (IntMap)--- > import qualified Data.IntMap as IntMap------ The implementation is based on /big-endian patricia trees/. This data--- structure performs especially well on binary operations like 'union'--- and 'intersection'. However, my benchmarks show that it is also--- (much) faster on insertions and deletions when compared to a generic--- size-balanced map implementation (see "Data.Map").------ * Chris Okasaki and Andy Gill, \"/Fast Mergeable Integer Maps/\",--- Workshop on ML, September 1998, pages 77-86,--- <http://citeseer.ist.psu.edu/okasaki98fast.html>------ * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve--- Information Coded In Alphanumeric/\", Journal of the ACM, 15(4),--- October 1968, pages 514-534.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.--- Many operations have a worst-case complexity of /O(min(n,W))/.--- This means that the operation can become linear in the number of--- elements with a maximum of /W/ -- the number of bits in an 'Int'--- (32 or 64).-----------------------------------------------------------------------------------module GHC.Event.IntMap- (- -- * Map type- IntMap- , Key-- -- * Query- , lookup- , member-- -- * Construction- , empty-- -- * Insertion- , insertWith-- -- * Delete\/Update- , delete- , updateWith-- -- * Traversal- -- ** Fold- , foldWithKey-- -- * Conversion- , keys- ) where--import Data.Bits--import Data.Maybe (Maybe(..))-import GHC.Base hiding (foldr)-import GHC.Num (Num(..))-import GHC.Real (fromIntegral)-import GHC.Show (Show(showsPrec), showParen, shows, showString)--#if __GLASGOW_HASKELL__-import GHC.Word (Word(..))-#else-import Data.Word-#endif---- | A @Nat@ is a natural machine word (an unsigned Int)-type Nat = Word--natFromInt :: Key -> Nat-natFromInt i = fromIntegral i--intFromNat :: Nat -> Key-intFromNat w = fromIntegral w--shiftRL :: Nat -> Key -> Nat-#if __GLASGOW_HASKELL__--- GHC: use unboxing to get @shiftRL@ inlined.-shiftRL (W# x) (I# i) = W# (shiftRL# x i)-#else-shiftRL x i = shiftR x i-#endif----------------------------------------------------------------------------- Types---- | A map of integers to values @a@.-data IntMap a = Nil- | Tip {-# UNPACK #-} !Key !a- | Bin {-# UNPACK #-} !Prefix- {-# UNPACK #-} !Mask- !(IntMap a)- !(IntMap a)--type Prefix = Int-type Mask = Int-type Key = Int----------------------------------------------------------------------------- Query---- | /O(min(n,W))/ Lookup the value at a key in the map. See also--- 'Data.Map.lookup'.-lookup :: Key -> IntMap a -> Maybe a-lookup k t = let nk = natFromInt k in seq nk (lookupN nk t)--lookupN :: Nat -> IntMap a -> Maybe a-lookupN k t- = case t of- Bin _ m l r- | zeroN k (natFromInt m) -> lookupN k l- | otherwise -> lookupN k r- Tip kx x- | (k == natFromInt kx) -> Just x- | otherwise -> Nothing- Nil -> Nothing---- | /O(min(n,W))/. Is the key a member of the map?------ > member 5 (fromList [(5,'a'), (3,'b')]) == True--- > member 1 (fromList [(5,'a'), (3,'b')]) == False--member :: Key -> IntMap a -> Bool-member k m- = case lookup k m of- Nothing -> False- Just _ -> True----------------------------------------------------------------------------- Construction---- | /O(1)/ The empty map.------ > empty == fromList []--- > size empty == 0-empty :: IntMap a-empty = Nil----------------------------------------------------------------------------- Insert---- | /O(min(n,W))/ Insert with a function, combining new value and old--- value. @insertWith f key value mp@ will insert the pair (key,--- value) into @mp@ if key does not exist in the map. If the key does--- exist, the function will insert the pair (key, f new_value--- old_value). The result is a pair where the first element is the--- old value, if one was present, and the second is the modified map.-insertWith :: (a -> a -> a) -> Key -> a -> IntMap a -> (Maybe a, IntMap a)-insertWith f k x t = case t of- Bin p m l r- | nomatch k p m -> (Nothing, join k (Tip k x) p t)- | zero k m -> let (found, l') = insertWith f k x l- in (found, Bin p m l' r)- | otherwise -> let (found, r') = insertWith f k x r- in (found, Bin p m l r')- Tip ky y- | k == ky -> (Just y, Tip k (f x y))- | otherwise -> (Nothing, join k (Tip k x) ky t)- Nil -> (Nothing, Tip k x)------------------------------------------------------------------------------ Delete/Update---- | /O(min(n,W))/. Delete a key and its value from the map. When the--- key is not a member of the map, the original map is returned. The--- result is a pair where the first element is the value associated--- with the deleted key, if one existed, and the second element is the--- modified map.-delete :: Key -> IntMap a -> (Maybe a, IntMap a)-delete k t = case t of- Bin p m l r- | nomatch k p m -> (Nothing, t)- | zero k m -> let (found, l') = delete k l- in (found, bin p m l' r)- | otherwise -> let (found, r') = delete k r- in (found, bin p m l r')- Tip ky y- | k == ky -> (Just y, Nil)- | otherwise -> (Nothing, t)- Nil -> (Nothing, Nil)--updateWith :: (a -> Maybe a) -> Key -> IntMap a -> (Maybe a, IntMap a)-updateWith f k t = case t of- Bin p m l r- | nomatch k p m -> (Nothing, t)- | zero k m -> let (found, l') = updateWith f k l- in (found, bin p m l' r)- | otherwise -> let (found, r') = updateWith f k r- in (found, bin p m l r')- Tip ky y- | k == ky -> case (f y) of- Just y' -> (Just y, Tip ky y')- Nothing -> (Just y, Nil)- | otherwise -> (Nothing, t)- Nil -> (Nothing, Nil)--- | /O(n)/. Fold the keys and values in the map, such that--- @'foldWithKey' f z == 'Prelude.foldr' ('uncurry' f) z . 'toAscList'@.--- For example,------ > keys map = foldWithKey (\k x ks -> k:ks) [] map------ > let f k a result = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (5:a)(3:b)"--foldWithKey :: (Key -> a -> b -> b) -> b -> IntMap a -> b-foldWithKey f z t- = foldr f z t---- | /O(n)/. Convert the map to a list of key\/value pairs.------ > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > toList empty == []--toList :: IntMap a -> [(Key,a)]-toList t- = foldWithKey (\k x xs -> (k,x):xs) [] t--foldr :: (Key -> a -> b -> b) -> b -> IntMap a -> b-foldr f z t- = case t of- Bin 0 m l r | m < 0 -> foldr' f (foldr' f z l) r -- put negative numbers before.- Bin _ _ _ _ -> foldr' f z t- Tip k x -> f k x z- Nil -> z--foldr' :: (Key -> a -> b -> b) -> b -> IntMap a -> b-foldr' f z t- = case t of- Bin _ _ l r -> foldr' f (foldr' f z r) l- Tip k x -> f k x z- Nil -> z---- | /O(n)/. Return all keys of the map in ascending order.------ > keys (fromList [(5,"a"), (3,"b")]) == [3,5]--- > keys empty == []--keys :: IntMap a -> [Key]-keys m- = foldWithKey (\k _ ks -> k:ks) [] m----------------------------------------------------------------------------- Eq--instance Eq a => Eq (IntMap a) where- t1 == t2 = equal t1 t2- t1 /= t2 = nequal t1 t2--equal :: Eq a => IntMap a -> IntMap a -> Bool-equal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- = (m1 == m2) && (p1 == p2) && (equal l1 l2) && (equal r1 r2)-equal (Tip kx x) (Tip ky y)- = (kx == ky) && (x==y)-equal Nil Nil = True-equal _ _ = False--nequal :: Eq a => IntMap a -> IntMap a -> Bool-nequal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- = (m1 /= m2) || (p1 /= p2) || (nequal l1 l2) || (nequal r1 r2)-nequal (Tip kx x) (Tip ky y)- = (kx /= ky) || (x/=y)-nequal Nil Nil = False-nequal _ _ = True--instance Show a => Show (IntMap a) where- showsPrec d m = showParen (d > 10) $- showString "fromList " . shows (toList m)----------------------------------------------------------------------------- Utility functions--join :: Prefix -> IntMap a -> Prefix -> IntMap a -> IntMap a-join p1 t1 p2 t2- | zero p1 m = Bin p m t1 t2- | otherwise = Bin p m t2 t1- where- m = branchMask p1 p2- p = mask p1 m---- | @bin@ assures that we never have empty trees within a tree.-bin :: Prefix -> Mask -> IntMap a -> IntMap a -> IntMap a-bin _ _ l Nil = l-bin _ _ Nil r = r-bin p m l r = Bin p m l r----------------------------------------------------------------------------- Endian independent bit twiddling--zero :: Key -> Mask -> Bool-zero i m = (natFromInt i) .&. (natFromInt m) == 0--nomatch :: Key -> Prefix -> Mask -> Bool-nomatch i p m = (mask i m) /= p--mask :: Key -> Mask -> Prefix-mask i m = maskW (natFromInt i) (natFromInt m)--zeroN :: Nat -> Nat -> Bool-zeroN i m = (i .&. m) == 0----------------------------------------------------------------------------- Big endian operations--maskW :: Nat -> Nat -> Prefix-maskW i m = intFromNat (i .&. (complement (m-1) `xor` m))--branchMask :: Prefix -> Prefix -> Mask-branchMask p1 p2- = intFromNat (highestBitMask (natFromInt p1 `xor` natFromInt p2))--{--Finding the highest bit mask in a word [x] can be done efficiently in-three ways:--* convert to a floating point value and the mantissa tells us the- [log2(x)] that corresponds with the highest bit position. The mantissa- is retrieved either via the standard C function [frexp] or by some bit- twiddling on IEEE compatible numbers (float). Note that one needs to- use at least [double] precision for an accurate mantissa of 32 bit- numbers.--* use bit twiddling, a logarithmic sequence of bitwise or's and shifts (bit).--* use processor specific assembler instruction (asm).--The most portable way would be [bit], but is it efficient enough?-I have measured the cycle counts of the different methods on an AMD-Athlon-XP 1800 (~ Pentium III 1.8Ghz) using the RDTSC instruction:--highestBitMask: method cycles- --------------- frexp 200- float 33- bit 11- asm 12--Wow, the bit twiddling is on today's RISC like machines even faster-than a single CISC instruction (BSR)!--}---- | @highestBitMask@ returns a word where only the highest bit is--- set. It is found by first setting all bits in lower positions than--- the highest bit and than taking an exclusive or with the original--- value. Allthough the function may look expensive, GHC compiles--- this into excellent C code that subsequently compiled into highly--- efficient machine code. The algorithm is derived from Jorg Arndt's--- FXT library.-highestBitMask :: Nat -> Nat-highestBitMask x0- = case (x0 .|. shiftRL x0 1) of- x1 -> case (x1 .|. shiftRL x1 2) of- x2 -> case (x2 .|. shiftRL x2 4) of- x3 -> case (x3 .|. shiftRL x3 8) of- x4 -> case (x4 .|. shiftRL x4 16) of- x5 -> case (x5 .|. shiftRL x5 32) of -- for 64 bit platforms- x6 -> (x6 `xor` (shiftRL x6 1))-
@@ -1,140 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE ExistentialQuantification, NoImplicitPrelude #-}--module GHC.Event.Internal- (- -- * Event back end- Backend- , backend- , delete- , poll- , modifyFd- -- * Event type- , Event- , evtRead- , evtWrite- , evtClose- , eventIs- -- * Timeout type- , Timeout(..)- -- * Helpers- , throwErrnoIfMinus1NoRetry- ) where--import Data.Bits ((.|.), (.&.))-import Data.List (foldl', intercalate)-import Data.Monoid (Monoid(..))-import Foreign.C.Error (eINTR, getErrno, throwErrno)-import System.Posix.Types (Fd)-import GHC.Base-import GHC.Num (Num(..))-import GHC.Show (Show(..))-import GHC.List (filter, null)---- | An I\/O event.-newtype Event = Event Int- deriving (Eq)--evtNothing :: Event-evtNothing = Event 0-{-# INLINE evtNothing #-}---- | Data is available to be read.-evtRead :: Event-evtRead = Event 1-{-# INLINE evtRead #-}---- | The file descriptor is ready to accept a write.-evtWrite :: Event-evtWrite = Event 2-{-# INLINE evtWrite #-}---- | Another thread closed the file descriptor.-evtClose :: Event-evtClose = Event 4-{-# INLINE evtClose #-}--eventIs :: Event -> Event -> Bool-eventIs (Event a) (Event b) = a .&. b /= 0--instance Show Event where- show e = '[' : (intercalate "," . filter (not . null) $- [evtRead `so` "evtRead",- evtWrite `so` "evtWrite",- evtClose `so` "evtClose"]) ++ "]"- where ev `so` disp | e `eventIs` ev = disp- | otherwise = ""--instance Monoid Event where- mempty = evtNothing- mappend = evtCombine- mconcat = evtConcat--evtCombine :: Event -> Event -> Event-evtCombine (Event a) (Event b) = Event (a .|. b)-{-# INLINE evtCombine #-}--evtConcat :: [Event] -> Event-evtConcat = foldl' evtCombine evtNothing-{-# INLINE evtConcat #-}---- | A type alias for timeouts, specified in seconds.-data Timeout = Timeout {-# UNPACK #-} !Double- | Forever- deriving (Show)---- | Event notification backend.-data Backend = forall a. Backend {- _beState :: !a-- -- | Poll backend for new events. The provided callback is called- -- once per file descriptor with new events.- , _bePoll :: a -- backend state- -> Timeout -- timeout in milliseconds- -> (Fd -> Event -> IO ()) -- I/O callback- -> IO ()-- -- | Register, modify, or unregister interest in the given events- -- on the given file descriptor.- , _beModifyFd :: a- -> Fd -- file descriptor- -> Event -- old events to watch for ('mempty' for new)- -> Event -- new events to watch for ('mempty' to delete)- -> IO ()-- , _beDelete :: a -> IO ()- }--backend :: (a -> Timeout -> (Fd -> Event -> IO ()) -> IO ())- -> (a -> Fd -> Event -> Event -> IO ())- -> (a -> IO ())- -> a- -> Backend-backend bPoll bModifyFd bDelete state = Backend state bPoll bModifyFd bDelete-{-# INLINE backend #-}--poll :: Backend -> Timeout -> (Fd -> Event -> IO ()) -> IO ()-poll (Backend bState bPoll _ _) = bPoll bState-{-# INLINE poll #-}--modifyFd :: Backend -> Fd -> Event -> Event -> IO ()-modifyFd (Backend bState _ bModifyFd _) = bModifyFd bState-{-# INLINE modifyFd #-}--delete :: Backend -> IO ()-delete (Backend bState _ _ bDelete) = bDelete bState-{-# INLINE delete #-}---- | Throw an 'IOError' corresponding to the current value of--- 'getErrno' if the result value of the 'IO' action is -1 and--- 'getErrno' is not 'eINTR'. If the result value is -1 and--- 'getErrno' returns 'eINTR' 0 is returned. Otherwise the result--- value is returned.-throwErrnoIfMinus1NoRetry :: (Eq a, Num a) => String -> IO a -> IO a-throwErrnoIfMinus1NoRetry loc f = do- res <- f- if res == -1- then do- err <- getErrno- if err == eINTR then return 0 else throwErrno loc- else return res
@@ -1,302 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , ForeignFunctionInterface- , GeneralizedNewtypeDeriving- , NoImplicitPrelude- , RecordWildCards- , BangPatterns- #-}--module GHC.Event.KQueue- (- new- , available- ) where--import qualified GHC.Event.Internal as E--#include "EventConfig.h"-#if !defined(HAVE_KQUEUE)-import GHC.Base--new :: IO E.Backend-new = error "KQueue back end not implemented for this platform"--available :: Bool-available = False-{-# INLINE available #-}-#else--import Control.Concurrent.MVar (MVar, newMVar, swapMVar, withMVar)-import Control.Monad (when, unless)-import Data.Bits (Bits(..))-import Data.Word (Word16, Word32)-import Foreign.C.Error (throwErrnoIfMinus1)-import Foreign.C.Types-import Foreign.Marshal.Alloc (alloca)-import Foreign.Ptr (Ptr, nullPtr)-import Foreign.Storable (Storable(..))-import GHC.Base-import GHC.Enum (toEnum)-import GHC.Err (undefined)-import GHC.Num (Num(..))-import GHC.Real (ceiling, floor, fromIntegral)-import GHC.Show (Show(show))-import GHC.Event.Internal (Timeout(..))-import System.Posix.Internals (c_close)-import System.Posix.Types (Fd(..))-import qualified GHC.Event.Array as A--#if defined(HAVE_KEVENT64)-import Data.Int (Int64)-import Data.Word (Word64)-#endif--#include <sys/types.h>-#include <sys/event.h>-#include <sys/time.h>---- Handle brokenness on some BSD variants, notably OS X up to at least--- 10.6. If NOTE_EOF isn't available, we have no way to receive a--- notification from the kernel when we reach EOF on a plain file.-#ifndef NOTE_EOF-# define NOTE_EOF 0-#endif--available :: Bool-available = True-{-# INLINE available #-}----------------------------------------------------------------------------- Exported interface--data EventQueue = EventQueue {- eqFd :: {-# UNPACK #-} !QueueFd- , eqChanges :: {-# UNPACK #-} !(MVar (A.Array Event))- , eqEvents :: {-# UNPACK #-} !(A.Array Event)- }--new :: IO E.Backend-new = do- qfd <- kqueue- changesArr <- A.empty- changes <- newMVar changesArr - events <- A.new 64- let !be = E.backend poll modifyFd delete (EventQueue qfd changes events)- return be--delete :: EventQueue -> IO ()-delete q = do- _ <- c_close . fromQueueFd . eqFd $ q- return ()--modifyFd :: EventQueue -> Fd -> E.Event -> E.Event -> IO ()-modifyFd q fd oevt nevt = withMVar (eqChanges q) $ \ch -> do- let addChange filt flag = A.snoc ch $ event fd filt flag noteEOF- when (oevt `E.eventIs` E.evtRead) $ addChange filterRead flagDelete- when (oevt `E.eventIs` E.evtWrite) $ addChange filterWrite flagDelete- when (nevt `E.eventIs` E.evtRead) $ addChange filterRead flagAdd- when (nevt `E.eventIs` E.evtWrite) $ addChange filterWrite flagAdd--poll :: EventQueue- -> Timeout- -> (Fd -> E.Event -> IO ())- -> IO ()-poll EventQueue{..} tout f = do- changesArr <- A.empty- changes <- swapMVar eqChanges changesArr- changesLen <- A.length changes- len <- A.length eqEvents- when (changesLen > len) $ A.ensureCapacity eqEvents (2 * changesLen)- n <- A.useAsPtr changes $ \changesPtr chLen ->- A.unsafeLoad eqEvents $ \evPtr evCap ->- withTimeSpec (fromTimeout tout) $- kevent eqFd changesPtr chLen evPtr evCap-- unless (n == 0) $ do- cap <- A.capacity eqEvents- when (n == cap) $ A.ensureCapacity eqEvents (2 * cap)- A.forM_ eqEvents $ \e -> f (fromIntegral (ident e)) (toEvent (filter e))----------------------------------------------------------------------------- FFI binding--newtype QueueFd = QueueFd {- fromQueueFd :: CInt- } deriving (Eq, Show)--#if defined(HAVE_KEVENT64)-data Event = KEvent64 {- ident :: {-# UNPACK #-} !Word64- , filter :: {-# UNPACK #-} !Filter- , flags :: {-# UNPACK #-} !Flag- , fflags :: {-# UNPACK #-} !FFlag- , data_ :: {-# UNPACK #-} !Int64- , udata :: {-# UNPACK #-} !Word64- , ext0 :: {-# UNPACK #-} !Word64- , ext1 :: {-# UNPACK #-} !Word64- } deriving Show--event :: Fd -> Filter -> Flag -> FFlag -> Event-event fd filt flag fflag = KEvent64 (fromIntegral fd) filt flag fflag 0 0 0 0--instance Storable Event where- sizeOf _ = #size struct kevent64_s- alignment _ = alignment (undefined :: CInt)-- peek ptr = do- ident' <- #{peek struct kevent64_s, ident} ptr- filter' <- #{peek struct kevent64_s, filter} ptr- flags' <- #{peek struct kevent64_s, flags} ptr- fflags' <- #{peek struct kevent64_s, fflags} ptr- data' <- #{peek struct kevent64_s, data} ptr- udata' <- #{peek struct kevent64_s, udata} ptr- ext0' <- #{peek struct kevent64_s, ext[0]} ptr- ext1' <- #{peek struct kevent64_s, ext[1]} ptr- let !ev = KEvent64 ident' (Filter filter') (Flag flags') fflags' data'- udata' ext0' ext1'- return ev-- poke ptr ev = do- #{poke struct kevent64_s, ident} ptr (ident ev)- #{poke struct kevent64_s, filter} ptr (filter ev)- #{poke struct kevent64_s, flags} ptr (flags ev)- #{poke struct kevent64_s, fflags} ptr (fflags ev)- #{poke struct kevent64_s, data} ptr (data_ ev)- #{poke struct kevent64_s, udata} ptr (udata ev)- #{poke struct kevent64_s, ext[0]} ptr (ext0 ev)- #{poke struct kevent64_s, ext[1]} ptr (ext1 ev)-#else-data Event = KEvent {- ident :: {-# UNPACK #-} !CUIntPtr- , filter :: {-# UNPACK #-} !Filter- , flags :: {-# UNPACK #-} !Flag- , fflags :: {-# UNPACK #-} !FFlag- , data_ :: {-# UNPACK #-} !CIntPtr- , udata :: {-# UNPACK #-} !(Ptr ())- } deriving Show--event :: Fd -> Filter -> Flag -> FFlag -> Event-event fd filt flag fflag = KEvent (fromIntegral fd) filt flag fflag 0 nullPtr--instance Storable Event where- sizeOf _ = #size struct kevent- alignment _ = alignment (undefined :: CInt)-- peek ptr = do- ident' <- #{peek struct kevent, ident} ptr- filter' <- #{peek struct kevent, filter} ptr- flags' <- #{peek struct kevent, flags} ptr- fflags' <- #{peek struct kevent, fflags} ptr- data' <- #{peek struct kevent, data} ptr- udata' <- #{peek struct kevent, udata} ptr- let !ev = KEvent ident' (Filter filter') (Flag flags') fflags' data'- udata'- return ev-- poke ptr ev = do- #{poke struct kevent, ident} ptr (ident ev)- #{poke struct kevent, filter} ptr (filter ev)- #{poke struct kevent, flags} ptr (flags ev)- #{poke struct kevent, fflags} ptr (fflags ev)- #{poke struct kevent, data} ptr (data_ ev)- #{poke struct kevent, udata} ptr (udata ev)-#endif--newtype FFlag = FFlag Word32- deriving (Eq, Show, Storable)--#{enum FFlag, FFlag- , noteEOF = NOTE_EOF- }--newtype Flag = Flag Word16- deriving (Eq, Show, Storable)--#{enum Flag, Flag- , flagAdd = EV_ADD- , flagDelete = EV_DELETE- }--newtype Filter = Filter Word16- deriving (Bits, Eq, Num, Show, Storable)--#{enum Filter, Filter- , filterRead = EVFILT_READ- , filterWrite = EVFILT_WRITE- }--data TimeSpec = TimeSpec {- tv_sec :: {-# UNPACK #-} !CTime- , tv_nsec :: {-# UNPACK #-} !CLong- }--instance Storable TimeSpec where- sizeOf _ = #size struct timespec- alignment _ = alignment (undefined :: CInt)-- peek ptr = do- tv_sec' <- #{peek struct timespec, tv_sec} ptr- tv_nsec' <- #{peek struct timespec, tv_nsec} ptr- let !ts = TimeSpec tv_sec' tv_nsec'- return ts-- poke ptr ts = do- #{poke struct timespec, tv_sec} ptr (tv_sec ts)- #{poke struct timespec, tv_nsec} ptr (tv_nsec ts)--kqueue :: IO QueueFd-kqueue = QueueFd `fmap` throwErrnoIfMinus1 "kqueue" c_kqueue---- TODO: We cannot retry on EINTR as the timeout would be wrong.--- Perhaps we should just return without calling any callbacks.-kevent :: QueueFd -> Ptr Event -> Int -> Ptr Event -> Int -> Ptr TimeSpec- -> IO Int-kevent k chs chlen evs evlen ts- = fmap fromIntegral $ E.throwErrnoIfMinus1NoRetry "kevent" $-#if defined(HAVE_KEVENT64)- c_kevent64 k chs (fromIntegral chlen) evs (fromIntegral evlen) 0 ts-#else- c_kevent k chs (fromIntegral chlen) evs (fromIntegral evlen) ts-#endif--withTimeSpec :: TimeSpec -> (Ptr TimeSpec -> IO a) -> IO a-withTimeSpec ts f =- if tv_sec ts < 0 then- f nullPtr- else- alloca $ \ptr -> poke ptr ts >> f ptr--fromTimeout :: Timeout -> TimeSpec-fromTimeout Forever = TimeSpec (-1) (-1)-fromTimeout (Timeout s) = TimeSpec (toEnum sec) (toEnum nanosec)- where- sec :: Int- sec = floor s-- nanosec :: Int- nanosec = ceiling $ (s - fromIntegral sec) * 1000000000--toEvent :: Filter -> E.Event-toEvent (Filter f)- | f == (#const EVFILT_READ) = E.evtRead- | f == (#const EVFILT_WRITE) = E.evtWrite- | otherwise = error $ "toEvent: unknown filter " ++ show f--foreign import ccall unsafe "kqueue"- c_kqueue :: IO CInt--#if defined(HAVE_KEVENT64)-foreign import ccall safe "kevent64"- c_kevent64 :: QueueFd -> Ptr Event -> CInt -> Ptr Event -> CInt -> CUInt- -> Ptr TimeSpec -> IO CInt-#elif defined(HAVE_KEVENT)-foreign import ccall safe "kevent"- c_kevent :: QueueFd -> Ptr Event -> CInt -> Ptr Event -> CInt- -> Ptr TimeSpec -> IO CInt-#else-#error no kevent system call available!?-#endif--#endif /* defined(HAVE_KQUEUE) */-
@@ -1,407 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE BangPatterns- , CPP- , ExistentialQuantification- , NoImplicitPrelude- , RecordWildCards- , TypeSynonymInstances- , FlexibleInstances- #-}--module GHC.Event.Manager- ( -- * Types- EventManager-- -- * Creation- , new- , newWith- , newDefaultBackend-- -- * Running- , finished- , loop- , step- , shutdown- , cleanup- , wakeManager-- -- * Registering interest in I/O events- , Event- , evtRead- , evtWrite- , IOCallback- , FdKey(keyFd)- , registerFd_- , registerFd- , unregisterFd_- , unregisterFd- , closeFd-- -- * Registering interest in timeout events- , TimeoutCallback- , TimeoutKey- , registerTimeout- , updateTimeout- , unregisterTimeout- ) where--#include "EventConfig.h"----------------------------------------------------------------------------- Imports--import Control.Concurrent.MVar (MVar, modifyMVar, newMVar, readMVar)-import Control.Exception (finally)-import Control.Monad ((=<<), forM_, liftM, sequence_, when)-import Data.IORef (IORef, atomicModifyIORef, mkWeakIORef, newIORef, readIORef,- writeIORef)-import Data.Maybe (Maybe(..))-import Data.Monoid (mappend, mconcat, mempty)-import GHC.Base-import GHC.Conc.Signal (runHandlers)-import GHC.List (filter)-import GHC.Num (Num(..))-import GHC.Real ((/), fromIntegral )-import GHC.Show (Show(..))-import GHC.Event.Clock (getCurrentTime)-import GHC.Event.Control-import GHC.Event.Internal (Backend, Event, evtClose, evtRead, evtWrite,- Timeout(..))-import GHC.Event.Unique (Unique, UniqueSource, newSource, newUnique)-import System.Posix.Types (Fd)--import qualified GHC.Event.IntMap as IM-import qualified GHC.Event.Internal as I-import qualified GHC.Event.PSQ as Q--#if defined(HAVE_KQUEUE)-import qualified GHC.Event.KQueue as KQueue-#elif defined(HAVE_EPOLL)-import qualified GHC.Event.EPoll as EPoll-#elif defined(HAVE_POLL)-import qualified GHC.Event.Poll as Poll-#else-# error not implemented for this operating system-#endif----------------------------------------------------------------------------- Types--data FdData = FdData {- fdKey :: {-# UNPACK #-} !FdKey- , fdEvents :: {-# UNPACK #-} !Event- , _fdCallback :: !IOCallback- }---- | A file descriptor registration cookie.-data FdKey = FdKey {- keyFd :: {-# UNPACK #-} !Fd- , keyUnique :: {-# UNPACK #-} !Unique- } deriving (Eq, Show)---- | Callback invoked on I/O events.-type IOCallback = FdKey -> Event -> IO ()---- | A timeout registration cookie.-newtype TimeoutKey = TK Unique- deriving (Eq)---- | Callback invoked on timeout events.-type TimeoutCallback = IO ()--data State = Created- | Running- | Dying- | Finished- deriving (Eq, Show)---- | A priority search queue, with timeouts as priorities.-type TimeoutQueue = Q.PSQ TimeoutCallback--{--Instead of directly modifying the 'TimeoutQueue' in-e.g. 'registerTimeout' we keep a list of edits to perform, in the form-of a chain of function closures, and have the I/O manager thread-perform the edits later. This exist to address the following GC-problem:--Since e.g. 'registerTimeout' doesn't force the evaluation of the-thunks inside the 'emTimeouts' IORef a number of thunks build up-inside the IORef. If the I/O manager thread doesn't evaluate these-thunks soon enough they'll get promoted to the old generation and-become roots for all subsequent minor GCs.--When the thunks eventually get evaluated they will each create a new-intermediate 'TimeoutQueue' that immediately becomes garbage. Since-the thunks serve as roots until the next major GC these intermediate-'TimeoutQueue's will get copied unnecesarily in the next minor GC,-increasing GC time. This problem is known as "floating garbage".--Keeping a list of edits doesn't stop this from happening but makes the-amount of data that gets copied smaller.--TODO: Evaluate the content of the IORef to WHNF on each insert once-this bug is resolved: http://hackage.haskell.org/trac/ghc/ticket/3838--}---- | An edit to apply to a 'TimeoutQueue'.-type TimeoutEdit = TimeoutQueue -> TimeoutQueue---- | The event manager state.-data EventManager = EventManager- { emBackend :: !Backend- , emFds :: {-# UNPACK #-} !(MVar (IM.IntMap [FdData]))- , emTimeouts :: {-# UNPACK #-} !(IORef TimeoutEdit)- , emState :: {-# UNPACK #-} !(IORef State)- , emUniqueSource :: {-# UNPACK #-} !UniqueSource- , emControl :: {-# UNPACK #-} !Control- }----------------------------------------------------------------------------- Creation--handleControlEvent :: EventManager -> FdKey -> Event -> IO ()-handleControlEvent mgr reg _evt = do- msg <- readControlMessage (emControl mgr) (keyFd reg)- case msg of- CMsgWakeup -> return ()- CMsgDie -> writeIORef (emState mgr) Finished- CMsgSignal fp s -> runHandlers fp s--newDefaultBackend :: IO Backend-#if defined(HAVE_KQUEUE)-newDefaultBackend = KQueue.new-#elif defined(HAVE_EPOLL)-newDefaultBackend = EPoll.new-#elif defined(HAVE_POLL)-newDefaultBackend = Poll.new-#else-newDefaultBackend = error "no back end for this platform"-#endif---- | Create a new event manager.-new :: IO EventManager-new = newWith =<< newDefaultBackend--newWith :: Backend -> IO EventManager-newWith be = do- iofds <- newMVar IM.empty- timeouts <- newIORef id- ctrl <- newControl- state <- newIORef Created- us <- newSource- _ <- mkWeakIORef state $ do- st <- atomicModifyIORef state $ \s -> (Finished, s)- when (st /= Finished) $ do- I.delete be- closeControl ctrl- let mgr = EventManager { emBackend = be- , emFds = iofds- , emTimeouts = timeouts- , emState = state- , emUniqueSource = us- , emControl = ctrl- }- _ <- registerFd_ mgr (handleControlEvent mgr) (controlReadFd ctrl) evtRead- _ <- registerFd_ mgr (handleControlEvent mgr) (wakeupReadFd ctrl) evtRead- return mgr---- | Asynchronously shuts down the event manager, if running.-shutdown :: EventManager -> IO ()-shutdown mgr = do- state <- atomicModifyIORef (emState mgr) $ \s -> (Dying, s)- when (state == Running) $ sendDie (emControl mgr)--finished :: EventManager -> IO Bool-finished mgr = (== Finished) `liftM` readIORef (emState mgr)--cleanup :: EventManager -> IO ()-cleanup EventManager{..} = do- writeIORef emState Finished- I.delete emBackend- closeControl emControl----------------------------------------------------------------------------- Event loop---- | Start handling events. This function loops until told to stop,--- using 'shutdown'.------ /Note/: This loop can only be run once per 'EventManager', as it--- closes all of its control resources when it finishes.-loop :: EventManager -> IO ()-loop mgr@EventManager{..} = do- state <- atomicModifyIORef emState $ \s -> case s of- Created -> (Running, s)- _ -> (s, s)- case state of- Created -> go Q.empty `finally` cleanup mgr- Dying -> cleanup mgr- _ -> do cleanup mgr- error $ "GHC.Event.Manager.loop: state is already " ++- show state- where- go q = do (running, q') <- step mgr q- when running $ go q'--step :: EventManager -> TimeoutQueue -> IO (Bool, TimeoutQueue)-step mgr@EventManager{..} tq = do- (timeout, q') <- mkTimeout tq- I.poll emBackend timeout (onFdEvent mgr)- state <- readIORef emState- state `seq` return (state == Running, q')- where-- -- | Call all expired timer callbacks and return the time to the- -- next timeout.- mkTimeout :: TimeoutQueue -> IO (Timeout, TimeoutQueue)- mkTimeout q = do- now <- getCurrentTime- applyEdits <- atomicModifyIORef emTimeouts $ \f -> (id, f)- let (expired, q'') = let q' = applyEdits q in q' `seq` Q.atMost now q'- sequence_ $ map Q.value expired- let timeout = case Q.minView q'' of- Nothing -> Forever- Just (Q.E _ t _, _) ->- -- This value will always be positive since the call- -- to 'atMost' above removed any timeouts <= 'now'- let t' = t - now in t' `seq` Timeout t'- return (timeout, q'')----------------------------------------------------------------------------- Registering interest in I/O events---- | Register interest in the given events, without waking the event--- manager thread. The 'Bool' return value indicates whether the--- event manager ought to be woken.-registerFd_ :: EventManager -> IOCallback -> Fd -> Event- -> IO (FdKey, Bool)-registerFd_ EventManager{..} cb fd evs = do- u <- newUnique emUniqueSource- modifyMVar emFds $ \oldMap -> do- let fd' = fromIntegral fd- reg = FdKey fd u- !fdd = FdData reg evs cb- (!newMap, (oldEvs, newEvs)) =- case IM.insertWith (++) fd' [fdd] oldMap of- (Nothing, n) -> (n, (mempty, evs))- (Just prev, n) -> (n, pairEvents prev newMap fd')- modify = oldEvs /= newEvs- when modify $ I.modifyFd emBackend fd oldEvs newEvs- return (newMap, (reg, modify))-{-# INLINE registerFd_ #-}---- | @registerFd mgr cb fd evs@ registers interest in the events @evs@--- on the file descriptor @fd@. @cb@ is called for each event that--- occurs. Returns a cookie that can be handed to 'unregisterFd'.-registerFd :: EventManager -> IOCallback -> Fd -> Event -> IO FdKey-registerFd mgr cb fd evs = do- (r, wake) <- registerFd_ mgr cb fd evs- when wake $ wakeManager mgr- return r-{-# INLINE registerFd #-}---- | Wake up the event manager.-wakeManager :: EventManager -> IO ()-wakeManager mgr = sendWakeup (emControl mgr)--eventsOf :: [FdData] -> Event-eventsOf = mconcat . map fdEvents--pairEvents :: [FdData] -> IM.IntMap [FdData] -> Int -> (Event, Event)-pairEvents prev m fd = let l = eventsOf prev- r = case IM.lookup fd m of- Nothing -> mempty- Just fds -> eventsOf fds- in (l, r)---- | Drop a previous file descriptor registration, without waking the--- event manager thread. The return value indicates whether the event--- manager ought to be woken.-unregisterFd_ :: EventManager -> FdKey -> IO Bool-unregisterFd_ EventManager{..} (FdKey fd u) =- modifyMVar emFds $ \oldMap -> do- let dropReg cbs = case filter ((/= u) . keyUnique . fdKey) cbs of- [] -> Nothing- cbs' -> Just cbs'- fd' = fromIntegral fd- (!newMap, (oldEvs, newEvs)) =- case IM.updateWith dropReg fd' oldMap of- (Nothing, _) -> (oldMap, (mempty, mempty))- (Just prev, newm) -> (newm, pairEvents prev newm fd')- modify = oldEvs /= newEvs- when modify $ I.modifyFd emBackend fd oldEvs newEvs- return (newMap, modify)---- | Drop a previous file descriptor registration.-unregisterFd :: EventManager -> FdKey -> IO ()-unregisterFd mgr reg = do- wake <- unregisterFd_ mgr reg- when wake $ wakeManager mgr---- | Close a file descriptor in a race-safe way.-closeFd :: EventManager -> (Fd -> IO ()) -> Fd -> IO ()-closeFd mgr close fd = do- fds <- modifyMVar (emFds mgr) $ \oldMap -> do- close fd- case IM.delete (fromIntegral fd) oldMap of- (Nothing, _) -> return (oldMap, [])- (Just fds, !newMap) -> do- when (eventsOf fds /= mempty) $ wakeManager mgr- return (newMap, fds)- forM_ fds $ \(FdData reg ev cb) -> cb reg (ev `mappend` evtClose)----------------------------------------------------------------------------- Registering interest in timeout events---- | Register a timeout in the given number of microseconds. The--- returned 'TimeoutKey' can be used to later unregister or update the--- timeout. The timeout is automatically unregistered after the given--- time has passed.-registerTimeout :: EventManager -> Int -> TimeoutCallback -> IO TimeoutKey-registerTimeout mgr us cb = do- !key <- newUnique (emUniqueSource mgr)- if us <= 0 then cb- else do- now <- getCurrentTime- let expTime = fromIntegral us / 1000000.0 + now-- -- We intentionally do not evaluate the modified map to WHNF here.- -- Instead, we leave a thunk inside the IORef and defer its- -- evaluation until mkTimeout in the event loop. This is a- -- workaround for a nasty IORef contention problem that causes the- -- thread-delay benchmark to take 20 seconds instead of 0.2.- atomicModifyIORef (emTimeouts mgr) $ \f ->- let f' = (Q.insert key expTime cb) . f in (f', ())- wakeManager mgr- return $ TK key---- | Unregister an active timeout.-unregisterTimeout :: EventManager -> TimeoutKey -> IO ()-unregisterTimeout mgr (TK key) = do- atomicModifyIORef (emTimeouts mgr) $ \f ->- let f' = (Q.delete key) . f in (f', ())- wakeManager mgr---- | Update an active timeout to fire in the given number of--- microseconds.-updateTimeout :: EventManager -> TimeoutKey -> Int -> IO ()-updateTimeout mgr (TK key) us = do- now <- getCurrentTime- let expTime = fromIntegral us / 1000000.0 + now-- atomicModifyIORef (emTimeouts mgr) $ \f ->- let f' = (Q.adjust (const expTime) key) . f in (f', ())- wakeManager mgr----------------------------------------------------------------------------- Utilities---- | Call the callbacks corresponding to the given file descriptor.-onFdEvent :: EventManager -> Fd -> Event -> IO ()-onFdEvent mgr fd evs = do- fds <- readMVar (emFds mgr)- case IM.lookup (fromIntegral fd) fds of- Just cbs -> forM_ cbs $ \(FdData reg ev cb) ->- when (evs `I.eventIs` ev) $ cb reg evs- Nothing -> return ()
@@ -1,485 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE BangPatterns, NoImplicitPrelude #-}---- Copyright (c) 2008, Ralf Hinze--- All rights reserved.------ Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions--- are met:------ * Redistributions of source code must retain the above--- copyright notice, this list of conditions and the following--- disclaimer.------ * Redistributions in binary form must reproduce the above--- copyright notice, this list of conditions and the following--- disclaimer in the documentation and/or other materials--- provided with the distribution.------ * The names of the contributors may not be used to endorse or--- promote products derived from this software without specific--- prior written permission.------ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS--- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT--- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS--- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE--- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,--- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES--- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR--- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)--- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,--- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED--- OF THE POSSIBILITY OF SUCH DAMAGE.---- | A /priority search queue/ (henceforth /queue/) efficiently--- supports the operations of both a search tree and a priority queue.--- An 'Elem'ent is a product of a key, a priority, and a--- value. Elements can be inserted, deleted, modified and queried in--- logarithmic time, and the element with the least priority can be--- retrieved in constant time. A queue can be built from a list of--- elements, sorted by keys, in linear time.------ This implementation is due to Ralf Hinze with some modifications by--- Scott Dillard and Johan Tibell.------ * Hinze, R., /A Simple Implementation Technique for Priority Search--- Queues/, ICFP 2001, pp. 110-121------ <http://citeseer.ist.psu.edu/hinze01simple.html>-module GHC.Event.PSQ- (- -- * Binding Type- Elem(..)- , Key- , Prio-- -- * Priority Search Queue Type- , PSQ-- -- * Query- , size- , null- , lookup-- -- * Construction- , empty- , singleton-- -- * Insertion- , insert-- -- * Delete/Update- , delete- , adjust-- -- * Conversion- , toList- , toAscList- , toDescList- , fromList-- -- * Min- , findMin- , deleteMin- , minView- , atMost- ) where--import Data.Maybe (Maybe(..))-import GHC.Base-import GHC.Num (Num(..))-import GHC.Show (Show(showsPrec))-import GHC.Event.Unique (Unique)---- | @E k p@ binds the key @k@ with the priority @p@.-data Elem a = E- { key :: {-# UNPACK #-} !Key- , prio :: {-# UNPACK #-} !Prio- , value :: a- } deriving (Eq, Show)----------------------------------------------------------------------------- | A mapping from keys @k@ to priorites @p@.--type Prio = Double-type Key = Unique--data PSQ a = Void- | Winner {-# UNPACK #-} !(Elem a)- !(LTree a)- {-# UNPACK #-} !Key -- max key- deriving (Eq, Show)---- | /O(1)/ The number of elements in a queue.-size :: PSQ a -> Int-size Void = 0-size (Winner _ lt _) = 1 + size' lt---- | /O(1)/ True if the queue is empty.-null :: PSQ a -> Bool-null Void = True-null (Winner _ _ _) = False---- | /O(log n)/ The priority and value of a given key, or Nothing if--- the key is not bound.-lookup :: Key -> PSQ a -> Maybe (Prio, a)-lookup k q = case tourView q of- Null -> Nothing- Single (E k' p v)- | k == k' -> Just (p, v)- | otherwise -> Nothing- tl `Play` tr- | k <= maxKey tl -> lookup k tl- | otherwise -> lookup k tr----------------------------------------------------------------------------- Construction--empty :: PSQ a-empty = Void---- | /O(1)/ Build a queue with one element.-singleton :: Key -> Prio -> a -> PSQ a-singleton k p v = Winner (E k p v) Start k----------------------------------------------------------------------------- Insertion---- | /O(log n)/ Insert a new key, priority and value in the queue. If--- the key is already present in the queue, the associated priority--- and value are replaced with the supplied priority and value.-insert :: Key -> Prio -> a -> PSQ a -> PSQ a-insert k p v q = case q of- Void -> singleton k p v- Winner (E k' p' v') Start _ -> case compare k k' of- LT -> singleton k p v `play` singleton k' p' v'- EQ -> singleton k p v- GT -> singleton k' p' v' `play` singleton k p v- Winner e (RLoser _ e' tl m tr) m'- | k <= m -> insert k p v (Winner e tl m) `play` (Winner e' tr m')- | otherwise -> (Winner e tl m) `play` insert k p v (Winner e' tr m')- Winner e (LLoser _ e' tl m tr) m'- | k <= m -> insert k p v (Winner e' tl m) `play` (Winner e tr m')- | otherwise -> (Winner e' tl m) `play` insert k p v (Winner e tr m')----------------------------------------------------------------------------- Delete/Update---- | /O(log n)/ Delete a key and its priority and value from the--- queue. When the key is not a member of the queue, the original--- queue is returned.-delete :: Key -> PSQ a -> PSQ a-delete k q = case q of- Void -> empty- Winner (E k' p v) Start _- | k == k' -> empty- | otherwise -> singleton k' p v- Winner e (RLoser _ e' tl m tr) m'- | k <= m -> delete k (Winner e tl m) `play` (Winner e' tr m')- | otherwise -> (Winner e tl m) `play` delete k (Winner e' tr m')- Winner e (LLoser _ e' tl m tr) m'- | k <= m -> delete k (Winner e' tl m) `play` (Winner e tr m')- | otherwise -> (Winner e' tl m) `play` delete k (Winner e tr m')---- | /O(log n)/ Update a priority at a specific key with the result--- of the provided function. When the key is not a member of the--- queue, the original queue is returned.-adjust :: (Prio -> Prio) -> Key -> PSQ a -> PSQ a-adjust f k q0 = go q0- where- go q = case q of- Void -> empty- Winner (E k' p v) Start _- | k == k' -> singleton k' (f p) v- | otherwise -> singleton k' p v- Winner e (RLoser _ e' tl m tr) m'- | k <= m -> go (Winner e tl m) `unsafePlay` (Winner e' tr m')- | otherwise -> (Winner e tl m) `unsafePlay` go (Winner e' tr m')- Winner e (LLoser _ e' tl m tr) m'- | k <= m -> go (Winner e' tl m) `unsafePlay` (Winner e tr m')- | otherwise -> (Winner e' tl m) `unsafePlay` go (Winner e tr m')-{-# INLINE adjust #-}----------------------------------------------------------------------------- Conversion---- | /O(n*log n)/ Build a queue from a list of key/priority/value--- tuples. If the list contains more than one priority and value for--- the same key, the last priority and value for the key is retained.-fromList :: [Elem a] -> PSQ a-fromList = foldr (\(E k p v) q -> insert k p v q) empty---- | /O(n)/ Convert to a list of key/priority/value tuples.-toList :: PSQ a -> [Elem a]-toList = toAscList---- | /O(n)/ Convert to an ascending list.-toAscList :: PSQ a -> [Elem a]-toAscList q = seqToList (toAscLists q)--toAscLists :: PSQ a -> Sequ (Elem a)-toAscLists q = case tourView q of- Null -> emptySequ- Single e -> singleSequ e- tl `Play` tr -> toAscLists tl <> toAscLists tr---- | /O(n)/ Convert to a descending list.-toDescList :: PSQ a -> [ Elem a ]-toDescList q = seqToList (toDescLists q)--toDescLists :: PSQ a -> Sequ (Elem a)-toDescLists q = case tourView q of- Null -> emptySequ- Single e -> singleSequ e- tl `Play` tr -> toDescLists tr <> toDescLists tl----------------------------------------------------------------------------- Min---- | /O(1)/ The element with the lowest priority.-findMin :: PSQ a -> Maybe (Elem a)-findMin Void = Nothing-findMin (Winner e _ _) = Just e---- | /O(log n)/ Delete the element with the lowest priority. Returns--- an empty queue if the queue is empty.-deleteMin :: PSQ a -> PSQ a-deleteMin Void = Void-deleteMin (Winner _ t m) = secondBest t m---- | /O(log n)/ Retrieve the binding with the least priority, and the--- rest of the queue stripped of that binding.-minView :: PSQ a -> Maybe (Elem a, PSQ a)-minView Void = Nothing-minView (Winner e t m) = Just (e, secondBest t m)--secondBest :: LTree a -> Key -> PSQ a-secondBest Start _ = Void-secondBest (LLoser _ e tl m tr) m' = Winner e tl m `play` secondBest tr m'-secondBest (RLoser _ e tl m tr) m' = secondBest tl m `play` Winner e tr m'---- | /O(r*(log n - log r))/ Return a list of elements ordered by--- key whose priorities are at most @pt@.-atMost :: Prio -> PSQ a -> ([Elem a], PSQ a)-atMost pt q = let (sequ, q') = atMosts pt q- in (seqToList sequ, q')--atMosts :: Prio -> PSQ a -> (Sequ (Elem a), PSQ a)-atMosts !pt q = case q of- (Winner e _ _)- | prio e > pt -> (emptySequ, q)- Void -> (emptySequ, Void)- Winner e Start _ -> (singleSequ e, Void)- Winner e (RLoser _ e' tl m tr) m' ->- let (sequ, q') = atMosts pt (Winner e tl m)- (sequ', q'') = atMosts pt (Winner e' tr m')- in (sequ <> sequ', q' `play` q'')- Winner e (LLoser _ e' tl m tr) m' ->- let (sequ, q') = atMosts pt (Winner e' tl m)- (sequ', q'') = atMosts pt (Winner e tr m')- in (sequ <> sequ', q' `play` q'')----------------------------------------------------------------------------- Loser tree--type Size = Int--data LTree a = Start- | LLoser {-# UNPACK #-} !Size- {-# UNPACK #-} !(Elem a)- !(LTree a)- {-# UNPACK #-} !Key -- split key- !(LTree a)- | RLoser {-# UNPACK #-} !Size- {-# UNPACK #-} !(Elem a)- !(LTree a)- {-# UNPACK #-} !Key -- split key- !(LTree a)- deriving (Eq, Show)--size' :: LTree a -> Size-size' Start = 0-size' (LLoser s _ _ _ _) = s-size' (RLoser s _ _ _ _) = s--left, right :: LTree a -> LTree a--left Start = moduleError "left" "empty loser tree"-left (LLoser _ _ tl _ _ ) = tl-left (RLoser _ _ tl _ _ ) = tl--right Start = moduleError "right" "empty loser tree"-right (LLoser _ _ _ _ tr) = tr-right (RLoser _ _ _ _ tr) = tr--maxKey :: PSQ a -> Key-maxKey Void = moduleError "maxKey" "empty queue"-maxKey (Winner _ _ m) = m--lloser, rloser :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-lloser k p v tl m tr = LLoser (1 + size' tl + size' tr) (E k p v) tl m tr-rloser k p v tl m tr = RLoser (1 + size' tl + size' tr) (E k p v) tl m tr----------------------------------------------------------------------------- Balancing---- | Balance factor-omega :: Int-omega = 4--lbalance, rbalance :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a--lbalance k p v l m r- | size' l + size' r < 2 = lloser k p v l m r- | size' r > omega * size' l = lbalanceLeft k p v l m r- | size' l > omega * size' r = lbalanceRight k p v l m r- | otherwise = lloser k p v l m r--rbalance k p v l m r- | size' l + size' r < 2 = rloser k p v l m r- | size' r > omega * size' l = rbalanceLeft k p v l m r- | size' l > omega * size' r = rbalanceRight k p v l m r- | otherwise = rloser k p v l m r--lbalanceLeft :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-lbalanceLeft k p v l m r- | size' (left r) < size' (right r) = lsingleLeft k p v l m r- | otherwise = ldoubleLeft k p v l m r--lbalanceRight :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-lbalanceRight k p v l m r- | size' (left l) > size' (right l) = lsingleRight k p v l m r- | otherwise = ldoubleRight k p v l m r--rbalanceLeft :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-rbalanceLeft k p v l m r- | size' (left r) < size' (right r) = rsingleLeft k p v l m r- | otherwise = rdoubleLeft k p v l m r--rbalanceRight :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-rbalanceRight k p v l m r- | size' (left l) > size' (right l) = rsingleRight k p v l m r- | otherwise = rdoubleRight k p v l m r--lsingleLeft :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-lsingleLeft k1 p1 v1 t1 m1 (LLoser _ (E k2 p2 v2) t2 m2 t3)- | p1 <= p2 = lloser k1 p1 v1 (rloser k2 p2 v2 t1 m1 t2) m2 t3- | otherwise = lloser k2 p2 v2 (lloser k1 p1 v1 t1 m1 t2) m2 t3-lsingleLeft k1 p1 v1 t1 m1 (RLoser _ (E k2 p2 v2) t2 m2 t3) =- rloser k2 p2 v2 (lloser k1 p1 v1 t1 m1 t2) m2 t3-lsingleLeft _ _ _ _ _ _ = moduleError "lsingleLeft" "malformed tree"--rsingleLeft :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-rsingleLeft k1 p1 v1 t1 m1 (LLoser _ (E k2 p2 v2) t2 m2 t3) =- rloser k1 p1 v1 (rloser k2 p2 v2 t1 m1 t2) m2 t3-rsingleLeft k1 p1 v1 t1 m1 (RLoser _ (E k2 p2 v2) t2 m2 t3) =- rloser k2 p2 v2 (rloser k1 p1 v1 t1 m1 t2) m2 t3-rsingleLeft _ _ _ _ _ _ = moduleError "rsingleLeft" "malformed tree"--lsingleRight :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-lsingleRight k1 p1 v1 (LLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- lloser k2 p2 v2 t1 m1 (lloser k1 p1 v1 t2 m2 t3)-lsingleRight k1 p1 v1 (RLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- lloser k1 p1 v1 t1 m1 (lloser k2 p2 v2 t2 m2 t3)-lsingleRight _ _ _ _ _ _ = moduleError "lsingleRight" "malformed tree"--rsingleRight :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-rsingleRight k1 p1 v1 (LLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- lloser k2 p2 v2 t1 m1 (rloser k1 p1 v1 t2 m2 t3)-rsingleRight k1 p1 v1 (RLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3- | p1 <= p2 = rloser k1 p1 v1 t1 m1 (lloser k2 p2 v2 t2 m2 t3)- | otherwise = rloser k2 p2 v2 t1 m1 (rloser k1 p1 v1 t2 m2 t3)-rsingleRight _ _ _ _ _ _ = moduleError "rsingleRight" "malformed tree"--ldoubleLeft :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-ldoubleLeft k1 p1 v1 t1 m1 (LLoser _ (E k2 p2 v2) t2 m2 t3) =- lsingleLeft k1 p1 v1 t1 m1 (lsingleRight k2 p2 v2 t2 m2 t3)-ldoubleLeft k1 p1 v1 t1 m1 (RLoser _ (E k2 p2 v2) t2 m2 t3) =- lsingleLeft k1 p1 v1 t1 m1 (rsingleRight k2 p2 v2 t2 m2 t3)-ldoubleLeft _ _ _ _ _ _ = moduleError "ldoubleLeft" "malformed tree"--ldoubleRight :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-ldoubleRight k1 p1 v1 (LLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- lsingleRight k1 p1 v1 (lsingleLeft k2 p2 v2 t1 m1 t2) m2 t3-ldoubleRight k1 p1 v1 (RLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- lsingleRight k1 p1 v1 (rsingleLeft k2 p2 v2 t1 m1 t2) m2 t3-ldoubleRight _ _ _ _ _ _ = moduleError "ldoubleRight" "malformed tree"--rdoubleLeft :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-rdoubleLeft k1 p1 v1 t1 m1 (LLoser _ (E k2 p2 v2) t2 m2 t3) =- rsingleLeft k1 p1 v1 t1 m1 (lsingleRight k2 p2 v2 t2 m2 t3)-rdoubleLeft k1 p1 v1 t1 m1 (RLoser _ (E k2 p2 v2) t2 m2 t3) =- rsingleLeft k1 p1 v1 t1 m1 (rsingleRight k2 p2 v2 t2 m2 t3)-rdoubleLeft _ _ _ _ _ _ = moduleError "rdoubleLeft" "malformed tree"--rdoubleRight :: Key -> Prio -> a -> LTree a -> Key -> LTree a -> LTree a-rdoubleRight k1 p1 v1 (LLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- rsingleRight k1 p1 v1 (lsingleLeft k2 p2 v2 t1 m1 t2) m2 t3-rdoubleRight k1 p1 v1 (RLoser _ (E k2 p2 v2) t1 m1 t2) m2 t3 =- rsingleRight k1 p1 v1 (rsingleLeft k2 p2 v2 t1 m1 t2) m2 t3-rdoubleRight _ _ _ _ _ _ = moduleError "rdoubleRight" "malformed tree"---- | Take two pennants and returns a new pennant that is the union of--- the two with the precondition that the keys in the first tree are--- strictly smaller than the keys in the second tree.-play :: PSQ a -> PSQ a -> PSQ a-Void `play` t' = t'-t `play` Void = t-Winner e@(E k p v) t m `play` Winner e'@(E k' p' v') t' m'- | p <= p' = Winner e (rbalance k' p' v' t m t') m'- | otherwise = Winner e' (lbalance k p v t m t') m'-{-# INLINE play #-}---- | A version of 'play' that can be used if the shape of the tree has--- not changed or if the tree is known to be balanced.-unsafePlay :: PSQ a -> PSQ a -> PSQ a-Void `unsafePlay` t' = t'-t `unsafePlay` Void = t-Winner e@(E k p v) t m `unsafePlay` Winner e'@(E k' p' v') t' m'- | p <= p' = Winner e (rloser k' p' v' t m t') m'- | otherwise = Winner e' (lloser k p v t m t') m'-{-# INLINE unsafePlay #-}--data TourView a = Null- | Single {-# UNPACK #-} !(Elem a)- | (PSQ a) `Play` (PSQ a)--tourView :: PSQ a -> TourView a-tourView Void = Null-tourView (Winner e Start _) = Single e-tourView (Winner e (RLoser _ e' tl m tr) m') =- Winner e tl m `Play` Winner e' tr m'-tourView (Winner e (LLoser _ e' tl m tr) m') =- Winner e' tl m `Play` Winner e tr m'----------------------------------------------------------------------------- Utility functions--moduleError :: String -> String -> a-moduleError fun msg = error ("GHC.Event.PSQ." ++ fun ++ ':' : ' ' : msg)-{-# NOINLINE moduleError #-}----------------------------------------------------------------------------- Hughes's efficient sequence type--newtype Sequ a = Sequ ([a] -> [a])--emptySequ :: Sequ a-emptySequ = Sequ (\as -> as)--singleSequ :: a -> Sequ a-singleSequ a = Sequ (\as -> a : as)--(<>) :: Sequ a -> Sequ a -> Sequ a-Sequ x1 <> Sequ x2 = Sequ (\as -> x1 (x2 as))-infixr 5 <>--seqToList :: Sequ a -> [a]-seqToList (Sequ x) = x []--instance Show a => Show (Sequ a) where- showsPrec d a = showsPrec d (seqToList a)-
@@ -1,163 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , ForeignFunctionInterface- , GeneralizedNewtypeDeriving- , NoImplicitPrelude- , BangPatterns- #-}--module GHC.Event.Poll- (- new- , available- ) where--#include "EventConfig.h"--#if !defined(HAVE_POLL_H)-import GHC.Base--new :: IO E.Backend-new = error "Poll back end not implemented for this platform"--available :: Bool-available = False-{-# INLINE available #-}-#else-#include <poll.h>--import Control.Concurrent.MVar (MVar, newMVar, swapMVar)-import Control.Monad ((=<<), liftM, liftM2, unless)-import Data.Bits (Bits, (.|.), (.&.))-import Data.Maybe (Maybe(..))-import Data.Monoid (Monoid(..))-import Foreign.C.Types (CInt(..), CShort(..), CULong(..))-import Foreign.Ptr (Ptr)-import Foreign.Storable (Storable(..))-import GHC.Base-import GHC.Conc.Sync (withMVar)-import GHC.Err (undefined)-import GHC.Num (Num(..))-import GHC.Real (ceiling, fromIntegral)-import GHC.Show (Show)-import System.Posix.Types (Fd(..))--import qualified GHC.Event.Array as A-import qualified GHC.Event.Internal as E--available :: Bool-available = True-{-# INLINE available #-}--data Poll = Poll {- pollChanges :: {-# UNPACK #-} !(MVar (A.Array PollFd))- , pollFd :: {-# UNPACK #-} !(A.Array PollFd)- }--new :: IO E.Backend-new = E.backend poll modifyFd (\_ -> return ()) `liftM`- liftM2 Poll (newMVar =<< A.empty) A.empty--modifyFd :: Poll -> Fd -> E.Event -> E.Event -> IO ()-modifyFd p fd oevt nevt =- withMVar (pollChanges p) $ \ary ->- A.snoc ary $ PollFd fd (fromEvent nevt) (fromEvent oevt)--reworkFd :: Poll -> PollFd -> IO ()-reworkFd p (PollFd fd npevt opevt) = do- let ary = pollFd p- if opevt == 0- then A.snoc ary $ PollFd fd npevt 0- else do- found <- A.findIndex ((== fd) . pfdFd) ary- case found of- Nothing -> error "reworkFd: event not found"- Just (i,_)- | npevt /= 0 -> A.unsafeWrite ary i $ PollFd fd npevt 0- | otherwise -> A.removeAt ary i--poll :: Poll- -> E.Timeout- -> (Fd -> E.Event -> IO ())- -> IO ()-poll p tout f = do- let a = pollFd p- mods <- swapMVar (pollChanges p) =<< A.empty- A.forM_ mods (reworkFd p)- n <- A.useAsPtr a $ \ptr len -> E.throwErrnoIfMinus1NoRetry "c_poll" $- c_poll ptr (fromIntegral len) (fromIntegral (fromTimeout tout))- unless (n == 0) $ do- A.loop a 0 $ \i e -> do- let r = pfdRevents e- if r /= 0- then do f (pfdFd e) (toEvent r)- let i' = i + 1- return (i', i' == n)- else return (i, True)--fromTimeout :: E.Timeout -> Int-fromTimeout E.Forever = -1-fromTimeout (E.Timeout s) = ceiling $ 1000 * s--data PollFd = PollFd {- pfdFd :: {-# UNPACK #-} !Fd- , pfdEvents :: {-# UNPACK #-} !Event- , pfdRevents :: {-# UNPACK #-} !Event- } deriving (Show)--newtype Event = Event CShort- deriving (Eq, Show, Num, Storable, Bits)---- We have to duplicate the whole enum like this in order for the--- hsc2hs cross-compilation mode to work-#ifdef POLLRDHUP-#{enum Event, Event- , pollIn = POLLIN- , pollOut = POLLOUT- , pollRdHup = POLLRDHUP- , pollErr = POLLERR- , pollHup = POLLHUP- }-#else-#{enum Event, Event- , pollIn = POLLIN- , pollOut = POLLOUT- , pollErr = POLLERR- , pollHup = POLLHUP- }-#endif--fromEvent :: E.Event -> Event-fromEvent e = remap E.evtRead pollIn .|.- remap E.evtWrite pollOut- where remap evt to- | e `E.eventIs` evt = to- | otherwise = 0--toEvent :: Event -> E.Event-toEvent e = remap (pollIn .|. pollErr .|. pollHup) E.evtRead `mappend`- remap (pollOut .|. pollErr .|. pollHup) E.evtWrite- where remap evt to- | e .&. evt /= 0 = to- | otherwise = mempty--instance Storable PollFd where- sizeOf _ = #size struct pollfd- alignment _ = alignment (undefined :: CInt)-- peek ptr = do- fd <- #{peek struct pollfd, fd} ptr- events <- #{peek struct pollfd, events} ptr- revents <- #{peek struct pollfd, revents} ptr- let !pollFd' = PollFd fd events revents- return pollFd'-- poke ptr p = do- #{poke struct pollfd, fd} ptr (pfdFd p)- #{poke struct pollfd, events} ptr (pfdEvents p)- #{poke struct pollfd, revents} ptr (pfdRevents p)--foreign import ccall safe "poll.h poll"- c_poll :: Ptr PollFd -> CULong -> CInt -> IO CInt--#endif /* defined(HAVE_POLL_H) */
@@ -1,151 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE BangPatterns, ForeignFunctionInterface, NoImplicitPrelude #-}--module GHC.Event.Thread- ( getSystemEventManager- , ensureIOManagerIsRunning- , threadWaitRead- , threadWaitWrite- , closeFdWith- , threadDelay- , registerDelay- ) where--import Data.IORef (IORef, newIORef, readIORef, writeIORef)-import Data.Maybe (Maybe(..))-import Foreign.C.Error (eBADF, errnoToIOError)-import Foreign.Ptr (Ptr)-import GHC.Base-import GHC.Conc.Sync (TVar, ThreadId, ThreadStatus(..), atomically, forkIO,- labelThread, modifyMVar_, newTVar, sharedCAF,- threadStatus, writeTVar)-import GHC.IO (mask_, onException)-import GHC.IO.Exception (ioError)-import GHC.MVar (MVar, newEmptyMVar, newMVar, putMVar, takeMVar)-import GHC.Event.Internal (eventIs, evtClose)-import GHC.Event.Manager (Event, EventManager, evtRead, evtWrite, loop,- new, registerFd, unregisterFd_, registerTimeout)-import qualified GHC.Event.Manager as M-import System.IO.Unsafe (unsafePerformIO)-import System.Posix.Types (Fd)---- | Suspends the current thread for a given number of microseconds--- (GHC only).------ There is no guarantee that the thread will be rescheduled promptly--- when the delay has expired, but the thread will never continue to--- run /earlier/ than specified.-threadDelay :: Int -> IO ()-threadDelay usecs = mask_ $ do- Just mgr <- getSystemEventManager- m <- newEmptyMVar- reg <- registerTimeout mgr usecs (putMVar m ())- takeMVar m `onException` M.unregisterTimeout mgr reg---- | Set the value of returned TVar to True after a given number of--- microseconds. The caveats associated with threadDelay also apply.----registerDelay :: Int -> IO (TVar Bool)-registerDelay usecs = do- t <- atomically $ newTVar False- Just mgr <- getSystemEventManager- _ <- registerTimeout mgr usecs . atomically $ writeTVar t True- return t---- | Block the current thread until data is available to read from the--- given file descriptor.------ This will throw an 'IOError' if the file descriptor was closed--- while this thread was blocked. To safely close a file descriptor--- that has been used with 'threadWaitRead', use 'closeFdWith'.-threadWaitRead :: Fd -> IO ()-threadWaitRead = threadWait evtRead-{-# INLINE threadWaitRead #-}---- | Block the current thread until the given file descriptor can--- accept data to write.------ This will throw an 'IOError' if the file descriptor was closed--- while this thread was blocked. To safely close a file descriptor--- that has been used with 'threadWaitWrite', use 'closeFdWith'.-threadWaitWrite :: Fd -> IO ()-threadWaitWrite = threadWait evtWrite-{-# INLINE threadWaitWrite #-}---- | Close a file descriptor in a concurrency-safe way.------ Any threads that are blocked on the file descriptor via--- 'threadWaitRead' or 'threadWaitWrite' will be unblocked by having--- IO exceptions thrown.-closeFdWith :: (Fd -> IO ()) -- ^ Action that performs the close.- -> Fd -- ^ File descriptor to close.- -> IO ()-closeFdWith close fd = do- Just mgr <- getSystemEventManager- M.closeFd mgr close fd--threadWait :: Event -> Fd -> IO ()-threadWait evt fd = mask_ $ do- m <- newEmptyMVar- Just mgr <- getSystemEventManager- reg <- registerFd mgr (\reg e -> unregisterFd_ mgr reg >> putMVar m e) fd evt- evt' <- takeMVar m `onException` unregisterFd_ mgr reg- if evt' `eventIs` evtClose- then ioError $ errnoToIOError "threadWait" eBADF Nothing Nothing- else return ()---- | Retrieve the system event manager.------ This function always returns 'Just' the system event manager when using the--- threaded RTS and 'Nothing' otherwise.-getSystemEventManager :: IO (Maybe EventManager)-getSystemEventManager = readIORef eventManager--foreign import ccall unsafe "getOrSetSystemEventThreadEventManagerStore"- getOrSetSystemEventThreadEventManagerStore :: Ptr a -> IO (Ptr a)--eventManager :: IORef (Maybe EventManager)-eventManager = unsafePerformIO $ do- em <- newIORef Nothing- sharedCAF em getOrSetSystemEventThreadEventManagerStore-{-# NOINLINE eventManager #-}--foreign import ccall unsafe "getOrSetSystemEventThreadIOManagerThreadStore"- getOrSetSystemEventThreadIOManagerThreadStore :: Ptr a -> IO (Ptr a)--{-# NOINLINE ioManager #-}-ioManager :: MVar (Maybe ThreadId)-ioManager = unsafePerformIO $ do- m <- newMVar Nothing- sharedCAF m getOrSetSystemEventThreadIOManagerThreadStore--ensureIOManagerIsRunning :: IO ()-ensureIOManagerIsRunning- | not threaded = return ()- | otherwise = modifyMVar_ ioManager $ \old -> do- let create = do- !mgr <- new- writeIORef eventManager $ Just mgr- !t <- forkIO $ loop mgr- labelThread t "IOManager"- return $ Just t- case old of- Nothing -> create- st@(Just t) -> do- s <- threadStatus t- case s of- ThreadFinished -> create- ThreadDied -> do - -- Sanity check: if the thread has died, there is a chance- -- that event manager is still alive. This could happend during- -- the fork, for example. In this case we should clean up- -- open pipes and everything else related to the event manager.- -- See #4449- mem <- readIORef eventManager- _ <- case mem of- Nothing -> return ()- Just em -> M.cleanup em- create- _other -> return st--foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool
@@ -1,42 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving, NoImplicitPrelude #-}-module GHC.Event.Unique- (- UniqueSource- , Unique(..)- , newSource- , newUnique- ) where--import Data.Int (Int64)-import GHC.Base-import GHC.Conc.Sync (TVar, atomically, newTVarIO, readTVar, writeTVar)-import GHC.Num (Num(..))-import GHC.Show (Show(..))---- We used to use IORefs here, but Simon switched us to STM when we--- found that our use of atomicModifyIORef was subject to a severe RTS--- performance problem when used in a tight loop from multiple--- threads: http://hackage.haskell.org/trac/ghc/ticket/3838------ There seems to be no performance cost to using a TVar instead.--newtype UniqueSource = US (TVar Int64)--newtype Unique = Unique { asInt64 :: Int64 }- deriving (Eq, Ord, Num)--instance Show Unique where- show = show . asInt64--newSource :: IO UniqueSource-newSource = US `fmap` newTVarIO 0--newUnique :: UniqueSource -> IO Unique-newUnique (US ref) = atomically $ do- u <- readTVar ref- let !u' = u+1- writeTVar ref u'- return $ Unique u'-{-# INLINE newUnique #-}-
@@ -1,196 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude- , ExistentialQuantification- , MagicHash- , DeriveDataTypeable- #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Exception--- Copyright : (c) The University of Glasgow, 1998-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Exceptions and exception-handling functions.--- ---------------------------------------------------------------------------------- #hide-module GHC.Exception where--import Data.Maybe-import {-# SOURCE #-} Data.Typeable (Typeable, cast)- -- loop: Data.Typeable -> GHC.Err -> GHC.Exception-import GHC.Base-import GHC.Show-\end{code}--%*********************************************************-%* *-\subsection{Exceptions}-%* *-%*********************************************************--\begin{code}-{- |-The @SomeException@ type is the root of the exception type hierarchy.-When an exception of type @e@ is thrown, behind the scenes it is-encapsulated in a @SomeException@.--}-data SomeException = forall e . Exception e => SomeException e- deriving Typeable--instance Show SomeException where- showsPrec p (SomeException e) = showsPrec p e--{- |-Any type that you wish to throw or catch as an exception must be an-instance of the @Exception@ class. The simplest case is a new exception-type directly below the root:--> data MyException = ThisException | ThatException-> deriving (Show, Typeable)->-> instance Exception MyException--The default method definitions in the @Exception@ class do what we need-in this case. You can now throw and catch @ThisException@ and-@ThatException@ as exceptions:--@-*Main> throw ThisException \`catch\` \\e -> putStrLn (\"Caught \" ++ show (e :: MyException))-Caught ThisException-@--In more complicated examples, you may wish to define a whole hierarchy-of exceptions:--> ----------------------------------------------------------------------> -- Make the root exception type for all the exceptions in a compiler->-> data SomeCompilerException = forall e . Exception e => SomeCompilerException e-> deriving Typeable->-> instance Show SomeCompilerException where-> show (SomeCompilerException e) = show e->-> instance Exception SomeCompilerException->-> compilerExceptionToException :: Exception e => e -> SomeException-> compilerExceptionToException = toException . SomeCompilerException->-> compilerExceptionFromException :: Exception e => SomeException -> Maybe e-> compilerExceptionFromException x = do-> SomeCompilerException a <- fromException x-> cast a->-> ----------------------------------------------------------------------> -- Make a subhierarchy for exceptions in the frontend of the compiler->-> data SomeFrontendException = forall e . Exception e => SomeFrontendException e-> deriving Typeable->-> instance Show SomeFrontendException where-> show (SomeFrontendException e) = show e->-> instance Exception SomeFrontendException where-> toException = compilerExceptionToException-> fromException = compilerExceptionFromException->-> frontendExceptionToException :: Exception e => e -> SomeException-> frontendExceptionToException = toException . SomeFrontendException->-> frontendExceptionFromException :: Exception e => SomeException -> Maybe e-> frontendExceptionFromException x = do-> SomeFrontendException a <- fromException x-> cast a->-> ----------------------------------------------------------------------> -- Make an exception type for a particular frontend compiler exception->-> data MismatchedParentheses = MismatchedParentheses-> deriving (Typeable, Show)->-> instance Exception MismatchedParentheses where-> toException = frontendExceptionToException-> fromException = frontendExceptionFromException--We can now catch a @MismatchedParentheses@ exception as-@MismatchedParentheses@, @SomeFrontendException@ or-@SomeCompilerException@, but not other types, e.g. @IOException@:--@-*Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: MismatchedParentheses))-Caught MismatchedParentheses-*Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeFrontendException))-Caught MismatchedParentheses-*Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeCompilerException))-Caught MismatchedParentheses-*Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: IOException))-*** Exception: MismatchedParentheses-@---}-class (Typeable e, Show e) => Exception e where- toException :: e -> SomeException- fromException :: SomeException -> Maybe e-- toException = SomeException- fromException (SomeException e) = cast e--instance Exception SomeException where- toException se = se- fromException = Just-\end{code}--%*********************************************************-%* *-\subsection{Primitive throw}-%* *-%*********************************************************--\begin{code}--- | Throw an exception. Exceptions may be thrown from purely--- functional code, but may only be caught within the 'IO' monad.-throw :: Exception e => e -> a-throw e = raise# (toException e)-\end{code}--\begin{code}--- |This is thrown when the user calls 'error'. The @String@ is the--- argument given to 'error'.-data ErrorCall = ErrorCall String- deriving Typeable--instance Exception ErrorCall--instance Show ErrorCall where- showsPrec _ (ErrorCall err) = showString err----------- |Arithmetic exceptions.-data ArithException- = Overflow- | Underflow- | LossOfPrecision- | DivideByZero- | Denormal- deriving (Eq, Ord, Typeable)--instance Exception ArithException--instance Show ArithException where- showsPrec _ Overflow = showString "arithmetic overflow"- showsPrec _ Underflow = showString "arithmetic underflow"- showsPrec _ LossOfPrecision = showString "loss of precision"- showsPrec _ DivideByZero = showString "divide by zero"- showsPrec _ Denormal = showString "denormal"--\end{code}
@@ -1,141 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE MagicHash, UnboxedTuples, DeriveDataTypeable #-}---------------------------------------------------------------------------------- |--- Module : GHC.Exts--- Copyright : (c) The University of Glasgow 2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ GHC Extensions: this is the Approved Way to get at GHC-specific extensions.-----------------------------------------------------------------------------------module GHC.Exts- (- -- * Representations of some basic types- Int(..),Word(..),Float(..),Double(..),- Char(..),- Ptr(..), FunPtr(..),-- -- * The maximum tuple size- maxTupleSize,-- -- * Primitive operations- module GHC.Prim,- shiftL#, shiftRL#, iShiftL#, iShiftRA#, iShiftRL#,- uncheckedShiftL64#, uncheckedShiftRL64#,- uncheckedIShiftL64#, uncheckedIShiftRA64#,-- -- * Fusion- build, augment,-- -- * Overloaded string literals- IsString(..),-- -- * Debugging- breakpoint, breakpointCond,-- -- * Ids with special behaviour- lazy, inline,-- -- * Transform comprehensions- Down(..), groupWith, sortWith, the,-- -- * Event logging- traceEvent,-- -- * SpecConstr annotations- SpecConstrAnnotation(..),-- -- * The call stack- currentCallStack,-- -- * The Constraint kind- Constraint- ) where--import Prelude--import GHC.Prim-import GHC.Base-import GHC.Magic-import GHC.Word-import GHC.Int-import GHC.Ptr-import GHC.Stack-import Data.String-import Data.List-import Data.Data-import qualified Debug.Trace---- XXX This should really be in Data.Tuple, where the definitions are-maxTupleSize :: Int-maxTupleSize = 62---- | The 'Down' type allows you to reverse sort order conveniently. A value of type--- @'Down' a@ contains a value of type @a@ (represented as @'Down' a@).--- If @a@ has an @'Ord'@ instance associated with it then comparing two--- values thus wrapped will give you the opposite of their normal sort order.--- This is particularly useful when sorting in generalised list comprehensions,--- as in: @then sortWith by 'Down' x@-newtype Down a = Down a deriving (Eq)--instance Ord a => Ord (Down a) where- compare (Down x) (Down y) = y `compare` x---- | 'the' ensures that all the elements of the list are identical--- and then returns that unique element-the :: Eq a => [a] -> a-the (x:xs)- | all (x ==) xs = x- | otherwise = error "GHC.Exts.the: non-identical elements"-the [] = error "GHC.Exts.the: empty list"---- | The 'sortWith' function sorts a list of elements using the--- user supplied function to project something out of each element-sortWith :: Ord b => (a -> b) -> [a] -> [a]-sortWith f = sortBy (\x y -> compare (f x) (f y))---- | The 'groupWith' function uses the user supplied function which--- projects an element out of every list element in order to to first sort the --- input list and then to form groups by equality on these projected elements-{-# INLINE groupWith #-}-groupWith :: Ord b => (a -> b) -> [a] -> [[a]]-groupWith f xs = build (\c n -> groupByFB c n (\x y -> f x == f y) (sortWith f xs))--groupByFB :: ([a] -> lst -> lst) -> lst -> (a -> a -> Bool) -> [a] -> lst-groupByFB c n eq xs0 = groupByFBCore xs0- where groupByFBCore [] = n- groupByFBCore (x:xs) = c (x:ys) (groupByFBCore zs)- where (ys, zs) = span (eq x) xs----- -------------------------------------------------------------------------------- tracing--traceEvent :: String -> IO ()-traceEvent = Debug.Trace.traceEventIO-{-# DEPRECATED traceEvent "Use Debug.Trace.traceEvent or Debug.Trace.traceEventIO" #-}---{- **********************************************************************-* *-* SpecConstr annotation *-* *-********************************************************************** -}---- Annotating a type with NoSpecConstr will make SpecConstr --- not specialise for arguments of that type.---- This data type is defined here, rather than in the SpecConstr module--- itself, so that importing it doesn't force stupidly linking the--- entire ghc package at runtime--data SpecConstrAnnotation = NoSpecConstr | ForceSpecConstr- deriving( Data, Typeable, Eq )-
@@ -1,78 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude- , BangPatterns- , ForeignFunctionInterface- , EmptyDataDecls- #-}---- ------------------------------------------------------------------------------- --- (c) The University of Glasgow 2006------ Fingerprints for recompilation checking and ABI versioning, and--- implementing fast comparison of Typeable.------ ------------------------------------------------------------------------------module GHC.Fingerprint (- Fingerprint(..), fingerprint0, - fingerprintData,- fingerprintString,- fingerprintFingerprints- ) where--import GHC.IO-import GHC.Base-import GHC.Num-import GHC.List-import GHC.Real-import Foreign-import Foreign.C--import GHC.Fingerprint.Type---- for SIZEOF_STRUCT_MD5CONTEXT:-#include "HsBaseConfig.h"---- XXX instance Storable Fingerprint--- defined in Foreign.Storable to avoid orphan instance--fingerprint0 :: Fingerprint-fingerprint0 = Fingerprint 0 0--fingerprintFingerprints :: [Fingerprint] -> Fingerprint-fingerprintFingerprints fs = unsafeDupablePerformIO $- withArrayLen fs $ \len p -> do- fingerprintData (castPtr p) (len * sizeOf (head fs))--fingerprintData :: Ptr Word8 -> Int -> IO Fingerprint-fingerprintData buf len = do- allocaBytes SIZEOF_STRUCT_MD5CONTEXT $ \pctxt -> do- c_MD5Init pctxt- c_MD5Update pctxt buf (fromIntegral len)- allocaBytes 16 $ \pdigest -> do- c_MD5Final pdigest pctxt- peek (castPtr pdigest :: Ptr Fingerprint)---- This is duplicated in compiler/utils/Fingerprint.hsc-fingerprintString :: String -> Fingerprint-fingerprintString str = unsafeDupablePerformIO $- withArrayLen word8s $ \len p ->- fingerprintData p len- where word8s = concatMap f str- f c = let w32 :: Word32- w32 = fromIntegral (ord c)- in [fromIntegral (w32 `shiftR` 24),- fromIntegral (w32 `shiftR` 16),- fromIntegral (w32 `shiftR` 8),- fromIntegral w32]--data MD5Context--foreign import ccall unsafe "MD5Init"- c_MD5Init :: Ptr MD5Context -> IO ()-foreign import ccall unsafe "MD5Update"- c_MD5Update :: Ptr MD5Context -> Ptr Word8 -> CInt -> IO ()-foreign import ccall unsafe "MD5Final"- c_MD5Final :: Ptr Word8 -> Ptr MD5Context -> IO ()-
@@ -1,13 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude #-}-module GHC.Fingerprint (- fingerprintString,- fingerprintFingerprints- ) where--import GHC.Base-import GHC.Fingerprint.Type--fingerprintFingerprints :: [Fingerprint] -> Fingerprint-fingerprintString :: String -> Fingerprint-
@@ -1,21 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--- ------------------------------------------------------------------------------- --- (c) The University of Glasgow 2006------ Fingerprints for recompilation checking and ABI versioning, and--- implementing fast comparison of Typeable.------ ------------------------------------------------------------------------------module GHC.Fingerprint.Type (Fingerprint(..)) where--import GHC.Base-import GHC.Word---- Using 128-bit MD5 fingerprints for now.--data Fingerprint = Fingerprint {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64- deriving (Eq, Ord)-
@@ -1,1173 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , MagicHash- , UnboxedTuples- , ForeignFunctionInterface- #-}--- We believe we could deorphan this module, by moving lots of things--- around, but we haven't got there yet:-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Float--- Copyright : (c) The University of Glasgow 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The types 'Float' and 'Double', and the classes 'Floating' and 'RealFloat'.-----------------------------------------------------------------------------------#include "ieee-flpt.h"---- #hide-module GHC.Float( module GHC.Float, Float(..), Double(..), Float#, Double#- , double2Int, int2Double, float2Int, int2Float )- where--import Data.Maybe--import Data.Bits-import GHC.Base-import GHC.List-import GHC.Enum-import GHC.Show-import GHC.Num-import GHC.Real-import GHC.Arr-import GHC.Float.RealFracMethods-import GHC.Float.ConversionUtils-import GHC.Integer.Logarithms ( integerLogBase# )-import GHC.Integer.Logarithms.Internals--infixr 8 **-\end{code}--%*********************************************************-%* *-\subsection{Standard numeric classes}-%* *-%*********************************************************--\begin{code}--- | Trigonometric and hyperbolic functions and related functions.------ Minimal complete definition:--- 'pi', 'exp', 'log', 'sin', 'cos', 'sinh', 'cosh',--- 'asin', 'acos', 'atan', 'asinh', 'acosh' and 'atanh'-class (Fractional a) => Floating a where- pi :: a- exp, log, sqrt :: a -> a- (**), logBase :: a -> a -> a- sin, cos, tan :: a -> a- asin, acos, atan :: a -> a- sinh, cosh, tanh :: a -> a- asinh, acosh, atanh :: a -> a-- {-# INLINE (**) #-}- {-# INLINE logBase #-}- {-# INLINE sqrt #-}- {-# INLINE tan #-}- {-# INLINE tanh #-}- x ** y = exp (log x * y)- logBase x y = log y / log x- sqrt x = x ** 0.5- tan x = sin x / cos x- tanh x = sinh x / cosh x---- | Efficient, machine-independent access to the components of a--- floating-point number.------ Minimal complete definition:--- all except 'exponent', 'significand', 'scaleFloat' and 'atan2'-class (RealFrac a, Floating a) => RealFloat a where- -- | a constant function, returning the radix of the representation- -- (often @2@)- floatRadix :: a -> Integer- -- | a constant function, returning the number of digits of- -- 'floatRadix' in the significand- floatDigits :: a -> Int- -- | a constant function, returning the lowest and highest values- -- the exponent may assume- floatRange :: a -> (Int,Int)- -- | The function 'decodeFloat' applied to a real floating-point- -- number returns the significand expressed as an 'Integer' and an- -- appropriately scaled exponent (an 'Int'). If @'decodeFloat' x@- -- yields @(m,n)@, then @x@ is equal in value to @m*b^^n@, where @b@- -- is the floating-point radix, and furthermore, either @m@ and @n@- -- are both zero or else @b^(d-1) <= 'abs' m < b^d@, where @d@ is- -- the value of @'floatDigits' x@.- -- In particular, @'decodeFloat' 0 = (0,0)@. If the type- -- contains a negative zero, also @'decodeFloat' (-0.0) = (0,0)@.- -- /The result of/ @'decodeFloat' x@ /is unspecified if either of/- -- @'isNaN' x@ /or/ @'isInfinite' x@ /is/ 'True'.- decodeFloat :: a -> (Integer,Int)- -- | 'encodeFloat' performs the inverse of 'decodeFloat' in the- -- sense that for finite @x@ with the exception of @-0.0@,- -- @'uncurry' 'encodeFloat' ('decodeFloat' x) = x@.- -- @'encodeFloat' m n@ is one of the two closest representable- -- floating-point numbers to @m*b^^n@ (or @±Infinity@ if overflow- -- occurs); usually the closer, but if @m@ contains too many bits,- -- the result may be rounded in the wrong direction.- encodeFloat :: Integer -> Int -> a- -- | 'exponent' corresponds to the second component of 'decodeFloat'.- -- @'exponent' 0 = 0@ and for finite nonzero @x@,- -- @'exponent' x = snd ('decodeFloat' x) + 'floatDigits' x@.- -- If @x@ is a finite floating-point number, it is equal in value to- -- @'significand' x * b ^^ 'exponent' x@, where @b@ is the- -- floating-point radix.- -- The behaviour is unspecified on infinite or @NaN@ values.- exponent :: a -> Int- -- | The first component of 'decodeFloat', scaled to lie in the open- -- interval (@-1@,@1@), either @0.0@ or of absolute value @>= 1\/b@,- -- where @b@ is the floating-point radix.- -- The behaviour is unspecified on infinite or @NaN@ values.- significand :: a -> a- -- | multiplies a floating-point number by an integer power of the radix- scaleFloat :: Int -> a -> a- -- | 'True' if the argument is an IEEE \"not-a-number\" (NaN) value- isNaN :: a -> Bool- -- | 'True' if the argument is an IEEE infinity or negative infinity- isInfinite :: a -> Bool- -- | 'True' if the argument is too small to be represented in- -- normalized format- isDenormalized :: a -> Bool- -- | 'True' if the argument is an IEEE negative zero- isNegativeZero :: a -> Bool- -- | 'True' if the argument is an IEEE floating point number- isIEEE :: a -> Bool- -- | a version of arctangent taking two real floating-point arguments.- -- For real floating @x@ and @y@, @'atan2' y x@ computes the angle- -- (from the positive x-axis) of the vector from the origin to the- -- point @(x,y)@. @'atan2' y x@ returns a value in the range [@-pi@,- -- @pi@]. It follows the Common Lisp semantics for the origin when- -- signed zeroes are supported. @'atan2' y 1@, with @y@ in a type- -- that is 'RealFloat', should return the same value as @'atan' y@.- -- A default definition of 'atan2' is provided, but implementors- -- can provide a more accurate implementation.- atan2 :: a -> a -> a--- exponent x = if m == 0 then 0 else n + floatDigits x- where (m,n) = decodeFloat x-- significand x = encodeFloat m (negate (floatDigits x))- where (m,_) = decodeFloat x-- scaleFloat 0 x = x- scaleFloat k x- | isFix = x- | otherwise = encodeFloat m (n + clamp b k)- where (m,n) = decodeFloat x- (l,h) = floatRange x- d = floatDigits x- b = h - l + 4*d- -- n+k may overflow, which would lead- -- to wrong results, hence we clamp the- -- scaling parameter.- -- If n + k would be larger than h,- -- n + clamp b k must be too, simliar- -- for smaller than l - d.- -- Add a little extra to keep clear- -- from the boundary cases.- isFix = x == 0 || isNaN x || isInfinite x-- atan2 y x- | x > 0 = atan (y/x)- | x == 0 && y > 0 = pi/2- | x < 0 && y > 0 = pi + atan (y/x)- |(x <= 0 && y < 0) ||- (x < 0 && isNegativeZero y) ||- (isNegativeZero x && isNegativeZero y)- = -atan2 (-y) x- | y == 0 && (x < 0 || isNegativeZero x)- = pi -- must be after the previous test on zero y- | x==0 && y==0 = y -- must be after the other double zero tests- | otherwise = x + y -- x or y is a NaN, return a NaN (via +)-\end{code}---%*********************************************************-%* *-\subsection{Type @Float@}-%* *-%*********************************************************--\begin{code}-instance Num Float where- (+) x y = plusFloat x y- (-) x y = minusFloat x y- negate x = negateFloat x- (*) x y = timesFloat x y- abs x | x >= 0.0 = x- | otherwise = negateFloat x- signum x | x == 0.0 = 0- | x > 0.0 = 1- | otherwise = negate 1-- {-# INLINE fromInteger #-}- fromInteger i = F# (floatFromInteger i)--instance Real Float where- toRational (F# x#) =- case decodeFloat_Int# x# of- (# m#, e# #)- | e# >=# 0# ->- (smallInteger m# `shiftLInteger` e#) :% 1- | (int2Word# m# `and#` 1##) `eqWord#` 0## ->- case elimZerosInt# m# (negateInt# e#) of- (# n, d# #) -> n :% shiftLInteger 1 d#- | otherwise ->- smallInteger m# :% shiftLInteger 1 (negateInt# e#)--instance Fractional Float where- (/) x y = divideFloat x y- fromRational (n:%0)- | n == 0 = 0/0- | n < 0 = (-1)/0- | otherwise = 1/0- fromRational (n:%d)- | n == 0 = encodeFloat 0 0- | n < 0 = -(fromRat'' minEx mantDigs (-n) d)- | otherwise = fromRat'' minEx mantDigs n d- where- minEx = FLT_MIN_EXP- mantDigs = FLT_MANT_DIG- recip x = 1.0 / x---- RULES for Integer and Int-{-# RULES-"properFraction/Float->Integer" properFraction = properFractionFloatInteger-"truncate/Float->Integer" truncate = truncateFloatInteger-"floor/Float->Integer" floor = floorFloatInteger-"ceiling/Float->Integer" ceiling = ceilingFloatInteger-"round/Float->Integer" round = roundFloatInteger-"properFraction/Float->Int" properFraction = properFractionFloatInt-"truncate/Float->Int" truncate = float2Int-"floor/Float->Int" floor = floorFloatInt-"ceiling/Float->Int" ceiling = ceilingFloatInt-"round/Float->Int" round = roundFloatInt- #-}-instance RealFrac Float where-- -- ceiling, floor, and truncate are all small- {-# INLINE [1] ceiling #-}- {-# INLINE [1] floor #-}- {-# INLINE [1] truncate #-}---- We assume that FLT_RADIX is 2 so that we can use more efficient code-#if FLT_RADIX != 2-#error FLT_RADIX must be 2-#endif- properFraction (F# x#)- = case decodeFloat_Int# x# of- (# m#, n# #) ->- let m = I# m#- n = I# n#- in- if n >= 0- then (fromIntegral m * (2 ^ n), 0.0)- else let i = if m >= 0 then m `shiftR` negate n- else negate (negate m `shiftR` negate n)- f = m - (i `shiftL` negate n)- in (fromIntegral i, encodeFloat (fromIntegral f) n)-- truncate x = case properFraction x of- (n,_) -> n-- round x = case properFraction x of- (n,r) -> let- m = if r < 0.0 then n - 1 else n + 1- half_down = abs r - 0.5- in- case (compare half_down 0.0) of- LT -> n- EQ -> if even n then n else m- GT -> m-- ceiling x = case properFraction x of- (n,r) -> if r > 0.0 then n + 1 else n-- floor x = case properFraction x of- (n,r) -> if r < 0.0 then n - 1 else n--instance Floating Float where- pi = 3.141592653589793238- exp x = expFloat x- log x = logFloat x- sqrt x = sqrtFloat x- sin x = sinFloat x- cos x = cosFloat x- tan x = tanFloat x- asin x = asinFloat x- acos x = acosFloat x- atan x = atanFloat x- sinh x = sinhFloat x- cosh x = coshFloat x- tanh x = tanhFloat x- (**) x y = powerFloat x y- logBase x y = log y / log x-- asinh x = log (x + sqrt (1.0+x*x))- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- atanh x = 0.5 * log ((1.0+x) / (1.0-x))--instance RealFloat Float where- floatRadix _ = FLT_RADIX -- from float.h- floatDigits _ = FLT_MANT_DIG -- ditto- floatRange _ = (FLT_MIN_EXP, FLT_MAX_EXP) -- ditto-- decodeFloat (F# f#) = case decodeFloat_Int# f# of- (# i, e #) -> (smallInteger i, I# e)-- encodeFloat i (I# e) = F# (encodeFloatInteger i e)-- exponent x = case decodeFloat x of- (m,n) -> if m == 0 then 0 else n + floatDigits x-- significand x = case decodeFloat x of- (m,_) -> encodeFloat m (negate (floatDigits x))-- scaleFloat 0 x = x- scaleFloat k x- | isFix = x- | otherwise = case decodeFloat x of- (m,n) -> encodeFloat m (n + clamp bf k)- where bf = FLT_MAX_EXP - (FLT_MIN_EXP) + 4*FLT_MANT_DIG- isFix = x == 0 || isFloatFinite x == 0-- isNaN x = 0 /= isFloatNaN x- isInfinite x = 0 /= isFloatInfinite x- isDenormalized x = 0 /= isFloatDenormalized x- isNegativeZero x = 0 /= isFloatNegativeZero x- isIEEE _ = True--instance Show Float where- showsPrec x = showSignedFloat showFloat x- showList = showList__ (showsPrec 0)-\end{code}--%*********************************************************-%* *-\subsection{Type @Double@}-%* *-%*********************************************************--\begin{code}-instance Num Double where- (+) x y = plusDouble x y- (-) x y = minusDouble x y- negate x = negateDouble x- (*) x y = timesDouble x y- abs x | x >= 0.0 = x- | otherwise = negateDouble x- signum x | x == 0.0 = 0- | x > 0.0 = 1- | otherwise = negate 1-- {-# INLINE fromInteger #-}- fromInteger i = D# (doubleFromInteger i)---instance Real Double where- toRational (D# x#) =- case decodeDoubleInteger x# of- (# m, e# #)- | e# >=# 0# ->- shiftLInteger m e# :% 1- | (integerToWord m `and#` 1##) `eqWord#` 0## ->- case elimZerosInteger m (negateInt# e#) of- (# n, d# #) -> n :% shiftLInteger 1 d#- | otherwise ->- m :% shiftLInteger 1 (negateInt# e#)--instance Fractional Double where- (/) x y = divideDouble x y- fromRational (n:%0)- | n == 0 = 0/0- | n < 0 = (-1)/0- | otherwise = 1/0- fromRational (n:%d)- | n == 0 = encodeFloat 0 0- | n < 0 = -(fromRat'' minEx mantDigs (-n) d)- | otherwise = fromRat'' minEx mantDigs n d- where- minEx = DBL_MIN_EXP- mantDigs = DBL_MANT_DIG- recip x = 1.0 / x--instance Floating Double where- pi = 3.141592653589793238- exp x = expDouble x- log x = logDouble x- sqrt x = sqrtDouble x- sin x = sinDouble x- cos x = cosDouble x- tan x = tanDouble x- asin x = asinDouble x- acos x = acosDouble x- atan x = atanDouble x- sinh x = sinhDouble x- cosh x = coshDouble x- tanh x = tanhDouble x- (**) x y = powerDouble x y- logBase x y = log y / log x-- asinh x = log (x + sqrt (1.0+x*x))- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- atanh x = 0.5 * log ((1.0+x) / (1.0-x))---- RULES for Integer and Int-{-# RULES-"properFraction/Double->Integer" properFraction = properFractionDoubleInteger-"truncate/Double->Integer" truncate = truncateDoubleInteger-"floor/Double->Integer" floor = floorDoubleInteger-"ceiling/Double->Integer" ceiling = ceilingDoubleInteger-"round/Double->Integer" round = roundDoubleInteger-"properFraction/Double->Int" properFraction = properFractionDoubleInt-"truncate/Double->Int" truncate = double2Int-"floor/Double->Int" floor = floorDoubleInt-"ceiling/Double->Int" ceiling = ceilingDoubleInt-"round/Double->Int" round = roundDoubleInt- #-}-instance RealFrac Double where-- -- ceiling, floor, and truncate are all small- {-# INLINE [1] ceiling #-}- {-# INLINE [1] floor #-}- {-# INLINE [1] truncate #-}-- properFraction x- = case (decodeFloat x) of { (m,n) ->- if n >= 0 then- (fromInteger m * 2 ^ n, 0.0)- else- case (quotRem m (2^(negate n))) of { (w,r) ->- (fromInteger w, encodeFloat r n)- }- }-- truncate x = case properFraction x of- (n,_) -> n-- round x = case properFraction x of- (n,r) -> let- m = if r < 0.0 then n - 1 else n + 1- half_down = abs r - 0.5- in- case (compare half_down 0.0) of- LT -> n- EQ -> if even n then n else m- GT -> m-- ceiling x = case properFraction x of- (n,r) -> if r > 0.0 then n + 1 else n-- floor x = case properFraction x of- (n,r) -> if r < 0.0 then n - 1 else n--instance RealFloat Double where- floatRadix _ = FLT_RADIX -- from float.h- floatDigits _ = DBL_MANT_DIG -- ditto- floatRange _ = (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto-- decodeFloat (D# x#)- = case decodeDoubleInteger x# of- (# i, j #) -> (i, I# j)-- encodeFloat i (I# j) = D# (encodeDoubleInteger i j)-- exponent x = case decodeFloat x of- (m,n) -> if m == 0 then 0 else n + floatDigits x-- significand x = case decodeFloat x of- (m,_) -> encodeFloat m (negate (floatDigits x))-- scaleFloat 0 x = x- scaleFloat k x- | isFix = x- | otherwise = case decodeFloat x of- (m,n) -> encodeFloat m (n + clamp bd k)- where bd = DBL_MAX_EXP - (DBL_MIN_EXP) + 4*DBL_MANT_DIG- isFix = x == 0 || isDoubleFinite x == 0-- isNaN x = 0 /= isDoubleNaN x- isInfinite x = 0 /= isDoubleInfinite x- isDenormalized x = 0 /= isDoubleDenormalized x- isNegativeZero x = 0 /= isDoubleNegativeZero x- isIEEE _ = True--instance Show Double where- showsPrec x = showSignedFloat showFloat x- showList = showList__ (showsPrec 0)-\end{code}--%*********************************************************-%* *-\subsection{@Enum@ instances}-%* *-%*********************************************************--The @Enum@ instances for Floats and Doubles are slightly unusual.-The @toEnum@ function truncates numbers to Int. The definitions-of @enumFrom@ and @enumFromThen@ allow floats to be used in arithmetic-series: [0,0.1 .. 1.0]. However, roundoff errors make these somewhat-dubious. This example may have either 10 or 11 elements, depending on-how 0.1 is represented.--NOTE: The instances for Float and Double do not make use of the default-methods for @enumFromTo@ and @enumFromThenTo@, as these rely on there being-a `non-lossy' conversion to and from Ints. Instead we make use of the-1.2 default methods (back in the days when Enum had Ord as a superclass)-for these (@numericEnumFromTo@ and @numericEnumFromThenTo@ below.)--\begin{code}-instance Enum Float where- succ x = x + 1- pred x = x - 1- toEnum = int2Float- fromEnum = fromInteger . truncate -- may overflow- enumFrom = numericEnumFrom- enumFromTo = numericEnumFromTo- enumFromThen = numericEnumFromThen- enumFromThenTo = numericEnumFromThenTo--instance Enum Double where- succ x = x + 1- pred x = x - 1- toEnum = int2Double- fromEnum = fromInteger . truncate -- may overflow- enumFrom = numericEnumFrom- enumFromTo = numericEnumFromTo- enumFromThen = numericEnumFromThen- enumFromThenTo = numericEnumFromThenTo-\end{code}---%*********************************************************-%* *-\subsection{Printing floating point}-%* *-%*********************************************************---\begin{code}--- | Show a signed 'RealFloat' value to full precision--- using standard decimal notation for arguments whose absolute value lies--- between @0.1@ and @9,999,999@, and scientific notation otherwise.-showFloat :: (RealFloat a) => a -> ShowS-showFloat x = showString (formatRealFloat FFGeneric Nothing x)---- These are the format types. This type is not exported.--data FFFormat = FFExponent | FFFixed | FFGeneric--formatRealFloat :: (RealFloat a) => FFFormat -> Maybe Int -> a -> String-formatRealFloat fmt decs x- | isNaN x = "NaN"- | isInfinite x = if x < 0 then "-Infinity" else "Infinity"- | x < 0 || isNegativeZero x = '-':doFmt fmt (floatToDigits (toInteger base) (-x))- | otherwise = doFmt fmt (floatToDigits (toInteger base) x)- where- base = 10-- doFmt format (is, e) =- let ds = map intToDigit is in- case format of- FFGeneric ->- doFmt (if e < 0 || e > 7 then FFExponent else FFFixed)- (is,e)- FFExponent ->- case decs of- Nothing ->- let show_e' = show (e-1) in- case ds of- "0" -> "0.0e0"- [d] -> d : ".0e" ++ show_e'- (d:ds') -> d : '.' : ds' ++ "e" ++ show_e'- [] -> error "formatRealFloat/doFmt/FFExponent: []"- Just dec ->- let dec' = max dec 1 in- case is of- [0] -> '0' :'.' : take dec' (repeat '0') ++ "e0"- _ ->- let- (ei,is') = roundTo base (dec'+1) is- (d:ds') = map intToDigit (if ei > 0 then init is' else is')- in- d:'.':ds' ++ 'e':show (e-1+ei)- FFFixed ->- let- mk0 ls = case ls of { "" -> "0" ; _ -> ls}- in- case decs of- Nothing- | e <= 0 -> "0." ++ replicate (-e) '0' ++ ds- | otherwise ->- let- f 0 s rs = mk0 (reverse s) ++ '.':mk0 rs- f n s "" = f (n-1) ('0':s) ""- f n s (r:rs) = f (n-1) (r:s) rs- in- f e "" ds- Just dec ->- let dec' = max dec 0 in- if e >= 0 then- let- (ei,is') = roundTo base (dec' + e) is- (ls,rs) = splitAt (e+ei) (map intToDigit is')- in- mk0 ls ++ (if null rs then "" else '.':rs)- else- let- (ei,is') = roundTo base dec' (replicate (-e) 0 ++ is)- d:ds' = map intToDigit (if ei > 0 then is' else 0:is')- in- d : (if null ds' then "" else '.':ds')---roundTo :: Int -> Int -> [Int] -> (Int,[Int])-roundTo base d is =- case f d is of- x@(0,_) -> x- (1,xs) -> (1, 1:xs)- _ -> error "roundTo: bad Value"- where- b2 = base `div` 2-- f n [] = (0, replicate n 0)- f 0 (x:_) = (if x >= b2 then 1 else 0, [])- f n (i:xs)- | i' == base = (1,0:ds)- | otherwise = (0,i':ds)- where- (c,ds) = f (n-1) xs- i' = c + i---- Based on "Printing Floating-Point Numbers Quickly and Accurately"--- by R.G. Burger and R.K. Dybvig in PLDI 96.--- This version uses a much slower logarithm estimator. It should be improved.---- | 'floatToDigits' takes a base and a non-negative 'RealFloat' number,--- and returns a list of digits and an exponent.--- In particular, if @x>=0@, and------ > floatToDigits base x = ([d1,d2,...,dn], e)------ then------ (1) @n >= 1@------ (2) @x = 0.d1d2...dn * (base**e)@------ (3) @0 <= di <= base-1@--floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int)-floatToDigits _ 0 = ([0], 0)-floatToDigits base x =- let- (f0, e0) = decodeFloat x- (minExp0, _) = floatRange x- p = floatDigits x- b = floatRadix x- minExp = minExp0 - p -- the real minimum exponent- -- Haskell requires that f be adjusted so denormalized numbers- -- will have an impossibly low exponent. Adjust for this.- (f, e) =- let n = minExp - e0 in- if n > 0 then (f0 `quot` (expt b n), e0+n) else (f0, e0)- (r, s, mUp, mDn) =- if e >= 0 then- let be = expt b e in- if f == expt b (p-1) then- (f*be*b*2, 2*b, be*b, be) -- according to Burger and Dybvig- else- (f*be*2, 2, be, be)- else- if e > minExp && f == expt b (p-1) then- (f*b*2, expt b (-e+1)*2, b, 1)- else- (f*2, expt b (-e)*2, 1, 1)- k :: Int- k =- let- k0 :: Int- k0 =- if b == 2 && base == 10 then- -- logBase 10 2 is very slightly larger than 8651/28738- -- (about 5.3558e-10), so if log x >= 0, the approximation- -- k1 is too small, hence we add one and need one fixup step less.- -- If log x < 0, the approximation errs rather on the high side.- -- That is usually more than compensated for by ignoring the- -- fractional part of logBase 2 x, but when x is a power of 1/2- -- or slightly larger and the exponent is a multiple of the- -- denominator of the rational approximation to logBase 10 2,- -- k1 is larger than logBase 10 x. If k1 > 1 + logBase 10 x,- -- we get a leading zero-digit we don't want.- -- With the approximation 3/10, this happened for- -- 0.5^1030, 0.5^1040, ..., 0.5^1070 and values close above.- -- The approximation 8651/28738 guarantees k1 < 1 + logBase 10 x- -- for IEEE-ish floating point types with exponent fields- -- <= 17 bits and mantissae of several thousand bits, earlier- -- convergents to logBase 10 2 would fail for long double.- -- Using quot instead of div is a little faster and requires- -- fewer fixup steps for negative lx.- let lx = p - 1 + e0- k1 = (lx * 8651) `quot` 28738- in if lx >= 0 then k1 + 1 else k1- else- -- f :: Integer, log :: Float -> Float,- -- ceiling :: Float -> Int- ceiling ((log (fromInteger (f+1) :: Float) +- fromIntegral e * log (fromInteger b)) /- log (fromInteger base))---WAS: fromInt e * log (fromInteger b))-- fixup n =- if n >= 0 then- if r + mUp <= expt base n * s then n else fixup (n+1)- else- if expt base (-n) * (r + mUp) <= s then n else fixup (n+1)- in- fixup k0-- gen ds rn sN mUpN mDnN =- let- (dn, rn') = (rn * base) `quotRem` sN- mUpN' = mUpN * base- mDnN' = mDnN * base- in- case (rn' < mDnN', rn' + mUpN' > sN) of- (True, False) -> dn : ds- (False, True) -> dn+1 : ds- (True, True) -> if rn' * 2 < sN then dn : ds else dn+1 : ds- (False, False) -> gen (dn:ds) rn' sN mUpN' mDnN'-- rds =- if k >= 0 then- gen [] r (s * expt base k) mUp mDn- else- let bk = expt base (-k) in- gen [] (r * bk) s (mUp * bk) (mDn * bk)- in- (map fromIntegral (reverse rds), k)--\end{code}---%*********************************************************-%* *-\subsection{Converting from a Rational to a RealFloat-%* *-%*********************************************************--[In response to a request for documentation of how fromRational works,-Joe Fasel writes:] A quite reasonable request! This code was added to-the Prelude just before the 1.2 release, when Lennart, working with an-early version of hbi, noticed that (read . show) was not the identity-for floating-point numbers. (There was a one-bit error about half the-time.) The original version of the conversion function was in fact-simply a floating-point divide, as you suggest above. The new version-is, I grant you, somewhat denser.--Unfortunately, Joe's code doesn't work! Here's an example:--main = putStr (shows (1.82173691287639817263897126389712638972163e-300::Double) "\n")--This program prints- 0.0000000000000000-instead of- 1.8217369128763981e-300--Here's Joe's code:--\begin{pseudocode}-fromRat :: (RealFloat a) => Rational -> a-fromRat x = x'- where x' = f e---- If the exponent of the nearest floating-point number to x--- is e, then the significand is the integer nearest xb^(-e),--- where b is the floating-point radix. We start with a good--- guess for e, and if it is correct, the exponent of the--- floating-point number we construct will again be e. If--- not, one more iteration is needed.-- f e = if e' == e then y else f e'- where y = encodeFloat (round (x * (1 % b)^^e)) e- (_,e') = decodeFloat y- b = floatRadix x'---- We obtain a trial exponent by doing a floating-point--- division of x's numerator by its denominator. The--- result of this division may not itself be the ultimate--- result, because of an accumulation of three rounding--- errors.-- (s,e) = decodeFloat (fromInteger (numerator x) `asTypeOf` x'- / fromInteger (denominator x))-\end{pseudocode}--Now, here's Lennart's code (which works)--\begin{code}--- | Converts a 'Rational' value into any type in class 'RealFloat'.-{-# RULES-"fromRat/Float" fromRat = (fromRational :: Rational -> Float)-"fromRat/Double" fromRat = (fromRational :: Rational -> Double)- #-}-fromRat :: (RealFloat a) => Rational -> a---- Deal with special cases first, delegating the real work to fromRat'-fromRat (n :% 0) | n > 0 = 1/0 -- +Infinity- | n < 0 = -1/0 -- -Infinity- | otherwise = 0/0 -- NaN--fromRat (n :% d) | n > 0 = fromRat' (n :% d)- | n < 0 = - fromRat' ((-n) :% d)- | otherwise = encodeFloat 0 0 -- Zero---- Conversion process:--- Scale the rational number by the RealFloat base until--- it lies in the range of the mantissa (as used by decodeFloat/encodeFloat).--- Then round the rational to an Integer and encode it with the exponent--- that we got from the scaling.--- To speed up the scaling process we compute the log2 of the number to get--- a first guess of the exponent.--fromRat' :: (RealFloat a) => Rational -> a--- Invariant: argument is strictly positive-fromRat' x = r- where b = floatRadix r- p = floatDigits r- (minExp0, _) = floatRange r- minExp = minExp0 - p -- the real minimum exponent- xMax = toRational (expt b p)- p0 = (integerLogBase b (numerator x) - integerLogBase b (denominator x) - p) `max` minExp- -- if x = n/d and ln = integerLogBase b n, ld = integerLogBase b d,- -- then b^(ln-ld-1) < x < b^(ln-ld+1)- f = if p0 < 0 then 1 :% expt b (-p0) else expt b p0 :% 1- x0 = x / f- -- if ln - ld >= minExp0, then b^(p-1) < x0 < b^(p+1), so there's at most- -- one scaling step needed, otherwise, x0 < b^p and no scaling is needed- (x', p') = if x0 >= xMax then (x0 / toRational b, p0+1) else (x0, p0)- r = encodeFloat (round x') p'---- Exponentiation with a cache for the most common numbers.-minExpt, maxExpt :: Int-minExpt = 0-maxExpt = 1100--expt :: Integer -> Int -> Integer-expt base n =- if base == 2 && n >= minExpt && n <= maxExpt then- expts!n- else- if base == 10 && n <= maxExpt10 then- expts10!n- else- base^n--expts :: Array Int Integer-expts = array (minExpt,maxExpt) [(n,2^n) | n <- [minExpt .. maxExpt]]--maxExpt10 :: Int-maxExpt10 = 324--expts10 :: Array Int Integer-expts10 = array (minExpt,maxExpt10) [(n,10^n) | n <- [minExpt .. maxExpt10]]---- Compute the (floor of the) log of i in base b.--- Simplest way would be just divide i by b until it's smaller then b, but that would--- be very slow! We are just slightly more clever, except for base 2, where--- we take advantage of the representation of Integers.--- The general case could be improved by a lookup table for--- approximating the result by integerLog2 i / integerLog2 b.-integerLogBase :: Integer -> Integer -> Int-integerLogBase b i- | i < b = 0- | b == 2 = I# (integerLog2# i)- | otherwise = I# (integerLogBase# b i)--\end{code}--Unfortunately, the old conversion code was awfully slow due to-a) a slow integer logarithm-b) repeated calculation of gcd's--For the case of Rational's coming from a Float or Double via toRational,-we can exploit the fact that the denominator is a power of two, which for-these brings a huge speedup since we need only shift and add instead-of division.--The below is an adaption of fromRat' for the conversion to-Float or Double exploiting the known floatRadix and avoiding-divisions as much as possible.--\begin{code}-{-# SPECIALISE fromRat'' :: Int -> Int -> Integer -> Integer -> Float,- Int -> Int -> Integer -> Integer -> Double #-}-fromRat'' :: RealFloat a => Int -> Int -> Integer -> Integer -> a--- Invariant: n and d strictly positive-fromRat'' minEx@(I# me#) mantDigs@(I# md#) n d =- case integerLog2IsPowerOf2# d of- (# ld#, pw# #)- | pw# ==# 0# ->- case integerLog2# n of- ln# | ln# >=# (ld# +# me# -# 1#) ->- -- this means n/d >= 2^(minEx-1), i.e. we are guaranteed to get- -- a normalised number, round to mantDigs bits- if ln# <# md#- then encodeFloat n (I# (negateInt# ld#))- else let n' = n `shiftR` (I# (ln# +# 1# -# md#))- n'' = case roundingMode# n (ln# -# md#) of- 0# -> n'- 2# -> n' + 1- _ -> case fromInteger n' .&. (1 :: Int) of- 0 -> n'- _ -> n' + 1- in encodeFloat n'' (I# (ln# -# ld# +# 1# -# md#))- | otherwise ->- -- n/d < 2^(minEx-1), a denorm or rounded to 2^(minEx-1)- -- the exponent for encoding is always minEx-mantDigs- -- so we must shift right by (minEx-mantDigs) - (-ld)- case ld# +# (me# -# md#) of- ld'# | ld'# <=# 0# -> -- we would shift left, so we don't shift- encodeFloat n (I# ((me# -# md#) -# ld'#))- | ld'# <=# ln# ->- let n' = n `shiftR` (I# ld'#)- in case roundingMode# n (ld'# -# 1#) of- 0# -> encodeFloat n' (minEx - mantDigs)- 1# -> if fromInteger n' .&. (1 :: Int) == 0- then encodeFloat n' (minEx-mantDigs)- else encodeFloat (n' + 1) (minEx-mantDigs)- _ -> encodeFloat (n' + 1) (minEx-mantDigs)- | ld'# ># (ln# +# 1#) -> encodeFloat 0 0 -- result of shift < 0.5- | otherwise -> -- first bit of n shifted to 0.5 place- case integerLog2IsPowerOf2# n of- (# _, 0# #) -> encodeFloat 0 0 -- round to even- (# _, _ #) -> encodeFloat 1 (minEx - mantDigs)- | otherwise ->- let ln = I# (integerLog2# n)- ld = I# ld#- -- 2^(ln-ld-1) < n/d < 2^(ln-ld+1)- p0 = max minEx (ln - ld)- (n', d')- | p0 < mantDigs = (n `shiftL` (mantDigs - p0), d)- | p0 == mantDigs = (n, d)- | otherwise = (n, d `shiftL` (p0 - mantDigs))- -- if ln-ld < minEx, then n'/d' < 2^mantDigs, else- -- 2^(mantDigs-1) < n'/d' < 2^(mantDigs+1) and we- -- may need one scaling step- scale p a b- | (b `shiftL` mantDigs) <= a = (p+1, a, b `shiftL` 1)- | otherwise = (p, a, b)- (p', n'', d'') = scale (p0-mantDigs) n' d'- -- n''/d'' < 2^mantDigs and p' == minEx-mantDigs or n''/d'' >= 2^(mantDigs-1)- rdq = case n'' `quotRem` d'' of- (q,r) -> case compare (r `shiftL` 1) d'' of- LT -> q- EQ -> if fromInteger q .&. (1 :: Int) == 0- then q else q+1- GT -> q+1- in encodeFloat rdq p'-\end{code}---%*********************************************************-%* *-\subsection{Floating point numeric primops}-%* *-%*********************************************************--Definitions of the boxed PrimOps; these will be-used in the case of partial applications, etc.--\begin{code}-plusFloat, minusFloat, timesFloat, divideFloat :: Float -> Float -> Float-plusFloat (F# x) (F# y) = F# (plusFloat# x y)-minusFloat (F# x) (F# y) = F# (minusFloat# x y)-timesFloat (F# x) (F# y) = F# (timesFloat# x y)-divideFloat (F# x) (F# y) = F# (divideFloat# x y)--negateFloat :: Float -> Float-negateFloat (F# x) = F# (negateFloat# x)--gtFloat, geFloat, eqFloat, neFloat, ltFloat, leFloat :: Float -> Float -> Bool-gtFloat (F# x) (F# y) = gtFloat# x y-geFloat (F# x) (F# y) = geFloat# x y-eqFloat (F# x) (F# y) = eqFloat# x y-neFloat (F# x) (F# y) = neFloat# x y-ltFloat (F# x) (F# y) = ltFloat# x y-leFloat (F# x) (F# y) = leFloat# x y--expFloat, logFloat, sqrtFloat :: Float -> Float-sinFloat, cosFloat, tanFloat :: Float -> Float-asinFloat, acosFloat, atanFloat :: Float -> Float-sinhFloat, coshFloat, tanhFloat :: Float -> Float-expFloat (F# x) = F# (expFloat# x)-logFloat (F# x) = F# (logFloat# x)-sqrtFloat (F# x) = F# (sqrtFloat# x)-sinFloat (F# x) = F# (sinFloat# x)-cosFloat (F# x) = F# (cosFloat# x)-tanFloat (F# x) = F# (tanFloat# x)-asinFloat (F# x) = F# (asinFloat# x)-acosFloat (F# x) = F# (acosFloat# x)-atanFloat (F# x) = F# (atanFloat# x)-sinhFloat (F# x) = F# (sinhFloat# x)-coshFloat (F# x) = F# (coshFloat# x)-tanhFloat (F# x) = F# (tanhFloat# x)--powerFloat :: Float -> Float -> Float-powerFloat (F# x) (F# y) = F# (powerFloat# x y)---- definitions of the boxed PrimOps; these will be--- used in the case of partial applications, etc.--plusDouble, minusDouble, timesDouble, divideDouble :: Double -> Double -> Double-plusDouble (D# x) (D# y) = D# (x +## y)-minusDouble (D# x) (D# y) = D# (x -## y)-timesDouble (D# x) (D# y) = D# (x *## y)-divideDouble (D# x) (D# y) = D# (x /## y)--negateDouble :: Double -> Double-negateDouble (D# x) = D# (negateDouble# x)--gtDouble, geDouble, eqDouble, neDouble, leDouble, ltDouble :: Double -> Double -> Bool-gtDouble (D# x) (D# y) = x >## y-geDouble (D# x) (D# y) = x >=## y-eqDouble (D# x) (D# y) = x ==## y-neDouble (D# x) (D# y) = x /=## y-ltDouble (D# x) (D# y) = x <## y-leDouble (D# x) (D# y) = x <=## y--double2Float :: Double -> Float-double2Float (D# x) = F# (double2Float# x)--float2Double :: Float -> Double-float2Double (F# x) = D# (float2Double# x)--expDouble, logDouble, sqrtDouble :: Double -> Double-sinDouble, cosDouble, tanDouble :: Double -> Double-asinDouble, acosDouble, atanDouble :: Double -> Double-sinhDouble, coshDouble, tanhDouble :: Double -> Double-expDouble (D# x) = D# (expDouble# x)-logDouble (D# x) = D# (logDouble# x)-sqrtDouble (D# x) = D# (sqrtDouble# x)-sinDouble (D# x) = D# (sinDouble# x)-cosDouble (D# x) = D# (cosDouble# x)-tanDouble (D# x) = D# (tanDouble# x)-asinDouble (D# x) = D# (asinDouble# x)-acosDouble (D# x) = D# (acosDouble# x)-atanDouble (D# x) = D# (atanDouble# x)-sinhDouble (D# x) = D# (sinhDouble# x)-coshDouble (D# x) = D# (coshDouble# x)-tanhDouble (D# x) = D# (tanhDouble# x)--powerDouble :: Double -> Double -> Double-powerDouble (D# x) (D# y) = D# (x **## y)-\end{code}--\begin{code}-foreign import ccall unsafe "isFloatNaN" isFloatNaN :: Float -> Int-foreign import ccall unsafe "isFloatInfinite" isFloatInfinite :: Float -> Int-foreign import ccall unsafe "isFloatDenormalized" isFloatDenormalized :: Float -> Int-foreign import ccall unsafe "isFloatNegativeZero" isFloatNegativeZero :: Float -> Int-foreign import ccall unsafe "isFloatFinite" isFloatFinite :: Float -> Int--foreign import ccall unsafe "isDoubleNaN" isDoubleNaN :: Double -> Int-foreign import ccall unsafe "isDoubleInfinite" isDoubleInfinite :: Double -> Int-foreign import ccall unsafe "isDoubleDenormalized" isDoubleDenormalized :: Double -> Int-foreign import ccall unsafe "isDoubleNegativeZero" isDoubleNegativeZero :: Double -> Int-foreign import ccall unsafe "isDoubleFinite" isDoubleFinite :: Double -> Int-\end{code}--%*********************************************************-%* *-\subsection{Coercion rules}-%* *-%*********************************************************--\begin{code}-{-# RULES-"fromIntegral/Int->Float" fromIntegral = int2Float-"fromIntegral/Int->Double" fromIntegral = int2Double-"realToFrac/Float->Float" realToFrac = id :: Float -> Float-"realToFrac/Float->Double" realToFrac = float2Double-"realToFrac/Double->Float" realToFrac = double2Float-"realToFrac/Double->Double" realToFrac = id :: Double -> Double-"realToFrac/Int->Double" realToFrac = int2Double -- See Note [realToFrac int-to-float]-"realToFrac/Int->Float" realToFrac = int2Float -- ..ditto- #-}-\end{code}--Note [realToFrac int-to-float]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Don found that the RULES for realToFrac/Int->Double and simliarly-Float made a huge difference to some stream-fusion programs. Here's-an example-- import Data.Array.Vector-- n = 40000000-- main = do- let c = replicateU n (2::Double)- a = mapU realToFrac (enumFromToU 0 (n-1) ) :: UArr Double- print (sumU (zipWithU (*) c a))--Without the RULE we get this loop body:-- case $wtoRational sc_sY4 of ww_aM7 { (# ww1_aM9, ww2_aMa #) ->- case $wfromRat ww1_aM9 ww2_aMa of tpl_X1P { D# ipv_sW3 ->- Main.$s$wfold- (+# sc_sY4 1)- (+# wild_X1i 1)- (+## sc2_sY6 (*## 2.0 ipv_sW3))--And with the rule:-- Main.$s$wfold- (+# sc_sXT 1)- (+# wild_X1h 1)- (+## sc2_sXV (*## 2.0 (int2Double# sc_sXT)))--The running time of the program goes from 120 seconds to 0.198 seconds-with the native backend, and 0.143 seconds with the C backend.--A few more details in Trac #2251, and the patch message-"Add RULES for realToFrac from Int".--%*********************************************************-%* *-\subsection{Utils}-%* *-%*********************************************************--\begin{code}-showSignedFloat :: (RealFloat a)- => (a -> ShowS) -- ^ a function that can show unsigned values- -> Int -- ^ the precedence of the enclosing context- -> a -- ^ the value to show- -> ShowS-showSignedFloat showPos p x- | x < 0 || isNegativeZero x- = showParen (p > 6) (showChar '-' . showPos (-x))- | otherwise = showPos x-\end{code}--We need to prevent over/underflow of the exponent in encodeFloat when-called from scaleFloat, hence we clamp the scaling parameter.-We must have a large enough range to cover the maximum difference of-exponents returned by decodeFloat.-\begin{code}-clamp :: Int -> Int -> Int-clamp bd k = max (-bd) (min bd k)-\end{code}
@@ -1,99 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-}-{-# OPTIONS_GHC -O2 #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Float.ConversionUtils--- Copyright : (c) Daniel Fischer 2010--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Utilities for conversion between Double/Float and Rational-----------------------------------------------------------------------------------#include "MachDeps.h"---- #hide-module GHC.Float.ConversionUtils ( elimZerosInteger, elimZerosInt# ) where--import GHC.Base-import GHC.Integer-#if WORD_SIZE_IN_BITS < 64-import GHC.IntWord64-#endif--default ()--#if WORD_SIZE_IN_BITS < 64--#define TO64 integerToInt64--toByte64# :: Int64# -> Int#-toByte64# i = word2Int# (and# 255## (int2Word# (int64ToInt# i)))---- Double mantissae have 53 bits, too much for Int#-elim64# :: Int64# -> Int# -> (# Integer, Int# #)-elim64# n e =- case zeroCount (toByte64# n) of- t | e <=# t -> (# int64ToInteger (uncheckedIShiftRA64# n e), 0# #)- | t <# 8# -> (# int64ToInteger (uncheckedIShiftRA64# n t), e -# t #)- | otherwise -> elim64# (uncheckedIShiftRA64# n 8#) (e -# 8#)--#else--#define TO64 integerToInt---- Double mantissae fit it Int#-elim64# :: Int# -> Int# -> (# Integer, Int# #)-elim64# = elimZerosInt#--#endif--{-# INLINE elimZerosInteger #-}-elimZerosInteger :: Integer -> Int# -> (# Integer, Int# #)-elimZerosInteger m e = elim64# (TO64 m) e--elimZerosInt# :: Int# -> Int# -> (# Integer, Int# #)-elimZerosInt# n e =- case zeroCount (toByte# n) of- t | e <=# t -> (# smallInteger (uncheckedIShiftRA# n e), 0# #)- | t <# 8# -> (# smallInteger (uncheckedIShiftRA# n t), e -# t #)- | otherwise -> elimZerosInt# (uncheckedIShiftRA# n 8#) (e -# 8#)--{-# INLINE zeroCount #-}-zeroCount :: Int# -> Int#-zeroCount i =- case zeroCountArr of- BA ba -> indexInt8Array# ba i--toByte# :: Int# -> Int#-toByte# i = word2Int# (and# 255## (int2Word# i))---data BA = BA ByteArray#---- Number of trailing zero bits in a byte-zeroCountArr :: BA-zeroCountArr =- let mkArr s =- case newByteArray# 256# s of- (# s1, mba #) ->- case writeInt8Array# mba 0# 8# s1 of- s2 ->- let fillA step val idx st- | idx <# 256# = case writeInt8Array# mba idx val st of- nx -> fillA step val (idx +# step) nx- | step <# 256# = fillA (2# *# step) (val +# 1#) step st- | otherwise = st- in case fillA 2# 0# 1# s2 of- s3 -> case unsafeFreezeByteArray# mba s3 of- (# _, ba #) -> ba- in case mkArr realWorld# of- b -> BA b-
@@ -1,344 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, MagicHash, UnboxedTuples, ForeignFunctionInterface,- NoImplicitPrelude #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Float.RealFracMethods--- Copyright : (c) Daniel Fischer 2010--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Methods for the RealFrac instances for 'Float' and 'Double',--- with specialised versions for 'Int'.------ Moved to their own module to not bloat GHC.Float further.-----------------------------------------------------------------------------------#include "MachDeps.h"---- #hide-module GHC.Float.RealFracMethods- ( -- * Double methods- -- ** Integer results- properFractionDoubleInteger- , truncateDoubleInteger- , floorDoubleInteger- , ceilingDoubleInteger- , roundDoubleInteger- -- ** Int results- , properFractionDoubleInt- , floorDoubleInt- , ceilingDoubleInt- , roundDoubleInt- -- * Double/Int conversions, wrapped primops- , double2Int- , int2Double- -- * Float methods- -- ** Integer results- , properFractionFloatInteger- , truncateFloatInteger- , floorFloatInteger- , ceilingFloatInteger- , roundFloatInteger- -- ** Int results- , properFractionFloatInt- , floorFloatInt- , ceilingFloatInt- , roundFloatInt- -- * Float/Int conversions, wrapped primops- , float2Int- , int2Float- ) where--import GHC.Integer--import GHC.Base-import GHC.Num ()--#if WORD_SIZE_IN_BITS < 64--import GHC.IntWord64--#define TO64 integerToInt64-#define FROM64 int64ToInteger-#define MINUS64 minusInt64#-#define NEGATE64 negateInt64#--#else--#define TO64 integerToInt-#define FROM64 smallInteger-#define MINUS64 ( -# )-#define NEGATE64 negateInt#--uncheckedIShiftRA64# :: Int# -> Int# -> Int#-uncheckedIShiftRA64# = uncheckedIShiftRA#--uncheckedIShiftL64# :: Int# -> Int# -> Int#-uncheckedIShiftL64# = uncheckedIShiftL#--#endif--default ()----------------------------------------------------------------------------------- Float Methods ------------------------------------------------------------------------------------- Special Functions for Int, nice, easy and fast.--- They should be small enough to be inlined automatically.---- We have to test for ±0.0 to avoid returning -0.0 in the second--- component of the pair. Unfortunately the branching costs a lot--- of performance.-properFractionFloatInt :: Float -> (Int, Float)-properFractionFloatInt (F# x) =- if x `eqFloat#` 0.0#- then (I# 0#, F# 0.0#)- else case float2Int# x of- n -> (I# n, F# (x `minusFloat#` int2Float# n))---- truncateFloatInt = float2Int--floorFloatInt :: Float -> Int-floorFloatInt (F# x) =- case float2Int# x of- n | x `ltFloat#` int2Float# n -> I# (n -# 1#)- | otherwise -> I# n--ceilingFloatInt :: Float -> Int-ceilingFloatInt (F# x) =- case float2Int# x of- n | int2Float# n `ltFloat#` x -> I# (n +# 1#)- | otherwise -> I# n--roundFloatInt :: Float -> Int-roundFloatInt x = float2Int (c_rintFloat x)---- Functions with Integer results---- With the new code generator in GHC 7, the explicit bit-fiddling is--- slower than the old code for values of small modulus, but when the--- 'Int' range is left, the bit-fiddling quickly wins big, so we use that.--- If the methods are called on smallish values, hopefully people go--- through Int and not larger types.---- Note: For negative exponents, we must check the validity of the shift--- distance for the right shifts of the mantissa.--{-# INLINE properFractionFloatInteger #-}-properFractionFloatInteger :: Float -> (Integer, Float)-properFractionFloatInteger v@(F# x) =- case decodeFloat_Int# x of- (# m, e #)- | e <# 0# ->- case negateInt# e of- s | s ># 23# -> (0, v)- | m <# 0# ->- case negateInt# (negateInt# m `uncheckedIShiftRA#` s) of- k -> (smallInteger k,- case m -# (k `uncheckedIShiftL#` s) of- r -> F# (encodeFloatInteger (smallInteger r) e))- | otherwise ->- case m `uncheckedIShiftRL#` s of- k -> (smallInteger k,- case m -# (k `uncheckedIShiftL#` s) of- r -> F# (encodeFloatInteger (smallInteger r) e))- | otherwise -> (shiftLInteger (smallInteger m) e, F# 0.0#)--{-# INLINE truncateFloatInteger #-}-truncateFloatInteger :: Float -> Integer-truncateFloatInteger x =- case properFractionFloatInteger x of- (n, _) -> n---- floor is easier for negative numbers than truncate, so this gets its--- own implementation, it's a little faster.-{-# INLINE floorFloatInteger #-}-floorFloatInteger :: Float -> Integer-floorFloatInteger (F# x) =- case decodeFloat_Int# x of- (# m, e #)- | e <# 0# ->- case negateInt# e of- s | s ># 23# -> if m <# 0# then (-1) else 0- | otherwise -> smallInteger (m `uncheckedIShiftRA#` s)- | otherwise -> shiftLInteger (smallInteger m) e---- ceiling x = -floor (-x)--- If giving this its own implementation is faster at all,--- it's only marginally so, hence we keep it short.-{-# INLINE ceilingFloatInteger #-}-ceilingFloatInteger :: Float -> Integer-ceilingFloatInteger (F# x) =- negateInteger (floorFloatInteger (F# (negateFloat# x)))--{-# INLINE roundFloatInteger #-}-roundFloatInteger :: Float -> Integer-roundFloatInteger x = float2Integer (c_rintFloat x)----------------------------------------------------------------------------------- Double Methods ------------------------------------------------------------------------------------- Special Functions for Int, nice, easy and fast.--- They should be small enough to be inlined automatically.---- We have to test for ±0.0 to avoid returning -0.0 in the second--- component of the pair. Unfortunately the branching costs a lot--- of performance.-properFractionDoubleInt :: Double -> (Int, Double)-properFractionDoubleInt (D# x) =- if x ==## 0.0##- then (I# 0#, D# 0.0##)- else case double2Int# x of- n -> (I# n, D# (x -## int2Double# n))---- truncateDoubleInt = double2Int--floorDoubleInt :: Double -> Int-floorDoubleInt (D# x) =- case double2Int# x of- n | x <## int2Double# n -> I# (n -# 1#)- | otherwise -> I# n--ceilingDoubleInt :: Double -> Int-ceilingDoubleInt (D# x) =- case double2Int# x of- n | int2Double# n <## x -> I# (n +# 1#)- | otherwise -> I# n--roundDoubleInt :: Double -> Int-roundDoubleInt x = double2Int (c_rintDouble x)---- Functions with Integer results---- The new Code generator isn't quite as good for the old 'Double' code--- as for the 'Float' code, so for 'Double' the bit-fiddling also wins--- when the values have small modulus.---- When the exponent is negative, all mantissae have less than 64 bits--- and the right shifting of sized types is much faster than that of--- 'Integer's, especially when we can---- Note: For negative exponents, we must check the validity of the shift--- distance for the right shifts of the mantissa.--{-# INLINE properFractionDoubleInteger #-}-properFractionDoubleInteger :: Double -> (Integer, Double)-properFractionDoubleInteger v@(D# x) =- case decodeDoubleInteger x of- (# m, e #)- | e <# 0# ->- case negateInt# e of- s | s ># 52# -> (0, v)- | m < 0 ->- case TO64 (negateInteger m) of- n ->- case n `uncheckedIShiftRA64#` s of- k ->- (FROM64 (NEGATE64 k),- case MINUS64 n (k `uncheckedIShiftL64#` s) of- r ->- D# (encodeDoubleInteger (FROM64 (NEGATE64 r)) e))- | otherwise ->- case TO64 m of- n ->- case n `uncheckedIShiftRA64#` s of- k -> (FROM64 k,- case MINUS64 n (k `uncheckedIShiftL64#` s) of- r -> D# (encodeDoubleInteger (FROM64 r) e))- | otherwise -> (shiftLInteger m e, D# 0.0##)--{-# INLINE truncateDoubleInteger #-}-truncateDoubleInteger :: Double -> Integer-truncateDoubleInteger x =- case properFractionDoubleInteger x of- (n, _) -> n---- floor is easier for negative numbers than truncate, so this gets its--- own implementation, it's a little faster.-{-# INLINE floorDoubleInteger #-}-floorDoubleInteger :: Double -> Integer-floorDoubleInteger (D# x) =- case decodeDoubleInteger x of- (# m, e #)- | e <# 0# ->- case negateInt# e of- s | s ># 52# -> if m < 0 then (-1) else 0- | otherwise ->- case TO64 m of- n -> FROM64 (n `uncheckedIShiftRA64#` s)- | otherwise -> shiftLInteger m e--{-# INLINE ceilingDoubleInteger #-}-ceilingDoubleInteger :: Double -> Integer-ceilingDoubleInteger (D# x) =- negateInteger (floorDoubleInteger (D# (negateDouble# x)))--{-# INLINE roundDoubleInteger #-}-roundDoubleInteger :: Double -> Integer-roundDoubleInteger x = double2Integer (c_rintDouble x)---- Wrappers around double2Int#, int2Double#, float2Int# and int2Float#,--- we need them here, so we move them from GHC.Float and re-export them--- explicitly from there.--double2Int :: Double -> Int-double2Int (D# x) = I# (double2Int# x)--int2Double :: Int -> Double-int2Double (I# i) = D# (int2Double# i)--float2Int :: Float -> Int-float2Int (F# x) = I# (float2Int# x)--int2Float :: Int -> Float-int2Float (I# i) = F# (int2Float# i)---- Quicker conversions from 'Double' and 'Float' to 'Integer',--- assuming the floating point value is integral.------ Note: Since the value is integral, the exponent can't be less than--- (-TYP_MANT_DIG), so we need not check the validity of the shift--- distance for the right shfts here.--{-# INLINE double2Integer #-}-double2Integer :: Double -> Integer-double2Integer (D# x) =- case decodeDoubleInteger x of- (# m, e #)- | e <# 0# ->- case TO64 m of- n -> FROM64 (n `uncheckedIShiftRA64#` negateInt# e)- | otherwise -> shiftLInteger m e--{-# INLINE float2Integer #-}-float2Integer :: Float -> Integer-float2Integer (F# x) =- case decodeFloat_Int# x of- (# m, e #)- | e <# 0# -> smallInteger (m `uncheckedIShiftRA#` negateInt# e)- | otherwise -> shiftLInteger (smallInteger m) e---- Foreign imports, the rounding is done faster in C when the value--- isn't integral, so we call out for rounding. For values of large--- modulus, calling out to C is slower than staying in Haskell, but--- presumably 'round' is mostly called for values with smaller modulus,--- when calling out to C is a major win.--- For all other functions, calling out to C gives at most a marginal--- speedup for values of small modulus and is much slower than staying--- in Haskell for values of large modulus, so those are done in Haskell.--foreign import ccall unsafe "rintDouble"- c_rintDouble :: Double -> Double--foreign import ccall unsafe "rintFloat"- c_rintFloat :: Float -> Float-
@@ -1,257 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : GHC.Foreign--- Copyright : (c) The University of Glasgow, 2008-2011--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Foreign marshalling support for CStrings with configurable encodings-----------------------------------------------------------------------------------module GHC.Foreign (- -- * C strings with a configurable encoding- - -- conversion of C strings into Haskell strings- --- peekCString, -- :: TextEncoding -> CString -> IO String- peekCStringLen, -- :: TextEncoding -> CStringLen -> IO String- - -- conversion of Haskell strings into C strings- --- newCString, -- :: TextEncoding -> String -> IO CString- newCStringLen, -- :: TextEncoding -> String -> IO CStringLen- - -- conversion of Haskell strings into C strings using temporary storage- --- withCString, -- :: TextEncoding -> String -> (CString -> IO a) -> IO a- withCStringLen, -- :: TextEncoding -> String -> (CStringLen -> IO a) -> IO a- - charIsRepresentable, -- :: TextEncoding -> Char -> IO Bool- ) where--import Foreign.Marshal.Array-import Foreign.C.Types-import Foreign.Ptr-import Foreign.Storable--import Data.Word---- Imports for the locale-encoding version of marshallers-import Control.Monad--import Data.Tuple (fst)-import Data.Maybe--import {-# SOURCE #-} System.Posix.Internals (puts)-import GHC.Show ( show )--import Foreign.Marshal.Alloc-import Foreign.ForeignPtr--import GHC.Err (undefined)-import GHC.List-import GHC.Num-import GHC.Base--import GHC.IO-import GHC.IO.Exception-import GHC.IO.Buffer-import GHC.IO.Encoding.Types---c_DEBUG_DUMP :: Bool-c_DEBUG_DUMP = False--putDebugMsg :: String -> IO ()-putDebugMsg | c_DEBUG_DUMP = puts- | otherwise = const (return ())----- These definitions are identical to those in Foreign.C.String, but copied in here to avoid a cycle:-type CString = Ptr CChar-type CStringLen = (Ptr CChar, Int)---- exported functions--- ---------------------- | Marshal a NUL terminated C string into a Haskell string.----peekCString :: TextEncoding -> CString -> IO String-peekCString enc cp = do- sz <- lengthArray0 nUL cp- peekEncodedCString enc (cp, sz * cCharSize)---- | Marshal a C string with explicit length into a Haskell string.----peekCStringLen :: TextEncoding -> CStringLen -> IO String-peekCStringLen = peekEncodedCString---- | Marshal a Haskell string into a NUL terminated C string.------ * the Haskell string may /not/ contain any NUL characters------ * new storage is allocated for the C string and must be--- explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCString :: TextEncoding -> String -> IO CString-newCString enc = liftM fst . newEncodedCString enc True---- | Marshal a Haskell string into a C string (ie, character array) with--- explicit length information.------ * new storage is allocated for the C string and must be--- explicitly freed using 'Foreign.Marshal.Alloc.free' or--- 'Foreign.Marshal.Alloc.finalizerFree'.----newCStringLen :: TextEncoding -> String -> IO CStringLen-newCStringLen enc = newEncodedCString enc False---- | Marshal a Haskell string into a NUL terminated C string using temporary--- storage.------ * the Haskell string may /not/ contain any NUL characters------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCString :: TextEncoding -> String -> (CString -> IO a) -> IO a-withCString enc s act = withEncodedCString enc True s $ \(cp, _sz) -> act cp---- | Marshal a Haskell string into a C string (ie, character array)--- in temporary storage, with explicit length information.------ * the memory is freed when the subcomputation terminates (either--- normally or via an exception), so the pointer to the temporary--- storage must /not/ be used after this.----withCStringLen :: TextEncoding -> String -> (CStringLen -> IO a) -> IO a-withCStringLen enc = withEncodedCString enc False----- | Determines whether a character can be accurately encoded in a 'CString'.------ Pretty much anyone who uses this function is in a state of sin because--- whether or not a character is encodable will, in general, depend on the--- context in which it occurs.-charIsRepresentable :: TextEncoding -> Char -> IO Bool-charIsRepresentable enc c = withCString enc [c] (fmap (== [c]) . peekCString enc) `catchException` (\e -> let _ = e :: IOException in return False)---- auxiliary definitions--- -------------------------- C's end of string character-nUL :: CChar-nUL = 0---- Size of a CChar in bytes-cCharSize :: Int-cCharSize = sizeOf (undefined :: CChar)---{-# INLINE peekEncodedCString #-}-peekEncodedCString :: TextEncoding -- ^ Encoding of CString- -> CStringLen- -> IO String -- ^ String in Haskell terms-peekEncodedCString (TextEncoding { mkTextDecoder = mk_decoder }) (p, sz_bytes)- = bracket mk_decoder close $ \decoder -> do- let chunk_size = sz_bytes `max` 1 -- Decode buffer chunk size in characters: one iteration only for ASCII- from0 <- fmap (\fp -> bufferAdd sz_bytes (emptyBuffer fp sz_bytes ReadBuffer)) $ newForeignPtr_ (castPtr p)- to <- newCharBuffer chunk_size WriteBuffer-- let go iteration from = do- (why, from', to') <- encode decoder from to- if isEmptyBuffer from'- then- -- No input remaining: @why@ will be InputUnderflow, but we don't care- withBuffer to' $ peekArray (bufferElems to')- else do- -- Input remaining: what went wrong?- putDebugMsg ("peekEncodedCString: " ++ show iteration ++ " " ++ show why)- (from'', to'') <- case why of InvalidSequence -> recover decoder from' to' -- These conditions are equally bad because- InputUnderflow -> recover decoder from' to' -- they indicate malformed/truncated input- OutputUnderflow -> return (from', to') -- We will have more space next time round- putDebugMsg ("peekEncodedCString: from " ++ summaryBuffer from ++ " " ++ summaryBuffer from' ++ " " ++ summaryBuffer from'')- putDebugMsg ("peekEncodedCString: to " ++ summaryBuffer to ++ " " ++ summaryBuffer to' ++ " " ++ summaryBuffer to'')- to_chars <- withBuffer to'' $ peekArray (bufferElems to'')- fmap (to_chars++) $ go (iteration + 1) from''-- go (0 :: Int) from0--{-# INLINE withEncodedCString #-}-withEncodedCString :: TextEncoding -- ^ Encoding of CString to create- -> Bool -- ^ Null-terminate?- -> String -- ^ String to encode- -> (CStringLen -> IO a) -- ^ Worker that can safely use the allocated memory- -> IO a-withEncodedCString (TextEncoding { mkTextEncoder = mk_encoder }) null_terminate s act- = bracket mk_encoder close $ \encoder -> withArrayLen s $ \sz p -> do- from <- fmap (\fp -> bufferAdd sz (emptyBuffer fp sz ReadBuffer)) $ newForeignPtr_ p-- let go iteration to_sz_bytes = do- putDebugMsg ("withEncodedCString: " ++ show iteration)- allocaBytes to_sz_bytes $ \to_p -> do- mb_res <- tryFillBufferAndCall encoder null_terminate from to_p to_sz_bytes act- case mb_res of- Nothing -> go (iteration + 1) (to_sz_bytes * 2)- Just res -> return res-- -- If the input string is ASCII, this value will ensure we only allocate once- go (0 :: Int) (cCharSize * (sz + 1))--{-# INLINE newEncodedCString #-}-newEncodedCString :: TextEncoding -- ^ Encoding of CString to create- -> Bool -- ^ Null-terminate?- -> String -- ^ String to encode- -> IO CStringLen-newEncodedCString (TextEncoding { mkTextEncoder = mk_encoder }) null_terminate s- = bracket mk_encoder close $ \encoder -> withArrayLen s $ \sz p -> do- from <- fmap (\fp -> bufferAdd sz (emptyBuffer fp sz ReadBuffer)) $ newForeignPtr_ p-- let go iteration to_p to_sz_bytes = do- putDebugMsg ("newEncodedCString: " ++ show iteration)- mb_res <- tryFillBufferAndCall encoder null_terminate from to_p to_sz_bytes return- case mb_res of- Nothing -> do- let to_sz_bytes' = to_sz_bytes * 2- to_p' <- reallocBytes to_p to_sz_bytes'- go (iteration + 1) to_p' to_sz_bytes'- Just res -> return res-- -- If the input string is ASCII, this value will ensure we only allocate once- let to_sz_bytes = cCharSize * (sz + 1)- to_p <- mallocBytes to_sz_bytes- go (0 :: Int) to_p to_sz_bytes---tryFillBufferAndCall :: TextEncoder dstate -> Bool -> Buffer Char -> Ptr Word8 -> Int- -> (CStringLen -> IO a) -> IO (Maybe a)-tryFillBufferAndCall encoder null_terminate from0 to_p to_sz_bytes act = do- to_fp <- newForeignPtr_ to_p- go (0 :: Int) (from0, emptyBuffer to_fp to_sz_bytes WriteBuffer)- where- go iteration (from, to) = do- (why, from', to') <- encode encoder from to- putDebugMsg ("tryFillBufferAndCall: " ++ show iteration ++ " " ++ show why ++ " " ++ summaryBuffer from ++ " " ++ summaryBuffer from')- if isEmptyBuffer from'- then if null_terminate && bufferAvailable to' == 0- then return Nothing -- We had enough for the string but not the terminator: ask the caller for more buffer- else do- -- Awesome, we had enough buffer- let bytes = bufferElems to'- withBuffer to' $ \to_ptr -> do- when null_terminate $ pokeElemOff to_ptr (bufR to') 0- fmap Just $ act (castPtr to_ptr, bytes) -- NB: the length information is specified as being in *bytes*- else case why of -- We didn't consume all of the input- InputUnderflow -> recover encoder from' to' >>= go (iteration + 1) -- These conditions are equally bad- InvalidSequence -> recover encoder from' to' >>= go (iteration + 1) -- since the input was truncated/invalid- OutputUnderflow -> return Nothing -- Oops, out of buffer during decoding: ask the caller for more-
@@ -1,390 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , BangPatterns- , MagicHash- , UnboxedTuples- #-}-{-# OPTIONS_HADDOCK hide #-}-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}---------------------------------------------------------------------------------- |--- Module : GHC.ForeignPtr--- Copyright : (c) The University of Glasgow, 1992-2003--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ GHC's implementation of the 'ForeignPtr' data type.--- ---------------------------------------------------------------------------------- #hide-module GHC.ForeignPtr- (- ForeignPtr(..),- FinalizerPtr,- FinalizerEnvPtr,- newForeignPtr_,- mallocForeignPtr,- mallocPlainForeignPtr,- mallocForeignPtrBytes,- mallocPlainForeignPtrBytes,- addForeignPtrFinalizer,- addForeignPtrFinalizerEnv,- touchForeignPtr,- unsafeForeignPtrToPtr,- castForeignPtr,- newConcForeignPtr,- addForeignPtrConcFinalizer,- finalizeForeignPtr- ) where--import Control.Monad ( sequence_ )-import Foreign.Storable-import Data.Typeable--import GHC.Show-import GHC.List ( null )-import GHC.Base-import GHC.IORef-import GHC.STRef ( STRef(..) )-import GHC.Ptr ( Ptr(..), FunPtr(..) )-import GHC.Err--#include "Typeable.h"---- |The type 'ForeignPtr' represents references to objects that are--- maintained in a foreign language, i.e., that are not part of the--- data structures usually managed by the Haskell storage manager.--- The essential difference between 'ForeignPtr's and vanilla memory--- references of type @Ptr a@ is that the former may be associated--- with /finalizers/. A finalizer is a routine that is invoked when--- the Haskell storage manager detects that - within the Haskell heap--- and stack - there are no more references left that are pointing to--- the 'ForeignPtr'. Typically, the finalizer will, then, invoke--- routines in the foreign language that free the resources bound by--- the foreign object.------ The 'ForeignPtr' is parameterised in the same way as 'Ptr'. The--- type argument of 'ForeignPtr' should normally be an instance of--- class 'Storable'.----data ForeignPtr a = ForeignPtr Addr# ForeignPtrContents- -- we cache the Addr# in the ForeignPtr object, but attach- -- the finalizer to the IORef (or the MutableByteArray# in- -- the case of a MallocPtr). The aim of the representation- -- is to make withForeignPtr efficient; in fact, withForeignPtr- -- should be just as efficient as unpacking a Ptr, and multiple- -- withForeignPtrs can share an unpacked ForeignPtr. Note- -- that touchForeignPtr only has to touch the ForeignPtrContents- -- object, because that ensures that whatever the finalizer is- -- attached to is kept alive.--INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")--data Finalizers- = NoFinalizers- | CFinalizers- | HaskellFinalizers- deriving Eq--data ForeignPtrContents- = PlainForeignPtr !(IORef (Finalizers, [IO ()]))- | MallocPtr (MutableByteArray# RealWorld) !(IORef (Finalizers, [IO ()]))- | PlainPtr (MutableByteArray# RealWorld)--instance Eq (ForeignPtr a) where- p == q = unsafeForeignPtrToPtr p == unsafeForeignPtrToPtr q--instance Ord (ForeignPtr a) where- compare p q = compare (unsafeForeignPtrToPtr p) (unsafeForeignPtrToPtr q)--instance Show (ForeignPtr a) where- showsPrec p f = showsPrec p (unsafeForeignPtrToPtr f)----- |A finalizer is represented as a pointer to a foreign function that, at--- finalisation time, gets as an argument a plain pointer variant of the--- foreign pointer that the finalizer is associated with.--- -type FinalizerPtr a = FunPtr (Ptr a -> IO ())-type FinalizerEnvPtr env a = FunPtr (Ptr env -> Ptr a -> IO ())--newConcForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)------ ^Turns a plain memory reference into a foreign object by--- associating a finalizer - given by the monadic operation - with the--- reference. The storage manager will start the finalizer, in a--- separate thread, some time after the last reference to the--- @ForeignPtr@ is dropped. There is no guarantee of promptness, and--- in fact there is no guarantee that the finalizer will eventually--- run at all.------ Note that references from a finalizer do not necessarily prevent--- another object from being finalized. If A's finalizer refers to B--- (perhaps using 'touchForeignPtr', then the only guarantee is that--- B's finalizer will never be started before A's. If both A and B--- are unreachable, then both finalizers will start together. See--- 'touchForeignPtr' for more on finalizer ordering.----newConcForeignPtr p finalizer- = do fObj <- newForeignPtr_ p- addForeignPtrConcFinalizer fObj finalizer- return fObj--mallocForeignPtr :: Storable a => IO (ForeignPtr a)--- ^ Allocate some memory and return a 'ForeignPtr' to it. The memory--- will be released automatically when the 'ForeignPtr' is discarded.------ 'mallocForeignPtr' is equivalent to------ > do { p <- malloc; newForeignPtr finalizerFree p }--- --- although it may be implemented differently internally: you may not--- assume that the memory returned by 'mallocForeignPtr' has been--- allocated with 'Foreign.Marshal.Alloc.malloc'.------ GHC notes: 'mallocForeignPtr' has a heavily optimised--- implementation in GHC. It uses pinned memory in the garbage--- collected heap, so the 'ForeignPtr' does not require a finalizer to--- free the memory. Use of 'mallocForeignPtr' and associated--- functions is strongly recommended in preference to 'newForeignPtr'--- with a finalizer.--- -mallocForeignPtr = doMalloc undefined- where doMalloc :: Storable b => b -> IO (ForeignPtr b)- doMalloc a- | I# size < 0 = error "mallocForeignPtr: size must be >= 0"- | otherwise = do- r <- newIORef (NoFinalizers, [])- IO $ \s ->- case newAlignedPinnedByteArray# size align s of { (# s', mbarr# #) ->- (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))- (MallocPtr mbarr# r) #)- }- where !(I# size) = sizeOf a- !(I# align) = alignment a---- | This function is similar to 'mallocForeignPtr', except that the--- size of the memory required is given explicitly as a number of bytes.-mallocForeignPtrBytes :: Int -> IO (ForeignPtr a)-mallocForeignPtrBytes size | size < 0 =- error "mallocForeignPtrBytes: size must be >= 0"-mallocForeignPtrBytes (I# size) = do - r <- newIORef (NoFinalizers, [])- IO $ \s ->- case newPinnedByteArray# size s of { (# s', mbarr# #) ->- (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))- (MallocPtr mbarr# r) #)- }---- | Allocate some memory and return a 'ForeignPtr' to it. The memory--- will be released automatically when the 'ForeignPtr' is discarded.------ GHC notes: 'mallocPlainForeignPtr' has a heavily optimised--- implementation in GHC. It uses pinned memory in the garbage--- collected heap, as for mallocForeignPtr. Unlike mallocForeignPtr, a--- ForeignPtr created with mallocPlainForeignPtr carries no finalizers.--- It is not possible to add a finalizer to a ForeignPtr created with--- mallocPlainForeignPtr. This is useful for ForeignPtrs that will live--- only inside Haskell (such as those created for packed strings).--- Attempts to add a finalizer to a ForeignPtr created this way, or to--- finalize such a pointer, will throw an exception.--- -mallocPlainForeignPtr :: Storable a => IO (ForeignPtr a)-mallocPlainForeignPtr = doMalloc undefined- where doMalloc :: Storable b => b -> IO (ForeignPtr b)- doMalloc a- | I# size < 0 = error "mallocForeignPtr: size must be >= 0"- | otherwise = IO $ \s ->- case newAlignedPinnedByteArray# size align s of { (# s', mbarr# #) ->- (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))- (PlainPtr mbarr#) #)- }- where !(I# size) = sizeOf a- !(I# align) = alignment a---- | This function is similar to 'mallocForeignPtrBytes', except that--- the internally an optimised ForeignPtr representation with no--- finalizer is used. Attempts to add a finalizer will cause an--- exception to be thrown.-mallocPlainForeignPtrBytes :: Int -> IO (ForeignPtr a)-mallocPlainForeignPtrBytes size | size < 0 =- error "mallocPlainForeignPtrBytes: size must be >= 0"-mallocPlainForeignPtrBytes (I# size) = IO $ \s ->- case newPinnedByteArray# size s of { (# s', mbarr# #) ->- (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))- (PlainPtr mbarr#) #)- }--addForeignPtrFinalizer :: FinalizerPtr a -> ForeignPtr a -> IO ()--- ^This function adds a finalizer to the given foreign object. The--- finalizer will run /before/ all other finalizers for the same--- object which have already been registered.-addForeignPtrFinalizer (FunPtr fp) (ForeignPtr p c) = case c of- PlainForeignPtr r -> f r >> return ()- MallocPtr _ r -> f r >> return ()- _ -> error "GHC.ForeignPtr: attempt to add a finalizer to a plain pointer"- where- f r =- noMixing CFinalizers r $- IO $ \s ->- case r of { IORef (STRef r#) ->- case mkWeakForeignEnv# r# () fp p 0# nullAddr# s of { (# s1, w #) ->- (# s1, finalizeForeign w #) }}--addForeignPtrFinalizerEnv ::- FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()--- ^ Like 'addForeignPtrFinalizerEnv' but allows the finalizer to be--- passed an additional environment parameter to be passed to the--- finalizer. The environment passed to the finalizer is fixed by the--- second argument to 'addForeignPtrFinalizerEnv'-addForeignPtrFinalizerEnv (FunPtr fp) (Ptr ep) (ForeignPtr p c) = case c of- PlainForeignPtr r -> f r >> return ()- MallocPtr _ r -> f r >> return ()- _ -> error "GHC.ForeignPtr: attempt to add a finalizer to a plain pointer"- where- f r =- noMixing CFinalizers r $- IO $ \s ->- case r of { IORef (STRef r#) ->- case mkWeakForeignEnv# r# () fp p 1# ep s of { (# s1, w #) ->- (# s1, finalizeForeign w #) }}--finalizeForeign :: Weak# () -> IO ()-finalizeForeign w = IO $ \s ->- case finalizeWeak# w s of- (# s1, 0#, _ #) -> (# s1, () #)- (# s1, _ , f #) -> f s1--addForeignPtrConcFinalizer :: ForeignPtr a -> IO () -> IO ()--- ^This function adds a finalizer to the given @ForeignPtr@. The--- finalizer will run /before/ all other finalizers for the same--- object which have already been registered.------ This is a variant of @addForeignPtrFinalizer@, where the finalizer--- is an arbitrary @IO@ action. When it is invoked, the finalizer--- will run in a new thread.------ NB. Be very careful with these finalizers. One common trap is that--- if a finalizer references another finalized value, it does not--- prevent that value from being finalized. In particular, 'Handle's--- are finalized objects, so a finalizer should not refer to a 'Handle'--- (including @stdout@, @stdin@ or @stderr@).----addForeignPtrConcFinalizer (ForeignPtr _ c) finalizer = - addForeignPtrConcFinalizer_ c finalizer--addForeignPtrConcFinalizer_ :: ForeignPtrContents -> IO () -> IO ()-addForeignPtrConcFinalizer_ (PlainForeignPtr r) finalizer = do- noFinalizers <- noMixing HaskellFinalizers r (return finalizer)- if noFinalizers- then IO $ \s ->- case r of { IORef (STRef r#) ->- case mkWeak# r# () (foreignPtrFinalizer r) s of { (# s1, _ #) ->- (# s1, () #) }}- else return ()-addForeignPtrConcFinalizer_ f@(MallocPtr fo r) finalizer = do- noFinalizers <- noMixing HaskellFinalizers r (return finalizer)- if noFinalizers- then IO $ \s -> - case mkWeak# fo () (do foreignPtrFinalizer r; touch f) s of- (# s1, _ #) -> (# s1, () #)- else return ()--addForeignPtrConcFinalizer_ _ _ =- error "GHC.ForeignPtr: attempt to add a finalizer to plain pointer"--noMixing ::- Finalizers -> IORef (Finalizers, [IO ()]) -> IO (IO ()) -> IO Bool-noMixing ftype0 r mkF = do- (ftype, fs) <- readIORef r- if ftype /= NoFinalizers && ftype /= ftype0- then error ("GHC.ForeignPtr: attempt to mix Haskell and C finalizers " ++- "in the same ForeignPtr")- else do- f <- mkF- writeIORef r (ftype0, f : fs)- return (null fs)--foreignPtrFinalizer :: IORef (Finalizers, [IO ()]) -> IO ()-foreignPtrFinalizer r = do (_, fs) <- readIORef r; sequence_ fs--newForeignPtr_ :: Ptr a -> IO (ForeignPtr a)--- ^Turns a plain memory reference into a foreign pointer that may be--- associated with finalizers by using 'addForeignPtrFinalizer'.-newForeignPtr_ (Ptr obj) = do- r <- newIORef (NoFinalizers, [])- return (ForeignPtr obj (PlainForeignPtr r))--touchForeignPtr :: ForeignPtr a -> IO ()--- ^This function ensures that the foreign object in--- question is alive at the given place in the sequence of IO--- actions. In particular 'Foreign.ForeignPtr.withForeignPtr'--- does a 'touchForeignPtr' after it--- executes the user action.--- --- Note that this function should not be used to express dependencies--- between finalizers on 'ForeignPtr's. For example, if the finalizer--- for a 'ForeignPtr' @F1@ calls 'touchForeignPtr' on a second--- 'ForeignPtr' @F2@, then the only guarantee is that the finalizer--- for @F2@ is never started before the finalizer for @F1@. They--- might be started together if for example both @F1@ and @F2@ are--- otherwise unreachable, and in that case the scheduler might end up--- running the finalizer for @F2@ first.------ In general, it is not recommended to use finalizers on separate--- objects with ordering constraints between them. To express the--- ordering robustly requires explicit synchronisation using @MVar@s--- between the finalizers, but even then the runtime sometimes runs--- multiple finalizers sequentially in a single thread (for--- performance reasons), so synchronisation between finalizers could--- result in artificial deadlock. Another alternative is to use--- explicit reference counting.----touchForeignPtr (ForeignPtr _ r) = touch r--touch :: ForeignPtrContents -> IO ()-touch r = IO $ \s -> case touch# r s of s' -> (# s', () #)--unsafeForeignPtrToPtr :: ForeignPtr a -> Ptr a--- ^This function extracts the pointer component of a foreign--- pointer. This is a potentially dangerous operations, as if the--- argument to 'unsafeForeignPtrToPtr' is the last usage--- occurrence of the given foreign pointer, then its finalizer(s) will--- be run, which potentially invalidates the plain pointer just--- obtained. Hence, 'touchForeignPtr' must be used--- wherever it has to be guaranteed that the pointer lives on - i.e.,--- has another usage occurrence.------ To avoid subtle coding errors, hand written marshalling code--- should preferably use 'Foreign.ForeignPtr.withForeignPtr' rather--- than combinations of 'unsafeForeignPtrToPtr' and--- 'touchForeignPtr'. However, the latter routines--- are occasionally preferred in tool generated marshalling code.-unsafeForeignPtrToPtr (ForeignPtr fo _) = Ptr fo--castForeignPtr :: ForeignPtr a -> ForeignPtr b--- ^This function casts a 'ForeignPtr'--- parameterised by one type into another type.-castForeignPtr f = unsafeCoerce# f---- | Causes the finalizers associated with a foreign pointer to be run--- immediately.-finalizeForeignPtr :: ForeignPtr a -> IO ()-finalizeForeignPtr (ForeignPtr _ (PlainPtr _)) = return () -- no effect-finalizeForeignPtr (ForeignPtr _ foreignPtr) = do- (ftype, finalizers) <- readIORef refFinalizers- sequence_ finalizers- writeIORef refFinalizers (ftype, [])- where- refFinalizers = case foreignPtr of- (PlainForeignPtr ref) -> ref- (MallocPtr _ ref) -> ref- PlainPtr _ ->- error "finalizeForeignPtr PlainPtr"-
@@ -1,57 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Handle--- Copyright : (c) The University of Glasgow, 1994-2001--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Backwards-compatibility interface------------------------------------------------------------------------------------- #hide-module GHC.Handle {-# DEPRECATED "use GHC.IO.Handle instead" #-} (- withHandle, withHandle', withHandle_,- wantWritableHandle, wantReadableHandle, wantSeekableHandle,---- newEmptyBuffer, allocateBuffer, readCharFromBuffer, writeCharIntoBuffer,--- flushWriteBufferOnly, flushWriteBuffer,--- flushReadBuffer,--- fillReadBuffer, fillReadBufferWithoutBlocking,--- readRawBuffer, readRawBufferPtr,--- readRawBufferNoBlock, readRawBufferPtrNoBlock,--- writeRawBuffer, writeRawBufferPtr,-- ioe_closedHandle, ioe_EOF, ioe_notReadable, ioe_notWritable,-- stdin, stdout, stderr,- IOMode(..), openFile, openBinaryFile, --- fdToHandle_stat,- fdToHandle, fdToHandle',- hFileSize, hSetFileSize, hIsEOF, isEOF, hLookAhead, hLookAhead_, - hSetBuffering, hSetBinaryMode,- hFlush, hDuplicate, hDuplicateTo,-- hClose, hClose_help,-- HandlePosition, HandlePosn(..), hGetPosn, hSetPosn,- SeekMode(..), hSeek, hTell,-- hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,- hSetEcho, hGetEcho, hIsTerminalDevice,-- hShow,-- ) where--import GHC.IO.IOMode-import GHC.IO.Handle-import GHC.IO.Handle.Internals-import GHC.IO.Handle.FD-
@@ -1,489 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude- , BangPatterns- , RankNTypes- , MagicHash- , UnboxedTuples- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO--- Copyright : (c) The University of Glasgow 1994-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Definitions for the 'IO' monad and its friends.------------------------------------------------------------------------------------- #hide-module GHC.IO (- IO(..), unIO, failIO, liftIO,- unsafePerformIO, unsafeInterleaveIO,- unsafeDupablePerformIO, unsafeDupableInterleaveIO,- noDuplicate,-- -- To and from from ST- stToIO, ioToST, unsafeIOToST, unsafeSTToIO,-- FilePath,-- catchException, catchAny, throwIO,- mask, mask_, uninterruptibleMask, uninterruptibleMask_, - MaskingState(..), getMaskingState,- block, unblock, blocked, unsafeUnmask,- onException, bracket, finally, evaluate- ) where--import GHC.Base-import GHC.ST-import GHC.Exception-import GHC.Show-import Data.Maybe--import {-# SOURCE #-} GHC.IO.Exception ( userError )---- ------------------------------------------------------------------------------ The IO Monad--{--The IO Monad is just an instance of the ST monad, where the state is-the real world. We use the exception mechanism (in GHC.Exception) to-implement IO exceptions.--NOTE: The IO representation is deeply wired in to various parts of the-system. The following list may or may not be exhaustive:--Compiler - types of various primitives in PrimOp.lhs--RTS - forceIO (StgMiscClosures.hc)- - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast - (Exceptions.hc)- - raiseAsync (Schedule.c)--Prelude - GHC.IO.lhs, and several other places including- GHC.Exception.lhs.--Libraries - parts of hslibs/lang.----SDM--}--liftIO :: IO a -> State# RealWorld -> STret RealWorld a-liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r--failIO :: String -> IO a-failIO s = IO (raiseIO# (toException (userError s)))---- ------------------------------------------------------------------------------ Coercions between IO and ST---- | A monad transformer embedding strict state transformers in the 'IO'--- monad. The 'RealWorld' parameter indicates that the internal state--- used by the 'ST' computation is a special one supplied by the 'IO'--- monad, and thus distinct from those used by invocations of 'runST'.-stToIO :: ST RealWorld a -> IO a-stToIO (ST m) = IO m--ioToST :: IO a -> ST RealWorld a-ioToST (IO m) = (ST m)---- This relies on IO and ST having the same representation modulo the--- constraint on the type of the state----unsafeIOToST :: IO a -> ST s a-unsafeIOToST (IO io) = ST $ \ s -> (unsafeCoerce# io) s--unsafeSTToIO :: ST s a -> IO a-unsafeSTToIO (ST m) = IO (unsafeCoerce# m)---- ------------------------------------------------------------------------------ Unsafe IO operations--{-|-This is the \"back door\" into the 'IO' monad, allowing-'IO' computation to be performed at any time. For-this to be safe, the 'IO' computation should be-free of side effects and independent of its environment.--If the I\/O computation wrapped in 'unsafePerformIO' performs side-effects, then the relative order in which those side effects take-place (relative to the main I\/O trunk, or other calls to-'unsafePerformIO') is indeterminate. Furthermore, when using-'unsafePerformIO' to cause side-effects, you should take the following-precautions to ensure the side effects are performed as many times as-you expect them to be. Note that these precautions are necessary for-GHC, but may not be sufficient, and other compilers may require-different precautions:-- * Use @{\-\# NOINLINE foo \#-\}@ as a pragma on any function @foo@- that calls 'unsafePerformIO'. If the call is inlined,- the I\/O may be performed more than once.-- * Use the compiler flag @-fno-cse@ to prevent common sub-expression- elimination being performed on the module, which might combine- two side effects that were meant to be separate. A good example- is using multiple global variables (like @test@ in the example below).-- * Make sure that the either you switch off let-floating (@-fno-full-laziness@), or that the - call to 'unsafePerformIO' cannot float outside a lambda. For example, - if you say:- @- f x = unsafePerformIO (newIORef [])- @- you may get only one reference cell shared between all calls to @f@.- Better would be- @- f x = unsafePerformIO (newIORef [x])- @- because now it can't float outside the lambda.--It is less well known that-'unsafePerformIO' is not type safe. For example:--> test :: IORef [a]-> test = unsafePerformIO $ newIORef []-> -> main = do-> writeIORef test [42]-> bang <- readIORef test-> print (bang :: [Char])--This program will core dump. This problem with polymorphic references-is well known in the ML community, and does not arise with normal-monadic use of references. There is no easy way to make it impossible-once you use 'unsafePerformIO'. Indeed, it is-possible to write @coerce :: a -> b@ with the-help of 'unsafePerformIO'. So be careful!--}-unsafePerformIO :: IO a -> a-unsafePerformIO m = unsafeDupablePerformIO (noDuplicate >> m)--{-| -This version of 'unsafePerformIO' is more efficient-because it omits the check that the IO is only being performed by a-single thread. Hence, when you use 'unsafeDupablePerformIO',-there is a possibility that the IO action may be performed multiple-times (on a multiprocessor), and you should therefore ensure that-it gives the same results each time.--}-{-# NOINLINE unsafeDupablePerformIO #-}-unsafeDupablePerformIO :: IO a -> a-unsafeDupablePerformIO (IO m) = lazy (case m realWorld# of (# _, r #) -> r)---- Why do we NOINLINE unsafeDupablePerformIO? See the comment with--- GHC.ST.runST. Essentially the issue is that the IO computation--- inside unsafePerformIO must be atomic: it must either all run, or--- not at all. If we let the compiler see the application of the IO--- to realWorld#, it might float out part of the IO.---- Why is there a call to 'lazy' in unsafeDupablePerformIO?--- If we don't have it, the demand analyser discovers the following strictness--- for unsafeDupablePerformIO: C(U(AV))--- But then consider--- unsafeDupablePerformIO (\s -> let r = f x in --- case writeIORef v r s of (# s1, _ #) ->--- (# s1, r #)--- The strictness analyser will find that the binding for r is strict,--- (becuase of uPIO's strictness sig), and so it'll evaluate it before --- doing the writeIORef. This actually makes tests/lib/should_run/memo002--- get a deadlock! ------ Solution: don't expose the strictness of unsafeDupablePerformIO,--- by hiding it with 'lazy'--{-|-'unsafeInterleaveIO' allows 'IO' computation to be deferred lazily.-When passed a value of type @IO a@, the 'IO' will only be performed-when the value of the @a@ is demanded. This is used to implement lazy-file reading, see 'System.IO.hGetContents'.--}-{-# INLINE unsafeInterleaveIO #-}-unsafeInterleaveIO :: IO a -> IO a-unsafeInterleaveIO m = unsafeDupableInterleaveIO (noDuplicate >> m)---- We used to believe that INLINE on unsafeInterleaveIO was safe,--- because the state from this IO thread is passed explicitly to the--- interleaved IO, so it cannot be floated out and shared.------ HOWEVER, if the compiler figures out that r is used strictly here,--- then it will eliminate the thunk and the side effects in m will no--- longer be shared in the way the programmer was probably expecting,--- but can be performed many times. In #5943, this broke our--- definition of fixIO, which contains------ ans <- unsafeInterleaveIO (takeMVar m)------ after inlining, we lose the sharing of the takeMVar, so the second--- time 'ans' was demanded we got a deadlock. We could fix this with--- a readMVar, but it seems wrong for unsafeInterleaveIO to sometimes--- share and sometimes not (plus it probably breaks the noDuplicate).--- So now, we do not inline unsafeDupableInterleaveIO.--{-# NOINLINE unsafeDupableInterleaveIO #-}-unsafeDupableInterleaveIO :: IO a -> IO a-unsafeDupableInterleaveIO (IO m)- = IO ( \ s -> let- r = case m s of (# _, res #) -> res- in- (# s, r #))--{-| -Ensures that the suspensions under evaluation by the current thread-are unique; that is, the current thread is not evaluating anything-that is also under evaluation by another thread that has also executed-'noDuplicate'.--This operation is used in the definition of 'unsafePerformIO' to-prevent the IO action from being executed multiple times, which is usually-undesirable.--}-noDuplicate :: IO ()-noDuplicate = IO $ \s -> case noDuplicate# s of s' -> (# s', () #)---- -------------------------------------------------------------------------------- | File and directory names are values of type 'String', whose precise--- meaning is operating system dependent. Files can be opened, yielding a--- handle which can then be used to operate on the contents of that file.--type FilePath = String---- -------------------------------------------------------------------------------- Primitive catch and throwIO--{--catchException used to handle the passing around of the state to the-action and the handler. This turned out to be a bad idea - it meant-that we had to wrap both arguments in thunks so they could be entered-as normal (remember IO returns an unboxed pair...).--Now catch# has type-- catch# :: IO a -> (b -> IO a) -> IO a--(well almost; the compiler doesn't know about the IO newtype so we-have to work around that in the definition of catchException below).--}--catchException :: Exception e => IO a -> (e -> IO a) -> IO a-catchException (IO io) handler = IO $ catch# io handler'- where handler' e = case fromException e of- Just e' -> unIO (handler e')- Nothing -> raiseIO# e--catchAny :: IO a -> (forall e . Exception e => e -> IO a) -> IO a-catchAny (IO io) handler = IO $ catch# io handler'- where handler' (SomeException e) = unIO (handler e)---- | A variant of 'throw' that can only be used within the 'IO' monad.------ Although 'throwIO' has a type that is an instance of the type of 'throw', the--- two functions are subtly different:------ > throw e `seq` x ===> throw e--- > throwIO e `seq` x ===> x------ The first example will cause the exception @e@ to be raised,--- whereas the second one won\'t. In fact, 'throwIO' will only cause--- an exception to be raised when it is used within the 'IO' monad.--- The 'throwIO' variant should be used in preference to 'throw' to--- raise an exception within the 'IO' monad because it guarantees--- ordering with respect to other 'IO' operations, whereas 'throw'--- does not.-throwIO :: Exception e => e -> IO a-throwIO e = IO (raiseIO# (toException e))---- -------------------------------------------------------------------------------- Controlling asynchronous exception delivery--{-# DEPRECATED block "use Control.Exception.mask instead" #-}--- | Note: this function is deprecated, please use 'mask' instead.------ Applying 'block' to a computation will--- execute that computation with asynchronous exceptions--- /blocked/. That is, any thread which--- attempts to raise an exception in the current thread with 'Control.Exception.throwTo' will be--- blocked until asynchronous exceptions are unblocked again. There\'s--- no need to worry about re-enabling asynchronous exceptions; that is--- done automatically on exiting the scope of--- 'block'.------ Threads created by 'Control.Concurrent.forkIO' inherit the blocked--- state from the parent; that is, to start a thread in blocked mode,--- use @block $ forkIO ...@. This is particularly useful if you need to--- establish an exception handler in the forked thread before any--- asynchronous exceptions are received.-block :: IO a -> IO a-block (IO io) = IO $ maskAsyncExceptions# io--{-# DEPRECATED unblock "use Control.Exception.mask instead" #-}--- | Note: this function is deprecated, please use 'mask' instead.------ To re-enable asynchronous exceptions inside the scope of--- 'block', 'unblock' can be--- used. It scopes in exactly the same way, so on exit from--- 'unblock' asynchronous exception delivery will--- be disabled again.-unblock :: IO a -> IO a-unblock = unsafeUnmask--unsafeUnmask :: IO a -> IO a-unsafeUnmask (IO io) = IO $ unmaskAsyncExceptions# io--blockUninterruptible :: IO a -> IO a-blockUninterruptible (IO io) = IO $ maskUninterruptible# io---- | Describes the behaviour of a thread when an asynchronous--- exception is received.-data MaskingState- = Unmasked -- ^ asynchronous exceptions are unmasked (the normal state)- | MaskedInterruptible - -- ^ the state during 'mask': asynchronous exceptions are masked, but blocking operations may still be interrupted- | MaskedUninterruptible- -- ^ the state during 'uninterruptibleMask': asynchronous exceptions are masked, and blocking operations may not be interrupted- deriving (Eq,Show)---- | Returns the 'MaskingState' for the current thread.-getMaskingState :: IO MaskingState-getMaskingState = IO $ \s -> - case getMaskingState# s of- (# s', i #) -> (# s', case i of- 0# -> Unmasked- 1# -> MaskedUninterruptible- _ -> MaskedInterruptible #)--{-# DEPRECATED blocked "use Control.Exception.getMaskingState instead" #-}--- | returns True if asynchronous exceptions are blocked in the--- current thread.-blocked :: IO Bool-blocked = fmap (/= Unmasked) getMaskingState--onException :: IO a -> IO b -> IO a-onException io what = io `catchException` \e -> do _ <- what- throwIO (e :: SomeException)---- | Executes an IO computation with asynchronous--- exceptions /masked/. That is, any thread which attempts to raise--- an exception in the current thread with 'Control.Exception.throwTo'--- will be blocked until asynchronous exceptions are unmasked again.------ The argument passed to 'mask' is a function that takes as its--- argument another function, which can be used to restore the--- prevailing masking state within the context of the masked--- computation. For example, a common way to use 'mask' is to protect--- the acquisition of a resource:------ > mask $ \restore -> do--- > x <- acquire--- > restore (do_something_with x) `onException` release--- > release------ This code guarantees that @acquire@ is paired with @release@, by masking--- asynchronous exceptions for the critical parts. (Rather than write--- this code yourself, it would be better to use--- 'Control.Exception.bracket' which abstracts the general pattern).------ Note that the @restore@ action passed to the argument to 'mask'--- does not necessarily unmask asynchronous exceptions, it just--- restores the masking state to that of the enclosing context. Thus--- if asynchronous exceptions are already masked, 'mask' cannot be used--- to unmask exceptions again. This is so that if you call a library function--- with exceptions masked, you can be sure that the library call will not be--- able to unmask exceptions again. If you are writing library code and need--- to use asynchronous exceptions, the only way is to create a new thread;--- see 'Control.Concurrent.forkIOWithUnmask'.------ Asynchronous exceptions may still be received while in the masked--- state if the masked thread /blocks/ in certain ways; see--- "Control.Exception#interruptible".------ Threads created by 'Control.Concurrent.forkIO' inherit the masked--- state from the parent; that is, to start a thread in blocked mode,--- use @mask_ $ forkIO ...@. This is particularly useful if you need--- to establish an exception handler in the forked thread before any--- asynchronous exceptions are received. To create a a new thread in--- an unmasked state use 'Control.Concurrent.forkIOUnmasked'.--- -mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b---- | Like 'mask', but does not pass a @restore@ action to the argument.-mask_ :: IO a -> IO a---- | Like 'mask', but the masked computation is not interruptible (see--- "Control.Exception#interruptible"). THIS SHOULD BE USED WITH--- GREAT CARE, because if a thread executing in 'uninterruptibleMask'--- blocks for any reason, then the thread (and possibly the program,--- if this is the main thread) will be unresponsive and unkillable.--- This function should only be necessary if you need to mask--- exceptions around an interruptible operation, and you can guarantee--- that the interruptible operation will only block for a short period--- of time.----uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b---- | Like 'uninterruptibleMask', but does not pass a @restore@ action--- to the argument.-uninterruptibleMask_ :: IO a -> IO a--mask_ io = mask $ \_ -> io--mask io = do- b <- getMaskingState- case b of- Unmasked -> block $ io unblock- _ -> io id--uninterruptibleMask_ io = uninterruptibleMask $ \_ -> io--uninterruptibleMask io = do- b <- getMaskingState- case b of- Unmasked -> blockUninterruptible $ io unblock- MaskedInterruptible -> blockUninterruptible $ io block- MaskedUninterruptible -> io id--bracket- :: IO a -- ^ computation to run first (\"acquire resource\")- -> (a -> IO b) -- ^ computation to run last (\"release resource\")- -> (a -> IO c) -- ^ computation to run in-between- -> IO c -- returns the value from the in-between computation-bracket before after thing =- mask $ \restore -> do- a <- before- r <- restore (thing a) `onException` after a- _ <- after a- return r--finally :: IO a -- ^ computation to run first- -> IO b -- ^ computation to run afterward (even if an exception- -- was raised)- -> IO a -- returns the value from the first computation-a `finally` sequel =- mask $ \restore -> do- r <- restore a `onException` sequel- _ <- sequel- return r---- | Forces its argument to be evaluated to weak head normal form when--- the resultant 'IO' action is executed. It can be used to order--- evaluation with respect to other 'IO' operations; its semantics are--- given by------ > evaluate x `seq` y ==> y--- > evaluate x `catch` f ==> (return $! x) `catch` f--- > evaluate x >>= f ==> (return $! x) >>= f------ /Note:/ the first equation implies that @(evaluate x)@ is /not/ the--- same as @(return $! x)@. A correct definition is------ > evaluate x = (return $! x) >>= return----evaluate :: a -> IO a-evaluate a = IO $ \s -> seq# a s -- NB. see #2273, #5129-
@@ -1,9 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.IO where--import GHC.Types--failIO :: [Char] -> IO a-
@@ -1,291 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ForeignFunctionInterface #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Buffer--- Copyright : (c) The University of Glasgow 2008--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Buffers used in the IO system-----------------------------------------------------------------------------------module GHC.IO.Buffer (- -- * Buffers of any element- Buffer(..), BufferState(..), CharBuffer, CharBufElem,-- -- ** Creation- newByteBuffer,- newCharBuffer,- newBuffer,- emptyBuffer,-- -- ** Insertion/removal- bufferRemove,- bufferAdd,- slideContents,- bufferAdjustL,-- -- ** Inspecting- isEmptyBuffer,- isFullBuffer,- isFullCharBuffer,- isWriteBuffer,- bufferElems,- bufferAvailable,- summaryBuffer,-- -- ** Operating on the raw buffer as a Ptr- withBuffer,- withRawBuffer,-- -- ** Assertions- checkBuffer,-- -- * Raw buffers- RawBuffer,- readWord8Buf,- writeWord8Buf,- RawCharBuffer,- peekCharBuf,- readCharBuf,- writeCharBuf,- readCharBufPtr,- writeCharBufPtr,- charSize,- ) where--import GHC.Base--- import GHC.IO-import GHC.Num-import GHC.Ptr-import GHC.Word-import GHC.Show-import GHC.Real-import Foreign.C.Types-import Foreign.ForeignPtr-import Foreign.Storable---- Char buffers use either UTF-16 or UTF-32, with the endianness matching--- the endianness of the host.------ Invariants:--- * a Char buffer consists of *valid* UTF-16 or UTF-32--- * only whole characters: no partial surrogate pairs--#define CHARBUF_UTF32---- #define CHARBUF_UTF16------ NB. it won't work to just change this to CHARBUF_UTF16. Some of--- the code to make this work is there, and it has been tested with--- the Iconv codec, but there are some pieces that are known to be--- broken. In particular, the built-in codecs--- e.g. GHC.IO.Encoding.UTF{8,16,32} need to use isFullCharBuffer or--- similar in place of the ow >= os comparisions.---- ------------------------------------------------------------------------------ Raw blocks of data--type RawBuffer e = ForeignPtr e--readWord8Buf :: RawBuffer Word8 -> Int -> IO Word8-readWord8Buf arr ix = withForeignPtr arr $ \p -> peekByteOff p ix--writeWord8Buf :: RawBuffer Word8 -> Int -> Word8 -> IO ()-writeWord8Buf arr ix w = withForeignPtr arr $ \p -> pokeByteOff p ix w--#ifdef CHARBUF_UTF16-type CharBufElem = Word16-#else-type CharBufElem = Char-#endif--type RawCharBuffer = RawBuffer CharBufElem--peekCharBuf :: RawCharBuffer -> Int -> IO Char-peekCharBuf arr ix = withForeignPtr arr $ \p -> do- (c,_) <- readCharBufPtr p ix- return c--{-# INLINE readCharBuf #-}-readCharBuf :: RawCharBuffer -> Int -> IO (Char, Int)-readCharBuf arr ix = withForeignPtr arr $ \p -> readCharBufPtr p ix--{-# INLINE writeCharBuf #-}-writeCharBuf :: RawCharBuffer -> Int -> Char -> IO Int-writeCharBuf arr ix c = withForeignPtr arr $ \p -> writeCharBufPtr p ix c--{-# INLINE readCharBufPtr #-}-readCharBufPtr :: Ptr CharBufElem -> Int -> IO (Char, Int)-#ifdef CHARBUF_UTF16-readCharBufPtr p ix = do- c1 <- peekElemOff p ix- if (c1 < 0xd800 || c1 > 0xdbff)- then return (chr (fromIntegral c1), ix+1)- else do c2 <- peekElemOff p (ix+1)- return (unsafeChr ((fromIntegral c1 - 0xd800)*0x400 +- (fromIntegral c2 - 0xdc00) + 0x10000), ix+2)-#else-readCharBufPtr p ix = do c <- peekElemOff (castPtr p) ix; return (c, ix+1)-#endif--{-# INLINE writeCharBufPtr #-}-writeCharBufPtr :: Ptr CharBufElem -> Int -> Char -> IO Int-#ifdef CHARBUF_UTF16-writeCharBufPtr p ix ch- | c < 0x10000 = do pokeElemOff p ix (fromIntegral c)- return (ix+1)- | otherwise = do let c' = c - 0x10000- pokeElemOff p ix (fromIntegral (c' `div` 0x400 + 0xd800))- pokeElemOff p (ix+1) (fromIntegral (c' `mod` 0x400 + 0xdc00))- return (ix+2)- where- c = ord ch-#else-writeCharBufPtr p ix ch = do pokeElemOff (castPtr p) ix ch; return (ix+1)-#endif--charSize :: Int-#ifdef CHARBUF_UTF16-charSize = 2-#else-charSize = 4-#endif---- ------------------------------------------------------------------------------ Buffers---- | A mutable array of bytes that can be passed to foreign functions.------ The buffer is represented by a record, where the record contains--- the raw buffer and the start/end points of the filled portion. The--- buffer contents itself is mutable, but the rest of the record is--- immutable. This is a slightly odd mix, but it turns out to be--- quite practical: by making all the buffer metadata immutable, we--- can have operations on buffer metadata outside of the IO monad.------ The "live" elements of the buffer are those between the 'bufL' and--- 'bufR' offsets. In an empty buffer, 'bufL' is equal to 'bufR', but--- they might not be zero: for exmaple, the buffer might correspond to--- a memory-mapped file and in which case 'bufL' will point to the--- next location to be written, which is not necessarily the beginning--- of the file.-data Buffer e- = Buffer {- bufRaw :: !(RawBuffer e),- bufState :: BufferState,- bufSize :: !Int, -- in elements, not bytes- bufL :: !Int, -- offset of first item in the buffer- bufR :: !Int -- offset of last item + 1- }--#ifdef CHARBUF_UTF16-type CharBuffer = Buffer Word16-#else-type CharBuffer = Buffer Char-#endif--data BufferState = ReadBuffer | WriteBuffer deriving (Eq)--withBuffer :: Buffer e -> (Ptr e -> IO a) -> IO a-withBuffer Buffer{ bufRaw=raw } f = withForeignPtr (castForeignPtr raw) f--withRawBuffer :: RawBuffer e -> (Ptr e -> IO a) -> IO a-withRawBuffer raw f = withForeignPtr (castForeignPtr raw) f--isEmptyBuffer :: Buffer e -> Bool-isEmptyBuffer Buffer{ bufL=l, bufR=r } = l == r--isFullBuffer :: Buffer e -> Bool-isFullBuffer Buffer{ bufR=w, bufSize=s } = s == w---- if a Char buffer does not have room for a surrogate pair, it is "full"-isFullCharBuffer :: Buffer e -> Bool-#ifdef CHARBUF_UTF16-isFullCharBuffer buf = bufferAvailable buf < 2-#else-isFullCharBuffer = isFullBuffer-#endif--isWriteBuffer :: Buffer e -> Bool-isWriteBuffer buf = case bufState buf of- WriteBuffer -> True- ReadBuffer -> False--bufferElems :: Buffer e -> Int-bufferElems Buffer{ bufR=w, bufL=r } = w - r--bufferAvailable :: Buffer e -> Int-bufferAvailable Buffer{ bufR=w, bufSize=s } = s - w--bufferRemove :: Int -> Buffer e -> Buffer e-bufferRemove i buf@Buffer{ bufL=r } = bufferAdjustL (r+i) buf--bufferAdjustL :: Int -> Buffer e -> Buffer e-bufferAdjustL l buf@Buffer{ bufR=w }- | l == w = buf{ bufL=0, bufR=0 }- | otherwise = buf{ bufL=l, bufR=w }--bufferAdd :: Int -> Buffer e -> Buffer e-bufferAdd i buf@Buffer{ bufR=w } = buf{ bufR=w+i }--emptyBuffer :: RawBuffer e -> Int -> BufferState -> Buffer e-emptyBuffer raw sz state = - Buffer{ bufRaw=raw, bufState=state, bufR=0, bufL=0, bufSize=sz }--newByteBuffer :: Int -> BufferState -> IO (Buffer Word8)-newByteBuffer c st = newBuffer c c st--newCharBuffer :: Int -> BufferState -> IO CharBuffer-newCharBuffer c st = newBuffer (c * charSize) c st--newBuffer :: Int -> Int -> BufferState -> IO (Buffer e)-newBuffer bytes sz state = do- fp <- mallocForeignPtrBytes bytes- return (emptyBuffer fp sz state)---- | slides the contents of the buffer to the beginning-slideContents :: Buffer Word8 -> IO (Buffer Word8)-slideContents buf@Buffer{ bufL=l, bufR=r, bufRaw=raw } = do- let elems = r - l- withRawBuffer raw $ \p ->- do _ <- memcpy p (p `plusPtr` l) (fromIntegral elems)- return ()- return buf{ bufL=0, bufR=elems }--foreign import ccall unsafe "memcpy"- memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr ())--summaryBuffer :: Buffer a -> String-summaryBuffer buf = "buf" ++ show (bufSize buf) ++ "(" ++ show (bufL buf) ++ "-" ++ show (bufR buf) ++ ")"---- INVARIANTS on Buffers:--- * r <= w--- * if r == w, and the buffer is for reading, then r == 0 && w == 0--- * a write buffer is never full. If an operation--- fills up the buffer, it will always flush it before --- returning.--- * a read buffer may be full as a result of hLookAhead. In normal--- operation, a read buffer always has at least one character of space.--checkBuffer :: Buffer a -> IO ()-checkBuffer buf@Buffer{ bufState = state, bufL=r, bufR=w, bufSize=size } = do- check buf (- size > 0- && r <= w- && w <= size- && ( r /= w || state == WriteBuffer || (r == 0 && w == 0) )- && ( state /= WriteBuffer || w < size ) -- write buffer is never full- )--check :: Buffer a -> Bool -> IO ()-check _ True = return ()-check buf False = error ("buffer invariant violation: " ++ summaryBuffer buf)-
@@ -1,127 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.BufferedIO--- Copyright : (c) The University of Glasgow 2008--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Class of buffered IO devices-----------------------------------------------------------------------------------module GHC.IO.BufferedIO (- BufferedIO(..),- readBuf, readBufNonBlocking, writeBuf, writeBufNonBlocking- ) where--import GHC.Base-import GHC.Ptr-import Data.Word-import GHC.Num-import Data.Maybe-import GHC.IO.Device as IODevice-import GHC.IO.Device as RawIO-import GHC.IO.Buffer---- | The purpose of 'BufferedIO' is to provide a common interface for I/O--- devices that can read and write data through a buffer. Devices that--- implement 'BufferedIO' include ordinary files, memory-mapped files,--- and bytestrings. The underlying device implementing a 'Handle' must--- provide 'BufferedIO'.----class BufferedIO dev where- -- | allocate a new buffer. The size of the buffer is at the- -- discretion of the device; e.g. for a memory-mapped file the- -- buffer will probably cover the entire file.- newBuffer :: dev -> BufferState -> IO (Buffer Word8)-- -- | reads bytes into the buffer, blocking if there are no bytes- -- available. Returns the number of bytes read (zero indicates- -- end-of-file), and the new buffer.- fillReadBuffer :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)-- -- | reads bytes into the buffer without blocking. Returns the- -- number of bytes read (Nothing indicates end-of-file), and the new- -- buffer.- fillReadBuffer0 :: dev -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)-- -- | Prepares an empty write buffer. This lets the device decide- -- how to set up a write buffer: the buffer may need to point to a- -- specific location in memory, for example. This is typically used- -- by the client when switching from reading to writing on a- -- buffered read/write device.- --- -- There is no corresponding operation for read buffers, because before- -- reading the client will always call 'fillReadBuffer'.- emptyWriteBuffer :: dev -> Buffer Word8 -> IO (Buffer Word8)- emptyWriteBuffer _dev buf - = return buf{ bufL=0, bufR=0, bufState = WriteBuffer }-- -- | Flush all the data from the supplied write buffer out to the device.- -- The returned buffer should be empty, and ready for writing.- flushWriteBuffer :: dev -> Buffer Word8 -> IO (Buffer Word8)-- -- | Flush data from the supplied write buffer out to the device- -- without blocking. Returns the number of bytes written and the- -- remaining buffer.- flushWriteBuffer0 :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)---- for an I/O device, these operations will perform reading/writing--- to/from the device.---- for a memory-mapped file, the buffer will be the whole file in--- memory. fillReadBuffer sets the pointers to encompass the whole--- file, and flushWriteBuffer needs to do no I/O. A memory-mapped--- file has to maintain its own file pointer.---- for a bytestring, again the buffer should match the bytestring in--- memory.---- ------------------------------------------------------------------------------ Low-level read/write to/from buffers---- These operations make it easy to implement an instance of 'BufferedIO'--- for an object that supports 'RawIO'.--readBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)-readBuf dev bbuf = do- let bytes = bufferAvailable bbuf- res <- withBuffer bbuf $ \ptr ->- RawIO.read dev (ptr `plusPtr` bufR bbuf) bytes- return (res, bbuf{ bufR = bufR bbuf + res })- -- zero indicates end of file--readBufNonBlocking :: RawIO dev => dev -> Buffer Word8- -> IO (Maybe Int, -- Nothing ==> end of file- -- Just n ==> n bytes were read (n>=0)- Buffer Word8)-readBufNonBlocking dev bbuf = do- let bytes = bufferAvailable bbuf- res <- withBuffer bbuf $ \ptr ->- IODevice.readNonBlocking dev (ptr `plusPtr` bufR bbuf) bytes- case res of- Nothing -> return (Nothing, bbuf)- Just n -> return (Just n, bbuf{ bufR = bufR bbuf + n })--writeBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Buffer Word8)-writeBuf dev bbuf = do- let bytes = bufferElems bbuf- withBuffer bbuf $ \ptr ->- IODevice.write dev (ptr `plusPtr` bufL bbuf) bytes- return bbuf{ bufL=0, bufR=0 }---- XXX ToDo-writeBufNonBlocking :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)-writeBufNonBlocking dev bbuf = do- let bytes = bufferElems bbuf- res <- withBuffer bbuf $ \ptr ->- IODevice.writeNonBlocking dev (ptr `plusPtr` bufL bbuf) bytes- return (res, bufferAdjustL res bbuf)-
@@ -1,179 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, BangPatterns #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Device--- Copyright : (c) The University of Glasgow, 1994-2008--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Type classes for I/O providers.-----------------------------------------------------------------------------------module GHC.IO.Device (- RawIO(..),- IODevice(..),- IODeviceType(..),- SeekMode(..)- ) where --#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Word-import GHC.Arr-import GHC.Enum-import GHC.Read-import GHC.Show-import GHC.Ptr-import Data.Maybe-import GHC.Num-import GHC.IO-import {-# SOURCE #-} GHC.IO.Exception ( unsupportedOperation )-#endif-#ifdef __NHC__-import Foreign-import Ix-import Control.Exception.Base-unsupportedOperation = userError "unsupported operation"-#endif---- | A low-level I/O provider where the data is bytes in memory.-class RawIO a where- -- | Read up to the specified number of bytes, returning the number- -- of bytes actually read. This function should only block if there- -- is no data available. If there is not enough data available,- -- then the function should just return the available data. A return- -- value of zero indicates that the end of the data stream (e.g. end- -- of file) has been reached.- read :: a -> Ptr Word8 -> Int -> IO Int-- -- | Read up to the specified number of bytes, returning the number- -- of bytes actually read, or 'Nothing' if the end of the stream has- -- been reached.- readNonBlocking :: a -> Ptr Word8 -> Int -> IO (Maybe Int)-- -- | Write the specified number of bytes.- write :: a -> Ptr Word8 -> Int -> IO ()-- -- | Write up to the specified number of bytes without blocking. Returns- -- the actual number of bytes written.- writeNonBlocking :: a -> Ptr Word8 -> Int -> IO Int----- | I/O operations required for implementing a 'Handle'.-class IODevice a where- -- | @ready dev write msecs@ returns 'True' if the device has data- -- to read (if @write@ is 'False') or space to write new data (if- -- @write@ is 'True'). @msecs@ specifies how long to wait, in- -- milliseconds.- -- - ready :: a -> Bool -> Int -> IO Bool-- -- | closes the device. Further operations on the device should- -- produce exceptions.- close :: a -> IO ()-- -- | returns 'True' if the device is a terminal or console.- isTerminal :: a -> IO Bool- isTerminal _ = return False-- -- | returns 'True' if the device supports 'seek' operations.- isSeekable :: a -> IO Bool- isSeekable _ = return False-- -- | seek to the specified position in the data.- seek :: a -> SeekMode -> Integer -> IO ()- seek _ _ _ = ioe_unsupportedOperation-- -- | return the current position in the data.- tell :: a -> IO Integer- tell _ = ioe_unsupportedOperation-- -- | return the size of the data.- getSize :: a -> IO Integer- getSize _ = ioe_unsupportedOperation-- -- | change the size of the data.- setSize :: a -> Integer -> IO () - setSize _ _ = ioe_unsupportedOperation-- -- | for terminal devices, changes whether characters are echoed on- -- the device.- setEcho :: a -> Bool -> IO ()- setEcho _ _ = ioe_unsupportedOperation-- -- | returns the current echoing status.- getEcho :: a -> IO Bool- getEcho _ = ioe_unsupportedOperation-- -- | some devices (e.g. terminals) support a "raw" mode where- -- characters entered are immediately made available to the program.- -- If available, this operations enables raw mode.- setRaw :: a -> Bool -> IO ()- setRaw _ _ = ioe_unsupportedOperation-- -- | returns the 'IODeviceType' corresponding to this device.- devType :: a -> IO IODeviceType-- -- | duplicates the device, if possible. The new device is expected- -- to share a file pointer with the original device (like Unix @dup@).- dup :: a -> IO a- dup _ = ioe_unsupportedOperation-- -- | @dup2 source target@ replaces the target device with the source- -- device. The target device is closed first, if necessary, and then- -- it is made into a duplicate of the first device (like Unix @dup2@).- dup2 :: a -> a -> IO a- dup2 _ _ = ioe_unsupportedOperation--ioe_unsupportedOperation :: IO a-ioe_unsupportedOperation = throwIO unsupportedOperation---- | Type of a device that can be used to back a--- 'GHC.IO.Handle.Handle' (see also 'GHC.IO.Handle.mkFileHandle'). The--- standard libraries provide creation of 'GHC.IO.Handle.Handle's via--- Posix file operations with file descriptors (see--- 'GHC.IO.Handle.FD.mkHandleFromFD') with FD being the underlying--- 'GHC.IO.Device.IODevice' instance.------ Users may provide custom instances of 'GHC.IO.Device.IODevice'--- which are expected to conform the following rules:--data IODeviceType- = Directory -- ^ The standard libraries do not have direct support- -- for this device type, but a user implementation is- -- expected to provide a list of file names in- -- the directory, in any order, separated by @'\0'@- -- characters, excluding the @"."@ and @".."@ names. See- -- also 'System.Directory.getDirectoryContents'. Seek- -- operations are not supported on directories (other- -- than to the zero position).- | Stream -- ^ A duplex communications channel (results in- -- creation of a duplex 'GHC.IO.Handle.Handle'). The- -- standard libraries use this device type when- -- creating 'GHC.IO.Handle.Handle's for open sockets.- | RegularFile -- ^ A file that may be read or written, and also- -- may be seekable.- | RawDevice -- ^ A "raw" (disk) device which supports block binary- -- read and write operations and may be seekable only- -- to positions of certain granularity (block-- -- aligned).- deriving (Eq)---- -------------------------------------------------------------------------------- SeekMode type---- | A mode that determines the effect of 'hSeek' @hdl mode i@.-data SeekMode- = AbsoluteSeek -- ^ the position of @hdl@ is set to @i@.- | RelativeSeek -- ^ the position of @hdl@ is set to offset @i@- -- from the current position.- | SeekFromEnd -- ^ the position of @hdl@ is set to offset @i@- -- from the end of the file.- deriving (Eq, Ord, Ix, Enum, Read, Show)-
@@ -1,233 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, PatternGuards #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding--- Copyright : (c) The University of Glasgow, 2008-2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Text codecs for I/O-----------------------------------------------------------------------------------module GHC.IO.Encoding (- BufferCodec(..), TextEncoding(..), TextEncoder, TextDecoder, CodingProgress(..),- latin1, latin1_encode, latin1_decode,- utf8, utf8_bom,- utf16, utf16le, utf16be,- utf32, utf32le, utf32be, - initLocaleEncoding,- getLocaleEncoding, getFileSystemEncoding, getForeignEncoding,- setLocaleEncoding, setFileSystemEncoding, setForeignEncoding,- char8,- mkTextEncoding,- ) where--import GHC.Base-import GHC.IO.Exception-import GHC.IO.Buffer-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types-#if !defined(mingw32_HOST_OS)-import qualified GHC.IO.Encoding.Iconv as Iconv-#else-import qualified GHC.IO.Encoding.CodePage as CodePage-import Text.Read (reads)-#endif-import qualified GHC.IO.Encoding.Latin1 as Latin1-import qualified GHC.IO.Encoding.UTF8 as UTF8-import qualified GHC.IO.Encoding.UTF16 as UTF16-import qualified GHC.IO.Encoding.UTF32 as UTF32-import GHC.Word--import Data.IORef-import Data.Char (toUpper)-import Data.List-import Data.Maybe-import System.IO.Unsafe (unsafePerformIO)---- --------------------------------------------------------------------------------- | The Latin1 (ISO8859-1) encoding. This encoding maps bytes--- directly to the first 256 Unicode code points, and is thus not a--- complete Unicode encoding. An attempt to write a character greater than--- '\255' to a 'Handle' using the 'latin1' encoding will result in an error.-latin1 :: TextEncoding-latin1 = Latin1.latin1_checked---- | The UTF-8 Unicode encoding-utf8 :: TextEncoding-utf8 = UTF8.utf8---- | The UTF-8 Unicode encoding, with a byte-order-mark (BOM; the byte--- sequence 0xEF 0xBB 0xBF). This encoding behaves like 'utf8',--- except that on input, the BOM sequence is ignored at the beginning--- of the stream, and on output, the BOM sequence is prepended.------ The byte-order-mark is strictly unnecessary in UTF-8, but is--- sometimes used to identify the encoding of a file.----utf8_bom :: TextEncoding-utf8_bom = UTF8.utf8_bom---- | The UTF-16 Unicode encoding (a byte-order-mark should be used to--- indicate endianness).-utf16 :: TextEncoding-utf16 = UTF16.utf16---- | The UTF-16 Unicode encoding (litte-endian)-utf16le :: TextEncoding-utf16le = UTF16.utf16le---- | The UTF-16 Unicode encoding (big-endian)-utf16be :: TextEncoding-utf16be = UTF16.utf16be---- | The UTF-32 Unicode encoding (a byte-order-mark should be used to--- indicate endianness).-utf32 :: TextEncoding-utf32 = UTF32.utf32---- | The UTF-32 Unicode encoding (litte-endian)-utf32le :: TextEncoding-utf32le = UTF32.utf32le---- | The UTF-32 Unicode encoding (big-endian)-utf32be :: TextEncoding-utf32be = UTF32.utf32be---- | The Unicode encoding of the current locale-getLocaleEncoding :: IO TextEncoding---- | The Unicode encoding of the current locale, but allowing arbitrary--- undecodable bytes to be round-tripped through it.------ This 'TextEncoding' is used to decode and encode command line arguments--- and environment variables on non-Windows platforms.------ On Windows, this encoding *should not* be used if possible because--- the use of code pages is deprecated: Strings should be retrieved--- via the "wide" W-family of UTF-16 APIs instead-getFileSystemEncoding :: IO TextEncoding---- | The Unicode encoding of the current locale, but where undecodable--- bytes are replaced with their closest visual match. Used for--- the 'CString' marshalling functions in "Foreign.C.String"-getForeignEncoding :: IO TextEncoding--setLocaleEncoding, setFileSystemEncoding, setForeignEncoding :: TextEncoding -> IO ()-(getLocaleEncoding, setLocaleEncoding) = mkGlobal initLocaleEncoding-(getFileSystemEncoding, setFileSystemEncoding) = mkGlobal initFileSystemEncoding-(getForeignEncoding, setForeignEncoding) = mkGlobal initForeignEncoding--mkGlobal :: a -> (IO a, a -> IO ())-mkGlobal x = unsafePerformIO $ do- x_ref <- newIORef x- return (readIORef x_ref, writeIORef x_ref)--initLocaleEncoding, initFileSystemEncoding, initForeignEncoding :: TextEncoding--#if !defined(mingw32_HOST_OS)--- It is rather important that we don't just call Iconv.mkIconvEncoding here--- because some iconvs (in particular GNU iconv) will brokenly UTF-8 encode--- lone surrogates without complaint.------ By going through our Haskell implementations of those encodings, we are--- guaranteed to catch such errors.------ FIXME: this is not a complete solution because if the locale encoding is one--- which we don't have a Haskell-side decoder for, iconv might still ignore the--- lone surrogate in the input.-initLocaleEncoding = unsafePerformIO $ mkTextEncoding' ErrorOnCodingFailure Iconv.localeEncodingName-initFileSystemEncoding = unsafePerformIO $ mkTextEncoding' RoundtripFailure Iconv.localeEncodingName-initForeignEncoding = unsafePerformIO $ mkTextEncoding' IgnoreCodingFailure Iconv.localeEncodingName-#else-initLocaleEncoding = CodePage.localeEncoding-initFileSystemEncoding = CodePage.mkLocaleEncoding RoundtripFailure-initForeignEncoding = CodePage.mkLocaleEncoding IgnoreCodingFailure-#endif---- | An encoding in which Unicode code points are translated to bytes--- by taking the code point modulo 256. When decoding, bytes are--- translated directly into the equivalent code point.------ This encoding never fails in either direction. However, encoding--- discards information, so encode followed by decode is not the--- identity.-char8 :: TextEncoding-char8 = Latin1.latin1---- | Look up the named Unicode encoding. May fail with ------ * 'isDoesNotExistError' if the encoding is unknown------ The set of known encodings is system-dependent, but includes at least:------ * @UTF-8@------ * @UTF-16@, @UTF-16BE@, @UTF-16LE@------ * @UTF-32@, @UTF-32BE@, @UTF-32LE@------ On systems using GNU iconv (e.g. Linux), there is additional--- notation for specifying how illegal characters are handled:------ * a suffix of @\/\/IGNORE@, e.g. @UTF-8\/\/IGNORE@, will cause --- all illegal sequences on input to be ignored, and on output--- will drop all code points that have no representation in the--- target encoding.------ * a suffix of @\/\/TRANSLIT@ will choose a replacement character--- for illegal sequences or code points.------ On Windows, you can access supported code pages with the prefix--- @CP@; for example, @\"CP1250\"@.----mkTextEncoding :: String -> IO TextEncoding-mkTextEncoding e = case mb_coding_failure_mode of- Nothing -> unknownEncodingErr e- Just cfm -> mkTextEncoding' cfm enc- where- -- The only problem with actually documenting //IGNORE and //TRANSLIT as- -- supported suffixes is that they are not necessarily supported with non-GNU iconv- (enc, suffix) = span (/= '/') e- mb_coding_failure_mode = case suffix of- "" -> Just ErrorOnCodingFailure- "//IGNORE" -> Just IgnoreCodingFailure- "//TRANSLIT" -> Just TransliterateCodingFailure- "//ROUNDTRIP" -> Just RoundtripFailure- _ -> Nothing--mkTextEncoding' :: CodingFailureMode -> String -> IO TextEncoding-mkTextEncoding' cfm enc = case [toUpper c | c <- enc, c /= '-'] of- "UTF8" -> return $ UTF8.mkUTF8 cfm- "UTF16" -> return $ UTF16.mkUTF16 cfm- "UTF16LE" -> return $ UTF16.mkUTF16le cfm- "UTF16BE" -> return $ UTF16.mkUTF16be cfm- "UTF32" -> return $ UTF32.mkUTF32 cfm- "UTF32LE" -> return $ UTF32.mkUTF32le cfm- "UTF32BE" -> return $ UTF32.mkUTF32be cfm-#if defined(mingw32_HOST_OS)- 'C':'P':n | [(cp,"")] <- reads n -> return $ CodePage.mkCodePageEncoding cfm cp- _ -> unknownEncodingErr (enc ++ codingFailureModeSuffix cfm)-#else- _ -> Iconv.mkIconvEncoding cfm enc-#endif--latin1_encode :: CharBuffer -> Buffer Word8 -> IO (CharBuffer, Buffer Word8)-latin1_encode input output = fmap (\(_why,input',output') -> (input',output')) $ Latin1.latin1_encode input output -- unchecked, used for char8---latin1_encode = unsafePerformIO $ do mkTextEncoder Iconv.latin1 >>= return.encode--latin1_decode :: Buffer Word8 -> CharBuffer -> IO (Buffer Word8, CharBuffer)-latin1_decode input output = fmap (\(_why,input',output') -> (input',output')) $ Latin1.latin1_decode input output---latin1_decode = unsafePerformIO $ do mkTextDecoder Iconv.latin1 >>= return.encode--unknownEncodingErr :: String -> IO a -unknownEncodingErr e = ioException (IOError Nothing NoSuchThing "mkTextEncoding"- ("unknown encoding:" ++ e) Nothing Nothing)
@@ -1,10 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.IO.Encoding where--import GHC.IO (IO)-import GHC.IO.Encoding.Types--getLocaleEncoding, getFileSystemEncoding, getForeignEncoding :: IO TextEncoding-
@@ -1,172 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, BangPatterns, ForeignFunctionInterface, NoImplicitPrelude,- NondecreasingIndentation, MagicHash #-}--module GHC.IO.Encoding.CodePage(-#if !defined(mingw32_HOST_OS)- ) where-#else- codePageEncoding, mkCodePageEncoding,- localeEncoding, mkLocaleEncoding- ) where--import GHC.Base-import GHC.Show-import GHC.Num-import GHC.Enum-import GHC.Word-import GHC.IO (unsafePerformIO)-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types-import GHC.IO.Buffer-import Data.Bits-import Data.Maybe-import Data.List (lookup)--import GHC.IO.Encoding.CodePage.Table--import GHC.IO.Encoding.Latin1 (mkLatin1)-import GHC.IO.Encoding.UTF8 (mkUTF8)-import GHC.IO.Encoding.UTF16 (mkUTF16le, mkUTF16be)-import GHC.IO.Encoding.UTF32 (mkUTF32le, mkUTF32be)---- note CodePage = UInt which might not work on Win64. But the Win32 package--- also has this issue.-getCurrentCodePage :: IO Word32-getCurrentCodePage = do- conCP <- getConsoleCP- if conCP > 0- then return conCP- else getACP---- Since the Win32 package depends on base, we have to import these ourselves:-foreign import stdcall unsafe "windows.h GetConsoleCP"- getConsoleCP :: IO Word32--foreign import stdcall unsafe "windows.h GetACP"- getACP :: IO Word32--{-# NOINLINE currentCodePage #-}-currentCodePage :: Word32-currentCodePage = unsafePerformIO getCurrentCodePage--localeEncoding :: TextEncoding-localeEncoding = mkLocaleEncoding ErrorOnCodingFailure--mkLocaleEncoding :: CodingFailureMode -> TextEncoding-mkLocaleEncoding cfm = mkCodePageEncoding cfm currentCodePage---codePageEncoding :: Word32 -> TextEncoding-codePageEncoding = mkCodePageEncoding ErrorOnCodingFailure--mkCodePageEncoding :: CodingFailureMode -> Word32 -> TextEncoding-mkCodePageEncoding cfm 65001 = mkUTF8 cfm-mkCodePageEncoding cfm 1200 = mkUTF16le cfm-mkCodePageEncoding cfm 1201 = mkUTF16be cfm-mkCodePageEncoding cfm 12000 = mkUTF32le cfm-mkCodePageEncoding cfm 12001 = mkUTF32be cfm-mkCodePageEncoding cfm cp = maybe (mkLatin1 cfm) (buildEncoding cfm cp) (lookup cp codePageMap)--buildEncoding :: CodingFailureMode -> Word32 -> CodePageArrays -> TextEncoding-buildEncoding cfm cp SingleByteCP {decoderArray = dec, encoderArray = enc}- = TextEncoding {- textEncodingName = "CP" ++ show cp- , mkTextDecoder = return $ simpleCodec (recoverDecode cfm) $ decodeFromSingleByte dec- , mkTextEncoder = return $ simpleCodec (recoverEncode cfm) $ encodeToSingleByte enc- }--simpleCodec :: (Buffer from -> Buffer to -> IO (Buffer from, Buffer to))- -> (Buffer from -> Buffer to -> IO (CodingProgress, Buffer from, Buffer to))- -> BufferCodec from to ()-simpleCodec r f = BufferCodec {- encode = f,- recover = r,- close = return (),- getState = return (),- setState = return- }--decodeFromSingleByte :: ConvArray Char -> DecodeBuffer-decodeFromSingleByte convArr- input@Buffer { bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer { bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let- done why !ir !ow = return (why,- if ir==iw then input{ bufL=0, bufR=0}- else input{ bufL=ir},- output {bufR=ow})- loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- b <- readWord8Buf iraw ir- let c = lookupConv convArr b- if c=='\0' && b /= 0 then invalid else do- ow' <- writeCharBuf oraw ow c- loop (ir+1) ow'- where- invalid = done InvalidSequence ir ow- in loop ir0 ow0--encodeToSingleByte :: CompactArray Char Word8 -> EncodeBuffer-encodeToSingleByte CompactArray { encoderMax = maxChar,- encoderIndices = indices,- encoderValues = values }- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let- done why !ir !ow = return (why,- if ir==iw then input { bufL=0, bufR=0 }- else input { bufL=ir },- output {bufR=ow})- loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- case lookupCompact maxChar indices values c of- Nothing -> invalid- Just 0 | c /= '\0' -> invalid- Just b -> do- writeWord8Buf oraw ow b- loop ir' (ow+1)- where- invalid = done InvalidSequence ir ow- in- loop ir0 ow0-------------------------------------------------- Array access functions---- {-# INLINE lookupConv #-}-lookupConv :: ConvArray Char -> Word8 -> Char-lookupConv a = indexChar a . fromEnum--{-# INLINE lookupCompact #-}-lookupCompact :: Char -> ConvArray Int -> ConvArray Word8 -> Char -> Maybe Word8-lookupCompact maxVal indexes values x- | x > maxVal = Nothing- | otherwise = Just $ indexWord8 values $ j + (i .&. mask)- where- i = fromEnum x- mask = (1 `shiftL` n) - 1- k = i `shiftR` n- j = indexInt indexes k- n = blockBitSize--{-# INLINE indexInt #-}-indexInt :: ConvArray Int -> Int -> Int-indexInt (ConvArray p) (I# i) = I# (indexInt16OffAddr# p i)--{-# INLINE indexWord8 #-}-indexWord8 :: ConvArray Word8 -> Int -> Word8-indexWord8 (ConvArray p) (I# i) = W8# (indexWord8OffAddr# p i)--{-# INLINE indexChar #-}-indexChar :: ConvArray Char -> Int -> Char-indexChar (ConvArray p) (I# i) = C# (chr# (indexInt16OffAddr# p i))--#endif-
@@ -1,432 +0,0 @@-{-# LANGUAGE CPP, MagicHash, NoImplicitPrelude #-}--- Do not edit this file directly!--- It was generated by the MakeTable.hs script using the files below.--- To regenerate it, run "make" in ../../../../codepages/--- --- Files:--- CP037.TXT--- CP1026.TXT--- CP1250.TXT--- CP1251.TXT--- CP1252.TXT--- CP1253.TXT--- CP1254.TXT--- CP1255.TXT--- CP1256.TXT--- CP1257.TXT--- CP1258.TXT--- CP437.TXT--- CP500.TXT--- CP737.TXT--- CP775.TXT--- CP850.TXT--- CP852.TXT--- CP855.TXT--- CP857.TXT--- CP860.TXT--- CP861.TXT--- CP862.TXT--- CP863.TXT--- CP864.TXT--- CP865.TXT--- CP866.TXT--- CP869.TXT--- CP874.TXT--- CP875.TXT-module GHC.IO.Encoding.CodePage.Table where--import GHC.Prim-import GHC.Base-import GHC.Word-data ConvArray a = ConvArray Addr#-data CompactArray a b = CompactArray {- encoderMax :: !a,- encoderIndices :: !(ConvArray Int),- encoderValues :: !(ConvArray b)- }--data CodePageArrays = SingleByteCP {- decoderArray :: !(ConvArray Char),- encoderArray :: !(CompactArray Char Word8)- }--blockBitSize :: Int-blockBitSize = 6-codePageMap :: [(Word32, CodePageArrays)]-codePageMap = [- (37, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x9c\x0\x9\x0\x86\x0\x7f\x0\x97\x0\x8d\x0\x8e\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x9d\x0\x85\x0\x8\x0\x87\x0\x18\x0\x19\x0\x92\x0\x8f\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x80\x0\x81\x0\x82\x0\x83\x0\x84\x0\xa\x0\x17\x0\x1b\x0\x88\x0\x89\x0\x8a\x0\x8b\x0\x8c\x0\x5\x0\x6\x0\x7\x0\x90\x0\x91\x0\x16\x0\x93\x0\x94\x0\x95\x0\x96\x0\x4\x0\x98\x0\x99\x0\x9a\x0\x9b\x0\x14\x0\x15\x0\x9e\x0\x1a\x0\x20\x0\xa0\x0\xe2\x0\xe4\x0\xe0\x0\xe1\x0\xe3\x0\xe5\x0\xe7\x0\xf1\x0\xa2\x0\x2e\x0\x3c\x0\x28\x0\x2b\x0\x7c\x0\x26\x0\xe9\x0\xea\x0\xeb\x0\xe8\x0\xed\x0\xee\x0\xef\x0\xec\x0\xdf\x0\x21\x0\x24\x0\x2a\x0\x29\x0\x3b\x0\xac\x0\x2d\x0\x2f\x0\xc2\x0\xc4\x0\xc0\x0\xc1\x0\xc3\x0\xc5\x0\xc7\x0\xd1\x0\xa6\x0\x2c\x0\x25\x0\x5f\x0\x3e\x0\x3f\x0\xf8\x0\xc9\x0\xca\x0\xcb\x0\xc8\x0\xcd\x0\xce\x0\xcf\x0\xcc\x0\x60\x0\x3a\x0\x23\x0\x40\x0\x27\x0\x3d\x0\x22\x0\xd8\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\xab\x0\xbb\x0\xf0\x0\xfd\x0\xfe\x0\xb1\x0\xb0\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\xaa\x0\xba\x0\xe6\x0\xb8\x0\xc6\x0\xa4\x0\xb5\x0\x7e\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\xa1\x0\xbf\x0\xd0\x0\xdd\x0\xde\x0\xae\x0\x5e\x0\xa3\x0\xa5\x0\xb7\x0\xa9\x0\xa7\x0\xb6\x0\xbc\x0\xbd\x0\xbe\x0\x5b\x0\x5d\x0\xaf\x0\xa8\x0\xb4\x0\xd7\x0\x7b\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\xad\x0\xf4\x0\xf6\x0\xf2\x0\xf3\x0\xf5\x0\x7d\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\xb9\x0\xfb\x0\xfc\x0\xf9\x0\xfa\x0\xff\x0\x5c\x0\xf7\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\xb2\x0\xd4\x0\xd6\x0\xd2\x0\xd3\x0\xd5\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\xb3\x0\xdb\x0\xdc\x0\xd9\x0\xda\x0\x9f\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x37\x2d\x2e\x2f\x16\x5\x25\xb\xc\xd\xe\xf\x10\x11\x12\x13\x3c\x3d\x32\x26\x18\x19\x3f\x27\x1c\x1d\x1e\x1f\x40\x5a\x7f\x7b\x5b\x6c\x50\x7d\x4d\x5d\x5c\x4e\x6b\x60\x4b\x61\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\x7a\x5e\x4c\x7e\x6e\x6f\x7c\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xba\xe0\xbb\xb0\x6d\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96\x97\x98\x99\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xc0\x4f\xd0\xa1\x7\x20\x21\x22\x23\x24\x15\x6\x17\x28\x29\x2a\x2b\x2c\x9\xa\x1b\x30\x31\x1a\x33\x34\x35\x36\x8\x38\x39\x3a\x3b\x4\x14\x3e\xff\x41\xaa\x4a\xb1\x9f\xb2\x6a\xb5\xbd\xb4\x9a\x8a\x5f\xca\xaf\xbc\x90\x8f\xea\xfa\xbe\xa0\xb6\xb3\x9d\xda\x9b\x8b\xb7\xb8\xb9\xab\x64\x65\x62\x66\x63\x67\x9e\x68\x74\x71\x72\x73\x78\x75\x76\x77\xac\x69\xed\xee\xeb\xef\xec\xbf\x80\xfd\xfe\xfb\xfc\xad\xae\x59\x44\x45\x42\x46\x43\x47\x9c\x48\x54\x51\x52\x53\x58\x55\x56\x57\x8c\x49\xcd\xce\xcb\xcf\xcc\xe1\x70\xdd\xde\xdb\xdc\x8d\x8e\xdf"#- , encoderMax = '\255'- }-- }- )-- ,- (1026, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x9c\x0\x9\x0\x86\x0\x7f\x0\x97\x0\x8d\x0\x8e\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x9d\x0\x85\x0\x8\x0\x87\x0\x18\x0\x19\x0\x92\x0\x8f\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x80\x0\x81\x0\x82\x0\x83\x0\x84\x0\xa\x0\x17\x0\x1b\x0\x88\x0\x89\x0\x8a\x0\x8b\x0\x8c\x0\x5\x0\x6\x0\x7\x0\x90\x0\x91\x0\x16\x0\x93\x0\x94\x0\x95\x0\x96\x0\x4\x0\x98\x0\x99\x0\x9a\x0\x9b\x0\x14\x0\x15\x0\x9e\x0\x1a\x0\x20\x0\xa0\x0\xe2\x0\xe4\x0\xe0\x0\xe1\x0\xe3\x0\xe5\x0\x7b\x0\xf1\x0\xc7\x0\x2e\x0\x3c\x0\x28\x0\x2b\x0\x21\x0\x26\x0\xe9\x0\xea\x0\xeb\x0\xe8\x0\xed\x0\xee\x0\xef\x0\xec\x0\xdf\x0\x1e\x1\x30\x1\x2a\x0\x29\x0\x3b\x0\x5e\x0\x2d\x0\x2f\x0\xc2\x0\xc4\x0\xc0\x0\xc1\x0\xc3\x0\xc5\x0\x5b\x0\xd1\x0\x5f\x1\x2c\x0\x25\x0\x5f\x0\x3e\x0\x3f\x0\xf8\x0\xc9\x0\xca\x0\xcb\x0\xc8\x0\xcd\x0\xce\x0\xcf\x0\xcc\x0\x31\x1\x3a\x0\xd6\x0\x5e\x1\x27\x0\x3d\x0\xdc\x0\xd8\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\xab\x0\xbb\x0\x7d\x0\x60\x0\xa6\x0\xb1\x0\xb0\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\xaa\x0\xba\x0\xe6\x0\xb8\x0\xc6\x0\xa4\x0\xb5\x0\xf6\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\xa1\x0\xbf\x0\x5d\x0\x24\x0\x40\x0\xae\x0\xa2\x0\xa3\x0\xa5\x0\xb7\x0\xa9\x0\xa7\x0\xb6\x0\xbc\x0\xbd\x0\xbe\x0\xac\x0\x7c\x0\xaf\x0\xa8\x0\xb4\x0\xd7\x0\xe7\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\xad\x0\xf4\x0\x7e\x0\xf2\x0\xf3\x0\xf5\x0\x1f\x1\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\xb9\x0\xfb\x0\x5c\x0\xf9\x0\xfa\x0\xff\x0\xfc\x0\xf7\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\xb2\x0\xd4\x0\x23\x0\xd2\x0\xd3\x0\xd5\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\xb3\x0\xdb\x0\x22\x0\xd9\x0\xda\x0\x9f\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x37\x2d\x2e\x2f\x16\x5\x25\xb\xc\xd\xe\xf\x10\x11\x12\x13\x3c\x3d\x32\x26\x18\x19\x3f\x27\x1c\x1d\x1e\x1f\x40\x4f\xfc\xec\xad\x6c\x50\x7d\x4d\x5d\x5c\x4e\x6b\x60\x4b\x61\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\x7a\x5e\x4c\x7e\x6e\x6f\xae\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\x68\xdc\xac\x5f\x6d\x8d\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96\x97\x98\x99\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\x48\xbb\x8c\xcc\x7\x20\x21\x22\x23\x24\x15\x6\x17\x28\x29\x2a\x2b\x2c\x9\xa\x1b\x30\x31\x1a\x33\x34\x35\x36\x8\x38\x39\x3a\x3b\x4\x14\x3e\xff\x41\xaa\xb0\xb1\x9f\xb2\x8e\xb5\xbd\xb4\x9a\x8a\xba\xca\xaf\xbc\x90\x8f\xea\xfa\xbe\xa0\xb6\xb3\x9d\xda\x9b\x8b\xb7\xb8\xb9\xab\x64\x65\x62\x66\x63\x67\x9e\x4a\x74\x71\x72\x73\x78\x75\x76\x77\x0\x69\xed\xee\xeb\xef\x7b\xbf\x80\xfd\xfe\xfb\x7f\x0\x0\x59\x44\x45\x42\x46\x43\x47\x9c\xc0\x54\x51\x52\x53\x58\x55\x56\x57\x0\x49\xcd\xce\xcb\xcf\xa1\xe1\x70\xdd\xde\xdb\xe0\x0\x0\xdf\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x5a\xd0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x5b\x79\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x7c\x6a"#- , encoderMax = '\351'- }-- }- )-- ,- (1250, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x0\x0\x1e\x20\x26\x20\x20\x20\x21\x20\x0\x0\x30\x20\x60\x1\x39\x20\x5a\x1\x64\x1\x7d\x1\x79\x1\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\x0\x0\x22\x21\x61\x1\x3a\x20\x5b\x1\x65\x1\x7e\x1\x7a\x1\xa0\x0\xc7\x2\xd8\x2\x41\x1\xa4\x0\x4\x1\xa6\x0\xa7\x0\xa8\x0\xa9\x0\x5e\x1\xab\x0\xac\x0\xad\x0\xae\x0\x7b\x1\xb0\x0\xb1\x0\xdb\x2\x42\x1\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xb8\x0\x5\x1\x5f\x1\xbb\x0\x3d\x1\xdd\x2\x3e\x1\x7c\x1\x54\x1\xc1\x0\xc2\x0\x2\x1\xc4\x0\x39\x1\x6\x1\xc7\x0\xc\x1\xc9\x0\x18\x1\xcb\x0\x1a\x1\xcd\x0\xce\x0\xe\x1\x10\x1\x43\x1\x47\x1\xd3\x0\xd4\x0\x50\x1\xd6\x0\xd7\x0\x58\x1\x6e\x1\xda\x0\x70\x1\xdc\x0\xdd\x0\x62\x1\xdf\x0\x55\x1\xe1\x0\xe2\x0\x3\x1\xe4\x0\x3a\x1\x7\x1\xe7\x0\xd\x1\xe9\x0\x19\x1\xeb\x0\x1b\x1\xed\x0\xee\x0\xf\x1\x11\x1\x44\x1\x48\x1\xf3\x0\xf4\x0\x51\x1\xf6\x0\xf7\x0\x59\x1\x6f\x1\xfa\x0\x71\x1\xfc\x0\xfd\x0\x63\x1\xd9\x2"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\xc0\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x0\x2\x80\x1\x40\x2\x80\x1\x80\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\x0\x0\xa4\x0\xa6\xa7\xa8\xa9\x0\xab\xac\xad\xae\x0\xb0\xb1\x0\x0\xb4\xb5\xb6\xb7\xb8\x0\x0\xbb\x0\x0\x0\x0\x0\xc1\xc2\x0\xc4\x0\x0\xc7\x0\xc9\x0\xcb\x0\xcd\xce\x0\x0\x0\x0\xd3\xd4\x0\xd6\xd7\x0\x0\xda\x0\xdc\xdd\x0\xdf\x0\xe1\xe2\x0\xe4\x0\x0\xe7\x0\xe9\x0\xeb\x0\xed\xee\x0\x0\x0\x0\xf3\xf4\x0\xf6\xf7\x0\x0\xfa\x0\xfc\xfd\x0\x0\x0\x0\xc3\xe3\xa5\xb9\xc6\xe6\x0\x0\x0\x0\xc8\xe8\xcf\xef\xd0\xf0\x0\x0\x0\x0\x0\x0\xca\xea\xcc\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc5\xe5\x0\x0\xbc\xbe\x0\x0\xa3\xb3\xd1\xf1\x0\x0\xd2\xf2\x0\x0\x0\x0\x0\x0\x0\xd5\xf5\x0\x0\xc0\xe0\x0\x0\xd8\xf8\x8c\x9c\x0\x0\xaa\xba\x8a\x9a\xde\xfe\x8d\x9d\x0\x0\x0\x0\x0\x0\x0\x0\xd9\xf9\xdb\xfb\x0\x0\x0\x0\x0\x0\x0\x8f\x9f\xaf\xbf\x8e\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa1\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa2\xff\x0\xb2\x0\xbd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1251, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\x2\x4\x3\x4\x1a\x20\x53\x4\x1e\x20\x26\x20\x20\x20\x21\x20\xac\x20\x30\x20\x9\x4\x39\x20\xa\x4\xc\x4\xb\x4\xf\x4\x52\x4\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\x0\x0\x22\x21\x59\x4\x3a\x20\x5a\x4\x5c\x4\x5b\x4\x5f\x4\xa0\x0\xe\x4\x5e\x4\x8\x4\xa4\x0\x90\x4\xa6\x0\xa7\x0\x1\x4\xa9\x0\x4\x4\xab\x0\xac\x0\xad\x0\xae\x0\x7\x4\xb0\x0\xb1\x0\x6\x4\x56\x4\x91\x4\xb5\x0\xb6\x0\xb7\x0\x51\x4\x16\x21\x54\x4\xbb\x0\x58\x4\x5\x4\x55\x4\x57\x4\x10\x4\x11\x4\x12\x4\x13\x4\x14\x4\x15\x4\x16\x4\x17\x4\x18\x4\x19\x4\x1a\x4\x1b\x4\x1c\x4\x1d\x4\x1e\x4\x1f\x4\x20\x4\x21\x4\x22\x4\x23\x4\x24\x4\x25\x4\x26\x4\x27\x4\x28\x4\x29\x4\x2a\x4\x2b\x4\x2c\x4\x2d\x4\x2e\x4\x2f\x4\x30\x4\x31\x4\x32\x4\x33\x4\x34\x4\x35\x4\x36\x4\x37\x4\x38\x4\x39\x4\x3a\x4\x3b\x4\x3c\x4\x3d\x4\x3e\x4\x3f\x4\x40\x4\x41\x4\x42\x4\x43\x4\x44\x4\x45\x4\x46\x4\x47\x4\x48\x4\x49\x4\x4a\x4\x4b\x4\x4c\x4\x4d\x4\x4e\x4\x4f\x4"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\x40\x1\x80\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x1\xc0\x0\x0\x2\xc0\x0\x40\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\x0\x0\xa4\x0\xa6\xa7\x0\xa9\x0\xab\xac\xad\xae\x0\xb0\xb1\x0\x0\x0\xb5\xb6\xb7\x0\x0\x0\xbb\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa8\x80\x81\xaa\xbd\xb2\xaf\xa3\x8a\x8c\x8e\x8d\x0\xa1\x8f\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x0\xb8\x90\x83\xba\xbe\xb3\xbf\xbc\x9a\x9c\x9e\x9d\x0\xa2\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa5\xb4\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xb9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1252, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x92\x1\x1e\x20\x26\x20\x20\x20\x21\x20\xc6\x2\x30\x20\x60\x1\x39\x20\x52\x1\x0\x0\x7d\x1\x0\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\xdc\x2\x22\x21\x61\x1\x3a\x20\x53\x1\x0\x0\x7e\x1\x78\x1\xa0\x0\xa1\x0\xa2\x0\xa3\x0\xa4\x0\xa5\x0\xa6\x0\xa7\x0\xa8\x0\xa9\x0\xaa\x0\xab\x0\xac\x0\xad\x0\xae\x0\xaf\x0\xb0\x0\xb1\x0\xb2\x0\xb3\x0\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xb8\x0\xb9\x0\xba\x0\xbb\x0\xbc\x0\xbd\x0\xbe\x0\xbf\x0\xc0\x0\xc1\x0\xc2\x0\xc3\x0\xc4\x0\xc5\x0\xc6\x0\xc7\x0\xc8\x0\xc9\x0\xca\x0\xcb\x0\xcc\x0\xcd\x0\xce\x0\xcf\x0\xd0\x0\xd1\x0\xd2\x0\xd3\x0\xd4\x0\xd5\x0\xd6\x0\xd7\x0\xd8\x0\xd9\x0\xda\x0\xdb\x0\xdc\x0\xdd\x0\xde\x0\xdf\x0\xe0\x0\xe1\x0\xe2\x0\xe3\x0\xe4\x0\xe5\x0\xe6\x0\xe7\x0\xe8\x0\xe9\x0\xea\x0\xeb\x0\xec\x0\xed\x0\xee\x0\xef\x0\xf0\x0\xf1\x0\xf2\x0\xf3\x0\xf4\x0\xf5\x0\xf6\x0\xf7\x0\xf8\x0\xf9\x0\xfa\x0\xfb\x0\xfc\x0\xfd\x0\xfe\x0\xff\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x0\x1\x40\x2\x0\x1\x80\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8c\x9c\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8a\x9a\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x8e\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x83\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1253, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x92\x1\x1e\x20\x26\x20\x20\x20\x21\x20\x0\x0\x30\x20\x0\x0\x39\x20\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\x0\x0\x22\x21\x0\x0\x3a\x20\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\x85\x3\x86\x3\xa3\x0\xa4\x0\xa5\x0\xa6\x0\xa7\x0\xa8\x0\xa9\x0\x0\x0\xab\x0\xac\x0\xad\x0\xae\x0\x15\x20\xb0\x0\xb1\x0\xb2\x0\xb3\x0\x84\x3\xb5\x0\xb6\x0\xb7\x0\x88\x3\x89\x3\x8a\x3\xbb\x0\x8c\x3\xbd\x0\x8e\x3\x8f\x3\x90\x3\x91\x3\x92\x3\x93\x3\x94\x3\x95\x3\x96\x3\x97\x3\x98\x3\x99\x3\x9a\x3\x9b\x3\x9c\x3\x9d\x3\x9e\x3\x9f\x3\xa0\x3\xa1\x3\x0\x0\xa3\x3\xa4\x3\xa5\x3\xa6\x3\xa7\x3\xa8\x3\xa9\x3\xaa\x3\xab\x3\xac\x3\xad\x3\xae\x3\xaf\x3\xb0\x3\xb1\x3\xb2\x3\xb3\x3\xb4\x3\xb5\x3\xb6\x3\xb7\x3\xb8\x3\xb9\x3\xba\x3\xbb\x3\xbc\x3\xbd\x3\xbe\x3\xbf\x3\xc0\x3\xc1\x3\xc2\x3\xc3\x3\xc4\x3\xc5\x3\xc6\x3\xc7\x3\xc8\x3\xc9\x3\xca\x3\xcb\x3\xcc\x3\xcd\x3\xce\x3\x0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x40\x1\x80\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x1\xc0\x0\x0\x2\xc0\x0\x40\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\x0\xa3\xa4\xa5\xa6\xa7\xa8\xa9\x0\xab\xac\xad\xae\x0\xb0\xb1\xb2\xb3\x0\xb5\xb6\xb7\x0\x0\x0\xbb\x0\xbd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x83\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xb4\xa1\xa2\x0\xb8\xb9\xba\x0\xbc\x0\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\x0\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\xaf\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1254, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x92\x1\x1e\x20\x26\x20\x20\x20\x21\x20\xc6\x2\x30\x20\x60\x1\x39\x20\x52\x1\x0\x0\x0\x0\x0\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\xdc\x2\x22\x21\x61\x1\x3a\x20\x53\x1\x0\x0\x0\x0\x78\x1\xa0\x0\xa1\x0\xa2\x0\xa3\x0\xa4\x0\xa5\x0\xa6\x0\xa7\x0\xa8\x0\xa9\x0\xaa\x0\xab\x0\xac\x0\xad\x0\xae\x0\xaf\x0\xb0\x0\xb1\x0\xb2\x0\xb3\x0\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xb8\x0\xb9\x0\xba\x0\xbb\x0\xbc\x0\xbd\x0\xbe\x0\xbf\x0\xc0\x0\xc1\x0\xc2\x0\xc3\x0\xc4\x0\xc5\x0\xc6\x0\xc7\x0\xc8\x0\xc9\x0\xca\x0\xcb\x0\xcc\x0\xcd\x0\xce\x0\xcf\x0\x1e\x1\xd1\x0\xd2\x0\xd3\x0\xd4\x0\xd5\x0\xd6\x0\xd7\x0\xd8\x0\xd9\x0\xda\x0\xdb\x0\xdc\x0\x30\x1\x5e\x1\xdf\x0\xe0\x0\xe1\x0\xe2\x0\xe3\x0\xe4\x0\xe5\x0\xe6\x0\xe7\x0\xe8\x0\xe9\x0\xea\x0\xeb\x0\xec\x0\xed\x0\xee\x0\xef\x0\x1f\x1\xf1\x0\xf2\x0\xf3\x0\xf4\x0\xf5\x0\xf6\x0\xf7\x0\xf8\x0\xf9\x0\xfa\x0\xfb\x0\xfc\x0\x31\x1\x5f\x1\xff\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\x0\x2\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\x40\x2\xc0\x1\x80\x2\xc0\x1\xc0\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\x0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\x0\x0\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\x0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\x0\x0\xff\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd0\xf0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdd\xfd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8c\x9c\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xde\xfe\x8a\x9a\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x83\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1255, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x92\x1\x1e\x20\x26\x20\x20\x20\x21\x20\xc6\x2\x30\x20\x0\x0\x39\x20\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\xdc\x2\x22\x21\x0\x0\x3a\x20\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\xa1\x0\xa2\x0\xa3\x0\xaa\x20\xa5\x0\xa6\x0\xa7\x0\xa8\x0\xa9\x0\xd7\x0\xab\x0\xac\x0\xad\x0\xae\x0\xaf\x0\xb0\x0\xb1\x0\xb2\x0\xb3\x0\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xb8\x0\xb9\x0\xf7\x0\xbb\x0\xbc\x0\xbd\x0\xbe\x0\xbf\x0\xb0\x5\xb1\x5\xb2\x5\xb3\x5\xb4\x5\xb5\x5\xb6\x5\xb7\x5\xb8\x5\xb9\x5\x0\x0\xbb\x5\xbc\x5\xbd\x5\xbe\x5\xbf\x5\xc0\x5\xc1\x5\xc2\x5\xc3\x5\xf0\x5\xf1\x5\xf2\x5\xf3\x5\xf4\x5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd0\x5\xd1\x5\xd2\x5\xd3\x5\xd4\x5\xd5\x5\xd6\x5\xd7\x5\xd8\x5\xd9\x5\xda\x5\xdb\x5\xdc\x5\xdd\x5\xde\x5\xdf\x5\xe0\x5\xe1\x5\xe2\x5\xe3\x5\xe4\x5\xe5\x5\xe6\x5\xe7\x5\xe8\x5\xe9\x5\xea\x5\x0\x0\x0\x0\xe\x20\xf\x20\x0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x40\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x1\x0\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x2\x0\x1\x80\x2\x0\x1\xc0\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\xa1\xa2\xa3\x0\xa5\xa6\xa7\xa8\xa9\x0\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\x0\xbb\xbc\xbd\xbe\xbf\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xaa\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xba\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x83\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\x0\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\x0\x0\x0\x0\x0\xd4\xd5\xd6\xd7\xd8\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfd\xfe\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa4\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1256, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x7e\x6\x1a\x20\x92\x1\x1e\x20\x26\x20\x20\x20\x21\x20\xc6\x2\x30\x20\x79\x6\x39\x20\x52\x1\x86\x6\x98\x6\x88\x6\xaf\x6\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\xa9\x6\x22\x21\x91\x6\x3a\x20\x53\x1\xc\x20\xd\x20\xba\x6\xa0\x0\xc\x6\xa2\x0\xa3\x0\xa4\x0\xa5\x0\xa6\x0\xa7\x0\xa8\x0\xa9\x0\xbe\x6\xab\x0\xac\x0\xad\x0\xae\x0\xaf\x0\xb0\x0\xb1\x0\xb2\x0\xb3\x0\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xb8\x0\xb9\x0\x1b\x6\xbb\x0\xbc\x0\xbd\x0\xbe\x0\x1f\x6\xc1\x6\x21\x6\x22\x6\x23\x6\x24\x6\x25\x6\x26\x6\x27\x6\x28\x6\x29\x6\x2a\x6\x2b\x6\x2c\x6\x2d\x6\x2e\x6\x2f\x6\x30\x6\x31\x6\x32\x6\x33\x6\x34\x6\x35\x6\x36\x6\xd7\x0\x37\x6\x38\x6\x39\x6\x3a\x6\x40\x6\x41\x6\x42\x6\x43\x6\xe0\x0\x44\x6\xe2\x0\x45\x6\x46\x6\x47\x6\x48\x6\xe7\x0\xe8\x0\xe9\x0\xea\x0\xeb\x0\x49\x6\x4a\x6\xee\x0\xef\x0\x4b\x6\x4c\x6\x4d\x6\x4e\x6\xf4\x0\x4f\x6\x50\x6\xf7\x0\x51\x6\xf9\x0\x52\x6\xfb\x0\xfc\x0\xe\x20\xf\x20\xd2\x6"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x40\x2\x80\x2\xc0\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x3\x0\x1\x40\x3\x0\x1\x80\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\x0\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\x0\xbb\xbc\xbd\xbe\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd7\x0\x0\x0\x0\x0\x0\x0\x0\xe0\x0\xe2\x0\x0\x0\x0\xe7\xe8\xe9\xea\xeb\x0\x0\xee\xef\x0\x0\x0\x0\xf4\x0\x0\xf7\x0\xf9\x0\xfb\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8c\x9c\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x83\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa1\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xba\x0\x0\x0\xbf\x0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\x0\x0\x0\x0\x0\xdc\xdd\xde\xdf\xe1\xe3\xe4\xe5\xe6\xec\xed\xf0\xf1\xf2\xf3\xf5\xf6\xf8\xfa\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8a\x0\x0\x0\x0\x81\x0\x0\x0\x0\x0\x0\x0\x8d\x0\x8f\x0\x0\x0\x0\x0\x0\x0\x0\x9a\x0\x0\x0\x0\x0\x0\x8e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x98\x0\x0\x0\x0\x0\x90\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\xaa\x0\x0\xc0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9d\x9e\xfd\xfe\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1257, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x0\x0\x1e\x20\x26\x20\x20\x20\x21\x20\x0\x0\x30\x20\x0\x0\x39\x20\x0\x0\xa8\x0\xc7\x2\xb8\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\x0\x0\x22\x21\x0\x0\x3a\x20\x0\x0\xaf\x0\xdb\x2\x0\x0\xa0\x0\x0\x0\xa2\x0\xa3\x0\xa4\x0\x0\x0\xa6\x0\xa7\x0\xd8\x0\xa9\x0\x56\x1\xab\x0\xac\x0\xad\x0\xae\x0\xc6\x0\xb0\x0\xb1\x0\xb2\x0\xb3\x0\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xf8\x0\xb9\x0\x57\x1\xbb\x0\xbc\x0\xbd\x0\xbe\x0\xe6\x0\x4\x1\x2e\x1\x0\x1\x6\x1\xc4\x0\xc5\x0\x18\x1\x12\x1\xc\x1\xc9\x0\x79\x1\x16\x1\x22\x1\x36\x1\x2a\x1\x3b\x1\x60\x1\x43\x1\x45\x1\xd3\x0\x4c\x1\xd5\x0\xd6\x0\xd7\x0\x72\x1\x41\x1\x5a\x1\x6a\x1\xdc\x0\x7b\x1\x7d\x1\xdf\x0\x5\x1\x2f\x1\x1\x1\x7\x1\xe4\x0\xe5\x0\x19\x1\x13\x1\xd\x1\xe9\x0\x7a\x1\x17\x1\x23\x1\x37\x1\x2b\x1\x3c\x1\x61\x1\x44\x1\x46\x1\xf3\x0\x4d\x1\xf5\x0\xf6\x0\xf7\x0\x73\x1\x42\x1\x5b\x1\x6b\x1\xfc\x0\x7c\x1\x7e\x1\xd9\x2"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\xc0\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x0\x2\x80\x1\x40\x2\x80\x1\x80\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\xa2\xa3\xa4\x0\xa6\xa7\x8d\xa9\x0\xab\xac\xad\xae\x9d\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\x8f\xb9\x0\xbb\xbc\xbd\xbe\x0\x0\x0\x0\x0\xc4\xc5\xaf\x0\x0\xc9\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd3\x0\xd5\xd6\xd7\xa8\x0\x0\x0\xdc\x0\x0\xdf\x0\x0\x0\x0\xe4\xe5\xbf\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf3\x0\xf5\xf6\xf7\xb8\x0\x0\x0\xfc\x0\x0\x0\xc2\xe2\x0\x0\xc0\xe0\xc3\xe3\x0\x0\x0\x0\xc8\xe8\x0\x0\x0\x0\xc7\xe7\x0\x0\xcb\xeb\xc6\xe6\x0\x0\x0\x0\x0\x0\x0\x0\xcc\xec\x0\x0\x0\x0\x0\x0\xce\xee\x0\x0\xc1\xe1\x0\x0\x0\x0\x0\x0\xcd\xed\x0\x0\x0\xcf\xef\x0\x0\x0\x0\xd9\xf9\xd1\xf1\xd2\xf2\x0\x0\x0\x0\x0\xd4\xf4\x0\x0\x0\x0\x0\x0\x0\x0\xaa\xba\x0\x0\xda\xfa\x0\x0\x0\x0\xd0\xf0\x0\x0\x0\x0\x0\x0\x0\x0\xdb\xfb\x0\x0\x0\x0\x0\x0\xd8\xf8\x0\x0\x0\x0\x0\xca\xea\xdd\xfd\xde\xfe\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (1258, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x1a\x20\x92\x1\x1e\x20\x26\x20\x20\x20\x21\x20\xc6\x2\x30\x20\x0\x0\x39\x20\x52\x1\x0\x0\x0\x0\x0\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\xdc\x2\x22\x21\x0\x0\x3a\x20\x53\x1\x0\x0\x0\x0\x78\x1\xa0\x0\xa1\x0\xa2\x0\xa3\x0\xa4\x0\xa5\x0\xa6\x0\xa7\x0\xa8\x0\xa9\x0\xaa\x0\xab\x0\xac\x0\xad\x0\xae\x0\xaf\x0\xb0\x0\xb1\x0\xb2\x0\xb3\x0\xb4\x0\xb5\x0\xb6\x0\xb7\x0\xb8\x0\xb9\x0\xba\x0\xbb\x0\xbc\x0\xbd\x0\xbe\x0\xbf\x0\xc0\x0\xc1\x0\xc2\x0\x2\x1\xc4\x0\xc5\x0\xc6\x0\xc7\x0\xc8\x0\xc9\x0\xca\x0\xcb\x0\x0\x3\xcd\x0\xce\x0\xcf\x0\x10\x1\xd1\x0\x9\x3\xd3\x0\xd4\x0\xa0\x1\xd6\x0\xd7\x0\xd8\x0\xd9\x0\xda\x0\xdb\x0\xdc\x0\xaf\x1\x3\x3\xdf\x0\xe0\x0\xe1\x0\xe2\x0\x3\x1\xe4\x0\xe5\x0\xe6\x0\xe7\x0\xe8\x0\xe9\x0\xea\x0\xeb\x0\x1\x3\xed\x0\xee\x0\xef\x0\x11\x1\xf1\x0\x23\x3\xf3\x0\xf4\x0\xa1\x1\xf6\x0\xf7\x0\xf8\x0\xf9\x0\xfa\x0\xfb\x0\xfc\x0\xb0\x1\xab\x20\xff\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\x0\x2\x40\x2\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\xc0\x1\x80\x2\xc0\x1\xc0\x2\xc0\x1\x0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\x0\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\x0\xcd\xce\xcf\x0\xd1\x0\xd3\xd4\x0\xd6\xd7\xd8\xd9\xda\xdb\xdc\x0\x0\xdf\xe0\xe1\xe2\x0\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\x0\xed\xee\xef\x0\xf1\x0\xf3\xf4\x0\xf6\xf7\xf8\xf9\xfa\xfb\xfc\x0\x0\xff\x0\x0\xc3\xe3\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd0\xf0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8c\x9c\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x83\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd5\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdd\xfd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcc\xec\x0\xde\x0\x0\x0\x0\x0\xd2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x82\x0\x93\x94\x84\x0\x86\x87\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x0\x8b\x9b\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x99"#- , encoderMax = '\8482'- }-- }- )-- ,- (437, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe4\x0\xe0\x0\xe5\x0\xe7\x0\xea\x0\xeb\x0\xe8\x0\xef\x0\xee\x0\xec\x0\xc4\x0\xc5\x0\xc9\x0\xe6\x0\xc6\x0\xf4\x0\xf6\x0\xf2\x0\xfb\x0\xf9\x0\xff\x0\xd6\x0\xdc\x0\xa2\x0\xa3\x0\xa5\x0\xa7\x20\x92\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\xf1\x0\xd1\x0\xaa\x0\xba\x0\xbf\x0\x10\x23\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xb1\x3\xdf\x0\x93\x3\xc0\x3\xa3\x3\xc3\x3\xb5\x0\xc4\x3\xa6\x3\x98\x3\xa9\x3\xb4\x3\x1e\x22\xc6\x3\xb5\x3\x29\x22\x61\x22\xb1\x0\x65\x22\x64\x22\x20\x23\x21\x23\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x40\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x40\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x2\xc0\x2\x0\x1\x0\x1\x0\x3\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x3\x80\x3\xc0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\x9b\x9c\x0\x9d\x0\x0\x0\x0\xa6\xae\xaa\x0\x0\x0\xf8\xf1\xfd\x0\x0\xe6\x0\xfa\x0\x0\xa7\xaf\xac\xab\x0\xa8\x0\x0\x0\x0\x8e\x8f\x92\x80\x0\x90\x0\x0\x0\x0\x0\x0\x0\xa5\x0\x0\x0\x0\x99\x0\x0\x0\x0\x0\x9a\x0\x0\xe1\x85\xa0\x83\x0\x84\x86\x91\x87\x8a\x82\x88\x89\x8d\xa1\x8c\x8b\x0\xa4\x95\xa2\x93\x0\x94\xf6\x0\x97\xa3\x96\x81\x0\x0\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe2\x0\x0\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe4\x0\x0\xe8\x0\x0\xea\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\xeb\xee\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe3\x0\x0\xe5\xe7\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (500, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x9c\x0\x9\x0\x86\x0\x7f\x0\x97\x0\x8d\x0\x8e\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x9d\x0\x85\x0\x8\x0\x87\x0\x18\x0\x19\x0\x92\x0\x8f\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x80\x0\x81\x0\x82\x0\x83\x0\x84\x0\xa\x0\x17\x0\x1b\x0\x88\x0\x89\x0\x8a\x0\x8b\x0\x8c\x0\x5\x0\x6\x0\x7\x0\x90\x0\x91\x0\x16\x0\x93\x0\x94\x0\x95\x0\x96\x0\x4\x0\x98\x0\x99\x0\x9a\x0\x9b\x0\x14\x0\x15\x0\x9e\x0\x1a\x0\x20\x0\xa0\x0\xe2\x0\xe4\x0\xe0\x0\xe1\x0\xe3\x0\xe5\x0\xe7\x0\xf1\x0\x5b\x0\x2e\x0\x3c\x0\x28\x0\x2b\x0\x21\x0\x26\x0\xe9\x0\xea\x0\xeb\x0\xe8\x0\xed\x0\xee\x0\xef\x0\xec\x0\xdf\x0\x5d\x0\x24\x0\x2a\x0\x29\x0\x3b\x0\x5e\x0\x2d\x0\x2f\x0\xc2\x0\xc4\x0\xc0\x0\xc1\x0\xc3\x0\xc5\x0\xc7\x0\xd1\x0\xa6\x0\x2c\x0\x25\x0\x5f\x0\x3e\x0\x3f\x0\xf8\x0\xc9\x0\xca\x0\xcb\x0\xc8\x0\xcd\x0\xce\x0\xcf\x0\xcc\x0\x60\x0\x3a\x0\x23\x0\x40\x0\x27\x0\x3d\x0\x22\x0\xd8\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\xab\x0\xbb\x0\xf0\x0\xfd\x0\xfe\x0\xb1\x0\xb0\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\xaa\x0\xba\x0\xe6\x0\xb8\x0\xc6\x0\xa4\x0\xb5\x0\x7e\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\xa1\x0\xbf\x0\xd0\x0\xdd\x0\xde\x0\xae\x0\xa2\x0\xa3\x0\xa5\x0\xb7\x0\xa9\x0\xa7\x0\xb6\x0\xbc\x0\xbd\x0\xbe\x0\xac\x0\x7c\x0\xaf\x0\xa8\x0\xb4\x0\xd7\x0\x7b\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\xad\x0\xf4\x0\xf6\x0\xf2\x0\xf3\x0\xf5\x0\x7d\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\xb9\x0\xfb\x0\xfc\x0\xf9\x0\xfa\x0\xff\x0\x5c\x0\xf7\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\xb2\x0\xd4\x0\xd6\x0\xd2\x0\xd3\x0\xd5\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\xb3\x0\xdb\x0\xdc\x0\xd9\x0\xda\x0\x9f\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x37\x2d\x2e\x2f\x16\x5\x25\xb\xc\xd\xe\xf\x10\x11\x12\x13\x3c\x3d\x32\x26\x18\x19\x3f\x27\x1c\x1d\x1e\x1f\x40\x4f\x7f\x7b\x5b\x6c\x50\x7d\x4d\x5d\x5c\x4e\x6b\x60\x4b\x61\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\x7a\x5e\x4c\x7e\x6e\x6f\x7c\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\x4a\xe0\x5a\x5f\x6d\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96\x97\x98\x99\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xc0\xbb\xd0\xa1\x7\x20\x21\x22\x23\x24\x15\x6\x17\x28\x29\x2a\x2b\x2c\x9\xa\x1b\x30\x31\x1a\x33\x34\x35\x36\x8\x38\x39\x3a\x3b\x4\x14\x3e\xff\x41\xaa\xb0\xb1\x9f\xb2\x6a\xb5\xbd\xb4\x9a\x8a\xba\xca\xaf\xbc\x90\x8f\xea\xfa\xbe\xa0\xb6\xb3\x9d\xda\x9b\x8b\xb7\xb8\xb9\xab\x64\x65\x62\x66\x63\x67\x9e\x68\x74\x71\x72\x73\x78\x75\x76\x77\xac\x69\xed\xee\xeb\xef\xec\xbf\x80\xfd\xfe\xfb\xfc\xad\xae\x59\x44\x45\x42\x46\x43\x47\x9c\x48\x54\x51\x52\x53\x58\x55\x56\x57\x8c\x49\xcd\xce\xcb\xcf\xcc\xe1\x70\xdd\xde\xdb\xdc\x8d\x8e\xdf"#- , encoderMax = '\255'- }-- }- )-- ,- (737, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\x91\x3\x92\x3\x93\x3\x94\x3\x95\x3\x96\x3\x97\x3\x98\x3\x99\x3\x9a\x3\x9b\x3\x9c\x3\x9d\x3\x9e\x3\x9f\x3\xa0\x3\xa1\x3\xa3\x3\xa4\x3\xa5\x3\xa6\x3\xa7\x3\xa8\x3\xa9\x3\xb1\x3\xb2\x3\xb3\x3\xb4\x3\xb5\x3\xb6\x3\xb7\x3\xb8\x3\xb9\x3\xba\x3\xbb\x3\xbc\x3\xbd\x3\xbe\x3\xbf\x3\xc0\x3\xc1\x3\xc3\x3\xc2\x3\xc4\x3\xc5\x3\xc6\x3\xc7\x3\xc8\x3\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xc9\x3\xac\x3\xad\x3\xae\x3\xca\x3\xaf\x3\xcc\x3\xcd\x3\xcb\x3\xce\x3\x86\x3\x88\x3\x89\x3\x8a\x3\x8c\x3\x8e\x3\x8f\x3\xb1\x0\x65\x22\x64\x22\xaa\x3\xab\x3\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x1\x80\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x40\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x2\xc0\x2\x0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf8\xf1\xfd\x0\x0\x0\x0\xfa\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf6\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xea\x0\xeb\xec\xed\x0\xee\x0\xef\xf0\x0\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x0\x91\x92\x93\x94\x95\x96\x97\xf4\xf5\xe1\xe2\xe3\xe5\x0\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xaa\xa9\xab\xac\xad\xae\xaf\xe0\xe4\xe8\xe6\xe7\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (775, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\x6\x1\xfc\x0\xe9\x0\x1\x1\xe4\x0\x23\x1\xe5\x0\x7\x1\x42\x1\x13\x1\x56\x1\x57\x1\x2b\x1\x79\x1\xc4\x0\xc5\x0\xc9\x0\xe6\x0\xc6\x0\x4d\x1\xf6\x0\x22\x1\xa2\x0\x5a\x1\x5b\x1\xd6\x0\xdc\x0\xf8\x0\xa3\x0\xd8\x0\xd7\x0\xa4\x0\x0\x1\x2a\x1\xf3\x0\x7b\x1\x7c\x1\x7a\x1\x1d\x20\xa6\x0\xa9\x0\xae\x0\xac\x0\xbd\x0\xbc\x0\x41\x1\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x4\x1\xc\x1\x18\x1\x16\x1\x63\x25\x51\x25\x57\x25\x5d\x25\x2e\x1\x60\x1\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x72\x1\x6a\x1\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x7d\x1\x5\x1\xd\x1\x19\x1\x17\x1\x2f\x1\x61\x1\x73\x1\x6b\x1\x7e\x1\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xd3\x0\xdf\x0\x4c\x1\x43\x1\xf5\x0\xd5\x0\xb5\x0\x44\x1\x36\x1\x37\x1\x3b\x1\x3c\x1\x46\x1\x12\x1\x45\x1\x19\x20\xad\x0\xb1\x0\x1c\x20\xbe\x0\xb6\x0\xa7\x0\xf7\x0\x1e\x20\xb0\x0\x19\x22\xb7\x0\xb9\x0\xb3\x0\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\xc0\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x0\x2\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x40\x2\x80\x2\xc0\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x96\x9c\x9f\x0\xa7\xf5\x0\xa8\x0\xae\xaa\xf0\xa9\x0\xf8\xf1\xfd\xfc\x0\xe6\xf4\xfa\x0\xfb\x0\xaf\xac\xab\xf3\x0\x0\x0\x0\x0\x8e\x8f\x92\x0\x0\x90\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe0\x0\xe5\x99\x9e\x9d\x0\x0\x0\x9a\x0\x0\xe1\x0\x0\x0\x0\x84\x86\x91\x0\x0\x82\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa2\x0\xe4\x94\xf6\x9b\x0\x0\x0\x81\x0\x0\x0\xa0\x83\x0\x0\xb5\xd0\x80\x87\x0\x0\x0\x0\xb6\xd1\x0\x0\x0\x0\xed\x89\x0\x0\xb8\xd3\xb7\xd2\x0\x0\x0\x0\x0\x0\x0\x0\x95\x85\x0\x0\x0\x0\x0\x0\xa1\x8c\x0\x0\xbd\xd4\x0\x0\x0\x0\x0\x0\xe8\xe9\x0\x0\x0\xea\xeb\x0\x0\x0\x0\xad\x88\xe3\xe7\xee\xec\x0\x0\x0\x0\x0\xe2\x93\x0\x0\x0\x0\x0\x0\x0\x0\x8a\x8b\x0\x0\x97\x98\x0\x0\x0\x0\xbe\xd5\x0\x0\x0\x0\x0\x0\x0\x0\xc7\xd7\x0\x0\x0\x0\x0\x0\xc6\xd6\x0\x0\x0\x0\x0\x8d\xa5\xa3\xa4\xcf\xd8\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\xf2\xa6\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\x0\x0\xc9\x0\x0\xbb\x0\x0\xc8\x0\x0\xbc\x0\x0\xcc\x0\x0\xb9\x0\x0\xcb\x0\x0\xca\x0\x0\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (850, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe4\x0\xe0\x0\xe5\x0\xe7\x0\xea\x0\xeb\x0\xe8\x0\xef\x0\xee\x0\xec\x0\xc4\x0\xc5\x0\xc9\x0\xe6\x0\xc6\x0\xf4\x0\xf6\x0\xf2\x0\xfb\x0\xf9\x0\xff\x0\xd6\x0\xdc\x0\xf8\x0\xa3\x0\xd8\x0\xd7\x0\x92\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\xf1\x0\xd1\x0\xaa\x0\xba\x0\xbf\x0\xae\x0\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\xc1\x0\xc2\x0\xc0\x0\xa9\x0\x63\x25\x51\x25\x57\x25\x5d\x25\xa2\x0\xa5\x0\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\xe3\x0\xc3\x0\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\xa4\x0\xf0\x0\xd0\x0\xca\x0\xcb\x0\xc8\x0\x31\x1\xcd\x0\xce\x0\xcf\x0\x18\x25\xc\x25\x88\x25\x84\x25\xa6\x0\xcc\x0\x80\x25\xd3\x0\xdf\x0\xd4\x0\xd2\x0\xf5\x0\xd5\x0\xb5\x0\xfe\x0\xde\x0\xda\x0\xdb\x0\xd9\x0\xfd\x0\xdd\x0\xaf\x0\xb4\x0\xad\x0\xb1\x0\x17\x20\xbe\x0\xb6\x0\xa7\x0\xf7\x0\xb8\x0\xb0\x0\xa8\x0\xb7\x0\xb9\x0\xb3\x0\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\xc0\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x40\x1\x0\x2\x40\x2\x80\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\xbd\x9c\xcf\xbe\xdd\xf5\xf9\xb8\xa6\xae\xaa\xf0\xa9\xee\xf8\xf1\xfd\xfc\xef\xe6\xf4\xfa\xf7\xfb\xa7\xaf\xac\xab\xf3\xa8\xb7\xb5\xb6\xc7\x8e\x8f\x92\x80\xd4\x90\xd2\xd3\xde\xd6\xd7\xd8\xd1\xa5\xe3\xe0\xe2\xe5\x99\x9e\x9d\xeb\xe9\xea\x9a\xed\xe8\xe1\x85\xa0\x83\xc6\x84\x86\x91\x87\x8a\x82\x88\x89\x8d\xa1\x8c\x8b\xd0\xa4\x95\xa2\x93\xe4\x94\xf6\x9b\x97\xa3\x96\x81\xec\xe7\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xd5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\x0\x0\xc9\x0\x0\xbb\x0\x0\xc8\x0\x0\xbc\x0\x0\xcc\x0\x0\xb9\x0\x0\xcb\x0\x0\xca\x0\x0\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\x0\x0\x0\x0\x0\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (852, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe4\x0\x6f\x1\x7\x1\xe7\x0\x42\x1\xeb\x0\x50\x1\x51\x1\xee\x0\x79\x1\xc4\x0\x6\x1\xc9\x0\x39\x1\x3a\x1\xf4\x0\xf6\x0\x3d\x1\x3e\x1\x5a\x1\x5b\x1\xd6\x0\xdc\x0\x64\x1\x65\x1\x41\x1\xd7\x0\xd\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\x4\x1\x5\x1\x7d\x1\x7e\x1\x18\x1\x19\x1\xac\x0\x7a\x1\xc\x1\x5f\x1\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\xc1\x0\xc2\x0\x1a\x1\x5e\x1\x63\x25\x51\x25\x57\x25\x5d\x25\x7b\x1\x7c\x1\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x2\x1\x3\x1\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\xa4\x0\x11\x1\x10\x1\xe\x1\xcb\x0\xf\x1\x47\x1\xcd\x0\xce\x0\x1b\x1\x18\x25\xc\x25\x88\x25\x84\x25\x62\x1\x6e\x1\x80\x25\xd3\x0\xdf\x0\xd4\x0\x43\x1\x44\x1\x48\x1\x60\x1\x61\x1\x54\x1\xda\x0\x55\x1\x70\x1\xfd\x0\xdd\x0\x63\x1\xb4\x0\xad\x0\xdd\x2\xdb\x2\xc7\x2\xd8\x2\xa7\x0\xf7\x0\xb8\x0\xb0\x0\xa8\x0\xd9\x2\x71\x1\x58\x1\x59\x1\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\xc0\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x0\x2\x40\x2\x80\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x0\x0\xcf\x0\x0\xf5\xf9\x0\x0\xae\xaa\xf0\x0\x0\xf8\x0\x0\x0\xef\x0\x0\x0\xf7\x0\x0\xaf\x0\x0\x0\x0\x0\xb5\xb6\x0\x8e\x0\x0\x80\x0\x90\x0\xd3\x0\xd6\xd7\x0\x0\x0\x0\xe0\xe2\x0\x99\x9e\x0\x0\xe9\x0\x9a\xed\x0\xe1\x0\xa0\x83\x0\x84\x0\x0\x87\x0\x82\x0\x89\x0\xa1\x8c\x0\x0\x0\x0\xa2\x93\x0\x94\xf6\x0\x0\xa3\x0\x81\xec\x0\x0\x0\x0\xc6\xc7\xa4\xa5\x8f\x86\x0\x0\x0\x0\xac\x9f\xd2\xd4\xd1\xd0\x0\x0\x0\x0\x0\x0\xa8\xa9\xb7\xd8\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x91\x92\x0\x0\x95\x96\x0\x0\x9d\x88\xe3\xe4\x0\x0\xd5\xe5\x0\x0\x0\x0\x0\x0\x0\x8a\x8b\x0\x0\xe8\xea\x0\x0\xfc\xfd\x97\x98\x0\x0\xb8\xad\xe6\xe7\xdd\xee\x9b\x9c\x0\x0\x0\x0\x0\x0\x0\x0\xde\x85\xeb\xfb\x0\x0\x0\x0\x0\x0\x0\x8d\xab\xbd\xbe\xa6\xa7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf3\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xfa\x0\xf2\x0\xf1\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\x0\x0\xc9\x0\x0\xbb\x0\x0\xc8\x0\x0\xbc\x0\x0\xcc\x0\x0\xb9\x0\x0\xcb\x0\x0\xca\x0\x0\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\x0\x0\x0\x0\x0\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (855, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\x52\x4\x2\x4\x53\x4\x3\x4\x51\x4\x1\x4\x54\x4\x4\x4\x55\x4\x5\x4\x56\x4\x6\x4\x57\x4\x7\x4\x58\x4\x8\x4\x59\x4\x9\x4\x5a\x4\xa\x4\x5b\x4\xb\x4\x5c\x4\xc\x4\x5e\x4\xe\x4\x5f\x4\xf\x4\x4e\x4\x2e\x4\x4a\x4\x2a\x4\x30\x4\x10\x4\x31\x4\x11\x4\x46\x4\x26\x4\x34\x4\x14\x4\x35\x4\x15\x4\x44\x4\x24\x4\x33\x4\x13\x4\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x45\x4\x25\x4\x38\x4\x18\x4\x63\x25\x51\x25\x57\x25\x5d\x25\x39\x4\x19\x4\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x3a\x4\x1a\x4\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\xa4\x0\x3b\x4\x1b\x4\x3c\x4\x1c\x4\x3d\x4\x1d\x4\x3e\x4\x1e\x4\x3f\x4\x18\x25\xc\x25\x88\x25\x84\x25\x1f\x4\x4f\x4\x80\x25\x2f\x4\x40\x4\x20\x4\x41\x4\x21\x4\x42\x4\x22\x4\x43\x4\x23\x4\x36\x4\x16\x4\x32\x4\x12\x4\x4c\x4\x2c\x4\x16\x21\xad\x0\x4b\x4\x2b\x4\x37\x4\x17\x4\x48\x4\x28\x4\x4d\x4\x2d\x4\x49\x4\x29\x4\x47\x4\x27\x4\xa7\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\x40\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x80\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x1\x0\x2\x40\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x0\x0\xcf\x0\x0\xfd\x0\x0\x0\xae\x0\xf0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xaf\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x85\x81\x83\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x0\x99\x9b\xa1\xa3\xec\xad\xa7\xa9\xea\xf4\xb8\xbe\xc7\xd1\xd3\xd5\xd7\xdd\xe2\xe4\xe6\xe8\xab\xb6\xa5\xfc\xf6\xfa\x9f\xf2\xee\xf8\x9d\xe0\xa0\xa2\xeb\xac\xa6\xa8\xe9\xf3\xb7\xbd\xc6\xd0\xd2\xd4\xd6\xd8\xe1\xe3\xe5\xe7\xaa\xb5\xa4\xfb\xf5\xf9\x9e\xf1\xed\xf7\x9c\xde\x0\x84\x80\x82\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x0\x98\x9a\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\x0\x0\xc9\x0\x0\xbb\x0\x0\xc8\x0\x0\xbc\x0\x0\xcc\x0\x0\xb9\x0\x0\xcb\x0\x0\xca\x0\x0\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\x0\x0\x0\x0\x0\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (857, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe4\x0\xe0\x0\xe5\x0\xe7\x0\xea\x0\xeb\x0\xe8\x0\xef\x0\xee\x0\x31\x1\xc4\x0\xc5\x0\xc9\x0\xe6\x0\xc6\x0\xf4\x0\xf6\x0\xf2\x0\xfb\x0\xf9\x0\x30\x1\xd6\x0\xdc\x0\xf8\x0\xa3\x0\xd8\x0\x5e\x1\x5f\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\xf1\x0\xd1\x0\x1e\x1\x1f\x1\xbf\x0\xae\x0\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\xc1\x0\xc2\x0\xc0\x0\xa9\x0\x63\x25\x51\x25\x57\x25\x5d\x25\xa2\x0\xa5\x0\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\xe3\x0\xc3\x0\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\xa4\x0\xba\x0\xaa\x0\xca\x0\xcb\x0\xc8\x0\x0\x0\xcd\x0\xce\x0\xcf\x0\x18\x25\xc\x25\x88\x25\x84\x25\xa6\x0\xcc\x0\x80\x25\xd3\x0\xdf\x0\xd4\x0\xd2\x0\xf5\x0\xd5\x0\xb5\x0\x0\x0\xd7\x0\xda\x0\xdb\x0\xd9\x0\xec\x0\xff\x0\xaf\x0\xb4\x0\xad\x0\xb1\x0\x0\x0\xbe\x0\xb6\x0\xa7\x0\xf7\x0\xb8\x0\xb0\x0\xa8\x0\xb7\x0\xb9\x0\xb3\x0\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x40\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\x80\x1\xc0\x1\x0\x2\x40\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\xbd\x9c\xcf\xbe\xdd\xf5\xf9\xb8\xd1\xae\xaa\xf0\xa9\xee\xf8\xf1\xfd\xfc\xef\xe6\xf4\xfa\xf7\xfb\xd0\xaf\xac\xab\xf3\xa8\xb7\xb5\xb6\xc7\x8e\x8f\x92\x80\xd4\x90\xd2\xd3\xde\xd6\xd7\xd8\x0\xa5\xe3\xe0\xe2\xe5\x99\xe8\x9d\xeb\xe9\xea\x9a\x0\x0\xe1\x85\xa0\x83\xc6\x84\x86\x91\x87\x8a\x82\x88\x89\xec\xa1\x8c\x8b\x0\xa4\x95\xa2\x93\xe4\x94\xf6\x9b\x97\xa3\x96\x81\x0\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa6\xa7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x98\x8d\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9e\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\x0\x0\xc9\x0\x0\xbb\x0\x0\xc8\x0\x0\xbc\x0\x0\xcc\x0\x0\xb9\x0\x0\xcb\x0\x0\xca\x0\x0\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\x0\x0\x0\x0\x0\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (860, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe3\x0\xe0\x0\xc1\x0\xe7\x0\xea\x0\xca\x0\xe8\x0\xcd\x0\xd4\x0\xec\x0\xc3\x0\xc2\x0\xc9\x0\xc0\x0\xc8\x0\xf4\x0\xf5\x0\xf2\x0\xda\x0\xf9\x0\xcc\x0\xd5\x0\xdc\x0\xa2\x0\xa3\x0\xd9\x0\xa7\x20\xd3\x0\xe1\x0\xed\x0\xf3\x0\xfa\x0\xf1\x0\xd1\x0\xaa\x0\xba\x0\xbf\x0\xd2\x0\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xb1\x3\xdf\x0\x93\x3\xc0\x3\xa3\x3\xc3\x3\xb5\x0\xc4\x3\xa6\x3\x98\x3\xa9\x3\xb4\x3\x1e\x22\xc6\x3\xb5\x3\x29\x22\x61\x22\xb1\x0\x65\x22\x64\x22\x20\x23\x21\x23\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x1\x80\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x1\x0\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x2\x80\x2\x0\x1\x0\x1\xc0\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x3\x40\x3\x80\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\x9b\x9c\x0\x0\x0\x0\x0\x0\xa6\xae\xaa\x0\x0\x0\xf8\xf1\xfd\x0\x0\xe6\x0\xfa\x0\x0\xa7\xaf\xac\xab\x0\xa8\x91\x86\x8f\x8e\x0\x0\x0\x80\x92\x90\x89\x0\x98\x8b\x0\x0\x0\xa5\xa9\x9f\x8c\x99\x0\x0\x0\x9d\x96\x0\x9a\x0\x0\xe1\x85\xa0\x83\x84\x0\x0\x0\x87\x8a\x82\x88\x0\x8d\xa1\x0\x0\x0\xa4\x95\xa2\x93\x94\x0\xf6\x0\x97\xa3\x0\x81\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe2\x0\x0\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe4\x0\x0\xe8\x0\x0\xea\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\xeb\xee\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe3\x0\x0\xe5\xe7\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (861, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe4\x0\xe0\x0\xe5\x0\xe7\x0\xea\x0\xeb\x0\xe8\x0\xd0\x0\xf0\x0\xde\x0\xc4\x0\xc5\x0\xc9\x0\xe6\x0\xc6\x0\xf4\x0\xf6\x0\xfe\x0\xfb\x0\xdd\x0\xfd\x0\xd6\x0\xdc\x0\xf8\x0\xa3\x0\xd8\x0\xa7\x20\x92\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\xc1\x0\xcd\x0\xd3\x0\xda\x0\xbf\x0\x10\x23\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xb1\x3\xdf\x0\x93\x3\xc0\x3\xa3\x3\xc3\x3\xb5\x0\xc4\x3\xa6\x3\x98\x3\xa9\x3\xb4\x3\x1e\x22\xc6\x3\xb5\x3\x29\x22\x61\x22\xb1\x0\x65\x22\x64\x22\x20\x23\x21\x23\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x40\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x40\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x2\xc0\x2\x0\x1\x0\x1\x0\x3\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x3\x80\x3\xc0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\x0\x9c\x0\x0\x0\x0\x0\x0\x0\xae\xaa\x0\x0\x0\xf8\xf1\xfd\x0\x0\xe6\x0\xfa\x0\x0\x0\xaf\xac\xab\x0\xa8\x0\xa4\x0\x0\x8e\x8f\x92\x80\x0\x90\x0\x0\x0\xa5\x0\x0\x8b\x0\x0\xa6\x0\x0\x99\x0\x9d\x0\xa7\x0\x9a\x97\x8d\xe1\x85\xa0\x83\x0\x84\x86\x91\x87\x8a\x82\x88\x89\x0\xa1\x0\x0\x8c\x0\x0\xa2\x93\x0\x94\xf6\x9b\x0\xa3\x96\x81\x98\x95\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe2\x0\x0\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe4\x0\x0\xe8\x0\x0\xea\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\xeb\xee\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe3\x0\x0\xe5\xe7\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (862, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xd0\x5\xd1\x5\xd2\x5\xd3\x5\xd4\x5\xd5\x5\xd6\x5\xd7\x5\xd8\x5\xd9\x5\xda\x5\xdb\x5\xdc\x5\xdd\x5\xde\x5\xdf\x5\xe0\x5\xe1\x5\xe2\x5\xe3\x5\xe4\x5\xe5\x5\xe6\x5\xe7\x5\xe8\x5\xe9\x5\xea\x5\xa2\x0\xa3\x0\xa5\x0\xa7\x20\x92\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\xf1\x0\xd1\x0\xaa\x0\xba\x0\xbf\x0\x10\x23\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xb1\x3\xdf\x0\x93\x3\xc0\x3\xa3\x3\xc3\x3\xb5\x0\xc4\x3\xa6\x3\x98\x3\xa9\x3\xb4\x3\x1e\x22\xc6\x3\xb5\x3\x29\x22\x61\x22\xb1\x0\x65\x22\x64\x22\x20\x23\x21\x23\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x40\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x2\x80\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x2\x0\x3\x0\x1\x0\x1\x40\x3\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x3\xc0\x3\x0\x4"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\x9b\x9c\x0\x9d\x0\x0\x0\x0\xa6\xae\xaa\x0\x0\x0\xf8\xf1\xfd\x0\x0\xe6\x0\xfa\x0\x0\xa7\xaf\xac\xab\x0\xa8\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe1\x0\xa0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa1\x0\x0\x0\xa4\x0\xa2\x0\x0\x0\xf6\x0\x0\xa3\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe2\x0\x0\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe4\x0\x0\xe8\x0\x0\xea\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\xeb\xee\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe3\x0\x0\xe5\xe7\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (863, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xc2\x0\xe0\x0\xb6\x0\xe7\x0\xea\x0\xeb\x0\xe8\x0\xef\x0\xee\x0\x17\x20\xc0\x0\xa7\x0\xc9\x0\xc8\x0\xca\x0\xf4\x0\xcb\x0\xcf\x0\xfb\x0\xf9\x0\xa4\x0\xd4\x0\xdc\x0\xa2\x0\xa3\x0\xd9\x0\xdb\x0\x92\x1\xa6\x0\xb4\x0\xf3\x0\xfa\x0\xa8\x0\xb8\x0\xb3\x0\xaf\x0\xce\x0\x10\x23\xac\x0\xbd\x0\xbc\x0\xbe\x0\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xb1\x3\xdf\x0\x93\x3\xc0\x3\xa3\x3\xc3\x3\xb5\x0\xc4\x3\xa6\x3\x98\x3\xa9\x3\xb4\x3\x1e\x22\xc6\x3\xb5\x3\x29\x22\x61\x22\xb1\x0\x65\x22\x64\x22\x20\x23\x21\x23\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x40\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x40\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x2\xc0\x2\x0\x1\x0\x1\x0\x3\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x3\x80\x3\xc0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x9b\x9c\x98\x0\xa0\x8f\xa4\x0\x0\xae\xaa\x0\x0\xa7\xf8\xf1\xfd\xa6\xa1\xe6\x86\xfa\xa5\x0\x0\xaf\xac\xab\xad\x0\x8e\x0\x84\x0\x0\x0\x0\x80\x91\x90\x92\x94\x0\x0\xa8\x95\x0\x0\x0\x0\x99\x0\x0\x0\x0\x9d\x0\x9e\x9a\x0\x0\xe1\x85\x0\x83\x0\x0\x0\x0\x87\x8a\x82\x88\x89\x0\x0\x8c\x8b\x0\x0\x0\xa2\x93\x0\x0\xf6\x0\x97\xa3\x96\x81\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe2\x0\x0\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe4\x0\x0\xe8\x0\x0\xea\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\xeb\xee\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe3\x0\x0\xe5\xe7\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8d\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (864, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x6a\x6\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xb0\x0\xb7\x0\x19\x22\x1a\x22\x92\x25\x0\x25\x2\x25\x3c\x25\x24\x25\x2c\x25\x1c\x25\x34\x25\x10\x25\xc\x25\x14\x25\x18\x25\xb2\x3\x1e\x22\xc6\x3\xb1\x0\xbd\x0\xbc\x0\x48\x22\xab\x0\xbb\x0\xf7\xfe\xf8\xfe\x0\x0\x0\x0\xfb\xfe\xfc\xfe\x0\x0\xa0\x0\xad\x0\x82\xfe\xa3\x0\xa4\x0\x84\xfe\x0\x0\x0\x0\x8e\xfe\x8f\xfe\x95\xfe\x99\xfe\xc\x6\x9d\xfe\xa1\xfe\xa5\xfe\x60\x6\x61\x6\x62\x6\x63\x6\x64\x6\x65\x6\x66\x6\x67\x6\x68\x6\x69\x6\xd1\xfe\x1b\x6\xb1\xfe\xb5\xfe\xb9\xfe\x1f\x6\xa2\x0\x80\xfe\x81\xfe\x83\xfe\x85\xfe\xca\xfe\x8b\xfe\x8d\xfe\x91\xfe\x93\xfe\x97\xfe\x9b\xfe\x9f\xfe\xa3\xfe\xa7\xfe\xa9\xfe\xab\xfe\xad\xfe\xaf\xfe\xb3\xfe\xb7\xfe\xbb\xfe\xbf\xfe\xc1\xfe\xc5\xfe\xcb\xfe\xcf\xfe\xa6\x0\xac\x0\xf7\x0\xd7\x0\xc9\xfe\x40\x6\xd3\xfe\xd7\xfe\xdb\xfe\xdf\xfe\xe3\xfe\xe7\xfe\xeb\xfe\xed\xfe\xef\xfe\xf3\xfe\xbd\xfe\xcc\xfe\xce\xfe\xcd\xfe\xe1\xfe\x7d\xfe\x51\x6\xe5\xfe\xe9\xfe\xec\xfe\xf0\xfe\xf2\xfe\xd0\xfe\xd5\xfe\xf5\xfe\xf6\xfe\xdd\xfe\xd9\xfe\xf1\xfe\xa0\x25\x0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x1\x80\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x1\x0\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x2\x80\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\xc0\x2\x0\x1\x0\x3\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x3\x80\x3\xc0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x0\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\xc0\xa3\xa4\x0\xdb\x0\x0\x0\x0\x97\xdc\xa1\x0\x0\x80\x93\x0\x0\x0\x0\x0\x81\x0\x0\x0\x98\x95\x94\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xde\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x90\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x92\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xac\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xbb\x0\x0\x0\xbf\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf1\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\x25\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x82\x83\x0\x0\x0\x91\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x85\x0\x86\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8d\x0\x0\x0\x8c\x0\x0\x0\x8e\x0\x0\x0\x8f\x0\x0\x0\x8a\x0\x0\x0\x0\x0\x0\x0\x88\x0\x0\x0\x0\x0\x0\x0\x89\x0\x0\x0\x0\x0\x0\x0\x8b\x0\x0\x0\x0\x0\x0\x0\x87\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x84\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xc1\xc2\xa2\xc3\xa5\xc4\x0\x0\x0\x0\x0\xc6\x0\xc7\xa8\xa9\x0\xc8\x0\xc9\x0\xaa\x0\xca\x0\xab\x0\xcb\x0\xad\x0\xcc\x0\xae\x0\xcd\x0\xaf\x0\xce\x0\xcf\x0\xd0\x0\xd1\x0\xd2\x0\xbc\x0\xd3\x0\xbd\x0\xd4\x0\xbe\x0\xd5\x0\xeb\x0\xd6\x0\xd7\x0\x0\x0\xd8\x0\x0\x0\xdf\xc5\xd9\xec\xee\xed\xda\xf7\xba\x0\xe1\x0\xf8\x0\xe2\x0\xfc\x0\xe3\x0\xfb\x0\xe4\x0\xef\x0\xe5\x0\xf2\x0\xe6\x0\xf3\x0\xe7\xf4\xe8\x0\xe9\xf5\xfd\xf6\xea\x0\xf9\xfa\x99\x9a\x0\x0\x9d\x9e"#- , encoderMax = '\65276'- }-- }- )-- ,- (865, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xc7\x0\xfc\x0\xe9\x0\xe2\x0\xe4\x0\xe0\x0\xe5\x0\xe7\x0\xea\x0\xeb\x0\xe8\x0\xef\x0\xee\x0\xec\x0\xc4\x0\xc5\x0\xc9\x0\xe6\x0\xc6\x0\xf4\x0\xf6\x0\xf2\x0\xfb\x0\xf9\x0\xff\x0\xd6\x0\xdc\x0\xf8\x0\xa3\x0\xd8\x0\xa7\x20\x92\x1\xe1\x0\xed\x0\xf3\x0\xfa\x0\xf1\x0\xd1\x0\xaa\x0\xba\x0\xbf\x0\x10\x23\xac\x0\xbd\x0\xbc\x0\xa1\x0\xab\x0\xa4\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\xb1\x3\xdf\x0\x93\x3\xc0\x3\xa3\x3\xc3\x3\xb5\x0\xc4\x3\xa6\x3\x98\x3\xa9\x3\xb4\x3\x1e\x22\xc6\x3\xb5\x3\x29\x22\x61\x22\xb1\x0\x65\x22\x64\x22\x20\x23\x21\x23\xf7\x0\x48\x22\xb0\x0\x19\x22\xb7\x0\x1a\x22\x7f\x20\xb2\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\x0\x1\x0\x1\x40\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x1\xc0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x2\x40\x2\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x80\x2\xc0\x2\x0\x1\x0\x1\x0\x3\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x0\x1\x40\x3\x80\x3\xc0\x3"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\xad\x0\x9c\xaf\x0\x0\x0\x0\x0\xa6\xae\xaa\x0\x0\x0\xf8\xf1\xfd\x0\x0\xe6\x0\xfa\x0\x0\xa7\x0\xac\xab\x0\xa8\x0\x0\x0\x0\x8e\x8f\x92\x80\x0\x90\x0\x0\x0\x0\x0\x0\x0\xa5\x0\x0\x0\x0\x99\x0\x9d\x0\x0\x0\x9a\x0\x0\xe1\x85\xa0\x83\x0\x84\x86\x91\x87\x8a\x82\x88\x89\x8d\xa1\x8c\x8b\x0\xa4\x95\xa2\x93\x0\x94\xf6\x9b\x97\xa3\x96\x81\x0\x0\x98\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe2\x0\x0\x0\x0\xe9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe4\x0\x0\xe8\x0\x0\xea\x0\x0\x0\x0\x0\x0\x0\xe0\x0\x0\xeb\xee\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe3\x0\x0\xe5\xe7\x0\xed\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x9e\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\xec\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf3\xf2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf4\xf5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (866, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\x10\x4\x11\x4\x12\x4\x13\x4\x14\x4\x15\x4\x16\x4\x17\x4\x18\x4\x19\x4\x1a\x4\x1b\x4\x1c\x4\x1d\x4\x1e\x4\x1f\x4\x20\x4\x21\x4\x22\x4\x23\x4\x24\x4\x25\x4\x26\x4\x27\x4\x28\x4\x29\x4\x2a\x4\x2b\x4\x2c\x4\x2d\x4\x2e\x4\x2f\x4\x30\x4\x31\x4\x32\x4\x33\x4\x34\x4\x35\x4\x36\x4\x37\x4\x38\x4\x39\x4\x3a\x4\x3b\x4\x3c\x4\x3d\x4\x3e\x4\x3f\x4\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x61\x25\x62\x25\x56\x25\x55\x25\x63\x25\x51\x25\x57\x25\x5d\x25\x5c\x25\x5b\x25\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\x5e\x25\x5f\x25\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\x67\x25\x68\x25\x64\x25\x65\x25\x59\x25\x58\x25\x52\x25\x53\x25\x6b\x25\x6a\x25\x18\x25\xc\x25\x88\x25\x84\x25\x8c\x25\x90\x25\x80\x25\x40\x4\x41\x4\x42\x4\x43\x4\x44\x4\x45\x4\x46\x4\x47\x4\x48\x4\x49\x4\x4a\x4\x4b\x4\x4c\x4\x4d\x4\x4e\x4\x4f\x4\x1\x4\x51\x4\x4\x4\x54\x4\x7\x4\x57\x4\xe\x4\x5e\x4\xb0\x0\x19\x22\xb7\x0\x1a\x22\x16\x21\xa4\x0\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\x40\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x80\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x2\x40\x2\x80\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x0\x0\xfd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf8\x0\x0\x0\x0\x0\x0\xfa\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf0\x0\x0\xf2\x0\x0\xf4\x0\x0\x0\x0\x0\x0\xf6\x0\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\x0\xf1\x0\x0\xf3\x0\x0\xf5\x0\x0\x0\x0\x0\x0\xf7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfc\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xf9\xfb\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\xd5\xd6\xc9\xb8\xb7\xbb\xd4\xd3\xc8\xbe\xbd\xbc\xc6\xc7\xcc\xb5\xb6\xb9\xd1\xd2\xcb\xcf\xd0\xca\xd8\xd7\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\xdd\x0\x0\x0\xde\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (869, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x86\x3\x0\x0\xb7\x0\xac\x0\xa6\x0\x18\x20\x19\x20\x88\x3\x15\x20\x89\x3\x8a\x3\xaa\x3\x8c\x3\x0\x0\x0\x0\x8e\x3\xab\x3\xa9\x0\x8f\x3\xb2\x0\xb3\x0\xac\x3\xa3\x0\xad\x3\xae\x3\xaf\x3\xca\x3\x90\x3\xcc\x3\xcd\x3\x91\x3\x92\x3\x93\x3\x94\x3\x95\x3\x96\x3\x97\x3\xbd\x0\x98\x3\x99\x3\xab\x0\xbb\x0\x91\x25\x92\x25\x93\x25\x2\x25\x24\x25\x9a\x3\x9b\x3\x9c\x3\x9d\x3\x63\x25\x51\x25\x57\x25\x5d\x25\x9e\x3\x9f\x3\x10\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x0\x25\x3c\x25\xa0\x3\xa1\x3\x5a\x25\x54\x25\x69\x25\x66\x25\x60\x25\x50\x25\x6c\x25\xa3\x3\xa4\x3\xa5\x3\xa6\x3\xa7\x3\xa8\x3\xa9\x3\xb1\x3\xb2\x3\xb3\x3\x18\x25\xc\x25\x88\x25\x84\x25\xb4\x3\xb5\x3\x80\x25\xb6\x3\xb7\x3\xb8\x3\xb9\x3\xba\x3\xbb\x3\xbc\x3\xbd\x3\xbe\x3\xbf\x3\xc0\x3\xc1\x3\xc3\x3\xc2\x3\xc4\x3\x84\x3\xad\x0\xb1\x0\xc5\x3\xc6\x3\xc7\x3\xa7\x0\xc8\x3\x85\x3\xb0\x0\xa8\x0\xc9\x3\xcb\x3\xb0\x3\xce\x3\xa0\x25\xa0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\x40\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x80\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x1\x0\x2\x40\x2"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xff\x0\x0\x9c\x0\x0\x8a\xf5\xf9\x97\x0\xae\x89\xf0\x0\x0\xf8\xf1\x99\x9a\x0\x0\x0\x88\x0\x0\x0\xaf\x0\xab\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xef\xf7\x86\x0\x8d\x8f\x90\x0\x92\x0\x95\x98\xa1\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xac\xad\xb5\xb6\xb7\xb8\xbd\xbe\xc6\xc7\x0\xcf\xd0\xd1\xd2\xd3\xd4\xd5\x91\x96\x9b\x9d\x9e\x9f\xfc\xd6\xd7\xd8\xdd\xde\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xed\xec\xee\xf2\xf3\xf4\xf6\xfa\xa0\xfb\xa2\xa3\xfd\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x8e\x0\x0\x8b\x8c\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xc4\x0\xb3\x0\x0\x0\x0\x0\x0\x0\x0\x0\xda\x0\x0\x0\xbf\x0\x0\x0\xc0\x0\x0\x0\xd9\x0\x0\x0\xc3\x0\x0\x0\x0\x0\x0\x0\xb4\x0\x0\x0\x0\x0\x0\x0\xc2\x0\x0\x0\x0\x0\x0\x0\xc1\x0\x0\x0\x0\x0\x0\x0\xc5\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcd\xba\x0\x0\xc9\x0\x0\xbb\x0\x0\xc8\x0\x0\xbc\x0\x0\xcc\x0\x0\xb9\x0\x0\xcb\x0\x0\xca\x0\x0\xce\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xdf\x0\x0\x0\xdc\x0\x0\x0\xdb\x0\x0\x0\x0\x0\x0\x0\x0\xb0\xb1\xb2\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xfe"#- , encoderMax = '\9632'- }-- }- )-- ,- (874, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0\x8\x0\x9\x0\xa\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x14\x0\x15\x0\x16\x0\x17\x0\x18\x0\x19\x0\x1a\x0\x1b\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x20\x0\x21\x0\x22\x0\x23\x0\x24\x0\x25\x0\x26\x0\x27\x0\x28\x0\x29\x0\x2a\x0\x2b\x0\x2c\x0\x2d\x0\x2e\x0\x2f\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\x3a\x0\x3b\x0\x3c\x0\x3d\x0\x3e\x0\x3f\x0\x40\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\x5b\x0\x5c\x0\x5d\x0\x5e\x0\x5f\x0\x60\x0\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\x7b\x0\x7c\x0\x7d\x0\x7e\x0\x7f\x0\xac\x20\x0\x0\x0\x0\x0\x0\x0\x0\x26\x20\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x18\x20\x19\x20\x1c\x20\x1d\x20\x22\x20\x13\x20\x14\x20\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\x1\xe\x2\xe\x3\xe\x4\xe\x5\xe\x6\xe\x7\xe\x8\xe\x9\xe\xa\xe\xb\xe\xc\xe\xd\xe\xe\xe\xf\xe\x10\xe\x11\xe\x12\xe\x13\xe\x14\xe\x15\xe\x16\xe\x17\xe\x18\xe\x19\xe\x1a\xe\x1b\xe\x1c\xe\x1d\xe\x1e\xe\x1f\xe\x20\xe\x21\xe\x22\xe\x23\xe\x24\xe\x25\xe\x26\xe\x27\xe\x28\xe\x29\xe\x2a\xe\x2b\xe\x2c\xe\x2d\xe\x2e\xe\x2f\xe\x30\xe\x31\xe\x32\xe\x33\xe\x34\xe\x35\xe\x36\xe\x37\xe\x38\xe\x39\xe\x3a\xe\x0\x0\x0\x0\x0\x0\x0\x0\x3f\xe\x40\xe\x41\xe\x42\xe\x43\xe\x44\xe\x45\xe\x46\xe\x47\xe\x48\xe\x49\xe\x4a\xe\x4b\xe\x4c\xe\x4d\xe\x4e\xe\x4f\xe\x50\xe\x51\xe\x52\xe\x53\xe\x54\xe\x55\xe\x56\xe\x57\xe\x58\xe\x59\xe\x5a\xe\x5b\xe\x0\x0\x0\x0\x0\x0\x0\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\x40\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x80\x1\xc0\x0\xc0\x1"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\x0\x0\x0\x0\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x96\x97\x0\x0\x0\x91\x92\x0\x0\x93\x94\x0\x0\x0\x0\x95\x0\x0\x0\x85\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80"#- , encoderMax = '\8364'- }-- }- )-- ,- (875, SingleByteCP {- decoderArray = ConvArray "\x0\x0\x1\x0\x2\x0\x3\x0\x9c\x0\x9\x0\x86\x0\x7f\x0\x97\x0\x8d\x0\x8e\x0\xb\x0\xc\x0\xd\x0\xe\x0\xf\x0\x10\x0\x11\x0\x12\x0\x13\x0\x9d\x0\x85\x0\x8\x0\x87\x0\x18\x0\x19\x0\x92\x0\x8f\x0\x1c\x0\x1d\x0\x1e\x0\x1f\x0\x80\x0\x81\x0\x82\x0\x83\x0\x84\x0\xa\x0\x17\x0\x1b\x0\x88\x0\x89\x0\x8a\x0\x8b\x0\x8c\x0\x5\x0\x6\x0\x7\x0\x90\x0\x91\x0\x16\x0\x93\x0\x94\x0\x95\x0\x96\x0\x4\x0\x98\x0\x99\x0\x9a\x0\x9b\x0\x14\x0\x15\x0\x9e\x0\x1a\x0\x20\x0\x91\x3\x92\x3\x93\x3\x94\x3\x95\x3\x96\x3\x97\x3\x98\x3\x99\x3\x5b\x0\x2e\x0\x3c\x0\x28\x0\x2b\x0\x21\x0\x26\x0\x9a\x3\x9b\x3\x9c\x3\x9d\x3\x9e\x3\x9f\x3\xa0\x3\xa1\x3\xa3\x3\x5d\x0\x24\x0\x2a\x0\x29\x0\x3b\x0\x5e\x0\x2d\x0\x2f\x0\xa4\x3\xa5\x3\xa6\x3\xa7\x3\xa8\x3\xa9\x3\xaa\x3\xab\x3\x7c\x0\x2c\x0\x25\x0\x5f\x0\x3e\x0\x3f\x0\xa8\x0\x86\x3\x88\x3\x89\x3\xa0\x0\x8a\x3\x8c\x3\x8e\x3\x8f\x3\x60\x0\x3a\x0\x23\x0\x40\x0\x27\x0\x3d\x0\x22\x0\x85\x3\x61\x0\x62\x0\x63\x0\x64\x0\x65\x0\x66\x0\x67\x0\x68\x0\x69\x0\xb1\x3\xb2\x3\xb3\x3\xb4\x3\xb5\x3\xb6\x3\xb0\x0\x6a\x0\x6b\x0\x6c\x0\x6d\x0\x6e\x0\x6f\x0\x70\x0\x71\x0\x72\x0\xb7\x3\xb8\x3\xb9\x3\xba\x3\xbb\x3\xbc\x3\xb4\x0\x7e\x0\x73\x0\x74\x0\x75\x0\x76\x0\x77\x0\x78\x0\x79\x0\x7a\x0\xbd\x3\xbe\x3\xbf\x3\xc0\x3\xc1\x3\xc3\x3\xa3\x0\xac\x3\xad\x3\xae\x3\xca\x3\xaf\x3\xcc\x3\xcd\x3\xcb\x3\xce\x3\xc2\x3\xc4\x3\xc5\x3\xc6\x3\xc7\x3\xc8\x3\x7b\x0\x41\x0\x42\x0\x43\x0\x44\x0\x45\x0\x46\x0\x47\x0\x48\x0\x49\x0\xad\x0\xc9\x3\x90\x3\xb0\x3\x18\x20\x15\x20\x7d\x0\x4a\x0\x4b\x0\x4c\x0\x4d\x0\x4e\x0\x4f\x0\x50\x0\x51\x0\x52\x0\xb1\x0\xbd\x0\x1a\x0\x87\x3\x19\x20\xa6\x0\x5c\x0\x1a\x0\x53\x0\x54\x0\x55\x0\x56\x0\x57\x0\x58\x0\x59\x0\x5a\x0\xb2\x0\xa7\x0\x1a\x0\x1a\x0\xab\x0\xac\x0\x30\x0\x31\x0\x32\x0\x33\x0\x34\x0\x35\x0\x36\x0\x37\x0\x38\x0\x39\x0\xb3\x0\xa9\x0\x1a\x0\x1a\x0\xbb\x0\x9f\x0"#- , encoderArray = - CompactArray {- encoderIndices = ConvArray "\x0\x0\x40\x0\x80\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x0\x1\x40\x1\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\xc0\x0\x80\x1"#- , encoderValues = ConvArray "\x0\x1\x2\x3\x37\x2d\x2e\x2f\x16\x5\x25\xb\xc\xd\xe\xf\x10\x11\x12\x13\x3c\x3d\x32\x26\x18\x19\xfd\x27\x1c\x1d\x1e\x1f\x40\x4f\x7f\x7b\x5b\x6c\x50\x7d\x4d\x5d\x5c\x4e\x6b\x60\x4b\x61\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\x7a\x5e\x4c\x7e\x6e\x6f\x7c\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\x4a\xe0\x5a\x5f\x6d\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96\x97\x98\x99\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xc0\x6a\xd0\xa1\x7\x20\x21\x22\x23\x24\x15\x6\x17\x28\x29\x2a\x2b\x2c\x9\xa\x1b\x30\x31\x1a\x33\x34\x35\x36\x8\x38\x39\x3a\x3b\x4\x14\x3e\xff\x74\x0\x0\xb0\x0\x0\xdf\xeb\x70\xfb\x0\xee\xef\xca\x0\x0\x90\xda\xea\xfa\xa0\x0\x0\x0\x0\x0\x0\xfe\x0\xdb\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x80\x71\xdd\x72\x73\x75\x0\x76\x0\x77\x78\xcc\x41\x42\x43\x44\x45\x46\x47\x48\x49\x51\x52\x53\x54\x55\x56\x57\x58\x0\x59\x62\x63\x64\x65\x66\x67\x68\x69\xb1\xb2\xb3\xb5\xcd\x8a\x8b\x8c\x8d\x8e\x8f\x9a\x9b\x9c\x9d\x9e\x9f\xaa\xab\xac\xad\xae\xba\xaf\xbb\xbc\xbd\xbe\xbf\xcb\xb4\xb8\xb6\xb7\xb9\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xcf\x0\x0\xce\xde"#- , encoderMax = '\8217'- }-- }- )- ]
@@ -1,204 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, PatternGuards #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.Failure--- Copyright : (c) The University of Glasgow, 2008-2011--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Types for specifying how text encoding/decoding fails-----------------------------------------------------------------------------------module GHC.IO.Encoding.Failure (- CodingFailureMode(..), codingFailureModeSuffix,- isSurrogate,- recoverDecode, recoverEncode- ) where--import GHC.IO-import GHC.IO.Buffer-import GHC.IO.Exception--import GHC.Base-import GHC.Word-import GHC.Show-import GHC.Num-import GHC.Real ( fromIntegral )----import System.Posix.Internals--import Data.Maybe----- | The 'CodingFailureMode' is used to construct 'TextEncoding's, and--- specifies how they handle illegal sequences.-data CodingFailureMode- = ErrorOnCodingFailure- -- ^ Throw an error when an illegal sequence is encountered- | IgnoreCodingFailure- -- ^ Attempt to ignore and recover if an illegal sequence is- -- encountered- | TransliterateCodingFailure- -- ^ Replace with the closest visual match upon an illegal- -- sequence- | RoundtripFailure- -- ^ Use the private-use escape mechanism to attempt to allow- -- illegal sequences to be roundtripped.- deriving (Show)- -- This will only work properly for those encodings which are- -- strict supersets of ASCII in the sense that valid ASCII data- -- is also valid in that encoding. This is not true for- -- e.g. UTF-16, because ASCII characters must be padded to two- -- bytes to retain their meaning.---- Note [Roundtripping]--- ~~~~~~~~~~~~~~~~~~~~------ Roundtripping is based on the ideas of PEP383.------ We used to use the range of private-use characters from 0xEF80 to--- 0xEFFF designated for "encoding hacks" by the ConScript Unicode Registery--- to encode these characters.------ However, people didn't like this because it means we don't get--- guaranteed roundtripping for byte sequences that look like a UTF-8--- encoded codepoint 0xEFxx.------ So now like PEP383 we use lone surrogate codepoints 0xDCxx to escape--- undecodable bytes, even though that may confuse Unicode processing--- software written in Haskell. This guarantees roundtripping because--- unicode input that includes lone surrogate codepoints is invalid by--- definition.------ When we used private-use characters there was a technical problem when it--- came to encoding back to bytes using iconv. The iconv code will not fail when--- it tries to encode a private-use character (as it would if trying to encode--- a surrogate), which means that we won't get a chance to replace it--- with the byte we originally escaped.------ To work around this, when filling the buffer to be encoded (in--- writeBlocks/withEncodedCString/newEncodedCString), we replaced the--- private-use characters with lone surrogates again! Likewise, when--- reading from a buffer (unpack/unpack_nl/peekEncodedCString) we have--- to do the inverse process.------ The user of String would never see these lone surrogates, but it--- ensures that iconv will throw an error when encountering them. We--- use lone surrogates in the range 0xDC00 to 0xDCFF for this purpose.--codingFailureModeSuffix :: CodingFailureMode -> String-codingFailureModeSuffix ErrorOnCodingFailure = ""-codingFailureModeSuffix IgnoreCodingFailure = "//IGNORE"-codingFailureModeSuffix TransliterateCodingFailure = "//TRANSLIT"-codingFailureModeSuffix RoundtripFailure = "//ROUNDTRIP"---- | In transliterate mode, we use this character when decoding--- unknown bytes.------ This is the defined Unicode replacement character:--- <http://www.fileformat.info/info/unicode/char/0fffd/index.htm>-unrepresentableChar :: Char-unrepresentableChar = '\xFFFD'---- It is extraordinarily important that this series of--- predicates/transformers gets inlined, because they tend to be used--- in inner loops related to text encoding. In particular,--- surrogatifyRoundtripCharacter must be inlined (see #5536)---- | Some characters are actually "surrogate" codepoints defined for--- use in UTF-16. We need to signal an invalid character if we detect--- them when encoding a sequence of 'Char's into 'Word8's because they--- won't give valid Unicode.------ We may also need to signal an invalid character if we detect them--- when encoding a sequence of 'Char's into 'Word8's because the--- 'RoundtripFailure' mode creates these to round-trip bytes through--- our internal UTF-16 encoding.-{-# INLINE isSurrogate #-}-isSurrogate :: Char -> Bool-isSurrogate c = (0xD800 <= x && x <= 0xDBFF)- || (0xDC00 <= x && x <= 0xDFFF)- where x = ord c---- Bytes (in Buffer Word8) --> lone surrogates (in Buffer CharBufElem)-{-# INLINE escapeToRoundtripCharacterSurrogate #-}-escapeToRoundtripCharacterSurrogate :: Word8 -> Char-escapeToRoundtripCharacterSurrogate b- | b < 128 = chr (fromIntegral b)- -- Disallow 'smuggling' of ASCII bytes. For roundtripping to- -- work, this assumes encoding is ASCII-superset.- | otherwise = chr (0xDC00 + fromIntegral b)---- Lone surrogates (in Buffer CharBufElem) --> bytes (in Buffer Word8)-{-# INLINE unescapeRoundtripCharacterSurrogate #-}-unescapeRoundtripCharacterSurrogate :: Char -> Maybe Word8-unescapeRoundtripCharacterSurrogate c- | 0xDC80 <= x && x < 0xDD00 = Just (fromIntegral x) -- Discard high byte- | otherwise = Nothing- where x = ord c--recoverDecode :: CodingFailureMode -> Buffer Word8 -> Buffer Char- -> IO (Buffer Word8, Buffer Char)-recoverDecode cfm input@Buffer{ bufRaw=iraw, bufL=ir, bufR=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow } = do- --puts $ "recoverDecode " ++ show ir- case cfm of- ErrorOnCodingFailure -> ioe_decodingError- IgnoreCodingFailure -> return (input { bufL=ir+1 }, output)- TransliterateCodingFailure -> do- ow' <- writeCharBuf oraw ow unrepresentableChar- return (input { bufL=ir+1 }, output { bufR=ow' })- RoundtripFailure -> do- b <- readWord8Buf iraw ir- ow' <- writeCharBuf oraw ow (escapeToRoundtripCharacterSurrogate b)- return (input { bufL=ir+1 }, output { bufR=ow' })--recoverEncode :: CodingFailureMode -> Buffer Char -> Buffer Word8- -> IO (Buffer Char, Buffer Word8)-recoverEncode cfm input@Buffer{ bufRaw=iraw, bufL=ir, bufR=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow } = do- (c,ir') <- readCharBuf iraw ir- --puts $ "recoverEncode " ++ show ir ++ " " ++ show ir'- case cfm of- IgnoreCodingFailure -> return (input { bufL=ir' }, output)- TransliterateCodingFailure -> do- if c == '?'- then return (input { bufL=ir' }, output)- else do- -- XXX: evil hack! To implement transliteration, we just- -- poke an ASCII ? into the input buffer and tell the caller- -- to try and decode again. This is *probably* safe given- -- current uses of TextEncoding.- --- -- The "if" test above ensures we skip if the encoding fails- -- to deal with the ?, though this should never happen in- -- practice as all encodings are in fact capable of- -- reperesenting all ASCII characters.- _ir' <- writeCharBuf iraw ir '?'- return (input, output)- - -- This implementation does not work because e.g. UTF-16- -- requires 2 bytes to encode a simple ASCII value- --writeWord8Buf oraw ow unrepresentableByte- --return (input { bufL=ir' }, output { bufR=ow+1 })- RoundtripFailure | Just x <- unescapeRoundtripCharacterSurrogate c -> do- writeWord8Buf oraw ow x- return (input { bufL=ir' }, output { bufR=ow+1 })- _ -> ioe_encodingError--ioe_decodingError :: IO a-ioe_decodingError = ioException- (IOError Nothing InvalidArgument "recoverDecode"- "invalid byte sequence" Nothing Nothing)--ioe_encodingError :: IO a-ioe_encodingError = ioException- (IOError Nothing InvalidArgument "recoverEncode"- "invalid character" Nothing Nothing)-
@@ -1,187 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , ForeignFunctionInterface- , NondecreasingIndentation- #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.Iconv--- Copyright : (c) The University of Glasgow, 2008-2009--- License : see libraries/base/LICENSE------ Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ This module provides text encoding/decoding using iconv------------------------------------------------------------------------------------- #hide-module GHC.IO.Encoding.Iconv (-#if !defined(mingw32_HOST_OS)- iconvEncoding, mkIconvEncoding,- localeEncodingName-#endif- ) where--#include "MachDeps.h"-#include "HsBaseConfig.h"--#if !defined(mingw32_HOST_OS)--import Foreign.Safe-import Foreign.C-import Data.Maybe-import GHC.Base-import GHC.IO.Buffer-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types-import GHC.List (span)-import GHC.Num-import GHC.Show-import GHC.Real-import System.IO.Unsafe (unsafePerformIO)-import System.Posix.Internals--c_DEBUG_DUMP :: Bool-c_DEBUG_DUMP = False--iconv_trace :: String -> IO ()-iconv_trace s- | c_DEBUG_DUMP = puts s- | otherwise = return ()---- -------------------------------------------------------------------------------- iconv encoders/decoders--{-# NOINLINE localeEncodingName #-}-localeEncodingName :: String-localeEncodingName = unsafePerformIO $ do- -- Use locale_charset() or nl_langinfo(CODESET) to get the encoding- -- if we have either of them.- cstr <- c_localeEncoding- peekCAString cstr -- Assume charset names are ASCII---- We hope iconv_t is a storable type. It should be, since it has at least the--- value -1, which is a possible return value from iconv_open.-type IConv = CLong -- ToDo: (#type iconv_t)--foreign import ccall unsafe "hs_iconv_open"- hs_iconv_open :: CString -> CString -> IO IConv--foreign import ccall unsafe "hs_iconv_close"- hs_iconv_close :: IConv -> IO CInt--foreign import ccall unsafe "hs_iconv"- hs_iconv :: IConv -> Ptr CString -> Ptr CSize -> Ptr CString -> Ptr CSize- -> IO CSize--foreign import ccall unsafe "localeEncoding"- c_localeEncoding :: IO CString--haskellChar :: String-#ifdef WORDS_BIGENDIAN-haskellChar | charSize == 2 = "UTF-16BE"- | otherwise = "UTF-32BE"-#else-haskellChar | charSize == 2 = "UTF-16LE"- | otherwise = "UTF-32LE"-#endif--char_shift :: Int-char_shift | charSize == 2 = 1- | otherwise = 2--iconvEncoding :: String -> IO TextEncoding-iconvEncoding = mkIconvEncoding ErrorOnCodingFailure--mkIconvEncoding :: CodingFailureMode -> String -> IO TextEncoding-mkIconvEncoding cfm charset = do- return (TextEncoding {- textEncodingName = charset,- mkTextDecoder = newIConv raw_charset (haskellChar ++ suffix) (recoverDecode cfm) iconvDecode,- mkTextEncoder = newIConv haskellChar charset (recoverEncode cfm) iconvEncode})- where- -- An annoying feature of GNU iconv is that the //PREFIXES only take- -- effect when they appear on the tocode parameter to iconv_open:- (raw_charset, suffix) = span (/= '/') charset--newIConv :: String -> String- -> (Buffer a -> Buffer b -> IO (Buffer a, Buffer b))- -> (IConv -> Buffer a -> Buffer b -> IO (CodingProgress, Buffer a, Buffer b))- -> IO (BufferCodec a b ())-newIConv from to rec fn =- -- Assume charset names are ASCII- withCAString from $ \ from_str ->- withCAString to $ \ to_str -> do- iconvt <- throwErrnoIfMinus1 "mkTextEncoding" $ hs_iconv_open to_str from_str- let iclose = throwErrnoIfMinus1_ "Iconv.close" $ hs_iconv_close iconvt- return BufferCodec{- encode = fn iconvt,- recover = rec,- close = iclose,- -- iconv doesn't supply a way to save/restore the state- getState = return (),- setState = const $ return ()- }--iconvDecode :: IConv -> DecodeBuffer-iconvDecode iconv_t ibuf obuf = iconvRecode iconv_t ibuf 0 obuf char_shift--iconvEncode :: IConv -> EncodeBuffer-iconvEncode iconv_t ibuf obuf = iconvRecode iconv_t ibuf char_shift obuf 0--iconvRecode :: IConv -> Buffer a -> Int -> Buffer b -> Int- -> IO (CodingProgress, Buffer a, Buffer b)-iconvRecode iconv_t- input@Buffer{ bufRaw=iraw, bufL=ir, bufR=iw, bufSize=_ } iscale- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow, bufSize=os } oscale- = do- iconv_trace ("haskellChar=" ++ show haskellChar)- iconv_trace ("iconvRecode before, input=" ++ show (summaryBuffer input))- iconv_trace ("iconvRecode before, output=" ++ show (summaryBuffer output))- withRawBuffer iraw $ \ piraw -> do- withRawBuffer oraw $ \ poraw -> do- with (piraw `plusPtr` (ir `shiftL` iscale)) $ \ p_inbuf -> do- with (poraw `plusPtr` (ow `shiftL` oscale)) $ \ p_outbuf -> do- with (fromIntegral ((iw-ir) `shiftL` iscale)) $ \ p_inleft -> do- with (fromIntegral ((os-ow) `shiftL` oscale)) $ \ p_outleft -> do- res <- hs_iconv iconv_t p_inbuf p_inleft p_outbuf p_outleft- new_inleft <- peek p_inleft- new_outleft <- peek p_outleft- let- new_inleft' = fromIntegral new_inleft `shiftR` iscale- new_outleft' = fromIntegral new_outleft `shiftR` oscale- new_input- | new_inleft == 0 = input { bufL = 0, bufR = 0 }- | otherwise = input { bufL = iw - new_inleft' }- new_output = output{ bufR = os - new_outleft' }- iconv_trace ("iconv res=" ++ show res)- iconv_trace ("iconvRecode after, input=" ++ show (summaryBuffer new_input))- iconv_trace ("iconvRecode after, output=" ++ show (summaryBuffer new_output))- if (res /= -1)- then do -- all input translated- return (InputUnderflow, new_input, new_output)- else do- errno <- getErrno- case errno of- e | e == e2BIG -> return (OutputUnderflow, new_input, new_output)- | e == eINVAL -> return (InputUnderflow, new_input, new_output)- -- Sometimes iconv reports EILSEQ for a- -- character in the input even when there is no room- -- in the output; in this case we might be about to- -- change the encoding anyway, so the following bytes- -- could very well be in a different encoding.- --- -- Because we can only say InvalidSequence if there is at least- -- one element left in the output, we have to special case this.- | e == eILSEQ -> return (if new_outleft' == 0 then OutputUnderflow else InvalidSequence, new_input, new_output)- | otherwise -> do- iconv_trace ("iconv returned error: " ++ show (errnoToIOError "iconv" e Nothing Nothing))- throwErrno "iconvRecoder"--#endif /* !mingw32_HOST_OS */-
@@ -1,153 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude- , BangPatterns- , NondecreasingIndentation- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.Latin1--- Copyright : (c) The University of Glasgow, 2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ UTF-32 Codecs for the IO library------ Portions Copyright : (c) Tom Harper 2008-2009,--- (c) Bryan O'Sullivan 2009,--- (c) Duncan Coutts 2009-----------------------------------------------------------------------------------module GHC.IO.Encoding.Latin1 (- latin1, mkLatin1,- latin1_checked, mkLatin1_checked,- latin1_decode,- latin1_encode,- latin1_checked_encode,- ) where--import GHC.Base-import GHC.Real-import GHC.Num--- import GHC.IO-import GHC.IO.Buffer-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types---- -------------------------------------------------------------------------------- Latin1--latin1 :: TextEncoding-latin1 = mkLatin1 ErrorOnCodingFailure--mkLatin1 :: CodingFailureMode -> TextEncoding-mkLatin1 cfm = TextEncoding { textEncodingName = "ISO8859-1",- mkTextDecoder = latin1_DF cfm,- mkTextEncoder = latin1_EF cfm }--latin1_DF :: CodingFailureMode -> IO (TextDecoder ())-latin1_DF cfm =- return (BufferCodec {- encode = latin1_decode,- recover = recoverDecode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--latin1_EF :: CodingFailureMode -> IO (TextEncoder ())-latin1_EF cfm =- return (BufferCodec {- encode = latin1_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--latin1_checked :: TextEncoding-latin1_checked = mkLatin1_checked ErrorOnCodingFailure--mkLatin1_checked :: CodingFailureMode -> TextEncoding-mkLatin1_checked cfm = TextEncoding { textEncodingName = "ISO8859-1(checked)",- mkTextDecoder = latin1_DF cfm,- mkTextEncoder = latin1_checked_EF cfm }--latin1_checked_EF :: CodingFailureMode -> IO (TextEncoder ())-latin1_checked_EF cfm =- return (BufferCodec {- encode = latin1_checked_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })---latin1_decode :: DecodeBuffer-latin1_decode - input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- c0 <- readWord8Buf iraw ir- ow' <- writeCharBuf oraw ow (unsafeChr (fromIntegral c0))- loop (ir+1) ow'-- -- lambda-lifted, to avoid thunks being built in the inner-loop:- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- in- loop ir0 ow0--latin1_encode :: EncodeBuffer-latin1_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- writeWord8Buf oraw ow (fromIntegral (ord c))- loop ir' (ow+1)- in- loop ir0 ow0--latin1_checked_encode :: EncodeBuffer-latin1_checked_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- if ord c > 0xff then invalid else do- writeWord8Buf oraw ow (fromIntegral (ord c))- loop ir' (ow+1)- where- invalid = done InvalidSequence ir ow- in- loop ir0 ow0-
@@ -1,134 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, ExistentialQuantification #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.Types--- Copyright : (c) The University of Glasgow, 2008-2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Types for text encoding/decoding-----------------------------------------------------------------------------------module GHC.IO.Encoding.Types (- BufferCodec(..),- TextEncoding(..),- TextEncoder, TextDecoder,- EncodeBuffer, DecodeBuffer,- CodingProgress(..)- ) where--import GHC.Base-import GHC.Word-import GHC.Show--- import GHC.IO-import GHC.IO.Buffer---- -------------------------------------------------------------------------------- Text encoders/decoders--data BufferCodec from to state = BufferCodec {- encode :: Buffer from -> Buffer to -> IO (CodingProgress, Buffer from, Buffer to),- -- ^ The @encode@ function translates elements of the buffer @from@- -- to the buffer @to@. It should translate as many elements as possible- -- given the sizes of the buffers, including translating zero elements- -- if there is either not enough room in @to@, or @from@ does not- -- contain a complete multibyte sequence.- --- -- The fact that as many elements as possible are translated is used by the IO- -- library in order to report translation errors at the point they- -- actually occur, rather than when the buffer is translated.- --- -- To allow us to use iconv as a BufferCode efficiently, character buffers are- -- defined to contain lone surrogates instead of those private use characters that- -- are used for roundtripping. Thus, Chars poked and peeked from a character buffer- -- must undergo surrogatifyRoundtripCharacter and desurrogatifyRoundtripCharacter- -- respectively.- --- -- For more information on this, see Note [Roundtripping] in GHC.IO.Encoding.Failure.- - recover :: Buffer from -> Buffer to -> IO (Buffer from, Buffer to),- -- ^ The @recover@ function is used to continue decoding- -- in the presence of invalid or unrepresentable sequences. This includes- -- both those detected by @encode@ returning @InvalidSequence@ and those- -- that occur because the input byte sequence appears to be truncated.- --- -- Progress will usually be made by skipping the first element of the @from@- -- buffer. This function should only be called if you are certain that you- -- wish to do this skipping and if the @to@ buffer has at least one element- -- of free space. Because this function deals with decoding failure, it assumes- -- that the from buffer has at least one element.- --- -- @recover@ may raise an exception rather than skipping anything.- --- -- Currently, some implementations of @recover@ may mutate the input buffer.- -- In particular, this feature is used to implement transliteration.- - close :: IO (),- -- ^ Resources associated with the encoding may now be released.- -- The @encode@ function may not be called again after calling- -- @close@.-- getState :: IO state,- -- ^ Return the current state of the codec.- --- -- Many codecs are not stateful, and in these case the state can be- -- represented as '()'. Other codecs maintain a state. For- -- example, UTF-16 recognises a BOM (byte-order-mark) character at- -- the beginning of the input, and remembers thereafter whether to- -- use big-endian or little-endian mode. In this case, the state- -- of the codec would include two pieces of information: whether we- -- are at the beginning of the stream (the BOM only occurs at the- -- beginning), and if not, whether to use the big or little-endian- -- encoding.-- setState :: state -> IO ()- -- restore the state of the codec using the state from a previous- -- call to 'getState'.- }--type DecodeBuffer = Buffer Word8 -> Buffer Char- -> IO (CodingProgress, Buffer Word8, Buffer Char)--type EncodeBuffer = Buffer Char -> Buffer Word8- -> IO (CodingProgress, Buffer Char, Buffer Word8)--type TextDecoder state = BufferCodec Word8 CharBufElem state-type TextEncoder state = BufferCodec CharBufElem Word8 state---- | A 'TextEncoding' is a specification of a conversion scheme--- between sequences of bytes and sequences of Unicode characters.------ For example, UTF-8 is an encoding of Unicode characters into a sequence--- of bytes. The 'TextEncoding' for UTF-8 is 'utf8'.-data TextEncoding- = forall dstate estate . TextEncoding {- textEncodingName :: String,- -- ^ a string that can be passed to 'mkTextEncoding' to- -- create an equivalent 'TextEncoding'.- mkTextDecoder :: IO (TextDecoder dstate),- -- ^ Creates a means of decoding bytes into characters: the result must not- -- be shared between several byte sequences or simultaneously across threads- mkTextEncoder :: IO (TextEncoder estate)- -- ^ Creates a means of encode characters into bytes: the result must not- -- be shared between several character sequences or simultaneously across threads- }--instance Show TextEncoding where- -- | Returns the value of 'textEncodingName'- show te = textEncodingName te--data CodingProgress = InputUnderflow -- ^ Stopped because the input contains insufficient available elements,- -- or all of the input sequence has been sucessfully translated.- | OutputUnderflow -- ^ Stopped because the output contains insufficient free elements- | InvalidSequence -- ^ Stopped because there are sufficient free elements in the output- -- to output at least one encoded ASCII character, but the input contains- -- an invalid or unrepresentable sequence- deriving (Eq, Show)-
@@ -1,358 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , BangPatterns- , NondecreasingIndentation- , MagicHash- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.UTF16--- Copyright : (c) The University of Glasgow, 2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ UTF-16 Codecs for the IO library------ Portions Copyright : (c) Tom Harper 2008-2009,--- (c) Bryan O'Sullivan 2009,--- (c) Duncan Coutts 2009-----------------------------------------------------------------------------------module GHC.IO.Encoding.UTF16 (- utf16, mkUTF16,- utf16_decode,- utf16_encode,-- utf16be, mkUTF16be,- utf16be_decode,- utf16be_encode,-- utf16le, mkUTF16le,- utf16le_decode,- utf16le_encode,- ) where--import GHC.Base-import GHC.Real-import GHC.Num--- import GHC.IO-import GHC.IO.Buffer-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types-import GHC.Word-import Data.Bits-import Data.Maybe-import GHC.IORef---- -------------------------------------------------------------------------------- The UTF-16 codec: either UTF16BE or UTF16LE with a BOM--utf16 :: TextEncoding-utf16 = mkUTF16 ErrorOnCodingFailure--mkUTF16 :: CodingFailureMode -> TextEncoding-mkUTF16 cfm = TextEncoding { textEncodingName = "UTF-16",- mkTextDecoder = utf16_DF cfm,- mkTextEncoder = utf16_EF cfm }--utf16_DF :: CodingFailureMode -> IO (TextDecoder (Maybe DecodeBuffer))-utf16_DF cfm = do- seen_bom <- newIORef Nothing- return (BufferCodec {- encode = utf16_decode seen_bom,- recover = recoverDecode cfm,- close = return (),- getState = readIORef seen_bom,- setState = writeIORef seen_bom- })--utf16_EF :: CodingFailureMode -> IO (TextEncoder Bool)-utf16_EF cfm = do- done_bom <- newIORef False- return (BufferCodec {- encode = utf16_encode done_bom,- recover = recoverEncode cfm,- close = return (),- getState = readIORef done_bom,- setState = writeIORef done_bom- })--utf16_encode :: IORef Bool -> EncodeBuffer-utf16_encode done_bom input- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow, bufSize=os }- = do- b <- readIORef done_bom- if b then utf16_native_encode input output- else if os - ow < 2- then return (OutputUnderflow,input,output)- else do- writeIORef done_bom True- writeWord8Buf oraw ow bom1- writeWord8Buf oraw (ow+1) bom2- utf16_native_encode input output{ bufR = ow+2 }--utf16_decode :: IORef (Maybe DecodeBuffer) -> DecodeBuffer-utf16_decode seen_bom- input@Buffer{ bufRaw=iraw, bufL=ir, bufR=iw, bufSize=_ }- output- = do- mb <- readIORef seen_bom- case mb of- Just decode -> decode input output- Nothing ->- if iw - ir < 2 then return (InputUnderflow,input,output) else do- c0 <- readWord8Buf iraw ir- c1 <- readWord8Buf iraw (ir+1)- case () of- _ | c0 == bomB && c1 == bomL -> do- writeIORef seen_bom (Just utf16be_decode)- utf16be_decode input{ bufL= ir+2 } output- | c0 == bomL && c1 == bomB -> do- writeIORef seen_bom (Just utf16le_decode)- utf16le_decode input{ bufL= ir+2 } output- | otherwise -> do- writeIORef seen_bom (Just utf16_native_decode)- utf16_native_decode input output---bomB, bomL, bom1, bom2 :: Word8-bomB = 0xfe-bomL = 0xff---- choose UTF-16BE by default for UTF-16 output-utf16_native_decode :: DecodeBuffer-utf16_native_decode = utf16be_decode--utf16_native_encode :: EncodeBuffer-utf16_native_encode = utf16be_encode--bom1 = bomB-bom2 = bomL---- -------------------------------------------------------------------------------- UTF16LE and UTF16BE--utf16be :: TextEncoding-utf16be = mkUTF16be ErrorOnCodingFailure--mkUTF16be :: CodingFailureMode -> TextEncoding-mkUTF16be cfm = TextEncoding { textEncodingName = "UTF-16BE",- mkTextDecoder = utf16be_DF cfm,- mkTextEncoder = utf16be_EF cfm }--utf16be_DF :: CodingFailureMode -> IO (TextDecoder ())-utf16be_DF cfm =- return (BufferCodec {- encode = utf16be_decode,- recover = recoverDecode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf16be_EF :: CodingFailureMode -> IO (TextEncoder ())-utf16be_EF cfm =- return (BufferCodec {- encode = utf16be_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf16le :: TextEncoding-utf16le = mkUTF16le ErrorOnCodingFailure--mkUTF16le :: CodingFailureMode -> TextEncoding-mkUTF16le cfm = TextEncoding { textEncodingName = "UTF16-LE",- mkTextDecoder = utf16le_DF cfm,- mkTextEncoder = utf16le_EF cfm }--utf16le_DF :: CodingFailureMode -> IO (TextDecoder ())-utf16le_DF cfm =- return (BufferCodec {- encode = utf16le_decode,- recover = recoverDecode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf16le_EF :: CodingFailureMode -> IO (TextEncoder ())-utf16le_EF cfm =- return (BufferCodec {- encode = utf16le_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })---utf16be_decode :: DecodeBuffer-utf16be_decode - input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | ir + 1 == iw = done InputUnderflow ir ow- | otherwise = do- c0 <- readWord8Buf iraw ir- c1 <- readWord8Buf iraw (ir+1)- let x1 = fromIntegral c0 `shiftL` 8 + fromIntegral c1- if validate1 x1- then do ow' <- writeCharBuf oraw ow (unsafeChr (fromIntegral x1))- loop (ir+2) ow'- else if iw - ir < 4 then done InputUnderflow ir ow else do- c2 <- readWord8Buf iraw (ir+2)- c3 <- readWord8Buf iraw (ir+3)- let x2 = fromIntegral c2 `shiftL` 8 + fromIntegral c3- if not (validate2 x1 x2) then invalid else do- ow' <- writeCharBuf oraw ow (chr2 x1 x2)- loop (ir+4) ow'- where- invalid = done InvalidSequence ir ow-- -- lambda-lifted, to avoid thunks being built in the inner-loop:- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- in- loop ir0 ow0--utf16le_decode :: DecodeBuffer-utf16le_decode - input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | ir + 1 == iw = done InputUnderflow ir ow- | otherwise = do- c0 <- readWord8Buf iraw ir- c1 <- readWord8Buf iraw (ir+1)- let x1 = fromIntegral c1 `shiftL` 8 + fromIntegral c0- if validate1 x1- then do ow' <- writeCharBuf oraw ow (unsafeChr (fromIntegral x1))- loop (ir+2) ow'- else if iw - ir < 4 then done InputUnderflow ir ow else do- c2 <- readWord8Buf iraw (ir+2)- c3 <- readWord8Buf iraw (ir+3)- let x2 = fromIntegral c3 `shiftL` 8 + fromIntegral c2- if not (validate2 x1 x2) then invalid else do- ow' <- writeCharBuf oraw ow (chr2 x1 x2)- loop (ir+4) ow'- where- invalid = done InvalidSequence ir ow-- -- lambda-lifted, to avoid thunks being built in the inner-loop:- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- in- loop ir0 ow0--utf16be_encode :: EncodeBuffer-utf16be_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ir >= iw = done InputUnderflow ir ow- | os - ow < 2 = done OutputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- case ord c of- x | x < 0x10000 -> if isSurrogate c then done InvalidSequence ir ow else do- writeWord8Buf oraw ow (fromIntegral (x `shiftR` 8))- writeWord8Buf oraw (ow+1) (fromIntegral x)- loop ir' (ow+2)- | otherwise -> do- if os - ow < 4 then done OutputUnderflow ir ow else do- let - n1 = x - 0x10000- c1 = fromIntegral (n1 `shiftR` 18 + 0xD8)- c2 = fromIntegral (n1 `shiftR` 10)- n2 = n1 .&. 0x3FF- c3 = fromIntegral (n2 `shiftR` 8 + 0xDC)- c4 = fromIntegral n2- --- writeWord8Buf oraw ow c1- writeWord8Buf oraw (ow+1) c2- writeWord8Buf oraw (ow+2) c3- writeWord8Buf oraw (ow+3) c4- loop ir' (ow+4)- in- loop ir0 ow0--utf16le_encode :: EncodeBuffer-utf16le_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ir >= iw = done InputUnderflow ir ow- | os - ow < 2 = done OutputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- case ord c of- x | x < 0x10000 -> if isSurrogate c then done InvalidSequence ir ow else do- writeWord8Buf oraw ow (fromIntegral x)- writeWord8Buf oraw (ow+1) (fromIntegral (x `shiftR` 8))- loop ir' (ow+2)- | otherwise ->- if os - ow < 4 then done OutputUnderflow ir ow else do- let - n1 = x - 0x10000- c1 = fromIntegral (n1 `shiftR` 18 + 0xD8)- c2 = fromIntegral (n1 `shiftR` 10)- n2 = n1 .&. 0x3FF- c3 = fromIntegral (n2 `shiftR` 8 + 0xDC)- c4 = fromIntegral n2- --- writeWord8Buf oraw ow c2- writeWord8Buf oraw (ow+1) c1- writeWord8Buf oraw (ow+2) c4- writeWord8Buf oraw (ow+3) c3- loop ir' (ow+4)- in- loop ir0 ow0--chr2 :: Word16 -> Word16 -> Char-chr2 (W16# a#) (W16# b#) = C# (chr# (upper# +# lower# +# 0x10000#))- where- !x# = word2Int# a#- !y# = word2Int# b#- !upper# = uncheckedIShiftL# (x# -# 0xD800#) 10#- !lower# = y# -# 0xDC00#-{-# INLINE chr2 #-}--validate1 :: Word16 -> Bool-validate1 x1 = (x1 >= 0 && x1 < 0xD800) || x1 > 0xDFFF-{-# INLINE validate1 #-}--validate2 :: Word16 -> Word16 -> Bool-validate2 x1 x2 = x1 >= 0xD800 && x1 <= 0xDBFF &&- x2 >= 0xDC00 && x2 <= 0xDFFF-{-# INLINE validate2 #-}-
@@ -1,334 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude- , BangPatterns- , NondecreasingIndentation- , MagicHash- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.UTF32--- Copyright : (c) The University of Glasgow, 2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ UTF-32 Codecs for the IO library------ Portions Copyright : (c) Tom Harper 2008-2009,--- (c) Bryan O'Sullivan 2009,--- (c) Duncan Coutts 2009-----------------------------------------------------------------------------------module GHC.IO.Encoding.UTF32 (- utf32, mkUTF32,- utf32_decode,- utf32_encode,-- utf32be, mkUTF32be,- utf32be_decode,- utf32be_encode,-- utf32le, mkUTF32le,- utf32le_decode,- utf32le_encode,- ) where--import GHC.Base-import GHC.Real-import GHC.Num--- import GHC.IO-import GHC.IO.Buffer-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types-import GHC.Word-import Data.Bits-import Data.Maybe-import GHC.IORef---- -------------------------------------------------------------------------------- The UTF-32 codec: either UTF-32BE or UTF-32LE with a BOM--utf32 :: TextEncoding-utf32 = mkUTF32 ErrorOnCodingFailure--mkUTF32 :: CodingFailureMode -> TextEncoding-mkUTF32 cfm = TextEncoding { textEncodingName = "UTF-32",- mkTextDecoder = utf32_DF cfm,- mkTextEncoder = utf32_EF cfm }--utf32_DF :: CodingFailureMode -> IO (TextDecoder (Maybe DecodeBuffer))-utf32_DF cfm = do- seen_bom <- newIORef Nothing- return (BufferCodec {- encode = utf32_decode seen_bom,- recover = recoverDecode cfm,- close = return (),- getState = readIORef seen_bom,- setState = writeIORef seen_bom- })--utf32_EF :: CodingFailureMode -> IO (TextEncoder Bool)-utf32_EF cfm = do- done_bom <- newIORef False- return (BufferCodec {- encode = utf32_encode done_bom,- recover = recoverEncode cfm,- close = return (),- getState = readIORef done_bom,- setState = writeIORef done_bom- })--utf32_encode :: IORef Bool -> EncodeBuffer-utf32_encode done_bom input- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow, bufSize=os }- = do- b <- readIORef done_bom- if b then utf32_native_encode input output- else if os - ow < 4- then return (OutputUnderflow, input,output)- else do- writeIORef done_bom True- writeWord8Buf oraw ow bom0- writeWord8Buf oraw (ow+1) bom1- writeWord8Buf oraw (ow+2) bom2- writeWord8Buf oraw (ow+3) bom3- utf32_native_encode input output{ bufR = ow+4 }--utf32_decode :: IORef (Maybe DecodeBuffer) -> DecodeBuffer-utf32_decode seen_bom- input@Buffer{ bufRaw=iraw, bufL=ir, bufR=iw, bufSize=_ }- output- = do- mb <- readIORef seen_bom- case mb of- Just decode -> decode input output- Nothing ->- if iw - ir < 4 then return (InputUnderflow, input,output) else do- c0 <- readWord8Buf iraw ir- c1 <- readWord8Buf iraw (ir+1)- c2 <- readWord8Buf iraw (ir+2)- c3 <- readWord8Buf iraw (ir+3)- case () of- _ | c0 == bom0 && c1 == bom1 && c2 == bom2 && c3 == bom3 -> do- writeIORef seen_bom (Just utf32be_decode)- utf32be_decode input{ bufL= ir+4 } output- _ | c0 == bom3 && c1 == bom2 && c2 == bom1 && c3 == bom0 -> do- writeIORef seen_bom (Just utf32le_decode)- utf32le_decode input{ bufL= ir+4 } output- | otherwise -> do- writeIORef seen_bom (Just utf32_native_decode)- utf32_native_decode input output---bom0, bom1, bom2, bom3 :: Word8-bom0 = 0-bom1 = 0-bom2 = 0xfe-bom3 = 0xff---- choose UTF-32BE by default for UTF-32 output-utf32_native_decode :: DecodeBuffer-utf32_native_decode = utf32be_decode--utf32_native_encode :: EncodeBuffer-utf32_native_encode = utf32be_encode---- -------------------------------------------------------------------------------- UTF32LE and UTF32BE--utf32be :: TextEncoding-utf32be = mkUTF32be ErrorOnCodingFailure--mkUTF32be :: CodingFailureMode -> TextEncoding-mkUTF32be cfm = TextEncoding { textEncodingName = "UTF-32BE",- mkTextDecoder = utf32be_DF cfm,- mkTextEncoder = utf32be_EF cfm }--utf32be_DF :: CodingFailureMode -> IO (TextDecoder ())-utf32be_DF cfm =- return (BufferCodec {- encode = utf32be_decode,- recover = recoverDecode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf32be_EF :: CodingFailureMode -> IO (TextEncoder ())-utf32be_EF cfm =- return (BufferCodec {- encode = utf32be_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })---utf32le :: TextEncoding-utf32le = mkUTF32le ErrorOnCodingFailure--mkUTF32le :: CodingFailureMode -> TextEncoding-mkUTF32le cfm = TextEncoding { textEncodingName = "UTF-32LE",- mkTextDecoder = utf32le_DF cfm,- mkTextEncoder = utf32le_EF cfm }--utf32le_DF :: CodingFailureMode -> IO (TextDecoder ())-utf32le_DF cfm =- return (BufferCodec {- encode = utf32le_decode,- recover = recoverDecode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf32le_EF :: CodingFailureMode -> IO (TextEncoder ())-utf32le_EF cfm =- return (BufferCodec {- encode = utf32le_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })---utf32be_decode :: DecodeBuffer-utf32be_decode - input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | iw - ir < 4 = done InputUnderflow ir ow- | otherwise = do- c0 <- readWord8Buf iraw ir- c1 <- readWord8Buf iraw (ir+1)- c2 <- readWord8Buf iraw (ir+2)- c3 <- readWord8Buf iraw (ir+3)- let x1 = chr4 c0 c1 c2 c3- if not (validate x1) then invalid else do- ow' <- writeCharBuf oraw ow x1- loop (ir+4) ow'- where- invalid = done InvalidSequence ir ow-- -- lambda-lifted, to avoid thunks being built in the inner-loop:- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- in- loop ir0 ow0--utf32le_decode :: DecodeBuffer-utf32le_decode - input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | iw - ir < 4 = done InputUnderflow ir ow- | otherwise = do- c0 <- readWord8Buf iraw ir- c1 <- readWord8Buf iraw (ir+1)- c2 <- readWord8Buf iraw (ir+2)- c3 <- readWord8Buf iraw (ir+3)- let x1 = chr4 c3 c2 c1 c0- if not (validate x1) then invalid else do- ow' <- writeCharBuf oraw ow x1- loop (ir+4) ow'- where- invalid = done InvalidSequence ir ow-- -- lambda-lifted, to avoid thunks being built in the inner-loop:- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- in- loop ir0 ow0--utf32be_encode :: EncodeBuffer-utf32be_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ir >= iw = done InputUnderflow ir ow- | os - ow < 4 = done OutputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- if isSurrogate c then done InvalidSequence ir ow else do- let (c0,c1,c2,c3) = ord4 c- writeWord8Buf oraw ow c0- writeWord8Buf oraw (ow+1) c1- writeWord8Buf oraw (ow+2) c2- writeWord8Buf oraw (ow+3) c3- loop ir' (ow+4)- in- loop ir0 ow0--utf32le_encode :: EncodeBuffer-utf32le_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ir >= iw = done InputUnderflow ir ow- | os - ow < 4 = done OutputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- if isSurrogate c then done InvalidSequence ir ow else do- let (c0,c1,c2,c3) = ord4 c- writeWord8Buf oraw ow c3- writeWord8Buf oraw (ow+1) c2- writeWord8Buf oraw (ow+2) c1- writeWord8Buf oraw (ow+3) c0- loop ir' (ow+4)- in- loop ir0 ow0--chr4 :: Word8 -> Word8 -> Word8 -> Word8 -> Char-chr4 (W8# x1#) (W8# x2#) (W8# x3#) (W8# x4#) =- C# (chr# (z1# +# z2# +# z3# +# z4#))- where- !y1# = word2Int# x1#- !y2# = word2Int# x2#- !y3# = word2Int# x3#- !y4# = word2Int# x4#- !z1# = uncheckedIShiftL# y1# 24#- !z2# = uncheckedIShiftL# y2# 16#- !z3# = uncheckedIShiftL# y3# 8#- !z4# = y4#-{-# INLINE chr4 #-}--ord4 :: Char -> (Word8,Word8,Word8,Word8)-ord4 c = (fromIntegral (x `shiftR` 24), - fromIntegral (x `shiftR` 16), - fromIntegral (x `shiftR` 8),- fromIntegral x)- where- x = ord c-{-# INLINE ord4 #-}---validate :: Char -> Bool-validate c = (x1 >= 0x0 && x1 < 0xD800) || (x1 > 0xDFFF && x1 <= 0x10FFFF)- where x1 = ord c-{-# INLINE validate #-}-
@@ -1,360 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude- , BangPatterns- , NondecreasingIndentation- , MagicHash- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Encoding.UTF8--- Copyright : (c) The University of Glasgow, 2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ UTF-8 Codec for the IO library------ Portions Copyright : (c) Tom Harper 2008-2009,--- (c) Bryan O'Sullivan 2009,--- (c) Duncan Coutts 2009-----------------------------------------------------------------------------------module GHC.IO.Encoding.UTF8 (- utf8, mkUTF8,- utf8_bom, mkUTF8_bom- ) where--import GHC.Base-import GHC.Real-import GHC.Num-import GHC.IORef--- import GHC.IO-import GHC.IO.Buffer-import GHC.IO.Encoding.Failure-import GHC.IO.Encoding.Types-import GHC.Word-import Data.Bits--utf8 :: TextEncoding-utf8 = mkUTF8 ErrorOnCodingFailure--mkUTF8 :: CodingFailureMode -> TextEncoding-mkUTF8 cfm = TextEncoding { textEncodingName = "UTF-8",- mkTextDecoder = utf8_DF cfm,- mkTextEncoder = utf8_EF cfm }---utf8_DF :: CodingFailureMode -> IO (TextDecoder ())-utf8_DF cfm =- return (BufferCodec {- encode = utf8_decode,- recover = recoverDecode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf8_EF :: CodingFailureMode -> IO (TextEncoder ())-utf8_EF cfm =- return (BufferCodec {- encode = utf8_encode,- recover = recoverEncode cfm,- close = return (),- getState = return (),- setState = const $ return ()- })--utf8_bom :: TextEncoding-utf8_bom = mkUTF8_bom ErrorOnCodingFailure--mkUTF8_bom :: CodingFailureMode -> TextEncoding-mkUTF8_bom cfm = TextEncoding { textEncodingName = "UTF-8BOM",- mkTextDecoder = utf8_bom_DF cfm,- mkTextEncoder = utf8_bom_EF cfm }--utf8_bom_DF :: CodingFailureMode -> IO (TextDecoder Bool)-utf8_bom_DF cfm = do- ref <- newIORef True- return (BufferCodec {- encode = utf8_bom_decode ref,- recover = recoverDecode cfm,- close = return (),- getState = readIORef ref,- setState = writeIORef ref- })--utf8_bom_EF :: CodingFailureMode -> IO (TextEncoder Bool)-utf8_bom_EF cfm = do- ref <- newIORef True- return (BufferCodec {- encode = utf8_bom_encode ref,- recover = recoverEncode cfm,- close = return (),- getState = readIORef ref,- setState = writeIORef ref- })--utf8_bom_decode :: IORef Bool -> DecodeBuffer-utf8_bom_decode ref- input@Buffer{ bufRaw=iraw, bufL=ir, bufR=iw, bufSize=_ }- output- = do- first <- readIORef ref- if not first- then utf8_decode input output- else do- let no_bom = do writeIORef ref False; utf8_decode input output- if iw - ir < 1 then return (InputUnderflow,input,output) else do- c0 <- readWord8Buf iraw ir- if (c0 /= bom0) then no_bom else do- if iw - ir < 2 then return (InputUnderflow,input,output) else do- c1 <- readWord8Buf iraw (ir+1)- if (c1 /= bom1) then no_bom else do- if iw - ir < 3 then return (InputUnderflow,input,output) else do- c2 <- readWord8Buf iraw (ir+2)- if (c2 /= bom2) then no_bom else do- -- found a BOM, ignore it and carry on- writeIORef ref False- utf8_decode input{ bufL = ir + 3 } output--utf8_bom_encode :: IORef Bool -> EncodeBuffer-utf8_bom_encode ref input- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow, bufSize=os }- = do- b <- readIORef ref- if not b then utf8_encode input output- else if os - ow < 3- then return (OutputUnderflow,input,output)- else do- writeIORef ref False- writeWord8Buf oraw ow bom0- writeWord8Buf oraw (ow+1) bom1- writeWord8Buf oraw (ow+2) bom2- utf8_encode input output{ bufR = ow+3 }--bom0, bom1, bom2 :: Word8-bom0 = 0xef-bom1 = 0xbb-bom2 = 0xbf--utf8_decode :: DecodeBuffer-utf8_decode - input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- c0 <- readWord8Buf iraw ir- case c0 of- _ | c0 <= 0x7f -> do - ow' <- writeCharBuf oraw ow (unsafeChr (fromIntegral c0))- loop (ir+1) ow'- | c0 >= 0xc0 && c0 <= 0xdf ->- if iw - ir < 2 then done InputUnderflow ir ow else do- c1 <- readWord8Buf iraw (ir+1)- if (c1 < 0x80 || c1 >= 0xc0) then invalid else do- ow' <- writeCharBuf oraw ow (chr2 c0 c1)- loop (ir+2) ow'- | c0 >= 0xe0 && c0 <= 0xef ->- case iw - ir of- 1 -> done InputUnderflow ir ow- 2 -> do -- check for an error even when we don't have- -- the full sequence yet (#3341)- c1 <- readWord8Buf iraw (ir+1)- if not (validate3 c0 c1 0x80) - then invalid else done InputUnderflow ir ow- _ -> do- c1 <- readWord8Buf iraw (ir+1)- c2 <- readWord8Buf iraw (ir+2)- if not (validate3 c0 c1 c2) then invalid else do- ow' <- writeCharBuf oraw ow (chr3 c0 c1 c2)- loop (ir+3) ow'- | c0 >= 0xf0 ->- case iw - ir of- 1 -> done InputUnderflow ir ow- 2 -> do -- check for an error even when we don't have- -- the full sequence yet (#3341)- c1 <- readWord8Buf iraw (ir+1)- if not (validate4 c0 c1 0x80 0x80)- then invalid else done InputUnderflow ir ow- 3 -> do- c1 <- readWord8Buf iraw (ir+1)- c2 <- readWord8Buf iraw (ir+2)- if not (validate4 c0 c1 c2 0x80)- then invalid else done InputUnderflow ir ow- _ -> do- c1 <- readWord8Buf iraw (ir+1)- c2 <- readWord8Buf iraw (ir+2)- c3 <- readWord8Buf iraw (ir+3)- if not (validate4 c0 c1 c2 c3) then invalid else do- ow' <- writeCharBuf oraw ow (chr4 c0 c1 c2 c3)- loop (ir+4) ow'- | otherwise ->- invalid- where- invalid = done InvalidSequence ir ow-- -- lambda-lifted, to avoid thunks being built in the inner-loop:- done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- in- loop ir0 ow0--utf8_encode :: EncodeBuffer-utf8_encode- input@Buffer{ bufRaw=iraw, bufL=ir0, bufR=iw, bufSize=_ }- output@Buffer{ bufRaw=oraw, bufL=_, bufR=ow0, bufSize=os }- = let - done why !ir !ow = return (why,- if ir == iw then input{ bufL=0, bufR=0 }- else input{ bufL=ir },- output{ bufR=ow })- loop !ir !ow- | ow >= os = done OutputUnderflow ir ow- | ir >= iw = done InputUnderflow ir ow- | otherwise = do- (c,ir') <- readCharBuf iraw ir- case ord c of- x | x <= 0x7F -> do- writeWord8Buf oraw ow (fromIntegral x)- loop ir' (ow+1)- | x <= 0x07FF ->- if os - ow < 2 then done OutputUnderflow ir ow else do- let (c1,c2) = ord2 c- writeWord8Buf oraw ow c1- writeWord8Buf oraw (ow+1) c2- loop ir' (ow+2)- | x <= 0xFFFF -> if isSurrogate c then done InvalidSequence ir ow else do- if os - ow < 3 then done OutputUnderflow ir ow else do- let (c1,c2,c3) = ord3 c- writeWord8Buf oraw ow c1- writeWord8Buf oraw (ow+1) c2- writeWord8Buf oraw (ow+2) c3- loop ir' (ow+3)- | otherwise -> do- if os - ow < 4 then done OutputUnderflow ir ow else do- let (c1,c2,c3,c4) = ord4 c- writeWord8Buf oraw ow c1- writeWord8Buf oraw (ow+1) c2- writeWord8Buf oraw (ow+2) c3- writeWord8Buf oraw (ow+3) c4- loop ir' (ow+4)- in- loop ir0 ow0---- -------------------------------------------------------------------------------- UTF-8 primitives, lifted from Data.Text.Fusion.Utf8- -ord2 :: Char -> (Word8,Word8)-ord2 c = assert (n >= 0x80 && n <= 0x07ff) (x1,x2)- where- n = ord c- x1 = fromIntegral $ (n `shiftR` 6) + 0xC0- x2 = fromIntegral $ (n .&. 0x3F) + 0x80--ord3 :: Char -> (Word8,Word8,Word8)-ord3 c = assert (n >= 0x0800 && n <= 0xffff) (x1,x2,x3)- where- n = ord c- x1 = fromIntegral $ (n `shiftR` 12) + 0xE0- x2 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80- x3 = fromIntegral $ (n .&. 0x3F) + 0x80--ord4 :: Char -> (Word8,Word8,Word8,Word8)-ord4 c = assert (n >= 0x10000) (x1,x2,x3,x4)- where- n = ord c- x1 = fromIntegral $ (n `shiftR` 18) + 0xF0- x2 = fromIntegral $ ((n `shiftR` 12) .&. 0x3F) + 0x80- x3 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80- x4 = fromIntegral $ (n .&. 0x3F) + 0x80--chr2 :: Word8 -> Word8 -> Char-chr2 (W8# x1#) (W8# x2#) = C# (chr# (z1# +# z2#))- where- !y1# = word2Int# x1#- !y2# = word2Int# x2#- !z1# = uncheckedIShiftL# (y1# -# 0xC0#) 6#- !z2# = y2# -# 0x80#-{-# INLINE chr2 #-}--chr3 :: Word8 -> Word8 -> Word8 -> Char-chr3 (W8# x1#) (W8# x2#) (W8# x3#) = C# (chr# (z1# +# z2# +# z3#))- where- !y1# = word2Int# x1#- !y2# = word2Int# x2#- !y3# = word2Int# x3#- !z1# = uncheckedIShiftL# (y1# -# 0xE0#) 12#- !z2# = uncheckedIShiftL# (y2# -# 0x80#) 6#- !z3# = y3# -# 0x80#-{-# INLINE chr3 #-}--chr4 :: Word8 -> Word8 -> Word8 -> Word8 -> Char-chr4 (W8# x1#) (W8# x2#) (W8# x3#) (W8# x4#) =- C# (chr# (z1# +# z2# +# z3# +# z4#))- where- !y1# = word2Int# x1#- !y2# = word2Int# x2#- !y3# = word2Int# x3#- !y4# = word2Int# x4#- !z1# = uncheckedIShiftL# (y1# -# 0xF0#) 18#- !z2# = uncheckedIShiftL# (y2# -# 0x80#) 12#- !z3# = uncheckedIShiftL# (y3# -# 0x80#) 6#- !z4# = y4# -# 0x80#-{-# INLINE chr4 #-}--between :: Word8 -- ^ byte to check- -> Word8 -- ^ lower bound- -> Word8 -- ^ upper bound- -> Bool-between x y z = x >= y && x <= z-{-# INLINE between #-}--validate3 :: Word8 -> Word8 -> Word8 -> Bool-{-# INLINE validate3 #-}-validate3 x1 x2 x3 = validate3_1 ||- validate3_2 ||- validate3_3 ||- validate3_4- where- validate3_1 = (x1 == 0xE0) &&- between x2 0xA0 0xBF &&- between x3 0x80 0xBF- validate3_2 = between x1 0xE1 0xEC &&- between x2 0x80 0xBF &&- between x3 0x80 0xBF- validate3_3 = x1 == 0xED &&- between x2 0x80 0x9F &&- between x3 0x80 0xBF- validate3_4 = between x1 0xEE 0xEF &&- between x2 0x80 0xBF &&- between x3 0x80 0xBF--validate4 :: Word8 -> Word8 -> Word8 -> Word8 -> Bool-{-# INLINE validate4 #-}-validate4 x1 x2 x3 x4 = validate4_1 ||- validate4_2 ||- validate4_3- where - validate4_1 = x1 == 0xF0 &&- between x2 0x90 0xBF &&- between x3 0x80 0xBF &&- between x4 0x80 0xBF- validate4_2 = between x1 0xF1 0xF3 &&- between x2 0x80 0xBF &&- between x3 0x80 0xBF &&- between x4 0x80 0xBF- validate4_3 = x1 == 0xF4 &&- between x2 0x80 0x8F &&- between x3 0x80 0xBF &&- between x4 0x80 0xBF-
@@ -1,343 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, DeriveDataTypeable, MagicHash #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Exception--- Copyright : (c) The University of Glasgow, 2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ IO-related Exception types and functions-----------------------------------------------------------------------------------module GHC.IO.Exception (- BlockedIndefinitelyOnMVar(..), blockedIndefinitelyOnMVar,- BlockedIndefinitelyOnSTM(..), blockedIndefinitelyOnSTM,- Deadlock(..),- AssertionFailed(..),- AsyncException(..), stackOverflow, heapOverflow,- ArrayException(..),- ExitCode(..),-- ioException,- ioError,- IOError,- IOException(..),- IOErrorType(..),- userError,- assertError,- unsupportedOperation,- untangle,- ) where--import GHC.Base-import GHC.List-import GHC.IO-import GHC.Show-import GHC.Read-import GHC.Exception-import Data.Maybe-import GHC.IO.Handle.Types-import Foreign.C.Types--import Data.Typeable ( Typeable )---- --------------------------------------------------------------------------- Exception datatypes and operations---- |The thread is blocked on an @MVar@, but there are no other references--- to the @MVar@ so it can't ever continue.-data BlockedIndefinitelyOnMVar = BlockedIndefinitelyOnMVar- deriving Typeable--instance Exception BlockedIndefinitelyOnMVar--instance Show BlockedIndefinitelyOnMVar where- showsPrec _ BlockedIndefinitelyOnMVar = showString "thread blocked indefinitely in an MVar operation"--blockedIndefinitelyOnMVar :: SomeException -- for the RTS-blockedIndefinitelyOnMVar = toException BlockedIndefinitelyOnMVar----------- |The thread is waiting to retry an STM transaction, but there are no--- other references to any @TVar@s involved, so it can't ever continue.-data BlockedIndefinitelyOnSTM = BlockedIndefinitelyOnSTM- deriving Typeable--instance Exception BlockedIndefinitelyOnSTM--instance Show BlockedIndefinitelyOnSTM where- showsPrec _ BlockedIndefinitelyOnSTM = showString "thread blocked indefinitely in an STM transaction"--blockedIndefinitelyOnSTM :: SomeException -- for the RTS-blockedIndefinitelyOnSTM = toException BlockedIndefinitelyOnSTM----------- |There are no runnable threads, so the program is deadlocked.--- The @Deadlock@ exception is raised in the main thread only.-data Deadlock = Deadlock- deriving Typeable--instance Exception Deadlock--instance Show Deadlock where- showsPrec _ Deadlock = showString "<<deadlock>>"----------- |'assert' was applied to 'False'.-data AssertionFailed = AssertionFailed String- deriving Typeable--instance Exception AssertionFailed--instance Show AssertionFailed where- showsPrec _ (AssertionFailed err) = showString err----------- |Asynchronous exceptions.-data AsyncException- = StackOverflow- -- ^The current thread\'s stack exceeded its limit.- -- Since an exception has been raised, the thread\'s stack- -- will certainly be below its limit again, but the- -- programmer should take remedial action- -- immediately.- | HeapOverflow- -- ^The program\'s heap is reaching its limit, and- -- the program should take action to reduce the amount of- -- live data it has. Notes:- --- -- * It is undefined which thread receives this exception.- --- -- * GHC currently does not throw 'HeapOverflow' exceptions.- | ThreadKilled- -- ^This exception is raised by another thread- -- calling 'Control.Concurrent.killThread', or by the system- -- if it needs to terminate the thread for some- -- reason.- | UserInterrupt- -- ^This exception is raised by default in the main thread of- -- the program when the user requests to terminate the program- -- via the usual mechanism(s) (e.g. Control-C in the console).- deriving (Eq, Ord, Typeable)--instance Exception AsyncException---- | Exceptions generated by array operations-data ArrayException- = IndexOutOfBounds String- -- ^An attempt was made to index an array outside- -- its declared bounds.- | UndefinedElement String- -- ^An attempt was made to evaluate an element of an- -- array that had not been initialized.- deriving (Eq, Ord, Typeable)--instance Exception ArrayException--stackOverflow, heapOverflow :: SomeException -- for the RTS-stackOverflow = toException StackOverflow-heapOverflow = toException HeapOverflow--instance Show AsyncException where- showsPrec _ StackOverflow = showString "stack overflow"- showsPrec _ HeapOverflow = showString "heap overflow"- showsPrec _ ThreadKilled = showString "thread killed"- showsPrec _ UserInterrupt = showString "user interrupt"--instance Show ArrayException where- showsPrec _ (IndexOutOfBounds s)- = showString "array index out of range"- . (if not (null s) then showString ": " . showString s- else id)- showsPrec _ (UndefinedElement s)- = showString "undefined array element"- . (if not (null s) then showString ": " . showString s- else id)---- -------------------------------------------------------------------------------- The ExitCode type---- We need it here because it is used in ExitException in the--- Exception datatype (above).---- | Defines the exit codes that a program can return.-data ExitCode- = ExitSuccess -- ^ indicates successful termination;- | ExitFailure Int- -- ^ indicates program failure with an exit code.- -- The exact interpretation of the code is- -- operating-system dependent. In particular, some values- -- may be prohibited (e.g. 0 on a POSIX-compliant system).- deriving (Eq, Ord, Read, Show, Typeable)--instance Exception ExitCode--ioException :: IOException -> IO a-ioException err = throwIO err---- | Raise an 'IOError' in the 'IO' monad.-ioError :: IOError -> IO a -ioError = ioException---- ------------------------------------------------------------------------------ IOError type---- | The Haskell 98 type for exceptions in the 'IO' monad.--- Any I\/O operation may raise an 'IOError' instead of returning a result.--- For a more general type of exception, including also those that arise--- in pure code, see "Control.Exception.Exception".------ In Haskell 98, this is an opaque type.-type IOError = IOException---- |Exceptions that occur in the @IO@ monad.--- An @IOException@ records a more specific error type, a descriptive--- string and maybe the handle that was used when the error was--- flagged.-data IOException- = IOError {- ioe_handle :: Maybe Handle, -- the handle used by the action flagging - -- the error.- ioe_type :: IOErrorType, -- what it was.- ioe_location :: String, -- location.- ioe_description :: String, -- error type specific information.- ioe_errno :: Maybe CInt, -- errno leading to this error, if any.- ioe_filename :: Maybe FilePath -- filename the error is related to.- }- deriving Typeable--instance Exception IOException--instance Eq IOException where- (IOError h1 e1 loc1 str1 en1 fn1) == (IOError h2 e2 loc2 str2 en2 fn2) = - e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && en1==en2 && fn1==fn2---- | An abstract type that contains a value for each variant of 'IOError'.-data IOErrorType- -- Haskell 98:- = AlreadyExists- | NoSuchThing- | ResourceBusy- | ResourceExhausted- | EOF- | IllegalOperation- | PermissionDenied- | UserError- -- GHC only:- | UnsatisfiedConstraints- | SystemError- | ProtocolError- | OtherError- | InvalidArgument- | InappropriateType- | HardwareFault- | UnsupportedOperation- | TimeExpired- | ResourceVanished- | Interrupted--instance Eq IOErrorType where- x == y = getTag x ==# getTag y- -instance Show IOErrorType where- showsPrec _ e =- showString $- case e of- AlreadyExists -> "already exists"- NoSuchThing -> "does not exist"- ResourceBusy -> "resource busy"- ResourceExhausted -> "resource exhausted"- EOF -> "end of file"- IllegalOperation -> "illegal operation"- PermissionDenied -> "permission denied"- UserError -> "user error"- HardwareFault -> "hardware fault"- InappropriateType -> "inappropriate type"- Interrupted -> "interrupted"- InvalidArgument -> "invalid argument"- OtherError -> "failed"- ProtocolError -> "protocol error"- ResourceVanished -> "resource vanished"- SystemError -> "system error"- TimeExpired -> "timeout"- UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!- UnsupportedOperation -> "unsupported operation"---- | Construct an 'IOError' value with a string describing the error.--- The 'fail' method of the 'IO' instance of the 'Monad' class raises a--- 'userError', thus:------ > instance Monad IO where --- > ...--- > fail s = ioError (userError s)----userError :: String -> IOError-userError str = IOError Nothing UserError "" str Nothing Nothing---- ------------------------------------------------------------------------------ Showing IOErrors--instance Show IOException where- showsPrec p (IOError hdl iot loc s _ fn) =- (case fn of- Nothing -> case hdl of- Nothing -> id- Just h -> showsPrec p h . showString ": "- Just name -> showString name . showString ": ") .- (case loc of- "" -> id- _ -> showString loc . showString ": ") .- showsPrec p iot . - (case s of- "" -> id- _ -> showString " (" . showString s . showString ")")---- Note the use of "lazy". This means that--- assert False (throw e)--- will throw the assertion failure rather than e. See trac #5561.-assertError :: Addr# -> Bool -> a -> a-assertError str predicate v- | predicate = lazy v- | otherwise = throw (AssertionFailed (untangle str "Assertion failed"))--unsupportedOperation :: IOError-unsupportedOperation = - (IOError Nothing UnsupportedOperation ""- "Operation is not supported" Nothing Nothing)--{--(untangle coded message) expects "coded" to be of the form- "location|details"-It prints- location message details--}-untangle :: Addr# -> String -> String-untangle coded message- = location- ++ ": "- ++ message- ++ details- ++ "\n"- where- coded_str = unpackCStringUtf8# coded-- (location, details)- = case (span not_bar coded_str) of { (loc, rest) ->- case rest of- ('|':det) -> (loc, ' ' : det)- _ -> (loc, "")- }- not_bar c = c /= '|'-
@@ -1,15 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.IO.Exception where--import GHC.Base-import GHC.Exception--data IOException-instance Exception IOException--type IOError = IOException-userError :: String -> IOError-unsupportedOperation :: IOError-
@@ -1,667 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , BangPatterns- , ForeignFunctionInterface- , DeriveDataTypeable- #-}-{-# OPTIONS_GHC -fno-warn-identities #-}--- Whether there are identities depends on the platform-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.FD--- Copyright : (c) The University of Glasgow, 1994-2008--- License : see libraries/base/LICENSE------ Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Raw read/write operations on file descriptors-----------------------------------------------------------------------------------module GHC.IO.FD (- FD(..),- openFile, mkFD, release,- setNonBlockingMode,- readRawBufferPtr, readRawBufferPtrNoBlock, writeRawBufferPtr,- stdin, stdout, stderr- ) where--import GHC.Base-import GHC.Num-import GHC.Real-import GHC.Show-import GHC.Enum-import Data.Maybe-import Control.Monad-import Data.Typeable--import GHC.IO-import GHC.IO.IOMode-import GHC.IO.Buffer-import GHC.IO.BufferedIO-import qualified GHC.IO.Device-import GHC.IO.Device (SeekMode(..), IODeviceType(..))-import GHC.Conc.IO-import GHC.IO.Exception-#ifdef mingw32_HOST_OS-import GHC.Windows-#endif--import Foreign-import Foreign.C-import qualified System.Posix.Internals-import System.Posix.Internals hiding (FD, setEcho, getEcho)-import System.Posix.Types--c_DEBUG_DUMP :: Bool-c_DEBUG_DUMP = False---- -------------------------------------------------------------------------------- The file-descriptor IO device--data FD = FD {- fdFD :: {-# UNPACK #-} !CInt,-#ifdef mingw32_HOST_OS- -- On Windows, a socket file descriptor needs to be read and written- -- using different functions (send/recv).- fdIsSocket_ :: {-# UNPACK #-} !Int-#else- -- On Unix we need to know whether this FD has O_NONBLOCK set.- -- If it has, then we can use more efficient routines to read/write to it.- -- It is always safe for this to be off.- fdIsNonBlocking :: {-# UNPACK #-} !Int-#endif- }- deriving Typeable--#ifdef mingw32_HOST_OS-fdIsSocket :: FD -> Bool-fdIsSocket fd = fdIsSocket_ fd /= 0-#endif--instance Show FD where- show fd = show (fdFD fd)--instance GHC.IO.Device.RawIO FD where- read = fdRead- readNonBlocking = fdReadNonBlocking- write = fdWrite- writeNonBlocking = fdWriteNonBlocking--instance GHC.IO.Device.IODevice FD where- ready = ready- close = close- isTerminal = isTerminal- isSeekable = isSeekable- seek = seek- tell = tell- getSize = getSize- setSize = setSize- setEcho = setEcho- getEcho = getEcho- setRaw = setRaw- devType = devType- dup = dup- dup2 = dup2---- We used to use System.Posix.Internals.dEFAULT_BUFFER_SIZE, which is--- taken from the value of BUFSIZ on the current platform. This value--- varies too much though: it is 512 on Windows, 1024 on OS X and 8192--- on Linux. So let's just use a decent size on every platform:-dEFAULT_FD_BUFFER_SIZE :: Int-dEFAULT_FD_BUFFER_SIZE = 8096--instance BufferedIO FD where- newBuffer _dev state = newByteBuffer dEFAULT_FD_BUFFER_SIZE state- fillReadBuffer fd buf = readBuf' fd buf- fillReadBuffer0 fd buf = readBufNonBlocking fd buf- flushWriteBuffer fd buf = writeBuf' fd buf- flushWriteBuffer0 fd buf = writeBufNonBlocking fd buf--readBuf' :: FD -> Buffer Word8 -> IO (Int, Buffer Word8)-readBuf' fd buf = do- when c_DEBUG_DUMP $- puts ("readBuf fd=" ++ show fd ++ " " ++ summaryBuffer buf ++ "\n")- (r,buf') <- readBuf fd buf- when c_DEBUG_DUMP $- puts ("after: " ++ summaryBuffer buf' ++ "\n")- return (r,buf')--writeBuf' :: FD -> Buffer Word8 -> IO (Buffer Word8)-writeBuf' fd buf = do- when c_DEBUG_DUMP $- puts ("writeBuf fd=" ++ show fd ++ " " ++ summaryBuffer buf ++ "\n")- writeBuf fd buf---- -------------------------------------------------------------------------------- opening files---- | Open a file and make an 'FD' for it. Truncates the file to zero--- size when the `IOMode` is `WriteMode`.-openFile- :: FilePath -- ^ file to open- -> IOMode -- ^ mode in which to open the file- -> Bool -- ^ open the file in non-blocking mode?- -> IO (FD,IODeviceType)--openFile filepath iomode non_blocking =- withFilePath filepath $ \ f ->-- let - oflags1 = case iomode of- ReadMode -> read_flags-#ifdef mingw32_HOST_OS- WriteMode -> write_flags .|. o_TRUNC-#else- WriteMode -> write_flags-#endif- ReadWriteMode -> rw_flags- AppendMode -> append_flags--#ifdef mingw32_HOST_OS- binary_flags = o_BINARY-#else- binary_flags = 0-#endif -- oflags2 = oflags1 .|. binary_flags-- oflags | non_blocking = oflags2 .|. nonblock_flags- | otherwise = oflags2- in do-- -- the old implementation had a complicated series of three opens,- -- which is perhaps because we have to be careful not to open- -- directories. However, the man pages I've read say that open()- -- always returns EISDIR if the file is a directory and was opened- -- for writing, so I think we're ok with a single open() here...- fd <- throwErrnoIfMinus1Retry "openFile"- (if non_blocking then c_open f oflags 0o666- else c_safe_open f oflags 0o666)-- (fD,fd_type) <- mkFD fd iomode Nothing{-no stat-}- False{-not a socket-} - non_blocking- `catchAny` \e -> do _ <- c_close fd- throwIO e--#ifndef mingw32_HOST_OS- -- we want to truncate() if this is an open in WriteMode, but only- -- if the target is a RegularFile. ftruncate() fails on special files- -- like /dev/null.- if iomode == WriteMode && fd_type == RegularFile- then setSize fD 0- else return ()-#endif-- return (fD,fd_type)--std_flags, output_flags, read_flags, write_flags, rw_flags,- append_flags, nonblock_flags :: CInt-std_flags = o_NOCTTY-output_flags = std_flags .|. o_CREAT-read_flags = std_flags .|. o_RDONLY -write_flags = output_flags .|. o_WRONLY-rw_flags = output_flags .|. o_RDWR-append_flags = write_flags .|. o_APPEND-nonblock_flags = o_NONBLOCK----- | Make a 'FD' from an existing file descriptor. Fails if the FD--- refers to a directory. If the FD refers to a file, `mkFD` locks--- the file according to the Haskell 98 single writer/multiple reader--- locking semantics (this is why we need the `IOMode` argument too).-mkFD :: CInt- -> IOMode- -> Maybe (IODeviceType, CDev, CIno)- -- the results of fdStat if we already know them, or we want- -- to prevent fdToHandle_stat from doing its own stat.- -- These are used for:- -- - we fail if the FD refers to a directory- -- - if the FD refers to a file, we lock it using (cdev,cino)- -> Bool -- ^ is a socket (on Windows)- -> Bool -- ^ is in non-blocking mode on Unix- -> IO (FD,IODeviceType)--mkFD fd iomode mb_stat is_socket is_nonblock = do-- let _ = (is_socket, is_nonblock) -- warning suppression-- (fd_type,dev,ino) <- - case mb_stat of- Nothing -> fdStat fd- Just stat -> return stat-- let write = case iomode of- ReadMode -> False- _ -> True--#ifdef mingw32_HOST_OS- _ <- setmode fd True -- unconditionally set binary mode- let _ = (dev,ino,write) -- warning suppression-#endif-- case fd_type of- Directory -> - ioException (IOError Nothing InappropriateType "openFile"- "is a directory" Nothing Nothing)--#ifndef mingw32_HOST_OS- -- regular files need to be locked- RegularFile -> do- -- On Windows we use explicit exclusion via sopen() to implement- -- this locking (see __hscore_open()); on Unix we have to- -- implment it in the RTS.- r <- lockFile fd dev ino (fromBool write)- when (r == -1) $- ioException (IOError Nothing ResourceBusy "openFile"- "file is locked" Nothing Nothing)-#endif-- _other_type -> return ()-- return (FD{ fdFD = fd,-#ifndef mingw32_HOST_OS- fdIsNonBlocking = fromEnum is_nonblock-#else- fdIsSocket_ = fromEnum is_socket-#endif- },- fd_type)--#ifdef mingw32_HOST_OS-foreign import ccall unsafe "__hscore_setmode"- setmode :: CInt -> Bool -> IO CInt-#endif---- -------------------------------------------------------------------------------- Standard file descriptors--stdFD :: CInt -> FD-stdFD fd = FD { fdFD = fd,-#ifdef mingw32_HOST_OS- fdIsSocket_ = 0-#else- fdIsNonBlocking = 0- -- We don't set non-blocking mode on standard handles, because it may- -- confuse other applications attached to the same TTY/pipe- -- see Note [nonblock]-#endif- }--stdin, stdout, stderr :: FD-stdin = stdFD 0-stdout = stdFD 1-stderr = stdFD 2---- -------------------------------------------------------------------------------- Operations on file descriptors--close :: FD -> IO ()-close fd =-#ifndef mingw32_HOST_OS- (flip finally) (release fd) $-#endif- do let closer realFd =- throwErrnoIfMinus1Retry_ "GHC.IO.FD.close" $-#ifdef mingw32_HOST_OS- if fdIsSocket fd then- c_closesocket (fromIntegral realFd)- else-#endif- c_close (fromIntegral realFd)- closeFdWith closer (fromIntegral (fdFD fd))--release :: FD -> IO ()-#ifdef mingw32_HOST_OS-release _ = return ()-#else-release fd = do _ <- unlockFile (fdFD fd)- return ()-#endif--#ifdef mingw32_HOST_OS-foreign import stdcall unsafe "HsBase.h closesocket"- c_closesocket :: CInt -> IO CInt-#endif--isSeekable :: FD -> IO Bool-isSeekable fd = do- t <- devType fd- return (t == RegularFile || t == RawDevice)--seek :: FD -> SeekMode -> Integer -> IO ()-seek fd mode off = do- throwErrnoIfMinus1Retry_ "seek" $- c_lseek (fdFD fd) (fromIntegral off) seektype- where- seektype :: CInt- seektype = case mode of- AbsoluteSeek -> sEEK_SET- RelativeSeek -> sEEK_CUR- SeekFromEnd -> sEEK_END--tell :: FD -> IO Integer-tell fd =- fromIntegral `fmap`- (throwErrnoIfMinus1Retry "hGetPosn" $- c_lseek (fdFD fd) 0 sEEK_CUR)--getSize :: FD -> IO Integer-getSize fd = fdFileSize (fdFD fd)--setSize :: FD -> Integer -> IO () -setSize fd size = do- throwErrnoIf_ (/=0) "GHC.IO.FD.setSize" $- c_ftruncate (fdFD fd) (fromIntegral size)--devType :: FD -> IO IODeviceType-devType fd = do (ty,_,_) <- fdStat (fdFD fd); return ty--dup :: FD -> IO FD-dup fd = do- newfd <- throwErrnoIfMinus1 "GHC.IO.FD.dup" $ c_dup (fdFD fd)- return fd{ fdFD = newfd }--dup2 :: FD -> FD -> IO FD-dup2 fd fdto = do- -- Windows' dup2 does not return the new descriptor, unlike Unix- throwErrnoIfMinus1_ "GHC.IO.FD.dup2" $- c_dup2 (fdFD fd) (fdFD fdto)- return fd{ fdFD = fdFD fdto } -- original FD, with the new fdFD--setNonBlockingMode :: FD -> Bool -> IO FD-setNonBlockingMode fd set = do - setNonBlockingFD (fdFD fd) set-#if defined(mingw32_HOST_OS)- return fd-#else- return fd{ fdIsNonBlocking = fromEnum set }-#endif--ready :: FD -> Bool -> Int -> IO Bool-ready fd write msecs = do- r <- throwErrnoIfMinus1Retry "GHC.IO.FD.ready" $- fdReady (fdFD fd) (fromIntegral $ fromEnum $ write)- (fromIntegral msecs)-#if defined(mingw32_HOST_OS)- (fromIntegral $ fromEnum $ fdIsSocket fd)-#else- 0-#endif- return (toEnum (fromIntegral r))--foreign import ccall safe "fdReady"- fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt---- ------------------------------------------------------------------------------ Terminal-related stuff--isTerminal :: FD -> IO Bool-isTerminal fd =-#if defined(mingw32_HOST_OS)- is_console (fdFD fd) >>= return.toBool-#else- c_isatty (fdFD fd) >>= return.toBool-#endif--setEcho :: FD -> Bool -> IO () -setEcho fd on = System.Posix.Internals.setEcho (fdFD fd) on--getEcho :: FD -> IO Bool-getEcho fd = System.Posix.Internals.getEcho (fdFD fd)--setRaw :: FD -> Bool -> IO ()-setRaw fd raw = System.Posix.Internals.setCooked (fdFD fd) (not raw)---- -------------------------------------------------------------------------------- Reading and Writing--fdRead :: FD -> Ptr Word8 -> Int -> IO Int-fdRead fd ptr bytes- = do { r <- readRawBufferPtr "GHC.IO.FD.fdRead" fd ptr 0 (fromIntegral bytes)- ; return (fromIntegral r) }--fdReadNonBlocking :: FD -> Ptr Word8 -> Int -> IO (Maybe Int)-fdReadNonBlocking fd ptr bytes = do- r <- readRawBufferPtrNoBlock "GHC.IO.FD.fdReadNonBlocking" fd ptr - 0 (fromIntegral bytes)- case fromIntegral r of- (-1) -> return (Nothing)- n -> return (Just n)---fdWrite :: FD -> Ptr Word8 -> Int -> IO ()-fdWrite fd ptr bytes = do- res <- writeRawBufferPtr "GHC.IO.FD.fdWrite" fd ptr 0 (fromIntegral bytes)- let res' = fromIntegral res- if res' < bytes - then fdWrite fd (ptr `plusPtr` res') (bytes - res')- else return ()---- XXX ToDo: this isn't non-blocking-fdWriteNonBlocking :: FD -> Ptr Word8 -> Int -> IO Int-fdWriteNonBlocking fd ptr bytes = do- res <- writeRawBufferPtrNoBlock "GHC.IO.FD.fdWriteNonBlocking" fd ptr 0- (fromIntegral bytes)- return (fromIntegral res)---- -------------------------------------------------------------------------------- FD operations---- Low level routines for reading/writing to (raw)buffers:--#ifndef mingw32_HOST_OS--{--NOTE [nonblock]:--Unix has broken semantics when it comes to non-blocking I/O: you can-set the O_NONBLOCK flag on an FD, but it applies to the all other FDs-attached to the same underlying file, pipe or TTY; there's no way to-have private non-blocking behaviour for an FD. See bug #724.--We fix this by only setting O_NONBLOCK on FDs that we create; FDs that-come from external sources or are exposed externally are left in-blocking mode. This solution has some problems though. We can't-completely simulate a non-blocking read without O_NONBLOCK: several-cases are wrong here. The cases that are wrong:-- * reading/writing to a blocking FD in non-threaded mode.- In threaded mode, we just make a safe call to read(). - In non-threaded mode we call select() before attempting to read,- but that leaves a small race window where the data can be read- from the file descriptor before we issue our blocking read().- * readRawBufferNoBlock for a blocking FD--NOTE [2363]:--In the threaded RTS we could just make safe calls to read()/write()-for file descriptors in blocking mode without worrying about blocking-other threads, but the problem with this is that the thread will be-uninterruptible while it is blocked in the foreign call. See #2363.-So now we always call fdReady() before reading, and if fdReady-indicates that there's no data, we call threadWaitRead.---}--readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int-readRawBufferPtr loc !fd buf off len- | isNonBlocking fd = unsafe_read -- unsafe is ok, it can't block- | otherwise = do r <- throwErrnoIfMinus1 loc - (unsafe_fdReady (fdFD fd) 0 0 0)- if r /= 0 - then read- else do threadWaitRead (fromIntegral (fdFD fd)); read- where- do_read call = fromIntegral `fmap`- throwErrnoIfMinus1RetryMayBlock loc call- (threadWaitRead (fromIntegral (fdFD fd)))- read = if threaded then safe_read else unsafe_read- unsafe_read = do_read (c_read (fdFD fd) (buf `plusPtr` off) len)- safe_read = do_read (c_safe_read (fdFD fd) (buf `plusPtr` off) len)---- return: -1 indicates EOF, >=0 is bytes read-readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int-readRawBufferPtrNoBlock loc !fd buf off len- | isNonBlocking fd = unsafe_read -- unsafe is ok, it can't block- | otherwise = do r <- unsafe_fdReady (fdFD fd) 0 0 0- if r /= 0 then safe_read- else return 0- -- XXX see note [nonblock]- where- do_read call = do r <- throwErrnoIfMinus1RetryOnBlock loc call (return (-1))- case r of- (-1) -> return 0- 0 -> return (-1)- n -> return (fromIntegral n)- unsafe_read = do_read (c_read (fdFD fd) (buf `plusPtr` off) len)- safe_read = do_read (c_safe_read (fdFD fd) (buf `plusPtr` off) len)--writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-writeRawBufferPtr loc !fd buf off len- | isNonBlocking fd = unsafe_write -- unsafe is ok, it can't block- | otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0- if r /= 0 - then write- else do threadWaitWrite (fromIntegral (fdFD fd)); write- where- do_write call = fromIntegral `fmap`- throwErrnoIfMinus1RetryMayBlock loc call- (threadWaitWrite (fromIntegral (fdFD fd)))- write = if threaded then safe_write else unsafe_write- unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)- safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)--writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-writeRawBufferPtrNoBlock loc !fd buf off len- | isNonBlocking fd = unsafe_write -- unsafe is ok, it can't block- | otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0- if r /= 0 then write- else return 0- where- do_write call = do r <- throwErrnoIfMinus1RetryOnBlock loc call (return (-1))- case r of- (-1) -> return 0- n -> return (fromIntegral n)- write = if threaded then safe_write else unsafe_write- unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)- safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)--isNonBlocking :: FD -> Bool-isNonBlocking fd = fdIsNonBlocking fd /= 0--foreign import ccall unsafe "fdReady"- unsafe_fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt--#else /* mingw32_HOST_OS.... */--readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-readRawBufferPtr loc !fd buf off len- | threaded = blockingReadRawBufferPtr loc fd buf off len- | otherwise = asyncReadRawBufferPtr loc fd buf off len--writeRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-writeRawBufferPtr loc !fd buf off len- | threaded = blockingWriteRawBufferPtr loc fd buf off len- | otherwise = asyncWriteRawBufferPtr loc fd buf off len--readRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-readRawBufferPtrNoBlock = readRawBufferPtr--writeRawBufferPtrNoBlock :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-writeRawBufferPtrNoBlock = writeRawBufferPtr---- Async versions of the read/write primitives, for the non-threaded RTS--asyncReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-asyncReadRawBufferPtr loc !fd buf off len = do- (l, rc) <- asyncRead (fromIntegral (fdFD fd)) (fdIsSocket_ fd) - (fromIntegral len) (buf `plusPtr` off)- if l == (-1)- then - ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)- else return (fromIntegral l)--asyncWriteRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-asyncWriteRawBufferPtr loc !fd buf off len = do- (l, rc) <- asyncWrite (fromIntegral (fdFD fd)) (fdIsSocket_ fd)- (fromIntegral len) (buf `plusPtr` off)- if l == (-1)- then - ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)- else return (fromIntegral l)---- Blocking versions of the read/write primitives, for the threaded RTS--blockingReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt-blockingReadRawBufferPtr loc fd buf off len- = fmap fromIntegral $ throwErrnoIfMinus1Retry loc $- if fdIsSocket fd- then c_safe_recv (fdFD fd) (buf `plusPtr` off) len 0- else c_safe_read (fdFD fd) (buf `plusPtr` off) len--blockingWriteRawBufferPtr :: String -> FD -> Ptr Word8-> Int -> CSize -> IO CInt-blockingWriteRawBufferPtr loc fd buf off len - = fmap fromIntegral $ throwErrnoIfMinus1Retry loc $- if fdIsSocket fd- then c_safe_send (fdFD fd) (buf `plusPtr` off) len 0- else do- r <- c_safe_write (fdFD fd) (buf `plusPtr` off) len- when (r == -1) c_maperrno- return r- -- we don't trust write() to give us the correct errno, and- -- instead do the errno conversion from GetLastError()- -- ourselves. The main reason is that we treat ERROR_NO_DATA- -- (pipe is closing) as EPIPE, whereas write() returns EINVAL- -- for this case. We need to detect EPIPE correctly, because it- -- shouldn't be reported as an error when it happens on stdout.---- NOTE: "safe" versions of the read/write calls for use by the threaded RTS.--- These calls may block, but that's ok.--foreign import stdcall safe "recv"- c_safe_recv :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize--foreign import stdcall safe "send"- c_safe_send :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize--#endif--foreign import ccall "rtsSupportsBoundThreads" threaded :: Bool---- -------------------------------------------------------------------------------- utils--#ifndef mingw32_HOST_OS-throwErrnoIfMinus1RetryOnBlock :: String -> IO CSsize -> IO CSsize -> IO CSsize-throwErrnoIfMinus1RetryOnBlock loc f on_block = - do- res <- f- if (res :: CSsize) == -1- then do- err <- getErrno- if err == eINTR- then throwErrnoIfMinus1RetryOnBlock loc f on_block- else if err == eWOULDBLOCK || err == eAGAIN- then do on_block- else throwErrno loc- else return res-#endif---- -------------------------------------------------------------------------------- Locking/unlocking--#ifndef mingw32_HOST_OS-foreign import ccall unsafe "lockFile"- lockFile :: CInt -> CDev -> CIno -> CInt -> IO CInt--foreign import ccall unsafe "unlockFile"- unlockFile :: CInt -> IO CInt-#endif-
@@ -1,744 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , RecordWildCards- , NondecreasingIndentation- #-}-{-# OPTIONS_GHC -fno-warn-unused-matches #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Handle--- Copyright : (c) The University of Glasgow, 1994-2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable------ External API for GHC's Handle implementation-----------------------------------------------------------------------------------module GHC.IO.Handle (- Handle,- BufferMode(..),- - mkFileHandle, mkDuplexHandle,- - hFileSize, hSetFileSize, hIsEOF, hLookAhead,- hSetBuffering, hSetBinaryMode, hSetEncoding, hGetEncoding,- hFlush, hFlushAll, hDuplicate, hDuplicateTo,- - hClose, hClose_help,- - HandlePosition, HandlePosn(..), hGetPosn, hSetPosn,- SeekMode(..), hSeek, hTell,- - hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,- hSetEcho, hGetEcho, hIsTerminalDevice,- - hSetNewlineMode, Newline(..), NewlineMode(..), nativeNewline,- noNewlineTranslation, universalNewlineMode, nativeNewlineMode,-- hShow,-- hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,-- hGetBuf, hGetBufNonBlocking, hPutBuf, hPutBufNonBlocking- ) where--import GHC.IO-import GHC.IO.Exception-import GHC.IO.Encoding-import GHC.IO.Buffer-import GHC.IO.BufferedIO ( BufferedIO )-import GHC.IO.Device as IODevice-import GHC.IO.Handle.Types-import GHC.IO.Handle.Internals-import GHC.IO.Handle.Text-import qualified GHC.IO.BufferedIO as Buffered--import GHC.Base-import GHC.Exception-import GHC.MVar-import GHC.IORef-import GHC.Show-import GHC.Num-import GHC.Real-import Data.Maybe-import Data.Typeable-import Control.Monad---- ------------------------------------------------------------------------------ Closing a handle---- | Computation 'hClose' @hdl@ makes handle @hdl@ closed. Before the--- computation finishes, if @hdl@ is writable its buffer is flushed as--- for 'hFlush'.--- Performing 'hClose' on a handle that has already been closed has no effect; --- doing so is not an error. All other operations on a closed handle will fail.--- If 'hClose' fails for any reason, any further operations (apart from--- 'hClose') on the handle will still fail as if @hdl@ had been successfully--- closed.--hClose :: Handle -> IO ()-hClose h@(FileHandle _ m) = do - mb_exc <- hClose' h m- hClose_maybethrow mb_exc h-hClose h@(DuplexHandle _ r w) = do- excs <- mapM (hClose' h) [r,w]- hClose_maybethrow (listToMaybe (catMaybes excs)) h--hClose_maybethrow :: Maybe SomeException -> Handle -> IO ()-hClose_maybethrow Nothing h = return ()-hClose_maybethrow (Just e) h = hClose_rethrow e h--hClose_rethrow :: SomeException -> Handle -> IO ()-hClose_rethrow e h = - case fromException e of- Just ioe -> ioError (augmentIOError ioe "hClose" h)- Nothing -> throwIO e--hClose' :: Handle -> MVar Handle__ -> IO (Maybe SomeException)-hClose' h m = withHandle' "hClose" h m $ hClose_help---------------------------------------------------------------------------------- Detecting and changing the size of a file---- | For a handle @hdl@ which attached to a physical file,--- 'hFileSize' @hdl@ returns the size of that file in 8-bit bytes.--hFileSize :: Handle -> IO Integer-hFileSize handle =- withHandle_ "hFileSize" handle $ \ handle_@Handle__{haDevice=dev} -> do- case haType handle_ of - ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- _ -> do flushWriteBuffer handle_- r <- IODevice.getSize dev- if r /= -1- then return r- else ioException (IOError Nothing InappropriateType "hFileSize"- "not a regular file" Nothing Nothing)----- | 'hSetFileSize' @hdl@ @size@ truncates the physical file with handle @hdl@ to @size@ bytes.--hSetFileSize :: Handle -> Integer -> IO ()-hSetFileSize handle size =- withHandle_ "hSetFileSize" handle $ \ handle_@Handle__{haDevice=dev} -> do- case haType handle_ of - ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- _ -> do flushWriteBuffer handle_- IODevice.setSize dev size- return ()---- ------------------------------------------------------------------------------ Detecting the End of Input---- | For a readable handle @hdl@, 'hIsEOF' @hdl@ returns--- 'True' if no further input can be taken from @hdl@ or for a--- physical file, if the current I\/O position is equal to the length of--- the file. Otherwise, it returns 'False'.------ NOTE: 'hIsEOF' may block, because it has to attempt to read from--- the stream to determine whether there is any more data to be read.--hIsEOF :: Handle -> IO Bool-hIsEOF handle = wantReadableHandle_ "hIsEOF" handle $ \Handle__{..} -> do-- cbuf <- readIORef haCharBuffer- if not (isEmptyBuffer cbuf) then return False else do-- bbuf <- readIORef haByteBuffer- if not (isEmptyBuffer bbuf) then return False else do-- -- NB. do no decoding, just fill the byte buffer; see #3808- (r,bbuf') <- Buffered.fillReadBuffer haDevice bbuf- if r == 0- then return True- else do writeIORef haByteBuffer bbuf'- return False---- ------------------------------------------------------------------------------ Looking ahead---- | Computation 'hLookAhead' returns the next character from the handle--- without removing it from the input buffer, blocking until a character--- is available.------ This operation may fail with:------ * 'isEOFError' if the end of file has been reached.--hLookAhead :: Handle -> IO Char-hLookAhead handle =- wantReadableHandle_ "hLookAhead" handle hLookAhead_---- ------------------------------------------------------------------------------ Buffering Operations---- Three kinds of buffering are supported: line-buffering,--- block-buffering or no-buffering. See GHC.IO.Handle for definition and--- further explanation of what the type represent.---- | Computation 'hSetBuffering' @hdl mode@ sets the mode of buffering for--- handle @hdl@ on subsequent reads and writes.------ If the buffer mode is changed from 'BlockBuffering' or--- 'LineBuffering' to 'NoBuffering', then------ * if @hdl@ is writable, the buffer is flushed as for 'hFlush';------ * if @hdl@ is not writable, the contents of the buffer is discarded.------ This operation may fail with:------ * 'isPermissionError' if the handle has already been used for reading--- or writing and the implementation does not allow the buffering mode--- to be changed.--hSetBuffering :: Handle -> BufferMode -> IO ()-hSetBuffering handle mode =- withAllHandles__ "hSetBuffering" handle $ \ handle_@Handle__{..} -> do- case haType of- ClosedHandle -> ioe_closedHandle- _ -> do- if mode == haBufferMode then return handle_ else do-- -- See [note Buffer Sizing] in GHC.IO.Handle.Types-- -- check for errors:- case mode of- BlockBuffering (Just n) | n <= 0 -> ioe_bufsiz n- _ -> return ()-- -- for input terminals we need to put the terminal into- -- cooked or raw mode depending on the type of buffering.- is_tty <- IODevice.isTerminal haDevice- when (is_tty && isReadableHandleType haType) $- case mode of-#ifndef mingw32_HOST_OS- -- 'raw' mode under win32 is a bit too specialised (and troublesome- -- for most common uses), so simply disable its use here.- NoBuffering -> IODevice.setRaw haDevice True-#else- NoBuffering -> return ()-#endif- _ -> IODevice.setRaw haDevice False-- -- throw away spare buffers, they might be the wrong size- writeIORef haBuffers BufferListNil-- return Handle__{ haBufferMode = mode,.. }---- -------------------------------------------------------------------------------- hSetEncoding---- | The action 'hSetEncoding' @hdl@ @encoding@ changes the text encoding--- for the handle @hdl@ to @encoding@. The default encoding when a 'Handle' is--- created is 'localeEncoding', namely the default encoding for the current--- locale.------ To create a 'Handle' with no encoding at all, use 'openBinaryFile'. To--- stop further encoding or decoding on an existing 'Handle', use--- 'hSetBinaryMode'.------ 'hSetEncoding' may need to flush buffered data in order to change--- the encoding.----hSetEncoding :: Handle -> TextEncoding -> IO ()-hSetEncoding hdl encoding = do- withAllHandles__ "hSetEncoding" hdl $ \h_@Handle__{..} -> do- flushCharBuffer h_- closeTextCodecs h_- openTextEncoding (Just encoding) haType $ \ mb_encoder mb_decoder -> do- bbuf <- readIORef haByteBuffer- ref <- newIORef (error "last_decode")- return (Handle__{ haLastDecode = ref, - haDecoder = mb_decoder, - haEncoder = mb_encoder,- haCodec = Just encoding, .. })---- | Return the current 'TextEncoding' for the specified 'Handle', or--- 'Nothing' if the 'Handle' is in binary mode.------ Note that the 'TextEncoding' remembers nothing about the state of--- the encoder/decoder in use on this 'Handle'. For example, if the--- encoding in use is UTF-16, then using 'hGetEncoding' and--- 'hSetEncoding' to save and restore the encoding may result in an--- extra byte-order-mark being written to the file.----hGetEncoding :: Handle -> IO (Maybe TextEncoding)-hGetEncoding hdl =- withHandle_ "hGetEncoding" hdl $ \h_@Handle__{..} -> return haCodec---- -------------------------------------------------------------------------------- hFlush---- | The action 'hFlush' @hdl@ causes any items buffered for output--- in handle @hdl@ to be sent immediately to the operating system.------ This operation may fail with:------ * 'isFullError' if the device is full;------ * 'isPermissionError' if a system resource limit would be exceeded.--- It is unspecified whether the characters in the buffer are discarded--- or retained under these circumstances.--hFlush :: Handle -> IO () -hFlush handle = wantWritableHandle "hFlush" handle flushWriteBuffer---- | The action 'hFlushAll' @hdl@ flushes all buffered data in @hdl@,--- including any buffered read data. Buffered read data is flushed--- by seeking the file position back to the point before the bufferred--- data was read, and hence only works if @hdl@ is seekable (see--- 'hIsSeekable').------ This operation may fail with:------ * 'isFullError' if the device is full;------ * 'isPermissionError' if a system resource limit would be exceeded.--- It is unspecified whether the characters in the buffer are discarded--- or retained under these circumstances;------ * 'isIllegalOperation' if @hdl@ has buffered read data, and is not--- seekable.--hFlushAll :: Handle -> IO () -hFlushAll handle = withHandle_ "hFlushAll" handle flushBuffer---- -------------------------------------------------------------------------------- Repositioning Handles--data HandlePosn = HandlePosn Handle HandlePosition--instance Eq HandlePosn where- (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2--instance Show HandlePosn where- showsPrec p (HandlePosn h pos) = - showsPrec p h . showString " at position " . shows pos-- -- HandlePosition is the Haskell equivalent of POSIX' off_t.- -- We represent it as an Integer on the Haskell side, but- -- cheat slightly in that hGetPosn calls upon a C helper- -- that reports the position back via (merely) an Int.-type HandlePosition = Integer---- | Computation 'hGetPosn' @hdl@ returns the current I\/O position of--- @hdl@ as a value of the abstract type 'HandlePosn'.--hGetPosn :: Handle -> IO HandlePosn-hGetPosn handle = do- posn <- hTell handle- return (HandlePosn handle posn)---- | If a call to 'hGetPosn' @hdl@ returns a position @p@,--- then computation 'hSetPosn' @p@ sets the position of @hdl@--- to the position it held at the time of the call to 'hGetPosn'.------ This operation may fail with:------ * 'isPermissionError' if a system resource limit would be exceeded.--hSetPosn :: HandlePosn -> IO () -hSetPosn (HandlePosn h i) = hSeek h AbsoluteSeek i---- ------------------------------------------------------------------------------ hSeek--{- Note: - - when seeking using `SeekFromEnd', positive offsets (>=0) means- seeking at or past EOF.-- - we possibly deviate from the report on the issue of seeking within- the buffer and whether to flush it or not. The report isn't exactly- clear here.--}---- | Computation 'hSeek' @hdl mode i@ sets the position of handle--- @hdl@ depending on @mode@.--- The offset @i@ is given in terms of 8-bit bytes.------ If @hdl@ is block- or line-buffered, then seeking to a position which is not--- in the current buffer will first cause any items in the output buffer to be--- written to the device, and then cause the input buffer to be discarded.--- Some handles may not be seekable (see 'hIsSeekable'), or only support a--- subset of the possible positioning operations (for instance, it may only--- be possible to seek to the end of a tape, or to a positive offset from--- the beginning or current position).--- It is not possible to set a negative I\/O position, or for--- a physical file, an I\/O position beyond the current end-of-file.------ This operation may fail with:------ * 'isIllegalOperationError' if the Handle is not seekable, or does--- not support the requested seek mode.------ * 'isPermissionError' if a system resource limit would be exceeded.--hSeek :: Handle -> SeekMode -> Integer -> IO () -hSeek handle mode offset =- wantSeekableHandle "hSeek" handle $ \ handle_@Handle__{..} -> do- debugIO ("hSeek " ++ show (mode,offset))- buf <- readIORef haCharBuffer-- if isWriteBuffer buf- then do flushWriteBuffer handle_- IODevice.seek haDevice mode offset- else do-- let r = bufL buf; w = bufR buf- if mode == RelativeSeek && isNothing haDecoder && - offset >= 0 && offset < fromIntegral (w - r)- then writeIORef haCharBuffer buf{ bufL = r + fromIntegral offset }- else do -- flushCharReadBuffer handle_- flushByteReadBuffer handle_- IODevice.seek haDevice mode offset----- | Computation 'hTell' @hdl@ returns the current position of the--- handle @hdl@, as the number of bytes from the beginning of--- the file. The value returned may be subsequently passed to--- 'hSeek' to reposition the handle to the current position.--- --- This operation may fail with:------ * 'isIllegalOperationError' if the Handle is not seekable.----hTell :: Handle -> IO Integer-hTell handle = - wantSeekableHandle "hGetPosn" handle $ \ handle_@Handle__{..} -> do-- posn <- IODevice.tell haDevice-- -- we can't tell the real byte offset if there are buffered- -- Chars, so must flush first:- flushCharBuffer handle_-- bbuf <- readIORef haByteBuffer-- let real_posn- | isWriteBuffer bbuf = posn + fromIntegral (bufferElems bbuf)- | otherwise = posn - fromIntegral (bufferElems bbuf)-- cbuf <- readIORef haCharBuffer- debugIO ("\nhGetPosn: (posn, real_posn) = " ++ show (posn, real_posn))- debugIO (" cbuf: " ++ summaryBuffer cbuf ++- " bbuf: " ++ summaryBuffer bbuf)-- return real_posn---- -------------------------------------------------------------------------------- Handle Properties---- A number of operations return information about the properties of a--- handle. Each of these operations returns `True' if the handle has--- the specified property, and `False' otherwise.--hIsOpen :: Handle -> IO Bool-hIsOpen handle =- withHandle_ "hIsOpen" handle $ \ handle_ -> do- case haType handle_ of - ClosedHandle -> return False- SemiClosedHandle -> return False- _ -> return True--hIsClosed :: Handle -> IO Bool-hIsClosed handle =- withHandle_ "hIsClosed" handle $ \ handle_ -> do- case haType handle_ of - ClosedHandle -> return True- _ -> return False--{- not defined, nor exported, but mentioned- here for documentation purposes:-- hSemiClosed :: Handle -> IO Bool- hSemiClosed h = do- ho <- hIsOpen h- hc <- hIsClosed h- return (not (ho || hc))--}--hIsReadable :: Handle -> IO Bool-hIsReadable (DuplexHandle _ _ _) = return True-hIsReadable handle =- withHandle_ "hIsReadable" handle $ \ handle_ -> do- case haType handle_ of - ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- htype -> return (isReadableHandleType htype)--hIsWritable :: Handle -> IO Bool-hIsWritable (DuplexHandle _ _ _) = return True-hIsWritable handle =- withHandle_ "hIsWritable" handle $ \ handle_ -> do- case haType handle_ of - ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- htype -> return (isWritableHandleType htype)---- | Computation 'hGetBuffering' @hdl@ returns the current buffering mode--- for @hdl@.--hGetBuffering :: Handle -> IO BufferMode-hGetBuffering handle = - withHandle_ "hGetBuffering" handle $ \ handle_ -> do- case haType handle_ of - ClosedHandle -> ioe_closedHandle- _ -> - -- We're being non-standard here, and allow the buffering- -- of a semi-closed handle to be queried. -- sof 6/98- return (haBufferMode handle_) -- could be stricter..--hIsSeekable :: Handle -> IO Bool-hIsSeekable handle =- withHandle_ "hIsSeekable" handle $ \ handle_@Handle__{..} -> do- case haType of - ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- AppendHandle -> return False- _ -> IODevice.isSeekable haDevice---- -------------------------------------------------------------------------------- Changing echo status (Non-standard GHC extensions)---- | Set the echoing status of a handle connected to a terminal.--hSetEcho :: Handle -> Bool -> IO ()-hSetEcho handle on = do- isT <- hIsTerminalDevice handle- if not isT- then return ()- else- withHandle_ "hSetEcho" handle $ \ Handle__{..} -> do- case haType of - ClosedHandle -> ioe_closedHandle- _ -> IODevice.setEcho haDevice on---- | Get the echoing status of a handle connected to a terminal.--hGetEcho :: Handle -> IO Bool-hGetEcho handle = do- isT <- hIsTerminalDevice handle- if not isT- then return False- else- withHandle_ "hGetEcho" handle $ \ Handle__{..} -> do- case haType of - ClosedHandle -> ioe_closedHandle- _ -> IODevice.getEcho haDevice---- | Is the handle connected to a terminal?--hIsTerminalDevice :: Handle -> IO Bool-hIsTerminalDevice handle = do- withHandle_ "hIsTerminalDevice" handle $ \ Handle__{..} -> do- case haType of - ClosedHandle -> ioe_closedHandle- _ -> IODevice.isTerminal haDevice---- -------------------------------------------------------------------------------- hSetBinaryMode---- | Select binary mode ('True') or text mode ('False') on a open handle.--- (See also 'openBinaryFile'.)------ This has the same effect as calling 'hSetEncoding' with 'char8', together--- with 'hSetNewlineMode' with 'noNewlineTranslation'.----hSetBinaryMode :: Handle -> Bool -> IO ()-hSetBinaryMode handle bin =- withAllHandles__ "hSetBinaryMode" handle $ \ h_@Handle__{..} ->- do - flushCharBuffer h_- closeTextCodecs h_-- mb_te <- if bin then return Nothing- else fmap Just getLocaleEncoding-- openTextEncoding mb_te haType $ \ mb_encoder mb_decoder -> do-- -- should match the default newline mode, whatever that is- let nl | bin = noNewlineTranslation- | otherwise = nativeNewlineMode-- bbuf <- readIORef haByteBuffer- ref <- newIORef (error "codec_state", bbuf)-- return Handle__{ haLastDecode = ref,- haEncoder = mb_encoder, - haDecoder = mb_decoder,- haCodec = mb_te,- haInputNL = inputNL nl,- haOutputNL = outputNL nl, .. }- --- -------------------------------------------------------------------------------- hSetNewlineMode---- | Set the 'NewlineMode' on the specified 'Handle'. All buffered--- data is flushed first.-hSetNewlineMode :: Handle -> NewlineMode -> IO ()-hSetNewlineMode handle NewlineMode{ inputNL=i, outputNL=o } =- withAllHandles__ "hSetNewlineMode" handle $ \h_@Handle__{..} ->- do- flushBuffer h_- return h_{ haInputNL=i, haOutputNL=o }---- -------------------------------------------------------------------------------- Duplicating a Handle---- | Returns a duplicate of the original handle, with its own buffer.--- The two Handles will share a file pointer, however. The original--- handle's buffer is flushed, including discarding any input data,--- before the handle is duplicated.--hDuplicate :: Handle -> IO Handle-hDuplicate h@(FileHandle path m) = do- withHandle_' "hDuplicate" h m $ \h_ ->- dupHandle path h Nothing h_ (Just handleFinalizer)-hDuplicate h@(DuplexHandle path r w) = do- write_side@(FileHandle _ write_m) <- - withHandle_' "hDuplicate" h w $ \h_ ->- dupHandle path h Nothing h_ (Just handleFinalizer)- read_side@(FileHandle _ read_m) <- - withHandle_' "hDuplicate" h r $ \h_ ->- dupHandle path h (Just write_m) h_ Nothing- return (DuplexHandle path read_m write_m)--dupHandle :: FilePath- -> Handle- -> Maybe (MVar Handle__)- -> Handle__- -> Maybe HandleFinalizer- -> IO Handle-dupHandle filepath h other_side h_@Handle__{..} mb_finalizer = do- -- flush the buffer first, so we don't have to copy its contents- flushBuffer h_- case other_side of- Nothing -> do- new_dev <- IODevice.dup haDevice- dupHandle_ new_dev filepath other_side h_ mb_finalizer- Just r -> - withHandle_' "dupHandle" h r $ \Handle__{haDevice=dev} -> do- dupHandle_ dev filepath other_side h_ mb_finalizer--dupHandle_ :: (IODevice dev, BufferedIO dev, Typeable dev) => dev- -> FilePath- -> Maybe (MVar Handle__)- -> Handle__- -> Maybe HandleFinalizer- -> IO Handle-dupHandle_ new_dev filepath other_side h_@Handle__{..} mb_finalizer = do- -- XXX wrong!- mb_codec <- if isJust haEncoder then fmap Just getLocaleEncoding else return Nothing- mkHandle new_dev filepath haType True{-buffered-} mb_codec- NewlineMode { inputNL = haInputNL, outputNL = haOutputNL }- mb_finalizer other_side---- -------------------------------------------------------------------------------- Replacing a Handle--{- |-Makes the second handle a duplicate of the first handle. The second -handle will be closed first, if it is not already.--This can be used to retarget the standard Handles, for example:--> do h <- openFile "mystdout" WriteMode-> hDuplicateTo h stdout--}--hDuplicateTo :: Handle -> Handle -> IO ()-hDuplicateTo h1@(FileHandle path m1) h2@(FileHandle _ m2) = do- withHandle__' "hDuplicateTo" h2 m2 $ \h2_ -> do- _ <- hClose_help h2_- withHandle_' "hDuplicateTo" h1 m1 $ \h1_ -> do- dupHandleTo path h1 Nothing h2_ h1_ (Just handleFinalizer)-hDuplicateTo h1@(DuplexHandle path r1 w1) h2@(DuplexHandle _ r2 w2) = do- withHandle__' "hDuplicateTo" h2 w2 $ \w2_ -> do- _ <- hClose_help w2_- withHandle_' "hDuplicateTo" h1 w1 $ \w1_ -> do- dupHandleTo path h1 Nothing w2_ w1_ (Just handleFinalizer)- withHandle__' "hDuplicateTo" h2 r2 $ \r2_ -> do- _ <- hClose_help r2_- withHandle_' "hDuplicateTo" h1 r1 $ \r1_ -> do- dupHandleTo path h1 (Just w1) r2_ r1_ Nothing-hDuplicateTo h1 _ = - ioe_dupHandlesNotCompatible h1---ioe_dupHandlesNotCompatible :: Handle -> IO a-ioe_dupHandlesNotCompatible h =- ioException (IOError (Just h) IllegalOperation "hDuplicateTo" - "handles are incompatible" Nothing Nothing)--dupHandleTo :: FilePath - -> Handle- -> Maybe (MVar Handle__)- -> Handle__- -> Handle__- -> Maybe HandleFinalizer- -> IO Handle__-dupHandleTo filepath h other_side - hto_@Handle__{haDevice=devTo,..}- h_@Handle__{haDevice=dev} mb_finalizer = do- flushBuffer h_- case cast devTo of- Nothing -> ioe_dupHandlesNotCompatible h- Just dev' -> do - _ <- IODevice.dup2 dev dev'- FileHandle _ m <- dupHandle_ dev' filepath other_side h_ mb_finalizer- takeMVar m---- ------------------------------------------------------------------------------ showing Handles.------ | 'hShow' is in the 'IO' monad, and gives more comprehensive output--- than the (pure) instance of 'Show' for 'Handle'.--hShow :: Handle -> IO String-hShow h@(FileHandle path _) = showHandle' path False h-hShow h@(DuplexHandle path _ _) = showHandle' path True h--showHandle' :: String -> Bool -> Handle -> IO String-showHandle' filepath is_duplex h = - withHandle_ "showHandle" h $ \hdl_ ->- let- showType | is_duplex = showString "duplex (read-write)"- | otherwise = shows (haType hdl_)- in- return - (( showChar '{' . - showHdl (haType hdl_) - (showString "loc=" . showString filepath . showChar ',' .- showString "type=" . showType . showChar ',' .- showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haCharBuffer hdl_))) (haBufferMode hdl_) . showString "}" )- ) "")- where-- showHdl :: HandleType -> ShowS -> ShowS- showHdl ht cont = - case ht of- ClosedHandle -> shows ht . showString "}"- _ -> cont-- showBufMode :: Buffer e -> BufferMode -> ShowS- showBufMode buf bmo =- case bmo of- NoBuffering -> showString "none"- LineBuffering -> showString "line"- BlockBuffering (Just n) -> showString "block " . showParen True (shows n)- BlockBuffering Nothing -> showString "block " . showParen True (shows def)- where- def :: Int - def = bufSize buf-
@@ -1,10 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.IO.Handle where--import GHC.IO-import GHC.IO.Handle.Types--hFlush :: Handle -> IO ()-
@@ -1,289 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, PatternGuards, ForeignFunctionInterface #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Handle.FD--- Copyright : (c) The University of Glasgow, 1994-2008--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Handle operations implemented by file descriptors (FDs)-----------------------------------------------------------------------------------module GHC.IO.Handle.FD ( - stdin, stdout, stderr,- openFile, openBinaryFile, openFileBlocking,- mkHandleFromFD, fdToHandle, fdToHandle',- isEOF- ) where--import GHC.Base-import GHC.Show-import Data.Maybe-import Foreign.C.Types-import GHC.MVar-import GHC.IO-import GHC.IO.Encoding-import GHC.IO.Device as IODevice-import GHC.IO.Exception-import GHC.IO.IOMode-import GHC.IO.Handle-import GHC.IO.Handle.Types-import GHC.IO.Handle.Internals-import qualified GHC.IO.FD as FD-import qualified System.Posix.Internals as Posix---- ------------------------------------------------------------------------------ Standard Handles---- Three handles are allocated during program initialisation. The first--- two manage input or output from the Haskell program's standard input--- or output channel respectively. The third manages output to the--- standard error channel. These handles are initially open.---- | A handle managing input from the Haskell program's standard input channel.-stdin :: Handle-{-# NOINLINE stdin #-}-stdin = unsafePerformIO $ do- -- ToDo: acquire lock- setBinaryMode FD.stdin- enc <- getLocaleEncoding- mkHandle FD.stdin "<stdin>" ReadHandle True (Just enc)- nativeNewlineMode{-translate newlines-}- (Just stdHandleFinalizer) Nothing---- | A handle managing output to the Haskell program's standard output channel.-stdout :: Handle-{-# NOINLINE stdout #-}-stdout = unsafePerformIO $ do- -- ToDo: acquire lock- setBinaryMode FD.stdout- enc <- getLocaleEncoding- mkHandle FD.stdout "<stdout>" WriteHandle True (Just enc)- nativeNewlineMode{-translate newlines-}- (Just stdHandleFinalizer) Nothing---- | A handle managing output to the Haskell program's standard error channel.-stderr :: Handle-{-# NOINLINE stderr #-}-stderr = unsafePerformIO $ do- -- ToDo: acquire lock- setBinaryMode FD.stderr- enc <- getLocaleEncoding- mkHandle FD.stderr "<stderr>" WriteHandle False{-stderr is unbuffered-} - (Just enc)- nativeNewlineMode{-translate newlines-}- (Just stdHandleFinalizer) Nothing--stdHandleFinalizer :: FilePath -> MVar Handle__ -> IO ()-stdHandleFinalizer fp m = do- h_ <- takeMVar m- flushWriteBuffer h_- case haType h_ of - ClosedHandle -> return ()- _other -> closeTextCodecs h_- putMVar m (ioe_finalizedHandle fp)---- We have to put the FDs into binary mode on Windows to avoid the newline--- translation that the CRT IO library does.-setBinaryMode :: FD.FD -> IO ()-#ifdef mingw32_HOST_OS-setBinaryMode fd = do _ <- setmode (FD.fdFD fd) True- return ()-#else-setBinaryMode _ = return ()-#endif--#ifdef mingw32_HOST_OS-foreign import ccall unsafe "__hscore_setmode"- setmode :: CInt -> Bool -> IO CInt-#endif---- ------------------------------------------------------------------------------ isEOF---- | The computation 'isEOF' is identical to 'hIsEOF',--- except that it works only on 'stdin'.--isEOF :: IO Bool-isEOF = hIsEOF stdin---- ------------------------------------------------------------------------------ Opening and Closing Files--addFilePathToIOError :: String -> FilePath -> IOException -> IOException-addFilePathToIOError fun fp ioe- = ioe{ ioe_location = fun, ioe_filename = Just fp }---- | Computation 'openFile' @file mode@ allocates and returns a new, open--- handle to manage the file @file@. It manages input if @mode@--- is 'ReadMode', output if @mode@ is 'WriteMode' or 'AppendMode',--- and both input and output if mode is 'ReadWriteMode'.------ If the file does not exist and it is opened for output, it should be--- created as a new file. If @mode@ is 'WriteMode' and the file--- already exists, then it should be truncated to zero length.--- Some operating systems delete empty files, so there is no guarantee--- that the file will exist following an 'openFile' with @mode@--- 'WriteMode' unless it is subsequently written to successfully.--- The handle is positioned at the end of the file if @mode@ is--- 'AppendMode', and otherwise at the beginning (in which case its--- internal position is 0).--- The initial buffer mode is implementation-dependent.------ This operation may fail with:------ * 'isAlreadyInUseError' if the file is already open and cannot be reopened;------ * 'isDoesNotExistError' if the file does not exist; or------ * 'isPermissionError' if the user does not have permission to open the file.------ Note: if you will be working with files containing binary data, you'll want to--- be using 'openBinaryFile'.-openFile :: FilePath -> IOMode -> IO Handle-openFile fp im = - catchException- (openFile' fp im dEFAULT_OPEN_IN_BINARY_MODE True)- (\e -> ioError (addFilePathToIOError "openFile" fp e))---- | Like 'openFile', but opens the file in ordinary blocking mode.--- This can be useful for opening a FIFO for reading: if we open in--- non-blocking mode then the open will fail if there are no writers,--- whereas a blocking open will block until a writer appears.-openFileBlocking :: FilePath -> IOMode -> IO Handle-openFileBlocking fp im =- catchException- (openFile' fp im dEFAULT_OPEN_IN_BINARY_MODE False)- (\e -> ioError (addFilePathToIOError "openFile" fp e))---- | Like 'openFile', but open the file in binary mode.--- On Windows, reading a file in text mode (which is the default)--- will translate CRLF to LF, and writing will translate LF to CRLF.--- This is usually what you want with text files. With binary files--- this is undesirable; also, as usual under Microsoft operating systems,--- text mode treats control-Z as EOF. Binary mode turns off all special--- treatment of end-of-line and end-of-file characters.--- (See also 'hSetBinaryMode'.)--openBinaryFile :: FilePath -> IOMode -> IO Handle-openBinaryFile fp m =- catchException- (openFile' fp m True True)- (\e -> ioError (addFilePathToIOError "openBinaryFile" fp e))--openFile' :: String -> IOMode -> Bool -> Bool -> IO Handle-openFile' filepath iomode binary non_blocking = do- -- first open the file to get an FD- (fd, fd_type) <- FD.openFile filepath iomode non_blocking-- mb_codec <- if binary then return Nothing else fmap Just getLocaleEncoding-- -- then use it to make a Handle- mkHandleFromFD fd fd_type filepath iomode- False {- do not *set* non-blocking mode -}- mb_codec- `onException` IODevice.close fd- -- NB. don't forget to close the FD if mkHandleFromFD fails, otherwise- -- this FD leaks.- -- ASSERT: if we just created the file, then fdToHandle' won't fail- -- (so we don't need to worry about removing the newly created file- -- in the event of an error).----- ------------------------------------------------------------------------------ Converting file descriptors to Handles--mkHandleFromFD- :: FD.FD- -> IODeviceType- -> FilePath -- a string describing this file descriptor (e.g. the filename)- -> IOMode- -> Bool -- *set* non-blocking mode on the FD- -> Maybe TextEncoding- -> IO Handle--mkHandleFromFD fd0 fd_type filepath iomode set_non_blocking mb_codec- = do-#ifndef mingw32_HOST_OS- -- turn on non-blocking mode- fd <- if set_non_blocking - then FD.setNonBlockingMode fd0 True- else return fd0-#else- let _ = set_non_blocking -- warning suppression- fd <- return fd0-#endif-- let nl | isJust mb_codec = nativeNewlineMode- | otherwise = noNewlineTranslation-- case fd_type of- Directory -> - ioException (IOError Nothing InappropriateType "openFile"- "is a directory" Nothing Nothing)-- Stream- -- only *Streams* can be DuplexHandles. Other read/write- -- Handles must share a buffer.- | ReadWriteMode <- iomode -> - mkDuplexHandle fd filepath mb_codec nl- -- _other -> - mkFileHandle fd filepath iomode mb_codec nl---- | Old API kept to avoid breaking clients-fdToHandle' :: CInt- -> Maybe IODeviceType- -> Bool -- is_socket on Win, non-blocking on Unix- -> FilePath- -> IOMode- -> Bool -- binary- -> IO Handle-fdToHandle' fdint mb_type is_socket filepath iomode binary = do- let mb_stat = case mb_type of- Nothing -> Nothing- -- mkFD will do the stat:- Just RegularFile -> Nothing- -- no stat required for streams etc.:- Just other -> Just (other,0,0)- (fd,fd_type) <- FD.mkFD fdint iomode mb_stat- is_socket- is_socket- enc <- if binary then return Nothing else fmap Just getLocaleEncoding- mkHandleFromFD fd fd_type filepath iomode is_socket enc----- | Turn an existing file descriptor into a Handle. This is used by--- various external libraries to make Handles.------ Makes a binary Handle. This is for historical reasons; it should--- probably be a text Handle with the default encoding and newline--- translation instead.-fdToHandle :: Posix.FD -> IO Handle-fdToHandle fdint = do- iomode <- Posix.fdGetMode fdint- (fd,fd_type) <- FD.mkFD fdint iomode Nothing- False{-is_socket-} - -- NB. the is_socket flag is False, meaning that:- -- on Windows we're guessing this is not a socket (XXX)- False{-is_nonblock-}- -- file descriptors that we get from external sources are- -- not put into non-blocking mode, becuase that would affect- -- other users of the file descriptor- let fd_str = "<file descriptor: " ++ show fd ++ ">"- mkHandleFromFD fd fd_type fd_str iomode False{-non-block-} - Nothing -- bin mode---- ------------------------------------------------------------------------------ Are files opened by default in text or binary mode, if the user doesn't--- specify?--dEFAULT_OPEN_IN_BINARY_MODE :: Bool-dEFAULT_OPEN_IN_BINARY_MODE = False
@@ -1,10 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.IO.Handle.FD where--import GHC.IO.Handle.Types---- used in GHC.Conc, which is below GHC.IO.Handle.FD-stdout :: Handle-
@@ -1,915 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude- , RecordWildCards- , BangPatterns- , PatternGuards- , NondecreasingIndentation- , Rank2Types- #-}-{-# OPTIONS_GHC -fno-warn-unused-matches #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Handle.Internals--- Copyright : (c) The University of Glasgow, 1994-2001--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ This module defines the basic operations on I\/O \"handles\". All--- of the operations defined here are independent of the underlying--- device.------------------------------------------------------------------------------------- #hide-module GHC.IO.Handle.Internals (- withHandle, withHandle', withHandle_,- withHandle__', withHandle_', withAllHandles__,- wantWritableHandle, wantReadableHandle, wantReadableHandle_, - wantSeekableHandle,-- mkHandle, mkFileHandle, mkDuplexHandle,- openTextEncoding, closeTextCodecs, initBufferState,- dEFAULT_CHAR_BUFFER_SIZE,-- flushBuffer, flushWriteBuffer, flushCharReadBuffer,- flushCharBuffer, flushByteReadBuffer, flushByteWriteBuffer,-- readTextDevice, writeCharBuffer, readTextDeviceNonBlocking,- decodeByteBuf,-- augmentIOError,- ioe_closedHandle, ioe_EOF, ioe_notReadable, ioe_notWritable,- ioe_finalizedHandle, ioe_bufsiz,-- hClose_help, hLookAhead_,-- HandleFinalizer, handleFinalizer,-- debugIO,- ) where--import GHC.IO-import GHC.IO.IOMode-import GHC.IO.Encoding as Encoding-import GHC.IO.Handle.Types-import GHC.IO.Buffer-import GHC.IO.BufferedIO (BufferedIO)-import GHC.IO.Exception-import GHC.IO.Device (IODevice, SeekMode(..))-import qualified GHC.IO.Device as IODevice-import qualified GHC.IO.BufferedIO as Buffered--import GHC.Conc.Sync-import GHC.Real-import GHC.Base-import GHC.Exception-import GHC.Num ( Num(..) )-import GHC.Show-import GHC.IORef-import GHC.MVar-import Data.Typeable-import Control.Monad-import Data.Maybe-import Foreign.Safe-import System.Posix.Internals hiding (FD)--import Foreign.C--c_DEBUG_DUMP :: Bool-c_DEBUG_DUMP = False---- ------------------------------------------------------------------------------ Creating a new handle--type HandleFinalizer = FilePath -> MVar Handle__ -> IO ()--newFileHandle :: FilePath -> Maybe HandleFinalizer -> Handle__ -> IO Handle-newFileHandle filepath mb_finalizer hc = do- m <- newMVar hc- case mb_finalizer of- Just finalizer -> addMVarFinalizer m (finalizer filepath m)- Nothing -> return ()- return (FileHandle filepath m)---- ------------------------------------------------------------------------------ Working with Handles--{--In the concurrent world, handles are locked during use. This is done-by wrapping an MVar around the handle which acts as a mutex over-operations on the handle.--To avoid races, we use the following bracketing operations. The idea-is to obtain the lock, do some operation and replace the lock again,-whether the operation succeeded or failed. We also want to handle the-case where the thread receives an exception while processing the IO-operation: in these cases we also want to relinquish the lock.--There are three versions of @withHandle@: corresponding to the three-possible combinations of:-- - the operation may side-effect the handle- - the operation may return a result--If the operation generates an error or an exception is raised, the-original handle is always replaced.--}--{-# INLINE withHandle #-}-withHandle :: String -> Handle -> (Handle__ -> IO (Handle__,a)) -> IO a-withHandle fun h@(FileHandle _ m) act = withHandle' fun h m act-withHandle fun h@(DuplexHandle _ m _) act = withHandle' fun h m act--withHandle' :: String -> Handle -> MVar Handle__- -> (Handle__ -> IO (Handle__,a)) -> IO a-withHandle' fun h m act =- mask_ $ do- (h',v) <- do_operation fun h act m- checkHandleInvariants h'- putMVar m h'- return v--{-# INLINE withHandle_ #-}-withHandle_ :: String -> Handle -> (Handle__ -> IO a) -> IO a-withHandle_ fun h@(FileHandle _ m) act = withHandle_' fun h m act-withHandle_ fun h@(DuplexHandle _ m _) act = withHandle_' fun h m act--withHandle_' :: String -> Handle -> MVar Handle__ -> (Handle__ -> IO a) -> IO a-withHandle_' fun h m act = withHandle' fun h m $ \h_ -> do- a <- act h_- return (h_,a)--withAllHandles__ :: String -> Handle -> (Handle__ -> IO Handle__) -> IO ()-withAllHandles__ fun h@(FileHandle _ m) act = withHandle__' fun h m act-withAllHandles__ fun h@(DuplexHandle _ r w) act = do- withHandle__' fun h r act- withHandle__' fun h w act--withHandle__' :: String -> Handle -> MVar Handle__ -> (Handle__ -> IO Handle__)- -> IO ()-withHandle__' fun h m act =- mask_ $ do- h' <- do_operation fun h act m- checkHandleInvariants h'- putMVar m h'- return ()--do_operation :: String -> Handle -> (Handle__ -> IO a) -> MVar Handle__ -> IO a-do_operation fun h act m = do- h_ <- takeMVar m- checkHandleInvariants h_- act h_ `catchException` handler h_- where- handler h_ e = do- putMVar m h_- case () of- _ | Just ioe <- fromException e ->- ioError (augmentIOError ioe fun h)- _ | Just async_ex <- fromException e -> do -- see Note [async]- let _ = async_ex :: AsyncException- t <- myThreadId- throwTo t e- do_operation fun h act m- _otherwise ->- throwIO e---- Note [async]------ If an asynchronous exception is raised during an I/O operation,--- normally it is fine to just re-throw the exception synchronously.--- However, if we are inside an unsafePerformIO or an--- unsafeInterleaveIO, this would replace the enclosing thunk with the--- exception raised, which is wrong (#3997). We have to release the--- lock on the Handle, but what do we replace the thunk with? What--- should happen when the thunk is subsequently demanded again?------ The only sensible choice we have is to re-do the IO operation on--- resumption, but then we have to be careful in the IO library that--- this is always safe to do. In particular we should------ never perform any side-effects before an interruptible operation------ because the interruptible operation may raise an asynchronous--- exception, which may cause the operation and its side effects to be--- subsequently performed again.------ Re-doing the IO operation is achieved by:--- - using throwTo to re-throw the asynchronous exception asynchronously--- in the current thread--- - on resumption, it will be as if throwTo returns. In that case, we--- recursively invoke the original operation (see do_operation above).------ Interruptible operations in the I/O library are:--- - threadWaitRead/threadWaitWrite--- - fillReadBuffer/flushWriteBuffer--- - readTextDevice/writeTextDevice--augmentIOError :: IOException -> String -> Handle -> IOException-augmentIOError ioe@IOError{ ioe_filename = fp } fun h- = ioe { ioe_handle = Just h, ioe_location = fun, ioe_filename = filepath }- where filepath- | Just _ <- fp = fp- | otherwise = case h of- FileHandle path _ -> Just path- DuplexHandle path _ _ -> Just path---- ------------------------------------------------------------------------------ Wrapper for write operations.--wantWritableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a-wantWritableHandle fun h@(FileHandle _ m) act- = wantWritableHandle' fun h m act-wantWritableHandle fun h@(DuplexHandle _ _ m) act- = wantWritableHandle' fun h m act- -- we know it's not a ReadHandle or ReadWriteHandle, but we have to- -- check for ClosedHandle/SemiClosedHandle. (#4808)--wantWritableHandle'- :: String -> Handle -> MVar Handle__- -> (Handle__ -> IO a) -> IO a-wantWritableHandle' fun h m act- = withHandle_' fun h m (checkWritableHandle act)--checkWritableHandle :: (Handle__ -> IO a) -> Handle__ -> IO a-checkWritableHandle act h_@Handle__{..}- = case haType of- ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- ReadHandle -> ioe_notWritable- ReadWriteHandle -> do- buf <- readIORef haCharBuffer- when (not (isWriteBuffer buf)) $ do- flushCharReadBuffer h_- flushByteReadBuffer h_- buf <- readIORef haCharBuffer- writeIORef haCharBuffer buf{ bufState = WriteBuffer }- buf <- readIORef haByteBuffer- buf' <- Buffered.emptyWriteBuffer haDevice buf- writeIORef haByteBuffer buf'- act h_- _other -> act h_---- ------------------------------------------------------------------------------ Wrapper for read operations.--wantReadableHandle :: String -> Handle -> (Handle__ -> IO (Handle__,a)) -> IO a-wantReadableHandle fun h act = withHandle fun h (checkReadableHandle act)--wantReadableHandle_ :: String -> Handle -> (Handle__ -> IO a) -> IO a-wantReadableHandle_ fun h@(FileHandle _ m) act- = wantReadableHandle' fun h m act-wantReadableHandle_ fun h@(DuplexHandle _ m _) act- = wantReadableHandle' fun h m act- -- we know it's not a WriteHandle or ReadWriteHandle, but we have to- -- check for ClosedHandle/SemiClosedHandle. (#4808)--wantReadableHandle'- :: String -> Handle -> MVar Handle__- -> (Handle__ -> IO a) -> IO a-wantReadableHandle' fun h m act- = withHandle_' fun h m (checkReadableHandle act)--checkReadableHandle :: (Handle__ -> IO a) -> Handle__ -> IO a-checkReadableHandle act h_@Handle__{..} =- case haType of- ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- AppendHandle -> ioe_notReadable- WriteHandle -> ioe_notReadable- ReadWriteHandle -> do- -- a read/write handle and we want to read from it. We must- -- flush all buffered write data first.- bbuf <- readIORef haByteBuffer- when (isWriteBuffer bbuf) $ do- when (not (isEmptyBuffer bbuf)) $ flushByteWriteBuffer h_- cbuf' <- readIORef haCharBuffer- writeIORef haCharBuffer cbuf'{ bufState = ReadBuffer }- bbuf <- readIORef haByteBuffer- writeIORef haByteBuffer bbuf{ bufState = ReadBuffer }- act h_- _other -> act h_---- ------------------------------------------------------------------------------ Wrapper for seek operations.--wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a-wantSeekableHandle fun h@(DuplexHandle _ _ _) _act =- ioException (IOError (Just h) IllegalOperation fun- "handle is not seekable" Nothing Nothing)-wantSeekableHandle fun h@(FileHandle _ m) act =- withHandle_' fun h m (checkSeekableHandle act)--checkSeekableHandle :: (Handle__ -> IO a) -> Handle__ -> IO a-checkSeekableHandle act handle_@Handle__{haDevice=dev} =- case haType handle_ of- ClosedHandle -> ioe_closedHandle- SemiClosedHandle -> ioe_closedHandle- AppendHandle -> ioe_notSeekable- _ -> do b <- IODevice.isSeekable dev- if b then act handle_- else ioe_notSeekable---- -------------------------------------------------------------------------------- Handy IOErrors--ioe_closedHandle, ioe_EOF,- ioe_notReadable, ioe_notWritable, ioe_cannotFlushNotSeekable,- ioe_notSeekable :: IO a--ioe_closedHandle = ioException- (IOError Nothing IllegalOperation ""- "handle is closed" Nothing Nothing)-ioe_EOF = ioException- (IOError Nothing EOF "" "" Nothing Nothing)-ioe_notReadable = ioException- (IOError Nothing IllegalOperation ""- "handle is not open for reading" Nothing Nothing)-ioe_notWritable = ioException- (IOError Nothing IllegalOperation ""- "handle is not open for writing" Nothing Nothing)-ioe_notSeekable = ioException- (IOError Nothing IllegalOperation ""- "handle is not seekable" Nothing Nothing)-ioe_cannotFlushNotSeekable = ioException- (IOError Nothing IllegalOperation ""- "cannot flush the read buffer: underlying device is not seekable"- Nothing Nothing)--ioe_finalizedHandle :: FilePath -> Handle__-ioe_finalizedHandle fp = throw- (IOError Nothing IllegalOperation ""- "handle is finalized" Nothing (Just fp))--ioe_bufsiz :: Int -> IO a-ioe_bufsiz n = ioException- (IOError Nothing InvalidArgument "hSetBuffering"- ("illegal buffer size " ++ showsPrec 9 n []) Nothing Nothing)- -- 9 => should be parens'ified.---- ------------------------------------------------------------------------------ Wrapper for Handle encoding/decoding.---- The interface for TextEncoding changed so that a TextEncoding doesn't raise--- an exception if it encounters an invalid sequnce. Furthermore, encoding--- returns a reason as to why encoding stopped, letting us know if it was due--- to input/output underflow or an invalid sequence.------ This code adapts this elaborated interface back to the original TextEncoding--- interface.------ FIXME: it is possible that Handle code using the haDecoder/haEncoder fields--- could be made clearer by using the 'encode' interface directly. I have not--- looked into this.--streamEncode :: BufferCodec from to state- -> Buffer from -> Buffer to- -> IO (Buffer from, Buffer to)-streamEncode codec from to = go (from, to)- where - go (from, to) = do- (why, from', to') <- encode codec from to- -- When we are dealing with Handles, we don't care about input/output- -- underflow particularly, and we want to delay errors about invalid- -- sequences as far as possible.- case why of- Encoding.InvalidSequence | bufL from == bufL from' -> recover codec from' to' >>= go- _ -> return (from', to')---- -------------------------------------------------------------------------------- Handle Finalizers---- For a duplex handle, we arrange that the read side points to the write side--- (and hence keeps it alive if the read side is alive). This is done by--- having the haOtherSide field of the read side point to the read side.--- The finalizer is then placed on the write side, and the handle only gets--- finalized once, when both sides are no longer required.---- NOTE about finalized handles: It's possible that a handle can be--- finalized and then we try to use it later, for example if the--- handle is referenced from another finalizer, or from a thread that--- has become unreferenced and then resurrected (arguably in the--- latter case we shouldn't finalize the Handle...). Anyway,--- we try to emit a helpful message which is better than nothing.------ [later; 8/2010] However, a program like this can yield a strange--- error message:------ main = writeFile "out" loop--- loop = let x = x in x------ because the main thread and the Handle are both unreachable at the--- same time, the Handle may get finalized before the main thread--- receives the NonTermination exception, and the exception handler--- will then report an error. We'd rather this was not an error and--- the program just prints "<<loop>>".--handleFinalizer :: FilePath -> MVar Handle__ -> IO ()-handleFinalizer fp m = do- handle_ <- takeMVar m- (handle_', _) <- hClose_help handle_- putMVar m handle_'- return ()---- ------------------------------------------------------------------------------ Allocating buffers---- using an 8k char buffer instead of 32k improved performance for a--- basic "cat" program by ~30% for me. --SDM-dEFAULT_CHAR_BUFFER_SIZE :: Int-dEFAULT_CHAR_BUFFER_SIZE = 2048 -- 8k/sizeof(HsChar)--getCharBuffer :: IODevice dev => dev -> BufferState- -> IO (IORef CharBuffer, BufferMode)-getCharBuffer dev state = do- buffer <- newCharBuffer dEFAULT_CHAR_BUFFER_SIZE state- ioref <- newIORef buffer- is_tty <- IODevice.isTerminal dev-- let buffer_mode - | is_tty = LineBuffering - | otherwise = BlockBuffering Nothing-- return (ioref, buffer_mode)--mkUnBuffer :: BufferState -> IO (IORef CharBuffer, BufferMode)-mkUnBuffer state = do- buffer <- newCharBuffer dEFAULT_CHAR_BUFFER_SIZE state- -- See [note Buffer Sizing], GHC.IO.Handle.Types- ref <- newIORef buffer- return (ref, NoBuffering)---- -------------------------------------------------------------------------------- Flushing buffers---- | syncs the file with the buffer, including moving the--- file pointer backwards in the case of a read buffer. This can fail--- on a non-seekable read Handle.-flushBuffer :: Handle__ -> IO ()-flushBuffer h_@Handle__{..} = do- buf <- readIORef haCharBuffer- case bufState buf of- ReadBuffer -> do- flushCharReadBuffer h_- flushByteReadBuffer h_- WriteBuffer -> do- flushByteWriteBuffer h_---- | flushes the Char buffer only. Works on all Handles.-flushCharBuffer :: Handle__ -> IO ()-flushCharBuffer h_@Handle__{..} = do- cbuf <- readIORef haCharBuffer- case bufState cbuf of- ReadBuffer -> do- flushCharReadBuffer h_- WriteBuffer ->- when (not (isEmptyBuffer cbuf)) $- error "internal IO library error: Char buffer non-empty"---- -------------------------------------------------------------------------------- Writing data (flushing write buffers)---- flushWriteBuffer flushes the buffer iff it contains pending write--- data. Flushes both the Char and the byte buffer, leaving both--- empty.-flushWriteBuffer :: Handle__ -> IO ()-flushWriteBuffer h_@Handle__{..} = do- buf <- readIORef haByteBuffer- when (isWriteBuffer buf) $ flushByteWriteBuffer h_--flushByteWriteBuffer :: Handle__ -> IO ()-flushByteWriteBuffer h_@Handle__{..} = do- bbuf <- readIORef haByteBuffer- when (not (isEmptyBuffer bbuf)) $ do- bbuf' <- Buffered.flushWriteBuffer haDevice bbuf- writeIORef haByteBuffer bbuf'---- write the contents of the CharBuffer to the Handle__.--- The data will be encoded and pushed to the byte buffer,--- flushing if the buffer becomes full.-writeCharBuffer :: Handle__ -> CharBuffer -> IO ()-writeCharBuffer h_@Handle__{..} !cbuf = do- --- bbuf <- readIORef haByteBuffer-- debugIO ("writeCharBuffer: cbuf=" ++ summaryBuffer cbuf ++- " bbuf=" ++ summaryBuffer bbuf)-- (cbuf',bbuf') <- case haEncoder of- Nothing -> latin1_encode cbuf bbuf- Just encoder -> (streamEncode encoder) cbuf bbuf-- debugIO ("writeCharBuffer after encoding: cbuf=" ++ summaryBuffer cbuf' ++- " bbuf=" ++ summaryBuffer bbuf')-- -- flush if the write buffer is full- if isFullBuffer bbuf'- -- or we made no progress- || not (isEmptyBuffer cbuf') && bufL cbuf' == bufL cbuf- -- or the byte buffer has more elements than the user wanted buffered- || (case haBufferMode of- BlockBuffering (Just s) -> bufferElems bbuf' >= s- NoBuffering -> True- _other -> False)- then do- bbuf'' <- Buffered.flushWriteBuffer haDevice bbuf'- writeIORef haByteBuffer bbuf''- else- writeIORef haByteBuffer bbuf'-- if not (isEmptyBuffer cbuf')- then writeCharBuffer h_ cbuf'- else return ()---- -------------------------------------------------------------------------------- Flushing read buffers---- It is always possible to flush the Char buffer back to the byte buffer.-flushCharReadBuffer :: Handle__ -> IO ()-flushCharReadBuffer Handle__{..} = do- cbuf <- readIORef haCharBuffer- if isWriteBuffer cbuf || isEmptyBuffer cbuf then return () else do-- -- haLastDecode is the byte buffer just before we did our last batch of- -- decoding. We're going to re-decode the bytes up to the current char,- -- to find out where we should revert the byte buffer to.- (codec_state, bbuf0) <- readIORef haLastDecode-- cbuf0 <- readIORef haCharBuffer- writeIORef haCharBuffer cbuf0{ bufL=0, bufR=0 }-- -- if we haven't used any characters from the char buffer, then just- -- re-install the old byte buffer.- if bufL cbuf0 == 0- then do writeIORef haByteBuffer bbuf0- return ()- else do-- case haDecoder of- Nothing -> do- writeIORef haByteBuffer bbuf0 { bufL = bufL bbuf0 + bufL cbuf0 }- -- no decoder: the number of bytes to decode is the same as the- -- number of chars we have used up.-- Just decoder -> do- debugIO ("flushCharReadBuffer re-decode, bbuf=" ++ summaryBuffer bbuf0 ++- " cbuf=" ++ summaryBuffer cbuf0)-- -- restore the codec state- setState decoder codec_state- - (bbuf1,cbuf1) <- (streamEncode decoder) bbuf0- cbuf0{ bufL=0, bufR=0, bufSize = bufL cbuf0 }- - debugIO ("finished, bbuf=" ++ summaryBuffer bbuf1 ++- " cbuf=" ++ summaryBuffer cbuf1)-- writeIORef haByteBuffer bbuf1----- When flushing the byte read buffer, we seek backwards by the number--- of characters in the buffer. The file descriptor must therefore be--- seekable: attempting to flush the read buffer on an unseekable--- handle is not allowed.--flushByteReadBuffer :: Handle__ -> IO ()-flushByteReadBuffer h_@Handle__{..} = do- bbuf <- readIORef haByteBuffer-- if isEmptyBuffer bbuf then return () else do-- seekable <- IODevice.isSeekable haDevice- when (not seekable) $ ioe_cannotFlushNotSeekable-- let seek = negate (bufR bbuf - bufL bbuf)-- debugIO ("flushByteReadBuffer: new file offset = " ++ show seek)- IODevice.seek haDevice RelativeSeek (fromIntegral seek)-- writeIORef haByteBuffer bbuf{ bufL=0, bufR=0 }---- ------------------------------------------------------------------------------- Making Handles--mkHandle :: (IODevice dev, BufferedIO dev, Typeable dev) => dev- -> FilePath- -> HandleType- -> Bool -- buffered?- -> Maybe TextEncoding- -> NewlineMode- -> Maybe HandleFinalizer- -> Maybe (MVar Handle__)- -> IO Handle--mkHandle dev filepath ha_type buffered mb_codec nl finalizer other_side = do- openTextEncoding mb_codec ha_type $ \ mb_encoder mb_decoder -> do-- let buf_state = initBufferState ha_type- bbuf <- Buffered.newBuffer dev buf_state- bbufref <- newIORef bbuf- last_decode <- newIORef (error "codec_state", bbuf)-- (cbufref,bmode) <- - if buffered then getCharBuffer dev buf_state- else mkUnBuffer buf_state-- spares <- newIORef BufferListNil- newFileHandle filepath finalizer- (Handle__ { haDevice = dev,- haType = ha_type,- haBufferMode = bmode,- haByteBuffer = bbufref,- haLastDecode = last_decode,- haCharBuffer = cbufref,- haBuffers = spares,- haEncoder = mb_encoder,- haDecoder = mb_decoder,- haCodec = mb_codec,- haInputNL = inputNL nl,- haOutputNL = outputNL nl,- haOtherSide = other_side- })---- | makes a new 'Handle'-mkFileHandle :: (IODevice dev, BufferedIO dev, Typeable dev)- => dev -- ^ the underlying IO device, which must support - -- 'IODevice', 'BufferedIO' and 'Typeable'- -> FilePath- -- ^ a string describing the 'Handle', e.g. the file- -- path for a file. Used in error messages.- -> IOMode- -- The mode in which the 'Handle' is to be used- -> Maybe TextEncoding- -- Create the 'Handle' with no text encoding?- -> NewlineMode- -- Translate newlines?- -> IO Handle-mkFileHandle dev filepath iomode mb_codec tr_newlines = do- mkHandle dev filepath (ioModeToHandleType iomode) True{-buffered-} mb_codec- tr_newlines- (Just handleFinalizer) Nothing{-other_side-}---- | like 'mkFileHandle', except that a 'Handle' is created with two--- independent buffers, one for reading and one for writing. Used for--- full-duplex streams, such as network sockets.-mkDuplexHandle :: (IODevice dev, BufferedIO dev, Typeable dev) => dev- -> FilePath -> Maybe TextEncoding -> NewlineMode -> IO Handle-mkDuplexHandle dev filepath mb_codec tr_newlines = do-- write_side@(FileHandle _ write_m) <- - mkHandle dev filepath WriteHandle True mb_codec- tr_newlines- (Just handleFinalizer)- Nothing -- no othersie-- read_side@(FileHandle _ read_m) <- - mkHandle dev filepath ReadHandle True mb_codec- tr_newlines- Nothing -- no finalizer- (Just write_m)-- return (DuplexHandle filepath read_m write_m)--ioModeToHandleType :: IOMode -> HandleType-ioModeToHandleType ReadMode = ReadHandle-ioModeToHandleType WriteMode = WriteHandle-ioModeToHandleType ReadWriteMode = ReadWriteHandle-ioModeToHandleType AppendMode = AppendHandle--initBufferState :: HandleType -> BufferState-initBufferState ReadHandle = ReadBuffer-initBufferState _ = WriteBuffer--openTextEncoding- :: Maybe TextEncoding- -> HandleType- -> (forall es ds . Maybe (TextEncoder es) -> Maybe (TextDecoder ds) -> IO a)- -> IO a--openTextEncoding Nothing ha_type cont = cont Nothing Nothing-openTextEncoding (Just TextEncoding{..}) ha_type cont = do- mb_decoder <- if isReadableHandleType ha_type then do- decoder <- mkTextDecoder- return (Just decoder)- else- return Nothing- mb_encoder <- if isWritableHandleType ha_type then do- encoder <- mkTextEncoder- return (Just encoder)- else - return Nothing- cont mb_encoder mb_decoder--closeTextCodecs :: Handle__ -> IO ()-closeTextCodecs Handle__{..} = do- case haDecoder of Nothing -> return (); Just d -> Encoding.close d- case haEncoder of Nothing -> return (); Just d -> Encoding.close d---- ------------------------------------------------------------------------------ closing Handles---- hClose_help is also called by lazyRead (in GHC.IO.Handle.Text) when--- EOF is read or an IO error occurs on a lazy stream. The--- semi-closed Handle is then closed immediately. We have to be--- careful with DuplexHandles though: we have to leave the closing to--- the finalizer in that case, because the write side may still be in--- use.-hClose_help :: Handle__ -> IO (Handle__, Maybe SomeException)-hClose_help handle_ =- case haType handle_ of - ClosedHandle -> return (handle_,Nothing)- _ -> do mb_exc1 <- trymaybe $ flushWriteBuffer handle_ -- interruptible- -- it is important that hClose doesn't fail and- -- leave the Handle open (#3128), so we catch- -- exceptions when flushing the buffer.- (h_, mb_exc2) <- hClose_handle_ handle_- return (h_, if isJust mb_exc1 then mb_exc1 else mb_exc2)---trymaybe :: IO () -> IO (Maybe SomeException)-trymaybe io = (do io; return Nothing) `catchException` \e -> return (Just e)--hClose_handle_ :: Handle__ -> IO (Handle__, Maybe SomeException)-hClose_handle_ h_@Handle__{..} = do-- -- close the file descriptor, but not when this is the read- -- side of a duplex handle.- -- If an exception is raised by the close(), we want to continue- -- to close the handle and release the lock if it has one, then - -- we return the exception to the caller of hClose_help which can- -- raise it if necessary.- maybe_exception <- - case haOtherSide of- Nothing -> trymaybe $ IODevice.close haDevice- Just _ -> return Nothing-- -- free the spare buffers- writeIORef haBuffers BufferListNil- writeIORef haCharBuffer noCharBuffer- writeIORef haByteBuffer noByteBuffer- - -- release our encoder/decoder- closeTextCodecs h_-- -- we must set the fd to -1, because the finalizer is going- -- to run eventually and try to close/unlock it.- -- ToDo: necessary? the handle will be marked ClosedHandle- -- XXX GHC won't let us use record update here, hence wildcards- return (Handle__{ haType = ClosedHandle, .. }, maybe_exception)--{-# NOINLINE noCharBuffer #-}-noCharBuffer :: CharBuffer-noCharBuffer = unsafePerformIO $ newCharBuffer 1 ReadBuffer--{-# NOINLINE noByteBuffer #-}-noByteBuffer :: Buffer Word8-noByteBuffer = unsafePerformIO $ newByteBuffer 1 ReadBuffer---- ------------------------------------------------------------------------------ Looking ahead--hLookAhead_ :: Handle__ -> IO Char-hLookAhead_ handle_@Handle__{..} = do- buf <- readIORef haCharBuffer- - -- fill up the read buffer if necessary- new_buf <- if isEmptyBuffer buf- then readTextDevice handle_ buf- else return buf- writeIORef haCharBuffer new_buf- - peekCharBuf (bufRaw buf) (bufL buf)---- ------------------------------------------------------------------------------ debugging--debugIO :: String -> IO ()-debugIO s- | c_DEBUG_DUMP- = do _ <- withCStringLen (s ++ "\n") $- \(p, len) -> c_write 1 (castPtr p) (fromIntegral len)- return ()- | otherwise = return ()---- ------------------------------------------------------------------------------- Text input/output---- Read characters into the provided buffer. Return when any--- characters are available; raise an exception if the end of --- file is reached.-readTextDevice :: Handle__ -> CharBuffer -> IO CharBuffer-readTextDevice h_@Handle__{..} cbuf = do- --- bbuf0 <- readIORef haByteBuffer-- debugIO ("readTextDevice: cbuf=" ++ summaryBuffer cbuf ++ - " bbuf=" ++ summaryBuffer bbuf0)-- bbuf1 <- if not (isEmptyBuffer bbuf0)- then return bbuf0- else do- (r,bbuf1) <- Buffered.fillReadBuffer haDevice bbuf0- if r == 0 then ioe_EOF else do -- raise EOF- return bbuf1-- debugIO ("readTextDevice after reading: bbuf=" ++ summaryBuffer bbuf1)-- (bbuf2,cbuf') <- - case haDecoder of- Nothing -> do- writeIORef haLastDecode (error "codec_state", bbuf1)- latin1_decode bbuf1 cbuf- Just decoder -> do- state <- getState decoder- writeIORef haLastDecode (state, bbuf1)- (streamEncode decoder) bbuf1 cbuf-- debugIO ("readTextDevice after decoding: cbuf=" ++ summaryBuffer cbuf' ++ - " bbuf=" ++ summaryBuffer bbuf2)-- writeIORef haByteBuffer bbuf2- if bufR cbuf' == bufR cbuf -- no new characters- then readTextDevice' h_ bbuf2 cbuf -- we need more bytes to make a Char- else return cbuf'---- we have an incomplete byte sequence at the end of the buffer: try to--- read more bytes.-readTextDevice' :: Handle__ -> Buffer Word8 -> CharBuffer -> IO CharBuffer-readTextDevice' h_@Handle__{..} bbuf0 cbuf0 = do- --- -- copy the partial sequence to the beginning of the buffer, so we have- -- room to read more bytes.- bbuf1 <- slideContents bbuf0-- -- readTextDevice only calls us if we got some bytes but not some characters.- -- This can't occur if haDecoder is Nothing because latin1_decode accepts all bytes.- let Just decoder = haDecoder- - (r,bbuf2) <- Buffered.fillReadBuffer haDevice bbuf1- if r == 0- then do- (bbuf3, cbuf1) <- recover decoder bbuf2 cbuf0- writeIORef haByteBuffer bbuf3- -- We should recursively invoke readTextDevice after recovery,- -- if recovery did not add at least one new character to the buffer:- -- 1. If we were using IgnoreCodingFailure it might be the case that- -- cbuf1 is the same length as cbuf0 and we need to raise ioe_EOF- -- 2. If we were using TransliterateCodingFailure we might have *mutated*- -- the byte buffer without changing the pointers into either buffer.- -- We need to try and decode it again - it might just go through this time.- if bufR cbuf1 == bufR cbuf0- then readTextDevice h_ cbuf1- else return cbuf1- else do- debugIO ("readTextDevice' after reading: bbuf=" ++ summaryBuffer bbuf2)- - (bbuf3,cbuf1) <- do- state <- getState decoder- writeIORef haLastDecode (state, bbuf2)- (streamEncode decoder) bbuf2 cbuf0- - debugIO ("readTextDevice' after decoding: cbuf=" ++ summaryBuffer cbuf1 ++ - " bbuf=" ++ summaryBuffer bbuf3)- - writeIORef haByteBuffer bbuf3- if bufR cbuf0 == bufR cbuf1- then readTextDevice' h_ bbuf3 cbuf1- else return cbuf1---- Read characters into the provided buffer. Do not block;--- return zero characters instead. Raises an exception on end-of-file.-readTextDeviceNonBlocking :: Handle__ -> CharBuffer -> IO CharBuffer-readTextDeviceNonBlocking h_@Handle__{..} cbuf = do- --- bbuf0 <- readIORef haByteBuffer- when (isEmptyBuffer bbuf0) $ do- (r,bbuf1) <- Buffered.fillReadBuffer0 haDevice bbuf0- if isNothing r then ioe_EOF else do -- raise EOF- writeIORef haByteBuffer bbuf1-- decodeByteBuf h_ cbuf---- Decode bytes from the byte buffer into the supplied CharBuffer.-decodeByteBuf :: Handle__ -> CharBuffer -> IO CharBuffer-decodeByteBuf h_@Handle__{..} cbuf = do- --- bbuf0 <- readIORef haByteBuffer-- (bbuf2,cbuf') <-- case haDecoder of- Nothing -> do- writeIORef haLastDecode (error "codec_state", bbuf0)- latin1_decode bbuf0 cbuf- Just decoder -> do- state <- getState decoder- writeIORef haLastDecode (state, bbuf0)- (streamEncode decoder) bbuf0 cbuf-- writeIORef haByteBuffer bbuf2- return cbuf'-
@@ -1,1010 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , RecordWildCards- , BangPatterns- , PatternGuards- , NondecreasingIndentation- , MagicHash- , ForeignFunctionInterface- #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# OPTIONS_GHC -fno-warn-unused-matches #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Text--- Copyright : (c) The University of Glasgow, 1992-2008--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ String I\/O functions------------------------------------------------------------------------------------- #hide-module GHC.IO.Handle.Text ( - hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,- commitBuffer', -- hack, see below- hGetBuf, hGetBufSome, hGetBufNonBlocking, hPutBuf, hPutBufNonBlocking,- memcpy, hPutStrLn,- ) where--import GHC.IO-import GHC.IO.FD-import GHC.IO.Buffer-import qualified GHC.IO.BufferedIO as Buffered-import GHC.IO.Exception-import GHC.Exception-import GHC.IO.Handle.Types-import GHC.IO.Handle.Internals-import qualified GHC.IO.Device as IODevice-import qualified GHC.IO.Device as RawIO--import Foreign-import Foreign.C--import qualified Control.Exception as Exception-import Data.Typeable-import System.IO.Error-import Data.Maybe-import Control.Monad--import GHC.IORef-import GHC.Base-import GHC.Real-import GHC.Num-import GHC.Show-import GHC.List---- ------------------------------------------------------------------------------ Simple input operations---- If hWaitForInput finds anything in the Handle's buffer, it--- immediately returns. If not, it tries to read from the underlying--- OS handle. Notice that for buffered Handles connected to terminals--- this means waiting until a complete line is available.---- | Computation 'hWaitForInput' @hdl t@--- waits until input is available on handle @hdl@.--- It returns 'True' as soon as input is available on @hdl@,--- or 'False' if no input is available within @t@ milliseconds. Note that--- 'hWaitForInput' waits until one or more full /characters/ are available,--- which means that it needs to do decoding, and hence may fail--- with a decoding error.------ If @t@ is less than zero, then @hWaitForInput@ waits indefinitely.------ This operation may fail with:------ * 'isEOFError' if the end of file has been reached.------ * a decoding error, if the input begins with an invalid byte sequence--- in this Handle's encoding.------ NOTE for GHC users: unless you use the @-threaded@ flag,--- @hWaitForInput t@ where @t >= 0@ will block all other Haskell--- threads for the duration of the call. It behaves like a--- @safe@ foreign call in this respect.-----hWaitForInput :: Handle -> Int -> IO Bool-hWaitForInput h msecs = do- wantReadableHandle_ "hWaitForInput" h $ \ handle_@Handle__{..} -> do- cbuf <- readIORef haCharBuffer-- if not (isEmptyBuffer cbuf) then return True else do-- if msecs < 0 - then do cbuf' <- readTextDevice handle_ cbuf- writeIORef haCharBuffer cbuf'- return True- else do- -- there might be bytes in the byte buffer waiting to be decoded- cbuf' <- decodeByteBuf handle_ cbuf- writeIORef haCharBuffer cbuf'-- if not (isEmptyBuffer cbuf') then return True else do-- r <- IODevice.ready haDevice False{-read-} msecs- if r then do -- Call hLookAhead' to throw an EOF- -- exception if appropriate- _ <- hLookAhead_ handle_- return True- else return False- -- XXX we should only return when there are full characters- -- not when there are only bytes. That would mean looping- -- and re-running IODevice.ready if we don't have any full- -- characters; but we don't know how long we've waited- -- so far.---- ------------------------------------------------------------------------------ hGetChar---- | Computation 'hGetChar' @hdl@ reads a character from the file or--- channel managed by @hdl@, blocking until a character is available.------ This operation may fail with:------ * 'isEOFError' if the end of file has been reached.--hGetChar :: Handle -> IO Char-hGetChar handle =- wantReadableHandle_ "hGetChar" handle $ \handle_@Handle__{..} -> do-- -- buffering mode makes no difference: we just read whatever is available- -- from the device (blocking only if there is nothing available), and then- -- return the first character.- -- See [note Buffered Reading] in GHC.IO.Handle.Types- buf0 <- readIORef haCharBuffer-- buf1 <- if isEmptyBuffer buf0- then readTextDevice handle_ buf0- else return buf0-- (c1,i) <- readCharBuf (bufRaw buf1) (bufL buf1)- let buf2 = bufferAdjustL i buf1-- if haInputNL == CRLF && c1 == '\r'- then do- mbuf3 <- if isEmptyBuffer buf2- then maybeFillReadBuffer handle_ buf2- else return (Just buf2)-- case mbuf3 of- -- EOF, so just return the '\r' we have- Nothing -> do- writeIORef haCharBuffer buf2- return '\r'- Just buf3 -> do- (c2,i2) <- readCharBuf (bufRaw buf2) (bufL buf2)- if c2 == '\n'- then do- writeIORef haCharBuffer (bufferAdjustL i2 buf3)- return '\n'- else do- -- not a \r\n sequence, so just return the \r- writeIORef haCharBuffer buf3- return '\r'- else do- writeIORef haCharBuffer buf2- return c1---- ------------------------------------------------------------------------------ hGetLine---- | Computation 'hGetLine' @hdl@ reads a line from the file or--- channel managed by @hdl@.------ This operation may fail with:------ * 'isEOFError' if the end of file is encountered when reading--- the /first/ character of the line.------ If 'hGetLine' encounters end-of-file at any other point while reading--- in a line, it is treated as a line terminator and the (partial)--- line is returned.--hGetLine :: Handle -> IO String-hGetLine h =- wantReadableHandle_ "hGetLine" h $ \ handle_ -> do- hGetLineBuffered handle_--hGetLineBuffered :: Handle__ -> IO String-hGetLineBuffered handle_@Handle__{..} = do- buf <- readIORef haCharBuffer- hGetLineBufferedLoop handle_ buf []--hGetLineBufferedLoop :: Handle__- -> CharBuffer -> [String]- -> IO String-hGetLineBufferedLoop handle_@Handle__{..}- buf@Buffer{ bufL=r0, bufR=w, bufRaw=raw0 } xss =- let- -- find the end-of-line character, if there is one- loop raw r- | r == w = return (False, w)- | otherwise = do- (c,r') <- readCharBuf raw r- if c == '\n'- then return (True, r) -- NB. not r': don't include the '\n'- else loop raw r'- in do- (eol, off) <- loop raw0 r0-- debugIO ("hGetLineBufferedLoop: r=" ++ show r0 ++ ", w=" ++ show w ++ ", off=" ++ show off)-- (xs,r') <- if haInputNL == CRLF- then unpack_nl raw0 r0 off ""- else do xs <- unpack raw0 r0 off ""- return (xs,off)-- -- if eol == True, then off is the offset of the '\n'- -- otherwise off == w and the buffer is now empty.- if eol -- r' == off- then do writeIORef haCharBuffer (bufferAdjustL (off+1) buf)- return (concat (reverse (xs:xss)))- else do- let buf1 = bufferAdjustL r' buf- maybe_buf <- maybeFillReadBuffer handle_ buf1- case maybe_buf of- -- Nothing indicates we caught an EOF, and we may have a- -- partial line to return.- Nothing -> do- -- we reached EOF. There might be a lone \r left- -- in the buffer, so check for that and- -- append it to the line if necessary.- -- - let pre = if not (isEmptyBuffer buf1) then "\r" else ""- writeIORef haCharBuffer buf1{ bufL=0, bufR=0 }- let str = concat (reverse (pre:xs:xss))- if not (null str)- then return str- else ioe_EOF- Just new_buf ->- hGetLineBufferedLoop handle_ new_buf (xs:xss)--maybeFillReadBuffer :: Handle__ -> CharBuffer -> IO (Maybe CharBuffer)-maybeFillReadBuffer handle_ buf- = Exception.catch- (do buf' <- getSomeCharacters handle_ buf- return (Just buf')- )- (\e -> do if isEOFError e- then return Nothing- else ioError e)---- See GHC.IO.Buffer-#define CHARBUF_UTF32--- #define CHARBUF_UTF16---- NB. performance-critical code: eyeball the Core.-unpack :: RawCharBuffer -> Int -> Int -> [Char] -> IO [Char]-unpack !buf !r !w acc0- | r == w = return acc0- | otherwise = - withRawBuffer buf $ \pbuf -> - let- unpackRB acc !i- | i < r = return acc- | otherwise = do- -- Here, we are rather careful to only put an *evaluated* character- -- in the output string. Due to pointer tagging, this allows the consumer- -- to avoid ping-ponging between the actual consumer code and the thunk code-#ifdef CHARBUF_UTF16- -- reverse-order decoding of UTF-16- c2 <- peekElemOff pbuf i- if (c2 < 0xdc00 || c2 > 0xdffff)- then unpackRB (unsafeChr (fromIntegral c2) : acc) (i-1)- else do c1 <- peekElemOff pbuf (i-1)- let c = (fromIntegral c1 - 0xd800) * 0x400 +- (fromIntegral c2 - 0xdc00) + 0x10000- case desurrogatifyRoundtripCharacter (unsafeChr c) of- { C# c# -> unpackRB (C# c# : acc) (i-2) }-#else- c <- peekElemOff pbuf i- unpackRB (c : acc) (i-1)-#endif- in- unpackRB acc0 (w-1)---- NB. performance-critical code: eyeball the Core.-unpack_nl :: RawCharBuffer -> Int -> Int -> [Char] -> IO ([Char],Int)-unpack_nl !buf !r !w acc0- | r == w = return (acc0, 0)- | otherwise =- withRawBuffer buf $ \pbuf ->- let- unpackRB acc !i- | i < r = return acc- | otherwise = do- c <- peekElemOff pbuf i- if (c == '\n' && i > r)- then do- c1 <- peekElemOff pbuf (i-1)- if (c1 == '\r')- then unpackRB ('\n':acc) (i-2)- else unpackRB ('\n':acc) (i-1)- else do- unpackRB (c : acc) (i-1)- in do- c <- peekElemOff pbuf (w-1)- if (c == '\r')- then do - -- If the last char is a '\r', we need to know whether or- -- not it is followed by a '\n', so leave it in the buffer- -- for now and just unpack the rest.- str <- unpackRB acc0 (w-2)- return (str, w-1)- else do- str <- unpackRB acc0 (w-1)- return (str, w)---- Note [#5536]------ We originally had------ let c' = desurrogatifyRoundtripCharacter c in--- c' `seq` unpackRB (c':acc) (i-1)------ but this resulted in Core like------ case (case x <# y of True -> C# e1; False -> C# e2) of c--- C# _ -> unpackRB (c:acc) (i-1)------ which compiles into a continuation for the outer case, with each--- branch of the inner case building a C# and then jumping to the--- continuation. We'd rather not have this extra jump, which makes--- quite a difference to performance (see #5536) It turns out that--- matching on the C# directly causes GHC to do the case-of-case,--- giving much straighter code.---- -------------------------------------------------------------------------------- hGetContents---- hGetContents on a DuplexHandle only affects the read side: you can--- carry on writing to it afterwards.---- | Computation 'hGetContents' @hdl@ returns the list of characters--- corresponding to the unread portion of the channel or file managed--- by @hdl@, which is put into an intermediate state, /semi-closed/.--- In this state, @hdl@ is effectively closed,--- but items are read from @hdl@ on demand and accumulated in a special--- list returned by 'hGetContents' @hdl@.------ Any operation that fails because a handle is closed,--- also fails if a handle is semi-closed. The only exception is 'hClose'.--- A semi-closed handle becomes closed:------ * if 'hClose' is applied to it;------ * if an I\/O error occurs when reading an item from the handle;------ * or once the entire contents of the handle has been read.------ Once a semi-closed handle becomes closed, the contents of the--- associated list becomes fixed. The contents of this final list is--- only partially specified: it will contain at least all the items of--- the stream that were evaluated prior to the handle becoming closed.------ Any I\/O errors encountered while a handle is semi-closed are simply--- discarded.------ This operation may fail with:------ * 'isEOFError' if the end of file has been reached.--hGetContents :: Handle -> IO String-hGetContents handle = - wantReadableHandle "hGetContents" handle $ \handle_ -> do- xs <- lazyRead handle- return (handle_{ haType=SemiClosedHandle}, xs )---- Note that someone may close the semi-closed handle (or change its--- buffering), so each time these lazy read functions are pulled on,--- they have to check whether the handle has indeed been closed.--lazyRead :: Handle -> IO String-lazyRead handle = - unsafeInterleaveIO $- withHandle "hGetContents" handle $ \ handle_ -> do- case haType handle_ of- ClosedHandle -> return (handle_, "")- SemiClosedHandle -> lazyReadBuffered handle handle_- _ -> ioException - (IOError (Just handle) IllegalOperation "hGetContents"- "illegal handle type" Nothing Nothing)--lazyReadBuffered :: Handle -> Handle__ -> IO (Handle__, [Char])-lazyReadBuffered h handle_@Handle__{..} = do- buf <- readIORef haCharBuffer- Exception.catch- (do- buf'@Buffer{..} <- getSomeCharacters handle_ buf- lazy_rest <- lazyRead h- (s,r) <- if haInputNL == CRLF- then unpack_nl bufRaw bufL bufR lazy_rest- else do s <- unpack bufRaw bufL bufR lazy_rest- return (s,bufR)- writeIORef haCharBuffer (bufferAdjustL r buf')- return (handle_, s)- )- (\e -> do (handle_', _) <- hClose_help handle_- debugIO ("hGetContents caught: " ++ show e)- -- We might have a \r cached in CRLF mode. So we- -- need to check for that and return it:- let r = if isEOFError e- then if not (isEmptyBuffer buf)- then "\r"- else ""- else- throw (augmentIOError e "hGetContents" h)-- return (handle_', r)- )---- ensure we have some characters in the buffer-getSomeCharacters :: Handle__ -> CharBuffer -> IO CharBuffer-getSomeCharacters handle_@Handle__{..} buf@Buffer{..} =- case bufferElems buf of-- -- buffer empty: read some more- 0 -> readTextDevice handle_ buf-- -- if the buffer has a single '\r' in it and we're doing newline- -- translation: read some more- 1 | haInputNL == CRLF -> do- (c,_) <- readCharBuf bufRaw bufL- if c == '\r'- then do -- shuffle the '\r' to the beginning. This is only safe- -- if we're about to call readTextDevice, otherwise it- -- would mess up flushCharBuffer.- -- See [note Buffer Flushing], GHC.IO.Handle.Types- _ <- writeCharBuf bufRaw 0 '\r'- let buf' = buf{ bufL=0, bufR=1 }- readTextDevice handle_ buf'- else do- return buf-- -- buffer has some chars in it already: just return it- _otherwise ->- return buf---- ------------------------------------------------------------------------------ hPutChar---- | Computation 'hPutChar' @hdl ch@ writes the character @ch@ to the--- file or channel managed by @hdl@. Characters may be buffered if--- buffering is enabled for @hdl@.------ This operation may fail with:------ * 'isFullError' if the device is full; or------ * 'isPermissionError' if another system resource limit would be exceeded.--hPutChar :: Handle -> Char -> IO ()-hPutChar handle c = do- c `seq` return ()- wantWritableHandle "hPutChar" handle $ \ handle_ -> do- hPutcBuffered handle_ c--hPutcBuffered :: Handle__ -> Char -> IO ()-hPutcBuffered handle_@Handle__{..} c = do- buf <- readIORef haCharBuffer- if c == '\n'- then do buf1 <- if haOutputNL == CRLF- then do- buf1 <- putc buf '\r'- putc buf1 '\n'- else do- putc buf '\n'- writeCharBuffer handle_ buf1- when is_line $ flushByteWriteBuffer handle_- else do- buf1 <- putc buf c- writeCharBuffer handle_ buf1- return ()- where- is_line = case haBufferMode of- LineBuffering -> True- _ -> False-- putc buf@Buffer{ bufRaw=raw, bufR=w } c = do- debugIO ("putc: " ++ summaryBuffer buf)- w' <- writeCharBuf raw w c- return buf{ bufR = w' }---- ------------------------------------------------------------------------------ hPutStr---- We go to some trouble to avoid keeping the handle locked while we're--- evaluating the string argument to hPutStr, in case doing so triggers another--- I/O operation on the same handle which would lead to deadlock. The classic--- case is------ putStr (trace "hello" "world")------ so the basic scheme is this:------ * copy the string into a fresh buffer,--- * "commit" the buffer to the handle.------ Committing may involve simply copying the contents of the new--- buffer into the handle's buffer, flushing one or both buffers, or--- maybe just swapping the buffers over (if the handle's buffer was--- empty). See commitBuffer below.---- | Computation 'hPutStr' @hdl s@ writes the string--- @s@ to the file or channel managed by @hdl@.------ This operation may fail with:------ * 'isFullError' if the device is full; or------ * 'isPermissionError' if another system resource limit would be exceeded.--hPutStr :: Handle -> String -> IO ()-hPutStr handle str = hPutStr' handle str False---- | The same as 'hPutStr', but adds a newline character.-hPutStrLn :: Handle -> String -> IO ()-hPutStrLn handle str = hPutStr' handle str True- -- An optimisation: we treat hPutStrLn specially, to avoid the- -- overhead of a single putChar '\n', which is quite high now that we- -- have to encode eagerly.--hPutStr' :: Handle -> String -> Bool -> IO ()-hPutStr' handle str add_nl =- do- (buffer_mode, nl) <-- wantWritableHandle "hPutStr" handle $ \h_ -> do- bmode <- getSpareBuffer h_- return (bmode, haOutputNL h_)-- case buffer_mode of- (NoBuffering, _) -> do- hPutChars handle str -- v. slow, but we don't care- when add_nl $ hPutChar handle '\n'- (LineBuffering, buf) -> do- writeBlocks handle True add_nl nl buf str- (BlockBuffering _, buf) -> do- writeBlocks handle False add_nl nl buf str--hPutChars :: Handle -> [Char] -> IO ()-hPutChars _ [] = return ()-hPutChars handle (c:cs) = hPutChar handle c >> hPutChars handle cs--getSpareBuffer :: Handle__ -> IO (BufferMode, CharBuffer)-getSpareBuffer Handle__{haCharBuffer=ref, - haBuffers=spare_ref,- haBufferMode=mode}- = do- case mode of- NoBuffering -> return (mode, error "no buffer!")- _ -> do- bufs <- readIORef spare_ref- buf <- readIORef ref- case bufs of- BufferListCons b rest -> do- writeIORef spare_ref rest- return ( mode, emptyBuffer b (bufSize buf) WriteBuffer)- BufferListNil -> do- new_buf <- newCharBuffer (bufSize buf) WriteBuffer- return (mode, new_buf)----- NB. performance-critical code: eyeball the Core.-writeBlocks :: Handle -> Bool -> Bool -> Newline -> Buffer CharBufElem -> String -> IO ()-writeBlocks hdl line_buffered add_nl nl- buf@Buffer{ bufRaw=raw, bufSize=len } s =- let- shoveString :: Int -> [Char] -> [Char] -> IO ()- shoveString !n [] [] = do- commitBuffer hdl raw len n False{-no flush-} True{-release-}- shoveString !n [] rest = do- shoveString n rest []- shoveString !n (c:cs) rest- -- n+1 so we have enough room to write '\r\n' if necessary- | n + 1 >= len = do- commitBuffer hdl raw len n False{-flush-} False- shoveString 0 (c:cs) rest- | c == '\n' = do- n' <- if nl == CRLF- then do - n1 <- writeCharBuf raw n '\r'- writeCharBuf raw n1 '\n'- else do- writeCharBuf raw n c- if line_buffered- then do- -- end of line, so write and flush- commitBuffer hdl raw len n' True{-flush-} False- shoveString 0 cs rest- else do- shoveString n' cs rest- | otherwise = do- n' <- writeCharBuf raw n c- shoveString n' cs rest- in- shoveString 0 s (if add_nl then "\n" else "")---- -------------------------------------------------------------------------------- commitBuffer handle buf sz count flush release--- --- Write the contents of the buffer 'buf' ('sz' bytes long, containing--- 'count' bytes of data) to handle (handle must be block or line buffered).--commitBuffer- :: Handle -- handle to commit to- -> RawCharBuffer -> Int -- address and size (in bytes) of buffer- -> Int -- number of bytes of data in buffer- -> Bool -- True <=> flush the handle afterward- -> Bool -- release the buffer?- -> IO ()--commitBuffer hdl !raw !sz !count flush release = - wantWritableHandle "commitBuffer" hdl $ \h_@Handle__{..} -> do- debugIO ("commitBuffer: sz=" ++ show sz ++ ", count=" ++ show count- ++ ", flush=" ++ show flush ++ ", release=" ++ show release)-- writeCharBuffer h_ Buffer{ bufRaw=raw, bufState=WriteBuffer,- bufL=0, bufR=count, bufSize=sz }-- when flush $ flushByteWriteBuffer h_-- -- release the buffer if necessary- when release $ do- -- find size of current buffer- old_buf@Buffer{ bufSize=size } <- readIORef haCharBuffer- when (sz == size) $ do- spare_bufs <- readIORef haBuffers- writeIORef haBuffers (BufferListCons raw spare_bufs)-- return ()---- backwards compatibility; the text package uses this-commitBuffer' :: RawCharBuffer -> Int -> Int -> Bool -> Bool -> Handle__- -> IO CharBuffer-commitBuffer' raw sz@(I# _) count@(I# _) flush release h_@Handle__{..}- = do- debugIO ("commitBuffer: sz=" ++ show sz ++ ", count=" ++ show count- ++ ", flush=" ++ show flush ++ ", release=" ++ show release)-- let this_buf = Buffer{ bufRaw=raw, bufState=WriteBuffer,- bufL=0, bufR=count, bufSize=sz }-- writeCharBuffer h_ this_buf-- when flush $ flushByteWriteBuffer h_-- -- release the buffer if necessary- when release $ do- -- find size of current buffer- old_buf@Buffer{ bufSize=size } <- readIORef haCharBuffer- when (sz == size) $ do- spare_bufs <- readIORef haBuffers- writeIORef haBuffers (BufferListCons raw spare_bufs)-- return this_buf---- ------------------------------------------------------------------------------ Reading/writing sequences of bytes.---- ------------------------------------------------------------------------------ hPutBuf---- | 'hPutBuf' @hdl buf count@ writes @count@ 8-bit bytes from the--- buffer @buf@ to the handle @hdl@. It returns ().------ 'hPutBuf' ignores any text encoding that applies to the 'Handle',--- writing the bytes directly to the underlying file or device.------ 'hPutBuf' ignores the prevailing 'TextEncoding' and--- 'NewlineMode' on the 'Handle', and writes bytes directly.------ This operation may fail with:------ * 'ResourceVanished' if the handle is a pipe or socket, and the--- reading end is closed. (If this is a POSIX system, and the program--- has not asked to ignore SIGPIPE, then a SIGPIPE may be delivered--- instead, whose default action is to terminate the program).--hPutBuf :: Handle -- handle to write to- -> Ptr a -- address of buffer- -> Int -- number of bytes of data in buffer- -> IO ()-hPutBuf h ptr count = do _ <- hPutBuf' h ptr count True- return ()--hPutBufNonBlocking- :: Handle -- handle to write to- -> Ptr a -- address of buffer- -> Int -- number of bytes of data in buffer- -> IO Int -- returns: number of bytes written-hPutBufNonBlocking h ptr count = hPutBuf' h ptr count False--hPutBuf':: Handle -- handle to write to- -> Ptr a -- address of buffer- -> Int -- number of bytes of data in buffer- -> Bool -- allow blocking?- -> IO Int-hPutBuf' handle ptr count can_block- | count == 0 = return 0- | count < 0 = illegalBufferSize handle "hPutBuf" count- | otherwise = - wantWritableHandle "hPutBuf" handle $ - \ h_@Handle__{..} -> do- debugIO ("hPutBuf count=" ++ show count)-- r <- bufWrite h_ (castPtr ptr) count can_block-- -- we must flush if this Handle is set to NoBuffering. If- -- it is set to LineBuffering, be conservative and flush- -- anyway (we didn't check for newlines in the data).- case haBufferMode of- BlockBuffering _ -> do return ()- _line_or_no_buffering -> do flushWriteBuffer h_- return r--bufWrite :: Handle__-> Ptr Word8 -> Int -> Bool -> IO Int-bufWrite h_@Handle__{..} ptr count can_block =- seq count $ do -- strictness hack- old_buf@Buffer{ bufRaw=old_raw, bufR=w, bufSize=size }- <- readIORef haByteBuffer-- -- enough room in handle buffer?- if (size - w > count)- -- There's enough room in the buffer:- -- just copy the data in and update bufR.- then do debugIO ("hPutBuf: copying to buffer, w=" ++ show w)- copyToRawBuffer old_raw w ptr count- writeIORef haByteBuffer old_buf{ bufR = w + count }- return count-- -- else, we have to flush- else do debugIO "hPutBuf: flushing first"- old_buf' <- Buffered.flushWriteBuffer haDevice old_buf- -- TODO: we should do a non-blocking flush here- writeIORef haByteBuffer old_buf'- -- if we can fit in the buffer, then just loop - if count < size- then bufWrite h_ ptr count can_block- else if can_block- then do writeChunk h_ (castPtr ptr) count- return count- else writeChunkNonBlocking h_ (castPtr ptr) count--writeChunk :: Handle__ -> Ptr Word8 -> Int -> IO ()-writeChunk h_@Handle__{..} ptr bytes- | Just fd <- cast haDevice = RawIO.write (fd::FD) ptr bytes- | otherwise = error "Todo: hPutBuf"--writeChunkNonBlocking :: Handle__ -> Ptr Word8 -> Int -> IO Int-writeChunkNonBlocking h_@Handle__{..} ptr bytes - | Just fd <- cast haDevice = RawIO.writeNonBlocking (fd::FD) ptr bytes- | otherwise = error "Todo: hPutBuf"---- ------------------------------------------------------------------------------ hGetBuf---- | 'hGetBuf' @hdl buf count@ reads data from the handle @hdl@--- into the buffer @buf@ until either EOF is reached or--- @count@ 8-bit bytes have been read.--- It returns the number of bytes actually read. This may be zero if--- EOF was reached before any data was read (or if @count@ is zero).------ 'hGetBuf' never raises an EOF exception, instead it returns a value--- smaller than @count@.------ If the handle is a pipe or socket, and the writing end--- is closed, 'hGetBuf' will behave as if EOF was reached.------ 'hGetBuf' ignores the prevailing 'TextEncoding' and 'NewlineMode'--- on the 'Handle', and reads bytes directly.--hGetBuf :: Handle -> Ptr a -> Int -> IO Int-hGetBuf h ptr count- | count == 0 = return 0- | count < 0 = illegalBufferSize h "hGetBuf" count- | otherwise = - wantReadableHandle_ "hGetBuf" h $ \ h_@Handle__{..} -> do- flushCharReadBuffer h_- buf@Buffer{ bufRaw=raw, bufR=w, bufL=r, bufSize=sz }- <- readIORef haByteBuffer- if isEmptyBuffer buf- then bufReadEmpty h_ buf (castPtr ptr) 0 count- else bufReadNonEmpty h_ buf (castPtr ptr) 0 count---- small reads go through the buffer, large reads are satisfied by--- taking data first from the buffer and then direct from the file--- descriptor.--bufReadNonEmpty :: Handle__ -> Buffer Word8 -> Ptr Word8 -> Int -> Int -> IO Int-bufReadNonEmpty h_@Handle__{..}- buf@Buffer{ bufRaw=raw, bufR=w, bufL=r, bufSize=sz }- ptr !so_far !count - = do- let avail = w - r- if (count < avail)- then do - copyFromRawBuffer ptr raw r count- writeIORef haByteBuffer buf{ bufL = r + count }- return (so_far + count)- else do- - copyFromRawBuffer ptr raw r avail- let buf' = buf{ bufR=0, bufL=0 }- writeIORef haByteBuffer buf'- let remaining = count - avail- so_far' = so_far + avail- ptr' = ptr `plusPtr` avail-- if remaining == 0 - then return so_far'- else bufReadEmpty h_ buf' ptr' so_far' remaining---bufReadEmpty :: Handle__ -> Buffer Word8 -> Ptr Word8 -> Int -> Int -> IO Int-bufReadEmpty h_@Handle__{..}- buf@Buffer{ bufRaw=raw, bufR=w, bufL=r, bufSize=sz }- ptr so_far count- | count > sz, Just fd <- cast haDevice = loop fd 0 count- | otherwise = do- (r,buf') <- Buffered.fillReadBuffer haDevice buf- if r == 0 - then return so_far- else do writeIORef haByteBuffer buf'- bufReadNonEmpty h_ buf' ptr so_far count- where- loop :: FD -> Int -> Int -> IO Int- loop fd off bytes | bytes <= 0 = return (so_far + off)- loop fd off bytes = do- r <- RawIO.read (fd::FD) (ptr `plusPtr` off) bytes- if r == 0- then return (so_far + off)- else loop fd (off + r) (bytes - r)---- ------------------------------------------------------------------------------ hGetBufSome---- | 'hGetBufSome' @hdl buf count@ reads data from the handle @hdl@--- into the buffer @buf@. If there is any data available to read,--- then 'hGetBufSome' returns it immediately; it only blocks if there--- is no data to be read.------ It returns the number of bytes actually read. This may be zero if--- EOF was reached before any data was read (or if @count@ is zero).------ 'hGetBufSome' never raises an EOF exception, instead it returns a value--- smaller than @count@.------ If the handle is a pipe or socket, and the writing end--- is closed, 'hGetBufSome' will behave as if EOF was reached.------ 'hGetBufSome' ignores the prevailing 'TextEncoding' and 'NewlineMode'--- on the 'Handle', and reads bytes directly.--hGetBufSome :: Handle -> Ptr a -> Int -> IO Int-hGetBufSome h ptr count- | count == 0 = return 0- | count < 0 = illegalBufferSize h "hGetBufSome" count- | otherwise =- wantReadableHandle_ "hGetBufSome" h $ \ h_@Handle__{..} -> do- flushCharReadBuffer h_- buf@Buffer{ bufSize=sz } <- readIORef haByteBuffer- if isEmptyBuffer buf- then if count > sz -- large read?- then do RawIO.read (haFD h_) (castPtr ptr) count- else do (r,buf') <- Buffered.fillReadBuffer haDevice buf- if r == 0- then return 0- else do writeIORef haByteBuffer buf'- bufReadNBNonEmpty h_ buf' (castPtr ptr) 0 (min r count)- -- new count is (min r count), so- -- that bufReadNBNonEmpty will not- -- issue another read.- else- let count' = min count (bufferElems buf)- in bufReadNBNonEmpty h_ buf (castPtr ptr) 0 count'--haFD :: Handle__ -> FD-haFD h_@Handle__{..} =- case cast haDevice of- Nothing -> error "not an FD"- Just fd -> fd---- | 'hGetBufNonBlocking' @hdl buf count@ reads data from the handle @hdl@--- into the buffer @buf@ until either EOF is reached, or--- @count@ 8-bit bytes have been read, or there is no more data available--- to read immediately.------ 'hGetBufNonBlocking' is identical to 'hGetBuf', except that it will--- never block waiting for data to become available, instead it returns--- only whatever data is available. To wait for data to arrive before--- calling 'hGetBufNonBlocking', use 'hWaitForInput'.------ If the handle is a pipe or socket, and the writing end--- is closed, 'hGetBufNonBlocking' will behave as if EOF was reached.------ 'hGetBufNonBlocking' ignores the prevailing 'TextEncoding' and--- 'NewlineMode' on the 'Handle', and reads bytes directly.------ NOTE: on Windows, this function does not work correctly; it--- behaves identically to 'hGetBuf'.--hGetBufNonBlocking :: Handle -> Ptr a -> Int -> IO Int-hGetBufNonBlocking h ptr count- | count == 0 = return 0- | count < 0 = illegalBufferSize h "hGetBufNonBlocking" count- | otherwise = - wantReadableHandle_ "hGetBufNonBlocking" h $ \ h_@Handle__{..} -> do- flushCharReadBuffer h_- buf@Buffer{ bufRaw=raw, bufR=w, bufL=r, bufSize=sz }- <- readIORef haByteBuffer- if isEmptyBuffer buf- then bufReadNBEmpty h_ buf (castPtr ptr) 0 count- else bufReadNBNonEmpty h_ buf (castPtr ptr) 0 count--bufReadNBEmpty :: Handle__ -> Buffer Word8 -> Ptr Word8 -> Int -> Int -> IO Int-bufReadNBEmpty h_@Handle__{..}- buf@Buffer{ bufRaw=raw, bufR=w, bufL=r, bufSize=sz }- ptr so_far count- | count > sz,- Just fd <- cast haDevice = do- m <- RawIO.readNonBlocking (fd::FD) ptr count- case m of- Nothing -> return so_far- Just n -> return (so_far + n)-- | otherwise = do- buf <- readIORef haByteBuffer- (r,buf') <- Buffered.fillReadBuffer0 haDevice buf- case r of- Nothing -> return so_far- Just 0 -> return so_far- Just r -> do- writeIORef haByteBuffer buf'- bufReadNBNonEmpty h_ buf' ptr so_far (min count r)- -- NOTE: new count is min count r- -- so we will just copy the contents of the- -- buffer in the recursive call, and not- -- loop again.---bufReadNBNonEmpty :: Handle__ -> Buffer Word8 -> Ptr Word8 -> Int -> Int -> IO Int-bufReadNBNonEmpty h_@Handle__{..}- buf@Buffer{ bufRaw=raw, bufR=w, bufL=r, bufSize=sz }- ptr so_far count- = do- let avail = w - r- if (count < avail)- then do - copyFromRawBuffer ptr raw r count- writeIORef haByteBuffer buf{ bufL = r + count }- return (so_far + count)- else do-- copyFromRawBuffer ptr raw r avail- let buf' = buf{ bufR=0, bufL=0 }- writeIORef haByteBuffer buf'- let remaining = count - avail- so_far' = so_far + avail- ptr' = ptr `plusPtr` avail-- if remaining == 0- then return so_far'- else bufReadNBEmpty h_ buf' ptr' so_far' remaining---- ------------------------------------------------------------------------------ memcpy wrappers--copyToRawBuffer :: RawBuffer e -> Int -> Ptr e -> Int -> IO ()-copyToRawBuffer raw off ptr bytes =- withRawBuffer raw $ \praw ->- do _ <- memcpy (praw `plusPtr` off) ptr (fromIntegral bytes)- return ()--copyFromRawBuffer :: Ptr e -> RawBuffer e -> Int -> Int -> IO ()-copyFromRawBuffer ptr raw off bytes =- withRawBuffer raw $ \praw ->- do _ <- memcpy ptr (praw `plusPtr` off) (fromIntegral bytes)- return ()--foreign import ccall unsafe "memcpy"- memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr ())---------------------------------------------------------------------------------- Internal Utils--illegalBufferSize :: Handle -> String -> Int -> IO a-illegalBufferSize handle fn sz =- ioException (IOError (Just handle)- InvalidArgument fn- ("illegal buffer size " ++ showsPrec 9 sz [])- Nothing Nothing)-
@@ -1,431 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , ExistentialQuantification- , DeriveDataTypeable- #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.Handle.Types--- Copyright : (c) The University of Glasgow, 1994-2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Basic types for the implementation of IO Handles.-----------------------------------------------------------------------------------module GHC.IO.Handle.Types (- Handle(..), Handle__(..), showHandle,- checkHandleInvariants,- BufferList(..),- HandleType(..),- isReadableHandleType, isWritableHandleType, isReadWriteHandleType,- BufferMode(..),- BufferCodec(..),- NewlineMode(..), Newline(..), nativeNewline,- universalNewlineMode, noNewlineTranslation, nativeNewlineMode- ) where--#undef DEBUG--import GHC.Base-import GHC.MVar-import GHC.IO-import GHC.IO.Buffer-import GHC.IO.BufferedIO-import GHC.IO.Encoding.Types-import GHC.IORef-import Data.Maybe-import GHC.Show-import GHC.Read-import GHC.Word-import GHC.IO.Device-import Data.Typeable-#ifdef DEBUG-import Control.Monad-#endif---- ------------------------------------------------------------------------------ Handle type---- A Handle is represented by (a reference to) a record --- containing the state of the I/O port/device. We record--- the following pieces of info:---- * type (read,write,closed etc.)--- * the underlying file descriptor--- * buffering mode --- * buffer, and spare buffers--- * user-friendly name (usually the--- FilePath used when IO.openFile was called)---- Note: when a Handle is garbage collected, we want to flush its buffer--- and close the OS file handle, so as to free up a (precious) resource.---- | Haskell defines operations to read and write characters from and to files,--- represented by values of type @Handle@. Each value of this type is a--- /handle/: a record used by the Haskell run-time system to /manage/ I\/O--- with file system objects. A handle has at least the following properties:--- --- * whether it manages input or output or both;------ * whether it is /open/, /closed/ or /semi-closed/;------ * whether the object is seekable;------ * whether buffering is disabled, or enabled on a line or block basis;------ * a buffer (whose length may be zero).------ Most handles will also have a current I\/O position indicating where the next--- input or output operation will occur. A handle is /readable/ if it--- manages only input or both input and output; likewise, it is /writable/ if--- it manages only output or both input and output. A handle is /open/ when--- first allocated.--- Once it is closed it can no longer be used for either input or output,--- though an implementation cannot re-use its storage while references--- remain to it. Handles are in the 'Show' and 'Eq' classes. The string--- produced by showing a handle is system dependent; it should include--- enough information to identify the handle for debugging. A handle is--- equal according to '==' only to itself; no attempt--- is made to compare the internal state of different handles for equality.--data Handle - = FileHandle -- A normal handle to a file- FilePath -- the file (used for error messages- -- only)- !(MVar Handle__)-- | DuplexHandle -- A handle to a read/write stream- FilePath -- file for a FIFO, otherwise some- -- descriptive string (used for error- -- messages only)- !(MVar Handle__) -- The read side- !(MVar Handle__) -- The write side-- deriving Typeable---- NOTES:--- * A 'FileHandle' is seekable. A 'DuplexHandle' may or may not be--- seekable.--instance Eq Handle where- (FileHandle _ h1) == (FileHandle _ h2) = h1 == h2- (DuplexHandle _ h1 _) == (DuplexHandle _ h2 _) = h1 == h2- _ == _ = False --data Handle__- = forall dev enc_state dec_state . (IODevice dev, BufferedIO dev, Typeable dev) =>- Handle__ {- haDevice :: !dev,- haType :: HandleType, -- type (read/write/append etc.)- haByteBuffer :: !(IORef (Buffer Word8)),- haBufferMode :: BufferMode,- haLastDecode :: !(IORef (dec_state, Buffer Word8)),- haCharBuffer :: !(IORef (Buffer CharBufElem)), -- the current buffer- haBuffers :: !(IORef (BufferList CharBufElem)), -- spare buffers- haEncoder :: Maybe (TextEncoder enc_state),- haDecoder :: Maybe (TextDecoder dec_state),- haCodec :: Maybe TextEncoding,- haInputNL :: Newline,- haOutputNL :: Newline,- haOtherSide :: Maybe (MVar Handle__) -- ptr to the write side of a - -- duplex handle.- }- deriving Typeable---- we keep a few spare buffers around in a handle to avoid allocating--- a new one for each hPutStr. These buffers are *guaranteed* to be the--- same size as the main buffer.-data BufferList e- = BufferListNil - | BufferListCons (RawBuffer e) (BufferList e)---- Internally, we classify handles as being one--- of the following:--data HandleType- = ClosedHandle- | SemiClosedHandle- | ReadHandle- | WriteHandle- | AppendHandle- | ReadWriteHandle--isReadableHandleType :: HandleType -> Bool-isReadableHandleType ReadHandle = True-isReadableHandleType ReadWriteHandle = True-isReadableHandleType _ = False--isWritableHandleType :: HandleType -> Bool-isWritableHandleType AppendHandle = True-isWritableHandleType WriteHandle = True-isWritableHandleType ReadWriteHandle = True-isWritableHandleType _ = False--isReadWriteHandleType :: HandleType -> Bool-isReadWriteHandleType ReadWriteHandle{} = True-isReadWriteHandleType _ = False---- INVARIANTS on Handles:------ * A handle *always* has a buffer, even if it is only 1 character long--- (an unbuffered handle needs a 1 character buffer in order to support--- hLookAhead and hIsEOF).--- * In a read Handle, the byte buffer is always empty (we decode when reading)--- * In a wriite Handle, the Char buffer is always empty (we encode when writing)----checkHandleInvariants :: Handle__ -> IO ()-#ifdef DEBUG-checkHandleInvariants h_ = do- bbuf <- readIORef (haByteBuffer h_)- checkBuffer bbuf- cbuf <- readIORef (haCharBuffer h_)- checkBuffer cbuf- when (isWriteBuffer cbuf && not (isEmptyBuffer cbuf)) $- error ("checkHandleInvariants: char write buffer non-empty: " ++- summaryBuffer bbuf ++ ", " ++ summaryBuffer cbuf)- when (isWriteBuffer bbuf /= isWriteBuffer cbuf) $- error ("checkHandleInvariants: buffer modes differ: " ++- summaryBuffer bbuf ++ ", " ++ summaryBuffer cbuf)--#else-checkHandleInvariants _ = return ()-#endif---- ------------------------------------------------------------------------------ Buffering modes---- | Three kinds of buffering are supported: line-buffering, --- block-buffering or no-buffering. These modes have the following--- effects. For output, items are written out, or /flushed/,--- from the internal buffer according to the buffer mode:------ * /line-buffering/: the entire output buffer is flushed--- whenever a newline is output, the buffer overflows, --- a 'System.IO.hFlush' is issued, or the handle is closed.------ * /block-buffering/: the entire buffer is written out whenever it--- overflows, a 'System.IO.hFlush' is issued, or the handle is closed.------ * /no-buffering/: output is written immediately, and never stored--- in the buffer.------ An implementation is free to flush the buffer more frequently,--- but not less frequently, than specified above.--- The output buffer is emptied as soon as it has been written out.------ Similarly, input occurs according to the buffer mode for the handle:------ * /line-buffering/: when the buffer for the handle is not empty,--- the next item is obtained from the buffer; otherwise, when the--- buffer is empty, characters up to and including the next newline--- character are read into the buffer. No characters are available--- until the newline character is available or the buffer is full.------ * /block-buffering/: when the buffer for the handle becomes empty,--- the next block of data is read into the buffer.------ * /no-buffering/: the next input item is read and returned.--- The 'System.IO.hLookAhead' operation implies that even a no-buffered--- handle may require a one-character buffer.------ The default buffering mode when a handle is opened is--- implementation-dependent and may depend on the file system object--- which is attached to that handle.--- For most implementations, physical files will normally be block-buffered --- and terminals will normally be line-buffered.--data BufferMode - = NoBuffering -- ^ buffering is disabled if possible.- | LineBuffering- -- ^ line-buffering should be enabled if possible.- | BlockBuffering (Maybe Int)- -- ^ block-buffering should be enabled if possible.- -- The size of the buffer is @n@ items if the argument- -- is 'Just' @n@ and is otherwise implementation-dependent.- deriving (Eq, Ord, Read, Show)--{--[note Buffering Implementation]--Each Handle has two buffers: a byte buffer (haByteBuffer) and a Char-buffer (haCharBuffer). --[note Buffered Reading]--For read Handles, bytes are read into the byte buffer, and immediately-decoded into the Char buffer (see-GHC.IO.Handle.Internals.readTextDevice). The only way there might be-some data left in the byte buffer is if there is a partial multi-byte-character sequence that cannot be decoded into a full character.--Note that the buffering mode (haBufferMode) makes no difference when-reading data into a Handle. When reading, we can always just read all-the data there is available without blocking, decode it into the Char-buffer, and then provide it immediately to the caller.--[note Buffered Writing]--Characters are written into the Char buffer by e.g. hPutStr. At the-end of the operation, or when the char buffer is full, the buffer is-decoded to the byte buffer (see writeCharBuffer). This is so that we-can detect encoding errors at the right point.--Hence, the Char buffer is always empty between Handle operations.--[note Buffer Sizing]--The char buffer is always a default size (dEFAULT_CHAR_BUFFER_SIZE).-The byte buffer size is chosen by the underlying device (via its-IODevice.newBuffer). Hence the size of these buffers is not under-user control.--There are certain minimum sizes for these buffers imposed by the-library (but not checked):-- - we must be able to buffer at least one character, so that- hLookAhead can work-- - the byte buffer must be able to store at least one encoded- character in the current encoding (6 bytes?)-- - when reading, the char buffer must have room for two characters, so- that we can spot the \r\n sequence.--How do we implement hSetBuffering?--For reading, we have never used the user-supplied buffer size, because-there's no point: we always pass all available data to the reader-immediately. Buffering would imply waiting until a certain amount of-data is available, which has no advantages. So hSetBuffering is-essentially a no-op for read handles, except that it turns on/off raw-mode for the underlying device if necessary.--For writing, the buffering mode is handled by the write operations-themselves (hPutChar and hPutStr). Every write ends with-writeCharBuffer, which checks whether the buffer should be flushed-according to the current buffering mode. Additionally, we look for-newlines and flush if the mode is LineBuffering.--[note Buffer Flushing]--** Flushing the Char buffer--We must be able to flush the Char buffer, in order to implement-hSetEncoding, and things like hGetBuf which want to read raw bytes.--Flushing the Char buffer on a write Handle is easy: it is always empty.--Flushing the Char buffer on a read Handle involves rewinding the byte-buffer to the point representing the next Char in the Char buffer.-This is done by-- - remembering the state of the byte buffer *before* the last decode-- - re-decoding the bytes that represent the chars already read from the- Char buffer. This gives us the point in the byte buffer that- represents the *next* Char to be read.--In order for this to work, after readTextHandle we must NOT MODIFY THE-CONTENTS OF THE BYTE OR CHAR BUFFERS, except to remove characters from-the Char buffer.--** Flushing the byte buffer--The byte buffer can be flushed if the Char buffer has already been-flushed (see above). For a read Handle, flushing the byte buffer-means seeking the device back by the number of bytes in the buffer,-and hence it is only possible on a seekable Handle.---}---- ------------------------------------------------------------------------------ Newline translation---- | The representation of a newline in the external file or stream.-data Newline = LF -- ^ '\n'- | CRLF -- ^ '\r\n'- deriving (Eq, Ord, Read, Show)---- | Specifies the translation, if any, of newline characters between--- internal Strings and the external file or stream. Haskell Strings--- are assumed to represent newlines with the '\n' character; the--- newline mode specifies how to translate '\n' on output, and what to--- translate into '\n' on input.-data NewlineMode - = NewlineMode { inputNL :: Newline,- -- ^ the representation of newlines on input- outputNL :: Newline- -- ^ the representation of newlines on output- }- deriving (Eq, Ord, Read, Show)---- | The native newline representation for the current platform: 'LF'--- on Unix systems, 'CRLF' on Windows.-nativeNewline :: Newline-#ifdef mingw32_HOST_OS-nativeNewline = CRLF-#else-nativeNewline = LF-#endif---- | Map '\r\n' into '\n' on input, and '\n' to the native newline--- represetnation on output. This mode can be used on any platform, and--- works with text files using any newline convention. The downside is--- that @readFile >>= writeFile@ might yield a different file.--- --- > universalNewlineMode = NewlineMode { inputNL = CRLF, --- > outputNL = nativeNewline }----universalNewlineMode :: NewlineMode-universalNewlineMode = NewlineMode { inputNL = CRLF, - outputNL = nativeNewline }---- | Use the native newline representation on both input and output--- --- > nativeNewlineMode = NewlineMode { inputNL = nativeNewline--- > outputNL = nativeNewline }----nativeNewlineMode :: NewlineMode-nativeNewlineMode = NewlineMode { inputNL = nativeNewline, - outputNL = nativeNewline }---- | Do no newline translation at all.--- --- > noNewlineTranslation = NewlineMode { inputNL = LF, outputNL = LF }----noNewlineTranslation :: NewlineMode-noNewlineTranslation = NewlineMode { inputNL = LF, outputNL = LF }---- ------------------------------------------------------------------------------ Show instance for Handles---- handle types are 'show'n when printing error msgs, so--- we provide a more user-friendly Show instance for it--- than the derived one.--instance Show HandleType where- showsPrec _ t =- case t of- ClosedHandle -> showString "closed"- SemiClosedHandle -> showString "semi-closed"- ReadHandle -> showString "readable"- WriteHandle -> showString "writable"- AppendHandle -> showString "writable (append)"- ReadWriteHandle -> showString "read-writable"--instance Show Handle where - showsPrec _ (FileHandle file _) = showHandle file- showsPrec _ (DuplexHandle file _ _) = showHandle file--showHandle :: FilePath -> String -> String-showHandle file = showString "{handle: " . showString file . showString "}"-
@@ -1,30 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IO.IOMode--- Copyright : (c) The University of Glasgow, 1994-2008--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ The IOMode type-----------------------------------------------------------------------------------module GHC.IO.IOMode (IOMode(..)) where--import GHC.Base-import GHC.Show-import GHC.Read-import GHC.Arr-import GHC.Enum---- | See 'System.IO.openFile'-data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode- deriving (Eq, Ord, Ix, Enum, Read, Show)-
@@ -1,73 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IOArray--- Copyright : (c) The University of Glasgow 2008--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The IOArray type-----------------------------------------------------------------------------------module GHC.IOArray (- IOArray(..),- newIOArray, unsafeReadIOArray, unsafeWriteIOArray,- readIOArray, writeIOArray,- boundsIOArray- ) where--import GHC.Base-import GHC.IO-import GHC.Arr---- ------------------------------------------------------------------------------ | An 'IOArray' is a mutable, boxed, non-strict array in the 'IO' monad.--- The type arguments are as follows:------ * @i@: the index type of the array (should be an instance of 'Ix')------ * @e@: the element type of the array.--------newtype IOArray i e = IOArray (STArray RealWorld i e)---- explicit instance because Haddock can't figure out a derived one-instance Eq (IOArray i e) where- IOArray x == IOArray y = x == y---- |Build a new 'IOArray'-newIOArray :: Ix i => (i,i) -> e -> IO (IOArray i e)-{-# INLINE newIOArray #-}-newIOArray lu initial = stToIO $ do {marr <- newSTArray lu initial; return (IOArray marr)}---- | Read a value from an 'IOArray'-unsafeReadIOArray :: Ix i => IOArray i e -> Int -> IO e-{-# INLINE unsafeReadIOArray #-}-unsafeReadIOArray (IOArray marr) i = stToIO (unsafeReadSTArray marr i)---- | Write a new value into an 'IOArray'-unsafeWriteIOArray :: Ix i => IOArray i e -> Int -> e -> IO ()-{-# INLINE unsafeWriteIOArray #-}-unsafeWriteIOArray (IOArray marr) i e = stToIO (unsafeWriteSTArray marr i e)---- | Read a value from an 'IOArray'-readIOArray :: Ix i => IOArray i e -> i -> IO e-readIOArray (IOArray marr) i = stToIO (readSTArray marr i)---- | Write a new value into an 'IOArray'-writeIOArray :: Ix i => IOArray i e -> i -> e -> IO ()-writeIOArray (IOArray marr) i e = stToIO (writeSTArray marr i e)--{-# INLINE boundsIOArray #-}-boundsIOArray :: IOArray i e -> (i,i)-boundsIOArray (IOArray marr) = boundsSTArray marr-
@@ -1,93 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IOBase--- Copyright : (c) The University of Glasgow 1994-2009--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Backwards-compatibility interface-----------------------------------------------------------------------------------module GHC.IOBase {-# DEPRECATED "use GHC.IO instead" #-} (- IO(..), unIO, failIO, liftIO, bindIO, thenIO, returnIO,- unsafePerformIO, unsafeInterleaveIO,- unsafeDupablePerformIO, unsafeDupableInterleaveIO,- noDuplicate,-- -- To and from from ST- stToIO, ioToST, unsafeIOToST, unsafeSTToIO,-- -- References- IORef(..), newIORef, readIORef, writeIORef,- IOArray(..), newIOArray, readIOArray, writeIOArray, unsafeReadIOArray, unsafeWriteIOArray,- MVar(..),-- -- Handles, file descriptors,- FilePath,- Handle(..), Handle__(..), HandleType(..), IOMode(..), FD,- isReadableHandleType, isWritableHandleType, isReadWriteHandleType, showHandle,-- -- Buffers- -- Buffer(..), RawBuffer, BufferState(..),- BufferList(..), BufferMode(..),- --bufferIsWritable, bufferEmpty, bufferFull,-- -- Exceptions- Exception(..), ArithException(..), AsyncException(..), ArrayException(..),- stackOverflow, heapOverflow, ioException,- IOError, IOException(..), IOErrorType(..), ioError, userError,- ExitCode(..),- throwIO, block, unblock, blocked, catchAny, catchException,- evaluate,- ErrorCall(..), AssertionFailed(..), assertError, untangle,- BlockedOnDeadMVar(..), BlockedIndefinitely(..), Deadlock(..),- blockedOnDeadMVar, blockedIndefinitely- ) where--import GHC.Base-import GHC.Exception-import GHC.IO-import GHC.IO.Handle.Types-import GHC.IO.IOMode-import GHC.IO.Exception-import GHC.IOArray-import GHC.IORef-import GHC.MVar-import Foreign.C.Types-import Data.Typeable--type FD = CInt---- Backwards compat: this was renamed to BlockedIndefinitelyOnMVar-data BlockedOnDeadMVar = BlockedOnDeadMVar- deriving Typeable--instance Exception BlockedOnDeadMVar--instance Show BlockedOnDeadMVar where- showsPrec _ BlockedOnDeadMVar = showString "thread blocked indefinitely"--blockedOnDeadMVar :: SomeException -- for the RTS-blockedOnDeadMVar = toException BlockedOnDeadMVar----- Backwards compat: this was renamed to BlockedIndefinitelyOnSTM-data BlockedIndefinitely = BlockedIndefinitely- deriving Typeable--instance Exception BlockedIndefinitely--instance Show BlockedIndefinitely where- showsPrec _ BlockedIndefinitely = showString "thread blocked indefinitely"--blockedIndefinitely :: SomeException -- for the RTS-blockedIndefinitely = toException BlockedIndefinitely-
@@ -1,53 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.IORef--- Copyright : (c) The University of Glasgow 2008--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The IORef type-----------------------------------------------------------------------------------module GHC.IORef (- IORef(..),- newIORef, readIORef, writeIORef, atomicModifyIORef- ) where--import GHC.Base-import GHC.STRef-import GHC.IO---- ------------------------------------------------------------------------------ IORefs---- |A mutable variable in the 'IO' monad-newtype IORef a = IORef (STRef RealWorld a)---- explicit instance because Haddock can't figure out a derived one-instance Eq (IORef a) where- IORef x == IORef y = x == y---- |Build a new 'IORef'-newIORef :: a -> IO (IORef a)-newIORef v = stToIO (newSTRef v) >>= \ var -> return (IORef var)---- |Read the value of an 'IORef'-readIORef :: IORef a -> IO a-readIORef (IORef var) = stToIO (readSTRef var)---- |Write a new value into an 'IORef'-writeIORef :: IORef a -> a -> IO ()-writeIORef (IORef var) v = stToIO (writeSTRef var v)--atomicModifyIORef :: IORef a -> (a -> (a,b)) -> IO b-atomicModifyIORef (IORef (STRef r#)) f = IO $ \s -> atomicModifyMutVar# r# f s-
@@ -1,950 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, BangPatterns, MagicHash,- StandaloneDeriving #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Int--- Copyright : (c) The University of Glasgow 1997-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The sized integral datatypes, 'Int8', 'Int16', 'Int32', and 'Int64'.-----------------------------------------------------------------------------------#include "MachDeps.h"---- #hide-module GHC.Int (- Int8(..), Int16(..), Int32(..), Int64(..),- uncheckedIShiftL64#, uncheckedIShiftRA64#- ) where--import Data.Bits--#if WORD_SIZE_IN_BITS < 64-import GHC.IntWord64-#endif--import GHC.Base-import GHC.Enum-import GHC.Num-import GHC.Real-import GHC.Read-import GHC.Arr-import GHC.Err-import GHC.Word hiding (uncheckedShiftL64#, uncheckedShiftRL64#)-import GHC.Show-import GHC.Float () -- for RealFrac methods------------------------------------------------------------------------------ type Int8----------------------------------------------------------------------------- Int8 is represented in the same way as Int. Operations may assume--- and must ensure that it holds only values from its logical range.--data Int8 = I8# Int# deriving (Eq, Ord)--- ^ 8-bit signed integer type--instance Show Int8 where- showsPrec p x = showsPrec p (fromIntegral x :: Int)--instance Num Int8 where- (I8# x#) + (I8# y#) = I8# (narrow8Int# (x# +# y#))- (I8# x#) - (I8# y#) = I8# (narrow8Int# (x# -# y#))- (I8# x#) * (I8# y#) = I8# (narrow8Int# (x# *# y#))- negate (I8# x#) = I8# (narrow8Int# (negateInt# x#))- abs x | x >= 0 = x- | otherwise = negate x- signum x | x > 0 = 1- signum 0 = 0- signum _ = -1- fromInteger i = I8# (narrow8Int# (integerToInt i))--instance Real Int8 where- toRational x = toInteger x % 1--instance Enum Int8 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Int8"- pred x- | x /= minBound = x - 1- | otherwise = predError "Int8"- toEnum i@(I# i#)- | i >= fromIntegral (minBound::Int8) && i <= fromIntegral (maxBound::Int8)- = I8# i#- | otherwise = toEnumError "Int8" i (minBound::Int8, maxBound::Int8)- fromEnum (I8# x#) = I# x#- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen--instance Integral Int8 where- quot x@(I8# x#) y@(I8# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I8# (narrow8Int# (x# `quotInt#` y#))- rem (I8# x#) y@(I8# y#)- | y == 0 = divZeroError- | otherwise = I8# (narrow8Int# (x# `remInt#` y#))- div x@(I8# x#) y@(I8# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I8# (narrow8Int# (x# `divInt#` y#))- mod (I8# x#) y@(I8# y#)- | y == 0 = divZeroError- | otherwise = I8# (narrow8Int# (x# `modInt#` y#))- quotRem x@(I8# x#) y@(I8# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I8# (narrow8Int# (x# `quotInt#` y#)),- I8# (narrow8Int# (x# `remInt#` y#)))- divMod x@(I8# x#) y@(I8# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I8# (narrow8Int# (x# `divInt#` y#)),- I8# (narrow8Int# (x# `modInt#` y#)))- toInteger (I8# x#) = smallInteger x#--instance Bounded Int8 where- minBound = -0x80- maxBound = 0x7F--instance Ix Int8 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral i - fromIntegral m- inRange (m,n) i = m <= i && i <= n--instance Read Int8 where- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]--instance Bits Int8 where- {-# INLINE shift #-}-- (I8# x#) .&. (I8# y#) = I8# (word2Int# (int2Word# x# `and#` int2Word# y#))- (I8# x#) .|. (I8# y#) = I8# (word2Int# (int2Word# x# `or#` int2Word# y#))- (I8# x#) `xor` (I8# y#) = I8# (word2Int# (int2Word# x# `xor#` int2Word# y#))- complement (I8# x#) = I8# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))- (I8# x#) `shift` (I# i#)- | i# >=# 0# = I8# (narrow8Int# (x# `iShiftL#` i#))- | otherwise = I8# (x# `iShiftRA#` negateInt# i#)- (I8# x#) `shiftL` (I# i#) = I8# (narrow8Int# (x# `iShiftL#` i#))- (I8# x#) `unsafeShiftL` (I# i#) = I8# (narrow8Int# (x# `uncheckedIShiftL#` i#))- (I8# x#) `shiftR` (I# i#) = I8# (x# `iShiftRA#` i#)- (I8# x#) `unsafeShiftR` (I# i#) = I8# (x# `uncheckedIShiftRA#` i#)- (I8# x#) `rotate` (I# i#)- | i'# ==# 0#- = I8# x#- | otherwise- = I8# (narrow8Int# (word2Int# ((x'# `uncheckedShiftL#` i'#) `or#`- (x'# `uncheckedShiftRL#` (8# -# i'#)))))- where- !x'# = narrow8Word# (int2Word# x#)- !i'# = word2Int# (int2Word# i# `and#` int2Word# 7#)- bitSize _ = 8- isSigned _ = True- popCount (I8# x#) = I# (word2Int# (popCnt8# (int2Word# x#)))--{-# RULES-"fromIntegral/Int8->Int8" fromIntegral = id :: Int8 -> Int8-"fromIntegral/a->Int8" fromIntegral = \x -> case fromIntegral x of I# x# -> I8# (narrow8Int# x#)-"fromIntegral/Int8->a" fromIntegral = \(I8# x#) -> fromIntegral (I# x#)- #-}--{-# RULES-"properFraction/Float->(Int8,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int8) n, y) }-"truncate/Float->Int8"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Int8) (truncate x)-"floor/Float->Int8"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Int8) (floor x)-"ceiling/Float->Int8"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Int8) (ceiling x)-"round/Float->Int8"- forall x. round (x :: Float) = (fromIntegral :: Int -> Int8) (round x)- #-}--{-# RULES-"properFraction/Double->(Int8,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int8) n, y) }-"truncate/Double->Int8"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Int8) (truncate x)-"floor/Double->Int8"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Int8) (floor x)-"ceiling/Double->Int8"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Int8) (ceiling x)-"round/Double->Int8"- forall x. round (x :: Double) = (fromIntegral :: Int -> Int8) (round x)- #-}----------------------------------------------------------------------------- type Int16----------------------------------------------------------------------------- Int16 is represented in the same way as Int. Operations may assume--- and must ensure that it holds only values from its logical range.--data Int16 = I16# Int# deriving (Eq, Ord)--- ^ 16-bit signed integer type--instance Show Int16 where- showsPrec p x = showsPrec p (fromIntegral x :: Int)--instance Num Int16 where- (I16# x#) + (I16# y#) = I16# (narrow16Int# (x# +# y#))- (I16# x#) - (I16# y#) = I16# (narrow16Int# (x# -# y#))- (I16# x#) * (I16# y#) = I16# (narrow16Int# (x# *# y#))- negate (I16# x#) = I16# (narrow16Int# (negateInt# x#))- abs x | x >= 0 = x- | otherwise = negate x- signum x | x > 0 = 1- signum 0 = 0- signum _ = -1- fromInteger i = I16# (narrow16Int# (integerToInt i))--instance Real Int16 where- toRational x = toInteger x % 1--instance Enum Int16 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Int16"- pred x- | x /= minBound = x - 1- | otherwise = predError "Int16"- toEnum i@(I# i#)- | i >= fromIntegral (minBound::Int16) && i <= fromIntegral (maxBound::Int16)- = I16# i#- | otherwise = toEnumError "Int16" i (minBound::Int16, maxBound::Int16)- fromEnum (I16# x#) = I# x#- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen--instance Integral Int16 where- quot x@(I16# x#) y@(I16# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I16# (narrow16Int# (x# `quotInt#` y#))- rem (I16# x#) y@(I16# y#)- | y == 0 = divZeroError- | otherwise = I16# (narrow16Int# (x# `remInt#` y#))- div x@(I16# x#) y@(I16# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I16# (narrow16Int# (x# `divInt#` y#))- mod (I16# x#) y@(I16# y#)- | y == 0 = divZeroError- | otherwise = I16# (narrow16Int# (x# `modInt#` y#))- quotRem x@(I16# x#) y@(I16# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I16# (narrow16Int# (x# `quotInt#` y#)),- I16# (narrow16Int# (x# `remInt#` y#)))- divMod x@(I16# x#) y@(I16# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I16# (narrow16Int# (x# `divInt#` y#)),- I16# (narrow16Int# (x# `modInt#` y#)))- toInteger (I16# x#) = smallInteger x#--instance Bounded Int16 where- minBound = -0x8000- maxBound = 0x7FFF--instance Ix Int16 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral i - fromIntegral m- inRange (m,n) i = m <= i && i <= n--instance Read Int16 where- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]--instance Bits Int16 where- {-# INLINE shift #-}-- (I16# x#) .&. (I16# y#) = I16# (word2Int# (int2Word# x# `and#` int2Word# y#))- (I16# x#) .|. (I16# y#) = I16# (word2Int# (int2Word# x# `or#` int2Word# y#))- (I16# x#) `xor` (I16# y#) = I16# (word2Int# (int2Word# x# `xor#` int2Word# y#))- complement (I16# x#) = I16# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))- (I16# x#) `shift` (I# i#)- | i# >=# 0# = I16# (narrow16Int# (x# `iShiftL#` i#))- | otherwise = I16# (x# `iShiftRA#` negateInt# i#)- (I16# x#) `shiftL` (I# i#) = I16# (narrow16Int# (x# `iShiftL#` i#))- (I16# x#) `unsafeShiftL` (I# i#) = I16# (narrow16Int# (x# `uncheckedIShiftL#` i#))- (I16# x#) `shiftR` (I# i#) = I16# (x# `iShiftRA#` i#)- (I16# x#) `unsafeShiftR` (I# i#) = I16# (x# `uncheckedIShiftRA#` i#)- (I16# x#) `rotate` (I# i#)- | i'# ==# 0#- = I16# x#- | otherwise- = I16# (narrow16Int# (word2Int# ((x'# `uncheckedShiftL#` i'#) `or#`- (x'# `uncheckedShiftRL#` (16# -# i'#)))))- where- !x'# = narrow16Word# (int2Word# x#)- !i'# = word2Int# (int2Word# i# `and#` int2Word# 15#)- bitSize _ = 16- isSigned _ = True- popCount (I16# x#) = I# (word2Int# (popCnt16# (int2Word# x#)))---{-# RULES-"fromIntegral/Word8->Int16" fromIntegral = \(W8# x#) -> I16# (word2Int# x#)-"fromIntegral/Int8->Int16" fromIntegral = \(I8# x#) -> I16# x#-"fromIntegral/Int16->Int16" fromIntegral = id :: Int16 -> Int16-"fromIntegral/a->Int16" fromIntegral = \x -> case fromIntegral x of I# x# -> I16# (narrow16Int# x#)-"fromIntegral/Int16->a" fromIntegral = \(I16# x#) -> fromIntegral (I# x#)- #-}--{-# RULES-"properFraction/Float->(Int16,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int16) n, y) }-"truncate/Float->Int16"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Int16) (truncate x)-"floor/Float->Int16"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Int16) (floor x)-"ceiling/Float->Int16"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Int16) (ceiling x)-"round/Float->Int16"- forall x. round (x :: Float) = (fromIntegral :: Int -> Int16) (round x)- #-}--{-# RULES-"properFraction/Double->(Int16,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int16) n, y) }-"truncate/Double->Int16"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Int16) (truncate x)-"floor/Double->Int16"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Int16) (floor x)-"ceiling/Double->Int16"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Int16) (ceiling x)-"round/Double->Int16"- forall x. round (x :: Double) = (fromIntegral :: Int -> Int16) (round x)- #-}----------------------------------------------------------------------------- type Int32----------------------------------------------------------------------------- Int32 is represented in the same way as Int.-#if WORD_SIZE_IN_BITS > 32--- Operations may assume and must ensure that it holds only values--- from its logical range.-#endif--data Int32 = I32# Int# deriving (Eq, Ord)--- ^ 32-bit signed integer type--instance Show Int32 where- showsPrec p x = showsPrec p (fromIntegral x :: Int)--instance Num Int32 where- (I32# x#) + (I32# y#) = I32# (narrow32Int# (x# +# y#))- (I32# x#) - (I32# y#) = I32# (narrow32Int# (x# -# y#))- (I32# x#) * (I32# y#) = I32# (narrow32Int# (x# *# y#))- negate (I32# x#) = I32# (narrow32Int# (negateInt# x#))- abs x | x >= 0 = x- | otherwise = negate x- signum x | x > 0 = 1- signum 0 = 0- signum _ = -1- fromInteger i = I32# (narrow32Int# (integerToInt i))--instance Enum Int32 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Int32"- pred x- | x /= minBound = x - 1- | otherwise = predError "Int32"-#if WORD_SIZE_IN_BITS == 32- toEnum (I# i#) = I32# i#-#else- toEnum i@(I# i#)- | i >= fromIntegral (minBound::Int32) && i <= fromIntegral (maxBound::Int32)- = I32# i#- | otherwise = toEnumError "Int32" i (minBound::Int32, maxBound::Int32)-#endif- fromEnum (I32# x#) = I# x#- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen--instance Integral Int32 where- quot x@(I32# x#) y@(I32# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I32# (narrow32Int# (x# `quotInt#` y#))- rem (I32# x#) y@(I32# y#)- | y == 0 = divZeroError- -- The quotRem CPU instruction fails for minBound `quotRem` -1,- -- but minBound `rem` -1 is well-defined (0). We therefore- -- special-case it.- | y == (-1) = 0- | otherwise = I32# (narrow32Int# (x# `remInt#` y#))- div x@(I32# x#) y@(I32# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I32# (narrow32Int# (x# `divInt#` y#))- mod (I32# x#) y@(I32# y#)- | y == 0 = divZeroError- -- The divMod CPU instruction fails for minBound `divMod` -1,- -- but minBound `mod` -1 is well-defined (0). We therefore- -- special-case it.- | y == (-1) = 0- | otherwise = I32# (narrow32Int# (x# `modInt#` y#))- quotRem x@(I32# x#) y@(I32# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I32# (narrow32Int# (x# `quotInt#` y#)),- I32# (narrow32Int# (x# `remInt#` y#)))- divMod x@(I32# x#) y@(I32# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I32# (narrow32Int# (x# `divInt#` y#)),- I32# (narrow32Int# (x# `modInt#` y#)))- toInteger (I32# x#) = smallInteger x#--instance Read Int32 where- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]--instance Bits Int32 where- {-# INLINE shift #-}-- (I32# x#) .&. (I32# y#) = I32# (word2Int# (int2Word# x# `and#` int2Word# y#))- (I32# x#) .|. (I32# y#) = I32# (word2Int# (int2Word# x# `or#` int2Word# y#))- (I32# x#) `xor` (I32# y#) = I32# (word2Int# (int2Word# x# `xor#` int2Word# y#))- complement (I32# x#) = I32# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))- (I32# x#) `shift` (I# i#)- | i# >=# 0# = I32# (narrow32Int# (x# `iShiftL#` i#))- | otherwise = I32# (x# `iShiftRA#` negateInt# i#)- (I32# x#) `shiftL` (I# i#) = I32# (narrow32Int# (x# `iShiftL#` i#))- (I32# x#) `unsafeShiftL` (I# i#) =- I32# (narrow32Int# (x# `uncheckedIShiftL#` i#))- (I32# x#) `shiftR` (I# i#) = I32# (x# `iShiftRA#` i#)- (I32# x#) `unsafeShiftR` (I# i#) = I32# (x# `uncheckedIShiftRA#` i#)- (I32# x#) `rotate` (I# i#)- | i'# ==# 0#- = I32# x#- | otherwise- = I32# (narrow32Int# (word2Int# ((x'# `uncheckedShiftL#` i'#) `or#`- (x'# `uncheckedShiftRL#` (32# -# i'#)))))- where- !x'# = narrow32Word# (int2Word# x#)- !i'# = word2Int# (int2Word# i# `and#` int2Word# 31#)- bitSize _ = 32- isSigned _ = True- popCount (I32# x#) = I# (word2Int# (popCnt32# (int2Word# x#)))--{-# RULES-"fromIntegral/Word8->Int32" fromIntegral = \(W8# x#) -> I32# (word2Int# x#)-"fromIntegral/Word16->Int32" fromIntegral = \(W16# x#) -> I32# (word2Int# x#)-"fromIntegral/Int8->Int32" fromIntegral = \(I8# x#) -> I32# x#-"fromIntegral/Int16->Int32" fromIntegral = \(I16# x#) -> I32# x#-"fromIntegral/Int32->Int32" fromIntegral = id :: Int32 -> Int32-"fromIntegral/a->Int32" fromIntegral = \x -> case fromIntegral x of I# x# -> I32# (narrow32Int# x#)-"fromIntegral/Int32->a" fromIntegral = \(I32# x#) -> fromIntegral (I# x#)- #-}--{-# RULES-"properFraction/Float->(Int32,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int32) n, y) }-"truncate/Float->Int32"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Int32) (truncate x)-"floor/Float->Int32"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Int32) (floor x)-"ceiling/Float->Int32"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Int32) (ceiling x)-"round/Float->Int32"- forall x. round (x :: Float) = (fromIntegral :: Int -> Int32) (round x)- #-}--{-# RULES-"properFraction/Double->(Int32,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int32) n, y) }-"truncate/Double->Int32"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Int32) (truncate x)-"floor/Double->Int32"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Int32) (floor x)-"ceiling/Double->Int32"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Int32) (ceiling x)-"round/Double->Int32"- forall x. round (x :: Double) = (fromIntegral :: Int -> Int32) (round x)- #-}--instance Real Int32 where- toRational x = toInteger x % 1--instance Bounded Int32 where- minBound = -0x80000000- maxBound = 0x7FFFFFFF--instance Ix Int32 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral i - fromIntegral m- inRange (m,n) i = m <= i && i <= n----------------------------------------------------------------------------- type Int64---------------------------------------------------------------------------#if WORD_SIZE_IN_BITS < 64--data Int64 = I64# Int64#--- ^ 64-bit signed integer type--instance Eq Int64 where- (I64# x#) == (I64# y#) = x# `eqInt64#` y#- (I64# x#) /= (I64# y#) = x# `neInt64#` y#--instance Ord Int64 where- (I64# x#) < (I64# y#) = x# `ltInt64#` y#- (I64# x#) <= (I64# y#) = x# `leInt64#` y#- (I64# x#) > (I64# y#) = x# `gtInt64#` y#- (I64# x#) >= (I64# y#) = x# `geInt64#` y#--instance Show Int64 where- showsPrec p x = showsPrec p (toInteger x)--instance Num Int64 where- (I64# x#) + (I64# y#) = I64# (x# `plusInt64#` y#)- (I64# x#) - (I64# y#) = I64# (x# `minusInt64#` y#)- (I64# x#) * (I64# y#) = I64# (x# `timesInt64#` y#)- negate (I64# x#) = I64# (negateInt64# x#)- abs x | x >= 0 = x- | otherwise = negate x- signum x | x > 0 = 1- signum 0 = 0- signum _ = -1- fromInteger i = I64# (integerToInt64 i)--instance Enum Int64 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Int64"- pred x- | x /= minBound = x - 1- | otherwise = predError "Int64"- toEnum (I# i#) = I64# (intToInt64# i#)- fromEnum x@(I64# x#)- | x >= fromIntegral (minBound::Int) && x <= fromIntegral (maxBound::Int)- = I# (int64ToInt# x#)- | otherwise = fromEnumError "Int64" x- enumFrom = integralEnumFrom- enumFromThen = integralEnumFromThen- enumFromTo = integralEnumFromTo- enumFromThenTo = integralEnumFromThenTo--instance Integral Int64 where- quot x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I64# (x# `quotInt64#` y#)- rem (I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- The quotRem CPU instruction fails for minBound `quotRem` -1,- -- but minBound `rem` -1 is well-defined (0). We therefore- -- special-case it.- | y == (-1) = 0- | otherwise = I64# (x# `remInt64#` y#)- div x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I64# (x# `divInt64#` y#)- mod (I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- The divMod CPU instruction fails for minBound `divMod` -1,- -- but minBound `mod` -1 is well-defined (0). We therefore- -- special-case it.- | y == (-1) = 0- | otherwise = I64# (x# `modInt64#` y#)- quotRem x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I64# (x# `quotInt64#` y#),- I64# (x# `remInt64#` y#))- divMod x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I64# (x# `divInt64#` y#),- I64# (x# `modInt64#` y#))- toInteger (I64# x) = int64ToInteger x---divInt64#, modInt64# :: Int64# -> Int64# -> Int64#-x# `divInt64#` y#- | (x# `gtInt64#` intToInt64# 0#) && (y# `ltInt64#` intToInt64# 0#)- = ((x# `minusInt64#` y#) `minusInt64#` intToInt64# 1#) `quotInt64#` y#- | (x# `ltInt64#` intToInt64# 0#) && (y# `gtInt64#` intToInt64# 0#)- = ((x# `minusInt64#` y#) `plusInt64#` intToInt64# 1#) `quotInt64#` y#- | otherwise = x# `quotInt64#` y#-x# `modInt64#` y#- | (x# `gtInt64#` intToInt64# 0#) && (y# `ltInt64#` intToInt64# 0#) ||- (x# `ltInt64#` intToInt64# 0#) && (y# `gtInt64#` intToInt64# 0#)- = if r# `neInt64#` intToInt64# 0# then r# `plusInt64#` y# else intToInt64# 0#- | otherwise = r#- where- !r# = x# `remInt64#` y#--instance Read Int64 where- readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]--instance Bits Int64 where- {-# INLINE shift #-}-- (I64# x#) .&. (I64# y#) = I64# (word64ToInt64# (int64ToWord64# x# `and64#` int64ToWord64# y#))- (I64# x#) .|. (I64# y#) = I64# (word64ToInt64# (int64ToWord64# x# `or64#` int64ToWord64# y#))- (I64# x#) `xor` (I64# y#) = I64# (word64ToInt64# (int64ToWord64# x# `xor64#` int64ToWord64# y#))- complement (I64# x#) = I64# (word64ToInt64# (not64# (int64ToWord64# x#)))- (I64# x#) `shift` (I# i#)- | i# >=# 0# = I64# (x# `iShiftL64#` i#)- | otherwise = I64# (x# `iShiftRA64#` negateInt# i#)- (I64# x#) `shiftL` (I# i#) = I64# (x# `iShiftL64#` i#)- (I64# x#) `unsafeShiftL` (I# i#) = I64# (x# `uncheckedIShiftL64#` i#)- (I64# x#) `shiftR` (I# i#) = I64# (x# `iShiftRA64#` i#)- (I64# x#) `unsafeShiftR` (I# i#) = I64# (x# `uncheckedIShiftRA64#` i#)- (I64# x#) `rotate` (I# i#)- | i'# ==# 0#- = I64# x#- | otherwise- = I64# (word64ToInt64# ((x'# `uncheckedShiftL64#` i'#) `or64#`- (x'# `uncheckedShiftRL64#` (64# -# i'#))))- where- !x'# = int64ToWord64# x#- !i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)- bitSize _ = 64- isSigned _ = True- popCount (I64# x#) =- I# (word2Int# (popCnt64# (int64ToWord64# x#)))---- give the 64-bit shift operations the same treatment as the 32-bit--- ones (see GHC.Base), namely we wrap them in tests to catch the--- cases when we're shifting more than 64 bits to avoid unspecified--- behaviour in the C shift operations.--iShiftL64#, iShiftRA64# :: Int64# -> Int# -> Int64#--a `iShiftL64#` b | b >=# 64# = intToInt64# 0#- | otherwise = a `uncheckedIShiftL64#` b--a `iShiftRA64#` b | b >=# 64# = if a `ltInt64#` (intToInt64# 0#)- then intToInt64# (-1#)- else intToInt64# 0#- | otherwise = a `uncheckedIShiftRA64#` b--{-# RULES-"fromIntegral/Int->Int64" fromIntegral = \(I# x#) -> I64# (intToInt64# x#)-"fromIntegral/Word->Int64" fromIntegral = \(W# x#) -> I64# (word64ToInt64# (wordToWord64# x#))-"fromIntegral/Word64->Int64" fromIntegral = \(W64# x#) -> I64# (word64ToInt64# x#)-"fromIntegral/Int64->Int" fromIntegral = \(I64# x#) -> I# (int64ToInt# x#)-"fromIntegral/Int64->Word" fromIntegral = \(I64# x#) -> W# (int2Word# (int64ToInt# x#))-"fromIntegral/Int64->Word64" fromIntegral = \(I64# x#) -> W64# (int64ToWord64# x#)-"fromIntegral/Int64->Int64" fromIntegral = id :: Int64 -> Int64- #-}---- No RULES for RealFrac methods if Int is smaller than Int64, we can't--- go through Int and whether going through Integer is faster is uncertain.-#else---- Int64 is represented in the same way as Int.--- Operations may assume and must ensure that it holds only values--- from its logical range.--data Int64 = I64# Int# deriving (Eq, Ord)--- ^ 64-bit signed integer type--instance Show Int64 where- showsPrec p x = showsPrec p (fromIntegral x :: Int)--instance Num Int64 where- (I64# x#) + (I64# y#) = I64# (x# +# y#)- (I64# x#) - (I64# y#) = I64# (x# -# y#)- (I64# x#) * (I64# y#) = I64# (x# *# y#)- negate (I64# x#) = I64# (negateInt# x#)- abs x | x >= 0 = x- | otherwise = negate x- signum x | x > 0 = 1- signum 0 = 0- signum _ = -1- fromInteger i = I64# (integerToInt i)--instance Enum Int64 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Int64"- pred x- | x /= minBound = x - 1- | otherwise = predError "Int64"- toEnum (I# i#) = I64# i#- fromEnum (I64# x#) = I# x#- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen--instance Integral Int64 where- quot x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I64# (x# `quotInt#` y#)- rem (I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- The quotRem CPU instruction fails for minBound `quotRem` -1,- -- but minBound `rem` -1 is well-defined (0). We therefore- -- special-case it.- | y == (-1) = 0- | otherwise = I64# (x# `remInt#` y#)- div x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError -- Note [Order of tests]- | otherwise = I64# (x# `divInt#` y#)- mod (I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- The divMod CPU instruction fails for minBound `divMod` -1,- -- but minBound `mod` -1 is well-defined (0). We therefore- -- special-case it.- | y == (-1) = 0- | otherwise = I64# (x# `modInt#` y#)- quotRem x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I64# (x# `quotInt#` y#), I64# (x# `remInt#` y#))- divMod x@(I64# x#) y@(I64# y#)- | y == 0 = divZeroError- -- Note [Order of tests]- | y == (-1) && x == minBound = (overflowError, 0)- | otherwise = (I64# (x# `divInt#` y#), I64# (x# `modInt#` y#))- toInteger (I64# x#) = smallInteger x#--instance Read Int64 where- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]--instance Bits Int64 where- {-# INLINE shift #-}-- (I64# x#) .&. (I64# y#) = I64# (word2Int# (int2Word# x# `and#` int2Word# y#))- (I64# x#) .|. (I64# y#) = I64# (word2Int# (int2Word# x# `or#` int2Word# y#))- (I64# x#) `xor` (I64# y#) = I64# (word2Int# (int2Word# x# `xor#` int2Word# y#))- complement (I64# x#) = I64# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))- (I64# x#) `shift` (I# i#)- | i# >=# 0# = I64# (x# `iShiftL#` i#)- | otherwise = I64# (x# `iShiftRA#` negateInt# i#)- (I64# x#) `shiftL` (I# i#) = I64# (x# `iShiftL#` i#)- (I64# x#) `unsafeShiftL` (I# i#) = I64# (x# `uncheckedIShiftL#` i#)- (I64# x#) `shiftR` (I# i#) = I64# (x# `iShiftRA#` i#)- (I64# x#) `unsafeShiftR` (I# i#) = I64# (x# `uncheckedIShiftRA#` i#)- (I64# x#) `rotate` (I# i#)- | i'# ==# 0#- = I64# x#- | otherwise- = I64# (word2Int# ((x'# `uncheckedShiftL#` i'#) `or#`- (x'# `uncheckedShiftRL#` (64# -# i'#))))- where- !x'# = int2Word# x#- !i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)- bitSize _ = 64- isSigned _ = True- popCount (I64# x#) = I# (word2Int# (popCnt64# (int2Word# x#)))--{-# RULES-"fromIntegral/a->Int64" fromIntegral = \x -> case fromIntegral x of I# x# -> I64# x#-"fromIntegral/Int64->a" fromIntegral = \(I64# x#) -> fromIntegral (I# x#)- #-}--{-# RULES-"properFraction/Float->(Int64,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int64) n, y) }-"truncate/Float->Int64"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Int64) (truncate x)-"floor/Float->Int64"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Int64) (floor x)-"ceiling/Float->Int64"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Int64) (ceiling x)-"round/Float->Int64"- forall x. round (x :: Float) = (fromIntegral :: Int -> Int64) (round x)- #-}--{-# RULES-"properFraction/Double->(Int64,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Int64) n, y) }-"truncate/Double->Int64"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Int64) (truncate x)-"floor/Double->Int64"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Int64) (floor x)-"ceiling/Double->Int64"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Int64) (ceiling x)-"round/Double->Int64"- forall x. round (x :: Double) = (fromIntegral :: Int -> Int64) (round x)- #-}--uncheckedIShiftL64# :: Int# -> Int# -> Int#-uncheckedIShiftL64# = uncheckedIShiftL#--uncheckedIShiftRA64# :: Int# -> Int# -> Int#-uncheckedIShiftRA64# = uncheckedIShiftRA#-#endif--instance Real Int64 where- toRational x = toInteger x % 1--instance Bounded Int64 where- minBound = -0x8000000000000000- maxBound = 0x7FFFFFFFFFFFFFFF--instance Ix Int64 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral i - fromIntegral m- inRange (m,n) i = m <= i && i <= n---{--Note [Order of tests]--Suppose we had a definition like:-- quot x y- | y == 0 = divZeroError- | x == minBound && y == (-1) = overflowError- | otherwise = x `primQuot` y--Note in particular that the- x == minBound-test comes before the- y == (-1)-test.--this expands to something like:-- case y of- 0 -> divZeroError- _ -> case x of- -9223372036854775808 ->- case y of- -1 -> overflowError- _ -> x `primQuot` y- _ -> x `primQuot` y--Now if we have the call (x `quot` 2), and quot gets inlined, then we get:-- case 2 of- 0 -> divZeroError- _ -> case x of- -9223372036854775808 ->- case 2 of- -1 -> overflowError- _ -> x `primQuot` 2- _ -> x `primQuot` 2--which simplifies to:-- case x of- -9223372036854775808 -> x `primQuot` 2- _ -> x `primQuot` 2--Now we have a case with two identical branches, which would be-eliminated (assuming it doesn't affect strictness, which it doesn't in-this case), leaving the desired:-- x `primQuot` 2--except in the minBound branch we know what x is, and GHC cleverly does-the division at compile time, giving:-- case x of- -9223372036854775808 -> -4611686018427387904- _ -> x `primQuot` 2--So instead we use a definition like:-- quot x y- | y == 0 = divZeroError- | y == (-1) && x == minBound = overflowError- | otherwise = x `primQuot` y--which gives us:-- case y of- 0 -> divZeroError- -1 ->- case x of- -9223372036854775808 -> overflowError- _ -> x `primQuot` y- _ -> x `primQuot` y--for which our call (x `quot` 2) expands to:-- case 2 of- 0 -> divZeroError- -1 ->- case x of- -9223372036854775808 -> overflowError- _ -> x `primQuot` 2- _ -> x `primQuot` 2--which simplifies to:-- x `primQuot` 2--as required.----But we now have the same problem with a constant numerator: the call-(2 `quot` y) expands to-- case y of- 0 -> divZeroError- -1 ->- case 2 of- -9223372036854775808 -> overflowError- _ -> 2 `primQuot` y- _ -> 2 `primQuot` y--which simplifies to:-- case y of- 0 -> divZeroError- -1 -> 2 `primQuot` y- _ -> 2 `primQuot` y--which simplifies to:-- case y of- 0 -> divZeroError- -1 -> -2- _ -> 2 `primQuot` y---However, constant denominators are more common than constant numerators,-so the- y == (-1) && x == minBound-order gives us better code in the common case.--}
@@ -1,812 +0,0 @@-\begin{code}--{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.List--- Copyright : (c) The University of Glasgow 1994-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The List data type and its operations------------------------------------------------------------------------------------- #hide-module GHC.List (- -- [] (..), -- Not Haskell 98; built in syntax-- map, (++), filter, concat,- head, last, tail, init, null, length, (!!),- foldl, scanl, scanl1, foldr, foldr1, scanr, scanr1,- iterate, repeat, replicate, cycle,- take, drop, splitAt, takeWhile, dropWhile, span, break,- reverse, and, or,- any, all, elem, notElem, lookup,- concatMap,- zip, zip3, zipWith, zipWith3, unzip, unzip3,- errorEmptyList,--#ifndef USE_REPORT_PRELUDE- -- non-standard, but hidden when creating the Prelude- -- export list.- takeUInt_append-#endif-- ) where--import Data.Maybe-import GHC.Base-import GHC.Num-import Language.Haskell.Liquid.Prelude (liquidAssert, liquidError)--infixl 9 !!-infix 4 `elem`, `notElem`-----\end{code}--%*********************************************************-%* *-\subsection{List-manipulation functions}-%* *-%*********************************************************--\begin{code}--- | Extract the first element of a list, which must be non-empty.-{-@ assert head :: xs:{v: [a] | len(v) > 0} -> a @-}-head :: [a] -> a-head (x:_) = x-head [] = errorEmptyList "head"--badHead :: a-badHead = error "errorEmptyList head" -- errorEmptyList "head"---- This rule is useful in cases like --- head [y | (x,y) <- ps, x==t]-{- RULES-"head/build" forall (g::forall b.(a->b->b)->b->b) .- head (build g) = g (\x _ -> x) badHead-"head/augment" forall xs (g::forall b. (a->b->b) -> b -> b) . - head (augment g xs) = g (\x _ -> x) (head xs)- -}---- | Extract the elements after the head of a list, which must be non-empty.-{-@ assert tail :: xs:{v: [a] | len(v) > 0} -> {v: [a] | len(v) = (len(xs) - 1)} @-}-tail :: [a] -> [a]-tail (_:xs) = xs-tail [] = liquidError "tail" -- errorEmptyList "tail"---- | Extract the last element of a list, which must be finite and non-empty.-{-@ assert last :: xs:{v: [a] | len(v) > 0} -> a @-}-last :: [a] -> a-#ifdef USE_REPORT_PRELUDE-last [x] = x-last (_:xs) = last xs-last [] = liquidError "last" -- errorEmptyList "last"-#else--- eliminate repeated cases-last [] = liquidError "last" -- errorEmptyList "last"-last (x:xs) = last' x xs- where last' y [] = y- last' _ (y:ys) = last' y ys-#endif---- | Return all the elements of a list except the last one.--- The list must be non-empty.-{-@ assert init :: xs:{v: [a] | len(v) > 0} -> {v: [a] | len(v) = len(xs) - 1} @-}-init :: [a] -> [a]-#ifdef USE_REPORT_PRELUDE-init [x] = []-init (x:xs) = x : init xs-init [] = liquidError "init" -- errorEmptyList "init"-#else--- eliminate repeated cases-init [] = liquidError "init" --errorEmptyList "init"-init (x:xs) = init' x xs- where init' _ [] = []- init' y (z:zs) = y : init' z zs-#endif---- | Test whether a list is empty.-{-@ assert null :: xs:[a] -> {v: Bool | (Prop(v) <=> len(xs) = 0) } @-}-null :: [a] -> Bool-null [] = True-null (_:_) = False---- | /O(n)/. 'length' returns the length of a finite list as an 'Int'.--- It is an instance of the more general 'Data.List.genericLength',--- the result type of which may be any kind of number.-{-@ assert length :: xs:[a] -> {v: GHC.Types.Int | v = len(xs)} @-}-length :: [a] -> Int-length l = len l 0#- where- --LIQUID FIXME: leaving the type signature causes this to compile to very strange core- --LIQUID len :: [a] -> Int# -> Int- len [] a# = I# a#- len (_:xs) a# = len xs (a# +# 1#)---- | 'filter', applied to a predicate and a list, returns the list of--- those elements that satisfy the predicate; i.e.,------ > filter p xs = [ x | x <- xs, p x]--{-@ assert filter :: (a -> GHC.Types.Bool) -> xs:[a] -> {v: [a] | len(v) <= len(xs)} @-}-filter :: (a -> Bool) -> [a] -> [a]-filter _pred [] = []-filter pred (x:xs)- | pred x = x : filter pred xs- | otherwise = filter pred xs--{-# NOINLINE [0] filterFB #-}-filterFB :: (a -> b -> b) -> (a -> Bool) -> a -> b -> b-filterFB c p x r | p x = x `c` r- | otherwise = r--{- RULES-"filter" [~1] forall p xs. filter p xs = build (\c n -> foldr (filterFB c p) n xs)-"filterList" [1] forall p. foldr (filterFB (:) p) [] = filter p-"filterFB" forall c p q. filterFB (filterFB c p) q = filterFB c (\x -> q x && p x)- -}---- Note the filterFB rule, which has p and q the "wrong way round" in the RHS.--- filterFB (filterFB c p) q a b--- = if q a then filterFB c p a b else b--- = if q a then (if p a then c a b else b) else b--- = if q a && p a then c a b else b--- = filterFB c (\x -> q x && p x) a b--- I originally wrote (\x -> p x && q x), which is wrong, and actually--- gave rise to a live bug report. SLPJ.----- | 'foldl', applied to a binary operator, a starting value (typically--- the left-identity of the operator), and a list, reduces the list--- using the binary operator, from left to right:------ > foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn------ The list must be finite.---- We write foldl as a non-recursive thing, so that it--- can be inlined, and then (often) strictness-analysed,--- and hence the classic space leak on foldl (+) 0 xs--foldl :: (a -> b -> a) -> a -> [b] -> a-foldl f z0 xs0 = lgo z0 xs0- where- lgo z [] = z- lgo z (x:xs) = lgo (f z x) xs---- | 'scanl' is similar to 'foldl', but returns a list of successive--- reduced values from the left:------ > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]------ Note that------ > last (scanl f z xs) == foldl f z xs.-{-@ assert scanl :: (a -> b -> a) -> a -> xs:[b] -> {v: [a] | len(v) = 1 + len(xs) } @-}-scanl :: (a -> b -> a) -> a -> [b] -> [a]-scanl f q ls = q : (case ls of- [] -> []- x:xs -> scanl f (f q x) xs)---- | 'scanl1' is a variant of 'scanl' that has no starting value argument:------ > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]--{-@ assert scanl1 :: (a -> a -> a) -> xs:{v: [a] | len(v) > 0} -> {v: [a] | len(v) = len(xs) } @-}-scanl1 :: (a -> a -> a) -> [a] -> [a]-scanl1 f (x:xs) = scanl f x xs-scanl1 _ [] = []---- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the--- above functions.---- | 'foldr1' is a variant of 'foldr' that has no starting value argument,--- and thus must be applied to non-empty lists.--{-@ assert foldr1 :: (a -> a -> a) -> xs:{v: [a] | len(v) > 0} -> a @-}-foldr1 :: (a -> a -> a) -> [a] -> a-foldr1 _ [x] = x-foldr1 f (x:xs@(_:_)) = f x (foldr1 f xs)-foldr1 _ [] = liquidError "foldr1" -- errorEmptyList "foldr1"---- | 'scanr' is the right-to-left dual of 'scanl'.--- Note that------ > head (scanr f z xs) == foldr f z xs.--{-@ assert scanr :: (a -> b -> b) -> b -> xs:[a] -> {v: [b] | len(v) = 1 + len(xs) } @-}-scanr :: (a -> b -> b) -> b -> [a] -> [b]-scanr _ q0 [] = [q0]-scanr f q0 (x:xs) = f x q : qs- where qs@(q:_) = scanr f q0 xs ---- | 'scanr1' is a variant of 'scanr' that has no starting value argument.--{-@ assert scanr1 :: (a -> a -> a) -> xs:{v: [a] | len(v) > 0} -> {v: [a] | len(v) = len(xs) } @-}-scanr1 :: (a -> a -> a) -> [a] -> [a]-scanr1 _ [] = []-scanr1 _ [x] = [x]-scanr1 f (x:xs@(_:_)) = f x q : qs- where qs@(q:_) = scanr1 f xs ---- | 'iterate' @f x@ returns an infinite list of repeated applications--- of @f@ to @x@:------ > iterate f x == [x, f x, f (f x), ...]--{-@ lazy GHC.List.iterate @-}-{-@ iterate :: (a -> a) -> a -> [a] @-}-iterate :: (a -> a) -> a -> [a]-iterate f x = x : iterate f (f x)--{-@ lazy GHC.List.iterateFB @-}-{-@ iterateFB :: (a -> b -> b) -> (a -> a) -> a -> b @-}-iterateFB :: (a -> b -> b) -> (a -> a) -> a -> b-iterateFB c f x = x `c` iterateFB c f (f x)---{- RULES-"iterate" [~1] forall f x. iterate f x = build (\c _n -> iterateFB c f x)-"iterateFB" [1] iterateFB (:) = iterate- -}----- | 'repeat' @x@ is an infinite list, with @x@ the value of every element.-{- measure inf :: Int @-}-{- invariant {v:Int | v < inf} @-}-{- repeat :: a -> {v:[a] | (len v) = inf} @-}-{-@ repeat :: a -> [a] @-}-{-@ lazy GHC.List.repeat @-}-repeat :: a -> [a]-{-# INLINE [0] repeat #-}--- The pragma just gives the rules more chance to fire-repeat x = xs where xs = x : xs--{-# INLINE [0] repeatFB #-} -- ditto-{-@ lazy GHC.List.repeatFB @-}-{-@ repeatFB :: (a -> b -> b) -> a -> b @-}-repeatFB :: (a -> b -> b) -> a -> b-repeatFB c x = xs where xs = x `c` xs---{- RULES-"repeat" [~1] forall x. repeat x = build (\c _n -> repeatFB c x)-"repeatFB" [1] repeatFB (:) = repeat- -}---- | 'replicate' @n x@ is a list of length @n@ with @x@ the value of--- every element.--- It is an instance of the more general 'Data.List.genericReplicate',--- in which @n@ may be of any integral type.-{-# INLINE replicate #-}-{-@ assert replicate :: n:Nat -> x:a -> {v: [{v:a | v = x}] | len(v) = n} @-}-replicate :: Int -> a -> [a]---LIQUID replicate n x = take n (repeat x)-replicate 0 _ = []-replicate n x = x : replicate (n-1) x---- | 'cycle' ties a finite list into a circular one, or equivalently,--- the infinite repetition of the original list. It is the identity--- on infinite lists.--{-@ assert cycle :: {v: [a] | len(v) > 0 } -> [a] @-}-{-@ lazy cycle @-}-cycle :: [a] -> [a]-cycle [] = liquidError {- error -} "Prelude.cycle: empty list"-cycle xs = xs' where xs' = xs ++ xs'---- | 'takeWhile', applied to a predicate @p@ and a list @xs@, returns the--- longest prefix (possibly empty) of @xs@ of elements that satisfy @p@:------ > takeWhile (< 3) [1,2,3,4,1,2,3,4] == [1,2]--- > takeWhile (< 9) [1,2,3] == [1,2,3]--- > takeWhile (< 0) [1,2,3] == []-----{-@ assert takeWhile :: (a -> Bool) -> xs:[a] -> {v: [a] | len(v) <= len(xs)} @-}-takeWhile :: (a -> Bool) -> [a] -> [a]-takeWhile _ [] = []-takeWhile p (x:xs) - | p x = x : takeWhile p xs- | otherwise = []---- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@:------ > dropWhile (< 3) [1,2,3,4,5,1,2,3] == [3,4,5,1,2,3]--- > dropWhile (< 9) [1,2,3] == []--- > dropWhile (< 0) [1,2,3] == [1,2,3]-----{-@ assert dropWhile :: (a -> Bool) -> xs:[a] -> {v: [a] | len(v) <= len(xs)} @-}-dropWhile :: (a -> Bool) -> [a] -> [a]-dropWhile _ [] = []-dropWhile p xs@(x:xs')- | p x = dropWhile p xs'- | otherwise = xs---- | 'take' @n@, applied to a list @xs@, returns the prefix of @xs@--- of length @n@, or @xs@ itself if @n > 'length' xs@:------ > take 5 "Hello World!" == "Hello"--- > take 3 [1,2,3,4,5] == [1,2,3]--- > take 3 [1,2] == [1,2]--- > take 3 [] == []--- > take (-1) [1,2] == []--- > take 0 [1,2] == []------ It is an instance of the more general 'Data.List.genericTake',--- in which @n@ may be of any integral type.---{-@ take :: n:Int- -> xs:[a] - -> {v:[a] | (if (n >=0) then ((len v) = ((len(xs) < n) ? len(xs):n)) else ((len v) = 0))} - @-}-take :: Int -> [a] -> [a]---- | 'drop' @n xs@ returns the suffix of @xs@--- after the first @n@ elements, or @[]@ if @n > 'length' xs@:------ > drop 6 "Hello World!" == "World!"--- > drop 3 [1,2,3,4,5] == [4,5]--- > drop 3 [1,2] == []--- > drop 3 [] == []--- > drop (-1) [1,2] == [1,2]--- > drop 0 [1,2] == [1,2]------ It is an instance of the more general 'Data.List.genericDrop',--- in which @n@ may be of any integral type.-{-@ drop :: n: Int - -> xs:[a] - -> {v:[a] | (if (n >= 0) then (len(v) = ((len(xs) < n) ? 0 : len(xs) - n)) else ((len v) = (len xs)))} @-}-drop :: Int -> [a] -> [a]---- | 'splitAt' @n xs@ returns a tuple where first element is @xs@ prefix of--- length @n@ and second element is the remainder of the list:------ > splitAt 6 "Hello World!" == ("Hello ","World!")--- > splitAt 3 [1,2,3,4,5] == ([1,2,3],[4,5])--- > splitAt 1 [1,2,3] == ([1],[2,3])--- > splitAt 3 [1,2,3] == ([1,2,3],[])--- > splitAt 4 [1,2,3] == ([1,2,3],[])--- > splitAt 0 [1,2,3] == ([],[1,2,3])--- > splitAt (-1) [1,2,3] == ([],[1,2,3])------ It is equivalent to @('take' n xs, 'drop' n xs)@ when @n@ is not @_|_@--- (@splitAt _|_ xs = _|_@).--- 'splitAt' is an instance of the more general 'Data.List.genericSplitAt',--- in which @n@ may be of any integral type.--- Liquid: TODO-{-@ splitAt :: n:Int -> x:[a] -> ({v:[a] | (if (n >= 0) then (Min (len v) (len x) n) else ((len v) = 0))},[a])<{\x1 x2 -> (len x2) = (len x) - (len x1)}> @-}-splitAt :: Int -> [a] -> ([a],[a])--#ifdef USE_REPORT_PRELUDE-take n _ | n <= 0 = []-take _ [] = []-take n (x:xs) = x : take (n-1) xs--drop n xs | n <= 0 = xs-drop _ [] = []-drop n (_:xs) = drop (n-1) xs--splitAt n xs = (take n xs, drop n xs)--#else /* hack away */-{- RULES-"take" [~1] forall n xs . take n xs = takeFoldr n xs -"takeList" [1] forall n xs . foldr (takeFB (:) []) (takeConst []) xs n = takeUInt n xs- -}--{-# INLINE takeFoldr #-}-takeFoldr :: Int -> [a] -> [a]-takeFoldr (I# n#) xs- = build (\c nil -> if n# <=# 0# then nil else- foldr (takeFB c nil) (takeConst nil) xs n#)--{-# NOINLINE [0] takeConst #-}--- just a version of const that doesn't get inlined too early, so we--- can spot it in rules. Also we need a type sig due to the unboxed Int#.-takeConst :: a -> Int# -> a-takeConst x _ = x--{-# NOINLINE [0] takeFB #-}-takeFB :: (a -> b -> b) -> b -> a -> (Int# -> b) -> Int# -> b-takeFB c n x xs m | m <=# 1# = x `c` n- | otherwise = x `c` xs (m -# 1#)--{-- INLINE [0] take #-}-take (I# n#) xs = takeUInt n# xs---- The general code for take, below, checks n <= maxInt--- No need to check for maxInt overflow when specialised--- at type Int or Int# since the Int must be <= maxInt--takeUInt :: Int# -> [b] -> [b]-takeUInt n xs- | n >=# 0# = take_unsafe_UInt n xs- | otherwise = []--take_unsafe_UInt :: Int# -> [b] -> [b]-take_unsafe_UInt 0# _ = []-take_unsafe_UInt m ls =- case ls of- [] -> []- (x:xs) -> x : take_unsafe_UInt (m -# 1#) xs--takeUInt_append :: Int# -> [b] -> [b] -> [b]-takeUInt_append n xs rs- | n >=# 0# = take_unsafe_UInt_append n xs rs- | otherwise = []--take_unsafe_UInt_append :: Int# -> [b] -> [b] -> [b]-take_unsafe_UInt_append 0# _ rs = rs-take_unsafe_UInt_append m ls rs =- case ls of- [] -> rs- (x:xs) -> x : take_unsafe_UInt_append (m -# 1#) xs rs--drop (I# n#) ls- | n# <# 0# = ls- | otherwise = drop# n# ls- where- drop# :: Int# -> [a] -> [a]- drop# 0# xs = xs- drop# _ xs@[] = xs- drop# m# (_:xs) = drop# (m# -# 1#) xs--splitAt (I# n#) ls- | n# <# 0# = ([], ls)- | otherwise = splitAt# n# ls- where- splitAt# :: Int# -> [a] -> ([a], [a])- splitAt# 0# xs = ([], xs)- splitAt# _ xs@[] = (xs, xs)- splitAt# m# (x:xs) = (x:xs', xs'')- where- (xs', xs'') = splitAt# (m# -# 1#) xs--#endif /* USE_REPORT_PRELUDE */---- | 'span', applied to a predicate @p@ and a list @xs@, returns a tuple where--- first element is longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@ and second element is the remainder of the list:--- --- > span (< 3) [1,2,3,4,1,2,3,4] == ([1,2],[3,4,1,2,3,4])--- > span (< 9) [1,2,3] == ([1,2,3],[])--- > span (< 0) [1,2,3] == ([],[1,2,3])--- --- 'span' @p xs@ is equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@--- Liquid: TODO-{-@-span :: (a -> Bool) - -> xs:[a] - -> ({v:[a]|((len v)<=(len xs))}, {v:[a]|((len v)<=(len xs))})-@-}-span :: (a -> Bool) -> [a] -> ([a], [a])-span _ xs@[] = (xs, xs)-span p xs@(x:xs')- | p x = let (ys,zs) = span p xs' in (x:ys,zs)- | otherwise = ([],xs)---- | 'break', applied to a predicate @p@ and a list @xs@, returns a tuple where--- first element is longest prefix (possibly empty) of @xs@ of elements that--- /do not satisfy/ @p@ and second element is the remainder of the list:--- --- > break (> 3) [1,2,3,4,1,2,3,4] == ([1,2,3],[4,1,2,3,4])--- > break (< 9) [1,2,3] == ([],[1,2,3])--- > break (> 9) [1,2,3] == ([1,2,3],[])------ 'break' @p@ is equivalent to @'span' ('not' . p)@.--- liquid:TODO-{-@ break :: (a -> Bool) -> xs:[a] -> ([a],[a])<{\x y -> (len xs) = (len x) + (len y)}> @-}-break :: (a -> Bool) -> [a] -> ([a],[a])-#ifdef USE_REPORT_PRELUDE-break p = span (not . p)-#else--- HBC version (stolen)-break _ xs@[] = (xs, xs)-break p xs@(x:xs')- | p x = ([],xs)- | otherwise = let (ys,zs) = break p xs' in (x:ys,zs)-#endif---- | 'reverse' @xs@ returns the elements of @xs@ in reverse order.--- @xs@ must be finite.-{-@ assert reverse :: xs:[a] -> {v: [a] | len(v) = len(xs)} @-}-{-@ include <len.hquals> @-}-reverse :: [a] -> [a]-#ifdef USE_REPORT_PRELUDE-reverse = foldl (flip (:)) []-#else-reverse l = rev l []- where- rev [] a = a- rev (x:xs) a = rev xs (x:a)-#endif---- | 'and' returns the conjunction of a Boolean list. For the result to be--- 'True', the list must be finite; 'False', however, results from a 'False'--- value at a finite index of a finite or infinite list.-and :: [Bool] -> Bool---- | 'or' returns the disjunction of a Boolean list. For the result to be--- 'False', the list must be finite; 'True', however, results from a 'True'--- value at a finite index of a finite or infinite list.-or :: [Bool] -> Bool-#ifdef USE_REPORT_PRELUDE-and = foldr (&&) True-or = foldr (||) False-#else-and [] = True-and (x:xs) = x && and xs-or [] = False-or (x:xs) = x || or xs--{- RULES-"and/build" forall (g::forall b.(Bool->b->b)->b->b) . - and (build g) = g (&&) True-"or/build" forall (g::forall b.(Bool->b->b)->b->b) . - or (build g) = g (||) False- -}-#endif---- | Applied to a predicate and a list, 'any' determines if any element--- of the list satisfies the predicate. For the result to be--- 'False', the list must be finite; 'True', however, results from a 'True'--- value for the predicate applied to an element at a finite index of a finite or infinite list.-any :: (a -> Bool) -> [a] -> Bool---- | Applied to a predicate and a list, 'all' determines if all elements--- of the list satisfy the predicate. For the result to be--- 'True', the list must be finite; 'False', however, results from a 'False'--- value for the predicate applied to an element at a finite index of a finite or infinite list.-all :: (a -> Bool) -> [a] -> Bool-#ifdef USE_REPORT_PRELUDE-any p = or . map p-all p = and . map p-#else-any _ [] = False-any p (x:xs) = p x || any p xs--all _ [] = True-all p (x:xs) = p x && all p xs-{- RULES-"any/build" forall p (g::forall b.(a->b->b)->b->b) . - any p (build g) = g ((||) . p) False-"all/build" forall p (g::forall b.(a->b->b)->b->b) . - all p (build g) = g ((&&) . p) True- -}-#endif---- | 'elem' is the list membership predicate, usually written in infix form,--- e.g., @x \`elem\` xs@. For the result to be--- 'False', the list must be finite; 'True', however, results from an element equal to @x@ found at a finite index of a finite or infinite list.-elem :: (Eq a) => a -> [a] -> Bool---- | 'notElem' is the negation of 'elem'.-notElem :: (Eq a) => a -> [a] -> Bool-#ifdef USE_REPORT_PRELUDE-elem x = any (== x)-notElem x = all (/= x)-#else-elem _ [] = False-elem x (y:ys) = x==y || elem x ys--notElem _ [] = True-notElem x (y:ys)= x /= y && notElem x ys-#endif---- | 'lookup' @key assocs@ looks up a key in an association list.-lookup :: (Eq a) => a -> [(a,b)] -> Maybe b-lookup _key [] = Nothing-lookup key ((x,y):xys)- | key == x = Just y- | otherwise = lookup key xys---- | Map a function over a list and concatenate the results.-concatMap :: (a -> [b]) -> [a] -> [b]-concatMap f = foldr ((++) . f) []---- | Concatenate a list of lists.-concat :: [[a]] -> [a]-concat = foldr (++) []--{- RULES- "concat" forall xs. concat xs = build (\c n -> foldr (\x y -> foldr c y x) n xs)--- We don't bother to turn non-fusible applications of concat back into concat- -}--\end{code}---\begin{code}--- | List index (subscript) operator, starting from 0.--- It is an instance of the more general 'Data.List.genericIndex',--- which takes an index of any integral type.--{-@ assert GHC.List.!! :: xs:[a] -> {v: Int | ((0 <= v) && (v < len(xs)))} -> a @-}-(!!) :: [a] -> Int -> a-#ifdef USE_REPORT_PRELUDE-xs !! n | n < 0 = liquidError {- error -} "Prelude.!!: negative index"-[] !! _ = liquidError {- error -} "Prelude.!!: index too large"-(x:_) !! 0 = x-(_:xs) !! n = xs !! (n-1)-#else--- HBC version (stolen), then unboxified--- The semantics is not quite the same for error conditions--- in the more efficient version.----xs !! (I# n0) | n0 <# 0# = liquidError {- error -} "Prelude.(!!): negative index\n"- | otherwise = sub xs n0- where- sub :: [a] -> Int# -> a- sub [] _ = liquidError {- error -} "Prelude.(!!): index too large\n"- sub (y:ys) n = if n ==# 0#- then y- else sub ys (n -# 1#)-#endif-\end{code}---%*********************************************************-%* *-\subsection{The zip family}-%* *-%*********************************************************--\begin{code}-foldr2 :: (a -> b -> c -> c) -> c -> [a] -> [b] -> c-foldr2 _k z [] _ys = z-foldr2 _k z _xs [] = z-foldr2 k z (x:xs) (y:ys) = k x y (foldr2 k z xs ys)--foldr2_left :: (a -> b -> c -> d) -> d -> a -> ([b] -> c) -> [b] -> d-foldr2_left _k z _x _r [] = z-foldr2_left k _z x r (y:ys) = k x y (r ys)--foldr2_right :: (a -> b -> c -> d) -> d -> b -> ([a] -> c) -> [a] -> d-foldr2_right _k z _y _r [] = z-foldr2_right k _z y r (x:xs) = k x y (r xs)---- foldr2 k z xs ys = foldr (foldr2_left k z) (\_ -> z) xs ys--- foldr2 k z xs ys = foldr (foldr2_right k z) (\_ -> z) ys xs-{- RULES-"foldr2/left" forall k z ys (g::forall b.(a->b->b)->b->b) . - foldr2 k z (build g) ys = g (foldr2_left k z) (\_ -> z) ys--"foldr2/right" forall k z xs (g::forall b.(a->b->b)->b->b) . - foldr2 k z xs (build g) = g (foldr2_right k z) (\_ -> z) xs- -}-\end{code}--The foldr2/right rule isn't exactly right, because it changes-the strictness of foldr2 (and thereby zip)--E.g. main = print (null (zip nonobviousNil (build undefined)))- where nonobviousNil = f 3- f n = if n == 0 then [] else f (n-1)--I'm going to leave it though.---Zips for larger tuples are in the List module.--\begin{code}-------------------------------------------------- | 'zip' takes two lists and returns a list of corresponding pairs.--- If one input list is short, excess elements of the longer list are--- discarded.--{-@ zip :: xs : [a] -> ys:[b] - -> {v : [(a, b)] | ((((len v) <= (len xs)) && ((len v) <= (len ys)))- && (((len xs) = (len ys)) => ((len v) = (len xs))) )} @-}--zip :: [a] -> [b] -> [(a,b)]-zip (a:as) (b:bs) = (a,b) : zip as bs-zip _ _ = []--{-# INLINE [0] zipFB #-}-zipFB :: ((a, b) -> c -> d) -> a -> b -> c -> d-zipFB c = \x y r -> (x,y) `c` r--{- RULES-"zip" [~1] forall xs ys. zip xs ys = build (\c n -> foldr2 (zipFB c) n xs ys)-"zipList" [1] foldr2 (zipFB (:)) [] = zip- -}-\end{code}--\begin{code}-------------------------------------------------- | 'zip3' takes three lists and returns a list of triples, analogous to--- 'zip'.-zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]--- Specification--- zip3 = zipWith3 (,,)-zip3 (a:as) (b:bs) (c:cs) = (a,b,c) : zip3 as bs cs-zip3 _ _ _ = []-\end{code}----- The zipWith family generalises the zip family by zipping with the--- function given as the first argument, instead of a tupling function.--\begin{code}-------------------------------------------------- | 'zipWith' generalises 'zip' by zipping with the function given--- as the first argument, instead of a tupling function.--- For example, @'zipWith' (+)@ is applied to two lists to produce the--- list of corresponding sums.---{-@ zipWith :: (a -> b -> c) - -> xs : [a] -> ys:[b] - -> {v : [c] | (((len v) <= (len xs)) && ((len v) <= (len ys)))} @-}-zipWith :: (a->b->c) -> [a]->[b]->[c]-zipWith f (a:as) (b:bs) = f a b : zipWith f as bs-zipWith _ _ _ = []---- zipWithFB must have arity 2 since it gets two arguments in the "zipWith"--- rule; it might not get inlined otherwise-{-# INLINE [0] zipWithFB #-}-zipWithFB :: (a -> b -> c) -> (d -> e -> a) -> d -> e -> b -> c-zipWithFB c f = \x y r -> (x `f` y) `c` r--{- RULES-"zipWith" [~1] forall f xs ys. zipWith f xs ys = build (\c n -> foldr2 (zipWithFB c f) n xs ys)-"zipWithList" [1] forall f. foldr2 (zipWithFB (:) f) [] = zipWith f- -}-\end{code}--\begin{code}--- | The 'zipWith3' function takes a function which combines three--- elements, as well as three lists and returns a list of their point-wise--- combination, analogous to 'zipWith'.-zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]-zipWith3 z (a:as) (b:bs) (c:cs)- = z a b c : zipWith3 z as bs cs-zipWith3 _ _ _ _ = []---- | 'unzip' transforms a list of pairs into a list of first components--- and a list of second components.-unzip :: [(a,b)] -> ([a],[b])-{-# INLINE unzip #-}-unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])---- | The 'unzip3' function takes a list of triples and returns three--- lists, analogous to 'unzip'.-unzip3 :: [(a,b,c)] -> ([a],[b],[c])-{-# INLINE unzip3 #-}-unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))- ([],[],[])-\end{code}---%*********************************************************-%* *-\subsection{Error code}-%* *-%*********************************************************--Common up near identical calls to `error' to reduce the number-constant strings created when compiled:--\begin{code}-{-@ assert errorEmptyList :: {v: String | (0 = 1)} -> a @-}-errorEmptyList :: String -> a-errorEmptyList fun =- liquidError {- error -} (prel_list_str ++ fun ++ ": empty list")--prel_list_str :: String-prel_list_str = "Prelude."-\end{code}
@@ -1,145 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.MVar--- Copyright : (c) The University of Glasgow 2008--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The MVar type-----------------------------------------------------------------------------------module GHC.MVar (- -- * MVars- MVar(..)- , newMVar -- :: a -> IO (MVar a)- , newEmptyMVar -- :: IO (MVar a)- , takeMVar -- :: MVar a -> IO a- , putMVar -- :: MVar a -> a -> IO ()- , tryTakeMVar -- :: MVar a -> IO (Maybe a)- , tryPutMVar -- :: MVar a -> a -> IO Bool- , isEmptyMVar -- :: MVar a -> IO Bool- , addMVarFinalizer -- :: MVar a -> IO () -> IO ()- ) where--import GHC.Base-import GHC.IO () -- instance Monad IO-import Data.Maybe--data MVar a = MVar (MVar# RealWorld a)-{- ^-An 'MVar' (pronounced \"em-var\") is a synchronising variable, used-for communication between concurrent threads. It can be thought of-as a a box, which may be empty or full.--}---- pull in Eq (Mvar a) too, to avoid GHC.Conc being an orphan-instance module-instance Eq (MVar a) where- (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#--{--M-Vars are rendezvous points for concurrent threads. They begin-empty, and any attempt to read an empty M-Var blocks. When an M-Var-is written, a single blocked thread may be freed. Reading an M-Var-toggles its state from full back to empty. Therefore, any value-written to an M-Var may only be read once. Multiple reads and writes-are allowed, but there must be at least one read between any two-writes.--}----Defined in IOBase to avoid cycle: data MVar a = MVar (SynchVar# RealWorld a)---- |Create an 'MVar' which is initially empty.-newEmptyMVar :: IO (MVar a)-newEmptyMVar = IO $ \ s# ->- case newMVar# s# of- (# s2#, svar# #) -> (# s2#, MVar svar# #)---- |Create an 'MVar' which contains the supplied value.-newMVar :: a -> IO (MVar a)-newMVar value =- newEmptyMVar >>= \ mvar ->- putMVar mvar value >>- return mvar---- |Return the contents of the 'MVar'. If the 'MVar' is currently--- empty, 'takeMVar' will wait until it is full. After a 'takeMVar',--- the 'MVar' is left empty.------ There are two further important properties of 'takeMVar':------ * 'takeMVar' is single-wakeup. That is, if there are multiple--- threads blocked in 'takeMVar', and the 'MVar' becomes full,--- only one thread will be woken up. The runtime guarantees that--- the woken thread completes its 'takeMVar' operation.------ * When multiple threads are blocked on an 'MVar', they are--- woken up in FIFO order. This is useful for providing--- fairness properties of abstractions built using 'MVar's.----takeMVar :: MVar a -> IO a-takeMVar (MVar mvar#) = IO $ \ s# -> takeMVar# mvar# s#---- |Put a value into an 'MVar'. If the 'MVar' is currently full,--- 'putMVar' will wait until it becomes empty.------ There are two further important properties of 'putMVar':------ * 'putMVar' is single-wakeup. That is, if there are multiple--- threads blocked in 'putMVar', and the 'MVar' becomes empty,--- only one thread will be woken up. The runtime guarantees that--- the woken thread completes its 'putMVar' operation.------ * When multiple threads are blocked on an 'MVar', they are--- woken up in FIFO order. This is useful for providing--- fairness properties of abstractions built using 'MVar's.----putMVar :: MVar a -> a -> IO ()-putMVar (MVar mvar#) x = IO $ \ s# ->- case putMVar# mvar# x s# of- s2# -> (# s2#, () #)---- |A non-blocking version of 'takeMVar'. The 'tryTakeMVar' function--- returns immediately, with 'Nothing' if the 'MVar' was empty, or--- @'Just' a@ if the 'MVar' was full with contents @a@. After 'tryTakeMVar',--- the 'MVar' is left empty.-tryTakeMVar :: MVar a -> IO (Maybe a)-tryTakeMVar (MVar m) = IO $ \ s ->- case tryTakeMVar# m s of- (# s', 0#, _ #) -> (# s', Nothing #) -- MVar is empty- (# s', _, a #) -> (# s', Just a #) -- MVar is full---- |A non-blocking version of 'putMVar'. The 'tryPutMVar' function--- attempts to put the value @a@ into the 'MVar', returning 'True' if--- it was successful, or 'False' otherwise.-tryPutMVar :: MVar a -> a -> IO Bool-tryPutMVar (MVar mvar#) x = IO $ \ s# ->- case tryPutMVar# mvar# x s# of- (# s, 0# #) -> (# s, False #)- (# s, _ #) -> (# s, True #)---- |Check whether a given 'MVar' is empty.------ Notice that the boolean value returned is just a snapshot of--- the state of the MVar. By the time you get to react on its result,--- the MVar may have been filled (or emptied) - so be extremely--- careful when using this operation. Use 'tryTakeMVar' instead if possible.-isEmptyMVar :: MVar a -> IO Bool-isEmptyMVar (MVar mv#) = IO $ \ s# ->- case isEmptyMVar# mv# s# of- (# s2#, flg #) -> (# s2#, not (flg ==# 0#) #)---- |Add a finalizer to an 'MVar' (GHC only). See "Foreign.ForeignPtr" and--- "System.Mem.Weak" for more about finalizers.-addMVarFinalizer :: MVar a -> IO () -> IO ()-addMVarFinalizer (MVar m) finalizer =- IO $ \s -> case mkWeak# m () finalizer s of { (# s1, _ #) -> (# s1, () #) }-
@@ -1,125 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}--------------------------------------------------------------------------------- |--- Module : GHC.Num--- Copyright : (c) The University of Glasgow 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The 'Num' class and the 'Integer' type.------------------------------------------------------------------------------------- #hide-module GHC.Num (module GHC.Num, module GHC.Integer) where--import GHC.Base-import GHC.Integer--infixl 7 *-infixl 6 +, ---default () -- Double isn't available yet,- -- and we shouldn't be using defaults anyway-\end{code}--%*********************************************************-%* *-\subsection{Standard numeric class}-%* *-%*********************************************************--\begin{code}--- | Basic numeric class.------ Minimal complete definition: all except 'negate' or @(-)@-class Num a where- (+), (-), (*) :: a -> a -> a- -- | Unary negation.- negate :: a -> a- -- | Absolute value.- abs :: a -> a- -- | Sign of a number.- -- The functions 'abs' and 'signum' should satisfy the law:- --- -- > abs x * signum x == x- --- -- For real numbers, the 'signum' is either @-1@ (negative), @0@ (zero)- -- or @1@ (positive).- signum :: a -> a- -- | Conversion from an 'Integer'.- -- An integer literal represents the application of the function- -- 'fromInteger' to the appropriate value of type 'Integer',- -- so such literals have type @('Num' a) => a@.- fromInteger :: Integer -> a-- {-# INLINE (-) #-}- {-# INLINE negate #-}- x - y = x + negate y- negate x = 0 - x---- | the same as @'flip' ('-')@.------ Because @-@ is treated specially in the Haskell grammar,--- @(-@ /e/@)@ is not a section, but an application of prefix negation.--- However, @('subtract'@ /exp/@)@ is equivalent to the disallowed section.-{-# INLINE subtract #-}-subtract :: (Num a) => a -> a -> a-subtract x y = y - x-\end{code}---%*********************************************************-%* *-\subsection{Instances for @Int@}-%* *-%*********************************************************--\begin{code}-instance Num Int where- (+) = plusInt- (-) = minusInt- negate = negateInt- (*) = timesInt- abs n = if n `geInt` 0 then n else negateInt n-- signum n | n `ltInt` 0 = negateInt 1- | n `eqInt` 0 = 0- | otherwise = 1-- {-# INLINE fromInteger #-} -- Just to be sure!- fromInteger i = I# (integerToInt i)--quotRemInt :: Int -> Int -> (Int, Int)-quotRemInt a@(I# _) b@(I# _) = (a `quotInt` b, a `remInt` b)- -- OK, so I made it a little stricter. Shoot me. (WDP 94/10)--divModInt :: Int -> Int -> (Int, Int)-divModInt x@(I# _) y@(I# _) = (x `divInt` y, x `modInt` y)- -- Stricter. Sorry if you don't like it. (WDP 94/10)-\end{code}--%*********************************************************-%* *-\subsection{The @Integer@ instances for @Num@}-%* *-%*********************************************************--\begin{code}-instance Num Integer where- (+) = plusInteger- (-) = minusInteger- (*) = timesInteger- negate = negateInteger- fromInteger x = x-- abs = absInteger- signum = signumInteger-\end{code}-
@@ -1,37 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE ParallelArrays, MagicHash #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.PArr--- Copyright : (c) 2001-2011 The Data Parallel Haskell team--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ BIG UGLY HACK: The desugarer special cases this module. Despite the uses of '-XParallelArrays',--- the desugarer does not load 'Data.Array.Parallel' into its global state. (Hence,--- the present module may not use any other piece of '-XParallelArray' syntax.)------ This will be cleaned up when we change the internal represention of '[::]' to not--- rely on a wired-in type constructor.---- #hide-module GHC.PArr where--import GHC.Base---- Representation of parallel arrays------ Vanilla representation of parallel Haskell based on standard GHC arrays that is used if the--- vectorised is /not/ used.------ NB: This definition *must* be kept in sync with `TysWiredIn.parrTyCon'!----data [::] e = PArr !Int (Array# e)--type PArr = [::] -- this synonym is to get access to '[::]' without using the special syntax
@@ -1,104 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Pack--- Copyright : (c) The University of Glasgow 1997-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ This module provides a small set of low-level functions for packing--- and unpacking a chunk of bytes. Used by code emitted by the compiler--- plus the prelude libraries.--- --- The programmer level view of packed strings is provided by a GHC--- system library PackedString.------------------------------------------------------------------------------------- #hide-module GHC.Pack- (- -- (**) - emitted by compiler.-- packCString#, -- :: [Char] -> ByteArray# (**)- unpackCString,- unpackCString#, -- :: Addr# -> [Char] (**)- unpackNBytes#, -- :: Addr# -> Int# -> [Char] (**)- unpackFoldrCString#, -- (**)- unpackAppendCString#, -- (**)- ) - where--import GHC.Base-import GHC.List ( length )-import GHC.ST-import GHC.Ptr--data ByteArray ix = ByteArray ix ix ByteArray#-data MutableByteArray s ix = MutableByteArray ix ix (MutableByteArray# s)--unpackCString :: Ptr a -> [Char]-unpackCString a@(Ptr addr)- | a == nullPtr = []- | otherwise = unpackCString# addr--packCString# :: [Char] -> ByteArray#-packCString# str = case (packString str) of { ByteArray _ _ bytes -> bytes }--packString :: [Char] -> ByteArray Int-packString str = runST (packStringST str)--packStringST :: [Char] -> ST s (ByteArray Int)-packStringST str =- let len = length str in- packNBytesST len str--packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)-packNBytesST (I# length#) str =- {- - allocate an array that will hold the string- (not forgetting the NUL byte at the end)- -}- new_ps_array (length# +# 1#) >>= \ ch_array ->- -- fill in packed string from "str"- fill_in ch_array 0# str >>- -- freeze the puppy:- freeze_ps_array ch_array length#- where- fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()- fill_in arr_in# idx [] =- write_ps_array arr_in# idx (chr# 0#) >>- return ()-- fill_in arr_in# idx (C# c : cs) =- write_ps_array arr_in# idx c >>- fill_in arr_in# (idx +# 1#) cs---- (Very :-) ``Specialised'' versions of some CharArray things...--new_ps_array :: Int# -> ST s (MutableByteArray s Int)-write_ps_array :: MutableByteArray s Int -> Int# -> Char# -> ST s () -freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)--new_ps_array size = ST $ \ s ->- case (newByteArray# size s) of { (# s2#, barr# #) ->- (# s2#, MutableByteArray bot bot barr# #) }- where- bot = error "new_ps_array"--write_ps_array (MutableByteArray _ _ barr#) n ch = ST $ \ s# ->- case writeCharArray# barr# n ch s# of { s2# ->- (# s2#, () #) }---- same as unsafeFreezeByteArray-freeze_ps_array (MutableByteArray _ _ arr#) len# = ST $ \ s# ->- case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) ->- (# s2#, ByteArray 0 (I# len#) frozen# #) }-\end{code}
@@ -1,168 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Ptr--- Copyright : (c) The FFI Task Force, 2000-2002--- License : see libraries/base/LICENSE--- --- Maintainer : ffi@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The 'Ptr' and 'FunPtr' types and operations.------------------------------------------------------------------------------------- #hide-module GHC.Ptr (- Ptr(..), FunPtr(..),- nullPtr, castPtr, plusPtr, alignPtr, minusPtr,- nullFunPtr, castFunPtr,-- -- * Unsafe functions- castFunPtrToPtr, castPtrToFunPtr- ) where--import GHC.Base-import GHC.Show-import GHC.Num-import GHC.List ( length, replicate )-import Numeric ( showHex )--#include "MachDeps.h"----------------------------------------------------------------------------- Data pointers.--data Ptr a = Ptr Addr# deriving (Eq, Ord)--- ^ A value of type @'Ptr' a@ represents a pointer to an object, or an--- array of objects, which may be marshalled to or from Haskell values--- of type @a@.------ The type @a@ will often be an instance of class--- 'Foreign.Storable.Storable' which provides the marshalling operations.--- However this is not essential, and you can provide your own operations--- to access the pointer. For example you might write small foreign--- functions to get or set the fields of a C @struct@.---- |The constant 'nullPtr' contains a distinguished value of 'Ptr'--- that is not associated with a valid memory location.-nullPtr :: Ptr a-nullPtr = Ptr nullAddr#---- |The 'castPtr' function casts a pointer from one type to another.-castPtr :: Ptr a -> Ptr b-castPtr (Ptr addr) = Ptr addr---- |Advances the given address by the given offset in bytes.-plusPtr :: Ptr a -> Int -> Ptr b-plusPtr (Ptr addr) (I# d) = Ptr (plusAddr# addr d)---- |Given an arbitrary address and an alignment constraint,--- 'alignPtr' yields the next higher address that fulfills the--- alignment constraint. An alignment constraint @x@ is fulfilled by--- any address divisible by @x@. This operation is idempotent.-alignPtr :: Ptr a -> Int -> Ptr a-alignPtr addr@(Ptr a) (I# i)- = case remAddr# a i of {- 0# -> addr;- n -> Ptr (plusAddr# a (i -# n)) }---- |Computes the offset required to get from the second to the first--- argument. We have ------ > p2 == p1 `plusPtr` (p2 `minusPtr` p1)-minusPtr :: Ptr a -> Ptr b -> Int-minusPtr (Ptr a1) (Ptr a2) = I# (minusAddr# a1 a2)----------------------------------------------------------------------------- Function pointers for the default calling convention.--data FunPtr a = FunPtr Addr# deriving (Eq, Ord)--- ^ A value of type @'FunPtr' a@ is a pointer to a function callable--- from foreign code. The type @a@ will normally be a /foreign type/,--- a function type with zero or more arguments where------ * the argument types are /marshallable foreign types/,--- i.e. 'Char', 'Int', 'Double', 'Float',--- 'Bool', 'Data.Int.Int8', 'Data.Int.Int16', 'Data.Int.Int32',--- 'Data.Int.Int64', 'Data.Word.Word8', 'Data.Word.Word16',--- 'Data.Word.Word32', 'Data.Word.Word64', @'Ptr' a@, @'FunPtr' a@,--- @'Foreign.StablePtr.StablePtr' a@ or a renaming of any of these--- using @newtype@.--- --- * the return type is either a marshallable foreign type or has the form--- @'IO' t@ where @t@ is a marshallable foreign type or @()@.------ A value of type @'FunPtr' a@ may be a pointer to a foreign function,--- either returned by another foreign function or imported with a--- a static address import like------ > foreign import ccall "stdlib.h &free"--- > p_free :: FunPtr (Ptr a -> IO ())------ or a pointer to a Haskell function created using a /wrapper/ stub--- declared to produce a 'FunPtr' of the correct type. For example:------ > type Compare = Int -> Int -> Bool--- > foreign import ccall "wrapper"--- > mkCompare :: Compare -> IO (FunPtr Compare)------ Calls to wrapper stubs like @mkCompare@ allocate storage, which--- should be released with 'Foreign.Ptr.freeHaskellFunPtr' when no--- longer required.------ To convert 'FunPtr' values to corresponding Haskell functions, one--- can define a /dynamic/ stub for the specific foreign type, e.g.------ > type IntFunction = CInt -> IO ()--- > foreign import ccall "dynamic" --- > mkFun :: FunPtr IntFunction -> IntFunction---- |The constant 'nullFunPtr' contains a--- distinguished value of 'FunPtr' that is not--- associated with a valid memory location.-nullFunPtr :: FunPtr a-nullFunPtr = FunPtr nullAddr#---- |Casts a 'FunPtr' to a 'FunPtr' of a different type.-castFunPtr :: FunPtr a -> FunPtr b-castFunPtr (FunPtr addr) = FunPtr addr---- |Casts a 'FunPtr' to a 'Ptr'.------ /Note:/ this is valid only on architectures where data and function--- pointers range over the same set of addresses, and should only be used--- for bindings to external libraries whose interface already relies on--- this assumption.-castFunPtrToPtr :: FunPtr a -> Ptr b-castFunPtrToPtr (FunPtr addr) = Ptr addr---- |Casts a 'Ptr' to a 'FunPtr'.------ /Note:/ this is valid only on architectures where data and function--- pointers range over the same set of addresses, and should only be used--- for bindings to external libraries whose interface already relies on--- this assumption.-castPtrToFunPtr :: Ptr a -> FunPtr b-castPtrToFunPtr (Ptr addr) = FunPtr addr------------------------------------------------------------------------------ Show instances for Ptr and FunPtr--instance Show (Ptr a) where- showsPrec _ (Ptr a) rs = pad_out (showHex (wordToInteger(int2Word#(addr2Int# a))) "")- where- -- want 0s prefixed to pad it out to a fixed length.- pad_out ls = - '0':'x':(replicate (2*SIZEOF_HSPTR - length ls) '0') ++ ls ++ rs--instance Show (FunPtr a) where- showsPrec p = showsPrec p . castFunPtrToPtr--\end{code}
@@ -1,703 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, StandaloneDeriving, PatternGuards,- ScopedTypeVariables #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Read--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The 'Read' class and instances for basic data types.------------------------------------------------------------------------------------- #hide-module GHC.Read- ( Read(..) -- class-- -- ReadS type- , ReadS -- :: *; = String -> [(a,String)]-- -- H98 compatibility- , lex -- :: ReadS String- , lexLitChar -- :: ReadS String- , readLitChar -- :: ReadS Char- , lexDigits -- :: ReadS String-- -- defining readers- , lexP -- :: ReadPrec Lexeme- , paren -- :: ReadPrec a -> ReadPrec a- , parens -- :: ReadPrec a -> ReadPrec a- , list -- :: ReadPrec a -> ReadPrec [a]- , choose -- :: [(String, ReadPrec a)] -> ReadPrec a- , readListDefault, readListPrecDefault-- -- Temporary- , readParen-- -- XXX Can this be removed?- , readp- )- where--import qualified Text.ParserCombinators.ReadP as P--import Text.ParserCombinators.ReadP- ( ReadP- , ReadS- , readP_to_S- )--import qualified Text.Read.Lex as L--- Lex exports 'lex', which is also defined here,--- hence the qualified import.--- We can't import *anything* unqualified, because that--- confuses Haddock.--import Text.ParserCombinators.ReadPrec--import Data.Maybe--#ifndef __HADDOCK__-import {-# SOURCE #-} GHC.Unicode ( isDigit )-#endif-import GHC.Num-import GHC.Real-import GHC.Float-import GHC.Show-import GHC.Base-import GHC.Err-import GHC.Arr--- For defining instances for the generic deriving mechanism-import GHC.Generics (Arity(..), Associativity(..), Fixity(..))-\end{code}---\begin{code}--- | @'readParen' 'True' p@ parses what @p@ parses, but surrounded with--- parentheses.------ @'readParen' 'False' p@ parses what @p@ parses, but optionally--- surrounded with parentheses.-readParen :: Bool -> ReadS a -> ReadS a--- A Haskell 98 function-readParen b g = if b then mandatory else optional- where optional r = g r ++ mandatory r- mandatory r = do- ("(",s) <- lex r- (x,t) <- optional s- (")",u) <- lex t- return (x,u)-\end{code}---%*********************************************************-%* *-\subsection{The @Read@ class}-%* *-%*********************************************************--\begin{code}---------------------------------------------------------------------------- class Read---- | Parsing of 'String's, producing values.------ Minimal complete definition: 'readsPrec' (or, for GHC only, 'readPrec')------ Derived instances of 'Read' make the following assumptions, which--- derived instances of 'Text.Show.Show' obey:------ * If the constructor is defined to be an infix operator, then the--- derived 'Read' instance will parse only infix applications of--- the constructor (not the prefix form).------ * Associativity is not used to reduce the occurrence of parentheses,--- although precedence may be.------ * If the constructor is defined using record syntax, the derived 'Read'--- will parse only the record-syntax form, and furthermore, the fields--- must be given in the same order as the original declaration.------ * The derived 'Read' instance allows arbitrary Haskell whitespace--- between tokens of the input string. Extra parentheses are also--- allowed.------ For example, given the declarations------ > infixr 5 :^:--- > data Tree a = Leaf a | Tree a :^: Tree a------ the derived instance of 'Read' in Haskell 98 is equivalent to------ > instance (Read a) => Read (Tree a) where--- >--- > readsPrec d r = readParen (d > app_prec)--- > (\r -> [(Leaf m,t) |--- > ("Leaf",s) <- lex r,--- > (m,t) <- readsPrec (app_prec+1) s]) r--- >--- > ++ readParen (d > up_prec)--- > (\r -> [(u:^:v,w) |--- > (u,s) <- readsPrec (up_prec+1) r,--- > (":^:",t) <- lex s,--- > (v,w) <- readsPrec (up_prec+1) t]) r--- >--- > where app_prec = 10--- > up_prec = 5------ Note that right-associativity of @:^:@ is unused.------ The derived instance in GHC is equivalent to------ > instance (Read a) => Read (Tree a) where--- >--- > readPrec = parens $ (prec app_prec $ do--- > Ident "Leaf" <- lexP--- > m <- step readPrec--- > return (Leaf m))--- >--- > +++ (prec up_prec $ do--- > u <- step readPrec--- > Symbol ":^:" <- lexP--- > v <- step readPrec--- > return (u :^: v))--- >--- > where app_prec = 10--- > up_prec = 5--- >--- > readListPrec = readListPrecDefault--class Read a where- -- | attempts to parse a value from the front of the string, returning- -- a list of (parsed value, remaining string) pairs. If there is no- -- successful parse, the returned list is empty.- --- -- Derived instances of 'Read' and 'Text.Show.Show' satisfy the following:- --- -- * @(x,\"\")@ is an element of- -- @('readsPrec' d ('Text.Show.showsPrec' d x \"\"))@.- --- -- That is, 'readsPrec' parses the string produced by- -- 'Text.Show.showsPrec', and delivers the value that- -- 'Text.Show.showsPrec' started with.-- readsPrec :: Int -- ^ the operator precedence of the enclosing- -- context (a number from @0@ to @11@).- -- Function application has precedence @10@.- -> ReadS a-- -- | The method 'readList' is provided to allow the programmer to- -- give a specialised way of parsing lists of values.- -- For example, this is used by the predefined 'Read' instance of- -- the 'Char' type, where values of type 'String' should be are- -- expected to use double quotes, rather than square brackets.- readList :: ReadS [a]-- -- | Proposed replacement for 'readsPrec' using new-style parsers (GHC only).- readPrec :: ReadPrec a-- -- | Proposed replacement for 'readList' using new-style parsers (GHC only).- -- The default definition uses 'readList'. Instances that define 'readPrec'- -- should also define 'readListPrec' as 'readListPrecDefault'.- readListPrec :: ReadPrec [a]- - -- default definitions- readsPrec = readPrec_to_S readPrec- readList = readPrec_to_S (list readPrec) 0- readPrec = readS_to_Prec readsPrec- readListPrec = readS_to_Prec (\_ -> readList)--readListDefault :: Read a => ReadS [a]--- ^ A possible replacement definition for the 'readList' method (GHC only).--- This is only needed for GHC, and even then only for 'Read' instances--- where 'readListPrec' isn't defined as 'readListPrecDefault'.-readListDefault = readPrec_to_S readListPrec 0--readListPrecDefault :: Read a => ReadPrec [a]--- ^ A possible replacement definition for the 'readListPrec' method,--- defined using 'readPrec' (GHC only).-readListPrecDefault = list readPrec----------------------------------------------------------------------------- H98 compatibility---- | The 'lex' function reads a single lexeme from the input, discarding--- initial white space, and returning the characters that constitute the--- lexeme. If the input string contains only white space, 'lex' returns a--- single successful \`lexeme\' consisting of the empty string. (Thus--- @'lex' \"\" = [(\"\",\"\")]@.) If there is no legal lexeme at the--- beginning of the input string, 'lex' fails (i.e. returns @[]@).------ This lexer is not completely faithful to the Haskell lexical syntax--- in the following respects:------ * Qualified names are not handled properly------ * Octal and hexadecimal numerics are not recognized as a single token------ * Comments are not treated properly-lex :: ReadS String -- As defined by H98-lex s = readP_to_S L.hsLex s---- | Read a string representation of a character, using Haskell--- source-language escape conventions. For example:------ > lexLitChar "\\nHello" = [("\\n", "Hello")]----lexLitChar :: ReadS String -- As defined by H98-lexLitChar = readP_to_S (do { (s, _) <- P.gather L.lexChar ;- return s })- -- There was a skipSpaces before the P.gather L.lexChar,- -- but that seems inconsistent with readLitChar---- | Read a string representation of a character, using Haskell--- source-language escape conventions, and convert it to the character--- that it encodes. For example:------ > readLitChar "\\nHello" = [('\n', "Hello")]----readLitChar :: ReadS Char -- As defined by H98-readLitChar = readP_to_S L.lexChar---- | Reads a non-empty string of decimal digits.-lexDigits :: ReadS String-lexDigits = readP_to_S (P.munch1 isDigit)----------------------------------------------------------------------------- utility parsers--lexP :: ReadPrec L.Lexeme--- ^ Parse a single lexeme-lexP = lift L.lex--lexP' :: ReadPrec L.Lexeme'--- ^ Parse a single lexeme-lexP' = lift L.lex'--paren :: ReadPrec a -> ReadPrec a--- ^ @(paren p)@ parses \"(P0)\"--- where @p@ parses \"P0\" in precedence context zero-paren p = do L.Punc "(" <- lexP- x <- reset p- L.Punc ")" <- lexP- return x--parens :: ReadPrec a -> ReadPrec a--- ^ @(parens p)@ parses \"P\", \"(P0)\", \"((P0))\", etc, --- where @p@ parses \"P\" in the current precedence context--- and parses \"P0\" in precedence context zero-parens p = optional- where- optional = p +++ mandatory- mandatory = paren optional--list :: ReadPrec a -> ReadPrec [a]--- ^ @(list p)@ parses a list of things parsed by @p@,--- using the usual square-bracket syntax.-list readx =- parens- ( do L.Punc "[" <- lexP- (listRest False +++ listNext)- )- where- listRest started =- do L.Punc c <- lexP- case c of- "]" -> return []- "," | started -> listNext- _ -> pfail- - listNext =- do x <- reset readx- xs <- listRest True- return (x:xs)--choose :: [(String, ReadPrec a)] -> ReadPrec a--- ^ Parse the specified lexeme and continue as specified.--- Esp useful for nullary constructors; e.g.--- @choose [(\"A\", return A), (\"B\", return B)]@--- We match both Ident and Symbol because the constructor--- might be an operator eg (:=:)-choose sps = foldr ((+++) . try_one) pfail sps- where- try_one (s,p) = do { token <- lexP ;- case token of- L.Ident s' | s==s' -> p- L.Symbol s' | s==s' -> p- _other -> pfail }-\end{code}---%*********************************************************-%* *-\subsection{Simple instances of Read}-%* *-%*********************************************************--\begin{code}-instance Read Char where- readPrec =- parens- ( do L.Char c <- lexP- return c- )-- readListPrec =- parens- ( do L.String s <- lexP -- Looks for "foo"- return s- +++- readListPrecDefault -- Looks for ['f','o','o']- ) -- (more generous than H98 spec)-- readList = readListDefault--instance Read Bool where- readPrec =- parens- ( do L.Ident s <- lexP- case s of- "True" -> return True- "False" -> return False- _ -> pfail- )-- readListPrec = readListPrecDefault- readList = readListDefault--instance Read Ordering where- readPrec =- parens- ( do L.Ident s <- lexP- case s of- "LT" -> return LT- "EQ" -> return EQ- "GT" -> return GT- _ -> pfail- )-- readListPrec = readListPrecDefault- readList = readListDefault-\end{code}---%*********************************************************-%* *-\subsection{Structure instances of Read: Maybe, List etc}-%* *-%*********************************************************--For structured instances of Read we start using the precedences. The-idea is then that 'parens (prec k p)' will fail immediately when trying-to parse it in a context with a higher precedence level than k. But if-there is one parenthesis parsed, then the required precedence level-drops to 0 again, and parsing inside p may succeed.--'appPrec' is just the precedence level of function application. So,-if we are parsing function application, we'd better require the-precedence level to be at least 'appPrec'. Otherwise, we have to put-parentheses around it.--'step' is used to increase the precedence levels inside a-parser, and can be used to express left- or right- associativity. For-example, % is defined to be left associative, so we only increase-precedence on the right hand side.--Note how step is used in for example the Maybe parser to increase the-precedence beyond appPrec, so that basically only literals and-parenthesis-like objects such as (...) and [...] can be an argument to-'Just'.--\begin{code}-instance Read a => Read (Maybe a) where- readPrec =- parens- (do L.Ident "Nothing" <- lexP- return Nothing- +++- prec appPrec (- do L.Ident "Just" <- lexP- x <- step readPrec- return (Just x))- )-- readListPrec = readListPrecDefault- readList = readListDefault--instance Read a => Read [a] where- readPrec = readListPrec- readListPrec = readListPrecDefault- readList = readListDefault--instance (Ix a, Read a, Read b) => Read (Array a b) where- readPrec = parens $ prec appPrec $- do L.Ident "array" <- lexP- theBounds <- step readPrec- vals <- step readPrec- return (array theBounds vals)-- readListPrec = readListPrecDefault- readList = readListDefault--instance Read L.Lexeme where- readPrec = lexP- readListPrec = readListPrecDefault- readList = readListDefault-\end{code}---%*********************************************************-%* *-\subsection{Numeric instances of Read}-%* *-%*********************************************************--\begin{code}-readNumber :: Num a => (L.Lexeme' -> ReadPrec a) -> ReadPrec a--- Read a signed number-readNumber convert =- parens- ( do x <- lexP'- case x of- L.Symbol' "-" -> do y <- lexP'- n <- convert y- return (negate n)-- _ -> convert x- )---convertInt :: Num a => L.Lexeme' -> ReadPrec a-convertInt (L.Number n)- | Just i <- L.numberToInteger n = return (fromInteger i)-convertInt _ = pfail--convertFrac :: forall a . RealFloat a => L.Lexeme' -> ReadPrec a-convertFrac (L.Ident' "NaN") = return (0 / 0)-convertFrac (L.Ident' "Infinity") = return (1 / 0)-convertFrac (L.Number n) = let resRange = floatRange (undefined :: a)- in case L.numberToRangedRational resRange n of- Nothing -> return (1 / 0)- Just rat -> return $ fromRational rat-convertFrac _ = pfail--instance Read Int where- readPrec = readNumber convertInt- readListPrec = readListPrecDefault- readList = readListDefault--instance Read Integer where- readPrec = readNumber convertInt- readListPrec = readListPrecDefault- readList = readListDefault--instance Read Float where- readPrec = readNumber convertFrac- readListPrec = readListPrecDefault- readList = readListDefault--instance Read Double where- readPrec = readNumber convertFrac- readListPrec = readListPrecDefault- readList = readListDefault--instance (Integral a, Read a) => Read (Ratio a) where- readPrec =- parens- ( prec ratioPrec- ( do x <- step readPrec- L.Symbol "%" <- lexP- y <- step readPrec- return (x % y)- )- )-- readListPrec = readListPrecDefault- readList = readListDefault-\end{code}---%*********************************************************-%* *- Tuple instances of Read, up to size 15-%* *-%*********************************************************--\begin{code}-instance Read () where- readPrec =- parens- ( paren- ( return ()- )- )-- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b) => Read (a,b) where- readPrec = wrap_tup read_tup2- readListPrec = readListPrecDefault- readList = readListDefault--wrap_tup :: ReadPrec a -> ReadPrec a-wrap_tup p = parens (paren p)--read_comma :: ReadPrec ()-read_comma = do { L.Punc "," <- lexP; return () }--read_tup2 :: (Read a, Read b) => ReadPrec (a,b)--- Reads "a , b" no parens!-read_tup2 = do x <- readPrec- read_comma- y <- readPrec- return (x,y)--read_tup4 :: (Read a, Read b, Read c, Read d) => ReadPrec (a,b,c,d)-read_tup4 = do (a,b) <- read_tup2- read_comma- (c,d) <- read_tup2- return (a,b,c,d)---read_tup8 :: (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h)- => ReadPrec (a,b,c,d,e,f,g,h)-read_tup8 = do (a,b,c,d) <- read_tup4- read_comma- (e,f,g,h) <- read_tup4- return (a,b,c,d,e,f,g,h)---instance (Read a, Read b, Read c) => Read (a, b, c) where- readPrec = wrap_tup (do { (a,b) <- read_tup2; read_comma - ; c <- readPrec - ; return (a,b,c) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d) => Read (a, b, c, d) where- readPrec = wrap_tup read_tup4- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e) => Read (a, b, c, d, e) where- readPrec = wrap_tup (do { (a,b,c,d) <- read_tup4; read_comma- ; e <- readPrec- ; return (a,b,c,d,e) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f)- => Read (a, b, c, d, e, f) where- readPrec = wrap_tup (do { (a,b,c,d) <- read_tup4; read_comma- ; (e,f) <- read_tup2- ; return (a,b,c,d,e,f) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g)- => Read (a, b, c, d, e, f, g) where- readPrec = wrap_tup (do { (a,b,c,d) <- read_tup4; read_comma- ; (e,f) <- read_tup2; read_comma- ; g <- readPrec- ; return (a,b,c,d,e,f,g) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h)- => Read (a, b, c, d, e, f, g, h) where- readPrec = wrap_tup read_tup8- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i)- => Read (a, b, c, d, e, f, g, h, i) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; i <- readPrec- ; return (a,b,c,d,e,f,g,h,i) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i, Read j)- => Read (a, b, c, d, e, f, g, h, i, j) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; (i,j) <- read_tup2- ; return (a,b,c,d,e,f,g,h,i,j) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i, Read j, Read k)- => Read (a, b, c, d, e, f, g, h, i, j, k) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; (i,j) <- read_tup2; read_comma- ; k <- readPrec- ; return (a,b,c,d,e,f,g,h,i,j,k) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i, Read j, Read k, Read l)- => Read (a, b, c, d, e, f, g, h, i, j, k, l) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; (i,j,k,l) <- read_tup4- ; return (a,b,c,d,e,f,g,h,i,j,k,l) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i, Read j, Read k, Read l, Read m)- => Read (a, b, c, d, e, f, g, h, i, j, k, l, m) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; (i,j,k,l) <- read_tup4; read_comma- ; m <- readPrec- ; return (a,b,c,d,e,f,g,h,i,j,k,l,m) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i, Read j, Read k, Read l, Read m, Read n)- => Read (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; (i,j,k,l) <- read_tup4; read_comma- ; (m,n) <- read_tup2- ; return (a,b,c,d,e,f,g,h,i,j,k,l,m,n) })- readListPrec = readListPrecDefault- readList = readListDefault--instance (Read a, Read b, Read c, Read d, Read e, Read f, Read g, Read h,- Read i, Read j, Read k, Read l, Read m, Read n, Read o)- => Read (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- readPrec = wrap_tup (do { (a,b,c,d,e,f,g,h) <- read_tup8; read_comma- ; (i,j,k,l) <- read_tup4; read_comma- ; (m,n) <- read_tup2; read_comma- ; o <- readPrec- ; return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) })- readListPrec = readListPrecDefault- readList = readListDefault-\end{code}--\begin{code}--- XXX Can this be removed?--readp :: Read a => ReadP a-readp = readPrec_to_P readPrec minPrec-\end{code}--Instances for types of the generic deriving mechanism.--\begin{code}-deriving instance Read Arity-deriving instance Read Associativity-deriving instance Read Fixity-\end{code}
@@ -1,615 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash, UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}--------------------------------------------------------------------------------- |--- Module : GHC.Real--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The types 'Ratio' and 'Rational', and the classes 'Real', 'Fractional',--- 'Integral', and 'RealFrac'.------------------------------------------------------------------------------------- #hide-module GHC.Real where--import GHC.Base-import GHC.Num-import GHC.List-import GHC.Enum-import GHC.Show-import GHC.Err--#ifdef OPTIMISE_INTEGER_GCD_LCM-import GHC.Integer.GMP.Internals-#endif--infixr 8 ^, ^^-infixl 7 /, `quot`, `rem`, `div`, `mod`-infixl 7 %--default () -- Double isn't available yet,- -- and we shouldn't be using defaults anyway-\end{code}---%*********************************************************-%* *-\subsection{The @Ratio@ and @Rational@ types}-%* *-%*********************************************************--\begin{code}--- | Rational numbers, with numerator and denominator of some 'Integral' type.-data Ratio a = !a :% !a deriving (Eq)---- | Arbitrary-precision rational numbers, represented as a ratio of--- two 'Integer' values. A rational number may be constructed using--- the '%' operator.-type Rational = Ratio Integer--ratioPrec, ratioPrec1 :: Int-ratioPrec = 7 -- Precedence of ':%' constructor-ratioPrec1 = ratioPrec + 1--infinity, notANumber :: Rational-infinity = 1 :% 0-notANumber = 0 :% 0---- Use :%, not % for Inf/NaN; the latter would--- immediately lead to a runtime error, because it normalises.-\end{code}---\begin{code}--- | Forms the ratio of two integral numbers.-{-# SPECIALISE (%) :: Integer -> Integer -> Rational #-}-(%) :: (Integral a) => a -> a -> Ratio a---- | Extract the numerator of the ratio in reduced form:--- the numerator and denominator have no common factor and the denominator--- is positive.-numerator :: (Integral a) => Ratio a -> a---- | Extract the denominator of the ratio in reduced form:--- the numerator and denominator have no common factor and the denominator--- is positive.-denominator :: (Integral a) => Ratio a -> a-\end{code}--\tr{reduce} is a subsidiary function used only in this module .-It normalises a ratio by dividing both numerator and denominator by-their greatest common divisor.--\begin{code}-reduce :: (Integral a) => a -> a -> Ratio a-{-# SPECIALISE reduce :: Integer -> Integer -> Rational #-}-reduce _ 0 = error "Ratio.%: zero denominator"-reduce x y = (x `quot` d) :% (y `quot` d)- where d = gcd x y-\end{code}--\begin{code}-x % y = reduce (x * signum y) (abs y)--numerator (x :% _) = x-denominator (_ :% y) = y-\end{code}---%*********************************************************-%* *-\subsection{Standard numeric classes}-%* *-%*********************************************************--\begin{code}-class (Num a, Ord a) => Real a where- -- | the rational equivalent of its real argument with full precision- toRational :: a -> Rational---- | Integral numbers, supporting integer division.------ Minimal complete definition: 'quotRem' and 'toInteger'-class (Real a, Enum a) => Integral a where- -- | integer division truncated toward zero- quot :: a -> a -> a- -- | integer remainder, satisfying- --- -- > (x `quot` y)*y + (x `rem` y) == x- rem :: a -> a -> a- -- | integer division truncated toward negative infinity- div :: a -> a -> a- -- | integer modulus, satisfying- --- -- > (x `div` y)*y + (x `mod` y) == x- mod :: a -> a -> a- -- | simultaneous 'quot' and 'rem'- quotRem :: a -> a -> (a,a)- -- | simultaneous 'div' and 'mod'- divMod :: a -> a -> (a,a)- -- | conversion to 'Integer'- toInteger :: a -> Integer-- {-# INLINE quot #-}- {-# INLINE rem #-}- {-# INLINE div #-}- {-# INLINE mod #-}- n `quot` d = q where (q,_) = quotRem n d- n `rem` d = r where (_,r) = quotRem n d- n `div` d = q where (q,_) = divMod n d- n `mod` d = r where (_,r) = divMod n d-- divMod n d = if signum r == negate (signum d) then (q-1, r+d) else qr- where qr@(q,r) = quotRem n d---- | Fractional numbers, supporting real division.------ Minimal complete definition: 'fromRational' and ('recip' or @('/')@)-class (Num a) => Fractional a where- -- | fractional division- (/) :: a -> a -> a- -- | reciprocal fraction- recip :: a -> a- -- | Conversion from a 'Rational' (that is @'Ratio' 'Integer'@).- -- A floating literal stands for an application of 'fromRational'- -- to a value of type 'Rational', so such literals have type- -- @('Fractional' a) => a@.- fromRational :: Rational -> a-- {-# INLINE recip #-}- {-# INLINE (/) #-}- recip x = 1 / x- x / y = x * recip y---- | Extracting components of fractions.------ Minimal complete definition: 'properFraction'-class (Real a, Fractional a) => RealFrac a where- -- | The function 'properFraction' takes a real fractional number @x@- -- and returns a pair @(n,f)@ such that @x = n+f@, and:- --- -- * @n@ is an integral number with the same sign as @x@; and- --- -- * @f@ is a fraction with the same type and sign as @x@,- -- and with absolute value less than @1@.- --- -- The default definitions of the 'ceiling', 'floor', 'truncate'- -- and 'round' functions are in terms of 'properFraction'.- properFraction :: (Integral b) => a -> (b,a)- -- | @'truncate' x@ returns the integer nearest @x@ between zero and @x@- truncate :: (Integral b) => a -> b- -- | @'round' x@ returns the nearest integer to @x@;- -- the even integer if @x@ is equidistant between two integers- round :: (Integral b) => a -> b- -- | @'ceiling' x@ returns the least integer not less than @x@- ceiling :: (Integral b) => a -> b- -- | @'floor' x@ returns the greatest integer not greater than @x@- floor :: (Integral b) => a -> b-- {-# INLINE truncate #-}- truncate x = m where (m,_) = properFraction x-- round x = let (n,r) = properFraction x- m = if r < 0 then n - 1 else n + 1- in case signum (abs r - 0.5) of- -1 -> n- 0 -> if even n then n else m- 1 -> m- _ -> error "round default defn: Bad value"-- ceiling x = if r > 0 then n + 1 else n- where (n,r) = properFraction x-- floor x = if r < 0 then n - 1 else n- where (n,r) = properFraction x-\end{code}---These 'numeric' enumerations come straight from the Report--\begin{code}-numericEnumFrom :: (Fractional a) => a -> [a]-numericEnumFrom n = n `seq` (n : numericEnumFrom (n + 1))--numericEnumFromThen :: (Fractional a) => a -> a -> [a]-numericEnumFromThen n m = n `seq` m `seq` (n : numericEnumFromThen m (m+m-n))--numericEnumFromTo :: (Ord a, Fractional a) => a -> a -> [a]-numericEnumFromTo n m = takeWhile (<= m + 1/2) (numericEnumFrom n)--numericEnumFromThenTo :: (Ord a, Fractional a) => a -> a -> a -> [a]-numericEnumFromThenTo e1 e2 e3- = takeWhile predicate (numericEnumFromThen e1 e2)- where- mid = (e2 - e1) / 2- predicate | e2 >= e1 = (<= e3 + mid)- | otherwise = (>= e3 + mid)-\end{code}---%*********************************************************-%* *-\subsection{Instances for @Int@}-%* *-%*********************************************************--\begin{code}-instance Real Int where- toRational x = toInteger x :% 1--instance Integral Int where- toInteger (I# i) = smallInteger i-- a `quot` b- | b == 0 = divZeroError- | b == (-1) && a == minBound = overflowError -- Note [Order of tests]- -- in GHC.Int- | otherwise = a `quotInt` b-- a `rem` b- | b == 0 = divZeroError- -- The quotRem CPU instruction fails for minBound `quotRem` -1,- -- but minBound `rem` -1 is well-defined (0). We therefore- -- special-case it.- | b == (-1) = 0- | otherwise = a `remInt` b-- a `div` b- | b == 0 = divZeroError- | b == (-1) && a == minBound = overflowError -- Note [Order of tests]- -- in GHC.Int- | otherwise = a `divInt` b-- a `mod` b- | b == 0 = divZeroError- -- The divMod CPU instruction fails for minBound `divMod` -1,- -- but minBound `mod` -1 is well-defined (0). We therefore- -- special-case it.- | b == (-1) = 0- | otherwise = a `modInt` b-- a `quotRem` b- | b == 0 = divZeroError- -- Note [Order of tests] in GHC.Int- | b == (-1) && a == minBound = (overflowError, 0)- | otherwise = a `quotRemInt` b-- a `divMod` b- | b == 0 = divZeroError- -- Note [Order of tests] in GHC.Int- | b == (-1) && a == minBound = (overflowError, 0)- | otherwise = a `divModInt` b-\end{code}---%*********************************************************-%* *-\subsection{Instances for @Integer@}-%* *-%*********************************************************--\begin{code}-instance Real Integer where- toRational x = x :% 1--instance Integral Integer where- toInteger n = n-- _ `quot` 0 = divZeroError- n `quot` d = n `quotInteger` d-- _ `rem` 0 = divZeroError- n `rem` d = n `remInteger` d-- _ `divMod` 0 = divZeroError- a `divMod` b = case a `divModInteger` b of- (# x, y #) -> (x, y)-- _ `quotRem` 0 = divZeroError- a `quotRem` b = case a `quotRemInteger` b of- (# q, r #) -> (q, r)-- -- use the defaults for div & mod-\end{code}---%*********************************************************-%* *-\subsection{Instances for @Ratio@}-%* *-%*********************************************************--\begin{code}-instance (Integral a) => Ord (Ratio a) where- {-# SPECIALIZE instance Ord Rational #-}- (x:%y) <= (x':%y') = x * y' <= x' * y- (x:%y) < (x':%y') = x * y' < x' * y--instance (Integral a) => Num (Ratio a) where- {-# SPECIALIZE instance Num Rational #-}- (x:%y) + (x':%y') = reduce (x*y' + x'*y) (y*y')- (x:%y) - (x':%y') = reduce (x*y' - x'*y) (y*y')- (x:%y) * (x':%y') = reduce (x * x') (y * y')- negate (x:%y) = (-x) :% y- abs (x:%y) = abs x :% y- signum (x:%_) = signum x :% 1- fromInteger x = fromInteger x :% 1--{-# RULES "fromRational/id" fromRational = id :: Rational -> Rational #-}-instance (Integral a) => Fractional (Ratio a) where- {-# SPECIALIZE instance Fractional Rational #-}- (x:%y) / (x':%y') = (x*y') % (y*x')- recip (0:%_) = error "Ratio.%: zero denominator"- recip (x:%y)- | x < 0 = negate y :% negate x- | otherwise = y :% x- fromRational (x:%y) = fromInteger x % fromInteger y--instance (Integral a) => Real (Ratio a) where- {-# SPECIALIZE instance Real Rational #-}- toRational (x:%y) = toInteger x :% toInteger y--instance (Integral a) => RealFrac (Ratio a) where- {-# SPECIALIZE instance RealFrac Rational #-}- properFraction (x:%y) = (fromInteger (toInteger q), r:%y)- where (q,r) = quotRem x y--instance (Integral a, Show a) => Show (Ratio a) where- {-# SPECIALIZE instance Show Rational #-}- showsPrec p (x:%y) = showParen (p > ratioPrec) $- showsPrec ratioPrec1 x .- showString " % " .- -- H98 report has spaces round the %- -- but we removed them [May 04]- -- and added them again for consistency with- -- Haskell 98 [Sep 08, #1920]- showsPrec ratioPrec1 y--instance (Integral a) => Enum (Ratio a) where- {-# SPECIALIZE instance Enum Rational #-}- succ x = x + 1- pred x = x - 1-- toEnum n = fromIntegral n :% 1- fromEnum = fromInteger . truncate-- enumFrom = numericEnumFrom- enumFromThen = numericEnumFromThen- enumFromTo = numericEnumFromTo- enumFromThenTo = numericEnumFromThenTo-\end{code}---%*********************************************************-%* *-\subsection{Coercions}-%* *-%*********************************************************--\begin{code}--- | general coercion from integral types-fromIntegral :: (Integral a, Num b) => a -> b-fromIntegral = fromInteger . toInteger--{-# RULES-"fromIntegral/Int->Int" fromIntegral = id :: Int -> Int- #-}---- | general coercion to fractional types-realToFrac :: (Real a, Fractional b) => a -> b-realToFrac = fromRational . toRational-\end{code}--%*********************************************************-%* *-\subsection{Overloaded numeric functions}-%* *-%*********************************************************--\begin{code}--- | Converts a possibly-negative 'Real' value to a string.-showSigned :: (Real a)- => (a -> ShowS) -- ^ a function that can show unsigned values- -> Int -- ^ the precedence of the enclosing context- -> a -- ^ the value to show- -> ShowS-showSigned showPos p x- | x < 0 = showParen (p > 6) (showChar '-' . showPos (-x))- | otherwise = showPos x--even, odd :: (Integral a) => a -> Bool-even n = n `rem` 2 == 0-odd = not . even------------------------------------------------------------ | raise a number to a non-negative integral power-{-# SPECIALISE [1] (^) ::- Integer -> Integer -> Integer,- Integer -> Int -> Integer,- Int -> Int -> Int #-}-{-# INLINABLE (^) #-} -- See Note [Inlining (^)]-(^) :: (Num a, Integral b) => a -> b -> a-x0 ^ y0 | y0 < 0 = error "Negative exponent"- | y0 == 0 = 1- | otherwise = f x0 y0- where -- f : x0 ^ y0 = x ^ y- f x y | even y = f (x * x) (y `quot` 2)- | y == 1 = x- | otherwise = g (x * x) ((y - 1) `quot` 2) x- -- g : x0 ^ y0 = (x ^ y) * z- g x y z | even y = g (x * x) (y `quot` 2) z- | y == 1 = x * z- | otherwise = g (x * x) ((y - 1) `quot` 2) (x * z)---- | raise a number to an integral power-(^^) :: (Fractional a, Integral b) => a -> b -> a-{-# INLINABLE (^^) #-} -- See Note [Inlining (^)-x ^^ n = if n >= 0 then x^n else recip (x^(negate n))--{- Note [Inlining (^)- ~~~~~~~~~~~~~~~~~~~~~- The INLINABLE pragma allows (^) to be specialised at its call sites.- If it is called repeatedly at the same type, that can make a huge- difference, because of those constants which can be repeatedly- calculated.-- Currently the fromInteger calls are not floated because we get- \d1 d2 x y -> blah- after the gentle round of simplification. -}--{- Rules for powers with known small exponent- see #5237- For small exponents, (^) is inefficient compared to manually- expanding the multiplication tree.- Here, rules for the most common exponent types are given.- The range of exponents for which rules are given is quite- arbitrary and kept small to not unduly increase the number of rules.- 0 and 1 are excluded based on the assumption that nobody would- write x^0 or x^1 in code and the cases where an exponent could- be statically resolved to 0 or 1 are rare.-- It might be desirable to have corresponding rules also for- exponents of other types, in particular Word, but we can't- have those rules here (importing GHC.Word or GHC.Int would- create a cyclic module dependency), and it's doubtful they- would fire, since the exponents of other types tend to get- floated out before the rule has a chance to fire.-- Also desirable would be rules for (^^), but I haven't managed- to get those to fire.-- Note: Trying to save multiplications by sharing the square for- exponents 4 and 5 does not save time, indeed, for Double, it is- up to twice slower, so the rules contain flat sequences of- multiplications.--}--{-# RULES-"^2/Int" forall x. x ^ (2 :: Int) = let u = x in u*u-"^3/Int" forall x. x ^ (3 :: Int) = let u = x in u*u*u-"^4/Int" forall x. x ^ (4 :: Int) = let u = x in u*u*u*u-"^5/Int" forall x. x ^ (5 :: Int) = let u = x in u*u*u*u*u-"^2/Integer" forall x. x ^ (2 :: Integer) = let u = x in u*u-"^3/Integer" forall x. x ^ (3 :: Integer) = let u = x in u*u*u-"^4/Integer" forall x. x ^ (4 :: Integer) = let u = x in u*u*u*u-"^5/Integer" forall x. x ^ (5 :: Integer) = let u = x in u*u*u*u*u- #-}------------------------------------------------------------ Special power functions for Rational------ see #4337------ Rationale:--- For a legitimate Rational (n :% d), the numerator and denominator are--- coprime, i.e. they have no common prime factor.--- Therefore all powers (n ^ a) and (d ^ b) are also coprime, so it is--- not necessary to compute the greatest common divisor, which would be--- done in the default implementation at each multiplication step.--- Since exponentiation quickly leads to very large numbers and--- calculation of gcds is generally very slow for large numbers,--- avoiding the gcd leads to an order of magnitude speedup relatively--- soon (and an asymptotic improvement overall).------ Note:--- We cannot use these functions for general Ratio a because that would--- change results in a multitude of cases.--- The cause is that if a and b are coprime, their remainders by any--- positive modulus generally aren't, so in the default implementation--- reduction occurs.------ Example:--- (17 % 3) ^ 3 :: Ratio Word8--- Default:--- (17 % 3) ^ 3 = ((17 % 3) ^ 2) * (17 % 3)--- = ((289 `mod` 256) % 9) * (17 % 3)--- = (33 % 9) * (17 % 3)--- = (11 % 3) * (17 % 3)--- = (187 % 9)--- But:--- ((17^3) `mod` 256) % (3^3) = (4913 `mod` 256) % 27--- = 49 % 27------ TODO:--- Find out whether special-casing for numerator, denominator or--- exponent = 1 (or -1, where that may apply) gains something.---- Special version of (^) for Rational base-{-# RULES "(^)/Rational" (^) = (^%^) #-}-(^%^) :: Integral a => Rational -> a -> Rational-(n :% d) ^%^ e- | e < 0 = error "Negative exponent"- | e == 0 = 1 :% 1- | otherwise = (n ^ e) :% (d ^ e)---- Special version of (^^) for Rational base-{-# RULES "(^^)/Rational" (^^) = (^^%^^) #-}-(^^%^^) :: Integral a => Rational -> a -> Rational-(n :% d) ^^%^^ e- | e > 0 = (n ^ e) :% (d ^ e)- | e == 0 = 1 :% 1- | n > 0 = (d ^ (negate e)) :% (n ^ (negate e))- | n == 0 = error "Ratio.%: zero denominator"- | otherwise = let nn = d ^ (negate e)- dd = (negate n) ^ (negate e)- in if even e then (nn :% dd) else (negate nn :% dd)------------------------------------------------------------ | @'gcd' x y@ is the non-negative factor of both @x@ and @y@ of which--- every common factor of @x@ and @y@ is also a factor; for example--- @'gcd' 4 2 = 2@, @'gcd' (-4) 6 = 2@, @'gcd' 0 4@ = @4@. @'gcd' 0 0@ = @0@.--- (That is, the common divisor that is \"greatest\" in the divisibility--- preordering.)------ Note: Since for signed fixed-width integer types, @'abs' 'minBound' < 0@,--- the result may be negative if one of the arguments is @'minBound'@ (and--- necessarily is if the other is @0@ or @'minBound'@) for such types.-gcd :: (Integral a) => a -> a -> a-gcd x y = gcd' (abs x) (abs y)- where gcd' a 0 = a- gcd' a b = gcd' b (a `rem` b)---- | @'lcm' x y@ is the smallest positive integer that both @x@ and @y@ divide.-lcm :: (Integral a) => a -> a -> a-{-# SPECIALISE lcm :: Int -> Int -> Int #-}-lcm _ 0 = 0-lcm 0 _ = 0-lcm x y = abs ((x `quot` (gcd x y)) * y)--#ifdef OPTIMISE_INTEGER_GCD_LCM-{-# RULES-"gcd/Int->Int->Int" gcd = gcdInt-"gcd/Integer->Integer->Integer" gcd = gcdInteger-"lcm/Integer->Integer->Integer" lcm = lcmInteger- #-}--gcdInt :: Int -> Int -> Int-gcdInt a b = fromIntegral (gcdInteger (fromIntegral a) (fromIntegral b))-#endif--integralEnumFrom :: (Integral a, Bounded a) => a -> [a]-integralEnumFrom n = map fromInteger [toInteger n .. toInteger (maxBound `asTypeOf` n)]--integralEnumFromThen :: (Integral a, Bounded a) => a -> a -> [a]-integralEnumFromThen n1 n2- | i_n2 >= i_n1 = map fromInteger [i_n1, i_n2 .. toInteger (maxBound `asTypeOf` n1)]- | otherwise = map fromInteger [i_n1, i_n2 .. toInteger (minBound `asTypeOf` n1)]- where- i_n1 = toInteger n1- i_n2 = toInteger n2--integralEnumFromTo :: Integral a => a -> a -> [a]-integralEnumFromTo n m = map fromInteger [toInteger n .. toInteger m]--integralEnumFromThenTo :: Integral a => a -> a -> a -> [a]-integralEnumFromThenTo n1 n2 m- = map fromInteger [toInteger n1, toInteger n2 .. toInteger m]-\end{code}
@@ -1,175 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples, Rank2Types #-}-{-# OPTIONS_HADDOCK hide #-}--------------------------------------------------------------------------------- |--- Module : GHC.ST--- Copyright : (c) The University of Glasgow, 1992-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The 'ST' Monad.------------------------------------------------------------------------------------- #hide-module GHC.ST (- ST(..), STret(..), STRep,- fixST, runST, runSTRep,-- -- * Unsafe functions- liftST, unsafeInterleaveST- ) where--import GHC.Base-import GHC.Show-import Control.Monad( forever )--default ()-\end{code}--%*********************************************************-%* *-\subsection{The @ST@ monad}-%* *-%*********************************************************--The state-transformer monad proper. By default the monad is strict;-too many people got bitten by space leaks when it was lazy.--\begin{code}--- | The strict state-transformer monad.--- A computation of type @'ST' s a@ transforms an internal state indexed--- by @s@, and returns a value of type @a@.--- The @s@ parameter is either------ * an uninstantiated type variable (inside invocations of 'runST'), or------ * 'RealWorld' (inside invocations of 'Control.Monad.ST.stToIO').------ It serves to keep the internal states of different invocations--- of 'runST' separate from each other and from invocations of--- 'Control.Monad.ST.stToIO'.------ The '>>=' and '>>' operations are strict in the state (though not in--- values stored in the state). For example,------ @'runST' (writeSTRef _|_ v >>= f) = _|_@-newtype ST s a = ST (STRep s a)-type STRep s a = State# s -> (# State# s, a #)--instance Functor (ST s) where- fmap f (ST m) = ST $ \ s ->- case (m s) of { (# new_s, r #) ->- (# new_s, f r #) }--instance Monad (ST s) where- {-# INLINE return #-}- {-# INLINE (>>) #-}- {-# INLINE (>>=) #-}- return x = ST (\ s -> (# s, x #))- m >> k = m >>= \ _ -> k-- (ST m) >>= k- = ST (\ s ->- case (m s) of { (# new_s, r #) ->- case (k r) of { ST k2 ->- (k2 new_s) }})--data STret s a = STret (State# s) a--{-# SPECIALISE forever :: ST s a -> ST s b #-}--- See Note [Make forever INLINABLE] in Control.Monad---- liftST is useful when we want a lifted result from an ST computation. See--- fixST below.-liftST :: ST s a -> State# s -> STret s a-liftST (ST m) = \s -> case m s of (# s', r #) -> STret s' r--{-# NOINLINE unsafeInterleaveST #-}-unsafeInterleaveST :: ST s a -> ST s a-unsafeInterleaveST (ST m) = ST ( \ s ->- let- r = case m s of (# _, res #) -> res- in- (# s, r #)- )---- | Allow the result of a state transformer computation to be used (lazily)--- inside the computation.--- Note that if @f@ is strict, @'fixST' f = _|_@.-fixST :: (a -> ST s a) -> ST s a-fixST k = ST $ \ s ->- let ans = liftST (k r) s- STret _ r = ans- in- case ans of STret s' x -> (# s', x #)--instance Show (ST s a) where- showsPrec _ _ = showString "<<ST action>>"- showList = showList__ (showsPrec 0)-\end{code}--Definition of runST-~~~~~~~~~~~~~~~~~~~--SLPJ 95/04: Why @runST@ must not have an unfolding; consider:-\begin{verbatim}-f x =- runST ( \ s -> let- (a, s') = newArray# 100 [] s- (_, s'') = fill_in_array_or_something a x s'- in- freezeArray# a s'' )-\end{verbatim}-If we inline @runST@, we'll get:-\begin{verbatim}-f x = let- (a, s') = newArray# 100 [] realWorld#{-NB-}- (_, s'') = fill_in_array_or_something a x s'- in- freezeArray# a s''-\end{verbatim}-And now the @newArray#@ binding can be floated to become a CAF, which-is totally and utterly wrong:-\begin{verbatim}-f = let- (a, s') = newArray# 100 [] realWorld#{-NB-} -- YIKES!!!- in- \ x ->- let (_, s'') = fill_in_array_or_something a x s' in- freezeArray# a s''-\end{verbatim}-All calls to @f@ will share a {\em single} array! End SLPJ 95/04.--\begin{code}-{-# INLINE runST #-}--- The INLINE prevents runSTRep getting inlined in *this* module--- so that it is still visible when runST is inlined in an importing--- module. Regrettably delicate. runST is behaving like a wrapper.---- | Return the value computed by a state transformer computation.--- The @forall@ ensures that the internal state used by the 'ST'--- computation is inaccessible to the rest of the program.-runST :: (forall s. ST s a) -> a-runST st = runSTRep (case st of { ST st_rep -> st_rep })---- I'm only letting runSTRep be inlined right at the end, in particular *after* full laziness--- That's what the "INLINE [0]" says.--- SLPJ Apr 99--- {-# INLINE [0] runSTRep #-}---- SDM: further to the above, inline phase 0 is run *before*--- full-laziness at the moment, which means that the above comment is--- invalid. Inlining runSTRep doesn't make a huge amount of--- difference, anyway. Hence:--{-# NOINLINE runSTRep #-}-runSTRep :: (forall s. STRep s a) -> a-runSTRep st_rep = case st_rep realWorld# of- (# _, r #) -> r-\end{code}
@@ -1,53 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.STRef--- Copyright : (c) The University of Glasgow, 1994-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ References in the 'ST' monad.------------------------------------------------------------------------------------- #hide-module GHC.STRef (- STRef(..),- newSTRef, readSTRef, writeSTRef- ) where--import GHC.ST-import GHC.Base--data STRef s a = STRef (MutVar# s a)--- ^ a value of type @STRef s a@ is a mutable variable in state thread @s@,--- containing a value of type @a@---- |Build a new 'STRef' in the current state thread-newSTRef :: a -> ST s (STRef s a)-newSTRef init = ST $ \s1# ->- case newMutVar# init s1# of { (# s2#, var# #) ->- (# s2#, STRef var# #) }---- |Read the value of an 'STRef'-readSTRef :: STRef s a -> ST s a-readSTRef (STRef var#) = ST $ \s1# -> readMutVar# var# s1#---- |Write a new value into an 'STRef'-writeSTRef :: STRef s a -> a -> ST s ()-writeSTRef (STRef var#) val = ST $ \s1# ->- case writeMutVar# var# val s1# of { s2# ->- (# s2#, () #) }---- Just pointer equality on mutable references:-instance Eq (STRef s a) where- STRef v1# == STRef v2# = sameMutVar# v1# v2#--\end{code}
@@ -1,553 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, BangPatterns, StandaloneDeriving,- MagicHash, UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}--#include "MachDeps.h"-#if SIZEOF_HSWORD == 4-#define DIGITS 9-#define BASE 1000000000-#elif SIZEOF_HSWORD == 8-#define DIGITS 18-#define BASE 1000000000000000000-#else-#error Please define DIGITS and BASE--- DIGITS should be the largest integer such that--- 10^DIGITS < 2^(SIZEOF_HSWORD * 8 - 1)--- BASE should be 10^DIGITS. Note that ^ is not available yet.-#endif---------------------------------------------------------------------------------- |--- Module : GHC.Show--- Copyright : (c) The University of Glasgow, 1992-2002--- License : see libraries/base/LICENSE------ Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ The 'Show' class, and related operations.------------------------------------------------------------------------------------- #hide-module GHC.Show- (- Show(..), ShowS,-- -- Instances for Show: (), [], Bool, Ordering, Int, Char-- -- Show support code- shows, showChar, showString, showMultiLineString,- showParen, showList__, showSpace,- showLitChar, showLitString, protectEsc,- intToDigit, showSignedInt,- appPrec, appPrec1,-- -- Character operations- asciiTab,- )- where--import GHC.Base-import GHC.Num-import Data.Maybe-import GHC.List ((!!), foldr1, break)--- For defining instances for the generic deriving mechanism-import GHC.Generics (Arity(..), Associativity(..), Fixity(..))-\end{code}----%*********************************************************-%* *-\subsection{The @Show@ class}-%* *-%*********************************************************--\begin{code}--- | The @shows@ functions return a function that prepends the--- output 'String' to an existing 'String'. This allows constant-time--- concatenation of results using function composition.-type ShowS = String -> String---- | Conversion of values to readable 'String's.------ Minimal complete definition: 'showsPrec' or 'show'.------ Derived instances of 'Show' have the following properties, which--- are compatible with derived instances of 'Text.Read.Read':------ * The result of 'show' is a syntactically correct Haskell--- expression containing only constants, given the fixity--- declarations in force at the point where the type is declared.--- It contains only the constructor names defined in the data type,--- parentheses, and spaces. When labelled constructor fields are--- used, braces, commas, field names, and equal signs are also used.------ * If the constructor is defined to be an infix operator, then--- 'showsPrec' will produce infix applications of the constructor.------ * the representation will be enclosed in parentheses if the--- precedence of the top-level constructor in @x@ is less than @d@--- (associativity is ignored). Thus, if @d@ is @0@ then the result--- is never surrounded in parentheses; if @d@ is @11@ it is always--- surrounded in parentheses, unless it is an atomic expression.------ * If the constructor is defined using record syntax, then 'show'--- will produce the record-syntax form, with the fields given in the--- same order as the original declaration.------ For example, given the declarations------ > infixr 5 :^:--- > data Tree a = Leaf a | Tree a :^: Tree a------ the derived instance of 'Show' is equivalent to------ > instance (Show a) => Show (Tree a) where--- >--- > showsPrec d (Leaf m) = showParen (d > app_prec) $--- > showString "Leaf " . showsPrec (app_prec+1) m--- > where app_prec = 10--- >--- > showsPrec d (u :^: v) = showParen (d > up_prec) $--- > showsPrec (up_prec+1) u .--- > showString " :^: " .--- > showsPrec (up_prec+1) v--- > where up_prec = 5------ Note that right-associativity of @:^:@ is ignored. For example,------ * @'show' (Leaf 1 :^: Leaf 2 :^: Leaf 3)@ produces the string--- @\"Leaf 1 :^: (Leaf 2 :^: Leaf 3)\"@.--class Show a where- -- | Convert a value to a readable 'String'.- --- -- 'showsPrec' should satisfy the law- --- -- > showsPrec d x r ++ s == showsPrec d x (r ++ s)- --- -- Derived instances of 'Text.Read.Read' and 'Show' satisfy the following:- --- -- * @(x,\"\")@ is an element of- -- @('Text.Read.readsPrec' d ('showsPrec' d x \"\"))@.- --- -- That is, 'Text.Read.readsPrec' parses the string produced by- -- 'showsPrec', and delivers the value that 'showsPrec' started with.-- showsPrec :: Int -- ^ the operator precedence of the enclosing- -- context (a number from @0@ to @11@).- -- Function application has precedence @10@.- -> a -- ^ the value to be converted to a 'String'- -> ShowS-- -- | A specialised variant of 'showsPrec', using precedence context- -- zero, and returning an ordinary 'String'.- show :: a -> String-- -- | The method 'showList' is provided to allow the programmer to- -- give a specialised way of showing lists of values.- -- For example, this is used by the predefined 'Show' instance of- -- the 'Char' type, where values of type 'String' should be shown- -- in double quotes, rather than between square brackets.- showList :: [a] -> ShowS-- showsPrec _ x s = show x ++ s- show x = shows x ""- showList ls s = showList__ shows ls s--showList__ :: (a -> ShowS) -> [a] -> ShowS-showList__ _ [] s = "[]" ++ s-showList__ showx (x:xs) s = '[' : showx x (showl xs)- where- showl [] = ']' : s- showl (y:ys) = ',' : showx y (showl ys)--appPrec, appPrec1 :: Int- -- Use unboxed stuff because we don't have overloaded numerics yet-appPrec = I# 10# -- Precedence of application:- -- one more than the maximum operator precedence of 9-appPrec1 = I# 11# -- appPrec + 1-\end{code}--%*********************************************************-%* *-\subsection{Simple Instances}-%* *-%*********************************************************--\begin{code}--instance Show () where- showsPrec _ () = showString "()"--instance Show a => Show [a] where- showsPrec _ = showList--instance Show Bool where- showsPrec _ True = showString "True"- showsPrec _ False = showString "False"--instance Show Ordering where- showsPrec _ LT = showString "LT"- showsPrec _ EQ = showString "EQ"- showsPrec _ GT = showString "GT"--instance Show Char where- showsPrec _ '\'' = showString "'\\''"- showsPrec _ c = showChar '\'' . showLitChar c . showChar '\''-- showList cs = showChar '"' . showLitString cs . showChar '"'--instance Show Int where- showsPrec = showSignedInt--instance Show a => Show (Maybe a) where- showsPrec _p Nothing s = showString "Nothing" s- showsPrec p (Just x) s- = (showParen (p > appPrec) $- showString "Just " .- showsPrec appPrec1 x) s-\end{code}---%*********************************************************-%* *-\subsection{Show instances for the first few tuples-%* *-%*********************************************************--\begin{code}--- The explicit 's' parameters are important--- Otherwise GHC thinks that "shows x" might take a lot of work to compute--- and generates defns like--- showsPrec _ (x,y) = let sx = shows x; sy = shows y in--- \s -> showChar '(' (sx (showChar ',' (sy (showChar ')' s))))--instance (Show a, Show b) => Show (a,b) where- showsPrec _ (a,b) s = show_tuple [shows a, shows b] s--instance (Show a, Show b, Show c) => Show (a, b, c) where- showsPrec _ (a,b,c) s = show_tuple [shows a, shows b, shows c] s--instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where- showsPrec _ (a,b,c,d) s = show_tuple [shows a, shows b, shows c, shows d] s--instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) where- showsPrec _ (a,b,c,d,e) s = show_tuple [shows a, shows b, shows c, shows d, shows e] s--instance (Show a, Show b, Show c, Show d, Show e, Show f) => Show (a,b,c,d,e,f) where- showsPrec _ (a,b,c,d,e,f) s = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g)- => Show (a,b,c,d,e,f,g) where- showsPrec _ (a,b,c,d,e,f,g) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h)- => Show (a,b,c,d,e,f,g,h) where- showsPrec _ (a,b,c,d,e,f,g,h) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i)- => Show (a,b,c,d,e,f,g,h,i) where- showsPrec _ (a,b,c,d,e,f,g,h,i) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j)- => Show (a,b,c,d,e,f,g,h,i,j) where- showsPrec _ (a,b,c,d,e,f,g,h,i,j) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i, shows j] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k)- => Show (a,b,c,d,e,f,g,h,i,j,k) where- showsPrec _ (a,b,c,d,e,f,g,h,i,j,k) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i, shows j, shows k] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k,- Show l)- => Show (a,b,c,d,e,f,g,h,i,j,k,l) where- showsPrec _ (a,b,c,d,e,f,g,h,i,j,k,l) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i, shows j, shows k, shows l] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k,- Show l, Show m)- => Show (a,b,c,d,e,f,g,h,i,j,k,l,m) where- showsPrec _ (a,b,c,d,e,f,g,h,i,j,k,l,m) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i, shows j, shows k, shows l, shows m] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k,- Show l, Show m, Show n)- => Show (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where- showsPrec _ (a,b,c,d,e,f,g,h,i,j,k,l,m,n) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i, shows j, shows k, shows l, shows m, shows n] s--instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k,- Show l, Show m, Show n, Show o)- => Show (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where- showsPrec _ (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) s- = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g, shows h,- shows i, shows j, shows k, shows l, shows m, shows n, shows o] s--show_tuple :: [ShowS] -> ShowS-show_tuple ss = showChar '('- . foldr1 (\s r -> s . showChar ',' . r) ss- . showChar ')'-\end{code}---%*********************************************************-%* *-\subsection{Support code for @Show@}-%* *-%*********************************************************--\begin{code}--- | equivalent to 'showsPrec' with a precedence of 0.-shows :: (Show a) => a -> ShowS-shows = showsPrec zeroInt---- | utility function converting a 'Char' to a show function that--- simply prepends the character unchanged.-showChar :: Char -> ShowS-showChar = (:)---- | utility function converting a 'String' to a show function that--- simply prepends the string unchanged.-showString :: String -> ShowS-showString = (++)---- | utility function that surrounds the inner show function with--- parentheses when the 'Bool' parameter is 'True'.-showParen :: Bool -> ShowS -> ShowS-showParen b p = if b then showChar '(' . p . showChar ')' else p--showSpace :: ShowS-showSpace = {-showChar ' '-} \ xs -> ' ' : xs-\end{code}--Code specific for characters--\begin{code}--- | Convert a character to a string using only printable characters,--- using Haskell source-language escape conventions. For example:------ > showLitChar '\n' s = "\\n" ++ s----showLitChar :: Char -> ShowS-showLitChar c s | c > '\DEL' = showChar '\\' (protectEsc isDec (shows (ord c)) s)-showLitChar '\DEL' s = showString "\\DEL" s-showLitChar '\\' s = showString "\\\\" s-showLitChar c s | c >= ' ' = showChar c s-showLitChar '\a' s = showString "\\a" s-showLitChar '\b' s = showString "\\b" s-showLitChar '\f' s = showString "\\f" s-showLitChar '\n' s = showString "\\n" s-showLitChar '\r' s = showString "\\r" s-showLitChar '\t' s = showString "\\t" s-showLitChar '\v' s = showString "\\v" s-showLitChar '\SO' s = protectEsc (== 'H') (showString "\\SO") s-showLitChar c s = showString ('\\' : asciiTab!!ord c) s- -- I've done manual eta-expansion here, becuase otherwise it's- -- impossible to stop (asciiTab!!ord) getting floated out as an MFE--showLitString :: String -> ShowS--- | Same as 'showLitChar', but for strings--- It converts the string to a string using Haskell escape conventions--- for non-printable characters. Does not add double-quotes around the--- whole thing; the caller should do that.--- The main difference from showLitChar (apart from the fact that the--- argument is a string not a list) is that we must escape double-quotes-showLitString [] s = s-showLitString ('"' : cs) s = showString "\\\"" (showLitString cs s)-showLitString (c : cs) s = showLitChar c (showLitString cs s)- -- Making 's' an explicit parameter makes it clear to GHC that- -- showLitString has arity 2, which avoids it allocating an extra lambda- -- The sticking point is the recursive call to (showLitString cs), which- -- it can't figure out would be ok with arity 2.--showMultiLineString :: String -> [String]--- | Like 'showLitString' (expand escape characters using Haskell--- escape conventions), but--- * break the string into multiple lines--- * wrap the entire thing in double quotes--- Example: @showMultiLineString "hello\ngoodbye\nblah"@--- returns @["\"hello\\", "\\goodbye\\", "\\blah\""]@-showMultiLineString str- = go '\"' str- where- go ch s = case break (== '\n') s of- (l, _:s'@(_:_)) -> (ch : showLitString l "\\") : go '\\' s'- (l, _) -> [ch : showLitString l "\""]--isDec :: Char -> Bool-isDec c = c >= '0' && c <= '9'--protectEsc :: (Char -> Bool) -> ShowS -> ShowS-protectEsc p f = f . cont- where cont s@(c:_) | p c = "\\&" ++ s- cont s = s---asciiTab :: [String]-asciiTab = -- Using an array drags in the array module. listArray ('\NUL', ' ')- ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",- "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",- "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",- "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",- "SP"]-\end{code}--Code specific for Ints.--\begin{code}--- | Convert an 'Int' in the range @0@..@15@ to the corresponding single--- digit 'Char'. This function fails on other inputs, and generates--- lower-case hexadecimal digits.-intToDigit :: Int -> Char-intToDigit (I# i)- | i >=# 0# && i <=# 9# = unsafeChr (ord '0' `plusInt` I# i)- | i >=# 10# && i <=# 15# = unsafeChr (ord 'a' `minusInt` ten `plusInt` I# i)- | otherwise = error ("Char.intToDigit: not a digit " ++ show (I# i))--ten :: Int-ten = I# 10#--showSignedInt :: Int -> Int -> ShowS-showSignedInt (I# p) (I# n) r- | n <# 0# && p ># 6# = '(' : itos n (')' : r)- | otherwise = itos n r--itos :: Int# -> String -> String-itos n# cs- | n# <# 0# =- let !(I# minInt#) = minInt in- if n# ==# minInt#- -- negateInt# minInt overflows, so we can't do that:- then '-' : itos' (negateInt# (n# `quotInt#` 10#))- (itos' (negateInt# (n# `remInt#` 10#)) cs)- else '-' : itos' (negateInt# n#) cs- | otherwise = itos' n# cs- where- itos' :: Int# -> String -> String- itos' x# cs'- | x# <# 10# = C# (chr# (ord# '0'# +# x#)) : cs'- | otherwise = case chr# (ord# '0'# +# (x# `remInt#` 10#)) of { c# ->- itos' (x# `quotInt#` 10#) (C# c# : cs') }-\end{code}--Instances for types of the generic deriving mechanism.--\begin{code}-deriving instance Show Arity-deriving instance Show Associativity-deriving instance Show Fixity-\end{code}---%*********************************************************-%* *-\subsection{The @Integer@ instances for @Show@}-%* *-%*********************************************************--\begin{code}-instance Show Integer where- showsPrec p n r- | p > 6 && n < 0 = '(' : integerToString n (')' : r)- -- Minor point: testing p first gives better code- -- in the not-uncommon case where the p argument- -- is a constant- | otherwise = integerToString n r- showList = showList__ (showsPrec 0)---- Divide an conquer implementation of string conversion-integerToString :: Integer -> String -> String-integerToString n0 cs0- | n0 < 0 = '-' : integerToString' (- n0) cs0- | otherwise = integerToString' n0 cs0- where- integerToString' :: Integer -> String -> String- integerToString' n cs- | n < BASE = jhead (fromInteger n) cs- | otherwise = jprinth (jsplitf (BASE*BASE) n) cs-- -- Split n into digits in base p. We first split n into digits- -- in base p*p and then split each of these digits into two.- -- Note that the first 'digit' modulo p*p may have a leading zero- -- in base p that we need to drop - this is what jsplith takes care of.- -- jsplitb the handles the remaining digits.- jsplitf :: Integer -> Integer -> [Integer]- jsplitf p n- | p > n = [n]- | otherwise = jsplith p (jsplitf (p*p) n)-- jsplith :: Integer -> [Integer] -> [Integer]- jsplith p (n:ns) =- case n `quotRemInteger` p of- (# q, r #) ->- if q > 0 then q : r : jsplitb p ns- else r : jsplitb p ns- jsplith _ [] = error "jsplith: []"-- jsplitb :: Integer -> [Integer] -> [Integer]- jsplitb _ [] = []- jsplitb p (n:ns) = case n `quotRemInteger` p of- (# q, r #) ->- q : r : jsplitb p ns-- -- Convert a number that has been split into digits in base BASE^2- -- this includes a last splitting step and then conversion of digits- -- that all fit into a machine word.- jprinth :: [Integer] -> String -> String- jprinth (n:ns) cs =- case n `quotRemInteger` BASE of- (# q', r' #) ->- let q = fromInteger q'- r = fromInteger r'- in if q > 0 then jhead q $ jblock r $ jprintb ns cs- else jhead r $ jprintb ns cs- jprinth [] _ = error "jprinth []"-- jprintb :: [Integer] -> String -> String- jprintb [] cs = cs- jprintb (n:ns) cs = case n `quotRemInteger` BASE of- (# q', r' #) ->- let q = fromInteger q'- r = fromInteger r'- in jblock q $ jblock r $ jprintb ns cs-- -- Convert an integer that fits into a machine word. Again, we have two- -- functions, one that drops leading zeros (jhead) and one that doesn't- -- (jblock)- jhead :: Int -> String -> String- jhead n cs- | n < 10 = case unsafeChr (ord '0' + n) of- c@(C# _) -> c : cs- | otherwise = case unsafeChr (ord '0' + r) of- c@(C# _) -> jhead q (c : cs)- where- (q, r) = n `quotRemInt` 10-- jblock = jblock' {- ' -} DIGITS-- jblock' :: Int -> Int -> String -> String- jblock' d n cs- | d == 1 = case unsafeChr (ord '0' + n) of- c@(C# _) -> c : cs- | otherwise = case unsafeChr (ord '0' + r) of- c@(C# _) -> jblock' (d - 1) q (c : cs)- where- (q, r) = n `quotRemInt` 10-\end{code}-
@@ -1,11 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.Show (showSignedInt) where--import GHC.Types--showSignedInt :: Int -> Int -> [Char] -> [Char]-\end{code}-
@@ -1,113 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE NoImplicitPrelude- , MagicHash- , UnboxedTuples- , ForeignFunctionInterface- #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Stable--- Copyright : (c) The University of Glasgow, 1992-2004--- License : see libraries/base/LICENSE--- --- Maintainer : ffi@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Stable pointers.------------------------------------------------------------------------------------- #hide-module GHC.Stable (- StablePtr(..),- newStablePtr, -- :: a -> IO (StablePtr a) - deRefStablePtr, -- :: StablePtr a -> a- freeStablePtr, -- :: StablePtr a -> IO ()- castStablePtrToPtr, -- :: StablePtr a -> Ptr ()- castPtrToStablePtr -- :: Ptr () -> StablePtr a- ) where--import GHC.Ptr-import GHC.Base---------------------------------------------------------------------------------- Stable Pointers--{- |-A /stable pointer/ is a reference to a Haskell expression that is-guaranteed not to be affected by garbage collection, i.e., it will neither be-deallocated nor will the value of the stable pointer itself change during-garbage collection (ordinary references may be relocated during garbage-collection). Consequently, stable pointers can be passed to foreign code,-which can treat it as an opaque reference to a Haskell value.--A value of type @StablePtr a@ is a stable pointer to a Haskell-expression of type @a@.--}-data StablePtr a = StablePtr (StablePtr# a)---- |--- Create a stable pointer referring to the given Haskell value.----newStablePtr :: a -> IO (StablePtr a)-newStablePtr a = IO $ \ s ->- case makeStablePtr# a s of (# s', sp #) -> (# s', StablePtr sp #)---- |--- Obtain the Haskell value referenced by a stable pointer, i.e., the--- same value that was passed to the corresponding call to--- 'makeStablePtr'. If the argument to 'deRefStablePtr' has--- already been freed using 'freeStablePtr', the behaviour of--- 'deRefStablePtr' is undefined.----deRefStablePtr :: StablePtr a -> IO a-deRefStablePtr (StablePtr sp) = IO $ \s -> deRefStablePtr# sp s---- |--- Dissolve the association between the stable pointer and the Haskell--- value. Afterwards, if the stable pointer is passed to--- 'deRefStablePtr' or 'freeStablePtr', the behaviour is--- undefined. However, the stable pointer may still be passed to--- 'castStablePtrToPtr', but the @'Foreign.Ptr.Ptr' ()@ value returned--- by 'castStablePtrToPtr', in this case, is undefined (in particular,--- it may be 'Foreign.Ptr.nullPtr'). Nevertheless, the call--- to 'castStablePtrToPtr' is guaranteed not to diverge.----foreign import ccall unsafe "hs_free_stable_ptr" freeStablePtr :: StablePtr a -> IO ()---- |--- Coerce a stable pointer to an address. No guarantees are made about--- the resulting value, except that the original stable pointer can be--- recovered by 'castPtrToStablePtr'. In particular, the address may not--- refer to an accessible memory location and any attempt to pass it to--- the member functions of the class 'Foreign.Storable.Storable' leads to--- undefined behaviour.----castStablePtrToPtr :: StablePtr a -> Ptr ()-castStablePtrToPtr (StablePtr s) = Ptr (unsafeCoerce# s)----- |--- The inverse of 'castStablePtrToPtr', i.e., we have the identity--- --- > sp == castPtrToStablePtr (castStablePtrToPtr sp)--- --- for any stable pointer @sp@ on which 'freeStablePtr' has--- not been executed yet. Moreover, 'castPtrToStablePtr' may--- only be applied to pointers that have been produced by--- 'castStablePtrToPtr'.----castPtrToStablePtr :: Ptr () -> StablePtr a-castPtrToStablePtr (Ptr a) = StablePtr (unsafeCoerce# a)--instance Eq (StablePtr a) where - (StablePtr sp1) == (StablePtr sp2) =- case eqStablePtr# sp1 sp2 of- 0# -> False- _ -> True--\end{code}
@@ -1,108 +0,0 @@--------------------------------------------------------------------------------- |--- Module : GHC.Stack--- Copyright : (c) The University of Glasgow 2011--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Access to GHC's call-stack simulation-----------------------------------------------------------------------------------{-# LANGUAGE UnboxedTuples, MagicHash, EmptyDataDecls #-}-module GHC.Stack (- -- * Call stack- currentCallStack,- whoCreated,-- -- * Internals- CostCentreStack,- CostCentre,- getCurrentCCS,- getCCSOf,- ccsCC,- ccsParent,- ccLabel,- ccModule,- ccSrcSpan,- ccsToStrings,- renderStack- ) where--import Foreign-import Foreign.C--import GHC.IO-import GHC.Base-import GHC.Ptr-import GHC.Foreign as GHC-import GHC.IO.Encoding--#define PROFILING-#include "Rts.h"--data CostCentreStack-data CostCentre--getCurrentCCS :: dummy -> IO (Ptr CostCentreStack)-getCurrentCCS dummy = IO $ \s ->- case getCurrentCCS## dummy s of- (## s', addr ##) -> (## s', Ptr addr ##)--getCCSOf :: a -> IO (Ptr CostCentreStack)-getCCSOf obj = IO $ \s ->- case getCCSOf## obj s of- (## s', addr ##) -> (## s', Ptr addr ##)--ccsCC :: Ptr CostCentreStack -> IO (Ptr CostCentre)-ccsCC p = (# peek CostCentreStack, cc) p--ccsParent :: Ptr CostCentreStack -> IO (Ptr CostCentreStack)-ccsParent p = (# peek CostCentreStack, prevStack) p--ccLabel :: Ptr CostCentre -> IO CString-ccLabel p = (# peek CostCentre, label) p--ccModule :: Ptr CostCentre -> IO CString-ccModule p = (# peek CostCentre, module) p--ccSrcSpan :: Ptr CostCentre -> IO CString-ccSrcSpan p = (# peek CostCentre, srcloc) p---- | returns a '[String]' representing the current call stack. This--- can be useful for debugging.------ The implementation uses the call-stack simulation maintined by the--- profiler, so it only works if the program was compiled with @-prof@--- and contains suitable SCC annotations (e.g. by using @-fprof-auto@).--- Otherwise, the list returned is likely to be empty or--- uninformative.--currentCallStack :: IO [String]-currentCallStack = ccsToStrings =<< getCurrentCCS ()--ccsToStrings :: Ptr CostCentreStack -> IO [String]-ccsToStrings ccs0 = go ccs0 []- where- go ccs acc- | ccs == nullPtr = return acc- | otherwise = do- cc <- ccsCC ccs- lbl <- GHC.peekCString utf8 =<< ccLabel cc- mdl <- GHC.peekCString utf8 =<< ccModule cc- loc <- GHC.peekCString utf8 =<< ccSrcSpan cc- parent <- ccsParent ccs- if (mdl == "MAIN" && lbl == "MAIN")- then return acc- else go parent ((mdl ++ '.':lbl ++ ' ':'(':loc ++ ")") : acc)--whoCreated :: a -> IO [String]-whoCreated obj = do- ccs <- getCCSOf obj- ccsToStrings ccs--renderStack :: [String] -> String-renderStack strs = "Stack trace:" ++ concatMap ("\n "++) (reverse strs)
@@ -1,130 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ForeignFunctionInterface #-}-{-# LANGUAGE RecordWildCards #-}-{-# OPTIONS_GHC -funbox-strict-fields #-}---------------------------------------------------------------------------------- | This module provides access to internal garbage collection and--- memory usage statistics. These statistics are not available unless--- a program is run with the @-T@ RTS flag.------ This module is GHC-only and should not be considered portable.----------------------------------------------------------------------------------module GHC.Stats- ( GCStats(..)- , getGCStats-) where--import Foreign.Marshal.Alloc-import Foreign.Storable-import Foreign.Ptr-import Data.Int--#include "Rts.h"--foreign import ccall "getGCStats" getGCStats_ :: Ptr () -> IO ()---- I'm probably violating a bucket of constraints here... oops.---- | Global garbage collection and memory statistics.-data GCStats = GCStats- { bytesAllocated :: !Int64 -- ^ Total number of bytes allocated- , numGcs :: !Int64 -- ^ Number of garbage collections performed- , maxBytesUsed :: !Int64 -- ^ Maximum number of live bytes seen so far- , numByteUsageSamples :: !Int64 -- ^ Number of byte usage samples taken- -- | Sum of all byte usage samples, can be used with- -- 'numByteUsageSamples' to calculate averages with- -- arbitrary weighting (if you are sampling this record multiple- -- times).- , cumulativeBytesUsed :: !Int64- , bytesCopied :: !Int64 -- ^ Number of bytes copied during GC- , currentBytesUsed :: !Int64 -- ^ Current number of live bytes- , currentBytesSlop :: !Int64 -- ^ Current number of bytes lost to slop- , maxBytesSlop :: !Int64 -- ^ Maximum number of bytes lost to slop at any one time so far- , peakMegabytesAllocated :: !Int64 -- ^ Maximum number of megabytes allocated- -- | CPU time spent running mutator threads. This does not include- -- any profiling overhead or initialization.- , mutatorCpuSeconds :: !Double- -- | Wall clock time spent running mutator threads. This does not- -- include initialization.- , mutatorWallSeconds :: !Double- , gcCpuSeconds :: !Double -- ^ CPU time spent running GC- , gcWallSeconds :: !Double -- ^ Wall clock time spent running GC- , cpuSeconds :: !Double -- ^ Total CPU time elapsed since program start- , wallSeconds :: !Double -- ^ Total wall clock time elapsed since start- -- | Number of bytes copied during GC, minus space held by mutable- -- lists held by the capabilities. Can be used with- -- 'parMaxBytesCopied' to determine how well parallel GC utilized- -- all cores.- , parAvgBytesCopied :: !Int64- -- | Sum of number of bytes copied each GC by the most active GC- -- thread each GC. The ratio of 'parAvgBytesCopied' divided by- -- 'parMaxBytesCopied' approaches 1 for a maximally sequential- -- run and approaches the number of threads (set by the RTS flag- -- @-N@) for a maximally parallel run.- , parMaxBytesCopied :: !Int64- } deriving (Show, Read)-- {-- , initCpuSeconds :: !Double- , initWallSeconds :: !Double- -}---- | Retrieves garbage collection and memory statistics as of the last--- garbage collection. If you would like your statistics as recent as--- possible, first run a 'System.Mem.performGC'.-getGCStats :: IO GCStats-getGCStats = allocaBytes (#size GCStats) $ \p -> do- getGCStats_ p- bytesAllocated <- (# peek GCStats, bytes_allocated) p- numGcs <- (# peek GCStats, num_gcs ) p- numByteUsageSamples <- (# peek GCStats, num_byte_usage_samples ) p- maxBytesUsed <- (# peek GCStats, max_bytes_used ) p- cumulativeBytesUsed <- (# peek GCStats, cumulative_bytes_used ) p- bytesCopied <- (# peek GCStats, bytes_copied ) p- currentBytesUsed <- (# peek GCStats, current_bytes_used ) p- currentBytesSlop <- (# peek GCStats, current_bytes_slop) p- maxBytesSlop <- (# peek GCStats, max_bytes_slop) p- peakMegabytesAllocated <- (# peek GCStats, peak_megabytes_allocated ) p- {-- initCpuSeconds <- (# peek GCStats, init_cpu_seconds) p- initWallSeconds <- (# peek GCStats, init_wall_seconds) p- -}- mutatorCpuSeconds <- (# peek GCStats, mutator_cpu_seconds) p- mutatorWallSeconds <- (# peek GCStats, mutator_wall_seconds) p- gcCpuSeconds <- (# peek GCStats, gc_cpu_seconds) p- gcWallSeconds <- (# peek GCStats, gc_wall_seconds) p- cpuSeconds <- (# peek GCStats, cpu_seconds) p- wallSeconds <- (# peek GCStats, wall_seconds) p- parAvgBytesCopied <- (# peek GCStats, par_avg_bytes_copied) p- parMaxBytesCopied <- (# peek GCStats, par_max_bytes_copied) p- return GCStats { .. }--{----- Nontrivial to implement: TaskStats needs arbitrarily large--- amounts of memory, spark stats wants to use SparkCounters--- but that needs a new rts/ header.--data TaskStats = TaskStats- { taskMutCpuSeconds :: Int64- , taskMutWallSeconds :: Int64- , taskGcCpuSeconds :: Int64- , taskGcWallSeconds :: Int64- } deriving (Show, Read)--data SparkStats = SparkStats- { sparksCreated :: Int64- , sparksDud :: Int64- , sparksOverflowed :: Int64- , sparksConverted :: Int64- , sparksGcd :: Int64- , sparksFizzled :: Int64- } deriving (Show, Read)---- We also could get per-generation stats, which requires a--- non-constant but at runtime known about of memory.---}
@@ -1,165 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Storable--- Copyright : (c) The FFI task force, 2000-2002--- License : see libraries/base/LICENSE--- --- Maintainer : ffi@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Helper functions for "Foreign.Storable"------------------------------------------------------------------------------------- #hide-module GHC.Storable- ( readWideCharOffPtr - , readIntOffPtr - , readWordOffPtr - , readPtrOffPtr - , readFunPtrOffPtr - , readFloatOffPtr - , readDoubleOffPtr - , readStablePtrOffPtr - , readInt8OffPtr - , readInt16OffPtr - , readInt32OffPtr - , readInt64OffPtr - , readWord8OffPtr - , readWord16OffPtr - , readWord32OffPtr - , readWord64OffPtr - , writeWideCharOffPtr - , writeIntOffPtr - , writeWordOffPtr - , writePtrOffPtr - , writeFunPtrOffPtr - , writeFloatOffPtr - , writeDoubleOffPtr - , writeStablePtrOffPtr- , writeInt8OffPtr - , writeInt16OffPtr - , writeInt32OffPtr - , writeInt64OffPtr - , writeWord8OffPtr - , writeWord16OffPtr - , writeWord32OffPtr - , writeWord64OffPtr - ) where--import GHC.Stable ( StablePtr(..) )-import GHC.Int-import GHC.Word-import GHC.Ptr-import GHC.Base-\end{code}--\begin{code}--readWideCharOffPtr :: Ptr Char -> Int -> IO Char-readIntOffPtr :: Ptr Int -> Int -> IO Int-readWordOffPtr :: Ptr Word -> Int -> IO Word-readPtrOffPtr :: Ptr (Ptr a) -> Int -> IO (Ptr a)-readFunPtrOffPtr :: Ptr (FunPtr a) -> Int -> IO (FunPtr a)-readFloatOffPtr :: Ptr Float -> Int -> IO Float-readDoubleOffPtr :: Ptr Double -> Int -> IO Double-readStablePtrOffPtr :: Ptr (StablePtr a) -> Int -> IO (StablePtr a)-readInt8OffPtr :: Ptr Int8 -> Int -> IO Int8-readInt16OffPtr :: Ptr Int16 -> Int -> IO Int16-readInt32OffPtr :: Ptr Int32 -> Int -> IO Int32-readInt64OffPtr :: Ptr Int64 -> Int -> IO Int64-readWord8OffPtr :: Ptr Word8 -> Int -> IO Word8-readWord16OffPtr :: Ptr Word16 -> Int -> IO Word16-readWord32OffPtr :: Ptr Word32 -> Int -> IO Word32-readWord64OffPtr :: Ptr Word64 -> Int -> IO Word64--readWideCharOffPtr (Ptr a) (I# i)- = IO $ \s -> case readWideCharOffAddr# a i s of (# s2, x #) -> (# s2, C# x #)-readIntOffPtr (Ptr a) (I# i)- = IO $ \s -> case readIntOffAddr# a i s of (# s2, x #) -> (# s2, I# x #)-readWordOffPtr (Ptr a) (I# i)- = IO $ \s -> case readWordOffAddr# a i s of (# s2, x #) -> (# s2, W# x #)-readPtrOffPtr (Ptr a) (I# i)- = IO $ \s -> case readAddrOffAddr# a i s of (# s2, x #) -> (# s2, Ptr x #)-readFunPtrOffPtr (Ptr a) (I# i)- = IO $ \s -> case readAddrOffAddr# a i s of (# s2, x #) -> (# s2, FunPtr x #)-readFloatOffPtr (Ptr a) (I# i)- = IO $ \s -> case readFloatOffAddr# a i s of (# s2, x #) -> (# s2, F# x #)-readDoubleOffPtr (Ptr a) (I# i)- = IO $ \s -> case readDoubleOffAddr# a i s of (# s2, x #) -> (# s2, D# x #)-readStablePtrOffPtr (Ptr a) (I# i)- = IO $ \s -> case readStablePtrOffAddr# a i s of (# s2, x #) -> (# s2, StablePtr x #)-readInt8OffPtr (Ptr a) (I# i)- = IO $ \s -> case readInt8OffAddr# a i s of (# s2, x #) -> (# s2, I8# x #)-readWord8OffPtr (Ptr a) (I# i)- = IO $ \s -> case readWord8OffAddr# a i s of (# s2, x #) -> (# s2, W8# x #)-readInt16OffPtr (Ptr a) (I# i)- = IO $ \s -> case readInt16OffAddr# a i s of (# s2, x #) -> (# s2, I16# x #)-readWord16OffPtr (Ptr a) (I# i)- = IO $ \s -> case readWord16OffAddr# a i s of (# s2, x #) -> (# s2, W16# x #)-readInt32OffPtr (Ptr a) (I# i)- = IO $ \s -> case readInt32OffAddr# a i s of (# s2, x #) -> (# s2, I32# x #)-readWord32OffPtr (Ptr a) (I# i)- = IO $ \s -> case readWord32OffAddr# a i s of (# s2, x #) -> (# s2, W32# x #)-readInt64OffPtr (Ptr a) (I# i)- = IO $ \s -> case readInt64OffAddr# a i s of (# s2, x #) -> (# s2, I64# x #)-readWord64OffPtr (Ptr a) (I# i)- = IO $ \s -> case readWord64OffAddr# a i s of (# s2, x #) -> (# s2, W64# x #)--writeWideCharOffPtr :: Ptr Char -> Int -> Char -> IO ()-writeIntOffPtr :: Ptr Int -> Int -> Int -> IO ()-writeWordOffPtr :: Ptr Word -> Int -> Word -> IO ()-writePtrOffPtr :: Ptr (Ptr a) -> Int -> Ptr a -> IO ()-writeFunPtrOffPtr :: Ptr (FunPtr a) -> Int -> FunPtr a -> IO ()-writeFloatOffPtr :: Ptr Float -> Int -> Float -> IO ()-writeDoubleOffPtr :: Ptr Double -> Int -> Double -> IO ()-writeStablePtrOffPtr :: Ptr (StablePtr a) -> Int -> StablePtr a -> IO ()-writeInt8OffPtr :: Ptr Int8 -> Int -> Int8 -> IO ()-writeInt16OffPtr :: Ptr Int16 -> Int -> Int16 -> IO ()-writeInt32OffPtr :: Ptr Int32 -> Int -> Int32 -> IO ()-writeInt64OffPtr :: Ptr Int64 -> Int -> Int64 -> IO ()-writeWord8OffPtr :: Ptr Word8 -> Int -> Word8 -> IO ()-writeWord16OffPtr :: Ptr Word16 -> Int -> Word16 -> IO ()-writeWord32OffPtr :: Ptr Word32 -> Int -> Word32 -> IO ()-writeWord64OffPtr :: Ptr Word64 -> Int -> Word64 -> IO ()--writeWideCharOffPtr (Ptr a) (I# i) (C# x)- = IO $ \s -> case writeWideCharOffAddr# a i x s of s2 -> (# s2, () #)-writeIntOffPtr (Ptr a) (I# i) (I# x)- = IO $ \s -> case writeIntOffAddr# a i x s of s2 -> (# s2, () #)-writeWordOffPtr (Ptr a) (I# i) (W# x)- = IO $ \s -> case writeWordOffAddr# a i x s of s2 -> (# s2, () #)-writePtrOffPtr (Ptr a) (I# i) (Ptr x)- = IO $ \s -> case writeAddrOffAddr# a i x s of s2 -> (# s2, () #)-writeFunPtrOffPtr (Ptr a) (I# i) (FunPtr x)- = IO $ \s -> case writeAddrOffAddr# a i x s of s2 -> (# s2, () #)-writeFloatOffPtr (Ptr a) (I# i) (F# x)- = IO $ \s -> case writeFloatOffAddr# a i x s of s2 -> (# s2, () #)-writeDoubleOffPtr (Ptr a) (I# i) (D# x)- = IO $ \s -> case writeDoubleOffAddr# a i x s of s2 -> (# s2, () #)-writeStablePtrOffPtr (Ptr a) (I# i) (StablePtr x)- = IO $ \s -> case writeStablePtrOffAddr# a i x s of s2 -> (# s2 , () #)-writeInt8OffPtr (Ptr a) (I# i) (I8# x)- = IO $ \s -> case writeInt8OffAddr# a i x s of s2 -> (# s2, () #)-writeWord8OffPtr (Ptr a) (I# i) (W8# x)- = IO $ \s -> case writeWord8OffAddr# a i x s of s2 -> (# s2, () #)-writeInt16OffPtr (Ptr a) (I# i) (I16# x)- = IO $ \s -> case writeInt16OffAddr# a i x s of s2 -> (# s2, () #)-writeWord16OffPtr (Ptr a) (I# i) (W16# x)- = IO $ \s -> case writeWord16OffAddr# a i x s of s2 -> (# s2, () #)-writeInt32OffPtr (Ptr a) (I# i) (I32# x)- = IO $ \s -> case writeInt32OffAddr# a i x s of s2 -> (# s2, () #)-writeWord32OffPtr (Ptr a) (I# i) (W32# x)- = IO $ \s -> case writeWord32OffAddr# a i x s of s2 -> (# s2, () #)-writeInt64OffPtr (Ptr a) (I# i) (I64# x)- = IO $ \s -> case writeInt64OffAddr# a i x s of s2 -> (# s2, () #)-writeWord64OffPtr (Ptr a) (I# i) (W64# x)- = IO $ \s -> case writeWord64OffAddr# a i x s of s2 -> (# s2, () #)--\end{code}
@@ -1,219 +0,0 @@-\begin{code}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , ForeignFunctionInterface- , MagicHash- , UnboxedTuples- , PatternGuards- #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.TopHandler--- Copyright : (c) The University of Glasgow, 2001-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Support for catching exceptions raised during top-level computations--- (e.g. @Main.main@, 'Control.Concurrent.forkIO', and foreign exports)------------------------------------------------------------------------------------- #hide-module GHC.TopHandler (- runMainIO, runIO, runIOFastExit, runNonIO,- topHandler, topHandlerFastExit,- reportStackOverflow, reportError,- flushStdHandles- ) where--#include "HsBaseConfig.h"--import Control.Exception-import Data.Maybe-import Data.Dynamic (toDyn)--import Foreign-import Foreign.C-import GHC.Base-import GHC.Conc hiding (throwTo)-import GHC.Num-import GHC.Real-import GHC.MVar-import GHC.IO-import GHC.IO.Handle.FD-import GHC.IO.Handle-import GHC.IO.Exception-import GHC.Weak-import Data.Typeable-#if defined(mingw32_HOST_OS)-import GHC.ConsoleHandler-#endif---- | 'runMainIO' is wrapped around 'Main.main' (or whatever main is--- called in the program). It catches otherwise uncaught exceptions,--- and also flushes stdout\/stderr before exiting.-runMainIO :: IO a -> IO a-runMainIO main = - do - main_thread_id <- myThreadId- weak_tid <- mkWeakThreadId main_thread_id- install_interrupt_handler $ do- m <- deRefWeak weak_tid - case m of- Nothing -> return ()- Just tid -> throwTo tid (toException UserInterrupt)- main -- hs_exit() will flush- `catch`- topHandler--install_interrupt_handler :: IO () -> IO ()-#ifdef mingw32_HOST_OS-install_interrupt_handler handler = do- _ <- GHC.ConsoleHandler.installHandler $- Catch $ \event -> - case event of- ControlC -> handler- Break -> handler- Close -> handler- _ -> return ()- return ()-#else-#include "rts/Signals.h"--- specialised version of System.Posix.Signals.installHandler, which--- isn't available here.-install_interrupt_handler handler = do- let sig = CONST_SIGINT :: CInt- _ <- setHandler sig (Just (const handler, toDyn handler))- _ <- stg_sig_install sig STG_SIG_RST nullPtr- -- STG_SIG_RST: the second ^C kills us for real, just in case the- -- RTS or program is unresponsive.- return ()--foreign import ccall unsafe- stg_sig_install- :: CInt -- sig no.- -> CInt -- action code (STG_SIG_HAN etc.)- -> Ptr () -- (in, out) blocked- -> IO CInt -- (ret) old action code-#endif---- make a weak pointer to a ThreadId: holding the weak pointer doesn't--- keep the thread alive and prevent it from being identified as--- deadlocked. Vitally important for the main thread.-mkWeakThreadId :: ThreadId -> IO (Weak ThreadId)-mkWeakThreadId t@(ThreadId t#) = IO $ \s ->- case mkWeak# t# t (unsafeCoerce# 0#) s of - (# s1, w #) -> (# s1, Weak w #)---- | 'runIO' is wrapped around every @foreign export@ and @foreign--- import \"wrapper\"@ to mop up any uncaught exceptions. Thus, the--- result of running 'System.Exit.exitWith' in a foreign-exported--- function is the same as in the main thread: it terminates the--- program.----runIO :: IO a -> IO a-runIO main = catch main topHandler---- | Like 'runIO', but in the event of an exception that causes an exit,--- we don't shut down the system cleanly, we just exit. This is--- useful in some cases, because the safe exit version will give other--- threads a chance to clean up first, which might shut down the--- system in a different way. For example, try ------ main = forkIO (runIO (exitWith (ExitFailure 1))) >> threadDelay 10000------ This will sometimes exit with "interrupted" and code 0, because the--- main thread is given a chance to shut down when the child thread calls--- safeExit. There is a race to shut down between the main and child threads.----runIOFastExit :: IO a -> IO a-runIOFastExit main = catch main topHandlerFastExit- -- NB. this is used by the testsuite driver---- | The same as 'runIO', but for non-IO computations. Used for--- wrapping @foreign export@ and @foreign import \"wrapper\"@ when these--- are used to export Haskell functions with non-IO types.----runNonIO :: a -> IO a-runNonIO a = catch (a `seq` return a) topHandler--topHandler :: SomeException -> IO a-topHandler err = catch (real_handler safeExit err) topHandler--topHandlerFastExit :: SomeException -> IO a-topHandlerFastExit err = - catchException (real_handler fastExit err) topHandlerFastExit---- Make sure we handle errors while reporting the error!--- (e.g. evaluating the string passed to 'error' might generate--- another error, etc.)----real_handler :: (Int -> IO a) -> SomeException -> IO a-real_handler exit se@(SomeException exn) = do- flushStdHandles -- before any error output- case cast exn of- Just StackOverflow -> do- reportStackOverflow- exit 2-- Just UserInterrupt -> exitInterrupted-- _ -> case cast exn of- -- only the main thread gets ExitException exceptions- Just ExitSuccess -> exit 0- Just (ExitFailure n) -> exit n-- -- EPIPE errors received for stdout are ignored (#2699)- _ -> case cast exn of- Just IOError{ ioe_type = ResourceVanished,- ioe_errno = Just ioe,- ioe_handle = Just hdl }- | Errno ioe == ePIPE, hdl == stdout -> exit 0- _ -> do reportError se- exit 1- ---- try to flush stdout/stderr, but don't worry if we fail--- (these handles might have errors, and we don't want to go into--- an infinite loop).-flushStdHandles :: IO ()-flushStdHandles = do- hFlush stdout `catchAny` \_ -> return ()- hFlush stderr `catchAny` \_ -> return ()---- we have to use unsafeCoerce# to get the 'IO a' result type, since the--- compiler doesn't let us declare that as the result type of a foreign export.-safeExit :: Int -> IO a-safeExit r = unsafeCoerce# (shutdownHaskellAndExit $ fromIntegral r)--exitInterrupted :: IO a-exitInterrupted = -#ifdef mingw32_HOST_OS- safeExit 252-#else- -- we must exit via the default action for SIGINT, so that the- -- parent of this process can take appropriate action (see #2301)- unsafeCoerce# (shutdownHaskellAndSignal CONST_SIGINT)--foreign import ccall "shutdownHaskellAndSignal"- shutdownHaskellAndSignal :: CInt -> IO ()-#endif---- NOTE: shutdownHaskellAndExit must be called "safe", because it *can*--- re-enter Haskell land through finalizers.-foreign import ccall "Rts.h shutdownHaskellAndExit"- shutdownHaskellAndExit :: CInt -> IO ()--fastExit :: Int -> IO a-fastExit r = unsafeCoerce# (stg_exit (fromIntegral r))--foreign import ccall "Rts.h stg_exit"- stg_exit :: CInt -> IO ()-\end{code}
@@ -1,224 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ForeignFunctionInterface #-}-{-# OPTIONS -#include "WCsubst.h" #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Unicode--- Copyright : (c) The University of Glasgow, 2003--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC extensions)------ Implementations for the character predicates (isLower, isUpper, etc.)--- and the conversions (toUpper, toLower). The implementation uses--- libunicode on Unix systems if that is available.------------------------------------------------------------------------------------- #hide-module GHC.Unicode (- isAscii, isLatin1, isControl,- isAsciiUpper, isAsciiLower,- isPrint, isSpace, isUpper,- isLower, isAlpha, isDigit,- isOctDigit, isHexDigit, isAlphaNum,- toUpper, toLower, toTitle,- wgencat- ) where--import GHC.Base-import GHC.Real (fromIntegral)-import Foreign.C.Types (CInt(..))--#include "HsBaseConfig.h"---- | Selects the first 128 characters of the Unicode character set,--- corresponding to the ASCII character set.-isAscii :: Char -> Bool-isAscii c = c < '\x80'---- | Selects the first 256 characters of the Unicode character set,--- corresponding to the ISO 8859-1 (Latin-1) character set.-isLatin1 :: Char -> Bool-isLatin1 c = c <= '\xff'---- | Selects ASCII lower-case letters,--- i.e. characters satisfying both 'isAscii' and 'isLower'.-isAsciiLower :: Char -> Bool-isAsciiLower c = c >= 'a' && c <= 'z'---- | Selects ASCII upper-case letters,--- i.e. characters satisfying both 'isAscii' and 'isUpper'.-isAsciiUpper :: Char -> Bool-isAsciiUpper c = c >= 'A' && c <= 'Z'---- | Selects control characters, which are the non-printing characters of--- the Latin-1 subset of Unicode.-isControl :: Char -> Bool---- | Selects printable Unicode characters--- (letters, numbers, marks, punctuation, symbols and spaces).-isPrint :: Char -> Bool---- | Returns 'True' for any Unicode space character, and the control--- characters @\\t@, @\\n@, @\\r@, @\\f@, @\\v@.-isSpace :: Char -> Bool--- isSpace includes non-breaking space--- Done with explicit equalities both for efficiency, and to avoid a tiresome--- recursion with GHC.List elem-isSpace c = c == ' ' ||- c == '\t' ||- c == '\n' ||- c == '\r' ||- c == '\f' ||- c == '\v' ||- c == '\xa0' ||- iswspace (fromIntegral (ord c)) /= 0---- | Selects upper-case or title-case alphabetic Unicode characters (letters).--- Title case is used by a small number of letter ligatures like the--- single-character form of /Lj/.-isUpper :: Char -> Bool---- | Selects lower-case alphabetic Unicode characters (letters).-isLower :: Char -> Bool---- | Selects alphabetic Unicode characters (lower-case, upper-case and--- title-case letters, plus letters of caseless scripts and modifiers letters).--- This function is equivalent to 'Data.Char.isLetter'.-isAlpha :: Char -> Bool---- | Selects alphabetic or numeric digit Unicode characters.------ Note that numeric digits outside the ASCII range are selected by this--- function but not by 'isDigit'. Such digits may be part of identifiers--- but are not used by the printer and reader to represent numbers.-isAlphaNum :: Char -> Bool---- | Selects ASCII digits, i.e. @\'0\'@..@\'9\'@.-isDigit :: Char -> Bool-isDigit c = c >= '0' && c <= '9'---- | Selects ASCII octal digits, i.e. @\'0\'@..@\'7\'@.-isOctDigit :: Char -> Bool-isOctDigit c = c >= '0' && c <= '7'---- | Selects ASCII hexadecimal digits,--- i.e. @\'0\'@..@\'9\'@, @\'a\'@..@\'f\'@, @\'A\'@..@\'F\'@.-isHexDigit :: Char -> Bool-isHexDigit c = isDigit c || c >= 'A' && c <= 'F' ||- c >= 'a' && c <= 'f'---- | Convert a letter to the corresponding upper-case letter, if any.--- Any other character is returned unchanged.-toUpper :: Char -> Char---- | Convert a letter to the corresponding lower-case letter, if any.--- Any other character is returned unchanged.-toLower :: Char -> Char---- | Convert a letter to the corresponding title-case or upper-case--- letter, if any. (Title case differs from upper case only for a small--- number of ligature letters.)--- Any other character is returned unchanged.-toTitle :: Char -> Char---- -------------------------------------------------------------------------------- Implementation with the supplied auto-generated Unicode character properties--- table (default)--#if 1---- Regardless of the O/S and Library, use the functions contained in WCsubst.c--isAlpha c = iswalpha (fromIntegral (ord c)) /= 0-isAlphaNum c = iswalnum (fromIntegral (ord c)) /= 0---isSpace c = iswspace (fromIntegral (ord c)) /= 0-isControl c = iswcntrl (fromIntegral (ord c)) /= 0-isPrint c = iswprint (fromIntegral (ord c)) /= 0-isUpper c = iswupper (fromIntegral (ord c)) /= 0-isLower c = iswlower (fromIntegral (ord c)) /= 0--toLower c = chr (fromIntegral (towlower (fromIntegral (ord c))))-toUpper c = chr (fromIntegral (towupper (fromIntegral (ord c))))-toTitle c = chr (fromIntegral (towtitle (fromIntegral (ord c))))--foreign import ccall unsafe "u_iswalpha"- iswalpha :: CInt -> CInt--foreign import ccall unsafe "u_iswalnum"- iswalnum :: CInt -> CInt--foreign import ccall unsafe "u_iswcntrl"- iswcntrl :: CInt -> CInt--foreign import ccall unsafe "u_iswspace"- iswspace :: CInt -> CInt--foreign import ccall unsafe "u_iswprint"- iswprint :: CInt -> CInt--foreign import ccall unsafe "u_iswlower"- iswlower :: CInt -> CInt--foreign import ccall unsafe "u_iswupper"- iswupper :: CInt -> CInt--foreign import ccall unsafe "u_towlower"- towlower :: CInt -> CInt--foreign import ccall unsafe "u_towupper"- towupper :: CInt -> CInt--foreign import ccall unsafe "u_towtitle"- towtitle :: CInt -> CInt--foreign import ccall unsafe "u_gencat"- wgencat :: CInt -> CInt---- -------------------------------------------------------------------------------- No libunicode, so fall back to the ASCII-only implementation (never used, indeed)--#else--isControl c = c < ' ' || c >= '\DEL' && c <= '\x9f'-isPrint c = not (isControl c)---- The upper case ISO characters have the multiplication sign dumped--- randomly in the middle of the range. Go figure.-isUpper c = c >= 'A' && c <= 'Z' ||- c >= '\xC0' && c <= '\xD6' ||- c >= '\xD8' && c <= '\xDE'--- The lower case ISO characters have the division sign dumped--- randomly in the middle of the range. Go figure.-isLower c = c >= 'a' && c <= 'z' ||- c >= '\xDF' && c <= '\xF6' ||- c >= '\xF8' && c <= '\xFF'--isAlpha c = isLower c || isUpper c-isAlphaNum c = isAlpha c || isDigit c---- Case-changing operations--toUpper c@(C# c#)- | isAsciiLower c = C# (chr# (ord# c# -# 32#))- | isAscii c = c- -- fall-through to the slower stuff.- | isLower c && c /= '\xDF' && c /= '\xFF'- = unsafeChr (ord c `minusInt` ord 'a' `plusInt` ord 'A')- | otherwise- = c---toLower c@(C# c#)- | isAsciiUpper c = C# (chr# (ord# c# +# 32#))- | isAscii c = c- | isUpper c = unsafeChr (ord c `minusInt` ord 'A' `plusInt` ord 'a')- | otherwise = c--#endif-
@@ -1,20 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}--module GHC.Unicode where--import GHC.Types--isAscii :: Char -> Bool-isLatin1 :: Char -> Bool-isControl :: Char -> Bool-isPrint :: Char -> Bool-isSpace :: Char -> Bool-isUpper :: Char -> Bool-isLower :: Char -> Bool-isAlpha :: Char -> Bool-isDigit :: Char -> Bool-isOctDigit :: Char -> Bool-isHexDigit :: Char -> Bool-isAlphaNum :: Char -> Bool-
@@ -1,148 +0,0 @@-\begin{code}-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , BangPatterns- , MagicHash- , UnboxedTuples- , DeriveDataTypeable- , StandaloneDeriving- #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Weak--- Copyright : (c) The University of Glasgow, 1998-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Weak pointers.------------------------------------------------------------------------------------- #hide-module GHC.Weak (- Weak(..),- mkWeak,- deRefWeak,- finalize,- runFinalizerBatch- ) where--import GHC.Base-import Data.Maybe-import Data.Typeable--{-|-A weak pointer object with a key and a value. The value has type @v@.--A weak pointer expresses a relationship between two objects, the-/key/ and the /value/: if the key is considered to be alive by the-garbage collector, then the value is also alive. A reference from-the value to the key does /not/ keep the key alive.--A weak pointer may also have a finalizer of type @IO ()@; if it does,-then the finalizer will be run at most once, at a time after the key-has become unreachable by the program (\"dead\"). The storage manager-attempts to run the finalizer(s) for an object soon after the object-dies, but promptness is not guaranteed. --It is not guaranteed that a finalizer will eventually run, and no-attempt is made to run outstanding finalizers when the program exits.-Therefore finalizers should not be relied on to clean up resources --other methods (eg. exception handlers) should be employed, possibly in-addition to finalisers.--References from the finalizer to the key are treated in the same way-as references from the value to the key: they do not keep the key-alive. A finalizer may therefore ressurrect the key, perhaps by-storing it in the same data structure.--The finalizer, and the relationship between the key and the value,-exist regardless of whether the program keeps a reference to the-'Weak' object or not.--There may be multiple weak pointers with the same key. In this-case, the finalizers for each of these weak pointers will all be-run in some arbitrary order, or perhaps concurrently, when the key-dies. If the programmer specifies a finalizer that assumes it has-the only reference to an object (for example, a file that it wishes-to close), then the programmer must ensure that there is only one-such finalizer.--If there are no other threads to run, the runtime system will check-for runnable finalizers before declaring the system to be deadlocked.--}-data Weak v = Weak (Weak# v)--#include "Typeable.h"-INSTANCE_TYPEABLE1(Weak,weakTc,"Weak")---- | Establishes a weak pointer to @k@, with value @v@ and a finalizer.------ This is the most general interface for building a weak pointer.----mkWeak :: k -- ^ key- -> v -- ^ value- -> Maybe (IO ()) -- ^ finalizer- -> IO (Weak v) -- ^ returns: a weak pointer object--mkWeak key val (Just finalizer) = IO $ \s ->- case mkWeak# key val finalizer s of { (# s1, w #) -> (# s1, Weak w #) }-mkWeak key val Nothing = IO $ \s ->- case mkWeak# key val (unsafeCoerce# 0#) s of { (# s1, w #) -> (# s1, Weak w #) }--{-|-Dereferences a weak pointer. If the key is still alive, then-@'Just' v@ is returned (where @v@ is the /value/ in the weak pointer), otherwise-'Nothing' is returned.--The return value of 'deRefWeak' depends on when the garbage collector-runs, hence it is in the 'IO' monad.--}-deRefWeak :: Weak v -> IO (Maybe v)-deRefWeak (Weak w) = IO $ \s ->- case deRefWeak# w s of- (# s1, flag, p #) -> case flag of- 0# -> (# s1, Nothing #)- _ -> (# s1, Just p #)---- | Causes a the finalizer associated with a weak pointer to be run--- immediately.-finalize :: Weak v -> IO ()-finalize (Weak w) = IO $ \s ->- case finalizeWeak# w s of- (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finaliser- (# s1, _, f #) -> f s1--{--Instance Eq (Weak v) where- (Weak w1) == (Weak w2) = w1 `sameWeak#` w2--}----- run a batch of finalizers from the garbage collector. We're given --- an array of finalizers and the length of the array, and we just--- call each one in turn.------ the IO primitives are inlined by hand here to get the optimal--- code (sigh) --SDM.--runFinalizerBatch :: Int -> Array# (IO ()) -> IO ()-runFinalizerBatch (I# n) arr = - let go m = IO $ \s ->- case m of - 0# -> (# s, () #)- _ -> let !m' = m -# 1# in- case indexArray# arr m' of { (# io #) -> - case unIO io s of { (# s', _ #) -> - unIO (go m') s'- }}- in- go n--\end{code}
@@ -1,48 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude, ForeignFunctionInterface #-}--------------------------------------------------------------------------------- |--- Module : GHC.Windows--- Copyright : (c) The University of Glasgow, 2009--- License : see libraries/base/LICENSE--- --- Maintainer : libraries@haskell.org--- Stability : internal--- Portability : non-portable------ Windows functionality used by several modules.------ ToDo: this just duplicates part of System.Win32.Types, which isn't--- available yet. We should move some Win32 functionality down here,--- maybe as part of the grand reorganisation of the base package...-----------------------------------------------------------------------------------module GHC.Windows (- HANDLE, DWORD, LPTSTR, iNFINITE,- throwGetLastError, c_maperrno- ) where--import GHC.Base-import GHC.Ptr--import Data.Word--import Foreign.C.Error (throwErrno)-import Foreign.C.Types---type HANDLE = Ptr ()-type DWORD = Word32--type LPTSTR = Ptr CWchar--iNFINITE :: DWORD-iNFINITE = 0xFFFFFFFF -- urgh--throwGetLastError :: String -> IO a-throwGetLastError where_from = c_maperrno >> throwErrno where_from--foreign import ccall unsafe "maperrno" -- in Win32Utils.c- c_maperrno :: IO ()-
@@ -1,856 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, BangPatterns, MagicHash #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : GHC.Word--- Copyright : (c) The University of Glasgow, 1997-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (GHC Extensions)------ Sized unsigned integral types: 'Word', 'Word8', 'Word16', 'Word32', and--- 'Word64'.-----------------------------------------------------------------------------------#include "MachDeps.h"---- #hide-module GHC.Word (- Word(..), Word8(..), Word16(..), Word32(..), Word64(..),- uncheckedShiftL64#,- uncheckedShiftRL64#- ) where--import Data.Bits--#if WORD_SIZE_IN_BITS < 64-import GHC.IntWord64-#endif--import GHC.Base-import GHC.Enum-import GHC.Num-import GHC.Real-import GHC.Read-import GHC.Arr-import GHC.Show-import GHC.Err-import GHC.Float () -- for RealFrac methods----------------------------------------------------------------------------- type Word----------------------------------------------------------------------------- |A 'Word' is an unsigned integral type, with the same size as 'Int'.-data Word = W# Word# deriving (Eq, Ord)--instance Show Word where- showsPrec _ (W# w) = showWord w--showWord :: Word# -> ShowS-showWord w# cs- | w# `ltWord#` 10## = C# (chr# (ord# '0'# +# word2Int# w#)) : cs- | otherwise = case chr# (ord# '0'# +# word2Int# (w# `remWord#` 10##)) of- c# ->- showWord (w# `quotWord#` 10##) (C# c# : cs)--instance Num Word where- (W# x#) + (W# y#) = W# (x# `plusWord#` y#)- (W# x#) - (W# y#) = W# (x# `minusWord#` y#)- (W# x#) * (W# y#) = W# (x# `timesWord#` y#)- negate (W# x#) = W# (int2Word# (negateInt# (word2Int# x#)))- abs x = x- signum 0 = 0- signum _ = 1- fromInteger i = W# (integerToWord i)--instance Real Word where- toRational x = toInteger x % 1--instance Enum Word where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Word"- pred x- | x /= minBound = x - 1- | otherwise = predError "Word"- toEnum i@(I# i#)- | i >= 0 = W# (int2Word# i#)- | otherwise = toEnumError "Word" i (minBound::Word, maxBound::Word)- fromEnum x@(W# x#)- | x <= fromIntegral (maxBound::Int)- = I# (word2Int# x#)- | otherwise = fromEnumError "Word" x- enumFrom = integralEnumFrom- enumFromThen = integralEnumFromThen- enumFromTo = integralEnumFromTo- enumFromThenTo = integralEnumFromThenTo--instance Integral Word where- quot (W# x#) y@(W# y#)- | y /= 0 = W# (x# `quotWord#` y#)- | otherwise = divZeroError- rem (W# x#) y@(W# y#)- | y /= 0 = W# (x# `remWord#` y#)- | otherwise = divZeroError- div (W# x#) y@(W# y#)- | y /= 0 = W# (x# `quotWord#` y#)- | otherwise = divZeroError- mod (W# x#) y@(W# y#)- | y /= 0 = W# (x# `remWord#` y#)- | otherwise = divZeroError- quotRem (W# x#) y@(W# y#)- | y /= 0 = (W# (x# `quotWord#` y#), W# (x# `remWord#` y#))- | otherwise = divZeroError- divMod (W# x#) y@(W# y#)- | y /= 0 = (W# (x# `quotWord#` y#), W# (x# `remWord#` y#))- | otherwise = divZeroError- toInteger (W# x#)- | i# >=# 0# = smallInteger i#- | otherwise = wordToInteger x#- where- !i# = word2Int# x#--instance Bounded Word where- minBound = 0-- -- use unboxed literals for maxBound, because GHC doesn't optimise- -- (fromInteger 0xffffffff :: Word).-#if WORD_SIZE_IN_BITS == 32- maxBound = W# (int2Word# 0xFFFFFFFF#)-#else- maxBound = W# (int2Word# 0xFFFFFFFFFFFFFFFF#)-#endif--instance Ix Word where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral (i - m)- inRange (m,n) i = m <= i && i <= n--instance Read Word where- readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]--instance Bits Word where- {-# INLINE shift #-}-- (W# x#) .&. (W# y#) = W# (x# `and#` y#)- (W# x#) .|. (W# y#) = W# (x# `or#` y#)- (W# x#) `xor` (W# y#) = W# (x# `xor#` y#)- complement (W# x#) = W# (x# `xor#` mb#)- where !(W# mb#) = maxBound- (W# x#) `shift` (I# i#)- | i# >=# 0# = W# (x# `shiftL#` i#)- | otherwise = W# (x# `shiftRL#` negateInt# i#)- (W# x#) `shiftL` (I# i#) = W# (x# `shiftL#` i#)- (W# x#) `unsafeShiftL` (I# i#) = W# (x# `uncheckedShiftL#` i#)- (W# x#) `shiftR` (I# i#) = W# (x# `shiftRL#` i#)- (W# x#) `unsafeShiftR` (I# i#) = W# (x# `uncheckedShiftRL#` i#)- (W# x#) `rotate` (I# i#)- | i'# ==# 0# = W# x#- | otherwise = W# ((x# `uncheckedShiftL#` i'#) `or#` (x# `uncheckedShiftRL#` (wsib -# i'#)))- where- !i'# = word2Int# (int2Word# i# `and#` int2Word# (wsib -# 1#))- !wsib = WORD_SIZE_IN_BITS# {- work around preprocessor problem (??) -}- bitSize _ = WORD_SIZE_IN_BITS- isSigned _ = False- popCount (W# x#) = I# (word2Int# (popCnt# x#))--{-# RULES-"fromIntegral/Int->Word" fromIntegral = \(I# x#) -> W# (int2Word# x#)-"fromIntegral/Word->Int" fromIntegral = \(W# x#) -> I# (word2Int# x#)-"fromIntegral/Word->Word" fromIntegral = id :: Word -> Word- #-}---- No RULES for RealFrac unfortunately.--- Going through Int isn't possible because Word's range is not--- included in Int's, going through Integer may or may not be slower.----------------------------------------------------------------------------- type Word8----------------------------------------------------------------------------- Word8 is represented in the same way as Word. Operations may assume--- and must ensure that it holds only values from its logical range.--data Word8 = W8# Word# deriving (Eq, Ord)--- ^ 8-bit unsigned integer type--instance Show Word8 where- showsPrec p x = showsPrec p (fromIntegral x :: Int)--instance Num Word8 where- (W8# x#) + (W8# y#) = W8# (narrow8Word# (x# `plusWord#` y#))- (W8# x#) - (W8# y#) = W8# (narrow8Word# (x# `minusWord#` y#))- (W8# x#) * (W8# y#) = W8# (narrow8Word# (x# `timesWord#` y#))- negate (W8# x#) = W8# (narrow8Word# (int2Word# (negateInt# (word2Int# x#))))- abs x = x- signum 0 = 0- signum _ = 1- fromInteger i = W8# (narrow8Word# (integerToWord i))--instance Real Word8 where- toRational x = toInteger x % 1--instance Enum Word8 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Word8"- pred x- | x /= minBound = x - 1- | otherwise = predError "Word8"- toEnum i@(I# i#)- | i >= 0 && i <= fromIntegral (maxBound::Word8)- = W8# (int2Word# i#)- | otherwise = toEnumError "Word8" i (minBound::Word8, maxBound::Word8)- fromEnum (W8# x#) = I# (word2Int# x#)- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen--instance Integral Word8 where- quot (W8# x#) y@(W8# y#)- | y /= 0 = W8# (x# `quotWord#` y#)- | otherwise = divZeroError- rem (W8# x#) y@(W8# y#)- | y /= 0 = W8# (x# `remWord#` y#)- | otherwise = divZeroError- div (W8# x#) y@(W8# y#)- | y /= 0 = W8# (x# `quotWord#` y#)- | otherwise = divZeroError- mod (W8# x#) y@(W8# y#)- | y /= 0 = W8# (x# `remWord#` y#)- | otherwise = divZeroError- quotRem (W8# x#) y@(W8# y#)- | y /= 0 = (W8# (x# `quotWord#` y#), W8# (x# `remWord#` y#))- | otherwise = divZeroError- divMod (W8# x#) y@(W8# y#)- | y /= 0 = (W8# (x# `quotWord#` y#), W8# (x# `remWord#` y#))- | otherwise = divZeroError- toInteger (W8# x#) = smallInteger (word2Int# x#)--instance Bounded Word8 where- minBound = 0- maxBound = 0xFF--instance Ix Word8 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral (i - m)- inRange (m,n) i = m <= i && i <= n--instance Read Word8 where- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]--instance Bits Word8 where- {-# INLINE shift #-}-- (W8# x#) .&. (W8# y#) = W8# (x# `and#` y#)- (W8# x#) .|. (W8# y#) = W8# (x# `or#` y#)- (W8# x#) `xor` (W8# y#) = W8# (x# `xor#` y#)- complement (W8# x#) = W8# (x# `xor#` mb#)- where !(W8# mb#) = maxBound- (W8# x#) `shift` (I# i#)- | i# >=# 0# = W8# (narrow8Word# (x# `shiftL#` i#))- | otherwise = W8# (x# `shiftRL#` negateInt# i#)- (W8# x#) `shiftL` (I# i#) = W8# (narrow8Word# (x# `shiftL#` i#))- (W8# x#) `unsafeShiftL` (I# i#) =- W8# (narrow8Word# (x# `uncheckedShiftL#` i#))- (W8# x#) `shiftR` (I# i#) = W8# (x# `shiftRL#` i#)- (W8# x#) `unsafeShiftR` (I# i#) = W8# (x# `uncheckedShiftRL#` i#)- (W8# x#) `rotate` (I# i#)- | i'# ==# 0# = W8# x#- | otherwise = W8# (narrow8Word# ((x# `uncheckedShiftL#` i'#) `or#`- (x# `uncheckedShiftRL#` (8# -# i'#))))- where- !i'# = word2Int# (int2Word# i# `and#` int2Word# 7#)- bitSize _ = 8- isSigned _ = False- popCount (W8# x#) = I# (word2Int# (popCnt8# x#))--{-# RULES-"fromIntegral/Word8->Word8" fromIntegral = id :: Word8 -> Word8-"fromIntegral/Word8->Integer" fromIntegral = toInteger :: Word8 -> Integer-"fromIntegral/a->Word8" fromIntegral = \x -> case fromIntegral x of W# x# -> W8# (narrow8Word# x#)-"fromIntegral/Word8->a" fromIntegral = \(W8# x#) -> fromIntegral (W# x#)- #-}--{-# RULES-"properFraction/Float->(Word8,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Word8) n, y) }-"truncate/Float->Word8"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Word8) (truncate x)-"floor/Float->Word8"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Word8) (floor x)-"ceiling/Float->Word8"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Word8) (ceiling x)-"round/Float->Word8"- forall x. round (x :: Float) = (fromIntegral :: Int -> Word8) (round x)- #-}--{-# RULES-"properFraction/Double->(Word8,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Word8) n, y) }-"truncate/Double->Word8"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Word8) (truncate x)-"floor/Double->Word8"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Word8) (floor x)-"ceiling/Double->Word8"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Word8) (ceiling x)-"round/Double->Word8"- forall x. round (x :: Double) = (fromIntegral :: Int -> Word8) (round x)- #-}----------------------------------------------------------------------------- type Word16----------------------------------------------------------------------------- Word16 is represented in the same way as Word. Operations may assume--- and must ensure that it holds only values from its logical range.--data Word16 = W16# Word# deriving (Eq, Ord)--- ^ 16-bit unsigned integer type--instance Show Word16 where- showsPrec p x = showsPrec p (fromIntegral x :: Int)--instance Num Word16 where- (W16# x#) + (W16# y#) = W16# (narrow16Word# (x# `plusWord#` y#))- (W16# x#) - (W16# y#) = W16# (narrow16Word# (x# `minusWord#` y#))- (W16# x#) * (W16# y#) = W16# (narrow16Word# (x# `timesWord#` y#))- negate (W16# x#) = W16# (narrow16Word# (int2Word# (negateInt# (word2Int# x#))))- abs x = x- signum 0 = 0- signum _ = 1- fromInteger i = W16# (narrow16Word# (integerToWord i))--instance Real Word16 where- toRational x = toInteger x % 1--instance Enum Word16 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Word16"- pred x- | x /= minBound = x - 1- | otherwise = predError "Word16"- toEnum i@(I# i#)- | i >= 0 && i <= fromIntegral (maxBound::Word16)- = W16# (int2Word# i#)- | otherwise = toEnumError "Word16" i (minBound::Word16, maxBound::Word16)- fromEnum (W16# x#) = I# (word2Int# x#)- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen--instance Integral Word16 where- quot (W16# x#) y@(W16# y#)- | y /= 0 = W16# (x# `quotWord#` y#)- | otherwise = divZeroError- rem (W16# x#) y@(W16# y#)- | y /= 0 = W16# (x# `remWord#` y#)- | otherwise = divZeroError- div (W16# x#) y@(W16# y#)- | y /= 0 = W16# (x# `quotWord#` y#)- | otherwise = divZeroError- mod (W16# x#) y@(W16# y#)- | y /= 0 = W16# (x# `remWord#` y#)- | otherwise = divZeroError- quotRem (W16# x#) y@(W16# y#)- | y /= 0 = (W16# (x# `quotWord#` y#), W16# (x# `remWord#` y#))- | otherwise = divZeroError- divMod (W16# x#) y@(W16# y#)- | y /= 0 = (W16# (x# `quotWord#` y#), W16# (x# `remWord#` y#))- | otherwise = divZeroError- toInteger (W16# x#) = smallInteger (word2Int# x#)--instance Bounded Word16 where- minBound = 0- maxBound = 0xFFFF--instance Ix Word16 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral (i - m)- inRange (m,n) i = m <= i && i <= n--instance Read Word16 where- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]--instance Bits Word16 where- {-# INLINE shift #-}-- (W16# x#) .&. (W16# y#) = W16# (x# `and#` y#)- (W16# x#) .|. (W16# y#) = W16# (x# `or#` y#)- (W16# x#) `xor` (W16# y#) = W16# (x# `xor#` y#)- complement (W16# x#) = W16# (x# `xor#` mb#)- where !(W16# mb#) = maxBound- (W16# x#) `shift` (I# i#)- | i# >=# 0# = W16# (narrow16Word# (x# `shiftL#` i#))- | otherwise = W16# (x# `shiftRL#` negateInt# i#)- (W16# x#) `shiftL` (I# i#) = W16# (narrow16Word# (x# `shiftL#` i#))- (W16# x#) `unsafeShiftL` (I# i#) =- W16# (narrow16Word# (x# `uncheckedShiftL#` i#))- (W16# x#) `shiftR` (I# i#) = W16# (x# `shiftRL#` i#)- (W16# x#) `unsafeShiftR` (I# i#) = W16# (x# `uncheckedShiftRL#` i#)- (W16# x#) `rotate` (I# i#)- | i'# ==# 0# = W16# x#- | otherwise = W16# (narrow16Word# ((x# `uncheckedShiftL#` i'#) `or#`- (x# `uncheckedShiftRL#` (16# -# i'#))))- where- !i'# = word2Int# (int2Word# i# `and#` int2Word# 15#)- bitSize _ = 16- isSigned _ = False- popCount (W16# x#) = I# (word2Int# (popCnt16# x#))--{-# RULES-"fromIntegral/Word8->Word16" fromIntegral = \(W8# x#) -> W16# x#-"fromIntegral/Word16->Word16" fromIntegral = id :: Word16 -> Word16-"fromIntegral/Word16->Integer" fromIntegral = toInteger :: Word16 -> Integer-"fromIntegral/a->Word16" fromIntegral = \x -> case fromIntegral x of W# x# -> W16# (narrow16Word# x#)-"fromIntegral/Word16->a" fromIntegral = \(W16# x#) -> fromIntegral (W# x#)- #-}--{-# RULES-"properFraction/Float->(Word16,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Word16) n, y) }-"truncate/Float->Word16"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Word16) (truncate x)-"floor/Float->Word16"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Word16) (floor x)-"ceiling/Float->Word16"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Word16) (ceiling x)-"round/Float->Word16"- forall x. round (x :: Float) = (fromIntegral :: Int -> Word16) (round x)- #-}--{-# RULES-"properFraction/Double->(Word16,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Word16) n, y) }-"truncate/Double->Word16"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Word16) (truncate x)-"floor/Double->Word16"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Word16) (floor x)-"ceiling/Double->Word16"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Word16) (ceiling x)-"round/Double->Word16"- forall x. round (x :: Double) = (fromIntegral :: Int -> Word16) (round x)- #-}----------------------------------------------------------------------------- type Word32----------------------------------------------------------------------------- Word32 is represented in the same way as Word.-#if WORD_SIZE_IN_BITS > 32--- Operations may assume and must ensure that it holds only values--- from its logical range.---- We can use rewrite rules for the RealFrac methods--{-# RULES-"properFraction/Float->(Word32,Float)"- forall x. properFraction (x :: Float) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Word32) n, y) }-"truncate/Float->Word32"- forall x. truncate (x :: Float) = (fromIntegral :: Int -> Word32) (truncate x)-"floor/Float->Word32"- forall x. floor (x :: Float) = (fromIntegral :: Int -> Word32) (floor x)-"ceiling/Float->Word32"- forall x. ceiling (x :: Float) = (fromIntegral :: Int -> Word32) (ceiling x)-"round/Float->Word32"- forall x. round (x :: Float) = (fromIntegral :: Int -> Word32) (round x)- #-}--{-# RULES-"properFraction/Double->(Word32,Double)"- forall x. properFraction (x :: Double) =- case properFraction x of {- (n, y) -> ((fromIntegral :: Int -> Word32) n, y) }-"truncate/Double->Word32"- forall x. truncate (x :: Double) = (fromIntegral :: Int -> Word32) (truncate x)-"floor/Double->Word32"- forall x. floor (x :: Double) = (fromIntegral :: Int -> Word32) (floor x)-"ceiling/Double->Word32"- forall x. ceiling (x :: Double) = (fromIntegral :: Int -> Word32) (ceiling x)-"round/Double->Word32"- forall x. round (x :: Double) = (fromIntegral :: Int -> Word32) (round x)- #-}--#endif--data Word32 = W32# Word# deriving (Eq, Ord)--- ^ 32-bit unsigned integer type--instance Num Word32 where- (W32# x#) + (W32# y#) = W32# (narrow32Word# (x# `plusWord#` y#))- (W32# x#) - (W32# y#) = W32# (narrow32Word# (x# `minusWord#` y#))- (W32# x#) * (W32# y#) = W32# (narrow32Word# (x# `timesWord#` y#))- negate (W32# x#) = W32# (narrow32Word# (int2Word# (negateInt# (word2Int# x#))))- abs x = x- signum 0 = 0- signum _ = 1- fromInteger i = W32# (narrow32Word# (integerToWord i))--instance Enum Word32 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Word32"- pred x- | x /= minBound = x - 1- | otherwise = predError "Word32"- toEnum i@(I# i#)- | i >= 0-#if WORD_SIZE_IN_BITS > 32- && i <= fromIntegral (maxBound::Word32)-#endif- = W32# (int2Word# i#)- | otherwise = toEnumError "Word32" i (minBound::Word32, maxBound::Word32)-#if WORD_SIZE_IN_BITS == 32- fromEnum x@(W32# x#)- | x <= fromIntegral (maxBound::Int)- = I# (word2Int# x#)- | otherwise = fromEnumError "Word32" x- enumFrom = integralEnumFrom- enumFromThen = integralEnumFromThen- enumFromTo = integralEnumFromTo- enumFromThenTo = integralEnumFromThenTo-#else- fromEnum (W32# x#) = I# (word2Int# x#)- enumFrom = boundedEnumFrom- enumFromThen = boundedEnumFromThen-#endif--instance Integral Word32 where- quot (W32# x#) y@(W32# y#)- | y /= 0 = W32# (x# `quotWord#` y#)- | otherwise = divZeroError- rem (W32# x#) y@(W32# y#)- | y /= 0 = W32# (x# `remWord#` y#)- | otherwise = divZeroError- div (W32# x#) y@(W32# y#)- | y /= 0 = W32# (x# `quotWord#` y#)- | otherwise = divZeroError- mod (W32# x#) y@(W32# y#)- | y /= 0 = W32# (x# `remWord#` y#)- | otherwise = divZeroError- quotRem (W32# x#) y@(W32# y#)- | y /= 0 = (W32# (x# `quotWord#` y#), W32# (x# `remWord#` y#))- | otherwise = divZeroError- divMod (W32# x#) y@(W32# y#)- | y /= 0 = (W32# (x# `quotWord#` y#), W32# (x# `remWord#` y#))- | otherwise = divZeroError- toInteger (W32# x#)-#if WORD_SIZE_IN_BITS == 32- | i# >=# 0# = smallInteger i#- | otherwise = wordToInteger x#- where- !i# = word2Int# x#-#else- = smallInteger (word2Int# x#)-#endif--instance Bits Word32 where- {-# INLINE shift #-}-- (W32# x#) .&. (W32# y#) = W32# (x# `and#` y#)- (W32# x#) .|. (W32# y#) = W32# (x# `or#` y#)- (W32# x#) `xor` (W32# y#) = W32# (x# `xor#` y#)- complement (W32# x#) = W32# (x# `xor#` mb#)- where !(W32# mb#) = maxBound- (W32# x#) `shift` (I# i#)- | i# >=# 0# = W32# (narrow32Word# (x# `shiftL#` i#))- | otherwise = W32# (x# `shiftRL#` negateInt# i#)- (W32# x#) `shiftL` (I# i#) = W32# (narrow32Word# (x# `shiftL#` i#))- (W32# x#) `unsafeShiftL` (I# i#) =- W32# (narrow32Word# (x# `uncheckedShiftL#` i#))- (W32# x#) `shiftR` (I# i#) = W32# (x# `shiftRL#` i#)- (W32# x#) `unsafeShiftR` (I# i#) = W32# (x# `uncheckedShiftRL#` i#)- (W32# x#) `rotate` (I# i#)- | i'# ==# 0# = W32# x#- | otherwise = W32# (narrow32Word# ((x# `uncheckedShiftL#` i'#) `or#`- (x# `uncheckedShiftRL#` (32# -# i'#))))- where- !i'# = word2Int# (int2Word# i# `and#` int2Word# 31#)- bitSize _ = 32- isSigned _ = False- popCount (W32# x#) = I# (word2Int# (popCnt32# x#))--{-# RULES-"fromIntegral/Word8->Word32" fromIntegral = \(W8# x#) -> W32# x#-"fromIntegral/Word16->Word32" fromIntegral = \(W16# x#) -> W32# x#-"fromIntegral/Word32->Word32" fromIntegral = id :: Word32 -> Word32-"fromIntegral/Word32->Integer" fromIntegral = toInteger :: Word32 -> Integer-"fromIntegral/a->Word32" fromIntegral = \x -> case fromIntegral x of W# x# -> W32# (narrow32Word# x#)-"fromIntegral/Word32->a" fromIntegral = \(W32# x#) -> fromIntegral (W# x#)- #-}--instance Show Word32 where-#if WORD_SIZE_IN_BITS < 33- showsPrec p x = showsPrec p (toInteger x)-#else- showsPrec p x = showsPrec p (fromIntegral x :: Int)-#endif---instance Real Word32 where- toRational x = toInteger x % 1--instance Bounded Word32 where- minBound = 0- maxBound = 0xFFFFFFFF--instance Ix Word32 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral (i - m)- inRange (m,n) i = m <= i && i <= n--instance Read Word32 where -#if WORD_SIZE_IN_BITS < 33- readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]-#else- readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]-#endif----------------------------------------------------------------------------- type Word64---------------------------------------------------------------------------#if WORD_SIZE_IN_BITS < 64--data Word64 = W64# Word64#--- ^ 64-bit unsigned integer type--instance Eq Word64 where- (W64# x#) == (W64# y#) = x# `eqWord64#` y#- (W64# x#) /= (W64# y#) = x# `neWord64#` y#--instance Ord Word64 where- (W64# x#) < (W64# y#) = x# `ltWord64#` y#- (W64# x#) <= (W64# y#) = x# `leWord64#` y#- (W64# x#) > (W64# y#) = x# `gtWord64#` y#- (W64# x#) >= (W64# y#) = x# `geWord64#` y#--instance Num Word64 where- (W64# x#) + (W64# y#) = W64# (int64ToWord64# (word64ToInt64# x# `plusInt64#` word64ToInt64# y#))- (W64# x#) - (W64# y#) = W64# (int64ToWord64# (word64ToInt64# x# `minusInt64#` word64ToInt64# y#))- (W64# x#) * (W64# y#) = W64# (int64ToWord64# (word64ToInt64# x# `timesInt64#` word64ToInt64# y#))- negate (W64# x#) = W64# (int64ToWord64# (negateInt64# (word64ToInt64# x#)))- abs x = x- signum 0 = 0- signum _ = 1- fromInteger i = W64# (integerToWord64 i)--instance Enum Word64 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Word64"- pred x- | x /= minBound = x - 1- | otherwise = predError "Word64"- toEnum i@(I# i#)- | i >= 0 = W64# (wordToWord64# (int2Word# i#))- | otherwise = toEnumError "Word64" i (minBound::Word64, maxBound::Word64)- fromEnum x@(W64# x#)- | x <= fromIntegral (maxBound::Int)- = I# (word2Int# (word64ToWord# x#))- | otherwise = fromEnumError "Word64" x- enumFrom = integralEnumFrom- enumFromThen = integralEnumFromThen- enumFromTo = integralEnumFromTo- enumFromThenTo = integralEnumFromThenTo--instance Integral Word64 where- quot (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `quotWord64#` y#)- | otherwise = divZeroError- rem (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `remWord64#` y#)- | otherwise = divZeroError- div (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `quotWord64#` y#)- | otherwise = divZeroError- mod (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `remWord64#` y#)- | otherwise = divZeroError- quotRem (W64# x#) y@(W64# y#)- | y /= 0 = (W64# (x# `quotWord64#` y#), W64# (x# `remWord64#` y#))- | otherwise = divZeroError- divMod (W64# x#) y@(W64# y#)- | y /= 0 = (W64# (x# `quotWord64#` y#), W64# (x# `remWord64#` y#))- | otherwise = divZeroError- toInteger (W64# x#) = word64ToInteger x#--instance Bits Word64 where- {-# INLINE shift #-}-- (W64# x#) .&. (W64# y#) = W64# (x# `and64#` y#)- (W64# x#) .|. (W64# y#) = W64# (x# `or64#` y#)- (W64# x#) `xor` (W64# y#) = W64# (x# `xor64#` y#)- complement (W64# x#) = W64# (not64# x#)- (W64# x#) `shift` (I# i#)- | i# >=# 0# = W64# (x# `shiftL64#` i#)- | otherwise = W64# (x# `shiftRL64#` negateInt# i#)- (W64# x#) `shiftL` (I# i#) = W64# (x# `shiftL64#` i#)- (W64# x#) `unsafeShiftL` (I# i#) = W64# (x# `uncheckedShiftL64#` i#)- (W64# x#) `shiftR` (I# i#) = W64# (x# `shiftRL64#` i#)- (W64# x#) `unsafeShiftR` (I# i#) = W64# (x# `uncheckedShiftRL64#` i#)- (W64# x#) `rotate` (I# i#)- | i'# ==# 0# = W64# x#- | otherwise = W64# ((x# `uncheckedShiftL64#` i'#) `or64#`- (x# `uncheckedShiftRL64#` (64# -# i'#)))- where- !i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)- bitSize _ = 64- isSigned _ = False- popCount (W64# x#) = I# (word2Int# (popCnt64# x#))---- give the 64-bit shift operations the same treatment as the 32-bit--- ones (see GHC.Base), namely we wrap them in tests to catch the--- cases when we're shifting more than 64 bits to avoid unspecified--- behaviour in the C shift operations.--shiftL64#, shiftRL64# :: Word64# -> Int# -> Word64#--a `shiftL64#` b | b >=# 64# = wordToWord64# (int2Word# 0#)- | otherwise = a `uncheckedShiftL64#` b--a `shiftRL64#` b | b >=# 64# = wordToWord64# (int2Word# 0#)- | otherwise = a `uncheckedShiftRL64#` b--{-# RULES-"fromIntegral/Int->Word64" fromIntegral = \(I# x#) -> W64# (int64ToWord64# (intToInt64# x#))-"fromIntegral/Word->Word64" fromIntegral = \(W# x#) -> W64# (wordToWord64# x#)-"fromIntegral/Word64->Int" fromIntegral = \(W64# x#) -> I# (word2Int# (word64ToWord# x#))-"fromIntegral/Word64->Word" fromIntegral = \(W64# x#) -> W# (word64ToWord# x#)-"fromIntegral/Word64->Word64" fromIntegral = id :: Word64 -> Word64- #-}--#else---- Word64 is represented in the same way as Word.--- Operations may assume and must ensure that it holds only values--- from its logical range.--data Word64 = W64# Word# deriving (Eq, Ord)--- ^ 64-bit unsigned integer type--instance Num Word64 where- (W64# x#) + (W64# y#) = W64# (x# `plusWord#` y#)- (W64# x#) - (W64# y#) = W64# (x# `minusWord#` y#)- (W64# x#) * (W64# y#) = W64# (x# `timesWord#` y#)- negate (W64# x#) = W64# (int2Word# (negateInt# (word2Int# x#)))- abs x = x- signum 0 = 0- signum _ = 1- fromInteger i = W64# (integerToWord i)--instance Enum Word64 where- succ x- | x /= maxBound = x + 1- | otherwise = succError "Word64"- pred x- | x /= minBound = x - 1- | otherwise = predError "Word64"- toEnum i@(I# i#)- | i >= 0 = W64# (int2Word# i#)- | otherwise = toEnumError "Word64" i (minBound::Word64, maxBound::Word64)- fromEnum x@(W64# x#)- | x <= fromIntegral (maxBound::Int)- = I# (word2Int# x#)- | otherwise = fromEnumError "Word64" x- enumFrom = integralEnumFrom- enumFromThen = integralEnumFromThen- enumFromTo = integralEnumFromTo- enumFromThenTo = integralEnumFromThenTo--instance Integral Word64 where- quot (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `quotWord#` y#)- | otherwise = divZeroError- rem (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `remWord#` y#)- | otherwise = divZeroError- div (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `quotWord#` y#)- | otherwise = divZeroError- mod (W64# x#) y@(W64# y#)- | y /= 0 = W64# (x# `remWord#` y#)- | otherwise = divZeroError- quotRem (W64# x#) y@(W64# y#)- | y /= 0 = (W64# (x# `quotWord#` y#), W64# (x# `remWord#` y#))- | otherwise = divZeroError- divMod (W64# x#) y@(W64# y#)- | y /= 0 = (W64# (x# `quotWord#` y#), W64# (x# `remWord#` y#))- | otherwise = divZeroError- toInteger (W64# x#)- | i# >=# 0# = smallInteger i#- | otherwise = wordToInteger x#- where- !i# = word2Int# x#--instance Bits Word64 where- {-# INLINE shift #-}-- (W64# x#) .&. (W64# y#) = W64# (x# `and#` y#)- (W64# x#) .|. (W64# y#) = W64# (x# `or#` y#)- (W64# x#) `xor` (W64# y#) = W64# (x# `xor#` y#)- complement (W64# x#) = W64# (x# `xor#` mb#)- where !(W64# mb#) = maxBound- (W64# x#) `shift` (I# i#)- | i# >=# 0# = W64# (x# `shiftL#` i#)- | otherwise = W64# (x# `shiftRL#` negateInt# i#)- (W64# x#) `shiftL` (I# i#) = W64# (x# `shiftL#` i#)- (W64# x#) `unsafeShiftL` (I# i#) = W64# (x# `uncheckedShiftL#` i#)- (W64# x#) `shiftR` (I# i#) = W64# (x# `shiftRL#` i#)- (W64# x#) `unsafeShiftR` (I# i#) = W64# (x# `uncheckedShiftRL#` i#)- (W64# x#) `rotate` (I# i#)- | i'# ==# 0# = W64# x#- | otherwise = W64# ((x# `uncheckedShiftL#` i'#) `or#`- (x# `uncheckedShiftRL#` (64# -# i'#)))- where- !i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)- bitSize _ = 64- isSigned _ = False- popCount (W64# x#) = I# (word2Int# (popCnt64# x#))--{-# RULES-"fromIntegral/a->Word64" fromIntegral = \x -> case fromIntegral x of W# x# -> W64# x#-"fromIntegral/Word64->a" fromIntegral = \(W64# x#) -> fromIntegral (W# x#)- #-}--uncheckedShiftL64# :: Word# -> Int# -> Word#-uncheckedShiftL64# = uncheckedShiftL#--uncheckedShiftRL64# :: Word# -> Int# -> Word#-uncheckedShiftRL64# = uncheckedShiftRL#--#endif--instance Show Word64 where- showsPrec p x = showsPrec p (toInteger x)--instance Real Word64 where- toRational x = toInteger x % 1--instance Bounded Word64 where- minBound = 0- maxBound = 0xFFFFFFFFFFFFFFFF--instance Ix Word64 where- range (m,n) = [m..n]- unsafeIndex (m,_) i = fromIntegral (i - m)- inRange (m,n) i = m <= i && i <= n--instance Read Word64 where- readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]-
@@ -1,83 +0,0 @@-This library (libraries/base) is derived from code from several-sources: -- * Code from the GHC project which is largely (c) The University of- Glasgow, and distributable under a BSD-style license (see below),-- * Code from the Haskell 98 Report which is (c) Simon Peyton Jones- and freely redistributable (but see the full license for- restrictions).-- * Code from the Haskell Foreign Function Interface specification,- which is (c) Manuel M. T. Chakravarty and freely redistributable- (but see the full license for restrictions).--The full text of these licenses is reproduced below. All of the-licenses are BSD-style or compatible.---------------------------------------------------------------------------------The Glasgow Haskell Compiler License--Copyright 2004, The University Court of the University of Glasgow. -All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:--- Redistributions of source code must retain the above copyright notice,-this list of conditions and the following disclaimer.- -- Redistributions in binary form must reproduce the above copyright notice,-this list of conditions and the following disclaimer in the documentation-and/or other materials provided with the distribution.- -- Neither name of the University nor the names of its contributors may be-used to endorse or promote products derived from this software without-specific prior written permission. --THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF-GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE-UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH-DAMAGE.---------------------------------------------------------------------------------Code derived from the document "Report on the Programming Language-Haskell 98", is distributed under the following license:-- Copyright (c) 2002 Simon Peyton Jones-- The authors intend this Report to belong to the entire Haskell- community, and so we grant permission to copy and distribute it for- any purpose, provided that it is reproduced in its entirety,- including this Notice. Modified versions of this Report may also be- copied and distributed for any purpose, provided that the modified- version is clearly presented as such, and that it does not claim to- be a definition of the Haskell 98 Language.---------------------------------------------------------------------------------Code derived from the document "The Haskell 98 Foreign Function-Interface, An Addendum to the Haskell 98 Report" is distributed under-the following license:-- Copyright (c) 2002 Manuel M. T. Chakravarty-- The authors intend this Report to belong to the entire Haskell- community, and so we grant permission to copy and distribute it for- any purpose, provided that it is reproduced in its entirety,- including this Notice. Modified versions of this Report may also be- copied and distributed for any purpose, provided that the modified- version is clearly presented as such, and that it does not claim to- be a definition of the Haskell 98 Foreign Function Interface.-------------------------------------------------------------------------------
@@ -1,221 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}---------------------------------------------------------------------------------- |--- Module : Numeric--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Odds and ends, mostly functions for reading and showing--- 'RealFloat'-like kind of values.-----------------------------------------------------------------------------------module Numeric (-- -- * Showing-- showSigned, -- :: (Real a) => (a -> ShowS) -> Int -> a -> ShowS-- showIntAtBase, -- :: Integral a => a -> (a -> Char) -> a -> ShowS- showInt, -- :: Integral a => a -> ShowS- showHex, -- :: Integral a => a -> ShowS- showOct, -- :: Integral a => a -> ShowS-- showEFloat, -- :: (RealFloat a) => Maybe Int -> a -> ShowS- showFFloat, -- :: (RealFloat a) => Maybe Int -> a -> ShowS- showGFloat, -- :: (RealFloat a) => Maybe Int -> a -> ShowS- showFloat, -- :: (RealFloat a) => a -> ShowS-- floatToDigits, -- :: (RealFloat a) => Integer -> a -> ([Int], Int)-- -- * Reading-- -- | /NB:/ 'readInt' is the \'dual\' of 'showIntAtBase',- -- and 'readDec' is the \`dual\' of 'showInt'.- -- The inconsistent naming is a historical accident.-- readSigned, -- :: (Real a) => ReadS a -> ReadS a-- readInt, -- :: (Integral a) => a -> (Char -> Bool)- -- -> (Char -> Int) -> ReadS a- readDec, -- :: (Integral a) => ReadS a- readOct, -- :: (Integral a) => ReadS a- readHex, -- :: (Integral a) => ReadS a-- readFloat, -- :: (RealFloat a) => ReadS a-- lexDigits, -- :: ReadS String-- -- * Miscellaneous-- fromRat, -- :: (RealFloat a) => Rational -> a-- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Read-import GHC.Real-import GHC.Float-import GHC.Num-import GHC.Show-import Data.Maybe-import Text.ParserCombinators.ReadP( ReadP, readP_to_S, pfail )-import qualified Text.Read.Lex as L-#else-import Data.Char-#endif--#ifdef __HUGS__-import Hugs.Prelude-import Hugs.Numeric-#endif--#ifdef __GLASGOW_HASKELL__--- -------------------------------------------------------------------------------- Reading---- | Reads an /unsigned/ 'Integral' value in an arbitrary base.-readInt :: Num a- => a -- ^ the base- -> (Char -> Bool) -- ^ a predicate distinguishing valid digits in this base- -> (Char -> Int) -- ^ a function converting a valid digit character to an 'Int'- -> ReadS a-readInt base isDigit valDigit = readP_to_S (L.readIntP base isDigit valDigit)---- | Read an unsigned number in octal notation.-readOct :: (Eq a, Num a) => ReadS a-readOct = readP_to_S L.readOctP---- | Read an unsigned number in decimal notation.-readDec :: (Eq a, Num a) => ReadS a-readDec = readP_to_S L.readDecP---- | Read an unsigned number in hexadecimal notation.--- Both upper or lower case letters are allowed.-readHex :: (Eq a, Num a) => ReadS a-readHex = readP_to_S L.readHexP ---- | Reads an /unsigned/ 'RealFrac' value,--- expressed in decimal scientific notation.-readFloat :: RealFrac a => ReadS a-readFloat = readP_to_S readFloatP--readFloatP :: RealFrac a => ReadP a-readFloatP =- do tok <- L.lex- case tok of- L.Rat y -> return (fromRational y)- L.Int i -> return (fromInteger i)- _ -> pfail---- It's turgid to have readSigned work using list comprehensions,--- but it's specified as a ReadS to ReadS transformer--- With a bit of luck no one will use it.---- | Reads a /signed/ 'Real' value, given a reader for an unsigned value.-readSigned :: (Real a) => ReadS a -> ReadS a-readSigned readPos = readParen False read'- where read' r = read'' r ++- (do- ("-",s) <- lex r- (x,t) <- read'' s- return (-x,t))- read'' r = do- (str,s) <- lex r- (n,"") <- readPos str- return (n,s)---- -------------------------------------------------------------------------------- Showing---- | Show /non-negative/ 'Integral' numbers in base 10.-showInt :: Integral a => a -> ShowS-showInt n0 cs0- | n0 < 0 = error "Numeric.showInt: can't show negative numbers"- | otherwise = go n0 cs0- where- go n cs- | n < 10 = case unsafeChr (ord '0' + fromIntegral n) of- c@(C# _) -> c:cs- | otherwise = case unsafeChr (ord '0' + fromIntegral r) of- c@(C# _) -> go q (c:cs)- where- (q,r) = n `quotRem` 10---- Controlling the format and precision of floats. The code that--- implements the formatting itself is in @PrelNum@ to avoid--- mutual module deps.--{-# SPECIALIZE showEFloat ::- Maybe Int -> Float -> ShowS,- Maybe Int -> Double -> ShowS #-}-{-# SPECIALIZE showFFloat ::- Maybe Int -> Float -> ShowS,- Maybe Int -> Double -> ShowS #-}-{-# SPECIALIZE showGFloat ::- Maybe Int -> Float -> ShowS,- Maybe Int -> Double -> ShowS #-}---- | Show a signed 'RealFloat' value--- using scientific (exponential) notation (e.g. @2.45e2@, @1.5e-3@).------ In the call @'showEFloat' digs val@, if @digs@ is 'Nothing',--- the value is shown to full precision; if @digs@ is @'Just' d@,--- then at most @d@ digits after the decimal point are shown.-showEFloat :: (RealFloat a) => Maybe Int -> a -> ShowS---- | Show a signed 'RealFloat' value--- using standard decimal notation (e.g. @245000@, @0.0015@).------ In the call @'showFFloat' digs val@, if @digs@ is 'Nothing',--- the value is shown to full precision; if @digs@ is @'Just' d@,--- then at most @d@ digits after the decimal point are shown.-showFFloat :: (RealFloat a) => Maybe Int -> a -> ShowS---- | Show a signed 'RealFloat' value--- using standard decimal notation for arguments whose absolute value lies --- between @0.1@ and @9,999,999@, and scientific notation otherwise.------ In the call @'showGFloat' digs val@, if @digs@ is 'Nothing',--- the value is shown to full precision; if @digs@ is @'Just' d@,--- then at most @d@ digits after the decimal point are shown.-showGFloat :: (RealFloat a) => Maybe Int -> a -> ShowS--showEFloat d x = showString (formatRealFloat FFExponent d x)-showFFloat d x = showString (formatRealFloat FFFixed d x)-showGFloat d x = showString (formatRealFloat FFGeneric d x)-#endif /* __GLASGOW_HASKELL__ */---- ------------------------------------------------------------------------------ Integer printing functions---- | Shows a /non-negative/ 'Integral' number using the base specified by the--- first argument, and the character representation specified by the second.-showIntAtBase :: (Integral a, Show a) => a -> (Int -> Char) -> a -> ShowS-showIntAtBase base toChr n0 r0- | base <= 1 = error ("Numeric.showIntAtBase: applied to unsupported base " ++ show base)- | n0 < 0 = error ("Numeric.showIntAtBase: applied to negative number " ++ show n0)- | otherwise = showIt (quotRem n0 base) r0- where- showIt (n,d) r = seq c $ -- stricter than necessary- case n of- 0 -> r'- _ -> showIt (quotRem n base) r'- where- c = toChr (fromIntegral d)- r' = c : r---- | Show /non-negative/ 'Integral' numbers in base 16.-showHex :: (Integral a,Show a) => a -> ShowS-showHex = showIntAtBase 16 intToDigit---- | Show /non-negative/ 'Integral' numbers in base 8.-showOct :: (Integral a, Show a) => a -> ShowS-showOct = showIntAtBase 8 intToDigit
@@ -1,194 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, BangPatterns #-}---------------------------------------------------------------------------------- |--- Module : Prelude--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ The Prelude: a standard module imported by default into all Haskell--- modules. For more documentation, see the Haskell 98 Report--- <http://www.haskell.org/onlinereport/>.-----------------------------------------------------------------------------------module Prelude (-- -- * Standard types, classes and related functions-- -- ** Basic data types- Bool(False, True),- (&&), (||), not, otherwise,-- Maybe(Nothing, Just),- maybe,-- Either(Left, Right),- either,-- Ordering(LT, EQ, GT),- Char, String,-- -- *** Tuples- fst, snd, curry, uncurry,--#if defined(__NHC__)- []((:), []), -- Not legal Haskell 98;- -- ... available through built-in syntax- module Data.Tuple, -- Includes tuple types- ()(..), -- Not legal Haskell 98- (->), -- ... available through built-in syntax-#endif-#ifdef __HUGS__- (:), -- Not legal Haskell 98-#endif-- -- ** Basic type classes- Eq((==), (/=)),- Ord(compare, (<), (<=), (>=), (>), max, min),- Enum(succ, pred, toEnum, fromEnum, enumFrom, enumFromThen,- enumFromTo, enumFromThenTo),- Bounded(minBound, maxBound),-- -- ** Numbers-- -- *** Numeric types- Int, Integer, Float, Double,- Rational,-- -- *** Numeric type classes- Num((+), (-), (*), negate, abs, signum, fromInteger),- Real(toRational),- Integral(quot, rem, div, mod, quotRem, divMod, toInteger),- Fractional((/), recip, fromRational),- Floating(pi, exp, log, sqrt, (**), logBase, sin, cos, tan,- asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh),- RealFrac(properFraction, truncate, round, ceiling, floor),- RealFloat(floatRadix, floatDigits, floatRange, decodeFloat,- encodeFloat, exponent, significand, scaleFloat, isNaN,- isInfinite, isDenormalized, isIEEE, isNegativeZero, atan2),-- -- *** Numeric functions- subtract, even, odd, gcd, lcm, (^), (^^),- fromIntegral, realToFrac,-- -- ** Monads and functors- Monad((>>=), (>>), return, fail),- Functor(fmap),- mapM, mapM_, sequence, sequence_, (=<<),-- -- ** Miscellaneous functions- id, const, (.), flip, ($), until,- asTypeOf, error, undefined,- seq, ($!),-- -- * List operations- map, (++), filter,- head, last, tail, init, null, length, (!!),- reverse,- -- ** Reducing lists (folds)- foldl, foldl1, foldr, foldr1,- -- *** Special folds- and, or, any, all,- sum, product,- concat, concatMap,- maximum, minimum,- -- ** Building lists- -- *** Scans- scanl, scanl1, scanr, scanr1,- -- *** Infinite lists- iterate, repeat, replicate, cycle,- -- ** Sublists- take, drop, splitAt, takeWhile, dropWhile, span, break,- -- ** Searching lists- elem, notElem, lookup,- -- ** Zipping and unzipping lists- zip, zip3, zipWith, zipWith3, unzip, unzip3,- -- ** Functions on strings- lines, words, unlines, unwords,-- -- * Converting to and from @String@- -- ** Converting to @String@- ShowS,- Show(showsPrec, showList, show),- shows,- showChar, showString, showParen,- -- ** Converting from @String@- ReadS,- Read(readsPrec, readList),- reads, readParen, read, lex,-- -- * Basic Input and output- IO,- -- ** Simple I\/O operations- -- All I/O functions defined here are character oriented. The- -- treatment of the newline character will vary on different systems.- -- For example, two characters of input, return and linefeed, may- -- read as a single newline character. These functions cannot be- -- used portably for binary I/O.- -- *** Output functions- putChar,- putStr, putStrLn, print,- -- *** Input functions- getChar,- getLine, getContents, interact,- -- *** Files- FilePath,- readFile, writeFile, appendFile, readIO, readLn,- -- ** Exception handling in the I\/O monad- IOError, ioError, userError, catch-- ) where--#ifndef __HUGS__-import Control.Monad-import System.IO-import System.IO.Error-import Data.List-import Data.Either-import Data.Maybe-import Data.Tuple-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import Text.Read-import GHC.Enum-import GHC.Num-import GHC.Real-import GHC.Float-import GHC.Show-import GHC.Err ( undefined )-#endif--#ifdef __HUGS__-import Hugs.Prelude-#endif--#ifndef __HUGS__-infixr 0 $!-#endif---- -------------------------------------------------------------------------------- Miscellaneous functions---- | Strict (call-by-value) application, defined in terms of 'seq'.-($!) :: (a -> b) -> a -> b-#ifdef __GLASGOW_HASKELL__-f $! x = let !vx = x in f vx -- see #2273-#elif !defined(__HUGS__)-f $! x = x `seq` f x-#endif--#ifdef __HADDOCK__--- | The value of @'seq' a b@ is bottom if @a@ is bottom, and otherwise--- equal to @b@. 'seq' is usually introduced to improve performance by--- avoiding unneeded laziness.-seq :: a -> b -> b-seq _ y = y-#endif
@@ -1,6 +0,0 @@-module Main (main) where--import Distribution.Simple--main :: IO ()-main = defaultMainWithHooks defaultUserHooks
@@ -1,186 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NondecreasingIndentation, ForeignFunctionInterface, CApiFFI #-}---------------------------------------------------------------------------------- |--- Module : System.CPUTime--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ The standard CPUTime library.-----------------------------------------------------------------------------------#include "HsFFI.h"-#include "HsBaseConfig.h"--module System.CPUTime - (- getCPUTime, -- :: IO Integer- cpuTimePrecision -- :: Integer- ) where--import Prelude--import Data.Ratio--#ifdef __HUGS__-import Hugs.Time ( getCPUTime, clockTicks )-#endif--#ifdef __NHC__-import CPUTime ( getCPUTime, cpuTimePrecision )-#endif--#ifdef __GLASGOW_HASKELL__-import Foreign.Safe-import Foreign.C-#if !defined(CLK_TCK)-import System.IO.Unsafe (unsafePerformIO)-#endif---- For _SC_CLK_TCK-#if HAVE_UNISTD_H-#include <unistd.h>-#endif---- For struct rusage-#if !defined(mingw32_HOST_OS) && !defined(irix_HOST_OS)-# if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-# endif-#endif---- For FILETIME etc. on Windows-#if HAVE_WINDOWS_H-#include <windows.h>-#endif---- for CLK_TCK-#if HAVE_TIME_H-#include <time.h>-#endif---- for struct tms-#if HAVE_SYS_TIMES_H-#include <sys/times.h>-#endif--#endif--#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS)-realToInteger :: Real a => a -> Integer-realToInteger ct = round (realToFrac ct :: Double)- -- CTime, CClock, CUShort etc are in Real but not Fractional, - -- so we must convert to Double before we can round it-#endif--#ifdef __GLASGOW_HASKELL__--- -------------------------------------------------------------------------------- |Computation 'getCPUTime' returns the number of picoseconds CPU time--- used by the current program. The precision of this result is--- implementation-dependent.--getCPUTime :: IO Integer-getCPUTime = do--#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS)--- getrusage() is right royal pain to deal with when targetting multiple--- versions of Solaris, since some versions supply it in libc (2.3 and 2.5),--- while 2.4 has got it in libucb (I wouldn't be too surprised if it was back--- again in libucb in 2.6..)------ Avoid the problem by resorting to times() instead.----#if defined(HAVE_GETRUSAGE) && ! irix_HOST_OS && ! solaris2_HOST_OS- allocaBytes (#const sizeof(struct rusage)) $ \ p_rusage -> do- throwErrnoIfMinus1_ "getrusage" $ getrusage (#const RUSAGE_SELF) p_rusage-- let ru_utime = (#ptr struct rusage, ru_utime) p_rusage- let ru_stime = (#ptr struct rusage, ru_stime) p_rusage- u_sec <- (#peek struct timeval,tv_sec) ru_utime :: IO CTime- u_usec <- (#peek struct timeval,tv_usec) ru_utime :: IO CSUSeconds- s_sec <- (#peek struct timeval,tv_sec) ru_stime :: IO CTime- s_usec <- (#peek struct timeval,tv_usec) ru_stime :: IO CSUSeconds- return ((realToInteger u_sec * 1000000 + realToInteger u_usec + - realToInteger s_sec * 1000000 + realToInteger s_usec) - * 1000000)--type CRUsage = ()-foreign import capi unsafe "HsBase.h getrusage" getrusage :: CInt -> Ptr CRUsage -> IO CInt-#elif defined(HAVE_TIMES)- allocaBytes (#const sizeof(struct tms)) $ \ p_tms -> do- _ <- times p_tms- u_ticks <- (#peek struct tms,tms_utime) p_tms :: IO CClock- s_ticks <- (#peek struct tms,tms_stime) p_tms :: IO CClock- return (( (realToInteger u_ticks + realToInteger s_ticks) * 1000000000000) - `div` fromIntegral clockTicks)--type CTms = ()-foreign import ccall unsafe times :: Ptr CTms -> IO CClock-#else- ioException (IOError Nothing UnsupportedOperation - "getCPUTime"- "can't get CPU time"- Nothing)-#endif--#else /* win32 */- -- NOTE: GetProcessTimes() is only supported on NT-based OSes.- -- The counts reported by GetProcessTimes() are in 100-ns (10^-7) units.- allocaBytes (#const sizeof(FILETIME)) $ \ p_creationTime -> do- allocaBytes (#const sizeof(FILETIME)) $ \ p_exitTime -> do- allocaBytes (#const sizeof(FILETIME)) $ \ p_kernelTime -> do- allocaBytes (#const sizeof(FILETIME)) $ \ p_userTime -> do- pid <- getCurrentProcess- ok <- getProcessTimes pid p_creationTime p_exitTime p_kernelTime p_userTime- if toBool ok then do- ut <- ft2psecs p_userTime- kt <- ft2psecs p_kernelTime- return (ut + kt)- else return 0- where - ft2psecs :: Ptr FILETIME -> IO Integer- ft2psecs ft = do- high <- (#peek FILETIME,dwHighDateTime) ft :: IO Word32- low <- (#peek FILETIME,dwLowDateTime) ft :: IO Word32- -- Convert 100-ns units to picosecs (10^-12) - -- => multiply by 10^5.- return (((fromIntegral high) * (2^(32::Int)) + (fromIntegral low)) * 100000)-- -- ToDo: pin down elapsed times to just the OS thread(s) that- -- are evaluating/managing Haskell code.--type FILETIME = ()-type HANDLE = ()--- need proper Haskell names (initial lower-case character)-foreign import stdcall unsafe "GetCurrentProcess" getCurrentProcess :: IO (Ptr HANDLE)-foreign import stdcall unsafe "GetProcessTimes" getProcessTimes :: Ptr HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO CInt--#endif /* not _WIN32 */-#endif /* __GLASGOW_HASKELL__ */---- |The 'cpuTimePrecision' constant is the smallest measurable difference--- in CPU time that the implementation can record, and is given as an--- integral number of picoseconds.--#ifndef __NHC__-cpuTimePrecision :: Integer-cpuTimePrecision = round ((1000000000000::Integer) % fromIntegral (clockTicks))-#endif--#ifdef __GLASGOW_HASKELL__-clockTicks :: Int-clockTicks =-#if defined(CLK_TCK)- (#const CLK_TCK)-#else- unsafePerformIO (sysconf (#const _SC_CLK_TCK) >>= return . fromIntegral)-foreign import ccall unsafe sysconf :: CInt -> IO CLong-#endif-#endif /* __GLASGOW_HASKELL__ */-
@@ -1,396 +0,0 @@-{-# LANGUAGE Safe #-}---------------------------------------------------------------------------------- |--- Module : System.Console.GetOpt--- Copyright : (c) Sven Panne 2002-2005--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ This library provides facilities for parsing the command-line options--- in a standalone program. It is essentially a Haskell port of the GNU --- @getopt@ library.-----------------------------------------------------------------------------------{--Sven Panne <Sven.Panne@informatik.uni-muenchen.de> Oct. 1996 (small-changes Dec. 1997)--Two rather obscure features are missing: The Bash 2.0 non-option hack-(if you don't already know it, you probably don't want to hear about-it...) and the recognition of long options with a single dash-(e.g. '-help' is recognised as '--help', as long as there is no short-option 'h').--Other differences between GNU's getopt and this implementation:--* To enforce a coherent description of options and arguments, there- are explanation fields in the option/argument descriptor.--* Error messages are now more informative, but no longer POSIX- compliant... :-(--And a final Haskell advertisement: The GNU C implementation uses well-over 1100 lines, we need only 195 here, including a 46 line example! -:-)--}--module System.Console.GetOpt (- -- * GetOpt- getOpt, getOpt',- usageInfo,- ArgOrder(..),- OptDescr(..),- ArgDescr(..),-- -- * Examples-- -- |To hopefully illuminate the role of the different data structures,- -- here are the command-line options for a (very simple) compiler,- -- done in two different ways.- -- The difference arises because the type of 'getOpt' is- -- parameterized by the type of values derived from flags.-- -- ** Interpreting flags as concrete values- -- $example1-- -- ** Interpreting flags as transformations of an options record- -- $example2-) where--import Prelude -- necessary to get dependencies right--import Data.List ( isPrefixOf, find )---- |What to do with options following non-options-data ArgOrder a- = RequireOrder -- ^ no option processing after first non-option- | Permute -- ^ freely intersperse options and non-options- | ReturnInOrder (String -> a) -- ^ wrap non-options into options--{-|-Each 'OptDescr' describes a single option.--The arguments to 'Option' are:--* list of short option characters--* list of long option strings (without \"--\")--* argument descriptor--* explanation of option for user--}-data OptDescr a = -- description of a single options:- Option [Char] -- list of short option characters- [String] -- list of long option strings (without "--")- (ArgDescr a) -- argument descriptor- String -- explanation of option for user---- |Describes whether an option takes an argument or not, and if so--- how the argument is injected into a value of type @a@.-data ArgDescr a- = NoArg a -- ^ no argument expected- | ReqArg (String -> a) String -- ^ option requires argument- | OptArg (Maybe String -> a) String -- ^ optional argument--data OptKind a -- kind of cmd line arg (internal use only):- = Opt a -- an option- | UnreqOpt String -- an un-recognized option- | NonOpt String -- a non-option- | EndOfOpts -- end-of-options marker (i.e. "--")- | OptErr String -- something went wrong...---- | Return a string describing the usage of a command, derived from--- the header (first argument) and the options described by the --- second argument.-usageInfo :: String -- header- -> [OptDescr a] -- option descriptors- -> String -- nicely formatted decription of options-usageInfo header optDescr = unlines (header:table)- where (ss,ls,ds) = (unzip3 . concatMap fmtOpt) optDescr- table = zipWith3 paste (sameLen ss) (sameLen ls) ds- paste x y z = " " ++ x ++ " " ++ y ++ " " ++ z- sameLen xs = flushLeft ((maximum . map length) xs) xs- flushLeft n xs = [ take n (x ++ repeat ' ') | x <- xs ]--fmtOpt :: OptDescr a -> [(String,String,String)]-fmtOpt (Option sos los ad descr) =- case lines descr of- [] -> [(sosFmt,losFmt,"")]- (d:ds) -> (sosFmt,losFmt,d) : [ ("","",d') | d' <- ds ]- where sepBy _ [] = ""- sepBy _ [x] = x- sepBy ch (x:xs) = x ++ ch:' ':sepBy ch xs- sosFmt = sepBy ',' (map (fmtShort ad) sos)- losFmt = sepBy ',' (map (fmtLong ad) los)--fmtShort :: ArgDescr a -> Char -> String-fmtShort (NoArg _ ) so = "-" ++ [so]-fmtShort (ReqArg _ ad) so = "-" ++ [so] ++ " " ++ ad-fmtShort (OptArg _ ad) so = "-" ++ [so] ++ "[" ++ ad ++ "]"--fmtLong :: ArgDescr a -> String -> String-fmtLong (NoArg _ ) lo = "--" ++ lo-fmtLong (ReqArg _ ad) lo = "--" ++ lo ++ "=" ++ ad-fmtLong (OptArg _ ad) lo = "--" ++ lo ++ "[=" ++ ad ++ "]"--{-|-Process the command-line, and return the list of values that matched-(and those that didn\'t). The arguments are:--* The order requirements (see 'ArgOrder')--* The option descriptions (see 'OptDescr')--* The actual command line arguments (presumably got from - 'System.Environment.getArgs').--'getOpt' returns a triple consisting of the option arguments, a list-of non-options, and a list of error messages.--}-getOpt :: ArgOrder a -- non-option handling- -> [OptDescr a] -- option descriptors- -> [String] -- the command-line arguments- -> ([a],[String],[String]) -- (options,non-options,error messages)-getOpt ordering optDescr args = (os,xs,es ++ map errUnrec us)- where (os,xs,us,es) = getOpt' ordering optDescr args--{-|-This is almost the same as 'getOpt', but returns a quadruple-consisting of the option arguments, a list of non-options, a list of-unrecognized options, and a list of error messages.--}-getOpt' :: ArgOrder a -- non-option handling- -> [OptDescr a] -- option descriptors- -> [String] -- the command-line arguments- -> ([a],[String], [String] ,[String]) -- (options,non-options,unrecognized,error messages)-getOpt' _ _ [] = ([],[],[],[])-getOpt' ordering optDescr (arg:args) = procNextOpt opt ordering- where procNextOpt (Opt o) _ = (o:os,xs,us,es)- procNextOpt (UnreqOpt u) _ = (os,xs,u:us,es)- procNextOpt (NonOpt x) RequireOrder = ([],x:rest,[],[])- procNextOpt (NonOpt x) Permute = (os,x:xs,us,es)- procNextOpt (NonOpt x) (ReturnInOrder f) = (f x :os, xs,us,es)- procNextOpt EndOfOpts RequireOrder = ([],rest,[],[])- procNextOpt EndOfOpts Permute = ([],rest,[],[])- procNextOpt EndOfOpts (ReturnInOrder f) = (map f rest,[],[],[])- procNextOpt (OptErr e) _ = (os,xs,us,e:es)-- (opt,rest) = getNext arg args optDescr- (os,xs,us,es) = getOpt' ordering optDescr rest---- take a look at the next cmd line arg and decide what to do with it-getNext :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])-getNext ('-':'-':[]) rest _ = (EndOfOpts,rest)-getNext ('-':'-':xs) rest optDescr = longOpt xs rest optDescr-getNext ('-': x :xs) rest optDescr = shortOpt x xs rest optDescr-getNext a rest _ = (NonOpt a,rest)---- handle long option-longOpt :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])-longOpt ls rs optDescr = long ads arg rs- where (opt,arg) = break (=='=') ls- getWith p = [ o | o@(Option _ xs _ _) <- optDescr- , find (p opt) xs /= Nothing ]- exact = getWith (==)- options = if null exact then getWith isPrefixOf else exact- ads = [ ad | Option _ _ ad _ <- options ]- optStr = ("--"++opt)-- long (_:_:_) _ rest = (errAmbig options optStr,rest)- long [NoArg a ] [] rest = (Opt a,rest)- long [NoArg _ ] ('=':_) rest = (errNoArg optStr,rest)- long [ReqArg _ d] [] [] = (errReq d optStr,[])- long [ReqArg f _] [] (r:rest) = (Opt (f r),rest)- long [ReqArg f _] ('=':xs) rest = (Opt (f xs),rest)- long [OptArg f _] [] rest = (Opt (f Nothing),rest)- long [OptArg f _] ('=':xs) rest = (Opt (f (Just xs)),rest)- long _ _ rest = (UnreqOpt ("--"++ls),rest)---- handle short option-shortOpt :: Char -> String -> [String] -> [OptDescr a] -> (OptKind a,[String])-shortOpt y ys rs optDescr = short ads ys rs- where options = [ o | o@(Option ss _ _ _) <- optDescr, s <- ss, y == s ]- ads = [ ad | Option _ _ ad _ <- options ]- optStr = '-':[y]-- short (_:_:_) _ rest = (errAmbig options optStr,rest)- short (NoArg a :_) [] rest = (Opt a,rest)- short (NoArg a :_) xs rest = (Opt a,('-':xs):rest)- short (ReqArg _ d:_) [] [] = (errReq d optStr,[])- short (ReqArg f _:_) [] (r:rest) = (Opt (f r),rest)- short (ReqArg f _:_) xs rest = (Opt (f xs),rest)- short (OptArg f _:_) [] rest = (Opt (f Nothing),rest)- short (OptArg f _:_) xs rest = (Opt (f (Just xs)),rest)- short [] [] rest = (UnreqOpt optStr,rest)- short [] xs rest = (UnreqOpt optStr,('-':xs):rest)---- miscellaneous error formatting--errAmbig :: [OptDescr a] -> String -> OptKind a-errAmbig ods optStr = OptErr (usageInfo header ods)- where header = "option `" ++ optStr ++ "' is ambiguous; could be one of:"--errReq :: String -> String -> OptKind a-errReq d optStr = OptErr ("option `" ++ optStr ++ "' requires an argument " ++ d ++ "\n")--errUnrec :: String -> String-errUnrec optStr = "unrecognized option `" ++ optStr ++ "'\n"--errNoArg :: String -> OptKind a-errNoArg optStr = OptErr ("option `" ++ optStr ++ "' doesn't allow an argument\n")--{---------------------------------------------------------------------------------------------- and here a small and hopefully enlightening example:--data Flag = Verbose | Version | Name String | Output String | Arg String deriving Show--options :: [OptDescr Flag]-options =- [Option ['v'] ["verbose"] (NoArg Verbose) "verbosely list files",- Option ['V','?'] ["version","release"] (NoArg Version) "show version info",- Option ['o'] ["output"] (OptArg out "FILE") "use FILE for dump",- Option ['n'] ["name"] (ReqArg Name "USER") "only dump USER's files"]--out :: Maybe String -> Flag-out Nothing = Output "stdout"-out (Just o) = Output o--test :: ArgOrder Flag -> [String] -> String-test order cmdline = case getOpt order options cmdline of- (o,n,[] ) -> "options=" ++ show o ++ " args=" ++ show n ++ "\n"- (_,_,errs) -> concat errs ++ usageInfo header options- where header = "Usage: foobar [OPTION...] files..."---- example runs:--- putStr (test RequireOrder ["foo","-v"])--- ==> options=[] args=["foo", "-v"]--- putStr (test Permute ["foo","-v"])--- ==> options=[Verbose] args=["foo"]--- putStr (test (ReturnInOrder Arg) ["foo","-v"])--- ==> options=[Arg "foo", Verbose] args=[]--- putStr (test Permute ["foo","--","-v"])--- ==> options=[] args=["foo", "-v"]--- putStr (test Permute ["-?o","--name","bar","--na=baz"])--- ==> options=[Version, Output "stdout", Name "bar", Name "baz"] args=[]--- putStr (test Permute ["--ver","foo"])--- ==> option `--ver' is ambiguous; could be one of:--- -v --verbose verbosely list files--- -V, -? --version, --release show version info --- Usage: foobar [OPTION...] files...--- -v --verbose verbosely list files --- -V, -? --version, --release show version info --- -o[FILE] --output[=FILE] use FILE for dump --- -n USER --name=USER only dump USER's files--------------------------------------------------------------------------------------------}--{- $example1--A simple choice for the type associated with flags is to define a type-@Flag@ as an algebraic type representing the possible flags and their-arguments:--> module Opts1 where-> -> import System.Console.GetOpt-> import Data.Maybe ( fromMaybe )-> -> data Flag -> = Verbose | Version -> | Input String | Output String | LibDir String-> deriving Show-> -> options :: [OptDescr Flag]-> options =-> [ Option ['v'] ["verbose"] (NoArg Verbose) "chatty output on stderr"-> , Option ['V','?'] ["version"] (NoArg Version) "show version number"-> , Option ['o'] ["output"] (OptArg outp "FILE") "output FILE"-> , Option ['c'] [] (OptArg inp "FILE") "input FILE"-> , Option ['L'] ["libdir"] (ReqArg LibDir "DIR") "library directory"-> ]-> -> inp,outp :: Maybe String -> Flag-> outp = Output . fromMaybe "stdout"-> inp = Input . fromMaybe "stdin"-> -> compilerOpts :: [String] -> IO ([Flag], [String])-> compilerOpts argv = -> case getOpt Permute options argv of-> (o,n,[] ) -> return (o,n)-> (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))-> where header = "Usage: ic [OPTION...] files..."--Then the rest of the program will use the constructed list of flags-to determine it\'s behaviour.---}--{- $example2--A different approach is to group the option values in a record of type-@Options@, and have each flag yield a function of type-@Options -> Options@ transforming this record.--> module Opts2 where->-> import System.Console.GetOpt-> import Data.Maybe ( fromMaybe )->-> data Options = Options-> { optVerbose :: Bool-> , optShowVersion :: Bool-> , optOutput :: Maybe FilePath-> , optInput :: Maybe FilePath-> , optLibDirs :: [FilePath]-> } deriving Show->-> defaultOptions = Options-> { optVerbose = False-> , optShowVersion = False-> , optOutput = Nothing-> , optInput = Nothing-> , optLibDirs = []-> }->-> options :: [OptDescr (Options -> Options)]-> options =-> [ Option ['v'] ["verbose"]-> (NoArg (\ opts -> opts { optVerbose = True }))-> "chatty output on stderr"-> , Option ['V','?'] ["version"]-> (NoArg (\ opts -> opts { optShowVersion = True }))-> "show version number"-> , Option ['o'] ["output"]-> (OptArg ((\ f opts -> opts { optOutput = Just f }) . fromMaybe "output")-> "FILE")-> "output FILE"-> , Option ['c'] []-> (OptArg ((\ f opts -> opts { optInput = Just f }) . fromMaybe "input")-> "FILE")-> "input FILE"-> , Option ['L'] ["libdir"]-> (ReqArg (\ d opts -> opts { optLibDirs = optLibDirs opts ++ [d] }) "DIR")-> "library directory"-> ]->-> compilerOpts :: [String] -> IO (Options, [String])-> compilerOpts argv =-> case getOpt Permute options argv of-> (o,n,[] ) -> return (foldl (flip id) defaultOptions o, n)-> (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))-> where header = "Usage: ic [OPTION...] files..."--Similarly, each flag could yield a monadic function transforming a record,-of type @Options -> IO Options@ (or any other monad), allowing option-processing to perform actions of the chosen monad, e.g. printing help or-version messages, checking that file arguments exist, etc.---}-
@@ -1,343 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP, ForeignFunctionInterface #-}---------------------------------------------------------------------------------- |--- Module : System.Environment--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Miscellaneous information about the system environment.-----------------------------------------------------------------------------------module System.Environment- (- getArgs, -- :: IO [String]- getProgName, -- :: IO String- getEnv, -- :: String -> IO String-#ifndef __NHC__- withArgs,- withProgName,-#endif-#ifdef __GLASGOW_HASKELL__- getEnvironment,-#endif- ) where--import Prelude--#ifdef __GLASGOW_HASKELL__-import Foreign.Safe-import Foreign.C-import Control.Exception.Base ( bracket )--- import GHC.IO-import GHC.IO.Exception-import GHC.IO.Encoding (getFileSystemEncoding)-import qualified GHC.Foreign as GHC-import Data.List-#ifdef mingw32_HOST_OS-import GHC.Environment-import GHC.Windows-#else-import Control.Monad-#endif-#endif--#ifdef __HUGS__-import Hugs.System-#endif--#ifdef __NHC__-import System- ( getArgs- , getProgName- , getEnv- )-#endif--#ifdef __GLASGOW_HASKELL__--- ------------------------------------------------------------------------------ getArgs, getProgName, getEnv--#ifdef mingw32_HOST_OS---- Ignore the arguments to hs_init on Windows for the sake of Unicode compat--getWin32ProgArgv_certainly :: IO [String]-getWin32ProgArgv_certainly = do- mb_argv <- getWin32ProgArgv- case mb_argv of- Nothing -> fmap dropRTSArgs getFullArgs- Just argv -> return argv--withWin32ProgArgv :: [String] -> IO a -> IO a-withWin32ProgArgv argv act = bracket begin setWin32ProgArgv (\_ -> act)- where- begin = do- mb_old_argv <- getWin32ProgArgv- setWin32ProgArgv (Just argv)- return mb_old_argv--getWin32ProgArgv :: IO (Maybe [String])-getWin32ProgArgv = alloca $ \p_argc -> alloca $ \p_argv -> do- c_getWin32ProgArgv p_argc p_argv- argc <- peek p_argc- argv_p <- peek p_argv- if argv_p == nullPtr- then return Nothing- else do- argv_ps <- peekArray (fromIntegral argc) argv_p- fmap Just $ mapM peekCWString argv_ps--setWin32ProgArgv :: Maybe [String] -> IO ()-setWin32ProgArgv Nothing = c_setWin32ProgArgv 0 nullPtr-setWin32ProgArgv (Just argv) = withMany withCWString argv $ \argv_ps -> withArrayLen argv_ps $ \argc argv_p -> do- c_setWin32ProgArgv (fromIntegral argc) argv_p--foreign import ccall unsafe "getWin32ProgArgv"- c_getWin32ProgArgv :: Ptr CInt -> Ptr (Ptr CWString) -> IO ()--foreign import ccall unsafe "setWin32ProgArgv"- c_setWin32ProgArgv :: CInt -> Ptr CWString -> IO ()--dropRTSArgs :: [String] -> [String]-dropRTSArgs [] = []-dropRTSArgs ("+RTS":rest) = dropRTSArgs (dropWhile (/= "-RTS") rest)-dropRTSArgs ("--RTS":rest) = rest-dropRTSArgs ("-RTS":rest) = dropRTSArgs rest-dropRTSArgs (arg:rest) = arg : dropRTSArgs rest--#endif---- | Computation 'getArgs' returns a list of the program's command--- line arguments (not including the program name).-getArgs :: IO [String]--#ifdef mingw32_HOST_OS-getArgs = fmap tail getWin32ProgArgv_certainly-#else-getArgs =- alloca $ \ p_argc ->- alloca $ \ p_argv -> do- getProgArgv p_argc p_argv- p <- fromIntegral `liftM` peek p_argc- argv <- peek p_argv- enc <- getFileSystemEncoding- peekArray (p - 1) (advancePtr argv 1) >>= mapM (GHC.peekCString enc)--foreign import ccall unsafe "getProgArgv"- getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()-#endif--{-|-Computation 'getProgName' returns the name of the program as it was-invoked.--However, this is hard-to-impossible to implement on some non-Unix-OSes, so instead, for maximum portability, we just return the leafname-of the program as invoked. Even then there are some differences-between platforms: on Windows, for example, a program invoked as foo-is probably really @FOO.EXE@, and that is what 'getProgName' will return.--}-getProgName :: IO String-#ifdef mingw32_HOST_OS--- Ignore the arguments to hs_init on Windows for the sake of Unicode compat-getProgName = fmap (basename . head) getWin32ProgArgv_certainly-#else-getProgName =- alloca $ \ p_argc ->- alloca $ \ p_argv -> do- getProgArgv p_argc p_argv- argv <- peek p_argv- unpackProgName argv--unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]-unpackProgName argv = do- enc <- getFileSystemEncoding- s <- peekElemOff argv 0 >>= GHC.peekCString enc- return (basename s)-#endif--basename :: FilePath -> FilePath-basename f = go f f- where- go acc [] = acc- go acc (x:xs)- | isPathSeparator x = go xs xs- | otherwise = go acc xs-- isPathSeparator :: Char -> Bool- isPathSeparator '/' = True-#ifdef mingw32_HOST_OS- isPathSeparator '\\' = True-#endif- isPathSeparator _ = False----- | Computation 'getEnv' @var@ returns the value--- of the environment variable @var@. ------ This computation may fail with:------ * 'System.IO.Error.isDoesNotExistError' if the environment variable--- does not exist.--getEnv :: String -> IO String-#ifdef mingw32_HOST_OS-getEnv name = withCWString name $ \s -> try_size s 256- where- try_size s size = allocaArray (fromIntegral size) $ \p_value -> do- res <- c_GetEnvironmentVariable s p_value size- case res of- 0 -> do- err <- c_GetLastError- if err == eRROR_ENVVAR_NOT_FOUND- then ioe_missingEnvVar name- else throwGetLastError "getEnv"- _ | res > size -> try_size s res -- Rare: size increased between calls to GetEnvironmentVariable- | otherwise -> peekCWString p_value--eRROR_ENVVAR_NOT_FOUND :: DWORD-eRROR_ENVVAR_NOT_FOUND = 203--foreign import stdcall unsafe "windows.h GetLastError"- c_GetLastError:: IO DWORD--foreign import stdcall unsafe "windows.h GetEnvironmentVariableW"- c_GetEnvironmentVariable :: LPTSTR -> LPTSTR -> DWORD -> IO DWORD-#else-getEnv name =- withCString name $ \s -> do- litstring <- c_getenv s- if litstring /= nullPtr- then getFileSystemEncoding >>= \enc -> GHC.peekCString enc litstring- else ioe_missingEnvVar name--foreign import ccall unsafe "getenv"- c_getenv :: CString -> IO (Ptr CChar)-#endif--ioe_missingEnvVar :: String -> IO a-ioe_missingEnvVar name = ioException (IOError Nothing NoSuchThing "getEnv"- "no environment variable" Nothing (Just name))--{-|-'withArgs' @args act@ - while executing action @act@, have 'getArgs'-return @args@.--}-withArgs :: [String] -> IO a -> IO a-withArgs xs act = do- p <- System.Environment.getProgName- withArgv (p:xs) act--{-|-'withProgName' @name act@ - while executing action @act@,-have 'getProgName' return @name@.--}-withProgName :: String -> IO a -> IO a-withProgName nm act = do- xs <- System.Environment.getArgs- withArgv (nm:xs) act---- Worker routine which marshals and replaces an argv vector for--- the duration of an action.--withArgv :: [String] -> IO a -> IO a--#ifdef mingw32_HOST_OS--- We have to reflect the updated arguments in the RTS-side variables as--- well, because the RTS still consults them for error messages and the like.--- If we don't do this then ghc-e005 fails.-withArgv new_args act = withWin32ProgArgv new_args $ withProgArgv new_args act-#else-withArgv = withProgArgv-#endif--withProgArgv :: [String] -> IO a -> IO a-withProgArgv new_args act = do- pName <- System.Environment.getProgName- existing_args <- System.Environment.getArgs- bracket (setProgArgv new_args)- (\argv -> do _ <- setProgArgv (pName:existing_args)- freeProgArgv argv)- (const act)--freeProgArgv :: Ptr CString -> IO ()-freeProgArgv argv = do- size <- lengthArray0 nullPtr argv- sequence_ [peek (argv `advancePtr` i) >>= free | i <- [size, size-1 .. 0]]- free argv--setProgArgv :: [String] -> IO (Ptr CString)-setProgArgv argv = do- enc <- getFileSystemEncoding- vs <- mapM (GHC.newCString enc) argv >>= newArray0 nullPtr- c_setProgArgv (genericLength argv) vs- return vs--foreign import ccall unsafe "setProgArgv" - c_setProgArgv :: CInt -> Ptr CString -> IO ()---- |'getEnvironment' retrieves the entire environment as a--- list of @(key,value)@ pairs.------ If an environment entry does not contain an @\'=\'@ character,--- the @key@ is the whole entry and the @value@ is the empty string.-getEnvironment :: IO [(String, String)]--#ifdef mingw32_HOST_OS-getEnvironment = bracket c_GetEnvironmentStrings c_FreeEnvironmentStrings $ \pBlock ->- if pBlock == nullPtr then return []- else go pBlock- where- go pBlock = do- -- The block is terminated by a null byte where there- -- should be an environment variable of the form X=Y- c <- peek pBlock- if c == 0 then return []- else do- -- Seek the next pair (or terminating null):- pBlock' <- seekNull pBlock False- -- We now know the length in bytes, but ignore it when- -- getting the actual String:- str <- peekCWString pBlock- fmap (divvy str :) $ go pBlock'- - -- Returns pointer to the byte *after* the next null- seekNull pBlock done = do- let pBlock' = pBlock `plusPtr` sizeOf (undefined :: CWchar)- if done then return pBlock'- else do- c <- peek pBlock'- seekNull pBlock' (c == (0 :: Word8 ))--foreign import stdcall unsafe "windows.h GetEnvironmentStringsW"- c_GetEnvironmentStrings :: IO (Ptr CWchar)--foreign import stdcall unsafe "windows.h FreeEnvironmentStringsW"- c_FreeEnvironmentStrings :: Ptr CWchar -> IO Bool-#else-getEnvironment = do- pBlock <- getEnvBlock- if pBlock == nullPtr then return []- else do- enc <- getFileSystemEncoding- stuff <- peekArray0 nullPtr pBlock >>= mapM (GHC.peekCString enc)- return (map divvy stuff)--foreign import ccall unsafe "__hscore_environ" - getEnvBlock :: IO (Ptr CString)-#endif--divvy :: String -> (String, String)-divvy str =- case break (=='=') str of- (xs,[]) -> (xs,[]) -- don't barf (like Posix.getEnvironment)- (name,_:value) -> (name,value)-#endif /* __GLASGOW_HASKELL__ */-
@@ -1,95 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : System.Exit--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Exiting the program.-----------------------------------------------------------------------------------module System.Exit- (- ExitCode(ExitSuccess,ExitFailure)- , exitWith -- :: ExitCode -> IO a- , exitFailure -- :: IO a- , exitSuccess -- :: IO a- ) where--import Prelude--#ifdef __GLASGOW_HASKELL__-import GHC.IO-import GHC.IO.Exception-#endif--#ifdef __HUGS__-import Hugs.Prelude (ExitCode(..))-import Control.Exception.Base-#endif--#ifdef __NHC__-import System- ( ExitCode(..)- , exitWith- )-#endif---- ------------------------------------------------------------------------------ exitWith---- | Computation 'exitWith' @code@ throws 'ExitCode' @code@.--- Normally this terminates the program, returning @code@ to the--- program's caller.------ On program termination, the standard 'Handle's 'stdout' and--- 'stderr' are flushed automatically; any other buffered 'Handle's--- need to be flushed manually, otherwise the buffered data will be--- discarded.------ A program that fails in any other way is treated as if it had--- called 'exitFailure'.--- A program that terminates successfully without calling 'exitWith'--- explicitly is treated as it it had called 'exitWith' 'ExitSuccess'.------ As an 'ExitCode' is not an 'IOError', 'exitWith' bypasses--- the error handling in the 'IO' monad and cannot be intercepted by--- 'catch' from the "Prelude". However it is a 'SomeException', and can--- be caught using the functions of "Control.Exception". This means--- that cleanup computations added with 'Control.Exception.bracket'--- (from "Control.Exception") are also executed properly on 'exitWith'.------ Note: in GHC, 'exitWith' should be called from the main program--- thread in order to exit the process. When called from another--- thread, 'exitWith' will throw an 'ExitException' as normal, but the--- exception will not cause the process itself to exit.----#ifndef __NHC__-exitWith :: ExitCode -> IO a-exitWith ExitSuccess = throwIO ExitSuccess-exitWith code@(ExitFailure n)- | n /= 0 = throwIO code-#ifdef __GLASGOW_HASKELL__- | otherwise = ioError (IOError Nothing InvalidArgument "exitWith" "ExitFailure 0" Nothing Nothing)-#endif-#endif /* ! __NHC__ */---- | The computation 'exitFailure' is equivalent to--- 'exitWith' @(@'ExitFailure' /exitfail/@)@,--- where /exitfail/ is implementation-dependent.-exitFailure :: IO a-exitFailure = exitWith (ExitFailure 1)---- | The computation 'exitSuccess' is equivalent to--- 'exitWith' 'ExitSuccess', It terminates the program--- successfully.-exitSuccess :: IO a-exitSuccess = exitWith ExitSuccess-
@@ -1,693 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-{-# LANGUAGE ForeignFunctionInterface #-}---------------------------------------------------------------------------------- |--- Module : System.IO--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ The standard IO library.-----------------------------------------------------------------------------------module System.IO (- -- * The IO monad-- IO, -- instance MonadFix- fixIO, -- :: (a -> IO a) -> IO a-- -- * Files and handles-- FilePath, -- :: String-- Handle, -- abstract, instance of: Eq, Show.-- -- | GHC note: a 'Handle' will be automatically closed when the garbage- -- collector detects that it has become unreferenced by the program.- -- However, relying on this behaviour is not generally recommended:- -- the garbage collector is unpredictable. If possible, use- -- an explicit 'hClose' to close 'Handle's when they are no longer- -- required. GHC does not currently attempt to free up file- -- descriptors when they have run out, it is your responsibility to- -- ensure that this doesn't happen.-- -- ** Standard handles-- -- | Three handles are allocated during program initialisation,- -- and are initially open.-- stdin, stdout, stderr, -- :: Handle-- -- * Opening and closing files-- -- ** Opening files-- withFile,- openFile, -- :: FilePath -> IOMode -> IO Handle- IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),-- -- ** Closing files-- hClose, -- :: Handle -> IO ()-- -- ** Special cases-- -- | These functions are also exported by the "Prelude".-- readFile, -- :: FilePath -> IO String- writeFile, -- :: FilePath -> String -> IO ()- appendFile, -- :: FilePath -> String -> IO ()-- -- ** File locking-- -- $locking-- -- * Operations on handles-- -- ** Determining and changing the size of a file-- hFileSize, -- :: Handle -> IO Integer-#ifdef __GLASGOW_HASKELL__- hSetFileSize, -- :: Handle -> Integer -> IO ()-#endif-- -- ** Detecting the end of input-- hIsEOF, -- :: Handle -> IO Bool- isEOF, -- :: IO Bool-- -- ** Buffering operations-- BufferMode(NoBuffering,LineBuffering,BlockBuffering),- hSetBuffering, -- :: Handle -> BufferMode -> IO ()- hGetBuffering, -- :: Handle -> IO BufferMode- hFlush, -- :: Handle -> IO ()-- -- ** Repositioning handles-- hGetPosn, -- :: Handle -> IO HandlePosn- hSetPosn, -- :: HandlePosn -> IO ()- HandlePosn, -- abstract, instance of: Eq, Show.-- hSeek, -- :: Handle -> SeekMode -> Integer -> IO ()- SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),-#if !defined(__NHC__)- hTell, -- :: Handle -> IO Integer-#endif-- -- ** Handle properties-- hIsOpen, hIsClosed, -- :: Handle -> IO Bool- hIsReadable, hIsWritable, -- :: Handle -> IO Bool- hIsSeekable, -- :: Handle -> IO Bool-- -- ** Terminal operations (not portable: GHC\/Hugs only)--#if !defined(__NHC__)- hIsTerminalDevice, -- :: Handle -> IO Bool-- hSetEcho, -- :: Handle -> Bool -> IO ()- hGetEcho, -- :: Handle -> IO Bool-#endif-- -- ** Showing handle state (not portable: GHC only)--#ifdef __GLASGOW_HASKELL__- hShow, -- :: Handle -> IO String-#endif-- -- * Text input and output-- -- ** Text input-- hWaitForInput, -- :: Handle -> Int -> IO Bool- hReady, -- :: Handle -> IO Bool- hGetChar, -- :: Handle -> IO Char- hGetLine, -- :: Handle -> IO [Char]- hLookAhead, -- :: Handle -> IO Char- hGetContents, -- :: Handle -> IO [Char]-- -- ** Text output-- hPutChar, -- :: Handle -> Char -> IO ()- hPutStr, -- :: Handle -> [Char] -> IO ()- hPutStrLn, -- :: Handle -> [Char] -> IO ()- hPrint, -- :: Show a => Handle -> a -> IO ()-- -- ** Special cases for standard input and output-- -- | These functions are also exported by the "Prelude".-- interact, -- :: (String -> String) -> IO ()- putChar, -- :: Char -> IO ()- putStr, -- :: String -> IO () - putStrLn, -- :: String -> IO ()- print, -- :: Show a => a -> IO ()- getChar, -- :: IO Char- getLine, -- :: IO String- getContents, -- :: IO String- readIO, -- :: Read a => String -> IO a- readLn, -- :: Read a => IO a-- -- * Binary input and output-- withBinaryFile,- openBinaryFile, -- :: FilePath -> IOMode -> IO Handle- hSetBinaryMode, -- :: Handle -> Bool -> IO ()- hPutBuf, -- :: Handle -> Ptr a -> Int -> IO ()- hGetBuf, -- :: Handle -> Ptr a -> Int -> IO Int-#if !defined(__NHC__) && !defined(__HUGS__)- hGetBufSome, -- :: Handle -> Ptr a -> Int -> IO Int- hPutBufNonBlocking, -- :: Handle -> Ptr a -> Int -> IO Int- hGetBufNonBlocking, -- :: Handle -> Ptr a -> Int -> IO Int-#endif-- -- * Temporary files-- openTempFile,- openBinaryTempFile,- openTempFileWithDefaultPermissions,- openBinaryTempFileWithDefaultPermissions,--#if !defined(__NHC__) && !defined(__HUGS__)- -- * Unicode encoding\/decoding-- -- | A text-mode 'Handle' has an associated 'TextEncoding', which- -- is used to decode bytes into Unicode characters when reading,- -- and encode Unicode characters into bytes when writing.- --- -- The default 'TextEncoding' is the same as the default encoding- -- on your system, which is also available as 'localeEncoding'.- -- (GHC note: on Windows, we currently do not support double-byte- -- encodings; if the console\'s code page is unsupported, then- -- 'localeEncoding' will be 'latin1'.)- --- -- Encoding and decoding errors are always detected and reported,- -- except during lazy I/O ('hGetContents', 'getContents', and- -- 'readFile'), where a decoding error merely results in- -- termination of the character stream, as with other I/O errors.-- hSetEncoding, - hGetEncoding,-- -- ** Unicode encodings- TextEncoding, - latin1,- utf8, utf8_bom,- utf16, utf16le, utf16be,- utf32, utf32le, utf32be, - localeEncoding,- char8,- mkTextEncoding,-#endif--#if !defined(__NHC__) && !defined(__HUGS__)- -- * Newline conversion- - -- | In Haskell, a newline is always represented by the character- -- '\n'. However, in files and external character streams, a- -- newline may be represented by another character sequence, such- -- as '\r\n'.- --- -- A text-mode 'Handle' has an associated 'NewlineMode' that- -- specifies how to transate newline characters. The- -- 'NewlineMode' specifies the input and output translation- -- separately, so that for instance you can translate '\r\n'- -- to '\n' on input, but leave newlines as '\n' on output.- --- -- The default 'NewlineMode' for a 'Handle' is- -- 'nativeNewlineMode', which does no translation on Unix systems,- -- but translates '\r\n' to '\n' and back on Windows.- --- -- Binary-mode 'Handle's do no newline translation at all.- --- hSetNewlineMode, - Newline(..), nativeNewline, - NewlineMode(..), - noNewlineTranslation, universalNewlineMode, nativeNewlineMode,-#endif- ) where--import Control.Exception.Base--#ifndef __NHC__-import Data.Bits-import Data.List-import Data.Maybe-import Foreign.C.Error-#ifdef mingw32_HOST_OS-import Foreign.C.String-#endif-import Foreign.C.Types-import System.Posix.Internals-import System.Posix.Types-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.IO hiding ( bracket, onException )-import GHC.IO.IOMode-import GHC.IO.Handle.FD-import qualified GHC.IO.FD as FD-import GHC.IO.Handle-import GHC.IO.Handle.Text ( hGetBufSome, hPutStrLn )-import GHC.IO.Exception ( userError )-import GHC.IO.Encoding-import GHC.Num-import Text.Read-import GHC.Show-import GHC.MVar-#endif--#ifdef __HUGS__-import Hugs.IO-import Hugs.IOExts-import Hugs.IORef-import System.IO.Unsafe ( unsafeInterleaveIO )-#endif--#ifdef __NHC__-import IO- ( Handle ()- , HandlePosn ()- , IOMode (ReadMode,WriteMode,AppendMode,ReadWriteMode)- , BufferMode (NoBuffering,LineBuffering,BlockBuffering)- , SeekMode (AbsoluteSeek,RelativeSeek,SeekFromEnd)- , stdin, stdout, stderr- , openFile -- :: FilePath -> IOMode -> IO Handle- , hClose -- :: Handle -> IO ()- , hFileSize -- :: Handle -> IO Integer- , hIsEOF -- :: Handle -> IO Bool- , isEOF -- :: IO Bool- , hSetBuffering -- :: Handle -> BufferMode -> IO ()- , hGetBuffering -- :: Handle -> IO BufferMode- , hFlush -- :: Handle -> IO ()- , hGetPosn -- :: Handle -> IO HandlePosn- , hSetPosn -- :: HandlePosn -> IO ()- , hSeek -- :: Handle -> SeekMode -> Integer -> IO ()- , hWaitForInput -- :: Handle -> Int -> IO Bool- , hGetChar -- :: Handle -> IO Char- , hGetLine -- :: Handle -> IO [Char]- , hLookAhead -- :: Handle -> IO Char- , hGetContents -- :: Handle -> IO [Char]- , hPutChar -- :: Handle -> Char -> IO ()- , hPutStr -- :: Handle -> [Char] -> IO ()- , hPutStrLn -- :: Handle -> [Char] -> IO ()- , hPrint -- :: Handle -> [Char] -> IO ()- , hReady -- :: Handle -> [Char] -> IO ()- , hIsOpen, hIsClosed -- :: Handle -> IO Bool- , hIsReadable, hIsWritable -- :: Handle -> IO Bool- , hIsSeekable -- :: Handle -> IO Bool- , bracket-- , IO ()- , FilePath -- :: String- )-import NHC.IOExtras (fixIO, hPutBuf, hGetBuf)-import NHC.FFI (Ptr)-#endif---- -------------------------------------------------------------------------------- Standard IO--#ifdef __GLASGOW_HASKELL__--- | Write a character to the standard output device--- (same as 'hPutChar' 'stdout').--putChar :: Char -> IO ()-putChar c = hPutChar stdout c---- | Write a string to the standard output device--- (same as 'hPutStr' 'stdout').--putStr :: String -> IO ()-putStr s = hPutStr stdout s---- | The same as 'putStr', but adds a newline character.--putStrLn :: String -> IO ()-putStrLn s = hPutStrLn stdout s---- | The 'print' function outputs a value of any printable type to the--- standard output device.--- Printable types are those that are instances of class 'Show'; 'print'--- converts values to strings for output using the 'show' operation and--- adds a newline.------ For example, a program to print the first 20 integers and their--- powers of 2 could be written as:------ > main = print ([(n, 2^n) | n <- [0..19]])--print :: Show a => a -> IO ()-print x = putStrLn (show x)---- | Read a character from the standard input device--- (same as 'hGetChar' 'stdin').--getChar :: IO Char-getChar = hGetChar stdin---- | Read a line from the standard input device--- (same as 'hGetLine' 'stdin').--getLine :: IO String-getLine = hGetLine stdin---- | The 'getContents' operation returns all user input as a single string,--- which is read lazily as it is needed--- (same as 'hGetContents' 'stdin').--getContents :: IO String-getContents = hGetContents stdin---- | The 'interact' function takes a function of type @String->String@--- as its argument. The entire input from the standard input device is--- passed to this function as its argument, and the resulting string is--- output on the standard output device.--interact :: (String -> String) -> IO ()-interact f = do s <- getContents- putStr (f s)---- | The 'readFile' function reads a file and--- returns the contents of the file as a string.--- The file is read lazily, on demand, as with 'getContents'.--readFile :: FilePath -> IO String-readFile name = openFile name ReadMode >>= hGetContents---- | The computation 'writeFile' @file str@ function writes the string @str@,--- to the file @file@.-writeFile :: FilePath -> String -> IO ()-writeFile f txt = withFile f WriteMode (\ hdl -> hPutStr hdl txt)---- | The computation 'appendFile' @file str@ function appends the string @str@,--- to the file @file@.------ Note that 'writeFile' and 'appendFile' write a literal string--- to a file. To write a value of any printable type, as with 'print',--- use the 'show' function to convert the value to a string first.------ > main = appendFile "squares" (show [(x,x*x) | x <- [0,0.1..2]])--appendFile :: FilePath -> String -> IO ()-appendFile f txt = withFile f AppendMode (\ hdl -> hPutStr hdl txt)---- | The 'readLn' function combines 'getLine' and 'readIO'.--readLn :: Read a => IO a-readLn = do l <- getLine- r <- readIO l- return r---- | The 'readIO' function is similar to 'read' except that it signals--- parse failure to the 'IO' monad instead of terminating the program.--readIO :: Read a => String -> IO a-readIO s = case (do { (x,t) <- reads s ;- ("","") <- lex t ;- return x }) of- [x] -> return x- [] -> ioError (userError "Prelude.readIO: no parse")- _ -> ioError (userError "Prelude.readIO: ambiguous parse")---- | The Unicode encoding of the current locale------ This is the initial locale encoding: if it has been subsequently changed by--- 'GHC.IO.Encoding.setLocaleEncoding' this value will not reflect that change.-localeEncoding :: TextEncoding-localeEncoding = initLocaleEncoding-#endif /* __GLASGOW_HASKELL__ */--#ifndef __NHC__--- | Computation 'hReady' @hdl@ indicates whether at least one item is--- available for input from handle @hdl@.--- --- This operation may fail with:------ * 'System.IO.Error.isEOFError' if the end of file has been reached.--hReady :: Handle -> IO Bool-hReady h = hWaitForInput h 0---- | Computation 'hPrint' @hdl t@ writes the string representation of @t@--- given by the 'shows' function to the file or channel managed by @hdl@--- and appends a newline.------ This operation may fail with:------ * 'System.IO.Error.isFullError' if the device is full; or------ * 'System.IO.Error.isPermissionError' if another system resource limit would be exceeded.--hPrint :: Show a => Handle -> a -> IO ()-hPrint hdl = hPutStrLn hdl . show-#endif /* !__NHC__ */---- | @'withFile' name mode act@ opens a file using 'openFile' and passes--- the resulting handle to the computation @act@. The handle will be--- closed on exit from 'withFile', whether by normal termination or by--- raising an exception. If closing the handle raises an exception, then--- this exception will be raised by 'withFile' rather than any exception--- raised by 'act'.-withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r-withFile name mode = bracket (openFile name mode) hClose---- | @'withBinaryFile' name mode act@ opens a file using 'openBinaryFile'--- and passes the resulting handle to the computation @act@. The handle--- will be closed on exit from 'withBinaryFile', whether by normal--- termination or by raising an exception.-withBinaryFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r-withBinaryFile name mode = bracket (openBinaryFile name mode) hClose---- ------------------------------------------------------------------------------ fixIO--#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)-fixIO :: (a -> IO a) -> IO a-fixIO k = do- m <- newEmptyMVar- ans <- unsafeInterleaveIO (takeMVar m)- result <- k ans- putMVar m result- return result---- NOTE: we do our own explicit black holing here, because GHC's lazy--- blackholing isn't enough. In an infinite loop, GHC may run the IO--- computation a few times before it notices the loop, which is wrong.------ NOTE2: the explicit black-holing with an IORef ran into trouble--- with multiple threads (see #5421), so now we use an MVar. I'm--- actually wondering whether we should use readMVar rather than--- takeMVar, just in case it ends up being executed multiple times,--- but even then it would have to be masked to protect against async--- exceptions. Ugh. What we really need here is an IVar, or an--- atomic readMVar, or even STM. All these seem like overkill.------ See also System.IO.Unsafe.unsafeFixIO.----#endif--#if defined(__NHC__)--- Assume a unix platform, where text and binary I/O are identical.-openBinaryFile = openFile-hSetBinaryMode _ _ = return ()--type CMode = Int-#endif---- | The function creates a temporary file in ReadWrite mode.--- The created file isn\'t deleted automatically, so you need to delete it manually.------ The file is creates with permissions such that only the current--- user can read\/write it.------ With some exceptions (see below), the file will be created securely--- in the sense that an attacker should not be able to cause--- openTempFile to overwrite another file on the filesystem using your--- credentials, by putting symbolic links (on Unix) in the place where--- the temporary file is to be created. On Unix the @O_CREAT@ and--- @O_EXCL@ flags are used to prevent this attack, but note that--- @O_EXCL@ is sometimes not supported on NFS filesystems, so if you--- rely on this behaviour it is best to use local filesystems only.----openTempFile :: FilePath -- ^ Directory in which to create the file- -> String -- ^ File name template. If the template is \"foo.ext\" then- -- the created file will be \"fooXXX.ext\" where XXX is some- -- random number.- -> IO (FilePath, Handle)-openTempFile tmp_dir template- = openTempFile' "openTempFile" tmp_dir template False 0o600---- | Like 'openTempFile', but opens the file in binary mode. See 'openBinaryFile' for more comments.-openBinaryTempFile :: FilePath -> String -> IO (FilePath, Handle)-openBinaryTempFile tmp_dir template- = openTempFile' "openBinaryTempFile" tmp_dir template True 0o600---- | Like 'openTempFile', but uses the default file permissions-openTempFileWithDefaultPermissions :: FilePath -> String- -> IO (FilePath, Handle)-openTempFileWithDefaultPermissions tmp_dir template- = openTempFile' "openBinaryTempFile" tmp_dir template False 0o666---- | Like 'openBinaryTempFile', but uses the default file permissions-openBinaryTempFileWithDefaultPermissions :: FilePath -> String- -> IO (FilePath, Handle)-openBinaryTempFileWithDefaultPermissions tmp_dir template- = openTempFile' "openBinaryTempFile" tmp_dir template True 0o666--openTempFile' :: String -> FilePath -> String -> Bool -> CMode- -> IO (FilePath, Handle)-openTempFile' loc tmp_dir template binary mode = do- pid <- c_getpid- findTempName pid- where- -- We split off the last extension, so we can use .foo.ext files- -- for temporary files (hidden on Unix OSes). Unfortunately we're- -- below filepath in the hierarchy here.- (prefix,suffix) =- case break (== '.') $ reverse template of- -- First case: template contains no '.'s. Just re-reverse it.- (rev_suffix, "") -> (reverse rev_suffix, "")- -- Second case: template contains at least one '.'. Strip the- -- dot from the prefix and prepend it to the suffix (if we don't- -- do this, the unique number will get added after the '.' and- -- thus be part of the extension, which is wrong.)- (rev_suffix, '.':rest) -> (reverse rest, '.':reverse rev_suffix)- -- Otherwise, something is wrong, because (break (== '.')) should- -- always return a pair with either the empty string or a string- -- beginning with '.' as the second component.- _ -> error "bug in System.IO.openTempFile"--#ifndef __NHC__-#endif--#if defined(__NHC__)- findTempName x = do h <- openFile filepath ReadWriteMode- return (filepath, h)-#elif defined(__GLASGOW_HASKELL__)- findTempName x = do- r <- openNewFile filepath binary mode- case r of- FileExists -> findTempName (x + 1)- OpenNewError errno -> ioError (errnoToIOError loc errno Nothing (Just tmp_dir))- NewFileCreated fd -> do- (fD,fd_type) <- FD.mkFD fd ReadWriteMode Nothing{-no stat-}- False{-is_socket-}- True{-is_nonblock-}-- enc <- getLocaleEncoding- h <- mkHandleFromFD fD fd_type filepath ReadWriteMode False{-set non-block-} (Just enc)-- return (filepath, h)-#else- h <- fdToHandle fd `onException` c_close fd- return (filepath, h)-#endif-- where- filename = prefix ++ show x ++ suffix- filepath = tmp_dir `combine` filename-- -- XXX bits copied from System.FilePath, since that's not available here- combine a b- | null b = a- | null a = b- | last a == pathSeparator = a ++ b- | otherwise = a ++ [pathSeparator] ++ b--#if __HUGS__- fdToHandle fd = openFd (fromIntegral fd) False ReadWriteMode binary-#endif--#if defined(__GLASGOW_HASKELL__)-data OpenNewFileResult- = NewFileCreated CInt- | FileExists- | OpenNewError Errno--openNewFile :: FilePath -> Bool -> CMode -> IO OpenNewFileResult-openNewFile filepath binary mode = do- let oflags1 = rw_flags .|. o_EXCL-- binary_flags- | binary = o_BINARY- | otherwise = 0-- oflags = oflags1 .|. binary_flags- fd <- withFilePath filepath $ \ f ->- c_open f oflags mode- if fd < 0- then do- errno <- getErrno- case errno of- _ | errno == eEXIST -> return FileExists-# ifdef mingw32_HOST_OS- -- If c_open throws EACCES on windows, it could mean that filepath is a- -- directory. In this case, we want to return FileExists so that the- -- enclosing openTempFile can try again instead of failing outright.- -- See bug #4968.- _ | errno == eACCES -> do- withCString filepath $ \path -> do- -- There is a race here: the directory might have been moved or- -- deleted between the c_open call and the next line, but there- -- doesn't seem to be any direct way to detect that the c_open call- -- failed because of an existing directory.- exists <- c_fileExists path- return $ if exists- then FileExists- else OpenNewError errno-# endif- _ -> return (OpenNewError errno)- else return (NewFileCreated fd)--# ifdef mingw32_HOST_OS-foreign import ccall "file_exists" c_fileExists :: CString -> IO Bool-# endif-#endif---- XXX Should use filepath library-pathSeparator :: Char-#ifdef mingw32_HOST_OS-pathSeparator = '\\'-#else-pathSeparator = '/'-#endif--#ifndef __NHC__--- XXX Copied from GHC.Handle-std_flags, output_flags, rw_flags :: CInt-std_flags = o_NONBLOCK .|. o_NOCTTY-output_flags = std_flags .|. o_CREAT-rw_flags = output_flags .|. o_RDWR-#endif--#ifdef __NHC__-foreign import ccall "getpid" c_getpid :: IO Int-#endif---- $locking--- Implementations should enforce as far as possible, at least locally to the--- Haskell process, multiple-reader single-writer locking on files.--- That is, /there may either be many handles on the same file which manage input, or just one handle on the file which manages output/. If any--- open or semi-closed handle is managing a file for output, no new--- handle can be allocated for that file. If any open or semi-closed--- handle is managing a file for input, new handles can only be allocated--- if they do not manage output. Whether two files are the same is--- implementation-dependent, but they should normally be the same if they--- have the same absolute path name and neither has been renamed, for--- example.------ /Warning/: the 'readFile' operation holds a semi-closed handle on--- the file until the entire contents of the file have been consumed.--- It follows that an attempt to write to a file (using 'writeFile', for--- example) that was earlier opened by 'readFile' will usually result in--- failure with 'System.IO.Error.isAlreadyInUseError'.-
@@ -1,478 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : System.IO.Error--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Standard IO Errors.-----------------------------------------------------------------------------------module System.IO.Error (-- -- * I\/O errors- IOError, -- = IOException-- userError, -- :: String -> IOError-- mkIOError, -- :: IOErrorType -> String -> Maybe Handle- -- -> Maybe FilePath -> IOError-- annotateIOError, -- :: IOError -> String -> Maybe Handle- -- -> Maybe FilePath -> IOError-- -- ** Classifying I\/O errors- isAlreadyExistsError, -- :: IOError -> Bool- isDoesNotExistError,- isAlreadyInUseError,- isFullError, - isEOFError,- isIllegalOperation, - isPermissionError,- isUserError,-- -- ** Attributes of I\/O errors- ioeGetErrorType, -- :: IOError -> IOErrorType- ioeGetLocation, -- :: IOError -> String- ioeGetErrorString, -- :: IOError -> String- ioeGetHandle, -- :: IOError -> Maybe Handle- ioeGetFileName, -- :: IOError -> Maybe FilePath-- ioeSetErrorType, -- :: IOError -> IOErrorType -> IOError- ioeSetErrorString, -- :: IOError -> String -> IOError- ioeSetLocation, -- :: IOError -> String -> IOError- ioeSetHandle, -- :: IOError -> Handle -> IOError- ioeSetFileName, -- :: IOError -> FilePath -> IOError-- -- * Types of I\/O error- IOErrorType, -- abstract-- alreadyExistsErrorType, -- :: IOErrorType- doesNotExistErrorType,- alreadyInUseErrorType,- fullErrorType,- eofErrorType,- illegalOperationErrorType, - permissionErrorType,- userErrorType,-- -- ** 'IOErrorType' predicates- isAlreadyExistsErrorType, -- :: IOErrorType -> Bool- isDoesNotExistErrorType,- isAlreadyInUseErrorType,- isFullErrorType, - isEOFErrorType,- isIllegalOperationErrorType, - isPermissionErrorType,- isUserErrorType, -- -- * Throwing and catching I\/O errors-- ioError, -- :: IOError -> IO a-- catchIOError, -- :: IO a -> (IOError -> IO a) -> IO a- catch, -- :: IO a -> (IOError -> IO a) -> IO a- tryIOError, -- :: IO a -> IO (Either IOError a)- try, -- :: IO a -> IO (Either IOError a)-- modifyIOError, -- :: (IOError -> IOError) -> IO a -> IO a- ) where--#ifndef __HUGS__-import qualified Control.Exception.Base as New (catch)-#endif--#ifndef __HUGS__-import Data.Either-#endif-import Data.Maybe--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.IO-import GHC.IO.Exception-import GHC.IO.Handle.Types-import Text.Show-#endif--#ifdef __HUGS__-import Hugs.Prelude(Handle, IOException(..), IOErrorType(..), IO)-#endif--#ifdef __NHC__-import IO- ( IOError ()- , Handle ()- , try- , ioError- , userError- , isAlreadyExistsError -- :: IOError -> Bool- , isDoesNotExistError- , isAlreadyInUseError- , isFullError- , isEOFError- , isIllegalOperation- , isPermissionError- , isUserError- , ioeGetErrorString -- :: IOError -> String- , ioeGetHandle -- :: IOError -> Maybe Handle- , ioeGetFileName -- :: IOError -> Maybe FilePath- )-import qualified NHC.Internal as NHC (IOError(..))-import qualified NHC.DErrNo as NHC (ErrNo(..))-import Data.Maybe (fromJust)-import Control.Monad (MonadPlus(mplus))-#endif---- | The construct 'tryIOError' @comp@ exposes IO errors which occur within a--- computation, and which are not fully handled.------ Non-I\/O exceptions are not caught by this variant; to catch all--- exceptions, use 'Control.Exception.try' from "Control.Exception".-tryIOError :: IO a -> IO (Either IOError a)-tryIOError f = catch (do r <- f- return (Right r))- (return . Left)--#ifndef __NHC__-{-# DEPRECATED try "Please use the new exceptions variant, Control.Exception.try" #-}--- | The 'try' function is deprecated. Please use the new exceptions--- variant, 'Control.Exception.try' from "Control.Exception", instead.-try :: IO a -> IO (Either IOError a)-try f = catch (do r <- f- return (Right r))- (return . Left)-#endif--#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)--- -------------------------------------------------------------------------------- Constructing an IOError---- | Construct an 'IOError' of the given type where the second argument--- describes the error location and the third and fourth argument--- contain the file handle and file path of the file involved in the--- error if applicable.-mkIOError :: IOErrorType -> String -> Maybe Handle -> Maybe FilePath -> IOError-mkIOError t location maybe_hdl maybe_filename =- IOError{ ioe_type = t, - ioe_location = location,- ioe_description = "",-#if defined(__GLASGOW_HASKELL__)- ioe_errno = Nothing,-#endif- ioe_handle = maybe_hdl, - ioe_filename = maybe_filename- }-#endif /* __GLASGOW_HASKELL__ || __HUGS__ */-#ifdef __NHC__-mkIOError EOF location maybe_hdl maybe_filename =- NHC.EOFError location (fromJust maybe_hdl)-mkIOError UserError location maybe_hdl maybe_filename =- NHC.UserError location ""-mkIOError t location maybe_hdl maybe_filename =- NHC.IOError location maybe_filename maybe_hdl (ioeTypeToErrNo t)- where- ioeTypeToErrNo AlreadyExists = NHC.EEXIST- ioeTypeToErrNo NoSuchThing = NHC.ENOENT- ioeTypeToErrNo ResourceBusy = NHC.EBUSY- ioeTypeToErrNo ResourceExhausted = NHC.ENOSPC- ioeTypeToErrNo IllegalOperation = NHC.EPERM- ioeTypeToErrNo PermissionDenied = NHC.EACCES-#endif /* __NHC__ */--#ifndef __NHC__--- -------------------------------------------------------------------------------- IOErrorType---- | An error indicating that an 'IO' operation failed because--- one of its arguments already exists.-isAlreadyExistsError :: IOError -> Bool-isAlreadyExistsError = isAlreadyExistsErrorType . ioeGetErrorType---- | An error indicating that an 'IO' operation failed because--- one of its arguments does not exist.-isDoesNotExistError :: IOError -> Bool-isDoesNotExistError = isDoesNotExistErrorType . ioeGetErrorType---- | An error indicating that an 'IO' operation failed because--- one of its arguments is a single-use resource, which is already--- being used (for example, opening the same file twice for writing--- might give this error).-isAlreadyInUseError :: IOError -> Bool-isAlreadyInUseError = isAlreadyInUseErrorType . ioeGetErrorType---- | An error indicating that an 'IO' operation failed because--- the device is full.-isFullError :: IOError -> Bool-isFullError = isFullErrorType . ioeGetErrorType---- | An error indicating that an 'IO' operation failed because--- the end of file has been reached.-isEOFError :: IOError -> Bool-isEOFError = isEOFErrorType . ioeGetErrorType---- | An error indicating that an 'IO' operation failed because--- the operation was not possible.--- Any computation which returns an 'IO' result may fail with--- 'isIllegalOperation'. In some cases, an implementation will not be--- able to distinguish between the possible error causes. In this case--- it should fail with 'isIllegalOperation'.-isIllegalOperation :: IOError -> Bool-isIllegalOperation = isIllegalOperationErrorType . ioeGetErrorType---- | An error indicating that an 'IO' operation failed because--- the user does not have sufficient operating system privilege--- to perform that operation.-isPermissionError :: IOError -> Bool-isPermissionError = isPermissionErrorType . ioeGetErrorType---- | A programmer-defined error value constructed using 'userError'.-isUserError :: IOError -> Bool-isUserError = isUserErrorType . ioeGetErrorType-#endif /* __NHC__ */---- -------------------------------------------------------------------------------- IOErrorTypes--#ifdef __NHC__-data IOErrorType = AlreadyExists | NoSuchThing | ResourceBusy- | ResourceExhausted | EOF | IllegalOperation- | PermissionDenied | UserError-#endif---- | I\/O error where the operation failed because one of its arguments--- already exists.-alreadyExistsErrorType :: IOErrorType-alreadyExistsErrorType = AlreadyExists---- | I\/O error where the operation failed because one of its arguments--- does not exist.-doesNotExistErrorType :: IOErrorType-doesNotExistErrorType = NoSuchThing---- | I\/O error where the operation failed because one of its arguments--- is a single-use resource, which is already being used.-alreadyInUseErrorType :: IOErrorType-alreadyInUseErrorType = ResourceBusy---- | I\/O error where the operation failed because the device is full.-fullErrorType :: IOErrorType-fullErrorType = ResourceExhausted---- | I\/O error where the operation failed because the end of file has--- been reached.-eofErrorType :: IOErrorType-eofErrorType = EOF---- | I\/O error where the operation is not possible.-illegalOperationErrorType :: IOErrorType-illegalOperationErrorType = IllegalOperation---- | I\/O error where the operation failed because the user does not--- have sufficient operating system privilege to perform that operation.-permissionErrorType :: IOErrorType-permissionErrorType = PermissionDenied---- | I\/O error that is programmer-defined.-userErrorType :: IOErrorType-userErrorType = UserError---- -------------------------------------------------------------------------------- IOErrorType predicates---- | I\/O error where the operation failed because one of its arguments--- already exists.-isAlreadyExistsErrorType :: IOErrorType -> Bool-isAlreadyExistsErrorType AlreadyExists = True-isAlreadyExistsErrorType _ = False---- | I\/O error where the operation failed because one of its arguments--- does not exist.-isDoesNotExistErrorType :: IOErrorType -> Bool-isDoesNotExistErrorType NoSuchThing = True-isDoesNotExistErrorType _ = False---- | I\/O error where the operation failed because one of its arguments--- is a single-use resource, which is already being used.-isAlreadyInUseErrorType :: IOErrorType -> Bool-isAlreadyInUseErrorType ResourceBusy = True-isAlreadyInUseErrorType _ = False---- | I\/O error where the operation failed because the device is full.-isFullErrorType :: IOErrorType -> Bool-isFullErrorType ResourceExhausted = True-isFullErrorType _ = False---- | I\/O error where the operation failed because the end of file has--- been reached.-isEOFErrorType :: IOErrorType -> Bool-isEOFErrorType EOF = True-isEOFErrorType _ = False---- | I\/O error where the operation is not possible.-isIllegalOperationErrorType :: IOErrorType -> Bool-isIllegalOperationErrorType IllegalOperation = True-isIllegalOperationErrorType _ = False---- | I\/O error where the operation failed because the user does not--- have sufficient operating system privilege to perform that operation.-isPermissionErrorType :: IOErrorType -> Bool-isPermissionErrorType PermissionDenied = True-isPermissionErrorType _ = False---- | I\/O error that is programmer-defined.-isUserErrorType :: IOErrorType -> Bool-isUserErrorType UserError = True-isUserErrorType _ = False---- -------------------------------------------------------------------------------- Miscellaneous--#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)-ioeGetErrorType :: IOError -> IOErrorType-ioeGetErrorString :: IOError -> String-ioeGetLocation :: IOError -> String-ioeGetHandle :: IOError -> Maybe Handle-ioeGetFileName :: IOError -> Maybe FilePath--ioeGetErrorType ioe = ioe_type ioe--ioeGetErrorString ioe- | isUserErrorType (ioe_type ioe) = ioe_description ioe- | otherwise = show (ioe_type ioe)--ioeGetLocation ioe = ioe_location ioe--ioeGetHandle ioe = ioe_handle ioe--ioeGetFileName ioe = ioe_filename ioe--ioeSetErrorType :: IOError -> IOErrorType -> IOError-ioeSetErrorString :: IOError -> String -> IOError-ioeSetLocation :: IOError -> String -> IOError-ioeSetHandle :: IOError -> Handle -> IOError-ioeSetFileName :: IOError -> FilePath -> IOError--ioeSetErrorType ioe errtype = ioe{ ioe_type = errtype }-ioeSetErrorString ioe str = ioe{ ioe_description = str }-ioeSetLocation ioe str = ioe{ ioe_location = str }-ioeSetHandle ioe hdl = ioe{ ioe_handle = Just hdl }-ioeSetFileName ioe filename = ioe{ ioe_filename = Just filename }--#elif defined(__NHC__)-ioeGetErrorType :: IOError -> IOErrorType-ioeGetLocation :: IOError -> String--ioeGetErrorType e | isAlreadyExistsError e = AlreadyExists- | isDoesNotExistError e = NoSuchThing- | isAlreadyInUseError e = ResourceBusy- | isFullError e = ResourceExhausted- | isEOFError e = EOF- | isIllegalOperation e = IllegalOperation- | isPermissionError e = PermissionDenied- | isUserError e = UserError--ioeGetLocation (NHC.IOError _ _ _ _) = "unknown location"-ioeGetLocation (NHC.EOFError _ _ ) = "unknown location"-ioeGetLocation (NHC.PatternError loc) = loc-ioeGetLocation (NHC.UserError loc _) = loc--ioeSetErrorType :: IOError -> IOErrorType -> IOError-ioeSetErrorString :: IOError -> String -> IOError-ioeSetLocation :: IOError -> String -> IOError-ioeSetHandle :: IOError -> Handle -> IOError-ioeSetFileName :: IOError -> FilePath -> IOError--ioeSetErrorType e _ = e-ioeSetErrorString (NHC.IOError _ f h e) s = NHC.IOError s f h e-ioeSetErrorString (NHC.EOFError _ f) s = NHC.EOFError s f-ioeSetErrorString e@(NHC.PatternError _) _ = e-ioeSetErrorString (NHC.UserError l _) s = NHC.UserError l s-ioeSetLocation e@(NHC.IOError _ _ _ _) _ = e-ioeSetLocation e@(NHC.EOFError _ _) _ = e-ioeSetLocation (NHC.PatternError _) l = NHC.PatternError l-ioeSetLocation (NHC.UserError _ m) l = NHC.UserError l m-ioeSetHandle (NHC.IOError o f _ e) h = NHC.IOError o f (Just h) e-ioeSetHandle (NHC.EOFError o _) h = NHC.EOFError o h-ioeSetHandle e@(NHC.PatternError _) _ = e-ioeSetHandle e@(NHC.UserError _ _) _ = e-ioeSetFileName (NHC.IOError o _ h e) f = NHC.IOError o (Just f) h e-ioeSetFileName e _ = e-#endif---- | Catch any 'IOError' that occurs in the computation and throw a--- modified version.-modifyIOError :: (IOError -> IOError) -> IO a -> IO a-modifyIOError f io = catch io (\e -> ioError (f e))---- -------------------------------------------------------------------------------- annotating an IOError---- | Adds a location description and maybe a file path and file handle--- to an 'IOError'. If any of the file handle or file path is not given--- the corresponding value in the 'IOError' remains unaltered.-annotateIOError :: IOError - -> String - -> Maybe Handle - -> Maybe FilePath - -> IOError --#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)-annotateIOError ioe loc hdl path = - ioe{ ioe_handle = hdl `mplus` ioe_handle ioe,- ioe_location = loc, ioe_filename = path `mplus` ioe_filename ioe }- where- mplus :: Maybe a -> Maybe a -> Maybe a- Nothing `mplus` ys = ys- xs `mplus` _ = xs-#endif /* __GLASGOW_HASKELL__ || __HUGS__ */--#if defined(__NHC__)-annotateIOError (NHC.IOError msg file hdl code) msg' hdl' file' =- NHC.IOError (msg++'\n':msg') (file`mplus`file') (hdl`mplus`hdl') code-annotateIOError (NHC.EOFError msg hdl) msg' _ _ =- NHC.EOFError (msg++'\n':msg') hdl-annotateIOError (NHC.UserError loc msg) msg' _ _ =- NHC.UserError loc (msg++'\n':msg')-annotateIOError (NHC.PatternError loc) msg' _ _ =- NHC.PatternError (loc++'\n':msg')-#endif--#ifndef __HUGS__--- | The 'catchIOError' function establishes a handler that receives any--- 'IOError' raised in the action protected by 'catchIOError'.--- An 'IOError' is caught by--- the most recent handler established by one of the exception handling--- functions. These handlers are--- not selective: all 'IOError's are caught. Exception propagation--- must be explicitly provided in a handler by re-raising any unwanted--- exceptions. For example, in------ > f = catchIOError g (\e -> if IO.isEOFError e then return [] else ioError e)------ the function @f@ returns @[]@ when an end-of-file exception--- (cf. 'System.IO.Error.isEOFError') occurs in @g@; otherwise, the--- exception is propagated to the next outer handler.------ When an exception propagates outside the main program, the Haskell--- system prints the associated 'IOError' value and exits the program.------ Non-I\/O exceptions are not caught by this variant; to catch all--- exceptions, use 'Control.Exception.catch' from "Control.Exception".-catchIOError :: IO a -> (IOError -> IO a) -> IO a-catchIOError = New.catch--{-# DEPRECATED catch "Please use the new exceptions variant, Control.Exception.catch" #-}--- | The 'catch' function is deprecated. Please use the new exceptions--- variant, 'Control.Exception.catch' from "Control.Exception", instead.-catch :: IO a -> (IOError -> IO a) -> IO a-catch = New.catch-#endif /* !__HUGS__ */-
@@ -1,61 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : System.IO.Unsafe--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ \"Unsafe\" IO operations.-----------------------------------------------------------------------------------module System.IO.Unsafe (- -- * Unsafe 'System.IO.IO' operations- unsafePerformIO, -- :: IO a -> a- unsafeDupablePerformIO, -- :: IO a -> a- unsafeInterleaveIO, -- :: IO a -> IO a- unsafeFixIO,- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.IO-import GHC.IORef-import GHC.Exception-import Control.Exception-#endif--#ifdef __HUGS__-import Hugs.IOExts (unsafePerformIO, unsafeInterleaveIO)-unsafeDupablePerformIO = unsafePerformIO-#endif--#ifdef __NHC__-import NHC.Internal (unsafePerformIO, unsafeInterleaveIO)-unsafeDupablePerformIO = unsafePerformIO-#endif---- | A slightly faster version of `System.IO.fixIO` that may not be--- safe to use with multiple threads. The unsafety arises when used--- like this:------ > unsafeFixIO $ \r ->--- > forkIO (print r)--- > return (...)------ In this case, the child thread will receive a @NonTermination@--- exception instead of waiting for the value of @r@ to be computed.----unsafeFixIO :: (a -> IO a) -> IO a-unsafeFixIO k = do- ref <- newIORef (throw NonTermination)- ans <- unsafeDupableInterleaveIO (readIORef ref)- result <- k ans- writeIORef ref result- return result
@@ -1,70 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : System.Info--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Information about the characteristics of the host --- system lucky enough to run your program.-----------------------------------------------------------------------------------module System.Info- (- os, -- :: String- arch, -- :: String- compilerName, -- :: String- compilerVersion -- :: Version- ) where--import Prelude-import Data.Version---- | The version of 'compilerName' with which the program was compiled--- or is being interpreted.-compilerVersion :: Version-compilerVersion = Version {versionBranch=[major, minor], versionTags=[]}- where (major, minor) = compilerVersionRaw `divMod` 100---- | The operating system on which the program is running.-os :: String---- | The machine architecture on which the program is running.-arch :: String---- | The Haskell implementation with which the program was compiled--- or is being interpreted.-compilerName :: String--compilerVersionRaw :: Int--#if defined(__NHC__)-#include "OSInfo.hs"-compilerName = "nhc98"-compilerVersionRaw = __NHC__--#elif defined(__GLASGOW_HASKELL__)-#include "ghcplatform.h"-os = HOST_OS-arch = HOST_ARCH-compilerName = "ghc"-compilerVersionRaw = __GLASGOW_HASKELL__--#elif defined(__HUGS__)-#include "platform.h"-os = HOST_OS-arch = HOST_ARCH-compilerName = "hugs"-compilerVersionRaw = 0 -- ToDo--#else-#error Unknown compiler name-#endif-
@@ -1,39 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE ForeignFunctionInterface #-}-#endif---------------------------------------------------------------------------------- |--- Module : System.Mem--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Memory-related system things.-----------------------------------------------------------------------------------module System.Mem (- performGC -- :: IO ()- ) where- -import Prelude--#ifdef __HUGS__-import Hugs.IOExts-#endif--#ifdef __GLASGOW_HASKELL__--- | Triggers an immediate garbage collection-foreign import ccall {-safe-} "performMajorGC" performGC :: IO ()-#endif--#ifdef __NHC__-import NHC.IOExtras (performGC)-#endif-
@@ -1,127 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-{-# LANGUAGE MagicHash #-}-#if !defined(__PARALLEL_HASKELL__)-{-# LANGUAGE UnboxedTuples #-}-#endif-#endif---------------------------------------------------------------------------------- |--- Module : System.Mem.StableName--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable------ Stable names are a way of performing fast (O(1)), not-quite-exact--- comparison between objects.--- --- Stable names solve the following problem: suppose you want to build--- a hash table with Haskell objects as keys, but you want to use--- pointer equality for comparison; maybe because the keys are large--- and hashing would be slow, or perhaps because the keys are infinite--- in size. We can\'t build a hash table using the address of the--- object as the key, because objects get moved around by the garbage--- collector, meaning a re-hash would be necessary after every garbage--- collection.-------------------------------------------------------------------------------------module System.Mem.StableName (- -- * Stable Names- StableName,- makeStableName,- hashStableName,- ) where--import Prelude--import Data.Typeable--#ifdef __HUGS__-import Hugs.Stable-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.IO ( IO(..) )-import GHC.Base ( Int(..), StableName#, makeStableName#- , eqStableName#, stableNameToInt# )---------------------------------------------------------------------------------- Stable Names--{-|- An abstract name for an object, that supports equality and hashing.-- Stable names have the following property:-- * If @sn1 :: StableName@ and @sn2 :: StableName@ and @sn1 == sn2@- then @sn1@ and @sn2@ were created by calls to @makeStableName@ on - the same object.-- The reverse is not necessarily true: if two stable names are not- equal, then the objects they name may still be equal. Note in particular- that `mkStableName` may return a different `StableName` after an- object is evaluated.-- Stable Names are similar to Stable Pointers ("Foreign.StablePtr"),- but differ in the following ways:-- * There is no @freeStableName@ operation, unlike "Foreign.StablePtr"s.- Stable names are reclaimed by the runtime system when they are no- longer needed.-- * There is no @deRefStableName@ operation. You can\'t get back from- a stable name to the original Haskell object. The reason for- this is that the existence of a stable name for an object does not- guarantee the existence of the object itself; it can still be garbage- collected.--}--data StableName a = StableName (StableName# a)----- | Makes a 'StableName' for an arbitrary object. The object passed as--- the first argument is not evaluated by 'makeStableName'.-makeStableName :: a -> IO (StableName a)-#if defined(__PARALLEL_HASKELL__)-makeStableName a = - error "makeStableName not implemented in parallel Haskell"-#else-makeStableName a = IO $ \ s ->- case makeStableName# a s of (# s', sn #) -> (# s', StableName sn #)-#endif---- | Convert a 'StableName' to an 'Int'. The 'Int' returned is not--- necessarily unique; several 'StableName's may map to the same 'Int'--- (in practice however, the chances of this are small, so the result--- of 'hashStableName' makes a good hash key).-hashStableName :: StableName a -> Int-#if defined(__PARALLEL_HASKELL__)-hashStableName (StableName sn) = - error "hashStableName not implemented in parallel Haskell"-#else-hashStableName (StableName sn) = I# (stableNameToInt# sn)-#endif--instance Eq (StableName a) where -#if defined(__PARALLEL_HASKELL__)- (StableName sn1) == (StableName sn2) = - error "eqStableName not implemented in parallel Haskell"-#else- (StableName sn1) == (StableName sn2) = - case eqStableName# sn1 sn2 of- 0# -> False- _ -> True-#endif--#endif /* __GLASGOW_HASKELL__ */--#include "Typeable.h"-INSTANCE_TYPEABLE1(StableName,stableNameTc,"StableName")-
@@ -1,154 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : System.Mem.Weak--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable------ In general terms, a weak pointer is a reference to an object that is--- not followed by the garbage collector - that is, the existence of a--- weak pointer to an object has no effect on the lifetime of that--- object. A weak pointer can be de-referenced to find out--- whether the object it refers to is still alive or not, and if so--- to return the object itself.--- --- Weak pointers are particularly useful for caches and memo tables.--- To build a memo table, you build a data structure --- mapping from the function argument (the key) to its result (the--- value). When you apply the function to a new argument you first--- check whether the key\/value pair is already in the memo table.--- The key point is that the memo table itself should not keep the--- key and value alive. So the table should contain a weak pointer--- to the key, not an ordinary pointer. The pointer to the value must--- not be weak, because the only reference to the value might indeed be--- from the memo table. --- --- So it looks as if the memo table will keep all its values--- alive for ever. One way to solve this is to purge the table--- occasionally, by deleting entries whose keys have died.--- --- The weak pointers in this library--- support another approach, called /finalization/.--- When the key referred to by a weak pointer dies, the storage manager--- arranges to run a programmer-specified finalizer. In the case of memo--- tables, for example, the finalizer could remove the key\/value pair--- from the memo table. --- --- Another difficulty with the memo table is that the value of a--- key\/value pair might itself contain a pointer to the key.--- So the memo table keeps the value alive, which keeps the key alive,--- even though there may be no other references to the key so both should--- die. The weak pointers in this library provide a slight --- generalisation of the basic weak-pointer idea, in which each--- weak pointer actually contains both a key and a value.-----------------------------------------------------------------------------------module System.Mem.Weak (- -- * The @Weak@ type- Weak, -- abstract-- -- * The general interface- mkWeak, -- :: k -> v -> Maybe (IO ()) -> IO (Weak v)- deRefWeak, -- :: Weak v -> IO (Maybe v)- finalize, -- :: Weak v -> IO ()-- -- * Specialised versions- mkWeakPtr, -- :: k -> Maybe (IO ()) -> IO (Weak k)- addFinalizer, -- :: key -> IO () -> IO ()- mkWeakPair, -- :: k -> v -> Maybe (IO ()) -> IO (Weak (k,v))- -- replaceFinaliser -- :: Weak v -> IO () -> IO ()-- -- * A precise semantics- - -- $precise- ) where--#ifdef __HUGS__-import Hugs.Weak-import Prelude-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.Weak-#endif---- | A specialised version of 'mkWeak', where the key and the value are--- the same object:------ > mkWeakPtr key finalizer = mkWeak key key finalizer----mkWeakPtr :: k -> Maybe (IO ()) -> IO (Weak k)-mkWeakPtr key finalizer = mkWeak key key finalizer--{-|- A specialised version of 'mkWeakPtr', where the 'Weak' object- returned is simply thrown away (however the finalizer will be- remembered by the garbage collector, and will still be run- when the key becomes unreachable).-- Note: adding a finalizer to a 'Foreign.ForeignPtr.ForeignPtr' using- 'addFinalizer' won't work as well as using the specialised version- 'Foreign.ForeignPtr.addForeignPtrFinalizer' because the latter- version adds the finalizer to the primitive 'ForeignPtr#' object- inside, whereas the generic 'addFinalizer' will add the finalizer to- the box. Optimisations tend to remove the box, which may cause the- finalizer to run earlier than you intended. The same motivation- justifies the existence of- 'Control.Concurrent.MVar.addMVarFinalizer' and- 'Data.IORef.mkWeakIORef' (the non-uniformity is accidental).--}-addFinalizer :: key -> IO () -> IO ()-addFinalizer key finalizer = do- _ <- mkWeakPtr key (Just finalizer) -- throw it away- return ()---- | A specialised version of 'mkWeak' where the value is actually a pair--- of the key and value passed to 'mkWeakPair':------ > mkWeakPair key val finalizer = mkWeak key (key,val) finalizer------ The advantage of this is that the key can be retrieved by 'deRefWeak'--- in addition to the value.-mkWeakPair :: k -> v -> Maybe (IO ()) -> IO (Weak (k,v))-mkWeakPair key val finalizer = mkWeak key (key,val) finalizer---{- $precise--The above informal specification is fine for simple situations, but-matters can get complicated. In particular, it needs to be clear-exactly when a key dies, so that any weak pointers that refer to it-can be finalized. Suppose, for example, the value of one weak pointer-refers to the key of another...does that keep the key alive?--The behaviour is simply this:-- * If a weak pointer (object) refers to an /unreachable/- key, it may be finalized.-- * Finalization means (a) arrange that subsequent calls- to 'deRefWeak' return 'Nothing'; and (b) run the finalizer.--This behaviour depends on what it means for a key to be reachable.-Informally, something is reachable if it can be reached by following-ordinary pointers from the root set, but not following weak pointers.-We define reachability more precisely as follows A heap object is-reachable if:-- * It is a member of the /root set/.-- * It is directly pointed to by a reachable object, other than- a weak pointer object.-- * It is a weak pointer object whose key is reachable.-- * It is the value or finalizer of an object whose key is reachable.--}-
@@ -1,581 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude, ForeignFunctionInterface, CApiFFI #-}-{-# OPTIONS_HADDOCK hide #-}---------------------------------------------------------------------------------- |--- Module : System.Posix.Internals--- Copyright : (c) The University of Glasgow, 1992-2002--- License : see libraries/base/LICENSE--- --- Maintainer : cvs-ghc@haskell.org--- Stability : internal--- Portability : non-portable (requires POSIX)------ POSIX support layer for the standard libraries.--- This library is built on *every* platform, including Win32.------ Non-posix compliant in order to support the following features:--- * S_ISSOCK (no sockets in POSIX)------------------------------------------------------------------------------------- #hide-module System.Posix.Internals where--#ifdef __NHC__-#define HTYPE_TCFLAG_T-#else-# include "HsBaseConfig.h"-#endif--#if ! (defined(mingw32_HOST_OS) || defined(__MINGW32__))-import Control.Monad-#endif-import System.Posix.Types--import Foreign-import Foreign.C---- import Data.Bits-import Data.Maybe--#if !defined(HTYPE_TCFLAG_T)-import System.IO.Error-#endif--#if __GLASGOW_HASKELL__-import GHC.Base-import GHC.Num-import GHC.Real-import GHC.IO-import GHC.IO.IOMode-import GHC.IO.Exception-import GHC.IO.Device-#ifndef mingw32_HOST_OS-import {-# SOURCE #-} GHC.IO.Encoding (getFileSystemEncoding)-import qualified GHC.Foreign as GHC-#endif-#elif __HUGS__-import Hugs.Prelude (IOException(..), IOErrorType(..))-import Hugs.IO (IOMode(..))-#elif __NHC__-import GHC.IO.Device -- yes, I know, but its portable, really!-import System.IO-import Control.Exception-import DIOError-#endif--#ifdef __HUGS__-{-# CFILES cbits/PrelIOUtils.c cbits/consUtils.c #-}-#endif----- ------------------------------------------------------------------------------ Debugging the base package--puts :: String -> IO ()-puts s = withCAStringLen (s ++ "\n") $ \(p, len) -> do- -- In reality should be withCString, but assume ASCII to avoid loop- -- if this is called by GHC.Foreign- _ <- c_write 1 (castPtr p) (fromIntegral len)- return ()----- ------------------------------------------------------------------------------ Types--type CFLock = ()-type CGroup = ()-type CLconv = ()-type CPasswd = ()-type CSigaction = ()-type CSigset = ()-type CStat = ()-type CTermios = ()-type CTm = ()-type CTms = ()-type CUtimbuf = ()-type CUtsname = ()--type FD = CInt---- ------------------------------------------------------------------------------ stat()-related stuff--fdFileSize :: FD -> IO Integer-fdFileSize fd = - allocaBytes sizeof_stat $ \ p_stat -> do- throwErrnoIfMinus1Retry_ "fileSize" $- c_fstat fd p_stat- c_mode <- st_mode p_stat :: IO CMode - if not (s_isreg c_mode)- then return (-1)- else do- c_size <- st_size p_stat- return (fromIntegral c_size)--fileType :: FilePath -> IO IODeviceType-fileType file =- allocaBytes sizeof_stat $ \ p_stat -> do- withFilePath file $ \p_file -> do- throwErrnoIfMinus1Retry_ "fileType" $- c_stat p_file p_stat- statGetType p_stat---- NOTE: On Win32 platforms, this will only work with file descriptors--- referring to file handles. i.e., it'll fail for socket FDs.-fdStat :: FD -> IO (IODeviceType, CDev, CIno)-fdStat fd = - allocaBytes sizeof_stat $ \ p_stat -> do- throwErrnoIfMinus1Retry_ "fdType" $- c_fstat fd p_stat- ty <- statGetType p_stat- dev <- st_dev p_stat- ino <- st_ino p_stat- return (ty,dev,ino)- -fdType :: FD -> IO IODeviceType-fdType fd = do (ty,_,_) <- fdStat fd; return ty--statGetType :: Ptr CStat -> IO IODeviceType-statGetType p_stat = do- c_mode <- st_mode p_stat :: IO CMode- case () of- _ | s_isdir c_mode -> return Directory- | s_isfifo c_mode || s_issock c_mode || s_ischr c_mode- -> return Stream- | s_isreg c_mode -> return RegularFile- -- Q: map char devices to RawDevice too?- | s_isblk c_mode -> return RawDevice- | otherwise -> ioError ioe_unknownfiletype- -ioe_unknownfiletype :: IOException-#ifndef __NHC__-ioe_unknownfiletype = IOError Nothing UnsupportedOperation "fdType"- "unknown file type"-# if __GLASGOW_HASKELL__- Nothing-# endif- Nothing-#else-ioe_unknownfiletype = UserError "fdType" "unknown file type"-#endif--fdGetMode :: FD -> IO IOMode-#if defined(mingw32_HOST_OS) || defined(__MINGW32__)-fdGetMode _ = do- -- We don't have a way of finding out which flags are set on FDs- -- on Windows, so make a handle that thinks that anything goes.- let flags = o_RDWR-#else-fdGetMode fd = do- flags <- throwErrnoIfMinus1Retry "fdGetMode" - (c_fcntl_read fd const_f_getfl)-#endif- let- wH = (flags .&. o_WRONLY) /= 0- aH = (flags .&. o_APPEND) /= 0- rwH = (flags .&. o_RDWR) /= 0-- mode- | wH && aH = AppendMode- | wH = WriteMode- | rwH = ReadWriteMode- | otherwise = ReadMode- - return mode--#ifdef mingw32_HOST_OS-withFilePath :: FilePath -> (CWString -> IO a) -> IO a-withFilePath = withCWString--peekFilePath :: CWString -> IO FilePath-peekFilePath = peekCWString-#else--withFilePath :: FilePath -> (CString -> IO a) -> IO a-peekFilePath :: CString -> IO FilePath-peekFilePathLen :: CStringLen -> IO FilePath--#if __GLASGOW_HASKELL__-withFilePath fp f = getFileSystemEncoding >>= \enc -> GHC.withCString enc fp f-peekFilePath fp = getFileSystemEncoding >>= \enc -> GHC.peekCString enc fp-peekFilePathLen fp = getFileSystemEncoding >>= \enc -> GHC.peekCStringLen enc fp-#else-withFilePath = withCString-peekFilePath = peekCString-peekFilePathLen = peekCStringLen-#endif--#endif---- ------------------------------------------------------------------------------ Terminal-related stuff--#if defined(HTYPE_TCFLAG_T)--setEcho :: FD -> Bool -> IO ()-setEcho fd on = do- tcSetAttr fd $ \ p_tios -> do- lflag <- c_lflag p_tios :: IO CTcflag- let new_lflag- | on = lflag .|. fromIntegral const_echo- | otherwise = lflag .&. complement (fromIntegral const_echo)- poke_c_lflag p_tios (new_lflag :: CTcflag)--getEcho :: FD -> IO Bool-getEcho fd = do- tcSetAttr fd $ \ p_tios -> do- lflag <- c_lflag p_tios :: IO CTcflag- return ((lflag .&. fromIntegral const_echo) /= 0)--setCooked :: FD -> Bool -> IO ()-setCooked fd cooked = - tcSetAttr fd $ \ p_tios -> do-- -- turn on/off ICANON- lflag <- c_lflag p_tios :: IO CTcflag- let new_lflag | cooked = lflag .|. (fromIntegral const_icanon)- | otherwise = lflag .&. complement (fromIntegral const_icanon)- poke_c_lflag p_tios (new_lflag :: CTcflag)-- -- set VMIN & VTIME to 1/0 respectively- when (not cooked) $ do- c_cc <- ptr_c_cc p_tios- let vmin = (c_cc `plusPtr` (fromIntegral const_vmin)) :: Ptr Word8- vtime = (c_cc `plusPtr` (fromIntegral const_vtime)) :: Ptr Word8- poke vmin 1- poke vtime 0--tcSetAttr :: FD -> (Ptr CTermios -> IO a) -> IO a-tcSetAttr fd fun = do- allocaBytes sizeof_termios $ \p_tios -> do- throwErrnoIfMinus1Retry_ "tcSetAttr"- (c_tcgetattr fd p_tios)--#ifdef __GLASGOW_HASKELL__- -- Save a copy of termios, if this is a standard file descriptor.- -- These terminal settings are restored in hs_exit().- when (fd <= 2) $ do- p <- get_saved_termios fd- when (p == nullPtr) $ do- saved_tios <- mallocBytes sizeof_termios- copyBytes saved_tios p_tios sizeof_termios- set_saved_termios fd saved_tios-#endif-- -- tcsetattr() when invoked by a background process causes the process- -- to be sent SIGTTOU regardless of whether the process has TOSTOP set- -- in its terminal flags (try it...). This function provides a- -- wrapper which temporarily blocks SIGTTOU around the call, making it- -- transparent.- allocaBytes sizeof_sigset_t $ \ p_sigset -> do- allocaBytes sizeof_sigset_t $ \ p_old_sigset -> do- throwErrnoIfMinus1_ "sigemptyset" $- c_sigemptyset p_sigset- throwErrnoIfMinus1_ "sigaddset" $- c_sigaddset p_sigset const_sigttou- throwErrnoIfMinus1_ "sigprocmask" $- c_sigprocmask const_sig_block p_sigset p_old_sigset- r <- fun p_tios -- do the business- throwErrnoIfMinus1Retry_ "tcSetAttr" $- c_tcsetattr fd const_tcsanow p_tios- throwErrnoIfMinus1_ "sigprocmask" $- c_sigprocmask const_sig_setmask p_old_sigset nullPtr- return r--#ifdef __GLASGOW_HASKELL__-foreign import ccall unsafe "HsBase.h __hscore_get_saved_termios"- get_saved_termios :: CInt -> IO (Ptr CTermios)--foreign import ccall unsafe "HsBase.h __hscore_set_saved_termios"- set_saved_termios :: CInt -> (Ptr CTermios) -> IO ()-#endif--#else---- 'raw' mode for Win32 means turn off 'line input' (=> buffering and--- character translation for the console.) The Win32 API for doing--- this is GetConsoleMode(), which also requires echoing to be disabled--- when turning off 'line input' processing. Notice that turning off--- 'line input' implies enter/return is reported as '\r' (and it won't--- report that character until another character is input..odd.) This--- latter feature doesn't sit too well with IO actions like IO.hGetLine..--- consider yourself warned.-setCooked :: FD -> Bool -> IO ()-setCooked fd cooked = do- x <- set_console_buffering fd (if cooked then 1 else 0)- if (x /= 0)- then ioError (ioe_unk_error "setCooked" "failed to set buffering")- else return ()--ioe_unk_error :: String -> String -> IOException-ioe_unk_error loc msg -#ifndef __NHC__- = ioeSetErrorString (mkIOError OtherError loc Nothing Nothing) msg-#else- = UserError loc msg-#endif---- Note: echoing goes hand in hand with enabling 'line input' / raw-ness--- for Win32 consoles, hence setEcho ends up being the inverse of setCooked.-setEcho :: FD -> Bool -> IO ()-setEcho fd on = do- x <- set_console_echo fd (if on then 1 else 0)- if (x /= 0)- then ioError (ioe_unk_error "setEcho" "failed to set echoing")- else return ()--getEcho :: FD -> IO Bool-getEcho fd = do- r <- get_console_echo fd- if (r == (-1))- then ioError (ioe_unk_error "getEcho" "failed to get echoing")- else return (r == 1)--foreign import ccall unsafe "consUtils.h set_console_buffering__"- set_console_buffering :: CInt -> CInt -> IO CInt--foreign import ccall unsafe "consUtils.h set_console_echo__"- set_console_echo :: CInt -> CInt -> IO CInt--foreign import ccall unsafe "consUtils.h get_console_echo__"- get_console_echo :: CInt -> IO CInt--foreign import ccall unsafe "consUtils.h is_console__"- is_console :: CInt -> IO CInt--#endif---- ------------------------------------------------------------------------------ Turning on non-blocking for a file descriptor--setNonBlockingFD :: FD -> Bool -> IO ()-#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)-setNonBlockingFD fd set = do- flags <- throwErrnoIfMinus1Retry "setNonBlockingFD"- (c_fcntl_read fd const_f_getfl)- let flags' | set = flags .|. o_NONBLOCK- | otherwise = flags .&. complement o_NONBLOCK- unless (flags == flags') $ do- -- An error when setting O_NONBLOCK isn't fatal: on some systems- -- there are certain file handles on which this will fail (eg. /dev/null- -- on FreeBSD) so we throw away the return code from fcntl_write.- _ <- c_fcntl_write fd const_f_setfl (fromIntegral flags')- return ()-#else---- bogus defns for win32-setNonBlockingFD _ _ = return ()--#endif---- -------------------------------------------------------------------------------- Set close-on-exec for a file descriptor--#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)-setCloseOnExec :: FD -> IO ()-setCloseOnExec fd = do- throwErrnoIfMinus1_ "setCloseOnExec" $- c_fcntl_write fd const_f_setfd const_fd_cloexec-#endif---- -------------------------------------------------------------------------------- foreign imports--#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)-type CFilePath = CString-#else-type CFilePath = CWString-#endif--foreign import ccall unsafe "HsBase.h access"- c_access :: CString -> CInt -> IO CInt--foreign import ccall unsafe "HsBase.h chmod"- c_chmod :: CString -> CMode -> IO CInt--foreign import ccall unsafe "HsBase.h close"- c_close :: CInt -> IO CInt--foreign import ccall unsafe "HsBase.h creat"- c_creat :: CString -> CMode -> IO CInt--foreign import ccall unsafe "HsBase.h dup"- c_dup :: CInt -> IO CInt--foreign import ccall unsafe "HsBase.h dup2"- c_dup2 :: CInt -> CInt -> IO CInt--foreign import ccall unsafe "HsBase.h __hscore_fstat"- c_fstat :: CInt -> Ptr CStat -> IO CInt--foreign import ccall unsafe "HsBase.h isatty"- c_isatty :: CInt -> IO CInt--#if defined(mingw32_HOST_OS) || defined(__MINGW32__)-foreign import ccall unsafe "HsBase.h __hscore_lseek"- c_lseek :: CInt -> Int64 -> CInt -> IO Int64-#else-foreign import ccall unsafe "HsBase.h __hscore_lseek"- c_lseek :: CInt -> COff -> CInt -> IO COff-#endif--foreign import ccall unsafe "HsBase.h __hscore_lstat"- lstat :: CFilePath -> Ptr CStat -> IO CInt--foreign import ccall unsafe "HsBase.h __hscore_open"- c_open :: CFilePath -> CInt -> CMode -> IO CInt--foreign import ccall safe "HsBase.h __hscore_open"- c_safe_open :: CFilePath -> CInt -> CMode -> IO CInt--foreign import ccall unsafe "HsBase.h read" - c_read :: CInt -> Ptr Word8 -> CSize -> IO CSsize--foreign import ccall safe "HsBase.h read"- c_safe_read :: CInt -> Ptr Word8 -> CSize -> IO CSsize--foreign import ccall unsafe "HsBase.h __hscore_stat"- c_stat :: CFilePath -> Ptr CStat -> IO CInt--foreign import ccall unsafe "HsBase.h umask"- c_umask :: CMode -> IO CMode--foreign import ccall unsafe "HsBase.h write" - c_write :: CInt -> Ptr Word8 -> CSize -> IO CSsize--foreign import ccall safe "HsBase.h write"- c_safe_write :: CInt -> Ptr Word8 -> CSize -> IO CSsize--foreign import ccall unsafe "HsBase.h __hscore_ftruncate"- c_ftruncate :: CInt -> COff -> IO CInt--foreign import ccall unsafe "HsBase.h unlink"- c_unlink :: CString -> IO CInt--foreign import ccall unsafe "HsBase.h getpid"- c_getpid :: IO CPid--#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)-foreign import capi unsafe "HsBase.h fcntl"- c_fcntl_read :: CInt -> CInt -> IO CInt--foreign import capi unsafe "HsBase.h fcntl"- c_fcntl_write :: CInt -> CInt -> CLong -> IO CInt--foreign import capi unsafe "HsBase.h fcntl"- c_fcntl_lock :: CInt -> CInt -> Ptr CFLock -> IO CInt--foreign import ccall unsafe "HsBase.h fork"- c_fork :: IO CPid --foreign import ccall unsafe "HsBase.h link"- c_link :: CString -> CString -> IO CInt--foreign import ccall unsafe "HsBase.h mkfifo"- c_mkfifo :: CString -> CMode -> IO CInt--foreign import ccall unsafe "HsBase.h pipe"- c_pipe :: Ptr CInt -> IO CInt--foreign import ccall unsafe "HsBase.h __hscore_sigemptyset"- c_sigemptyset :: Ptr CSigset -> IO CInt--foreign import ccall unsafe "HsBase.h __hscore_sigaddset"- c_sigaddset :: Ptr CSigset -> CInt -> IO CInt--foreign import ccall unsafe "HsBase.h sigprocmask"- c_sigprocmask :: CInt -> Ptr CSigset -> Ptr CSigset -> IO CInt--foreign import ccall unsafe "HsBase.h tcgetattr"- c_tcgetattr :: CInt -> Ptr CTermios -> IO CInt--foreign import ccall unsafe "HsBase.h tcsetattr"- c_tcsetattr :: CInt -> CInt -> Ptr CTermios -> IO CInt--foreign import capi unsafe "HsBase.h utime"- c_utime :: CString -> Ptr CUtimbuf -> IO CInt--foreign import ccall unsafe "HsBase.h waitpid"- c_waitpid :: CPid -> Ptr CInt -> CInt -> IO CPid-#endif---- POSIX flags only:-foreign import ccall unsafe "HsBase.h __hscore_o_rdonly" o_RDONLY :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_wronly" o_WRONLY :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_rdwr" o_RDWR :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_append" o_APPEND :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_creat" o_CREAT :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_excl" o_EXCL :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_trunc" o_TRUNC :: CInt---- non-POSIX flags.-foreign import ccall unsafe "HsBase.h __hscore_o_noctty" o_NOCTTY :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_nonblock" o_NONBLOCK :: CInt-foreign import ccall unsafe "HsBase.h __hscore_o_binary" o_BINARY :: CInt--foreign import ccall unsafe "HsBase.h __hscore_s_isreg" c_s_isreg :: CMode -> CInt-foreign import ccall unsafe "HsBase.h __hscore_s_ischr" c_s_ischr :: CMode -> CInt-foreign import ccall unsafe "HsBase.h __hscore_s_isblk" c_s_isblk :: CMode -> CInt-foreign import ccall unsafe "HsBase.h __hscore_s_isdir" c_s_isdir :: CMode -> CInt-foreign import ccall unsafe "HsBase.h __hscore_s_isfifo" c_s_isfifo :: CMode -> CInt--s_isreg :: CMode -> Bool-s_isreg cm = c_s_isreg cm /= 0-s_ischr :: CMode -> Bool-s_ischr cm = c_s_ischr cm /= 0-s_isblk :: CMode -> Bool-s_isblk cm = c_s_isblk cm /= 0-s_isdir :: CMode -> Bool-s_isdir cm = c_s_isdir cm /= 0-s_isfifo :: CMode -> Bool-s_isfifo cm = c_s_isfifo cm /= 0--foreign import ccall unsafe "HsBase.h __hscore_sizeof_stat" sizeof_stat :: Int-foreign import ccall unsafe "HsBase.h __hscore_st_mtime" st_mtime :: Ptr CStat -> IO CTime-#ifdef mingw32_HOST_OS-foreign import ccall unsafe "HsBase.h __hscore_st_size" st_size :: Ptr CStat -> IO Int64-#else-foreign import ccall unsafe "HsBase.h __hscore_st_size" st_size :: Ptr CStat -> IO COff-#endif-foreign import ccall unsafe "HsBase.h __hscore_st_mode" st_mode :: Ptr CStat -> IO CMode-foreign import ccall unsafe "HsBase.h __hscore_st_dev" st_dev :: Ptr CStat -> IO CDev-foreign import ccall unsafe "HsBase.h __hscore_st_ino" st_ino :: Ptr CStat -> IO CIno--foreign import ccall unsafe "HsBase.h __hscore_echo" const_echo :: CInt-foreign import ccall unsafe "HsBase.h __hscore_tcsanow" const_tcsanow :: CInt-foreign import ccall unsafe "HsBase.h __hscore_icanon" const_icanon :: CInt-foreign import ccall unsafe "HsBase.h __hscore_vmin" const_vmin :: CInt-foreign import ccall unsafe "HsBase.h __hscore_vtime" const_vtime :: CInt-foreign import ccall unsafe "HsBase.h __hscore_sigttou" const_sigttou :: CInt-foreign import ccall unsafe "HsBase.h __hscore_sig_block" const_sig_block :: CInt-foreign import ccall unsafe "HsBase.h __hscore_sig_setmask" const_sig_setmask :: CInt-foreign import ccall unsafe "HsBase.h __hscore_f_getfl" const_f_getfl :: CInt-foreign import ccall unsafe "HsBase.h __hscore_f_setfl" const_f_setfl :: CInt-foreign import ccall unsafe "HsBase.h __hscore_f_setfd" const_f_setfd :: CInt-foreign import ccall unsafe "HsBase.h __hscore_fd_cloexec" const_fd_cloexec :: CLong--#if defined(HTYPE_TCFLAG_T)-foreign import ccall unsafe "HsBase.h __hscore_sizeof_termios" sizeof_termios :: Int-foreign import ccall unsafe "HsBase.h __hscore_sizeof_sigset_t" sizeof_sigset_t :: Int--foreign import ccall unsafe "HsBase.h __hscore_lflag" c_lflag :: Ptr CTermios -> IO CTcflag-foreign import ccall unsafe "HsBase.h __hscore_poke_lflag" poke_c_lflag :: Ptr CTermios -> CTcflag -> IO ()-foreign import ccall unsafe "HsBase.h __hscore_ptr_c_cc" ptr_c_cc :: Ptr CTermios -> IO (Ptr Word8)-#endif--s_issock :: CMode -> Bool-#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)-s_issock cmode = c_s_issock cmode /= 0-foreign import ccall unsafe "HsBase.h __hscore_s_issock" c_s_issock :: CMode -> CInt-#else-s_issock _ = False-#endif--foreign import ccall unsafe "__hscore_bufsiz" dEFAULT_BUFFER_SIZE :: Int-foreign import ccall unsafe "__hscore_seek_cur" sEEK_CUR :: CInt-foreign import ccall unsafe "__hscore_seek_set" sEEK_SET :: CInt-foreign import ccall unsafe "__hscore_seek_end" sEEK_END :: CInt-
@@ -1,9 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE NoImplicitPrelude #-}-module System.Posix.Internals where--import GHC.IO-import GHC.Base--puts :: String -> IO ()-
@@ -1,210 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP- , NoImplicitPrelude- , MagicHash- , GeneralizedNewtypeDeriving- #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif---------------------------------------------------------------------------------- |--- Module : System.Posix.Types--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (requires POSIX)------ POSIX data types: Haskell equivalents of the types defined by the--- @\<sys\/types.h>@ C header on a POSIX system.----------------------------------------------------------------------------------#ifdef __NHC__-#define HTYPE_DEV_T-#define HTYPE_INO_T-#define HTYPE_MODE_T-#define HTYPE_OFF_T-#define HTYPE_PID_T-#define HTYPE_SSIZE_T-#define HTYPE_GID_T-#define HTYPE_NLINK_T-#define HTYPE_UID_T-#define HTYPE_CC_T-#define HTYPE_SPEED_T-#define HTYPE_TCFLAG_T-#define HTYPE_RLIM_T-#define HTYPE_NLINK_T-#define HTYPE_UID_T-#define HTYPE_GID_T-#else-#include "HsBaseConfig.h"-#endif--module System.Posix.Types (-- -- * POSIX data types-#if defined(HTYPE_DEV_T)- CDev(..),-#endif-#if defined(HTYPE_INO_T)- CIno(..),-#endif-#if defined(HTYPE_MODE_T)- CMode(..),-#endif-#if defined(HTYPE_OFF_T)- COff(..),-#endif-#if defined(HTYPE_PID_T)- CPid(..),-#endif-#if defined(HTYPE_SSIZE_T)- CSsize(..),-#endif--#if defined(HTYPE_GID_T)- CGid(..),-#endif-#if defined(HTYPE_NLINK_T)- CNlink(..),-#endif-#if defined(HTYPE_UID_T)- CUid(..),-#endif-#if defined(HTYPE_CC_T)- CCc(..),-#endif-#if defined(HTYPE_SPEED_T)- CSpeed(..),-#endif-#if defined(HTYPE_TCFLAG_T)- CTcflag(..),-#endif-#if defined(HTYPE_RLIM_T)- CRLim(..),-#endif-- Fd(..),--#if defined(HTYPE_NLINK_T)- LinkCount,-#endif-#if defined(HTYPE_UID_T)- UserID,-#endif-#if defined(HTYPE_GID_T)- GroupID,-#endif-- ByteCount,- ClockTick,- EpochTime,- FileOffset,- ProcessID,- ProcessGroupID,- DeviceID,- FileID,- FileMode,- Limit- ) where--#ifdef __NHC__-import NHC.PosixTypes-import Foreign.C-#else--import Foreign-import Foreign.C-import Data.Typeable--- import Data.Bits--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Enum-import GHC.Num-import GHC.Real--- import GHC.Prim-import GHC.Read-import GHC.Show-#else-import Control.Monad-#endif--#include "CTypes.h"--#if defined(HTYPE_DEV_T)-ARITHMETIC_TYPE(CDev,tyConCDev,"CDev",HTYPE_DEV_T)-#endif-#if defined(HTYPE_INO_T)-INTEGRAL_TYPE(CIno,tyConCIno,"CIno",HTYPE_INO_T)-#endif-#if defined(HTYPE_MODE_T)-INTEGRAL_TYPE(CMode,tyConCMode,"CMode",HTYPE_MODE_T)-#endif-#if defined(HTYPE_OFF_T)-INTEGRAL_TYPE(COff,tyConCOff,"COff",HTYPE_OFF_T)-#endif-#if defined(HTYPE_PID_T)-INTEGRAL_TYPE(CPid,tyConCPid,"CPid",HTYPE_PID_T)-#endif--#if defined(HTYPE_SSIZE_T)-INTEGRAL_TYPE(CSsize,tyConCSsize,"CSsize",HTYPE_SSIZE_T)-#endif--#if defined(HTYPE_GID_T)-INTEGRAL_TYPE(CGid,tyConCGid,"CGid",HTYPE_GID_T)-#endif-#if defined(HTYPE_NLINK_T)-INTEGRAL_TYPE(CNlink,tyConCNlink,"CNlink",HTYPE_NLINK_T)-#endif--#if defined(HTYPE_UID_T)-INTEGRAL_TYPE(CUid,tyConCUid,"CUid",HTYPE_UID_T)-#endif-#if defined(HTYPE_CC_T)-ARITHMETIC_TYPE(CCc,tyConCCc,"CCc",HTYPE_CC_T)-#endif-#if defined(HTYPE_SPEED_T)-ARITHMETIC_TYPE(CSpeed,tyConCSpeed,"CSpeed",HTYPE_SPEED_T)-#endif-#if defined(HTYPE_TCFLAG_T)-INTEGRAL_TYPE(CTcflag,tyConCTcflag,"CTcflag",HTYPE_TCFLAG_T)-#endif-#if defined(HTYPE_RLIM_T)-INTEGRAL_TYPE(CRLim,tyConCRlim,"CRLim",HTYPE_RLIM_T)-#endif---- ToDo: blksize_t, clockid_t, blkcnt_t, fsblkcnt_t, fsfilcnt_t, id_t, key_t--- suseconds_t, timer_t, useconds_t---- Make an Fd type rather than using CInt everywhere-INTEGRAL_TYPE(Fd,tyConFd,"Fd",CInt)---- nicer names, and backwards compatibility with POSIX library:-#if defined(HTYPE_NLINK_T)-type LinkCount = CNlink-#endif-#if defined(HTYPE_UID_T)-type UserID = CUid-#endif-#if defined(HTYPE_GID_T)-type GroupID = CGid-#endif--#endif /* !__NHC__ */--type ByteCount = CSize-type ClockTick = CClock-type EpochTime = CTime-type DeviceID = CDev-type FileID = CIno-type FileMode = CMode-type ProcessID = CPid-type FileOffset = COff-type ProcessGroupID = CPid-type Limit = CLong-
@@ -1,95 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP #-}-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif------------------------------------------------------------------------------------ |--- Module : System.Timeout--- Copyright : (c) The University of Glasgow 2007--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : non-portable------ Attach a timeout event to arbitrary 'IO' computations.-------------------------------------------------------------------------------------#ifdef __GLASGOW_HASKELL__-#include "Typeable.h"-#endif--module System.Timeout ( timeout ) where--#ifdef __GLASGOW_HASKELL__-import Prelude (Show(show), IO, Ord((<)), Eq((==)), Int,- otherwise, fmap)-import Data.Maybe (Maybe(..))-import Control.Monad (Monad(..))-import Control.Concurrent (forkIO, threadDelay, myThreadId, killThread)-import Control.Exception (Exception, handleJust, throwTo, bracket)-import Data.Typeable-import Data.Unique (Unique, newUnique)---- An internal type that is thrown as a dynamic exception to--- interrupt the running IO computation when the timeout has--- expired.--newtype Timeout = Timeout Unique deriving Eq-INSTANCE_TYPEABLE0(Timeout,timeoutTc,"Timeout")--instance Show Timeout where- show _ = "<<timeout>>"--instance Exception Timeout-#endif /* !__GLASGOW_HASKELL__ */---- |Wrap an 'IO' computation to time out and return @Nothing@ in case no result--- is available within @n@ microseconds (@1\/10^6@ seconds). In case a result--- is available before the timeout expires, @Just a@ is returned. A negative--- timeout interval means \"wait indefinitely\". When specifying long timeouts,--- be careful not to exceed @maxBound :: Int@.------ The design of this combinator was guided by the objective that @timeout n f@--- should behave exactly the same as @f@ as long as @f@ doesn't time out. This--- means that @f@ has the same 'myThreadId' it would have without the timeout--- wrapper. Any exceptions @f@ might throw cancel the timeout and propagate--- further up. It also possible for @f@ to receive exceptions thrown to it by--- another thread.------ A tricky implementation detail is the question of how to abort an @IO@--- computation. This combinator relies on asynchronous exceptions internally.--- The technique works very well for computations executing inside of the--- Haskell runtime system, but it doesn't work at all for non-Haskell code.--- Foreign function calls, for example, cannot be timed out with this--- combinator simply because an arbitrary C function cannot receive--- asynchronous exceptions. When @timeout@ is used to wrap an FFI call that--- blocks, no timeout event can be delivered until the FFI call returns, which--- pretty much negates the purpose of the combinator. In practice, however,--- this limitation is less severe than it may sound. Standard I\/O functions--- like 'System.IO.hGetBuf', 'System.IO.hPutBuf', Network.Socket.accept, or--- 'System.IO.hWaitForInput' appear to be blocking, but they really don't--- because the runtime system uses scheduling mechanisms like @select(2)@ to--- perform asynchronous I\/O, so it is possible to interrupt standard socket--- I\/O or file I\/O using this combinator.--timeout :: Int -> IO a -> IO (Maybe a)-#ifdef __GLASGOW_HASKELL__-timeout n f- | n < 0 = fmap Just f- | n == 0 = return Nothing- | otherwise = do- pid <- myThreadId- ex <- fmap Timeout newUnique- handleJust (\e -> if e == ex then Just () else Nothing)- (\_ -> return Nothing)- (bracket (forkIO (threadDelay n >> throwTo pid ex))- (killThread)- (\_ -> fmap Just f))-#else-timeout n f = fmap Just f-#endif /* !__GLASGOW_HASKELL__ */-
@@ -1,543 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}-#ifndef __NHC__-{-# LANGUAGE Rank2Types #-}-#endif-#ifdef __GLASGOW_HASKELL__-{-# LANGUAGE MagicHash #-}-#endif---------------------------------------------------------------------------------- |--- Module : Text.ParserCombinators.ReadP--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (local universal quantification)------ This is a library of parser combinators, originally written by Koen Claessen.--- It parses all alternatives in parallel, so it never keeps hold of --- the beginning of the input string, a common source of space leaks with--- other parsers. The '(+++)' choice combinator is genuinely commutative;--- it makes no difference which branch is \"shorter\".---------------------------------------------------------------------------------module Text.ParserCombinators.ReadP- ( - -- * The 'ReadP' type-#ifndef __NHC__- ReadP, -- :: * -> *; instance Functor, Monad, MonadPlus-#else- ReadPN, -- :: * -> * -> *; instance Functor, Monad, MonadPlus-#endif- - -- * Primitive operations- get, -- :: ReadP Char- look, -- :: ReadP String- (+++), -- :: ReadP a -> ReadP a -> ReadP a- (<++), -- :: ReadP a -> ReadP a -> ReadP a- gather, -- :: ReadP a -> ReadP (String, a)- - -- * Other operations- pfail, -- :: ReadP a- eof, -- :: ReadP ()- satisfy, -- :: (Char -> Bool) -> ReadP Char- char, -- :: Char -> ReadP Char- string, -- :: String -> ReadP String- munch, -- :: (Char -> Bool) -> ReadP String- munch1, -- :: (Char -> Bool) -> ReadP String- skipSpaces, -- :: ReadP ()- choice, -- :: [ReadP a] -> ReadP a- count, -- :: Int -> ReadP a -> ReadP [a]- between, -- :: ReadP open -> ReadP close -> ReadP a -> ReadP a- option, -- :: a -> ReadP a -> ReadP a- optional, -- :: ReadP a -> ReadP ()- many, -- :: ReadP a -> ReadP [a]- many1, -- :: ReadP a -> ReadP [a]- skipMany, -- :: ReadP a -> ReadP ()- skipMany1, -- :: ReadP a -> ReadP ()- sepBy, -- :: ReadP a -> ReadP sep -> ReadP [a]- sepBy1, -- :: ReadP a -> ReadP sep -> ReadP [a]- endBy, -- :: ReadP a -> ReadP sep -> ReadP [a]- endBy1, -- :: ReadP a -> ReadP sep -> ReadP [a]- chainr, -- :: ReadP a -> ReadP (a -> a -> a) -> a -> ReadP a- chainl, -- :: ReadP a -> ReadP (a -> a -> a) -> a -> ReadP a- chainl1, -- :: ReadP a -> ReadP (a -> a -> a) -> ReadP a- chainr1, -- :: ReadP a -> ReadP (a -> a -> a) -> ReadP a- manyTill, -- :: ReadP a -> ReadP end -> ReadP [a]- - -- * Running a parser- ReadS, -- :: *; = String -> [(a,String)]- readP_to_S, -- :: ReadP a -> ReadS a- readS_to_P, -- :: ReadS a -> ReadP a- - -- * Properties- -- $properties- )- where--import Control.Monad( MonadPlus(..), sequence, liftM2 )--#ifdef __GLASGOW_HASKELL__-#ifndef __HADDOCK__-import {-# SOURCE #-} GHC.Unicode ( isSpace )-#endif-import GHC.List ( replicate, null )-import GHC.Base-#else-import Data.Char( isSpace )-#endif--infixr 5 +++, <++--#ifdef __GLASGOW_HASKELL__---------------------------------------------------------------------------- ReadS---- | A parser for a type @a@, represented as a function that takes a--- 'String' and returns a list of possible parses as @(a,'String')@ pairs.------ Note that this kind of backtracking parser is very inefficient;--- reading a large structure may be quite slow (cf 'ReadP').-type ReadS a = String -> [(a,String)]-#endif---- ------------------------------------------------------------------------------ The P type--- is representation type -- should be kept abstract--data P a- = Get (Char -> P a)- | Look (String -> P a)- | Fail- | Result a (P a)- | Final [(a,String)] -- invariant: list is non-empty!---- Monad, MonadPlus--instance Monad P where- return x = Result x Fail-- (Get f) >>= k = Get (\c -> f c >>= k)- (Look f) >>= k = Look (\s -> f s >>= k)- Fail >>= _ = Fail- (Result x p) >>= k = k x `mplus` (p >>= k)- (Final r) >>= k = final [ys' | (x,s) <- r, ys' <- run (k x) s]--instance MonadPlus P where- mzero = Fail-- -- most common case: two gets are combined- Get f1 `mplus` Get f2 = Get (\c -> f1 c `mplus` f2 c)- - -- results are delivered as soon as possible- Result x p `mplus` q = Result x (p `mplus` q)- p `mplus` Result x q = Result x (p `mplus` q)-- -- fail disappears- Fail `mplus` p = p- p `mplus` Fail = p-- -- two finals are combined- -- final + look becomes one look and one final (=optimization)- -- final + sthg else becomes one look and one final- Final r `mplus` Final t = Final (r ++ t)- Final r `mplus` Look f = Look (\s -> Final (r ++ run (f s) s))- Final r `mplus` p = Look (\s -> Final (r ++ run p s))- Look f `mplus` Final r = Look (\s -> Final (run (f s) s ++ r))- p `mplus` Final r = Look (\s -> Final (run p s ++ r))-- -- two looks are combined (=optimization)- -- look + sthg else floats upwards- Look f `mplus` Look g = Look (\s -> f s `mplus` g s)- Look f `mplus` p = Look (\s -> f s `mplus` p)- p `mplus` Look f = Look (\s -> p `mplus` f s)---- ------------------------------------------------------------------------------ The ReadP type--#ifndef __NHC__-newtype ReadP a = R (forall b . (a -> P b) -> P b)-#else-#define ReadP (ReadPN b)-newtype ReadPN b a = R ((a -> P b) -> P b)-#endif---- Functor, Monad, MonadPlus--instance Functor ReadP where- fmap h (R f) = R (\k -> f (k . h))--instance Monad ReadP where- return x = R (\k -> k x)- R m >>= f = R (\k -> m (\a -> let R m' = f a in m' k))--instance MonadPlus ReadP where- mzero = pfail- mplus = (+++)---- ------------------------------------------------------------------------------ Operations over P--final :: [(a,String)] -> P a--- Maintains invariant for Final constructor-final [] = Fail-final r = Final r--run :: P a -> ReadS a-run (Get f) (c:s) = run (f c) s-run (Look f) s = run (f s) s-run (Result x p) s = (x,s) : run p s-run (Final r) _ = r-run _ _ = []---- ------------------------------------------------------------------------------ Operations over ReadP--get :: ReadP Char--- ^ Consumes and returns the next character.--- Fails if there is no input left.-get = R Get--look :: ReadP String--- ^ Look-ahead: returns the part of the input that is left, without--- consuming it.-look = R Look--pfail :: ReadP a--- ^ Always fails.-pfail = R (\_ -> Fail)--(+++) :: ReadP a -> ReadP a -> ReadP a--- ^ Symmetric choice.-R f1 +++ R f2 = R (\k -> f1 k `mplus` f2 k)--#ifndef __NHC__-(<++) :: ReadP a -> ReadP a -> ReadP a-#else-(<++) :: ReadPN a a -> ReadPN a a -> ReadPN a a-#endif--- ^ Local, exclusive, left-biased choice: If left parser--- locally produces any result at all, then right parser is--- not used.-#ifdef __GLASGOW_HASKELL__-R f0 <++ q =- do s <- look- probe (f0 return) s 0#- where- probe (Get f) (c:s) n = probe (f c) s (n+#1#)- probe (Look f) s n = probe (f s) s n- probe p@(Result _ _) _ n = discard n >> R (p >>=)- probe (Final r) _ _ = R (Final r >>=)- probe _ _ _ = q-- discard 0# = return ()- discard n = get >> discard (n-#1#)-#else-R f <++ q =- do s <- look- probe (f return) s 0- where- probe (Get f) (c:s) n = probe (f c) s (n+1)- probe (Look f) s n = probe (f s) s n- probe p@(Result _ _) _ n = discard n >> R (p >>=)- probe (Final r) _ _ = R (Final r >>=)- probe _ _ _ = q-- discard 0 = return ()- discard n = get >> discard (n-1)-#endif--#ifndef __NHC__-gather :: ReadP a -> ReadP (String, a)-#else--- gather :: ReadPN (String->P b) a -> ReadPN (String->P b) (String, a)-#endif--- ^ Transforms a parser into one that does the same, but--- in addition returns the exact characters read.--- IMPORTANT NOTE: 'gather' gives a runtime error if its first argument--- is built using any occurrences of readS_to_P. -gather (R m)- = R (\k -> gath id (m (\a -> return (\s -> k (s,a))))) - where- gath :: (String -> String) -> P (String -> P b) -> P b- gath l (Get f) = Get (\c -> gath (l.(c:)) (f c))- gath _ Fail = Fail- gath l (Look f) = Look (\s -> gath l (f s))- gath l (Result k p) = k (l []) `mplus` gath l p- gath _ (Final _) = error "do not use readS_to_P in gather!"---- ------------------------------------------------------------------------------ Derived operations--satisfy :: (Char -> Bool) -> ReadP Char--- ^ Consumes and returns the next character, if it satisfies the--- specified predicate.-satisfy p = do c <- get; if p c then return c else pfail--char :: Char -> ReadP Char--- ^ Parses and returns the specified character.-char c = satisfy (c ==)--eof :: ReadP ()--- ^ Succeeds iff we are at the end of input-eof = do { s <- look - ; if null s then return () - else pfail }--string :: String -> ReadP String--- ^ Parses and returns the specified string.-string this = do s <- look; scan this s- where- scan [] _ = do return this- scan (x:xs) (y:ys) | x == y = do _ <- get; scan xs ys- scan _ _ = do pfail--munch :: (Char -> Bool) -> ReadP String--- ^ Parses the first zero or more characters satisfying the predicate.--- Always succeeds, exactly once having consumed all the characters--- Hence NOT the same as (many (satisfy p))-munch p =- do s <- look- scan s- where- scan (c:cs) | p c = do _ <- get; s <- scan cs; return (c:s)- scan _ = do return ""--munch1 :: (Char -> Bool) -> ReadP String--- ^ Parses the first one or more characters satisfying the predicate.--- Fails if none, else succeeds exactly once having consumed all the characters--- Hence NOT the same as (many1 (satisfy p))-munch1 p =- do c <- get- if p c then do s <- munch p; return (c:s)- else pfail--choice :: [ReadP a] -> ReadP a--- ^ Combines all parsers in the specified list.-choice [] = pfail-choice [p] = p-choice (p:ps) = p +++ choice ps--skipSpaces :: ReadP ()--- ^ Skips all whitespace.-skipSpaces =- do s <- look- skip s- where- skip (c:s) | isSpace c = do _ <- get; skip s- skip _ = do return ()--count :: Int -> ReadP a -> ReadP [a]--- ^ @count n p@ parses @n@ occurrences of @p@ in sequence. A list of--- results is returned.-count n p = sequence (replicate n p)--between :: ReadP open -> ReadP close -> ReadP a -> ReadP a--- ^ @between open close p@ parses @open@, followed by @p@ and finally--- @close@. Only the value of @p@ is returned.-between open close p = do _ <- open- x <- p- _ <- close- return x--option :: a -> ReadP a -> ReadP a--- ^ @option x p@ will either parse @p@ or return @x@ without consuming--- any input.-option x p = p +++ return x--optional :: ReadP a -> ReadP ()--- ^ @optional p@ optionally parses @p@ and always returns @()@.-optional p = (p >> return ()) +++ return ()--many :: ReadP a -> ReadP [a]--- ^ Parses zero or more occurrences of the given parser.-many p = return [] +++ many1 p--many1 :: ReadP a -> ReadP [a]--- ^ Parses one or more occurrences of the given parser.-many1 p = liftM2 (:) p (many p)--skipMany :: ReadP a -> ReadP ()--- ^ Like 'many', but discards the result.-skipMany p = many p >> return ()--skipMany1 :: ReadP a -> ReadP ()--- ^ Like 'many1', but discards the result.-skipMany1 p = p >> skipMany p--sepBy :: ReadP a -> ReadP sep -> ReadP [a]--- ^ @sepBy p sep@ parses zero or more occurrences of @p@, separated by @sep@.--- Returns a list of values returned by @p@.-sepBy p sep = sepBy1 p sep +++ return []--sepBy1 :: ReadP a -> ReadP sep -> ReadP [a]--- ^ @sepBy1 p sep@ parses one or more occurrences of @p@, separated by @sep@.--- Returns a list of values returned by @p@.-sepBy1 p sep = liftM2 (:) p (many (sep >> p))--endBy :: ReadP a -> ReadP sep -> ReadP [a]--- ^ @endBy p sep@ parses zero or more occurrences of @p@, separated and ended--- by @sep@.-endBy p sep = many (do x <- p ; _ <- sep ; return x)--endBy1 :: ReadP a -> ReadP sep -> ReadP [a]--- ^ @endBy p sep@ parses one or more occurrences of @p@, separated and ended--- by @sep@.-endBy1 p sep = many1 (do x <- p ; _ <- sep ; return x)--chainr :: ReadP a -> ReadP (a -> a -> a) -> a -> ReadP a--- ^ @chainr p op x@ parses zero or more occurrences of @p@, separated by @op@.--- Returns a value produced by a /right/ associative application of all--- functions returned by @op@. If there are no occurrences of @p@, @x@ is--- returned.-chainr p op x = chainr1 p op +++ return x--chainl :: ReadP a -> ReadP (a -> a -> a) -> a -> ReadP a--- ^ @chainl p op x@ parses zero or more occurrences of @p@, separated by @op@.--- Returns a value produced by a /left/ associative application of all--- functions returned by @op@. If there are no occurrences of @p@, @x@ is--- returned.-chainl p op x = chainl1 p op +++ return x--chainr1 :: ReadP a -> ReadP (a -> a -> a) -> ReadP a--- ^ Like 'chainr', but parses one or more occurrences of @p@.-chainr1 p op = scan- where scan = p >>= rest- rest x = do f <- op- y <- scan- return (f x y)- +++ return x--chainl1 :: ReadP a -> ReadP (a -> a -> a) -> ReadP a--- ^ Like 'chainl', but parses one or more occurrences of @p@.-chainl1 p op = p >>= rest- where rest x = do f <- op- y <- p- rest (f x y)- +++ return x--#ifndef __NHC__-manyTill :: ReadP a -> ReadP end -> ReadP [a]-#else-manyTill :: ReadPN [a] a -> ReadPN [a] end -> ReadPN [a] [a]-#endif--- ^ @manyTill p end@ parses zero or more occurrences of @p@, until @end@--- succeeds. Returns a list of values returned by @p@.-manyTill p end = scan- where scan = (end >> return []) <++ (liftM2 (:) p scan)---- ------------------------------------------------------------------------------ Converting between ReadP and Read--#ifndef __NHC__-readP_to_S :: ReadP a -> ReadS a-#else-readP_to_S :: ReadPN a a -> ReadS a-#endif--- ^ Converts a parser into a Haskell ReadS-style function.--- This is the main way in which you can \"run\" a 'ReadP' parser:--- the expanded type is--- @ readP_to_S :: ReadP a -> String -> [(a,String)] @-readP_to_S (R f) = run (f return)--readS_to_P :: ReadS a -> ReadP a--- ^ Converts a Haskell ReadS-style function into a parser.--- Warning: This introduces local backtracking in the resulting--- parser, and therefore a possible inefficiency.-readS_to_P r =- R (\k -> Look (\s -> final [bs'' | (a,s') <- r s, bs'' <- run (k a) s']))---- ------------------------------------------------------------------------------ QuickCheck properties that hold for the combinators--{- $properties-The following are QuickCheck specifications of what the combinators do.-These can be seen as formal specifications of the behavior of the-combinators.--We use bags to give semantics to the combinators.--> type Bag a = [a]--Equality on bags does not care about the order of elements.--> (=~) :: Ord a => Bag a -> Bag a -> Bool-> xs =~ ys = sort xs == sort ys--A special equality operator to avoid unresolved overloading-when testing the properties.--> (=~.) :: Bag (Int,String) -> Bag (Int,String) -> Bool-> (=~.) = (=~)--Here follow the properties:--> prop_Get_Nil =-> readP_to_S get [] =~ []->-> prop_Get_Cons c s =-> readP_to_S get (c:s) =~ [(c,s)]->-> prop_Look s =-> readP_to_S look s =~ [(s,s)]->-> prop_Fail s =-> readP_to_S pfail s =~. []->-> prop_Return x s =-> readP_to_S (return x) s =~. [(x,s)]->-> prop_Bind p k s =-> readP_to_S (p >>= k) s =~.-> [ ys''-> | (x,s') <- readP_to_S p s-> , ys'' <- readP_to_S (k (x::Int)) s'-> ]->-> prop_Plus p q s =-> readP_to_S (p +++ q) s =~.-> (readP_to_S p s ++ readP_to_S q s)->-> prop_LeftPlus p q s =-> readP_to_S (p <++ q) s =~.-> (readP_to_S p s +<+ readP_to_S q s)-> where-> [] +<+ ys = ys-> xs +<+ _ = xs->-> prop_Gather s =-> forAll readPWithoutReadS $ \p -> -> readP_to_S (gather p) s =~-> [ ((pre,x::Int),s')-> | (x,s') <- readP_to_S p s-> , let pre = take (length s - length s') s-> ]->-> prop_String_Yes this s =-> readP_to_S (string this) (this ++ s) =~-> [(this,s)]->-> prop_String_Maybe this s =-> readP_to_S (string this) s =~-> [(this, drop (length this) s) | this `isPrefixOf` s]->-> prop_Munch p s =-> readP_to_S (munch p) s =~-> [(takeWhile p s, dropWhile p s)]->-> prop_Munch1 p s =-> readP_to_S (munch1 p) s =~-> [(res,s') | let (res,s') = (takeWhile p s, dropWhile p s), not (null res)]->-> prop_Choice ps s =-> readP_to_S (choice ps) s =~.-> readP_to_S (foldr (+++) pfail ps) s->-> prop_ReadS r s =-> readP_to_S (readS_to_P r) s =~. r s--}-
@@ -1,164 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Text.ParserCombinators.ReadPrec--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (uses Text.ParserCombinators.ReadP)------ This library defines parser combinators for precedence parsing.---------------------------------------------------------------------------------module Text.ParserCombinators.ReadPrec- ( - ReadPrec, -- :: * -> *; instance Functor, Monad, MonadPlus- - -- * Precedences- Prec, -- :: *; = Int- minPrec, -- :: Prec; = 0-- -- * Precedence operations- lift, -- :: ReadP a -> ReadPrec a- prec, -- :: Prec -> ReadPrec a -> ReadPrec a- step, -- :: ReadPrec a -> ReadPrec a- reset, -- :: ReadPrec a -> ReadPrec a-- -- * Other operations- -- | All are based directly on their similarly-named 'ReadP' counterparts.- get, -- :: ReadPrec Char- look, -- :: ReadPrec String- (+++), -- :: ReadPrec a -> ReadPrec a -> ReadPrec a- (<++), -- :: ReadPrec a -> ReadPrec a -> ReadPrec a- pfail, -- :: ReadPrec a- choice, -- :: [ReadPrec a] -> ReadPrec a-- -- * Converters- readPrec_to_P, -- :: ReadPrec a -> (Int -> ReadP a)- readP_to_Prec, -- :: (Int -> ReadP a) -> ReadPrec a- readPrec_to_S, -- :: ReadPrec a -> (Int -> ReadS a)- readS_to_Prec, -- :: (Int -> ReadS a) -> ReadPrec a- )- where---import Text.ParserCombinators.ReadP- ( ReadP- , ReadS- , readP_to_S- , readS_to_P- )--import qualified Text.ParserCombinators.ReadP as ReadP- ( get- , look- , (+++), (<++)- , pfail- )--import Control.Monad( MonadPlus(..) )-#ifdef __GLASGOW_HASKELL__-import GHC.Num( Num(..) )-import GHC.Base-#endif---- ------------------------------------------------------------------------------ The readPrec type--newtype ReadPrec a = P (Prec -> ReadP a)---- Functor, Monad, MonadPlus--instance Functor ReadPrec where- fmap h (P f) = P (\n -> fmap h (f n))--instance Monad ReadPrec where- return x = P (\_ -> return x)- P f >>= k = P (\n -> do a <- f n; let P f' = k a in f' n)- -instance MonadPlus ReadPrec where- mzero = pfail- mplus = (+++)---- precedences- -type Prec = Int--minPrec :: Prec-minPrec = 0---- ------------------------------------------------------------------------------ Operations over ReadPrec--lift :: ReadP a -> ReadPrec a--- ^ Lift a precedence-insensitive 'ReadP' to a 'ReadPrec'.-lift m = P (\_ -> m)--step :: ReadPrec a -> ReadPrec a--- ^ Increases the precedence context by one.-step (P f) = P (\n -> f (n+1))--reset :: ReadPrec a -> ReadPrec a--- ^ Resets the precedence context to zero.-reset (P f) = P (\_ -> f minPrec)--prec :: Prec -> ReadPrec a -> ReadPrec a--- ^ @(prec n p)@ checks whether the precedence context is --- less than or equal to @n@, and------ * if not, fails------ * if so, parses @p@ in context @n@.-prec n (P f) = P (\c -> if c <= n then f n else ReadP.pfail)---- ------------------------------------------------------------------------------ Derived operations--get :: ReadPrec Char--- ^ Consumes and returns the next character.--- Fails if there is no input left.-get = lift ReadP.get--look :: ReadPrec String--- ^ Look-ahead: returns the part of the input that is left, without--- consuming it.-look = lift ReadP.look--(+++) :: ReadPrec a -> ReadPrec a -> ReadPrec a--- ^ Symmetric choice.-P f1 +++ P f2 = P (\n -> f1 n ReadP.+++ f2 n)--(<++) :: ReadPrec a -> ReadPrec a -> ReadPrec a--- ^ Local, exclusive, left-biased choice: If left parser--- locally produces any result at all, then right parser is--- not used.-P f1 <++ P f2 = P (\n -> f1 n ReadP.<++ f2 n)--pfail :: ReadPrec a--- ^ Always fails.-pfail = lift ReadP.pfail--choice :: [ReadPrec a] -> ReadPrec a--- ^ Combines all parsers in the specified list.-choice ps = foldr (+++) pfail ps---- ------------------------------------------------------------------------------ Converting between ReadPrec and Read--readPrec_to_P :: ReadPrec a -> (Int -> ReadP a)-readPrec_to_P (P f) = f--readP_to_Prec :: (Int -> ReadP a) -> ReadPrec a-readP_to_Prec f = P f--readPrec_to_S :: ReadPrec a -> (Int -> ReadS a)-readPrec_to_S (P f) n = readP_to_S (f n)--readS_to_Prec :: (Int -> ReadS a) -> ReadPrec a-readS_to_Prec f = P (\n -> readS_to_P (f n))-
@@ -1,331 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Text.Printf--- Copyright : (c) Lennart Augustsson, 2004-2008--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : lennart@augustsson.net--- Stability : provisional--- Portability : portable------ A C printf like formatter.-----------------------------------------------------------------------------------{-# Language CPP #-}--module Text.Printf(- printf, hPrintf,- PrintfType, HPrintfType, PrintfArg, IsChar-) where--import Prelude-import Data.Char-import Data.Int-import Data.Word-import Numeric(showEFloat, showFFloat, showGFloat)-import System.IO------------------------- | Format a variable number of arguments with the C-style formatting string.--- The return value is either 'String' or @('IO' a)@.------ The format string consists of ordinary characters and /conversion--- specifications/, which specify how to format one of the arguments--- to printf in the output string. A conversion specification begins with the--- character @%@, followed by one or more of the following flags:------ > - left adjust (default is right adjust)--- > + always use a sign (+ or -) for signed conversions--- > 0 pad with zeroes rather than spaces------ followed optionally by a field width:--- --- > num field width--- > * as num, but taken from argument list------ followed optionally by a precision:------ > .num precision (number of decimal places)------ and finally, a format character:------ > c character Char, Int, Integer, ...--- > d decimal Char, Int, Integer, ...--- > o octal Char, Int, Integer, ...--- > x hexadecimal Char, Int, Integer, ...--- > X hexadecimal Char, Int, Integer, ...--- > u unsigned decimal Char, Int, Integer, ...--- > f floating point Float, Double--- > g general format float Float, Double--- > G general format float Float, Double--- > e exponent format float Float, Double--- > E exponent format float Float, Double--- > s string String------ Mismatch between the argument types and the format string will cause--- an exception to be thrown at runtime.------ Examples:------ > > printf "%d\n" (23::Int)--- > 23--- > > printf "%s %s\n" "Hello" "World"--- > Hello World--- > > printf "%.2f\n" pi--- > 3.14----printf :: (PrintfType r) => String -> r-printf fmts = spr fmts []---- | Similar to 'printf', except that output is via the specified--- 'Handle'. The return type is restricted to @('IO' a)@.-hPrintf :: (HPrintfType r) => Handle -> String -> r-hPrintf hdl fmts = hspr hdl fmts []---- |The 'PrintfType' class provides the variable argument magic for--- 'printf'. Its implementation is intentionally not visible from--- this module. If you attempt to pass an argument of a type which--- is not an instance of this class to 'printf' or 'hPrintf', then--- the compiler will report it as a missing instance of 'PrintfArg'.-class PrintfType t where- spr :: String -> [UPrintf] -> t---- | The 'HPrintfType' class provides the variable argument magic for--- 'hPrintf'. Its implementation is intentionally not visible from--- this module.-class HPrintfType t where- hspr :: Handle -> String -> [UPrintf] -> t--{- not allowed in Haskell 98-instance PrintfType String where- spr fmt args = uprintf fmt (reverse args)--}-instance (IsChar c) => PrintfType [c] where- spr fmts args = map fromChar (uprintf fmts (reverse args))--instance PrintfType (IO a) where- spr fmts args = do- putStr (uprintf fmts (reverse args))- return (error "PrintfType (IO a): result should not be used.")--instance HPrintfType (IO a) where- hspr hdl fmts args = do- hPutStr hdl (uprintf fmts (reverse args))- return (error "HPrintfType (IO a): result should not be used.")--instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) where- spr fmts args = \ a -> spr fmts (toUPrintf a : args)--instance (PrintfArg a, HPrintfType r) => HPrintfType (a -> r) where- hspr hdl fmts args = \ a -> hspr hdl fmts (toUPrintf a : args)--class PrintfArg a where- toUPrintf :: a -> UPrintf--instance PrintfArg Char where- toUPrintf c = UChar c--{- not allowed in Haskell 98-instance PrintfArg String where- toUPrintf s = UString s--}-instance (IsChar c) => PrintfArg [c] where- toUPrintf = UString . map toChar--instance PrintfArg Int where- toUPrintf = uInteger--instance PrintfArg Int8 where- toUPrintf = uInteger--instance PrintfArg Int16 where- toUPrintf = uInteger--instance PrintfArg Int32 where- toUPrintf = uInteger--instance PrintfArg Int64 where- toUPrintf = uInteger--#ifndef __NHC__-instance PrintfArg Word where- toUPrintf = uInteger-#endif--instance PrintfArg Word8 where- toUPrintf = uInteger--instance PrintfArg Word16 where- toUPrintf = uInteger--instance PrintfArg Word32 where- toUPrintf = uInteger--instance PrintfArg Word64 where- toUPrintf = uInteger--instance PrintfArg Integer where- toUPrintf = UInteger 0--instance PrintfArg Float where- toUPrintf = UFloat--instance PrintfArg Double where- toUPrintf = UDouble--uInteger :: (Integral a, Bounded a) => a -> UPrintf-uInteger x = UInteger (toInteger $ minBound `asTypeOf` x) (toInteger x)--class IsChar c where- toChar :: c -> Char- fromChar :: Char -> c--instance IsChar Char where- toChar c = c- fromChar c = c-----------------------data UPrintf = UChar Char | UString String | UInteger Integer Integer | UFloat Float | UDouble Double--uprintf :: String -> [UPrintf] -> String-uprintf "" [] = ""-uprintf "" (_:_) = fmterr-uprintf ('%':'%':cs) us = '%':uprintf cs us-uprintf ('%':_) [] = argerr-uprintf ('%':cs) us@(_:_) = fmt cs us-uprintf (c:cs) us = c:uprintf cs us--fmt :: String -> [UPrintf] -> String-fmt cs us =- let (width, prec, ladj, zero, plus, cs', us') = getSpecs False False False cs us- adjust (pre, str) = - let lstr = length str- lpre = length pre- fill = if lstr+lpre < width then take (width-(lstr+lpre)) (repeat (if zero then '0' else ' ')) else ""- in if ladj then pre ++ str ++ fill else if zero then pre ++ fill ++ str else fill ++ pre ++ str- adjust' ("", str) | plus = adjust ("+", str)- adjust' ps = adjust ps- in- case cs' of- [] -> fmterr- c:cs'' ->- case us' of- [] -> argerr- u:us'' ->- (case c of- 'c' -> adjust ("", [toEnum (toint u)])- 'd' -> adjust' (fmti prec u)- 'i' -> adjust' (fmti prec u)- 'x' -> adjust ("", fmtu 16 prec u)- 'X' -> adjust ("", map toUpper $ fmtu 16 prec u)- 'o' -> adjust ("", fmtu 8 prec u)- 'u' -> adjust ("", fmtu 10 prec u)- 'e' -> adjust' (dfmt' c prec u)- 'E' -> adjust' (dfmt' c prec u)- 'f' -> adjust' (dfmt' c prec u)- 'g' -> adjust' (dfmt' c prec u)- 'G' -> adjust' (dfmt' c prec u)- 's' -> adjust ("", tostr prec u)- _ -> perror ("bad formatting char " ++ [c])- ) ++ uprintf cs'' us''--fmti :: Int -> UPrintf -> (String, String)-fmti prec (UInteger _ i) = if i < 0 then ("-", integral_prec prec (show (-i))) else ("", integral_prec prec (show i))-fmti _ (UChar c) = fmti 0 (uInteger (fromEnum c))-fmti _ _ = baderr--fmtu :: Integer -> Int -> UPrintf -> String-fmtu b prec (UInteger l i) = integral_prec prec (itosb b (if i < 0 then -2*l + i else i))-fmtu b _ (UChar c) = itosb b (toInteger (fromEnum c))-fmtu _ _ _ = baderr--integral_prec :: Int -> String -> String-integral_prec prec integral = (replicate (prec - (length integral)) '0') ++ integral--toint :: UPrintf -> Int-toint (UInteger _ i) = fromInteger i-toint (UChar c) = fromEnum c-toint _ = baderr--tostr :: Int -> UPrintf -> String-tostr n (UString s) = if n >= 0 then take n s else s-tostr _ _ = baderr--itosb :: Integer -> Integer -> String-itosb b n = - if n < b then - [intToDigit $ fromInteger n]- else- let (q, r) = quotRem n b in- itosb b q ++ [intToDigit $ fromInteger r]--stoi :: Int -> String -> (Int, String)-stoi a (c:cs) | isDigit c = stoi (a*10 + digitToInt c) cs-stoi a cs = (a, cs)--getSpecs :: Bool -> Bool -> Bool -> String -> [UPrintf] -> (Int, Int, Bool, Bool, Bool, String, [UPrintf])-getSpecs _ z s ('-':cs) us = getSpecs True z s cs us-getSpecs l z _ ('+':cs) us = getSpecs l z True cs us-getSpecs l _ s ('0':cs) us = getSpecs l True s cs us-getSpecs l z s ('*':cs) us =- let (us', n) = getStar us- ((p, cs''), us'') =- case cs of- '.':'*':r -> let (us''', p') = getStar us'- in ((p', r), us''')- '.':r -> (stoi 0 r, us')- _ -> ((-1, cs), us')- in (n, p, l, z, s, cs'', us'')-getSpecs l z s ('.':cs) us =- let ((p, cs'), us') = - case cs of- '*':cs'' -> let (us'', p') = getStar us in ((p', cs''), us'')- _ -> (stoi 0 cs, us)- in (0, p, l, z, s, cs', us')-getSpecs l z s cs@(c:_) us | isDigit c =- let (n, cs') = stoi 0 cs- ((p, cs''), us') = case cs' of- '.':'*':r -> let (us'', p') = getStar us in ((p', r), us'')- '.':r -> (stoi 0 r, us)- _ -> ((-1, cs'), us)- in (n, p, l, z, s, cs'', us')-getSpecs l z s cs us = (0, -1, l, z, s, cs, us)--getStar :: [UPrintf] -> ([UPrintf], Int)-getStar us =- case us of- [] -> argerr- nu : us' -> (us', toint nu)---dfmt' :: Char -> Int -> UPrintf -> (String, String)-dfmt' c p (UDouble d) = dfmt c p d-dfmt' c p (UFloat f) = dfmt c p f-dfmt' _ _ _ = baderr--dfmt :: (RealFloat a) => Char -> Int -> a -> (String, String)-dfmt c p d =- case (if isUpper c then map toUpper else id) $- (case toLower c of- 'e' -> showEFloat- 'f' -> showFFloat- 'g' -> showGFloat- _ -> error "Printf.dfmt: impossible"- )- (if p < 0 then Nothing else Just p) d "" of- '-':cs -> ("-", cs)- cs -> ("" , cs)--perror :: String -> a-perror s = error ("Printf.printf: "++s)-fmterr, argerr, baderr :: a-fmterr = perror "formatting string ended prematurely"-argerr = perror "argument list ended prematurely"-baderr = perror "bad argument"-
@@ -1,102 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Text.Read--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (uses Text.ParserCombinators.ReadP)------ Converting strings to values.------ The "Text.Read" library is the canonical library to import for--- 'Read'-class facilities. For GHC only, it offers an extended and much--- improved 'Read' class, which constitutes a proposed alternative to the --- Haskell 98 'Read'. In particular, writing parsers is easier, and--- the parsers are much more efficient.-----------------------------------------------------------------------------------module Text.Read (- -- * The 'Read' class- Read(..), -- The Read class- ReadS, -- String -> Maybe (a,String)-- -- * Haskell 98 functions- reads, -- :: (Read a) => ReadS a- read, -- :: (Read a) => String -> a- readParen, -- :: Bool -> ReadS a -> ReadS a- lex, -- :: ReadS String--#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)- -- * New parsing functions- module Text.ParserCombinators.ReadPrec,- L.Lexeme(..),- lexP, -- :: ReadPrec Lexeme- parens, -- :: ReadPrec a -> ReadPrec a-#endif-#ifdef __GLASGOW_HASKELL__- readListDefault, -- :: Read a => ReadS [a]- readListPrecDefault, -- :: Read a => ReadPrec [a]-#endif-- ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Read-import Data.Either-import Text.ParserCombinators.ReadP as P-#endif-#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)-import Text.ParserCombinators.ReadPrec-import qualified Text.Read.Lex as L-#endif--#ifdef __HUGS__--- copied from GHC.Read--lexP :: ReadPrec L.Lexeme-lexP = lift L.lex--parens :: ReadPrec a -> ReadPrec a-parens p = optional- where- optional = p +++ mandatory- mandatory = do- L.Punc "(" <- lexP- x <- reset optional- L.Punc ")" <- lexP- return x-#endif--#ifdef __GLASGOW_HASKELL__---------------------------------------------------------------------------- utility functions---- | equivalent to 'readsPrec' with a precedence of 0.-reads :: Read a => ReadS a-reads = readsPrec minPrec--readEither :: Read a => String -> Either String a-readEither s =- case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of- [x] -> Right x- [] -> Left "Prelude.read: no parse"- _ -> Left "Prelude.read: ambiguous parse"- where- read' =- do x <- readPrec- lift P.skipSpaces- return x---- | The 'read' function reads input from a string, which must be--- completely consumed by the input process.-read :: Read a => String -> a-read s = either error id (readEither s)-#endif-
@@ -1,559 +0,0 @@-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Text.Read.Lex--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : non-portable (uses Text.ParserCombinators.ReadP)------ The cut-down Haskell lexer, used by Text.Read-----------------------------------------------------------------------------------module Text.Read.Lex- -- lexing types- ( Lexeme(..) -- :: *; Show, Eq- , Lexeme'(..)-- , numberToInteger, numberToRangedRational-- -- lexer- , lex -- :: ReadP Lexeme Skips leading spaces- , lex' -- :: ReadP Lexeme Skips leading spaces- , hsLex -- :: ReadP String- , lexChar -- :: ReadP Char Reads just one char, with H98 escapes-- , readIntP -- :: Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadP a- , readOctP -- :: Num a => ReadP a- , readDecP -- :: Num a => ReadP a- , readHexP -- :: Num a => ReadP a- )- where--import Text.ParserCombinators.ReadP--#ifdef __GLASGOW_HASKELL__-import GHC.Base-import GHC.Num( Num(..), Integer )-import GHC.Show( Show(..) )-#ifndef __HADDOCK__-import {-# SOURCE #-} GHC.Unicode ( isSpace, isAlpha, isAlphaNum )-#endif-import GHC.Real( Integral, Rational, (%), fromIntegral,- toInteger, (^), infinity, notANumber )-import GHC.List-import GHC.Enum( maxBound )-#else-import Prelude hiding ( lex )-import Data.Char( chr, ord, isSpace, isAlpha, isAlphaNum )-import Data.Ratio( Ratio, (%) )-#endif-#ifdef __HUGS__-import Hugs.Prelude( Ratio(..) )-#endif-import Data.Maybe-import Control.Monad---- -------------------------------------------------------------------------------- Lexing types---- ^ Haskell lexemes.-data Lexeme- = Char Char -- ^ Character literal- | String String -- ^ String literal, with escapes interpreted- | Punc String -- ^ Punctuation or reserved symbol, e.g. @(@, @::@- | Ident String -- ^ Haskell identifier, e.g. @foo@, @Baz@- | Symbol String -- ^ Haskell symbol, e.g. @>>@, @:%@- | Int Integer -- ^ Integer literal- | Rat Rational -- ^ Floating point literal- | EOF- deriving (Eq, Show)--data Lexeme' = Ident' String- | Punc' String- | Symbol' String- | Number Number- deriving (Eq, Show)--data Number = MkNumber Int -- Base- Digits -- Integral part- | MkDecimal Digits -- Integral part- (Maybe Digits) -- Fractional part- (Maybe Integer) -- Exponent- deriving (Eq, Show)--numberToInteger :: Number -> Maybe Integer-numberToInteger (MkNumber base iPart) = Just (val (fromIntegral base) 0 iPart)-numberToInteger (MkDecimal iPart Nothing Nothing) = Just (val 10 0 iPart)-numberToInteger _ = Nothing--numberToRangedRational :: (Int, Int) -> Number- -> Maybe Rational -- Nothing = Inf-numberToRangedRational (neg, pos) n@(MkDecimal iPart mFPart (Just exp))- = let mFirstDigit = case dropWhile (0 ==) iPart of- iPart'@(_ : _) -> Just (length iPart')- [] -> case mFPart of- Nothing -> Nothing- Just fPart ->- case span (0 ==) fPart of- (_, []) -> Nothing- (zeroes, _) ->- Just (negate (length zeroes))- in case mFirstDigit of- Nothing -> Just 0- Just firstDigit ->- let firstDigit' = firstDigit + fromInteger exp- in if firstDigit' > (pos + 3)- then Nothing- else if firstDigit' < (neg - 3)- then Just 0- else Just (numberToRational n)-numberToRangedRational _ n = Just (numberToRational n)--numberToRational :: Number -> Rational-numberToRational (MkNumber base iPart) = val (fromIntegral base) 0 iPart % 1-numberToRational (MkDecimal iPart mFPart mExp)- = let i = val 10 0 iPart- in case (mFPart, mExp) of- (Nothing, Nothing) -> i % 1- (Nothing, Just exp)- | exp >= 0 -> (i * (10 ^ exp)) % 1- | otherwise -> i % (10 ^ (- exp))- (Just fPart, Nothing) -> fracExp 0 i fPart- (Just fPart, Just exp) -> fracExp exp i fPart---- -------------------------------------------------------------------------------- Lexing--lex :: ReadP Lexeme-lex = skipSpaces >> lexToken--lex' :: ReadP Lexeme'-lex' = skipSpaces >> lexToken'--hsLex :: ReadP String--- ^ Haskell lexer: returns the lexed string, rather than the lexeme-hsLex = do skipSpaces- (s,_) <- gather lexToken- return s--lexToken :: ReadP Lexeme-lexToken = lexEOF +++- lexLitChar +++- lexString +++- lexPunc +++- lexSymbol +++- lexId +++- lexNumber--lexToken' :: ReadP Lexeme'-lexToken' = lexSymbol' +++- lexId' +++- fmap Number lexNumber'----- ------------------------------------------------------------------------- End of file-lexEOF :: ReadP Lexeme-lexEOF = do s <- look- guard (null s)- return EOF---- ------------------------------------------------------------------------------ Single character lexemes--lexPunc :: ReadP Lexeme-lexPunc =- do c <- satisfy isPuncChar- return (Punc [c])- where- isPuncChar c = c `elem` ",;()[]{}`"---- ------------------------------------------------------------------------- Symbols--lexSymbol :: ReadP Lexeme-lexSymbol =- do s <- munch1 isSymbolChar- if s `elem` reserved_ops then- return (Punc s) -- Reserved-ops count as punctuation- else- return (Symbol s)- where- isSymbolChar c = c `elem` "!@#$%&*+./<=>?\\^|:-~"- reserved_ops = ["..", "::", "=", "\\", "|", "<-", "->", "@", "~", "=>"]--lexSymbol' :: ReadP Lexeme'-lexSymbol' =- do s <- munch1 isSymbolChar- if s `elem` reserved_ops then- return (Punc' s) -- Reserved-ops count as punctuation- else- return (Symbol' s)- where- isSymbolChar c = c `elem` "!@#$%&*+./<=>?\\^|:-~"- reserved_ops = ["..", "::", "=", "\\", "|", "<-", "->", "@", "~", "=>"]---- ------------------------------------------------------------------------- identifiers--lexId :: ReadP Lexeme-lexId = lex_nan <++ lex_id- where- -- NaN and Infinity look like identifiers, so- -- we parse them first.- lex_nan = (string "NaN" >> return (Rat notANumber)) +++- (string "Infinity" >> return (Rat infinity))-- lex_id = do c <- satisfy isIdsChar- s <- munch isIdfChar- return (Ident (c:s))-- -- Identifiers can start with a '_'- isIdsChar c = isAlpha c || c == '_'- isIdfChar c = isAlphaNum c || c `elem` "_'"--lexId' :: ReadP Lexeme'-lexId' = do c <- satisfy isIdsChar- s <- munch isIdfChar- return (Ident' (c:s))- where- -- Identifiers can start with a '_'- isIdsChar c = isAlpha c || c == '_'- isIdfChar c = isAlphaNum c || c `elem` "_'"--#ifndef __GLASGOW_HASKELL__-infinity, notANumber :: Rational-infinity = 1 :% 0-notANumber = 0 :% 0-#endif---- ------------------------------------------------------------------------------ Lexing character literals--lexLitChar :: ReadP Lexeme-lexLitChar =- do _ <- char '\''- (c,esc) <- lexCharE- guard (esc || c /= '\'') -- Eliminate '' possibility- _ <- char '\''- return (Char c)--lexChar :: ReadP Char-lexChar = do { (c,_) <- lexCharE; return c }--lexCharE :: ReadP (Char, Bool) -- "escaped or not"?-lexCharE =- do c1 <- get- if c1 == '\\'- then do c2 <- lexEsc; return (c2, True)- else do return (c1, False)- where- lexEsc =- lexEscChar- +++ lexNumeric- +++ lexCntrlChar- +++ lexAscii-- lexEscChar =- do c <- get- case c of- 'a' -> return '\a'- 'b' -> return '\b'- 'f' -> return '\f'- 'n' -> return '\n'- 'r' -> return '\r'- 't' -> return '\t'- 'v' -> return '\v'- '\\' -> return '\\'- '\"' -> return '\"'- '\'' -> return '\''- _ -> pfail-- lexNumeric =- do base <- lexBaseChar <++ return 10- n <- lexInteger base- guard (n <= toInteger (ord maxBound))- return (chr (fromInteger n))-- lexCntrlChar =- do _ <- char '^'- c <- get- case c of- '@' -> return '\^@'- 'A' -> return '\^A'- 'B' -> return '\^B'- 'C' -> return '\^C'- 'D' -> return '\^D'- 'E' -> return '\^E'- 'F' -> return '\^F'- 'G' -> return '\^G'- 'H' -> return '\^H'- 'I' -> return '\^I'- 'J' -> return '\^J'- 'K' -> return '\^K'- 'L' -> return '\^L'- 'M' -> return '\^M'- 'N' -> return '\^N'- 'O' -> return '\^O'- 'P' -> return '\^P'- 'Q' -> return '\^Q'- 'R' -> return '\^R'- 'S' -> return '\^S'- 'T' -> return '\^T'- 'U' -> return '\^U'- 'V' -> return '\^V'- 'W' -> return '\^W'- 'X' -> return '\^X'- 'Y' -> return '\^Y'- 'Z' -> return '\^Z'- '[' -> return '\^['- '\\' -> return '\^\'- ']' -> return '\^]'- '^' -> return '\^^'- '_' -> return '\^_'- _ -> pfail-- lexAscii =- do choice- [ (string "SOH" >> return '\SOH') <++- (string "SO" >> return '\SO')- -- \SO and \SOH need maximal-munch treatment- -- See the Haskell report Sect 2.6-- , string "NUL" >> return '\NUL'- , string "STX" >> return '\STX'- , string "ETX" >> return '\ETX'- , string "EOT" >> return '\EOT'- , string "ENQ" >> return '\ENQ'- , string "ACK" >> return '\ACK'- , string "BEL" >> return '\BEL'- , string "BS" >> return '\BS'- , string "HT" >> return '\HT'- , string "LF" >> return '\LF'- , string "VT" >> return '\VT'- , string "FF" >> return '\FF'- , string "CR" >> return '\CR'- , string "SI" >> return '\SI'- , string "DLE" >> return '\DLE'- , string "DC1" >> return '\DC1'- , string "DC2" >> return '\DC2'- , string "DC3" >> return '\DC3'- , string "DC4" >> return '\DC4'- , string "NAK" >> return '\NAK'- , string "SYN" >> return '\SYN'- , string "ETB" >> return '\ETB'- , string "CAN" >> return '\CAN'- , string "EM" >> return '\EM'- , string "SUB" >> return '\SUB'- , string "ESC" >> return '\ESC'- , string "FS" >> return '\FS'- , string "GS" >> return '\GS'- , string "RS" >> return '\RS'- , string "US" >> return '\US'- , string "SP" >> return '\SP'- , string "DEL" >> return '\DEL'- ]----- ------------------------------------------------------------------------------ string literal--lexString :: ReadP Lexeme-lexString =- do _ <- char '"'- body id- where- body f =- do (c,esc) <- lexStrItem- if c /= '"' || esc- then body (f.(c:))- else let s = f "" in- return (String s)-- lexStrItem = (lexEmpty >> lexStrItem)- +++ lexCharE-- lexEmpty =- do _ <- char '\\'- c <- get- case c of- '&' -> do return ()- _ | isSpace c -> do skipSpaces; _ <- char '\\'; return ()- _ -> do pfail---- ------------------------------------------------------------------------------ Lexing numbers--type Base = Int-type Digits = [Int]--lexNumber :: ReadP Lexeme-lexNumber- = lexHexOct <++ -- First try for hex or octal 0x, 0o etc- -- If that fails, try for a decimal number- lexDecNumber -- Start with ordinary digits--lexNumber' :: ReadP Number-lexNumber'- = lexHexOct' <++ -- First try for hex or octal 0x, 0o etc- -- If that fails, try for a decimal number- lexDecNumber'--lexHexOct :: ReadP Lexeme-lexHexOct- = do _ <- char '0'- base <- lexBaseChar- digits <- lexDigits base- return (Int (val (fromIntegral base) 0 digits))--lexHexOct' :: ReadP Number-lexHexOct'- = do _ <- char '0'- base <- lexBaseChar- digits <- lexDigits base- return (MkNumber base digits)--lexBaseChar :: ReadP Int--- Lex a single character indicating the base; fail if not there-lexBaseChar = do { c <- get;- case c of- 'o' -> return 8- 'O' -> return 8- 'x' -> return 16- 'X' -> return 16- _ -> pfail }--lexDecNumber :: ReadP Lexeme-lexDecNumber =- do xs <- lexDigits 10- mFrac <- lexFrac <++ return Nothing- mExp <- lexExp <++ return Nothing- return (value xs mFrac mExp)- where- value xs mFrac mExp = valueFracExp (val 10 0 xs) mFrac mExp-- valueFracExp :: Integer -> Maybe Digits -> Maybe Integer- -> Lexeme- valueFracExp a Nothing Nothing- = Int a -- 43- valueFracExp a Nothing (Just exp)- | exp >= 0 = Int (a * (10 ^ exp)) -- 43e7- | otherwise = Rat (a % (10 ^ (-exp))) -- 43e-7- valueFracExp a (Just fs) mExp -- 4.3[e2]- = Rat (fracExp (fromMaybe 0 mExp) a fs)- -- Be a bit more efficient in calculating the Rational.- -- Instead of calculating the fractional part alone, then- -- adding the integral part and finally multiplying with- -- 10 ^ exp if an exponent was given, do it all at once.--lexDecNumber' :: ReadP Number-lexDecNumber' =- do xs <- lexDigits 10- mFrac <- lexFrac <++ return Nothing- mExp <- lexExp <++ return Nothing- return (MkDecimal xs mFrac mExp)--lexFrac :: ReadP (Maybe Digits)--- Read the fractional part; fail if it doesn't--- start ".d" where d is a digit-lexFrac = do _ <- char '.'- fraction <- lexDigits 10- return (Just fraction)--lexExp :: ReadP (Maybe Integer)-lexExp = do _ <- char 'e' +++ char 'E'- exp <- signedExp +++ lexInteger 10- return (Just exp)- where- signedExp- = do c <- char '-' +++ char '+'- n <- lexInteger 10- return (if c == '-' then -n else n)--lexDigits :: Int -> ReadP Digits--- Lex a non-empty sequence of digits in specified base-lexDigits base =- do s <- look- xs <- scan s id- guard (not (null xs))- return xs- where- scan (c:cs) f = case valDig base c of- Just n -> do _ <- get; scan cs (f.(n:))- Nothing -> do return (f [])- scan [] f = do return (f [])--lexInteger :: Base -> ReadP Integer-lexInteger base =- do xs <- lexDigits base- return (val (fromIntegral base) 0 xs)--val :: Num a => a -> a -> Digits -> a--- val base y [d1,..,dn] = y ++ [d1,..,dn], as it were-val _ y [] = y-val base y (x:xs) = y' `seq` val base y' xs- where- y' = y * base + fromIntegral x---- Calculate a Rational from the exponent [of 10 to multiply with],--- the integral part of the mantissa and the digits of the fractional--- part. Leaving the calculation of the power of 10 until the end,--- when we know the effective exponent, saves multiplications.--- More importantly, this way we need at most one gcd instead of three.------ frac was never used with anything but Integer and base 10, so--- those are hardcoded now (trivial to change if necessary).-fracExp :: Integer -> Integer -> Digits -> Rational-fracExp exp mant []- | exp < 0 = mant % (10 ^ (-exp))- | otherwise = fromInteger (mant * 10 ^ exp)-fracExp exp mant (d:ds) = exp' `seq` mant' `seq` fracExp exp' mant' ds- where- exp' = exp - 1- mant' = mant * 10 + fromIntegral d--valDig :: (Eq a, Num a) => a -> Char -> Maybe Int-valDig 8 c- | '0' <= c && c <= '7' = Just (ord c - ord '0')- | otherwise = Nothing--valDig 10 c = valDecDig c--valDig 16 c- | '0' <= c && c <= '9' = Just (ord c - ord '0')- | 'a' <= c && c <= 'f' = Just (ord c - ord 'a' + 10)- | 'A' <= c && c <= 'F' = Just (ord c - ord 'A' + 10)- | otherwise = Nothing--valDig _ _ = error "valDig: Bad base"--valDecDig :: Char -> Maybe Int-valDecDig c- | '0' <= c && c <= '9' = Just (ord c - ord '0')- | otherwise = Nothing---- ------------------------------------------------------------------------- other numeric lexing functions--readIntP :: Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadP a-readIntP base isDigit valDigit =- do s <- munch1 isDigit- return (val base 0 (map valDigit s))--readIntP' :: (Eq a, Num a) => a -> ReadP a-readIntP' base = readIntP base isDigit valDigit- where- isDigit c = maybe False (const True) (valDig base c)- valDigit c = maybe 0 id (valDig base c)--readOctP, readDecP, readHexP :: (Eq a, Num a) => ReadP a-readOctP = readIntP' 8-readDecP = readIntP' 10-readHexP = readIntP' 16-
@@ -1,50 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP, NoImplicitPrelude #-}---------------------------------------------------------------------------------- |--- Module : Text.Show--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Converting values to readable strings:--- the 'Show' class and associated functions.-----------------------------------------------------------------------------------module Text.Show (- ShowS, -- String -> String- Show(- showsPrec, -- :: Int -> a -> ShowS- show, -- :: a -> String- showList -- :: [a] -> ShowS - ),- shows, -- :: (Show a) => a -> ShowS- showChar, -- :: Char -> ShowS- showString, -- :: String -> ShowS- showParen, -- :: Bool -> ShowS -> ShowS- showListWith, -- :: (a -> ShowS) -> [a] -> ShowS - ) where--#ifdef __GLASGOW_HASKELL__-import GHC.Show-#endif---- | Show a list (using square brackets and commas), given a function--- for showing elements.-showListWith :: (a -> ShowS) -> [a] -> ShowS-showListWith = showList__--#ifndef __GLASGOW_HASKELL__-showList__ :: (a -> ShowS) -> [a] -> ShowS-showList__ _ [] s = "[]" ++ s-showList__ showx (x:xs) s = '[' : showx x (showl xs)- where- showl [] = ']' : s- showl (y:ys) = ',' : showx y (showl ys)-#endif-
@@ -1,39 +0,0 @@-{-# LANGUAGE Safe #-}-{-# LANGUAGE CPP #-}--- This module deliberately declares orphan instances:-{-# OPTIONS_GHC -fno-warn-orphans #-}---------------------------------------------------------------------------------- |--- Module : Text.Show.Functions--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)--- --- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ Optional instance of 'Text.Show.Show' for functions:------ > instance Show (a -> b) where--- > showsPrec _ _ = showString \"\<function\>\"-----------------------------------------------------------------------------------module Text.Show.Functions () where--import Prelude--#ifndef __NHC__-instance Show (a -> b) where- showsPrec _ _ = showString "<function>"-#else-instance (Show a,Show b) => Show (a->b) where- showsPrec d a = showString "<<function>>"-- showsType a = showChar '(' . showsType value . showString " -> " .- showsType result . showChar ')'- where (value,result) = getTypes undefined- getTypes x = (x,a x)-#endif-
@@ -1,47 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}---------------------------------------------------------------------------------- |--- Module : Unsafe.Coerce--- Copyright : Malcolm Wallace 2006--- License : BSD-style (see the LICENSE file in the distribution)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The highly unsafe primitive 'unsafeCoerce' converts a value from any--- type to any other type. Needless to say, if you use this function,--- it is your responsibility to ensure that the old and new types have--- identical internal representations, in order to prevent runtime corruption.------ The types for which 'unsafeCoerce' is representation-safe may differ--- from compiler to compiler (and version to version).------ * Documentation for correct usage in GHC will be found under--- 'unsafeCoerce#' in GHC.Base (around which 'unsafeCoerce' is just a--- trivial wrapper).------ * In nhc98, the only representation-safe coercions are between Enum--- types with the same range (e.g. Int, Int32, Char, Word32),--- or between a newtype and the type that it wraps.-----------------------------------------------------------------------------------module Unsafe.Coerce (unsafeCoerce) where--#if defined(__GLASGOW_HASKELL__)-import GHC.Prim (unsafeCoerce#)-unsafeCoerce :: a -> b-unsafeCoerce = unsafeCoerce#-#endif--#if defined(__NHC__)-import NonStdUnsafeCoerce (unsafeCoerce)-#endif--#if defined(__HUGS__)-import Hugs.IOExts (unsafeCoerce)-#endif-
@@ -1,231 +0,0 @@-# FP_COMPUTE_INT(EXPRESSION, VARIABLE, INCLUDES, IF-FAILS)-# ---------------------------------------------------------# Assign VARIABLE the value of the compile-time EXPRESSION using INCLUDES for-# compilation. Execute IF-FAILS when unable to determine the value. Works for-# cross-compilation, too.-#-# Implementation note: We are lazy and use an internal autoconf macro, but it-# is supported in autoconf versions 2.50 up to the actual 2.57, so there is-# little risk.-# The public AC_COMPUTE_INT macro isn't supported by some versions of-# autoconf.-AC_DEFUN([FP_COMPUTE_INT],-[_AC_COMPUTE_INT([$2], [$1], [$3], [$4])[]dnl-])# FP_COMPUTE_INT---# FP_CHECK_CONST(EXPRESSION, [INCLUDES = DEFAULT-INCLUDES], [VALUE-IF-FAIL = -1])-# --------------------------------------------------------------------------------# Defines CONST_EXPRESSION to the value of the compile-time EXPRESSION, using-# INCLUDES. If the value cannot be determined, use VALUE-IF-FAIL.-AC_DEFUN([FP_CHECK_CONST],-[AS_VAR_PUSHDEF([fp_Cache], [fp_cv_const_$1])[]dnl-AC_CACHE_CHECK([value of $1], fp_Cache,-[FP_COMPUTE_INT(fp_check_const_result, [$1], [AC_INCLUDES_DEFAULT([$2])],- [fp_check_const_result=m4_default([$3], ['-1'])])-AS_VAR_SET(fp_Cache, [$fp_check_const_result])])[]dnl-AC_DEFINE_UNQUOTED(AS_TR_CPP([CONST_$1]), AS_VAR_GET(fp_Cache), [The value of $1.])[]dnl-AS_VAR_POPDEF([fp_Cache])[]dnl-])# FP_CHECK_CONST---# FP_CHECK_CONSTS_TEMPLATE(EXPRESSION...)-# ----------------------------------------# autoheader helper for FP_CHECK_CONSTS-m4_define([FP_CHECK_CONSTS_TEMPLATE],-[AC_FOREACH([fp_Const], [$1],- [AH_TEMPLATE(AS_TR_CPP(CONST_[]fp_Const),- [The value of ]fp_Const[.])])[]dnl-])# FP_CHECK_CONSTS_TEMPLATE---# FP_CHECK_CONSTS(EXPRESSION..., [INCLUDES = DEFAULT-INCLUDES], [VALUE-IF-FAIL = -1])-# ------------------------------------------------------------------------------------# List version of FP_CHECK_CONST-AC_DEFUN([FP_CHECK_CONSTS],-[FP_CHECK_CONSTS_TEMPLATE([$1])dnl-for fp_const_name in $1-do-FP_CHECK_CONST([$fp_const_name], [$2], [$3])-done-])# FP_CHECK_CONSTS---dnl FPTOOLS_HTYPE_INCLUDES-AC_DEFUN([FPTOOLS_HTYPE_INCLUDES],-[-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-])---dnl ** Map an arithmetic C type to a Haskell type.-dnl Based on autconf's AC_CHECK_SIZEOF.--dnl FPTOOLS_CHECK_HTYPE_ELSE(TYPE, WHAT_TO_DO_IF_TYPE_DOES_NOT_EXIST)-AC_DEFUN([FPTOOLS_CHECK_HTYPE_ELSE],[- changequote(<<, >>)- dnl The name to #define.- define(<<AC_TYPE_NAME>>, translit(htype_$1, [a-z *], [A-Z_P]))- dnl The cache variable names.- define(<<AC_CV_NAME>>, translit(fptools_cv_htype_$1, [ *], [_p]))- define(<<AC_CV_NAME_supported>>, translit(fptools_cv_htype_sup_$1, [ *], [_p]))- changequote([, ])-- AC_MSG_CHECKING(Haskell type for $1)- AC_CACHE_VAL(AC_CV_NAME,[- AC_CV_NAME_supported=yes- FP_COMPUTE_INT([HTYPE_IS_INTEGRAL],- [(($1)((int)(($1)1.4))) == (($1)1.4)],- [FPTOOLS_HTYPE_INCLUDES],[AC_CV_NAME_supported=no])- if test "$AC_CV_NAME_supported" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- FP_COMPUTE_INT([HTYPE_IS_FLOAT],[sizeof($1) == sizeof(float)],- [FPTOOLS_HTYPE_INCLUDES],- [AC_CV_NAME_supported=no])- FP_COMPUTE_INT([HTYPE_IS_DOUBLE],[sizeof($1) == sizeof(double)],- [FPTOOLS_HTYPE_INCLUDES],- [AC_CV_NAME_supported=no])- FP_COMPUTE_INT([HTYPE_IS_LDOUBLE],[sizeof($1) == sizeof(long double)],- [FPTOOLS_HTYPE_INCLUDES],- [AC_CV_NAME_supported=no])- if test "$HTYPE_IS_FLOAT" -eq 1- then- AC_CV_NAME=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- AC_CV_NAME=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- AC_CV_NAME=LDouble- else- AC_CV_NAME_supported=no- fi- else- FP_COMPUTE_INT([HTYPE_IS_SIGNED],[(($1)(-1)) < (($1)0)],- [FPTOOLS_HTYPE_INCLUDES],- [AC_CV_NAME_supported=no])- FP_COMPUTE_INT([HTYPE_SIZE],[sizeof($1) * 8],- [FPTOOLS_HTYPE_INCLUDES],- [AC_CV_NAME_supported=no])- if test "$HTYPE_IS_SIGNED" -eq 0- then- AC_CV_NAME="Word$HTYPE_SIZE"- else- AC_CV_NAME="Int$HTYPE_SIZE"- fi- fi- fi- ])- if test "$AC_CV_NAME_supported" = no- then- $2- fi-- dnl Note: evaluating dollar-2 can change the value of- dnl $AC_CV_NAME_supported, so we might now get a different answer- if test "$AC_CV_NAME_supported" = yes; then- AC_MSG_RESULT($AC_CV_NAME)- AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME,- [Define to Haskell type for $1])- fi- undefine([AC_TYPE_NAME])dnl- undefine([AC_CV_NAME])dnl- undefine([AC_CV_NAME_supported])dnl-])--dnl FPTOOLS_CHECK_HTYPE(TYPE)-AC_DEFUN([FPTOOLS_CHECK_HTYPE],[- FPTOOLS_CHECK_HTYPE_ELSE([$1],[- AC_CV_NAME=NotReallyAType- AC_MSG_RESULT([not supported])- ])-])---# FP_SEARCH_LIBS_PROTO(WHAT, PROTOTYPE, FUNCTION, SEARCH-LIBS,-# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND],-# [OTHER-LIBRARIES])-# ---------------------------------------------------------# Search for a library defining FUNC, if it's not already available.-# This is a copy of the AC_SEARCH_LIBS definition, but extended to take-# the name of the thing we are looking for as its first argument, and-# prototype text as its second argument. It also calls AC_LANG_PROGRAM-# instead of AC_LANG_CALL-AC_DEFUN([FP_SEARCH_LIBS_PROTO],-[AS_VAR_PUSHDEF([ac_Search], [ac_cv_search_$1])dnl-AC_CACHE_CHECK([for library containing $1], [ac_Search],-[ac_func_search_save_LIBS=$LIBS-AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])])-for ac_lib in '' $4; do- if test -z "$ac_lib"; then- ac_res="none required"- else- ac_res=-l$ac_lib- LIBS="-l$ac_lib $7 $ac_func_search_save_LIBS"- fi- AC_LINK_IFELSE([], [AS_VAR_SET([ac_Search], [$ac_res])])- AS_VAR_SET_IF([ac_Search], [break])-done-AS_VAR_SET_IF([ac_Search], , [AS_VAR_SET([ac_Search], [no])])-rm conftest.$ac_ext-LIBS=$ac_func_search_save_LIBS])-ac_res=AS_VAR_GET([ac_Search])-AS_IF([test "$ac_res" != no],- [test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"- $5],- [$6])dnl-AS_VAR_POPDEF([ac_Search])dnl-])
@@ -1,253 +0,0 @@-name: base-version: 4.5.1.0-license: BSD3-license-file: LICENSE-maintainer: libraries@haskell.org-bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/base-synopsis: Basic libraries-description:- This package contains the Prelude and its support libraries,- and a large collection of useful libraries ranging from data- structures to parsing combinators and debugging utilities.-cabal-version: >=1.6-build-type: Configure-extra-tmp-files:- config.log config.status autom4te.cache- include/HsBaseConfig.h include/EventConfig.h-extra-source-files:- config.guess config.sub install-sh- aclocal.m4 configure.ac configure- include/CTypes.h include/md5.h--source-repository head- type: git- location: http://darcs.haskell.org/packages/base.git/--Flag integer-simple- Description: Use integer-simple--Library {- if impl(ghc) {- if flag(integer-simple)- build-depends: integer-simple- else- build-depends: integer-gmp- cpp-options: -DOPTIMISE_INTEGER_GCD_LCM- build-depends: rts, ghc-prim- exposed-modules:- Foreign.Concurrent,- GHC.Arr,- GHC.Base,- GHC.Conc,- GHC.Conc.IO,- GHC.Conc.Signal,- GHC.Conc.Sync,- GHC.ConsoleHandler,- GHC.Constants,- GHC.Desugar,- GHC.Enum,- GHC.Environment,- GHC.Err,- GHC.Exception,- GHC.Exts,- GHC.Fingerprint,- GHC.Fingerprint.Type,- GHC.Float,- GHC.Float.ConversionUtils,- GHC.Float.RealFracMethods,- GHC.Foreign,- GHC.ForeignPtr,- GHC.Handle,- GHC.IO,- GHC.IO.Buffer,- GHC.IO.BufferedIO,- GHC.IO.Device,- GHC.IO.Encoding,- GHC.IO.Encoding.CodePage,- GHC.IO.Encoding.Failure,- GHC.IO.Encoding.Iconv,- GHC.IO.Encoding.Latin1,- GHC.IO.Encoding.Types,- GHC.IO.Encoding.UTF16,- GHC.IO.Encoding.UTF32,- GHC.IO.Encoding.UTF8,- GHC.IO.Exception,- GHC.IO.FD,- GHC.IO.Handle,- GHC.IO.Handle.FD,- GHC.IO.Handle.Internals,- GHC.IO.Handle.Text,- GHC.IO.Handle.Types,- GHC.IO.IOMode,- GHC.IOArray,- GHC.IOBase,- GHC.IORef,- GHC.Int,- GHC.List,- GHC.MVar,- GHC.Num,- GHC.PArr,- GHC.Pack,- GHC.Ptr,- GHC.Read,- GHC.Real,- GHC.ST,- GHC.Stack,- GHC.Stats,- GHC.Show,- GHC.Stable,- GHC.Storable,- GHC.STRef,- GHC.TopHandler,- GHC.Unicode,- GHC.Weak,- GHC.Word,- System.Timeout- if os(windows)- exposed-modules: GHC.IO.Encoding.CodePage.Table- GHC.Conc.Windows- GHC.Windows- }- exposed-modules:- Control.Applicative,- Control.Arrow,- Control.Category,- Control.Concurrent,- Control.Concurrent.Chan,- Control.Concurrent.MVar,- Control.Concurrent.QSem,- Control.Concurrent.QSemN,- Control.Concurrent.SampleVar,- Control.Exception,- Control.Exception.Base- Control.OldException,- Control.Monad,- Control.Monad.Fix,- Control.Monad.Instances,- Control.Monad.ST,- Control.Monad.ST.Safe,- Control.Monad.ST.Unsafe,- Control.Monad.ST.Lazy,- Control.Monad.ST.Lazy.Safe,- Control.Monad.ST.Lazy.Unsafe,- Control.Monad.ST.Strict,- Control.Monad.Zip- Data.Bits,- Data.Bool,- Data.Char,- Data.Complex,- Data.Dynamic,- Data.Either,- Data.Eq,- Data.Data,- Data.Fixed,- Data.Foldable- Data.Function,- Data.Functor,- Data.HashTable,- Data.IORef,- Data.Int,- Data.Ix,- Data.List,- Data.Maybe,- Data.Monoid,- Data.Ord,- Data.Ratio,- Data.STRef- Data.STRef.Lazy- Data.STRef.Strict- Data.String,- Data.Traversable- Data.Tuple,- Data.Typeable,- Data.Typeable.Internal,- Data.Unique,- Data.Version,- Data.Word,- Debug.Trace,- Foreign,- Foreign.C,- Foreign.C.Error,- Foreign.C.String,- Foreign.C.Types,- Foreign.ForeignPtr,- Foreign.ForeignPtr.Safe,- Foreign.ForeignPtr.Unsafe,- Foreign.Marshal,- Foreign.Marshal.Alloc,- Foreign.Marshal.Array,- Foreign.Marshal.Error,- Foreign.Marshal.Pool,- Foreign.Marshal.Safe,- Foreign.Marshal.Utils,- Foreign.Marshal.Unsafe,- Foreign.Ptr,- Foreign.Safe,- Foreign.StablePtr,- Foreign.Storable,- Numeric,- Prelude,- System.Console.GetOpt- System.CPUTime,- System.Environment,- System.Exit,- System.IO,- System.IO.Error,- System.IO.Unsafe,- System.Info,- System.Mem,- System.Mem.StableName,- System.Mem.Weak,- System.Posix.Internals,- System.Posix.Types,- Text.ParserCombinators.ReadP,- Text.ParserCombinators.ReadPrec,- Text.Printf,- Text.Read,- Text.Read.Lex,- Text.Show,- Text.Show.Functions- Unsafe.Coerce- other-modules:- Control.Monad.ST.Imp- Control.Monad.ST.Lazy.Imp- Foreign.ForeignPtr.Imp- c-sources:- cbits/PrelIOUtils.c- cbits/WCsubst.c- cbits/Win32Utils.c- cbits/consUtils.c- cbits/iconv.c- cbits/inputReady.c- cbits/selectUtils.c- cbits/primFloat.c- cbits/md5.c- include-dirs: include- includes: HsBase.h- install-includes: HsBase.h HsBaseConfig.h EventConfig.h WCsubst.h consUtils.h Typeable.h- if os(windows) {- extra-libraries: wsock32, user32, shell32- }- if !os(windows) {- exposed-modules:- GHC.Event- other-modules:- GHC.Event.Array- GHC.Event.Clock- GHC.Event.Control- GHC.Event.EPoll- GHC.Event.IntMap- GHC.Event.Internal- GHC.Event.KQueue- GHC.Event.Manager- GHC.Event.PSQ- GHC.Event.Poll- GHC.Event.Thread- GHC.Event.Unique- }- -- We need to set the package name to base (without a version number)- -- as it's magic.- ghc-options: -package-name base- nhc98-options: -H4M -K3M- extensions: CPP-}
@@ -1,52 +0,0 @@-/* - * (c) The University of Glasgow 2002- *- * static versions of the inline functions in HsCore.h- */--#define INLINE--#ifdef __GLASGOW_HASKELL__-# include "Rts.h"-#endif--#include "HsBase.h"--#ifdef __GLASGOW_HASKELL__--void errorBelch2(const char*s, char *t)-{- errorBelch(s,t);-}--void debugBelch2(const char*s, char *t)-{- debugBelch(s,t);-}--#if defined(HAVE_LIBCHARSET)-# include <libcharset.h>-#elif defined(HAVE_LANGINFO_H)-# include <langinfo.h>-#endif--#if !defined(mingw32_HOST_OS)-const char* localeEncoding(void)-{-#if defined(HAVE_LIBCHARSET)- return locale_charset();--#elif defined(HAVE_LANGINFO_H)- return nl_langinfo(CODESET);--#else-#warning Depending on the unportable behavior of GNU iconv due to absence of both libcharset and langinfo.h- /* GNU iconv accepts "" to mean the current locale's- * encoding. Warning: This isn't portable.- */- return "";-#endif-}-#endif--#endif /* __GLASGOW_HASKELL__ */
@@ -1,4398 +0,0 @@-/*--------------------------------------------------------------------------This is an automatically generated file: do not edit-Generated by ubconfc at Mon Feb 7 20:26:56 CET 2011--------------------------------------------------------------------------*/--#include "WCsubst.h"--/* Unicode general categories, listed in the same order as in the Unicode- * standard -- this must be the same order as in GHC.Unicode.- */--enum {- NUMCAT_LU, /* Letter, Uppercase */- NUMCAT_LL, /* Letter, Lowercase */- NUMCAT_LT, /* Letter, Titlecase */- NUMCAT_LM, /* Letter, Modifier */- NUMCAT_LO, /* Letter, Other */- NUMCAT_MN, /* Mark, Non-Spacing */- NUMCAT_MC, /* Mark, Spacing Combining */- NUMCAT_ME, /* Mark, Enclosing */- NUMCAT_ND, /* Number, Decimal */- NUMCAT_NL, /* Number, Letter */- NUMCAT_NO, /* Number, Other */- NUMCAT_PC, /* Punctuation, Connector */- NUMCAT_PD, /* Punctuation, Dash */- NUMCAT_PS, /* Punctuation, Open */- NUMCAT_PE, /* Punctuation, Close */- NUMCAT_PI, /* Punctuation, Initial quote */- NUMCAT_PF, /* Punctuation, Final quote */- NUMCAT_PO, /* Punctuation, Other */- NUMCAT_SM, /* Symbol, Math */- NUMCAT_SC, /* Symbol, Currency */- NUMCAT_SK, /* Symbol, Modifier */- NUMCAT_SO, /* Symbol, Other */- NUMCAT_ZS, /* Separator, Space */- NUMCAT_ZL, /* Separator, Line */- NUMCAT_ZP, /* Separator, Paragraph */- NUMCAT_CC, /* Other, Control */- NUMCAT_CF, /* Other, Format */- NUMCAT_CS, /* Other, Surrogate */- NUMCAT_CO, /* Other, Private Use */- NUMCAT_CN /* Other, Not Assigned */-};--struct _convrule_ -{ - unsigned int category;- unsigned int catnumber;- int possible;- int updist;- int lowdist; - int titledist;-};--struct _charblock_ -{ - int start;- int length;- const struct _convrule_ *rule;-};--#define GENCAT_LO 262144-#define GENCAT_PC 2048-#define GENCAT_PD 128-#define GENCAT_MN 2097152-#define GENCAT_PE 32-#define GENCAT_NL 16777216-#define GENCAT_PF 131072-#define GENCAT_LT 524288-#define GENCAT_NO 65536-#define GENCAT_LU 512-#define GENCAT_PI 16384-#define GENCAT_SC 8-#define GENCAT_PO 4-#define GENCAT_PS 16-#define GENCAT_SK 1024-#define GENCAT_SM 64-#define GENCAT_SO 8192-#define GENCAT_CC 1-#define GENCAT_CF 32768-#define GENCAT_CO 268435456-#define GENCAT_ZL 33554432-#define GENCAT_CS 134217728-#define GENCAT_ZP 67108864-#define GENCAT_ZS 2-#define GENCAT_MC 8388608-#define GENCAT_ME 4194304-#define GENCAT_ND 256-#define GENCAT_LL 4096-#define GENCAT_LM 1048576-#define MAX_UNI_CHAR 1114109-#define NUM_BLOCKS 2783-#define NUM_CONVBLOCKS 1230-#define NUM_SPACEBLOCKS 8-#define NUM_LAT1BLOCKS 63-#define NUM_RULES 167-static const struct _convrule_ rule160={GENCAT_LL, NUMCAT_LL, 1, -7264, 0, -7264};-static const struct _convrule_ rule36={GENCAT_LU, NUMCAT_LU, 1, 0, 211, 0};-static const struct _convrule_ rule25={GENCAT_LU, NUMCAT_LU, 1, 0, -121, 0};-static const struct _convrule_ rule18={GENCAT_LL, NUMCAT_LL, 1, 743, 0, 743};-static const struct _convrule_ rule108={GENCAT_LU, NUMCAT_LU, 1, 0, 80, 0};-static const struct _convrule_ rule50={GENCAT_LL, NUMCAT_LL, 1, -79, 0, -79};-static const struct _convrule_ rule106={GENCAT_LL, NUMCAT_LL, 1, -96, 0, -96};-static const struct _convrule_ rule79={GENCAT_LL, NUMCAT_LL, 1, -69, 0, -69};-static const struct _convrule_ rule126={GENCAT_LL, NUMCAT_LL, 1, 128, 0, 128};-static const struct _convrule_ rule119={GENCAT_LL, NUMCAT_LL, 1, -59, 0, -59};-static const struct _convrule_ rule102={GENCAT_LL, NUMCAT_LL, 1, -86, 0, -86};-static const struct _convrule_ rule38={GENCAT_LL, NUMCAT_LL, 1, 163, 0, 163};-static const struct _convrule_ rule113={GENCAT_LL, NUMCAT_LL, 1, -48, 0, -48};-static const struct _convrule_ rule133={GENCAT_LL, NUMCAT_LL, 1, -7205, 0, -7205};-static const struct _convrule_ rule128={GENCAT_LL, NUMCAT_LL, 1, 126, 0, 126};-static const struct _convrule_ rule97={GENCAT_LL, NUMCAT_LL, 1, -57, 0, -57};-static const struct _convrule_ rule161={GENCAT_LU, NUMCAT_LU, 1, 0, -35332, 0};-static const struct _convrule_ rule136={GENCAT_LU, NUMCAT_LU, 1, 0, -112, 0};-static const struct _convrule_ rule99={GENCAT_LL, NUMCAT_LL, 1, -47, 0, -47};-static const struct _convrule_ rule90={GENCAT_LL, NUMCAT_LL, 1, -38, 0, -38};-static const struct _convrule_ rule32={GENCAT_LU, NUMCAT_LU, 1, 0, 202, 0};-static const struct _convrule_ rule145={GENCAT_LL, NUMCAT_LL, 1, -28, 0, -28};-static const struct _convrule_ rule93={GENCAT_LL, NUMCAT_LL, 1, -64, 0, -64};-static const struct _convrule_ rule91={GENCAT_LL, NUMCAT_LL, 1, -37, 0, -37};-static const struct _convrule_ rule60={GENCAT_LU, NUMCAT_LU, 1, 0, 71, 0};-static const struct _convrule_ rule100={GENCAT_LL, NUMCAT_LL, 1, -54, 0, -54};-static const struct _convrule_ rule94={GENCAT_LL, NUMCAT_LL, 1, -63, 0, -63};-static const struct _convrule_ rule35={GENCAT_LL, NUMCAT_LL, 1, 97, 0, 97};-static const struct _convrule_ rule149={GENCAT_SO, NUMCAT_SO, 1, -26, 0, -26};-static const struct _convrule_ rule103={GENCAT_LL, NUMCAT_LL, 1, -80, 0, -80};-static const struct _convrule_ rule96={GENCAT_LL, NUMCAT_LL, 1, -62, 0, -62};-static const struct _convrule_ rule81={GENCAT_LL, NUMCAT_LL, 1, -71, 0, -71};-static const struct _convrule_ rule9={GENCAT_LU, NUMCAT_LU, 1, 0, 32, 0};-static const struct _convrule_ rule147={GENCAT_NL, NUMCAT_NL, 1, -16, 0, -16};-static const struct _convrule_ rule143={GENCAT_LU, NUMCAT_LU, 1, 0, -8262, 0};-static const struct _convrule_ rule127={GENCAT_LL, NUMCAT_LL, 1, 112, 0, 112};-static const struct _convrule_ rule124={GENCAT_LL, NUMCAT_LL, 1, 86, 0, 86};-static const struct _convrule_ rule40={GENCAT_LL, NUMCAT_LL, 1, 130, 0, 130};-static const struct _convrule_ rule20={GENCAT_LL, NUMCAT_LL, 1, 121, 0, 121};-static const struct _convrule_ rule158={GENCAT_LU, NUMCAT_LU, 1, 0, -10782, 0};-static const struct _convrule_ rule111={GENCAT_LL, NUMCAT_LL, 1, -15, 0, -15};-static const struct _convrule_ rule12={GENCAT_LL, NUMCAT_LL, 1, -32, 0, -32};-static const struct _convrule_ rule85={GENCAT_MN, NUMCAT_MN, 1, 84, 0, 84};-static const struct _convrule_ rule166={GENCAT_LL, NUMCAT_LL, 1, -40, 0, -40};-static const struct _convrule_ rule125={GENCAT_LL, NUMCAT_LL, 1, 100, 0, 100};-static const struct _convrule_ rule123={GENCAT_LL, NUMCAT_LL, 1, 74, 0, 74};-static const struct _convrule_ rule92={GENCAT_LL, NUMCAT_LL, 1, -31, 0, -31};-static const struct _convrule_ rule56={GENCAT_LU, NUMCAT_LU, 1, 0, 10792, 0};-static const struct _convrule_ rule46={GENCAT_LL, NUMCAT_LL, 1, 56, 0, 56};-static const struct _convrule_ rule33={GENCAT_LU, NUMCAT_LU, 1, 0, 203, 0};-static const struct _convrule_ rule150={GENCAT_LU, NUMCAT_LU, 1, 0, -10743, 0};-static const struct _convrule_ rule39={GENCAT_LU, NUMCAT_LU, 1, 0, 213, 0};-static const struct _convrule_ rule57={GENCAT_LL, NUMCAT_LL, 1, 10815, 0, 10815};-static const struct _convrule_ rule157={GENCAT_LU, NUMCAT_LU, 1, 0, -10783, 0};-static const struct _convrule_ rule55={GENCAT_LU, NUMCAT_LU, 1, 0, -163, 0};-static const struct _convrule_ rule151={GENCAT_LU, NUMCAT_LU, 1, 0, -3814, 0};-static const struct _convrule_ rule142={GENCAT_LU, NUMCAT_LU, 1, 0, -8383, 0};-static const struct _convrule_ rule101={GENCAT_LL, NUMCAT_LL, 1, -8, 0, -8};-static const struct _convrule_ rule89={GENCAT_LU, NUMCAT_LU, 1, 0, 63, 0};-static const struct _convrule_ rule41={GENCAT_LU, NUMCAT_LU, 1, 0, 214, 0};-static const struct _convrule_ rule118={GENCAT_LL, NUMCAT_LL, 1, 3814, 0, 3814};-static const struct _convrule_ rule26={GENCAT_LL, NUMCAT_LL, 1, -300, 0, -300};-static const struct _convrule_ rule159={GENCAT_LU, NUMCAT_LU, 1, 0, -10815, 0};-static const struct _convrule_ rule115={GENCAT_LU, NUMCAT_LU, 1, 0, 7264, 0};-static const struct _convrule_ rule22={GENCAT_LL, NUMCAT_LL, 1, -1, 0, -1};-static const struct _convrule_ rule120={GENCAT_LU, NUMCAT_LU, 1, 0, -7615, 0};-static const struct _convrule_ rule49={GENCAT_LL, NUMCAT_LL, 1, -2, 0, -1};-static const struct _convrule_ rule131={GENCAT_LU, NUMCAT_LU, 1, 0, -74, 0};-static const struct _convrule_ rule88={GENCAT_LU, NUMCAT_LU, 1, 0, 64, 0};-static const struct _convrule_ rule30={GENCAT_LU, NUMCAT_LU, 1, 0, 205, 0};-static const struct _convrule_ rule117={GENCAT_LL, NUMCAT_LL, 1, 35332, 0, 35332};-static const struct _convrule_ rule110={GENCAT_LU, NUMCAT_LU, 1, 0, 15, 0};-static const struct _convrule_ rule130={GENCAT_LL, NUMCAT_LL, 1, 9, 0, 9};-static const struct _convrule_ rule121={GENCAT_LL, NUMCAT_LL, 1, 8, 0, 8};-static const struct _convrule_ rule95={GENCAT_LU, NUMCAT_LU, 1, 0, 8, 0};-static const struct _convrule_ rule54={GENCAT_LU, NUMCAT_LU, 1, 0, 10795, 0};-static const struct _convrule_ rule29={GENCAT_LU, NUMCAT_LU, 1, 0, 206, 0};-static const struct _convrule_ rule138={GENCAT_LU, NUMCAT_LU, 1, 0, -126, 0};-static const struct _convrule_ rule104={GENCAT_LL, NUMCAT_LL, 1, 7, 0, 7};-static const struct _convrule_ rule58={GENCAT_LU, NUMCAT_LU, 1, 0, -195, 0};-static const struct _convrule_ rule146={GENCAT_NL, NUMCAT_NL, 1, 0, 16, 0};-static const struct _convrule_ rule148={GENCAT_SO, NUMCAT_SO, 1, 0, 26, 0};-static const struct _convrule_ rule70={GENCAT_LL, NUMCAT_LL, 1, 42280, 0, 42280};-static const struct _convrule_ rule107={GENCAT_LU, NUMCAT_LU, 1, 0, -7, 0};-static const struct _convrule_ rule52={GENCAT_LU, NUMCAT_LU, 1, 0, -56, 0};-static const struct _convrule_ rule153={GENCAT_LL, NUMCAT_LL, 1, -10795, 0, -10795};-static const struct _convrule_ rule152={GENCAT_LU, NUMCAT_LU, 1, 0, -10727, 0};-static const struct _convrule_ rule141={GENCAT_LU, NUMCAT_LU, 1, 0, -7517, 0};-static const struct _convrule_ rule34={GENCAT_LU, NUMCAT_LU, 1, 0, 207, 0};-static const struct _convrule_ rule164={GENCAT_CO, NUMCAT_CO, 0, 0, 0, 0};-static const struct _convrule_ rule84={GENCAT_MN, NUMCAT_MN, 0, 0, 0, 0};-static const struct _convrule_ rule16={GENCAT_CF, NUMCAT_CF, 0, 0, 0, 0};-static const struct _convrule_ rule45={GENCAT_LO, NUMCAT_LO, 0, 0, 0, 0};-static const struct _convrule_ rule13={GENCAT_SO, NUMCAT_SO, 0, 0, 0, 0};-static const struct _convrule_ rule17={GENCAT_NO, NUMCAT_NO, 0, 0, 0, 0};-static const struct _convrule_ rule8={GENCAT_ND, NUMCAT_ND, 0, 0, 0, 0};-static const struct _convrule_ rule14={GENCAT_LL, NUMCAT_LL, 0, 0, 0, 0};-static const struct _convrule_ rule98={GENCAT_LU, NUMCAT_LU, 0, 0, 0, 0};-static const struct _convrule_ rule6={GENCAT_SM, NUMCAT_SM, 0, 0, 0, 0};-static const struct _convrule_ rule114={GENCAT_MC, NUMCAT_MC, 0, 0, 0, 0};-static const struct _convrule_ rule2={GENCAT_PO, NUMCAT_PO, 0, 0, 0, 0};-static const struct _convrule_ rule116={GENCAT_NL, NUMCAT_NL, 0, 0, 0, 0};-static const struct _convrule_ rule3={GENCAT_SC, NUMCAT_SC, 0, 0, 0, 0};-static const struct _convrule_ rule10={GENCAT_SK, NUMCAT_SK, 0, 0, 0, 0};-static const struct _convrule_ rule83={GENCAT_LM, NUMCAT_LM, 0, 0, 0, 0};-static const struct _convrule_ rule5={GENCAT_PE, NUMCAT_PE, 0, 0, 0, 0};-static const struct _convrule_ rule4={GENCAT_PS, NUMCAT_PS, 0, 0, 0, 0};-static const struct _convrule_ rule11={GENCAT_PC, NUMCAT_PC, 0, 0, 0, 0};-static const struct _convrule_ rule7={GENCAT_PD, NUMCAT_PD, 0, 0, 0, 0};-static const struct _convrule_ rule163={GENCAT_CS, NUMCAT_CS, 0, 0, 0, 0};-static const struct _convrule_ rule109={GENCAT_ME, NUMCAT_ME, 0, 0, 0, 0};-static const struct _convrule_ rule1={GENCAT_ZS, NUMCAT_ZS, 0, 0, 0, 0};-static const struct _convrule_ rule19={GENCAT_PF, NUMCAT_PF, 0, 0, 0, 0};-static const struct _convrule_ rule15={GENCAT_PI, NUMCAT_PI, 0, 0, 0, 0};-static const struct _convrule_ rule140={GENCAT_ZP, NUMCAT_ZP, 0, 0, 0, 0};-static const struct _convrule_ rule139={GENCAT_ZL, NUMCAT_ZL, 0, 0, 0, 0};-static const struct _convrule_ rule134={GENCAT_LU, NUMCAT_LU, 1, 0, -86, 0};-static const struct _convrule_ rule43={GENCAT_LU, NUMCAT_LU, 1, 0, 217, 0};-static const struct _convrule_ rule0={GENCAT_CC, NUMCAT_CC, 0, 0, 0, 0};-static const struct _convrule_ rule154={GENCAT_LL, NUMCAT_LL, 1, -10792, 0, -10792};-static const struct _convrule_ rule74={GENCAT_LL, NUMCAT_LL, 1, 10749, 0, 10749};-static const struct _convrule_ rule87={GENCAT_LU, NUMCAT_LU, 1, 0, 37, 0};-static const struct _convrule_ rule61={GENCAT_LL, NUMCAT_LL, 1, 10783, 0, 10783};-static const struct _convrule_ rule122={GENCAT_LU, NUMCAT_LU, 1, 0, -8, 0};-static const struct _convrule_ rule129={GENCAT_LT, NUMCAT_LT, 1, 0, -8, 0};-static const struct _convrule_ rule63={GENCAT_LL, NUMCAT_LL, 1, 10782, 0, 10782};-static const struct _convrule_ rule82={GENCAT_LL, NUMCAT_LL, 1, -219, 0, -219};-static const struct _convrule_ rule77={GENCAT_LL, NUMCAT_LL, 1, 10727, 0, 10727};-static const struct _convrule_ rule78={GENCAT_LL, NUMCAT_LL, 1, -218, 0, -218};-static const struct _convrule_ rule71={GENCAT_LL, NUMCAT_LL, 1, -209, 0, -209};-static const struct _convrule_ rule62={GENCAT_LL, NUMCAT_LL, 1, 10780, 0, 10780};-static const struct _convrule_ rule48={GENCAT_LT, NUMCAT_LT, 1, -1, 1, 0};-static const struct _convrule_ rule21={GENCAT_LU, NUMCAT_LU, 1, 0, 1, 0};-static const struct _convrule_ rule137={GENCAT_LU, NUMCAT_LU, 1, 0, -128, 0};-static const struct _convrule_ rule80={GENCAT_LL, NUMCAT_LL, 1, -217, 0, -217};-static const struct _convrule_ rule73={GENCAT_LL, NUMCAT_LL, 1, 10743, 0, 10743};-static const struct _convrule_ rule42={GENCAT_LU, NUMCAT_LU, 1, 0, 218, 0};-static const struct _convrule_ rule69={GENCAT_LL, NUMCAT_LL, 1, -207, 0, -207};-static const struct _convrule_ rule51={GENCAT_LU, NUMCAT_LU, 1, 0, -97, 0};-static const struct _convrule_ rule144={GENCAT_LU, NUMCAT_LU, 1, 0, 28, 0};-static const struct _convrule_ rule65={GENCAT_LL, NUMCAT_LL, 1, -206, 0, -206};-static const struct _convrule_ rule86={GENCAT_LU, NUMCAT_LU, 1, 0, 38, 0};-static const struct _convrule_ rule76={GENCAT_LL, NUMCAT_LL, 1, -214, 0, -214};-static const struct _convrule_ rule66={GENCAT_LL, NUMCAT_LL, 1, -205, 0, -205};-static const struct _convrule_ rule24={GENCAT_LL, NUMCAT_LL, 1, -232, 0, -232};-static const struct _convrule_ rule112={GENCAT_LU, NUMCAT_LU, 1, 0, 48, 0};-static const struct _convrule_ rule132={GENCAT_LT, NUMCAT_LT, 1, 0, -9, 0};-static const struct _convrule_ rule75={GENCAT_LL, NUMCAT_LL, 1, -213, 0, -213};-static const struct _convrule_ rule68={GENCAT_LL, NUMCAT_LL, 1, -203, 0, -203};-static const struct _convrule_ rule135={GENCAT_LU, NUMCAT_LU, 1, 0, -100, 0};-static const struct _convrule_ rule72={GENCAT_LL, NUMCAT_LL, 1, -211, 0, -211};-static const struct _convrule_ rule67={GENCAT_LL, NUMCAT_LL, 1, -202, 0, -202};-static const struct _convrule_ rule47={GENCAT_LU, NUMCAT_LU, 1, 0, 2, 1};-static const struct _convrule_ rule37={GENCAT_LU, NUMCAT_LU, 1, 0, 209, 0};-static const struct _convrule_ rule156={GENCAT_LU, NUMCAT_LU, 1, 0, -10749, 0};-static const struct _convrule_ rule64={GENCAT_LL, NUMCAT_LL, 1, -210, 0, -210};-static const struct _convrule_ rule44={GENCAT_LU, NUMCAT_LU, 1, 0, 219, 0};-static const struct _convrule_ rule28={GENCAT_LU, NUMCAT_LU, 1, 0, 210, 0};-static const struct _convrule_ rule53={GENCAT_LU, NUMCAT_LU, 1, 0, -130, 0};-static const struct _convrule_ rule165={GENCAT_LU, NUMCAT_LU, 1, 0, 40, 0};-static const struct _convrule_ rule162={GENCAT_LU, NUMCAT_LU, 1, 0, -42280, 0};-static const struct _convrule_ rule155={GENCAT_LU, NUMCAT_LU, 1, 0, -10780, 0};-static const struct _convrule_ rule105={GENCAT_LU, NUMCAT_LU, 1, 0, -60, 0};-static const struct _convrule_ rule59={GENCAT_LU, NUMCAT_LU, 1, 0, 69, 0};-static const struct _convrule_ rule31={GENCAT_LU, NUMCAT_LU, 1, 0, 79, 0};-static const struct _convrule_ rule27={GENCAT_LL, NUMCAT_LL, 1, 195, 0, 195};-static const struct _convrule_ rule23={GENCAT_LU, NUMCAT_LU, 1, 0, -199, 0};-static const struct _charblock_ allchars[]={- {0, 32, &rule0},- {32, 1, &rule1},- {33, 3, &rule2},- {36, 1, &rule3},- {37, 3, &rule2},- {40, 1, &rule4},- {41, 1, &rule5},- {42, 1, &rule2},- {43, 1, &rule6},- {44, 1, &rule2},- {45, 1, &rule7},- {46, 2, &rule2},- {48, 10, &rule8},- {58, 2, &rule2},- {60, 3, &rule6},- {63, 2, &rule2},- {65, 26, &rule9},- {91, 1, &rule4},- {92, 1, &rule2},- {93, 1, &rule5},- {94, 1, &rule10},- {95, 1, &rule11},- {96, 1, &rule10},- {97, 26, &rule12},- {123, 1, &rule4},- {124, 1, &rule6},- {125, 1, &rule5},- {126, 1, &rule6},- {127, 33, &rule0},- {160, 1, &rule1},- {161, 1, &rule2},- {162, 4, &rule3},- {166, 2, &rule13},- {168, 1, &rule10},- {169, 1, &rule13},- {170, 1, &rule14},- {171, 1, &rule15},- {172, 1, &rule6},- {173, 1, &rule16},- {174, 1, &rule13},- {175, 1, &rule10},- {176, 1, &rule13},- {177, 1, &rule6},- {178, 2, &rule17},- {180, 1, &rule10},- {181, 1, &rule18},- {182, 1, &rule13},- {183, 1, &rule2},- {184, 1, &rule10},- {185, 1, &rule17},- {186, 1, &rule14},- {187, 1, &rule19},- {188, 3, &rule17},- {191, 1, &rule2},- {192, 23, &rule9},- {215, 1, &rule6},- {216, 7, &rule9},- {223, 1, &rule14},- {224, 23, &rule12},- {247, 1, &rule6},- {248, 7, &rule12},- {255, 1, &rule20},- {256, 1, &rule21},- {257, 1, &rule22},- {258, 1, &rule21},- {259, 1, &rule22},- {260, 1, &rule21},- {261, 1, &rule22},- {262, 1, &rule21},- {263, 1, &rule22},- {264, 1, &rule21},- {265, 1, &rule22},- {266, 1, &rule21},- {267, 1, &rule22},- {268, 1, &rule21},- {269, 1, &rule22},- {270, 1, &rule21},- {271, 1, &rule22},- {272, 1, &rule21},- {273, 1, &rule22},- {274, 1, &rule21},- {275, 1, &rule22},- {276, 1, &rule21},- {277, 1, &rule22},- {278, 1, &rule21},- {279, 1, &rule22},- {280, 1, &rule21},- {281, 1, &rule22},- {282, 1, &rule21},- {283, 1, &rule22},- {284, 1, &rule21},- {285, 1, &rule22},- {286, 1, &rule21},- {287, 1, &rule22},- {288, 1, &rule21},- {289, 1, &rule22},- {290, 1, &rule21},- {291, 1, &rule22},- {292, 1, &rule21},- {293, 1, &rule22},- {294, 1, &rule21},- {295, 1, &rule22},- {296, 1, &rule21},- {297, 1, &rule22},- {298, 1, &rule21},- {299, 1, &rule22},- {300, 1, &rule21},- {301, 1, &rule22},- {302, 1, &rule21},- {303, 1, &rule22},- {304, 1, &rule23},- {305, 1, &rule24},- {306, 1, &rule21},- {307, 1, &rule22},- {308, 1, &rule21},- {309, 1, &rule22},- {310, 1, &rule21},- {311, 1, &rule22},- {312, 1, &rule14},- {313, 1, &rule21},- {314, 1, &rule22},- {315, 1, &rule21},- {316, 1, &rule22},- {317, 1, &rule21},- {318, 1, &rule22},- {319, 1, &rule21},- {320, 1, &rule22},- {321, 1, &rule21},- {322, 1, &rule22},- {323, 1, &rule21},- {324, 1, &rule22},- {325, 1, &rule21},- {326, 1, &rule22},- {327, 1, &rule21},- {328, 1, &rule22},- {329, 1, &rule14},- {330, 1, &rule21},- {331, 1, &rule22},- {332, 1, &rule21},- {333, 1, &rule22},- {334, 1, &rule21},- {335, 1, &rule22},- {336, 1, &rule21},- {337, 1, &rule22},- {338, 1, &rule21},- {339, 1, &rule22},- {340, 1, &rule21},- {341, 1, &rule22},- {342, 1, &rule21},- {343, 1, &rule22},- {344, 1, &rule21},- {345, 1, &rule22},- {346, 1, &rule21},- {347, 1, &rule22},- {348, 1, &rule21},- {349, 1, &rule22},- {350, 1, &rule21},- {351, 1, &rule22},- {352, 1, &rule21},- {353, 1, &rule22},- {354, 1, &rule21},- {355, 1, &rule22},- {356, 1, &rule21},- {357, 1, &rule22},- {358, 1, &rule21},- {359, 1, &rule22},- {360, 1, &rule21},- {361, 1, &rule22},- {362, 1, &rule21},- {363, 1, &rule22},- {364, 1, &rule21},- {365, 1, &rule22},- {366, 1, &rule21},- {367, 1, &rule22},- {368, 1, &rule21},- {369, 1, &rule22},- {370, 1, &rule21},- {371, 1, &rule22},- {372, 1, &rule21},- {373, 1, &rule22},- {374, 1, &rule21},- {375, 1, &rule22},- {376, 1, &rule25},- {377, 1, &rule21},- {378, 1, &rule22},- {379, 1, &rule21},- {380, 1, &rule22},- {381, 1, &rule21},- {382, 1, &rule22},- {383, 1, &rule26},- {384, 1, &rule27},- {385, 1, &rule28},- {386, 1, &rule21},- {387, 1, &rule22},- {388, 1, &rule21},- {389, 1, &rule22},- {390, 1, &rule29},- {391, 1, &rule21},- {392, 1, &rule22},- {393, 2, &rule30},- {395, 1, &rule21},- {396, 1, &rule22},- {397, 1, &rule14},- {398, 1, &rule31},- {399, 1, &rule32},- {400, 1, &rule33},- {401, 1, &rule21},- {402, 1, &rule22},- {403, 1, &rule30},- {404, 1, &rule34},- {405, 1, &rule35},- {406, 1, &rule36},- {407, 1, &rule37},- {408, 1, &rule21},- {409, 1, &rule22},- {410, 1, &rule38},- {411, 1, &rule14},- {412, 1, &rule36},- {413, 1, &rule39},- {414, 1, &rule40},- {415, 1, &rule41},- {416, 1, &rule21},- {417, 1, &rule22},- {418, 1, &rule21},- {419, 1, &rule22},- {420, 1, &rule21},- {421, 1, &rule22},- {422, 1, &rule42},- {423, 1, &rule21},- {424, 1, &rule22},- {425, 1, &rule42},- {426, 2, &rule14},- {428, 1, &rule21},- {429, 1, &rule22},- {430, 1, &rule42},- {431, 1, &rule21},- {432, 1, &rule22},- {433, 2, &rule43},- {435, 1, &rule21},- {436, 1, &rule22},- {437, 1, &rule21},- {438, 1, &rule22},- {439, 1, &rule44},- {440, 1, &rule21},- {441, 1, &rule22},- {442, 1, &rule14},- {443, 1, &rule45},- {444, 1, &rule21},- {445, 1, &rule22},- {446, 1, &rule14},- {447, 1, &rule46},- {448, 4, &rule45},- {452, 1, &rule47},- {453, 1, &rule48},- {454, 1, &rule49},- {455, 1, &rule47},- {456, 1, &rule48},- {457, 1, &rule49},- {458, 1, &rule47},- {459, 1, &rule48},- {460, 1, &rule49},- {461, 1, &rule21},- {462, 1, &rule22},- {463, 1, &rule21},- {464, 1, &rule22},- {465, 1, &rule21},- {466, 1, &rule22},- {467, 1, &rule21},- {468, 1, &rule22},- {469, 1, &rule21},- {470, 1, &rule22},- {471, 1, &rule21},- {472, 1, &rule22},- {473, 1, &rule21},- {474, 1, &rule22},- {475, 1, &rule21},- {476, 1, &rule22},- {477, 1, &rule50},- {478, 1, &rule21},- {479, 1, &rule22},- {480, 1, &rule21},- {481, 1, &rule22},- {482, 1, &rule21},- {483, 1, &rule22},- {484, 1, &rule21},- {485, 1, &rule22},- {486, 1, &rule21},- {487, 1, &rule22},- {488, 1, &rule21},- {489, 1, &rule22},- {490, 1, &rule21},- {491, 1, &rule22},- {492, 1, &rule21},- {493, 1, &rule22},- {494, 1, &rule21},- {495, 1, &rule22},- {496, 1, &rule14},- {497, 1, &rule47},- {498, 1, &rule48},- {499, 1, &rule49},- {500, 1, &rule21},- {501, 1, &rule22},- {502, 1, &rule51},- {503, 1, &rule52},- {504, 1, &rule21},- {505, 1, &rule22},- {506, 1, &rule21},- {507, 1, &rule22},- {508, 1, &rule21},- {509, 1, &rule22},- {510, 1, &rule21},- {511, 1, &rule22},- {512, 1, &rule21},- {513, 1, &rule22},- {514, 1, &rule21},- {515, 1, &rule22},- {516, 1, &rule21},- {517, 1, &rule22},- {518, 1, &rule21},- {519, 1, &rule22},- {520, 1, &rule21},- {521, 1, &rule22},- {522, 1, &rule21},- {523, 1, &rule22},- {524, 1, &rule21},- {525, 1, &rule22},- {526, 1, &rule21},- {527, 1, &rule22},- {528, 1, &rule21},- {529, 1, &rule22},- {530, 1, &rule21},- {531, 1, &rule22},- {532, 1, &rule21},- {533, 1, &rule22},- {534, 1, &rule21},- {535, 1, &rule22},- {536, 1, &rule21},- {537, 1, &rule22},- {538, 1, &rule21},- {539, 1, &rule22},- {540, 1, &rule21},- {541, 1, &rule22},- {542, 1, &rule21},- {543, 1, &rule22},- {544, 1, &rule53},- {545, 1, &rule14},- {546, 1, &rule21},- {547, 1, &rule22},- {548, 1, &rule21},- {549, 1, &rule22},- {550, 1, &rule21},- {551, 1, &rule22},- {552, 1, &rule21},- {553, 1, &rule22},- {554, 1, &rule21},- {555, 1, &rule22},- {556, 1, &rule21},- {557, 1, &rule22},- {558, 1, &rule21},- {559, 1, &rule22},- {560, 1, &rule21},- {561, 1, &rule22},- {562, 1, &rule21},- {563, 1, &rule22},- {564, 6, &rule14},- {570, 1, &rule54},- {571, 1, &rule21},- {572, 1, &rule22},- {573, 1, &rule55},- {574, 1, &rule56},- {575, 2, &rule57},- {577, 1, &rule21},- {578, 1, &rule22},- {579, 1, &rule58},- {580, 1, &rule59},- {581, 1, &rule60},- {582, 1, &rule21},- {583, 1, &rule22},- {584, 1, &rule21},- {585, 1, &rule22},- {586, 1, &rule21},- {587, 1, &rule22},- {588, 1, &rule21},- {589, 1, &rule22},- {590, 1, &rule21},- {591, 1, &rule22},- {592, 1, &rule61},- {593, 1, &rule62},- {594, 1, &rule63},- {595, 1, &rule64},- {596, 1, &rule65},- {597, 1, &rule14},- {598, 2, &rule66},- {600, 1, &rule14},- {601, 1, &rule67},- {602, 1, &rule14},- {603, 1, &rule68},- {604, 4, &rule14},- {608, 1, &rule66},- {609, 2, &rule14},- {611, 1, &rule69},- {612, 1, &rule14},- {613, 1, &rule70},- {614, 2, &rule14},- {616, 1, &rule71},- {617, 1, &rule72},- {618, 1, &rule14},- {619, 1, &rule73},- {620, 3, &rule14},- {623, 1, &rule72},- {624, 1, &rule14},- {625, 1, &rule74},- {626, 1, &rule75},- {627, 2, &rule14},- {629, 1, &rule76},- {630, 7, &rule14},- {637, 1, &rule77},- {638, 2, &rule14},- {640, 1, &rule78},- {641, 2, &rule14},- {643, 1, &rule78},- {644, 4, &rule14},- {648, 1, &rule78},- {649, 1, &rule79},- {650, 2, &rule80},- {652, 1, &rule81},- {653, 5, &rule14},- {658, 1, &rule82},- {659, 1, &rule14},- {660, 1, &rule45},- {661, 27, &rule14},- {688, 18, &rule83},- {706, 4, &rule10},- {710, 12, &rule83},- {722, 14, &rule10},- {736, 5, &rule83},- {741, 7, &rule10},- {748, 1, &rule83},- {749, 1, &rule10},- {750, 1, &rule83},- {751, 17, &rule10},- {768, 69, &rule84},- {837, 1, &rule85},- {838, 42, &rule84},- {880, 1, &rule21},- {881, 1, &rule22},- {882, 1, &rule21},- {883, 1, &rule22},- {884, 1, &rule83},- {885, 1, &rule10},- {886, 1, &rule21},- {887, 1, &rule22},- {890, 1, &rule83},- {891, 3, &rule40},- {894, 1, &rule2},- {900, 2, &rule10},- {902, 1, &rule86},- {903, 1, &rule2},- {904, 3, &rule87},- {908, 1, &rule88},- {910, 2, &rule89},- {912, 1, &rule14},- {913, 17, &rule9},- {931, 9, &rule9},- {940, 1, &rule90},- {941, 3, &rule91},- {944, 1, &rule14},- {945, 17, &rule12},- {962, 1, &rule92},- {963, 9, &rule12},- {972, 1, &rule93},- {973, 2, &rule94},- {975, 1, &rule95},- {976, 1, &rule96},- {977, 1, &rule97},- {978, 3, &rule98},- {981, 1, &rule99},- {982, 1, &rule100},- {983, 1, &rule101},- {984, 1, &rule21},- {985, 1, &rule22},- {986, 1, &rule21},- {987, 1, &rule22},- {988, 1, &rule21},- {989, 1, &rule22},- {990, 1, &rule21},- {991, 1, &rule22},- {992, 1, &rule21},- {993, 1, &rule22},- {994, 1, &rule21},- {995, 1, &rule22},- {996, 1, &rule21},- {997, 1, &rule22},- {998, 1, &rule21},- {999, 1, &rule22},- {1000, 1, &rule21},- {1001, 1, &rule22},- {1002, 1, &rule21},- {1003, 1, &rule22},- {1004, 1, &rule21},- {1005, 1, &rule22},- {1006, 1, &rule21},- {1007, 1, &rule22},- {1008, 1, &rule102},- {1009, 1, &rule103},- {1010, 1, &rule104},- {1011, 1, &rule14},- {1012, 1, &rule105},- {1013, 1, &rule106},- {1014, 1, &rule6},- {1015, 1, &rule21},- {1016, 1, &rule22},- {1017, 1, &rule107},- {1018, 1, &rule21},- {1019, 1, &rule22},- {1020, 1, &rule14},- {1021, 3, &rule53},- {1024, 16, &rule108},- {1040, 32, &rule9},- {1072, 32, &rule12},- {1104, 16, &rule103},- {1120, 1, &rule21},- {1121, 1, &rule22},- {1122, 1, &rule21},- {1123, 1, &rule22},- {1124, 1, &rule21},- {1125, 1, &rule22},- {1126, 1, &rule21},- {1127, 1, &rule22},- {1128, 1, &rule21},- {1129, 1, &rule22},- {1130, 1, &rule21},- {1131, 1, &rule22},- {1132, 1, &rule21},- {1133, 1, &rule22},- {1134, 1, &rule21},- {1135, 1, &rule22},- {1136, 1, &rule21},- {1137, 1, &rule22},- {1138, 1, &rule21},- {1139, 1, &rule22},- {1140, 1, &rule21},- {1141, 1, &rule22},- {1142, 1, &rule21},- {1143, 1, &rule22},- {1144, 1, &rule21},- {1145, 1, &rule22},- {1146, 1, &rule21},- {1147, 1, &rule22},- {1148, 1, &rule21},- {1149, 1, &rule22},- {1150, 1, &rule21},- {1151, 1, &rule22},- {1152, 1, &rule21},- {1153, 1, &rule22},- {1154, 1, &rule13},- {1155, 5, &rule84},- {1160, 2, &rule109},- {1162, 1, &rule21},- {1163, 1, &rule22},- {1164, 1, &rule21},- {1165, 1, &rule22},- {1166, 1, &rule21},- {1167, 1, &rule22},- {1168, 1, &rule21},- {1169, 1, &rule22},- {1170, 1, &rule21},- {1171, 1, &rule22},- {1172, 1, &rule21},- {1173, 1, &rule22},- {1174, 1, &rule21},- {1175, 1, &rule22},- {1176, 1, &rule21},- {1177, 1, &rule22},- {1178, 1, &rule21},- {1179, 1, &rule22},- {1180, 1, &rule21},- {1181, 1, &rule22},- {1182, 1, &rule21},- {1183, 1, &rule22},- {1184, 1, &rule21},- {1185, 1, &rule22},- {1186, 1, &rule21},- {1187, 1, &rule22},- {1188, 1, &rule21},- {1189, 1, &rule22},- {1190, 1, &rule21},- {1191, 1, &rule22},- {1192, 1, &rule21},- {1193, 1, &rule22},- {1194, 1, &rule21},- {1195, 1, &rule22},- {1196, 1, &rule21},- {1197, 1, &rule22},- {1198, 1, &rule21},- {1199, 1, &rule22},- {1200, 1, &rule21},- {1201, 1, &rule22},- {1202, 1, &rule21},- {1203, 1, &rule22},- {1204, 1, &rule21},- {1205, 1, &rule22},- {1206, 1, &rule21},- {1207, 1, &rule22},- {1208, 1, &rule21},- {1209, 1, &rule22},- {1210, 1, &rule21},- {1211, 1, &rule22},- {1212, 1, &rule21},- {1213, 1, &rule22},- {1214, 1, &rule21},- {1215, 1, &rule22},- {1216, 1, &rule110},- {1217, 1, &rule21},- {1218, 1, &rule22},- {1219, 1, &rule21},- {1220, 1, &rule22},- {1221, 1, &rule21},- {1222, 1, &rule22},- {1223, 1, &rule21},- {1224, 1, &rule22},- {1225, 1, &rule21},- {1226, 1, &rule22},- {1227, 1, &rule21},- {1228, 1, &rule22},- {1229, 1, &rule21},- {1230, 1, &rule22},- {1231, 1, &rule111},- {1232, 1, &rule21},- {1233, 1, &rule22},- {1234, 1, &rule21},- {1235, 1, &rule22},- {1236, 1, &rule21},- {1237, 1, &rule22},- {1238, 1, &rule21},- {1239, 1, &rule22},- {1240, 1, &rule21},- {1241, 1, &rule22},- {1242, 1, &rule21},- {1243, 1, &rule22},- {1244, 1, &rule21},- {1245, 1, &rule22},- {1246, 1, &rule21},- {1247, 1, &rule22},- {1248, 1, &rule21},- {1249, 1, &rule22},- {1250, 1, &rule21},- {1251, 1, &rule22},- {1252, 1, &rule21},- {1253, 1, &rule22},- {1254, 1, &rule21},- {1255, 1, &rule22},- {1256, 1, &rule21},- {1257, 1, &rule22},- {1258, 1, &rule21},- {1259, 1, &rule22},- {1260, 1, &rule21},- {1261, 1, &rule22},- {1262, 1, &rule21},- {1263, 1, &rule22},- {1264, 1, &rule21},- {1265, 1, &rule22},- {1266, 1, &rule21},- {1267, 1, &rule22},- {1268, 1, &rule21},- {1269, 1, &rule22},- {1270, 1, &rule21},- {1271, 1, &rule22},- {1272, 1, &rule21},- {1273, 1, &rule22},- {1274, 1, &rule21},- {1275, 1, &rule22},- {1276, 1, &rule21},- {1277, 1, &rule22},- {1278, 1, &rule21},- {1279, 1, &rule22},- {1280, 1, &rule21},- {1281, 1, &rule22},- {1282, 1, &rule21},- {1283, 1, &rule22},- {1284, 1, &rule21},- {1285, 1, &rule22},- {1286, 1, &rule21},- {1287, 1, &rule22},- {1288, 1, &rule21},- {1289, 1, &rule22},- {1290, 1, &rule21},- {1291, 1, &rule22},- {1292, 1, &rule21},- {1293, 1, &rule22},- {1294, 1, &rule21},- {1295, 1, &rule22},- {1296, 1, &rule21},- {1297, 1, &rule22},- {1298, 1, &rule21},- {1299, 1, &rule22},- {1300, 1, &rule21},- {1301, 1, &rule22},- {1302, 1, &rule21},- {1303, 1, &rule22},- {1304, 1, &rule21},- {1305, 1, &rule22},- {1306, 1, &rule21},- {1307, 1, &rule22},- {1308, 1, &rule21},- {1309, 1, &rule22},- {1310, 1, &rule21},- {1311, 1, &rule22},- {1312, 1, &rule21},- {1313, 1, &rule22},- {1314, 1, &rule21},- {1315, 1, &rule22},- {1316, 1, &rule21},- {1317, 1, &rule22},- {1318, 1, &rule21},- {1319, 1, &rule22},- {1329, 38, &rule112},- {1369, 1, &rule83},- {1370, 6, &rule2},- {1377, 38, &rule113},- {1415, 1, &rule14},- {1417, 1, &rule2},- {1418, 1, &rule7},- {1425, 45, &rule84},- {1470, 1, &rule7},- {1471, 1, &rule84},- {1472, 1, &rule2},- {1473, 2, &rule84},- {1475, 1, &rule2},- {1476, 2, &rule84},- {1478, 1, &rule2},- {1479, 1, &rule84},- {1488, 27, &rule45},- {1520, 3, &rule45},- {1523, 2, &rule2},- {1536, 4, &rule16},- {1542, 3, &rule6},- {1545, 2, &rule2},- {1547, 1, &rule3},- {1548, 2, &rule2},- {1550, 2, &rule13},- {1552, 11, &rule84},- {1563, 1, &rule2},- {1566, 2, &rule2},- {1568, 32, &rule45},- {1600, 1, &rule83},- {1601, 10, &rule45},- {1611, 21, &rule84},- {1632, 10, &rule8},- {1642, 4, &rule2},- {1646, 2, &rule45},- {1648, 1, &rule84},- {1649, 99, &rule45},- {1748, 1, &rule2},- {1749, 1, &rule45},- {1750, 7, &rule84},- {1757, 1, &rule16},- {1758, 1, &rule13},- {1759, 6, &rule84},- {1765, 2, &rule83},- {1767, 2, &rule84},- {1769, 1, &rule13},- {1770, 4, &rule84},- {1774, 2, &rule45},- {1776, 10, &rule8},- {1786, 3, &rule45},- {1789, 2, &rule13},- {1791, 1, &rule45},- {1792, 14, &rule2},- {1807, 1, &rule16},- {1808, 1, &rule45},- {1809, 1, &rule84},- {1810, 30, &rule45},- {1840, 27, &rule84},- {1869, 89, &rule45},- {1958, 11, &rule84},- {1969, 1, &rule45},- {1984, 10, &rule8},- {1994, 33, &rule45},- {2027, 9, &rule84},- {2036, 2, &rule83},- {2038, 1, &rule13},- {2039, 3, &rule2},- {2042, 1, &rule83},- {2048, 22, &rule45},- {2070, 4, &rule84},- {2074, 1, &rule83},- {2075, 9, &rule84},- {2084, 1, &rule83},- {2085, 3, &rule84},- {2088, 1, &rule83},- {2089, 5, &rule84},- {2096, 15, &rule2},- {2112, 25, &rule45},- {2137, 3, &rule84},- {2142, 1, &rule2},- {2304, 3, &rule84},- {2307, 1, &rule114},- {2308, 54, &rule45},- {2362, 1, &rule84},- {2363, 1, &rule114},- {2364, 1, &rule84},- {2365, 1, &rule45},- {2366, 3, &rule114},- {2369, 8, &rule84},- {2377, 4, &rule114},- {2381, 1, &rule84},- {2382, 2, &rule114},- {2384, 1, &rule45},- {2385, 7, &rule84},- {2392, 10, &rule45},- {2402, 2, &rule84},- {2404, 2, &rule2},- {2406, 10, &rule8},- {2416, 1, &rule2},- {2417, 1, &rule83},- {2418, 6, &rule45},- {2425, 7, &rule45},- {2433, 1, &rule84},- {2434, 2, &rule114},- {2437, 8, &rule45},- {2447, 2, &rule45},- {2451, 22, &rule45},- {2474, 7, &rule45},- {2482, 1, &rule45},- {2486, 4, &rule45},- {2492, 1, &rule84},- {2493, 1, &rule45},- {2494, 3, &rule114},- {2497, 4, &rule84},- {2503, 2, &rule114},- {2507, 2, &rule114},- {2509, 1, &rule84},- {2510, 1, &rule45},- {2519, 1, &rule114},- {2524, 2, &rule45},- {2527, 3, &rule45},- {2530, 2, &rule84},- {2534, 10, &rule8},- {2544, 2, &rule45},- {2546, 2, &rule3},- {2548, 6, &rule17},- {2554, 1, &rule13},- {2555, 1, &rule3},- {2561, 2, &rule84},- {2563, 1, &rule114},- {2565, 6, &rule45},- {2575, 2, &rule45},- {2579, 22, &rule45},- {2602, 7, &rule45},- {2610, 2, &rule45},- {2613, 2, &rule45},- {2616, 2, &rule45},- {2620, 1, &rule84},- {2622, 3, &rule114},- {2625, 2, &rule84},- {2631, 2, &rule84},- {2635, 3, &rule84},- {2641, 1, &rule84},- {2649, 4, &rule45},- {2654, 1, &rule45},- {2662, 10, &rule8},- {2672, 2, &rule84},- {2674, 3, &rule45},- {2677, 1, &rule84},- {2689, 2, &rule84},- {2691, 1, &rule114},- {2693, 9, &rule45},- {2703, 3, &rule45},- {2707, 22, &rule45},- {2730, 7, &rule45},- {2738, 2, &rule45},- {2741, 5, &rule45},- {2748, 1, &rule84},- {2749, 1, &rule45},- {2750, 3, &rule114},- {2753, 5, &rule84},- {2759, 2, &rule84},- {2761, 1, &rule114},- {2763, 2, &rule114},- {2765, 1, &rule84},- {2768, 1, &rule45},- {2784, 2, &rule45},- {2786, 2, &rule84},- {2790, 10, &rule8},- {2801, 1, &rule3},- {2817, 1, &rule84},- {2818, 2, &rule114},- {2821, 8, &rule45},- {2831, 2, &rule45},- {2835, 22, &rule45},- {2858, 7, &rule45},- {2866, 2, &rule45},- {2869, 5, &rule45},- {2876, 1, &rule84},- {2877, 1, &rule45},- {2878, 1, &rule114},- {2879, 1, &rule84},- {2880, 1, &rule114},- {2881, 4, &rule84},- {2887, 2, &rule114},- {2891, 2, &rule114},- {2893, 1, &rule84},- {2902, 1, &rule84},- {2903, 1, &rule114},- {2908, 2, &rule45},- {2911, 3, &rule45},- {2914, 2, &rule84},- {2918, 10, &rule8},- {2928, 1, &rule13},- {2929, 1, &rule45},- {2930, 6, &rule17},- {2946, 1, &rule84},- {2947, 1, &rule45},- {2949, 6, &rule45},- {2958, 3, &rule45},- {2962, 4, &rule45},- {2969, 2, &rule45},- {2972, 1, &rule45},- {2974, 2, &rule45},- {2979, 2, &rule45},- {2984, 3, &rule45},- {2990, 12, &rule45},- {3006, 2, &rule114},- {3008, 1, &rule84},- {3009, 2, &rule114},- {3014, 3, &rule114},- {3018, 3, &rule114},- {3021, 1, &rule84},- {3024, 1, &rule45},- {3031, 1, &rule114},- {3046, 10, &rule8},- {3056, 3, &rule17},- {3059, 6, &rule13},- {3065, 1, &rule3},- {3066, 1, &rule13},- {3073, 3, &rule114},- {3077, 8, &rule45},- {3086, 3, &rule45},- {3090, 23, &rule45},- {3114, 10, &rule45},- {3125, 5, &rule45},- {3133, 1, &rule45},- {3134, 3, &rule84},- {3137, 4, &rule114},- {3142, 3, &rule84},- {3146, 4, &rule84},- {3157, 2, &rule84},- {3160, 2, &rule45},- {3168, 2, &rule45},- {3170, 2, &rule84},- {3174, 10, &rule8},- {3192, 7, &rule17},- {3199, 1, &rule13},- {3202, 2, &rule114},- {3205, 8, &rule45},- {3214, 3, &rule45},- {3218, 23, &rule45},- {3242, 10, &rule45},- {3253, 5, &rule45},- {3260, 1, &rule84},- {3261, 1, &rule45},- {3262, 1, &rule114},- {3263, 1, &rule84},- {3264, 5, &rule114},- {3270, 1, &rule84},- {3271, 2, &rule114},- {3274, 2, &rule114},- {3276, 2, &rule84},- {3285, 2, &rule114},- {3294, 1, &rule45},- {3296, 2, &rule45},- {3298, 2, &rule84},- {3302, 10, &rule8},- {3313, 2, &rule45},- {3330, 2, &rule114},- {3333, 8, &rule45},- {3342, 3, &rule45},- {3346, 41, &rule45},- {3389, 1, &rule45},- {3390, 3, &rule114},- {3393, 4, &rule84},- {3398, 3, &rule114},- {3402, 3, &rule114},- {3405, 1, &rule84},- {3406, 1, &rule45},- {3415, 1, &rule114},- {3424, 2, &rule45},- {3426, 2, &rule84},- {3430, 10, &rule8},- {3440, 6, &rule17},- {3449, 1, &rule13},- {3450, 6, &rule45},- {3458, 2, &rule114},- {3461, 18, &rule45},- {3482, 24, &rule45},- {3507, 9, &rule45},- {3517, 1, &rule45},- {3520, 7, &rule45},- {3530, 1, &rule84},- {3535, 3, &rule114},- {3538, 3, &rule84},- {3542, 1, &rule84},- {3544, 8, &rule114},- {3570, 2, &rule114},- {3572, 1, &rule2},- {3585, 48, &rule45},- {3633, 1, &rule84},- {3634, 2, &rule45},- {3636, 7, &rule84},- {3647, 1, &rule3},- {3648, 6, &rule45},- {3654, 1, &rule83},- {3655, 8, &rule84},- {3663, 1, &rule2},- {3664, 10, &rule8},- {3674, 2, &rule2},- {3713, 2, &rule45},- {3716, 1, &rule45},- {3719, 2, &rule45},- {3722, 1, &rule45},- {3725, 1, &rule45},- {3732, 4, &rule45},- {3737, 7, &rule45},- {3745, 3, &rule45},- {3749, 1, &rule45},- {3751, 1, &rule45},- {3754, 2, &rule45},- {3757, 4, &rule45},- {3761, 1, &rule84},- {3762, 2, &rule45},- {3764, 6, &rule84},- {3771, 2, &rule84},- {3773, 1, &rule45},- {3776, 5, &rule45},- {3782, 1, &rule83},- {3784, 6, &rule84},- {3792, 10, &rule8},- {3804, 2, &rule45},- {3840, 1, &rule45},- {3841, 3, &rule13},- {3844, 15, &rule2},- {3859, 5, &rule13},- {3864, 2, &rule84},- {3866, 6, &rule13},- {3872, 10, &rule8},- {3882, 10, &rule17},- {3892, 1, &rule13},- {3893, 1, &rule84},- {3894, 1, &rule13},- {3895, 1, &rule84},- {3896, 1, &rule13},- {3897, 1, &rule84},- {3898, 1, &rule4},- {3899, 1, &rule5},- {3900, 1, &rule4},- {3901, 1, &rule5},- {3902, 2, &rule114},- {3904, 8, &rule45},- {3913, 36, &rule45},- {3953, 14, &rule84},- {3967, 1, &rule114},- {3968, 5, &rule84},- {3973, 1, &rule2},- {3974, 2, &rule84},- {3976, 5, &rule45},- {3981, 11, &rule84},- {3993, 36, &rule84},- {4030, 8, &rule13},- {4038, 1, &rule84},- {4039, 6, &rule13},- {4046, 2, &rule13},- {4048, 5, &rule2},- {4053, 4, &rule13},- {4057, 2, &rule2},- {4096, 43, &rule45},- {4139, 2, &rule114},- {4141, 4, &rule84},- {4145, 1, &rule114},- {4146, 6, &rule84},- {4152, 1, &rule114},- {4153, 2, &rule84},- {4155, 2, &rule114},- {4157, 2, &rule84},- {4159, 1, &rule45},- {4160, 10, &rule8},- {4170, 6, &rule2},- {4176, 6, &rule45},- {4182, 2, &rule114},- {4184, 2, &rule84},- {4186, 4, &rule45},- {4190, 3, &rule84},- {4193, 1, &rule45},- {4194, 3, &rule114},- {4197, 2, &rule45},- {4199, 7, &rule114},- {4206, 3, &rule45},- {4209, 4, &rule84},- {4213, 13, &rule45},- {4226, 1, &rule84},- {4227, 2, &rule114},- {4229, 2, &rule84},- {4231, 6, &rule114},- {4237, 1, &rule84},- {4238, 1, &rule45},- {4239, 1, &rule114},- {4240, 10, &rule8},- {4250, 3, &rule114},- {4253, 1, &rule84},- {4254, 2, &rule13},- {4256, 38, &rule115},- {4304, 43, &rule45},- {4347, 1, &rule2},- {4348, 1, &rule83},- {4352, 329, &rule45},- {4682, 4, &rule45},- {4688, 7, &rule45},- {4696, 1, &rule45},- {4698, 4, &rule45},- {4704, 41, &rule45},- {4746, 4, &rule45},- {4752, 33, &rule45},- {4786, 4, &rule45},- {4792, 7, &rule45},- {4800, 1, &rule45},- {4802, 4, &rule45},- {4808, 15, &rule45},- {4824, 57, &rule45},- {4882, 4, &rule45},- {4888, 67, &rule45},- {4957, 3, &rule84},- {4960, 1, &rule13},- {4961, 8, &rule2},- {4969, 20, &rule17},- {4992, 16, &rule45},- {5008, 10, &rule13},- {5024, 85, &rule45},- {5120, 1, &rule7},- {5121, 620, &rule45},- {5741, 2, &rule2},- {5743, 17, &rule45},- {5760, 1, &rule1},- {5761, 26, &rule45},- {5787, 1, &rule4},- {5788, 1, &rule5},- {5792, 75, &rule45},- {5867, 3, &rule2},- {5870, 3, &rule116},- {5888, 13, &rule45},- {5902, 4, &rule45},- {5906, 3, &rule84},- {5920, 18, &rule45},- {5938, 3, &rule84},- {5941, 2, &rule2},- {5952, 18, &rule45},- {5970, 2, &rule84},- {5984, 13, &rule45},- {5998, 3, &rule45},- {6002, 2, &rule84},- {6016, 52, &rule45},- {6068, 2, &rule16},- {6070, 1, &rule114},- {6071, 7, &rule84},- {6078, 8, &rule114},- {6086, 1, &rule84},- {6087, 2, &rule114},- {6089, 11, &rule84},- {6100, 3, &rule2},- {6103, 1, &rule83},- {6104, 3, &rule2},- {6107, 1, &rule3},- {6108, 1, &rule45},- {6109, 1, &rule84},- {6112, 10, &rule8},- {6128, 10, &rule17},- {6144, 6, &rule2},- {6150, 1, &rule7},- {6151, 4, &rule2},- {6155, 3, &rule84},- {6158, 1, &rule1},- {6160, 10, &rule8},- {6176, 35, &rule45},- {6211, 1, &rule83},- {6212, 52, &rule45},- {6272, 41, &rule45},- {6313, 1, &rule84},- {6314, 1, &rule45},- {6320, 70, &rule45},- {6400, 29, &rule45},- {6432, 3, &rule84},- {6435, 4, &rule114},- {6439, 2, &rule84},- {6441, 3, &rule114},- {6448, 2, &rule114},- {6450, 1, &rule84},- {6451, 6, &rule114},- {6457, 3, &rule84},- {6464, 1, &rule13},- {6468, 2, &rule2},- {6470, 10, &rule8},- {6480, 30, &rule45},- {6512, 5, &rule45},- {6528, 44, &rule45},- {6576, 17, &rule114},- {6593, 7, &rule45},- {6600, 2, &rule114},- {6608, 10, &rule8},- {6618, 1, &rule17},- {6622, 34, &rule13},- {6656, 23, &rule45},- {6679, 2, &rule84},- {6681, 3, &rule114},- {6686, 2, &rule2},- {6688, 53, &rule45},- {6741, 1, &rule114},- {6742, 1, &rule84},- {6743, 1, &rule114},- {6744, 7, &rule84},- {6752, 1, &rule84},- {6753, 1, &rule114},- {6754, 1, &rule84},- {6755, 2, &rule114},- {6757, 8, &rule84},- {6765, 6, &rule114},- {6771, 10, &rule84},- {6783, 1, &rule84},- {6784, 10, &rule8},- {6800, 10, &rule8},- {6816, 7, &rule2},- {6823, 1, &rule83},- {6824, 6, &rule2},- {6912, 4, &rule84},- {6916, 1, &rule114},- {6917, 47, &rule45},- {6964, 1, &rule84},- {6965, 1, &rule114},- {6966, 5, &rule84},- {6971, 1, &rule114},- {6972, 1, &rule84},- {6973, 5, &rule114},- {6978, 1, &rule84},- {6979, 2, &rule114},- {6981, 7, &rule45},- {6992, 10, &rule8},- {7002, 7, &rule2},- {7009, 10, &rule13},- {7019, 9, &rule84},- {7028, 9, &rule13},- {7040, 2, &rule84},- {7042, 1, &rule114},- {7043, 30, &rule45},- {7073, 1, &rule114},- {7074, 4, &rule84},- {7078, 2, &rule114},- {7080, 2, &rule84},- {7082, 1, &rule114},- {7086, 2, &rule45},- {7088, 10, &rule8},- {7104, 38, &rule45},- {7142, 1, &rule84},- {7143, 1, &rule114},- {7144, 2, &rule84},- {7146, 3, &rule114},- {7149, 1, &rule84},- {7150, 1, &rule114},- {7151, 3, &rule84},- {7154, 2, &rule114},- {7164, 4, &rule2},- {7168, 36, &rule45},- {7204, 8, &rule114},- {7212, 8, &rule84},- {7220, 2, &rule114},- {7222, 2, &rule84},- {7227, 5, &rule2},- {7232, 10, &rule8},- {7245, 3, &rule45},- {7248, 10, &rule8},- {7258, 30, &rule45},- {7288, 6, &rule83},- {7294, 2, &rule2},- {7376, 3, &rule84},- {7379, 1, &rule2},- {7380, 13, &rule84},- {7393, 1, &rule114},- {7394, 7, &rule84},- {7401, 4, &rule45},- {7405, 1, &rule84},- {7406, 4, &rule45},- {7410, 1, &rule114},- {7424, 44, &rule14},- {7468, 54, &rule83},- {7522, 22, &rule14},- {7544, 1, &rule83},- {7545, 1, &rule117},- {7546, 3, &rule14},- {7549, 1, &rule118},- {7550, 29, &rule14},- {7579, 37, &rule83},- {7616, 39, &rule84},- {7676, 4, &rule84},- {7680, 1, &rule21},- {7681, 1, &rule22},- {7682, 1, &rule21},- {7683, 1, &rule22},- {7684, 1, &rule21},- {7685, 1, &rule22},- {7686, 1, &rule21},- {7687, 1, &rule22},- {7688, 1, &rule21},- {7689, 1, &rule22},- {7690, 1, &rule21},- {7691, 1, &rule22},- {7692, 1, &rule21},- {7693, 1, &rule22},- {7694, 1, &rule21},- {7695, 1, &rule22},- {7696, 1, &rule21},- {7697, 1, &rule22},- {7698, 1, &rule21},- {7699, 1, &rule22},- {7700, 1, &rule21},- {7701, 1, &rule22},- {7702, 1, &rule21},- {7703, 1, &rule22},- {7704, 1, &rule21},- {7705, 1, &rule22},- {7706, 1, &rule21},- {7707, 1, &rule22},- {7708, 1, &rule21},- {7709, 1, &rule22},- {7710, 1, &rule21},- {7711, 1, &rule22},- {7712, 1, &rule21},- {7713, 1, &rule22},- {7714, 1, &rule21},- {7715, 1, &rule22},- {7716, 1, &rule21},- {7717, 1, &rule22},- {7718, 1, &rule21},- {7719, 1, &rule22},- {7720, 1, &rule21},- {7721, 1, &rule22},- {7722, 1, &rule21},- {7723, 1, &rule22},- {7724, 1, &rule21},- {7725, 1, &rule22},- {7726, 1, &rule21},- {7727, 1, &rule22},- {7728, 1, &rule21},- {7729, 1, &rule22},- {7730, 1, &rule21},- {7731, 1, &rule22},- {7732, 1, &rule21},- {7733, 1, &rule22},- {7734, 1, &rule21},- {7735, 1, &rule22},- {7736, 1, &rule21},- {7737, 1, &rule22},- {7738, 1, &rule21},- {7739, 1, &rule22},- {7740, 1, &rule21},- {7741, 1, &rule22},- {7742, 1, &rule21},- {7743, 1, &rule22},- {7744, 1, &rule21},- {7745, 1, &rule22},- {7746, 1, &rule21},- {7747, 1, &rule22},- {7748, 1, &rule21},- {7749, 1, &rule22},- {7750, 1, &rule21},- {7751, 1, &rule22},- {7752, 1, &rule21},- {7753, 1, &rule22},- {7754, 1, &rule21},- {7755, 1, &rule22},- {7756, 1, &rule21},- {7757, 1, &rule22},- {7758, 1, &rule21},- {7759, 1, &rule22},- {7760, 1, &rule21},- {7761, 1, &rule22},- {7762, 1, &rule21},- {7763, 1, &rule22},- {7764, 1, &rule21},- {7765, 1, &rule22},- {7766, 1, &rule21},- {7767, 1, &rule22},- {7768, 1, &rule21},- {7769, 1, &rule22},- {7770, 1, &rule21},- {7771, 1, &rule22},- {7772, 1, &rule21},- {7773, 1, &rule22},- {7774, 1, &rule21},- {7775, 1, &rule22},- {7776, 1, &rule21},- {7777, 1, &rule22},- {7778, 1, &rule21},- {7779, 1, &rule22},- {7780, 1, &rule21},- {7781, 1, &rule22},- {7782, 1, &rule21},- {7783, 1, &rule22},- {7784, 1, &rule21},- {7785, 1, &rule22},- {7786, 1, &rule21},- {7787, 1, &rule22},- {7788, 1, &rule21},- {7789, 1, &rule22},- {7790, 1, &rule21},- {7791, 1, &rule22},- {7792, 1, &rule21},- {7793, 1, &rule22},- {7794, 1, &rule21},- {7795, 1, &rule22},- {7796, 1, &rule21},- {7797, 1, &rule22},- {7798, 1, &rule21},- {7799, 1, &rule22},- {7800, 1, &rule21},- {7801, 1, &rule22},- {7802, 1, &rule21},- {7803, 1, &rule22},- {7804, 1, &rule21},- {7805, 1, &rule22},- {7806, 1, &rule21},- {7807, 1, &rule22},- {7808, 1, &rule21},- {7809, 1, &rule22},- {7810, 1, &rule21},- {7811, 1, &rule22},- {7812, 1, &rule21},- {7813, 1, &rule22},- {7814, 1, &rule21},- {7815, 1, &rule22},- {7816, 1, &rule21},- {7817, 1, &rule22},- {7818, 1, &rule21},- {7819, 1, &rule22},- {7820, 1, &rule21},- {7821, 1, &rule22},- {7822, 1, &rule21},- {7823, 1, &rule22},- {7824, 1, &rule21},- {7825, 1, &rule22},- {7826, 1, &rule21},- {7827, 1, &rule22},- {7828, 1, &rule21},- {7829, 1, &rule22},- {7830, 5, &rule14},- {7835, 1, &rule119},- {7836, 2, &rule14},- {7838, 1, &rule120},- {7839, 1, &rule14},- {7840, 1, &rule21},- {7841, 1, &rule22},- {7842, 1, &rule21},- {7843, 1, &rule22},- {7844, 1, &rule21},- {7845, 1, &rule22},- {7846, 1, &rule21},- {7847, 1, &rule22},- {7848, 1, &rule21},- {7849, 1, &rule22},- {7850, 1, &rule21},- {7851, 1, &rule22},- {7852, 1, &rule21},- {7853, 1, &rule22},- {7854, 1, &rule21},- {7855, 1, &rule22},- {7856, 1, &rule21},- {7857, 1, &rule22},- {7858, 1, &rule21},- {7859, 1, &rule22},- {7860, 1, &rule21},- {7861, 1, &rule22},- {7862, 1, &rule21},- {7863, 1, &rule22},- {7864, 1, &rule21},- {7865, 1, &rule22},- {7866, 1, &rule21},- {7867, 1, &rule22},- {7868, 1, &rule21},- {7869, 1, &rule22},- {7870, 1, &rule21},- {7871, 1, &rule22},- {7872, 1, &rule21},- {7873, 1, &rule22},- {7874, 1, &rule21},- {7875, 1, &rule22},- {7876, 1, &rule21},- {7877, 1, &rule22},- {7878, 1, &rule21},- {7879, 1, &rule22},- {7880, 1, &rule21},- {7881, 1, &rule22},- {7882, 1, &rule21},- {7883, 1, &rule22},- {7884, 1, &rule21},- {7885, 1, &rule22},- {7886, 1, &rule21},- {7887, 1, &rule22},- {7888, 1, &rule21},- {7889, 1, &rule22},- {7890, 1, &rule21},- {7891, 1, &rule22},- {7892, 1, &rule21},- {7893, 1, &rule22},- {7894, 1, &rule21},- {7895, 1, &rule22},- {7896, 1, &rule21},- {7897, 1, &rule22},- {7898, 1, &rule21},- {7899, 1, &rule22},- {7900, 1, &rule21},- {7901, 1, &rule22},- {7902, 1, &rule21},- {7903, 1, &rule22},- {7904, 1, &rule21},- {7905, 1, &rule22},- {7906, 1, &rule21},- {7907, 1, &rule22},- {7908, 1, &rule21},- {7909, 1, &rule22},- {7910, 1, &rule21},- {7911, 1, &rule22},- {7912, 1, &rule21},- {7913, 1, &rule22},- {7914, 1, &rule21},- {7915, 1, &rule22},- {7916, 1, &rule21},- {7917, 1, &rule22},- {7918, 1, &rule21},- {7919, 1, &rule22},- {7920, 1, &rule21},- {7921, 1, &rule22},- {7922, 1, &rule21},- {7923, 1, &rule22},- {7924, 1, &rule21},- {7925, 1, &rule22},- {7926, 1, &rule21},- {7927, 1, &rule22},- {7928, 1, &rule21},- {7929, 1, &rule22},- {7930, 1, &rule21},- {7931, 1, &rule22},- {7932, 1, &rule21},- {7933, 1, &rule22},- {7934, 1, &rule21},- {7935, 1, &rule22},- {7936, 8, &rule121},- {7944, 8, &rule122},- {7952, 6, &rule121},- {7960, 6, &rule122},- {7968, 8, &rule121},- {7976, 8, &rule122},- {7984, 8, &rule121},- {7992, 8, &rule122},- {8000, 6, &rule121},- {8008, 6, &rule122},- {8016, 1, &rule14},- {8017, 1, &rule121},- {8018, 1, &rule14},- {8019, 1, &rule121},- {8020, 1, &rule14},- {8021, 1, &rule121},- {8022, 1, &rule14},- {8023, 1, &rule121},- {8025, 1, &rule122},- {8027, 1, &rule122},- {8029, 1, &rule122},- {8031, 1, &rule122},- {8032, 8, &rule121},- {8040, 8, &rule122},- {8048, 2, &rule123},- {8050, 4, &rule124},- {8054, 2, &rule125},- {8056, 2, &rule126},- {8058, 2, &rule127},- {8060, 2, &rule128},- {8064, 8, &rule121},- {8072, 8, &rule129},- {8080, 8, &rule121},- {8088, 8, &rule129},- {8096, 8, &rule121},- {8104, 8, &rule129},- {8112, 2, &rule121},- {8114, 1, &rule14},- {8115, 1, &rule130},- {8116, 1, &rule14},- {8118, 2, &rule14},- {8120, 2, &rule122},- {8122, 2, &rule131},- {8124, 1, &rule132},- {8125, 1, &rule10},- {8126, 1, &rule133},- {8127, 3, &rule10},- {8130, 1, &rule14},- {8131, 1, &rule130},- {8132, 1, &rule14},- {8134, 2, &rule14},- {8136, 4, &rule134},- {8140, 1, &rule132},- {8141, 3, &rule10},- {8144, 2, &rule121},- {8146, 2, &rule14},- {8150, 2, &rule14},- {8152, 2, &rule122},- {8154, 2, &rule135},- {8157, 3, &rule10},- {8160, 2, &rule121},- {8162, 3, &rule14},- {8165, 1, &rule104},- {8166, 2, &rule14},- {8168, 2, &rule122},- {8170, 2, &rule136},- {8172, 1, &rule107},- {8173, 3, &rule10},- {8178, 1, &rule14},- {8179, 1, &rule130},- {8180, 1, &rule14},- {8182, 2, &rule14},- {8184, 2, &rule137},- {8186, 2, &rule138},- {8188, 1, &rule132},- {8189, 2, &rule10},- {8192, 11, &rule1},- {8203, 5, &rule16},- {8208, 6, &rule7},- {8214, 2, &rule2},- {8216, 1, &rule15},- {8217, 1, &rule19},- {8218, 1, &rule4},- {8219, 2, &rule15},- {8221, 1, &rule19},- {8222, 1, &rule4},- {8223, 1, &rule15},- {8224, 8, &rule2},- {8232, 1, &rule139},- {8233, 1, &rule140},- {8234, 5, &rule16},- {8239, 1, &rule1},- {8240, 9, &rule2},- {8249, 1, &rule15},- {8250, 1, &rule19},- {8251, 4, &rule2},- {8255, 2, &rule11},- {8257, 3, &rule2},- {8260, 1, &rule6},- {8261, 1, &rule4},- {8262, 1, &rule5},- {8263, 11, &rule2},- {8274, 1, &rule6},- {8275, 1, &rule2},- {8276, 1, &rule11},- {8277, 10, &rule2},- {8287, 1, &rule1},- {8288, 5, &rule16},- {8298, 6, &rule16},- {8304, 1, &rule17},- {8305, 1, &rule83},- {8308, 6, &rule17},- {8314, 3, &rule6},- {8317, 1, &rule4},- {8318, 1, &rule5},- {8319, 1, &rule83},- {8320, 10, &rule17},- {8330, 3, &rule6},- {8333, 1, &rule4},- {8334, 1, &rule5},- {8336, 13, &rule83},- {8352, 26, &rule3},- {8400, 13, &rule84},- {8413, 4, &rule109},- {8417, 1, &rule84},- {8418, 3, &rule109},- {8421, 12, &rule84},- {8448, 2, &rule13},- {8450, 1, &rule98},- {8451, 4, &rule13},- {8455, 1, &rule98},- {8456, 2, &rule13},- {8458, 1, &rule14},- {8459, 3, &rule98},- {8462, 2, &rule14},- {8464, 3, &rule98},- {8467, 1, &rule14},- {8468, 1, &rule13},- {8469, 1, &rule98},- {8470, 2, &rule13},- {8472, 1, &rule6},- {8473, 5, &rule98},- {8478, 6, &rule13},- {8484, 1, &rule98},- {8485, 1, &rule13},- {8486, 1, &rule141},- {8487, 1, &rule13},- {8488, 1, &rule98},- {8489, 1, &rule13},- {8490, 1, &rule142},- {8491, 1, &rule143},- {8492, 2, &rule98},- {8494, 1, &rule13},- {8495, 1, &rule14},- {8496, 2, &rule98},- {8498, 1, &rule144},- {8499, 1, &rule98},- {8500, 1, &rule14},- {8501, 4, &rule45},- {8505, 1, &rule14},- {8506, 2, &rule13},- {8508, 2, &rule14},- {8510, 2, &rule98},- {8512, 5, &rule6},- {8517, 1, &rule98},- {8518, 4, &rule14},- {8522, 1, &rule13},- {8523, 1, &rule6},- {8524, 2, &rule13},- {8526, 1, &rule145},- {8527, 1, &rule13},- {8528, 16, &rule17},- {8544, 16, &rule146},- {8560, 16, &rule147},- {8576, 3, &rule116},- {8579, 1, &rule21},- {8580, 1, &rule22},- {8581, 4, &rule116},- {8585, 1, &rule17},- {8592, 5, &rule6},- {8597, 5, &rule13},- {8602, 2, &rule6},- {8604, 4, &rule13},- {8608, 1, &rule6},- {8609, 2, &rule13},- {8611, 1, &rule6},- {8612, 2, &rule13},- {8614, 1, &rule6},- {8615, 7, &rule13},- {8622, 1, &rule6},- {8623, 31, &rule13},- {8654, 2, &rule6},- {8656, 2, &rule13},- {8658, 1, &rule6},- {8659, 1, &rule13},- {8660, 1, &rule6},- {8661, 31, &rule13},- {8692, 268, &rule6},- {8960, 8, &rule13},- {8968, 4, &rule6},- {8972, 20, &rule13},- {8992, 2, &rule6},- {8994, 7, &rule13},- {9001, 1, &rule4},- {9002, 1, &rule5},- {9003, 81, &rule13},- {9084, 1, &rule6},- {9085, 30, &rule13},- {9115, 25, &rule6},- {9140, 40, &rule13},- {9180, 6, &rule6},- {9186, 18, &rule13},- {9216, 39, &rule13},- {9280, 11, &rule13},- {9312, 60, &rule17},- {9372, 26, &rule13},- {9398, 26, &rule148},- {9424, 26, &rule149},- {9450, 22, &rule17},- {9472, 183, &rule13},- {9655, 1, &rule6},- {9656, 9, &rule13},- {9665, 1, &rule6},- {9666, 54, &rule13},- {9720, 8, &rule6},- {9728, 111, &rule13},- {9839, 1, &rule6},- {9840, 144, &rule13},- {9985, 103, &rule13},- {10088, 1, &rule4},- {10089, 1, &rule5},- {10090, 1, &rule4},- {10091, 1, &rule5},- {10092, 1, &rule4},- {10093, 1, &rule5},- {10094, 1, &rule4},- {10095, 1, &rule5},- {10096, 1, &rule4},- {10097, 1, &rule5},- {10098, 1, &rule4},- {10099, 1, &rule5},- {10100, 1, &rule4},- {10101, 1, &rule5},- {10102, 30, &rule17},- {10132, 44, &rule13},- {10176, 5, &rule6},- {10181, 1, &rule4},- {10182, 1, &rule5},- {10183, 4, &rule6},- {10188, 1, &rule6},- {10190, 24, &rule6},- {10214, 1, &rule4},- {10215, 1, &rule5},- {10216, 1, &rule4},- {10217, 1, &rule5},- {10218, 1, &rule4},- {10219, 1, &rule5},- {10220, 1, &rule4},- {10221, 1, &rule5},- {10222, 1, &rule4},- {10223, 1, &rule5},- {10224, 16, &rule6},- {10240, 256, &rule13},- {10496, 131, &rule6},- {10627, 1, &rule4},- {10628, 1, &rule5},- {10629, 1, &rule4},- {10630, 1, &rule5},- {10631, 1, &rule4},- {10632, 1, &rule5},- {10633, 1, &rule4},- {10634, 1, &rule5},- {10635, 1, &rule4},- {10636, 1, &rule5},- {10637, 1, &rule4},- {10638, 1, &rule5},- {10639, 1, &rule4},- {10640, 1, &rule5},- {10641, 1, &rule4},- {10642, 1, &rule5},- {10643, 1, &rule4},- {10644, 1, &rule5},- {10645, 1, &rule4},- {10646, 1, &rule5},- {10647, 1, &rule4},- {10648, 1, &rule5},- {10649, 63, &rule6},- {10712, 1, &rule4},- {10713, 1, &rule5},- {10714, 1, &rule4},- {10715, 1, &rule5},- {10716, 32, &rule6},- {10748, 1, &rule4},- {10749, 1, &rule5},- {10750, 258, &rule6},- {11008, 48, &rule13},- {11056, 21, &rule6},- {11077, 2, &rule13},- {11079, 6, &rule6},- {11088, 10, &rule13},- {11264, 47, &rule112},- {11312, 47, &rule113},- {11360, 1, &rule21},- {11361, 1, &rule22},- {11362, 1, &rule150},- {11363, 1, &rule151},- {11364, 1, &rule152},- {11365, 1, &rule153},- {11366, 1, &rule154},- {11367, 1, &rule21},- {11368, 1, &rule22},- {11369, 1, &rule21},- {11370, 1, &rule22},- {11371, 1, &rule21},- {11372, 1, &rule22},- {11373, 1, &rule155},- {11374, 1, &rule156},- {11375, 1, &rule157},- {11376, 1, &rule158},- {11377, 1, &rule14},- {11378, 1, &rule21},- {11379, 1, &rule22},- {11380, 1, &rule14},- {11381, 1, &rule21},- {11382, 1, &rule22},- {11383, 6, &rule14},- {11389, 1, &rule83},- {11390, 2, &rule159},- {11392, 1, &rule21},- {11393, 1, &rule22},- {11394, 1, &rule21},- {11395, 1, &rule22},- {11396, 1, &rule21},- {11397, 1, &rule22},- {11398, 1, &rule21},- {11399, 1, &rule22},- {11400, 1, &rule21},- {11401, 1, &rule22},- {11402, 1, &rule21},- {11403, 1, &rule22},- {11404, 1, &rule21},- {11405, 1, &rule22},- {11406, 1, &rule21},- {11407, 1, &rule22},- {11408, 1, &rule21},- {11409, 1, &rule22},- {11410, 1, &rule21},- {11411, 1, &rule22},- {11412, 1, &rule21},- {11413, 1, &rule22},- {11414, 1, &rule21},- {11415, 1, &rule22},- {11416, 1, &rule21},- {11417, 1, &rule22},- {11418, 1, &rule21},- {11419, 1, &rule22},- {11420, 1, &rule21},- {11421, 1, &rule22},- {11422, 1, &rule21},- {11423, 1, &rule22},- {11424, 1, &rule21},- {11425, 1, &rule22},- {11426, 1, &rule21},- {11427, 1, &rule22},- {11428, 1, &rule21},- {11429, 1, &rule22},- {11430, 1, &rule21},- {11431, 1, &rule22},- {11432, 1, &rule21},- {11433, 1, &rule22},- {11434, 1, &rule21},- {11435, 1, &rule22},- {11436, 1, &rule21},- {11437, 1, &rule22},- {11438, 1, &rule21},- {11439, 1, &rule22},- {11440, 1, &rule21},- {11441, 1, &rule22},- {11442, 1, &rule21},- {11443, 1, &rule22},- {11444, 1, &rule21},- {11445, 1, &rule22},- {11446, 1, &rule21},- {11447, 1, &rule22},- {11448, 1, &rule21},- {11449, 1, &rule22},- {11450, 1, &rule21},- {11451, 1, &rule22},- {11452, 1, &rule21},- {11453, 1, &rule22},- {11454, 1, &rule21},- {11455, 1, &rule22},- {11456, 1, &rule21},- {11457, 1, &rule22},- {11458, 1, &rule21},- {11459, 1, &rule22},- {11460, 1, &rule21},- {11461, 1, &rule22},- {11462, 1, &rule21},- {11463, 1, &rule22},- {11464, 1, &rule21},- {11465, 1, &rule22},- {11466, 1, &rule21},- {11467, 1, &rule22},- {11468, 1, &rule21},- {11469, 1, &rule22},- {11470, 1, &rule21},- {11471, 1, &rule22},- {11472, 1, &rule21},- {11473, 1, &rule22},- {11474, 1, &rule21},- {11475, 1, &rule22},- {11476, 1, &rule21},- {11477, 1, &rule22},- {11478, 1, &rule21},- {11479, 1, &rule22},- {11480, 1, &rule21},- {11481, 1, &rule22},- {11482, 1, &rule21},- {11483, 1, &rule22},- {11484, 1, &rule21},- {11485, 1, &rule22},- {11486, 1, &rule21},- {11487, 1, &rule22},- {11488, 1, &rule21},- {11489, 1, &rule22},- {11490, 1, &rule21},- {11491, 1, &rule22},- {11492, 1, &rule14},- {11493, 6, &rule13},- {11499, 1, &rule21},- {11500, 1, &rule22},- {11501, 1, &rule21},- {11502, 1, &rule22},- {11503, 3, &rule84},- {11513, 4, &rule2},- {11517, 1, &rule17},- {11518, 2, &rule2},- {11520, 38, &rule160},- {11568, 54, &rule45},- {11631, 1, &rule83},- {11632, 1, &rule2},- {11647, 1, &rule84},- {11648, 23, &rule45},- {11680, 7, &rule45},- {11688, 7, &rule45},- {11696, 7, &rule45},- {11704, 7, &rule45},- {11712, 7, &rule45},- {11720, 7, &rule45},- {11728, 7, &rule45},- {11736, 7, &rule45},- {11744, 32, &rule84},- {11776, 2, &rule2},- {11778, 1, &rule15},- {11779, 1, &rule19},- {11780, 1, &rule15},- {11781, 1, &rule19},- {11782, 3, &rule2},- {11785, 1, &rule15},- {11786, 1, &rule19},- {11787, 1, &rule2},- {11788, 1, &rule15},- {11789, 1, &rule19},- {11790, 9, &rule2},- {11799, 1, &rule7},- {11800, 2, &rule2},- {11802, 1, &rule7},- {11803, 1, &rule2},- {11804, 1, &rule15},- {11805, 1, &rule19},- {11806, 2, &rule2},- {11808, 1, &rule15},- {11809, 1, &rule19},- {11810, 1, &rule4},- {11811, 1, &rule5},- {11812, 1, &rule4},- {11813, 1, &rule5},- {11814, 1, &rule4},- {11815, 1, &rule5},- {11816, 1, &rule4},- {11817, 1, &rule5},- {11818, 5, &rule2},- {11823, 1, &rule83},- {11824, 2, &rule2},- {11904, 26, &rule13},- {11931, 89, &rule13},- {12032, 214, &rule13},- {12272, 12, &rule13},- {12288, 1, &rule1},- {12289, 3, &rule2},- {12292, 1, &rule13},- {12293, 1, &rule83},- {12294, 1, &rule45},- {12295, 1, &rule116},- {12296, 1, &rule4},- {12297, 1, &rule5},- {12298, 1, &rule4},- {12299, 1, &rule5},- {12300, 1, &rule4},- {12301, 1, &rule5},- {12302, 1, &rule4},- {12303, 1, &rule5},- {12304, 1, &rule4},- {12305, 1, &rule5},- {12306, 2, &rule13},- {12308, 1, &rule4},- {12309, 1, &rule5},- {12310, 1, &rule4},- {12311, 1, &rule5},- {12312, 1, &rule4},- {12313, 1, &rule5},- {12314, 1, &rule4},- {12315, 1, &rule5},- {12316, 1, &rule7},- {12317, 1, &rule4},- {12318, 2, &rule5},- {12320, 1, &rule13},- {12321, 9, &rule116},- {12330, 6, &rule84},- {12336, 1, &rule7},- {12337, 5, &rule83},- {12342, 2, &rule13},- {12344, 3, &rule116},- {12347, 1, &rule83},- {12348, 1, &rule45},- {12349, 1, &rule2},- {12350, 2, &rule13},- {12353, 86, &rule45},- {12441, 2, &rule84},- {12443, 2, &rule10},- {12445, 2, &rule83},- {12447, 1, &rule45},- {12448, 1, &rule7},- {12449, 90, &rule45},- {12539, 1, &rule2},- {12540, 3, &rule83},- {12543, 1, &rule45},- {12549, 41, &rule45},- {12593, 94, &rule45},- {12688, 2, &rule13},- {12690, 4, &rule17},- {12694, 10, &rule13},- {12704, 27, &rule45},- {12736, 36, &rule13},- {12784, 16, &rule45},- {12800, 31, &rule13},- {12832, 10, &rule17},- {12842, 39, &rule13},- {12881, 15, &rule17},- {12896, 32, &rule13},- {12928, 10, &rule17},- {12938, 39, &rule13},- {12977, 15, &rule17},- {12992, 63, &rule13},- {13056, 256, &rule13},- {13312, 6582, &rule45},- {19904, 64, &rule13},- {19968, 20940, &rule45},- {40960, 21, &rule45},- {40981, 1, &rule83},- {40982, 1143, &rule45},- {42128, 55, &rule13},- {42192, 40, &rule45},- {42232, 6, &rule83},- {42238, 2, &rule2},- {42240, 268, &rule45},- {42508, 1, &rule83},- {42509, 3, &rule2},- {42512, 16, &rule45},- {42528, 10, &rule8},- {42538, 2, &rule45},- {42560, 1, &rule21},- {42561, 1, &rule22},- {42562, 1, &rule21},- {42563, 1, &rule22},- {42564, 1, &rule21},- {42565, 1, &rule22},- {42566, 1, &rule21},- {42567, 1, &rule22},- {42568, 1, &rule21},- {42569, 1, &rule22},- {42570, 1, &rule21},- {42571, 1, &rule22},- {42572, 1, &rule21},- {42573, 1, &rule22},- {42574, 1, &rule21},- {42575, 1, &rule22},- {42576, 1, &rule21},- {42577, 1, &rule22},- {42578, 1, &rule21},- {42579, 1, &rule22},- {42580, 1, &rule21},- {42581, 1, &rule22},- {42582, 1, &rule21},- {42583, 1, &rule22},- {42584, 1, &rule21},- {42585, 1, &rule22},- {42586, 1, &rule21},- {42587, 1, &rule22},- {42588, 1, &rule21},- {42589, 1, &rule22},- {42590, 1, &rule21},- {42591, 1, &rule22},- {42592, 1, &rule21},- {42593, 1, &rule22},- {42594, 1, &rule21},- {42595, 1, &rule22},- {42596, 1, &rule21},- {42597, 1, &rule22},- {42598, 1, &rule21},- {42599, 1, &rule22},- {42600, 1, &rule21},- {42601, 1, &rule22},- {42602, 1, &rule21},- {42603, 1, &rule22},- {42604, 1, &rule21},- {42605, 1, &rule22},- {42606, 1, &rule45},- {42607, 1, &rule84},- {42608, 3, &rule109},- {42611, 1, &rule2},- {42620, 2, &rule84},- {42622, 1, &rule2},- {42623, 1, &rule83},- {42624, 1, &rule21},- {42625, 1, &rule22},- {42626, 1, &rule21},- {42627, 1, &rule22},- {42628, 1, &rule21},- {42629, 1, &rule22},- {42630, 1, &rule21},- {42631, 1, &rule22},- {42632, 1, &rule21},- {42633, 1, &rule22},- {42634, 1, &rule21},- {42635, 1, &rule22},- {42636, 1, &rule21},- {42637, 1, &rule22},- {42638, 1, &rule21},- {42639, 1, &rule22},- {42640, 1, &rule21},- {42641, 1, &rule22},- {42642, 1, &rule21},- {42643, 1, &rule22},- {42644, 1, &rule21},- {42645, 1, &rule22},- {42646, 1, &rule21},- {42647, 1, &rule22},- {42656, 70, &rule45},- {42726, 10, &rule116},- {42736, 2, &rule84},- {42738, 6, &rule2},- {42752, 23, &rule10},- {42775, 9, &rule83},- {42784, 2, &rule10},- {42786, 1, &rule21},- {42787, 1, &rule22},- {42788, 1, &rule21},- {42789, 1, &rule22},- {42790, 1, &rule21},- {42791, 1, &rule22},- {42792, 1, &rule21},- {42793, 1, &rule22},- {42794, 1, &rule21},- {42795, 1, &rule22},- {42796, 1, &rule21},- {42797, 1, &rule22},- {42798, 1, &rule21},- {42799, 1, &rule22},- {42800, 2, &rule14},- {42802, 1, &rule21},- {42803, 1, &rule22},- {42804, 1, &rule21},- {42805, 1, &rule22},- {42806, 1, &rule21},- {42807, 1, &rule22},- {42808, 1, &rule21},- {42809, 1, &rule22},- {42810, 1, &rule21},- {42811, 1, &rule22},- {42812, 1, &rule21},- {42813, 1, &rule22},- {42814, 1, &rule21},- {42815, 1, &rule22},- {42816, 1, &rule21},- {42817, 1, &rule22},- {42818, 1, &rule21},- {42819, 1, &rule22},- {42820, 1, &rule21},- {42821, 1, &rule22},- {42822, 1, &rule21},- {42823, 1, &rule22},- {42824, 1, &rule21},- {42825, 1, &rule22},- {42826, 1, &rule21},- {42827, 1, &rule22},- {42828, 1, &rule21},- {42829, 1, &rule22},- {42830, 1, &rule21},- {42831, 1, &rule22},- {42832, 1, &rule21},- {42833, 1, &rule22},- {42834, 1, &rule21},- {42835, 1, &rule22},- {42836, 1, &rule21},- {42837, 1, &rule22},- {42838, 1, &rule21},- {42839, 1, &rule22},- {42840, 1, &rule21},- {42841, 1, &rule22},- {42842, 1, &rule21},- {42843, 1, &rule22},- {42844, 1, &rule21},- {42845, 1, &rule22},- {42846, 1, &rule21},- {42847, 1, &rule22},- {42848, 1, &rule21},- {42849, 1, &rule22},- {42850, 1, &rule21},- {42851, 1, &rule22},- {42852, 1, &rule21},- {42853, 1, &rule22},- {42854, 1, &rule21},- {42855, 1, &rule22},- {42856, 1, &rule21},- {42857, 1, &rule22},- {42858, 1, &rule21},- {42859, 1, &rule22},- {42860, 1, &rule21},- {42861, 1, &rule22},- {42862, 1, &rule21},- {42863, 1, &rule22},- {42864, 1, &rule83},- {42865, 8, &rule14},- {42873, 1, &rule21},- {42874, 1, &rule22},- {42875, 1, &rule21},- {42876, 1, &rule22},- {42877, 1, &rule161},- {42878, 1, &rule21},- {42879, 1, &rule22},- {42880, 1, &rule21},- {42881, 1, &rule22},- {42882, 1, &rule21},- {42883, 1, &rule22},- {42884, 1, &rule21},- {42885, 1, &rule22},- {42886, 1, &rule21},- {42887, 1, &rule22},- {42888, 1, &rule83},- {42889, 2, &rule10},- {42891, 1, &rule21},- {42892, 1, &rule22},- {42893, 1, &rule162},- {42894, 1, &rule14},- {42896, 1, &rule21},- {42897, 1, &rule22},- {42912, 1, &rule21},- {42913, 1, &rule22},- {42914, 1, &rule21},- {42915, 1, &rule22},- {42916, 1, &rule21},- {42917, 1, &rule22},- {42918, 1, &rule21},- {42919, 1, &rule22},- {42920, 1, &rule21},- {42921, 1, &rule22},- {43002, 1, &rule14},- {43003, 7, &rule45},- {43010, 1, &rule84},- {43011, 3, &rule45},- {43014, 1, &rule84},- {43015, 4, &rule45},- {43019, 1, &rule84},- {43020, 23, &rule45},- {43043, 2, &rule114},- {43045, 2, &rule84},- {43047, 1, &rule114},- {43048, 4, &rule13},- {43056, 6, &rule17},- {43062, 2, &rule13},- {43064, 1, &rule3},- {43065, 1, &rule13},- {43072, 52, &rule45},- {43124, 4, &rule2},- {43136, 2, &rule114},- {43138, 50, &rule45},- {43188, 16, &rule114},- {43204, 1, &rule84},- {43214, 2, &rule2},- {43216, 10, &rule8},- {43232, 18, &rule84},- {43250, 6, &rule45},- {43256, 3, &rule2},- {43259, 1, &rule45},- {43264, 10, &rule8},- {43274, 28, &rule45},- {43302, 8, &rule84},- {43310, 2, &rule2},- {43312, 23, &rule45},- {43335, 11, &rule84},- {43346, 2, &rule114},- {43359, 1, &rule2},- {43360, 29, &rule45},- {43392, 3, &rule84},- {43395, 1, &rule114},- {43396, 47, &rule45},- {43443, 1, &rule84},- {43444, 2, &rule114},- {43446, 4, &rule84},- {43450, 2, &rule114},- {43452, 1, &rule84},- {43453, 4, &rule114},- {43457, 13, &rule2},- {43471, 1, &rule83},- {43472, 10, &rule8},- {43486, 2, &rule2},- {43520, 41, &rule45},- {43561, 6, &rule84},- {43567, 2, &rule114},- {43569, 2, &rule84},- {43571, 2, &rule114},- {43573, 2, &rule84},- {43584, 3, &rule45},- {43587, 1, &rule84},- {43588, 8, &rule45},- {43596, 1, &rule84},- {43597, 1, &rule114},- {43600, 10, &rule8},- {43612, 4, &rule2},- {43616, 16, &rule45},- {43632, 1, &rule83},- {43633, 6, &rule45},- {43639, 3, &rule13},- {43642, 1, &rule45},- {43643, 1, &rule114},- {43648, 48, &rule45},- {43696, 1, &rule84},- {43697, 1, &rule45},- {43698, 3, &rule84},- {43701, 2, &rule45},- {43703, 2, &rule84},- {43705, 5, &rule45},- {43710, 2, &rule84},- {43712, 1, &rule45},- {43713, 1, &rule84},- {43714, 1, &rule45},- {43739, 2, &rule45},- {43741, 1, &rule83},- {43742, 2, &rule2},- {43777, 6, &rule45},- {43785, 6, &rule45},- {43793, 6, &rule45},- {43808, 7, &rule45},- {43816, 7, &rule45},- {43968, 35, &rule45},- {44003, 2, &rule114},- {44005, 1, &rule84},- {44006, 2, &rule114},- {44008, 1, &rule84},- {44009, 2, &rule114},- {44011, 1, &rule2},- {44012, 1, &rule114},- {44013, 1, &rule84},- {44016, 10, &rule8},- {44032, 11172, &rule45},- {55216, 23, &rule45},- {55243, 49, &rule45},- {55296, 896, &rule163},- {56192, 128, &rule163},- {56320, 1024, &rule163},- {57344, 6400, &rule164},- {63744, 302, &rule45},- {64048, 62, &rule45},- {64112, 106, &rule45},- {64256, 7, &rule14},- {64275, 5, &rule14},- {64285, 1, &rule45},- {64286, 1, &rule84},- {64287, 10, &rule45},- {64297, 1, &rule6},- {64298, 13, &rule45},- {64312, 5, &rule45},- {64318, 1, &rule45},- {64320, 2, &rule45},- {64323, 2, &rule45},- {64326, 108, &rule45},- {64434, 16, &rule10},- {64467, 363, &rule45},- {64830, 1, &rule4},- {64831, 1, &rule5},- {64848, 64, &rule45},- {64914, 54, &rule45},- {65008, 12, &rule45},- {65020, 1, &rule3},- {65021, 1, &rule13},- {65024, 16, &rule84},- {65040, 7, &rule2},- {65047, 1, &rule4},- {65048, 1, &rule5},- {65049, 1, &rule2},- {65056, 7, &rule84},- {65072, 1, &rule2},- {65073, 2, &rule7},- {65075, 2, &rule11},- {65077, 1, &rule4},- {65078, 1, &rule5},- {65079, 1, &rule4},- {65080, 1, &rule5},- {65081, 1, &rule4},- {65082, 1, &rule5},- {65083, 1, &rule4},- {65084, 1, &rule5},- {65085, 1, &rule4},- {65086, 1, &rule5},- {65087, 1, &rule4},- {65088, 1, &rule5},- {65089, 1, &rule4},- {65090, 1, &rule5},- {65091, 1, &rule4},- {65092, 1, &rule5},- {65093, 2, &rule2},- {65095, 1, &rule4},- {65096, 1, &rule5},- {65097, 4, &rule2},- {65101, 3, &rule11},- {65104, 3, &rule2},- {65108, 4, &rule2},- {65112, 1, &rule7},- {65113, 1, &rule4},- {65114, 1, &rule5},- {65115, 1, &rule4},- {65116, 1, &rule5},- {65117, 1, &rule4},- {65118, 1, &rule5},- {65119, 3, &rule2},- {65122, 1, &rule6},- {65123, 1, &rule7},- {65124, 3, &rule6},- {65128, 1, &rule2},- {65129, 1, &rule3},- {65130, 2, &rule2},- {65136, 5, &rule45},- {65142, 135, &rule45},- {65279, 1, &rule16},- {65281, 3, &rule2},- {65284, 1, &rule3},- {65285, 3, &rule2},- {65288, 1, &rule4},- {65289, 1, &rule5},- {65290, 1, &rule2},- {65291, 1, &rule6},- {65292, 1, &rule2},- {65293, 1, &rule7},- {65294, 2, &rule2},- {65296, 10, &rule8},- {65306, 2, &rule2},- {65308, 3, &rule6},- {65311, 2, &rule2},- {65313, 26, &rule9},- {65339, 1, &rule4},- {65340, 1, &rule2},- {65341, 1, &rule5},- {65342, 1, &rule10},- {65343, 1, &rule11},- {65344, 1, &rule10},- {65345, 26, &rule12},- {65371, 1, &rule4},- {65372, 1, &rule6},- {65373, 1, &rule5},- {65374, 1, &rule6},- {65375, 1, &rule4},- {65376, 1, &rule5},- {65377, 1, &rule2},- {65378, 1, &rule4},- {65379, 1, &rule5},- {65380, 2, &rule2},- {65382, 10, &rule45},- {65392, 1, &rule83},- {65393, 45, &rule45},- {65438, 2, &rule83},- {65440, 31, &rule45},- {65474, 6, &rule45},- {65482, 6, &rule45},- {65490, 6, &rule45},- {65498, 3, &rule45},- {65504, 2, &rule3},- {65506, 1, &rule6},- {65507, 1, &rule10},- {65508, 1, &rule13},- {65509, 2, &rule3},- {65512, 1, &rule13},- {65513, 4, &rule6},- {65517, 2, &rule13},- {65529, 3, &rule16},- {65532, 2, &rule13},- {65536, 12, &rule45},- {65549, 26, &rule45},- {65576, 19, &rule45},- {65596, 2, &rule45},- {65599, 15, &rule45},- {65616, 14, &rule45},- {65664, 123, &rule45},- {65792, 2, &rule2},- {65794, 1, &rule13},- {65799, 45, &rule17},- {65847, 9, &rule13},- {65856, 53, &rule116},- {65909, 4, &rule17},- {65913, 17, &rule13},- {65930, 1, &rule17},- {65936, 12, &rule13},- {66000, 45, &rule13},- {66045, 1, &rule84},- {66176, 29, &rule45},- {66208, 49, &rule45},- {66304, 31, &rule45},- {66336, 4, &rule17},- {66352, 17, &rule45},- {66369, 1, &rule116},- {66370, 8, &rule45},- {66378, 1, &rule116},- {66432, 30, &rule45},- {66463, 1, &rule2},- {66464, 36, &rule45},- {66504, 8, &rule45},- {66512, 1, &rule2},- {66513, 5, &rule116},- {66560, 40, &rule165},- {66600, 40, &rule166},- {66640, 78, &rule45},- {66720, 10, &rule8},- {67584, 6, &rule45},- {67592, 1, &rule45},- {67594, 44, &rule45},- {67639, 2, &rule45},- {67644, 1, &rule45},- {67647, 23, &rule45},- {67671, 1, &rule2},- {67672, 8, &rule17},- {67840, 22, &rule45},- {67862, 6, &rule17},- {67871, 1, &rule2},- {67872, 26, &rule45},- {67903, 1, &rule2},- {68096, 1, &rule45},- {68097, 3, &rule84},- {68101, 2, &rule84},- {68108, 4, &rule84},- {68112, 4, &rule45},- {68117, 3, &rule45},- {68121, 27, &rule45},- {68152, 3, &rule84},- {68159, 1, &rule84},- {68160, 8, &rule17},- {68176, 9, &rule2},- {68192, 29, &rule45},- {68221, 2, &rule17},- {68223, 1, &rule2},- {68352, 54, &rule45},- {68409, 7, &rule2},- {68416, 22, &rule45},- {68440, 8, &rule17},- {68448, 19, &rule45},- {68472, 8, &rule17},- {68608, 73, &rule45},- {69216, 31, &rule17},- {69632, 1, &rule114},- {69633, 1, &rule84},- {69634, 1, &rule114},- {69635, 53, &rule45},- {69688, 15, &rule84},- {69703, 7, &rule2},- {69714, 20, &rule17},- {69734, 10, &rule8},- {69760, 2, &rule84},- {69762, 1, &rule114},- {69763, 45, &rule45},- {69808, 3, &rule114},- {69811, 4, &rule84},- {69815, 2, &rule114},- {69817, 2, &rule84},- {69819, 2, &rule2},- {69821, 1, &rule16},- {69822, 4, &rule2},- {73728, 879, &rule45},- {74752, 99, &rule116},- {74864, 4, &rule2},- {77824, 1071, &rule45},- {92160, 569, &rule45},- {110592, 2, &rule45},- {118784, 246, &rule13},- {119040, 39, &rule13},- {119081, 60, &rule13},- {119141, 2, &rule114},- {119143, 3, &rule84},- {119146, 3, &rule13},- {119149, 6, &rule114},- {119155, 8, &rule16},- {119163, 8, &rule84},- {119171, 2, &rule13},- {119173, 7, &rule84},- {119180, 30, &rule13},- {119210, 4, &rule84},- {119214, 48, &rule13},- {119296, 66, &rule13},- {119362, 3, &rule84},- {119365, 1, &rule13},- {119552, 87, &rule13},- {119648, 18, &rule17},- {119808, 26, &rule98},- {119834, 26, &rule14},- {119860, 26, &rule98},- {119886, 7, &rule14},- {119894, 18, &rule14},- {119912, 26, &rule98},- {119938, 26, &rule14},- {119964, 1, &rule98},- {119966, 2, &rule98},- {119970, 1, &rule98},- {119973, 2, &rule98},- {119977, 4, &rule98},- {119982, 8, &rule98},- {119990, 4, &rule14},- {119995, 1, &rule14},- {119997, 7, &rule14},- {120005, 11, &rule14},- {120016, 26, &rule98},- {120042, 26, &rule14},- {120068, 2, &rule98},- {120071, 4, &rule98},- {120077, 8, &rule98},- {120086, 7, &rule98},- {120094, 26, &rule14},- {120120, 2, &rule98},- {120123, 4, &rule98},- {120128, 5, &rule98},- {120134, 1, &rule98},- {120138, 7, &rule98},- {120146, 26, &rule14},- {120172, 26, &rule98},- {120198, 26, &rule14},- {120224, 26, &rule98},- {120250, 26, &rule14},- {120276, 26, &rule98},- {120302, 26, &rule14},- {120328, 26, &rule98},- {120354, 26, &rule14},- {120380, 26, &rule98},- {120406, 26, &rule14},- {120432, 26, &rule98},- {120458, 28, &rule14},- {120488, 25, &rule98},- {120513, 1, &rule6},- {120514, 25, &rule14},- {120539, 1, &rule6},- {120540, 6, &rule14},- {120546, 25, &rule98},- {120571, 1, &rule6},- {120572, 25, &rule14},- {120597, 1, &rule6},- {120598, 6, &rule14},- {120604, 25, &rule98},- {120629, 1, &rule6},- {120630, 25, &rule14},- {120655, 1, &rule6},- {120656, 6, &rule14},- {120662, 25, &rule98},- {120687, 1, &rule6},- {120688, 25, &rule14},- {120713, 1, &rule6},- {120714, 6, &rule14},- {120720, 25, &rule98},- {120745, 1, &rule6},- {120746, 25, &rule14},- {120771, 1, &rule6},- {120772, 6, &rule14},- {120778, 1, &rule98},- {120779, 1, &rule14},- {120782, 50, &rule8},- {126976, 44, &rule13},- {127024, 100, &rule13},- {127136, 15, &rule13},- {127153, 14, &rule13},- {127169, 15, &rule13},- {127185, 15, &rule13},- {127232, 11, &rule17},- {127248, 31, &rule13},- {127280, 58, &rule13},- {127344, 43, &rule13},- {127462, 29, &rule13},- {127504, 43, &rule13},- {127552, 9, &rule13},- {127568, 2, &rule13},- {127744, 33, &rule13},- {127792, 6, &rule13},- {127799, 70, &rule13},- {127872, 20, &rule13},- {127904, 37, &rule13},- {127942, 5, &rule13},- {127968, 17, &rule13},- {128000, 63, &rule13},- {128064, 1, &rule13},- {128066, 182, &rule13},- {128249, 4, &rule13},- {128256, 62, &rule13},- {128336, 24, &rule13},- {128507, 5, &rule13},- {128513, 16, &rule13},- {128530, 3, &rule13},- {128534, 1, &rule13},- {128536, 1, &rule13},- {128538, 1, &rule13},- {128540, 3, &rule13},- {128544, 6, &rule13},- {128552, 4, &rule13},- {128557, 1, &rule13},- {128560, 4, &rule13},- {128565, 12, &rule13},- {128581, 11, &rule13},- {128640, 70, &rule13},- {128768, 116, &rule13},- {131072, 42711, &rule45},- {173824, 4149, &rule45},- {177984, 222, &rule45},- {194560, 542, &rule45},- {917505, 1, &rule16},- {917536, 96, &rule16},- {917760, 240, &rule84},- {983040, 65534, &rule164},- {1048576, 65534, &rule164}-};-static const struct _charblock_ convchars[]={- {65, 26, &rule9},- {97, 26, &rule12},- {181, 1, &rule18},- {192, 23, &rule9},- {216, 7, &rule9},- {224, 23, &rule12},- {248, 7, &rule12},- {255, 1, &rule20},- {256, 1, &rule21},- {257, 1, &rule22},- {258, 1, &rule21},- {259, 1, &rule22},- {260, 1, &rule21},- {261, 1, &rule22},- {262, 1, &rule21},- {263, 1, &rule22},- {264, 1, &rule21},- {265, 1, &rule22},- {266, 1, &rule21},- {267, 1, &rule22},- {268, 1, &rule21},- {269, 1, &rule22},- {270, 1, &rule21},- {271, 1, &rule22},- {272, 1, &rule21},- {273, 1, &rule22},- {274, 1, &rule21},- {275, 1, &rule22},- {276, 1, &rule21},- {277, 1, &rule22},- {278, 1, &rule21},- {279, 1, &rule22},- {280, 1, &rule21},- {281, 1, &rule22},- {282, 1, &rule21},- {283, 1, &rule22},- {284, 1, &rule21},- {285, 1, &rule22},- {286, 1, &rule21},- {287, 1, &rule22},- {288, 1, &rule21},- {289, 1, &rule22},- {290, 1, &rule21},- {291, 1, &rule22},- {292, 1, &rule21},- {293, 1, &rule22},- {294, 1, &rule21},- {295, 1, &rule22},- {296, 1, &rule21},- {297, 1, &rule22},- {298, 1, &rule21},- {299, 1, &rule22},- {300, 1, &rule21},- {301, 1, &rule22},- {302, 1, &rule21},- {303, 1, &rule22},- {304, 1, &rule23},- {305, 1, &rule24},- {306, 1, &rule21},- {307, 1, &rule22},- {308, 1, &rule21},- {309, 1, &rule22},- {310, 1, &rule21},- {311, 1, &rule22},- {313, 1, &rule21},- {314, 1, &rule22},- {315, 1, &rule21},- {316, 1, &rule22},- {317, 1, &rule21},- {318, 1, &rule22},- {319, 1, &rule21},- {320, 1, &rule22},- {321, 1, &rule21},- {322, 1, &rule22},- {323, 1, &rule21},- {324, 1, &rule22},- {325, 1, &rule21},- {326, 1, &rule22},- {327, 1, &rule21},- {328, 1, &rule22},- {330, 1, &rule21},- {331, 1, &rule22},- {332, 1, &rule21},- {333, 1, &rule22},- {334, 1, &rule21},- {335, 1, &rule22},- {336, 1, &rule21},- {337, 1, &rule22},- {338, 1, &rule21},- {339, 1, &rule22},- {340, 1, &rule21},- {341, 1, &rule22},- {342, 1, &rule21},- {343, 1, &rule22},- {344, 1, &rule21},- {345, 1, &rule22},- {346, 1, &rule21},- {347, 1, &rule22},- {348, 1, &rule21},- {349, 1, &rule22},- {350, 1, &rule21},- {351, 1, &rule22},- {352, 1, &rule21},- {353, 1, &rule22},- {354, 1, &rule21},- {355, 1, &rule22},- {356, 1, &rule21},- {357, 1, &rule22},- {358, 1, &rule21},- {359, 1, &rule22},- {360, 1, &rule21},- {361, 1, &rule22},- {362, 1, &rule21},- {363, 1, &rule22},- {364, 1, &rule21},- {365, 1, &rule22},- {366, 1, &rule21},- {367, 1, &rule22},- {368, 1, &rule21},- {369, 1, &rule22},- {370, 1, &rule21},- {371, 1, &rule22},- {372, 1, &rule21},- {373, 1, &rule22},- {374, 1, &rule21},- {375, 1, &rule22},- {376, 1, &rule25},- {377, 1, &rule21},- {378, 1, &rule22},- {379, 1, &rule21},- {380, 1, &rule22},- {381, 1, &rule21},- {382, 1, &rule22},- {383, 1, &rule26},- {384, 1, &rule27},- {385, 1, &rule28},- {386, 1, &rule21},- {387, 1, &rule22},- {388, 1, &rule21},- {389, 1, &rule22},- {390, 1, &rule29},- {391, 1, &rule21},- {392, 1, &rule22},- {393, 2, &rule30},- {395, 1, &rule21},- {396, 1, &rule22},- {398, 1, &rule31},- {399, 1, &rule32},- {400, 1, &rule33},- {401, 1, &rule21},- {402, 1, &rule22},- {403, 1, &rule30},- {404, 1, &rule34},- {405, 1, &rule35},- {406, 1, &rule36},- {407, 1, &rule37},- {408, 1, &rule21},- {409, 1, &rule22},- {410, 1, &rule38},- {412, 1, &rule36},- {413, 1, &rule39},- {414, 1, &rule40},- {415, 1, &rule41},- {416, 1, &rule21},- {417, 1, &rule22},- {418, 1, &rule21},- {419, 1, &rule22},- {420, 1, &rule21},- {421, 1, &rule22},- {422, 1, &rule42},- {423, 1, &rule21},- {424, 1, &rule22},- {425, 1, &rule42},- {428, 1, &rule21},- {429, 1, &rule22},- {430, 1, &rule42},- {431, 1, &rule21},- {432, 1, &rule22},- {433, 2, &rule43},- {435, 1, &rule21},- {436, 1, &rule22},- {437, 1, &rule21},- {438, 1, &rule22},- {439, 1, &rule44},- {440, 1, &rule21},- {441, 1, &rule22},- {444, 1, &rule21},- {445, 1, &rule22},- {447, 1, &rule46},- {452, 1, &rule47},- {453, 1, &rule48},- {454, 1, &rule49},- {455, 1, &rule47},- {456, 1, &rule48},- {457, 1, &rule49},- {458, 1, &rule47},- {459, 1, &rule48},- {460, 1, &rule49},- {461, 1, &rule21},- {462, 1, &rule22},- {463, 1, &rule21},- {464, 1, &rule22},- {465, 1, &rule21},- {466, 1, &rule22},- {467, 1, &rule21},- {468, 1, &rule22},- {469, 1, &rule21},- {470, 1, &rule22},- {471, 1, &rule21},- {472, 1, &rule22},- {473, 1, &rule21},- {474, 1, &rule22},- {475, 1, &rule21},- {476, 1, &rule22},- {477, 1, &rule50},- {478, 1, &rule21},- {479, 1, &rule22},- {480, 1, &rule21},- {481, 1, &rule22},- {482, 1, &rule21},- {483, 1, &rule22},- {484, 1, &rule21},- {485, 1, &rule22},- {486, 1, &rule21},- {487, 1, &rule22},- {488, 1, &rule21},- {489, 1, &rule22},- {490, 1, &rule21},- {491, 1, &rule22},- {492, 1, &rule21},- {493, 1, &rule22},- {494, 1, &rule21},- {495, 1, &rule22},- {497, 1, &rule47},- {498, 1, &rule48},- {499, 1, &rule49},- {500, 1, &rule21},- {501, 1, &rule22},- {502, 1, &rule51},- {503, 1, &rule52},- {504, 1, &rule21},- {505, 1, &rule22},- {506, 1, &rule21},- {507, 1, &rule22},- {508, 1, &rule21},- {509, 1, &rule22},- {510, 1, &rule21},- {511, 1, &rule22},- {512, 1, &rule21},- {513, 1, &rule22},- {514, 1, &rule21},- {515, 1, &rule22},- {516, 1, &rule21},- {517, 1, &rule22},- {518, 1, &rule21},- {519, 1, &rule22},- {520, 1, &rule21},- {521, 1, &rule22},- {522, 1, &rule21},- {523, 1, &rule22},- {524, 1, &rule21},- {525, 1, &rule22},- {526, 1, &rule21},- {527, 1, &rule22},- {528, 1, &rule21},- {529, 1, &rule22},- {530, 1, &rule21},- {531, 1, &rule22},- {532, 1, &rule21},- {533, 1, &rule22},- {534, 1, &rule21},- {535, 1, &rule22},- {536, 1, &rule21},- {537, 1, &rule22},- {538, 1, &rule21},- {539, 1, &rule22},- {540, 1, &rule21},- {541, 1, &rule22},- {542, 1, &rule21},- {543, 1, &rule22},- {544, 1, &rule53},- {546, 1, &rule21},- {547, 1, &rule22},- {548, 1, &rule21},- {549, 1, &rule22},- {550, 1, &rule21},- {551, 1, &rule22},- {552, 1, &rule21},- {553, 1, &rule22},- {554, 1, &rule21},- {555, 1, &rule22},- {556, 1, &rule21},- {557, 1, &rule22},- {558, 1, &rule21},- {559, 1, &rule22},- {560, 1, &rule21},- {561, 1, &rule22},- {562, 1, &rule21},- {563, 1, &rule22},- {570, 1, &rule54},- {571, 1, &rule21},- {572, 1, &rule22},- {573, 1, &rule55},- {574, 1, &rule56},- {575, 2, &rule57},- {577, 1, &rule21},- {578, 1, &rule22},- {579, 1, &rule58},- {580, 1, &rule59},- {581, 1, &rule60},- {582, 1, &rule21},- {583, 1, &rule22},- {584, 1, &rule21},- {585, 1, &rule22},- {586, 1, &rule21},- {587, 1, &rule22},- {588, 1, &rule21},- {589, 1, &rule22},- {590, 1, &rule21},- {591, 1, &rule22},- {592, 1, &rule61},- {593, 1, &rule62},- {594, 1, &rule63},- {595, 1, &rule64},- {596, 1, &rule65},- {598, 2, &rule66},- {601, 1, &rule67},- {603, 1, &rule68},- {608, 1, &rule66},- {611, 1, &rule69},- {613, 1, &rule70},- {616, 1, &rule71},- {617, 1, &rule72},- {619, 1, &rule73},- {623, 1, &rule72},- {625, 1, &rule74},- {626, 1, &rule75},- {629, 1, &rule76},- {637, 1, &rule77},- {640, 1, &rule78},- {643, 1, &rule78},- {648, 1, &rule78},- {649, 1, &rule79},- {650, 2, &rule80},- {652, 1, &rule81},- {658, 1, &rule82},- {837, 1, &rule85},- {880, 1, &rule21},- {881, 1, &rule22},- {882, 1, &rule21},- {883, 1, &rule22},- {886, 1, &rule21},- {887, 1, &rule22},- {891, 3, &rule40},- {902, 1, &rule86},- {904, 3, &rule87},- {908, 1, &rule88},- {910, 2, &rule89},- {913, 17, &rule9},- {931, 9, &rule9},- {940, 1, &rule90},- {941, 3, &rule91},- {945, 17, &rule12},- {962, 1, &rule92},- {963, 9, &rule12},- {972, 1, &rule93},- {973, 2, &rule94},- {975, 1, &rule95},- {976, 1, &rule96},- {977, 1, &rule97},- {981, 1, &rule99},- {982, 1, &rule100},- {983, 1, &rule101},- {984, 1, &rule21},- {985, 1, &rule22},- {986, 1, &rule21},- {987, 1, &rule22},- {988, 1, &rule21},- {989, 1, &rule22},- {990, 1, &rule21},- {991, 1, &rule22},- {992, 1, &rule21},- {993, 1, &rule22},- {994, 1, &rule21},- {995, 1, &rule22},- {996, 1, &rule21},- {997, 1, &rule22},- {998, 1, &rule21},- {999, 1, &rule22},- {1000, 1, &rule21},- {1001, 1, &rule22},- {1002, 1, &rule21},- {1003, 1, &rule22},- {1004, 1, &rule21},- {1005, 1, &rule22},- {1006, 1, &rule21},- {1007, 1, &rule22},- {1008, 1, &rule102},- {1009, 1, &rule103},- {1010, 1, &rule104},- {1012, 1, &rule105},- {1013, 1, &rule106},- {1015, 1, &rule21},- {1016, 1, &rule22},- {1017, 1, &rule107},- {1018, 1, &rule21},- {1019, 1, &rule22},- {1021, 3, &rule53},- {1024, 16, &rule108},- {1040, 32, &rule9},- {1072, 32, &rule12},- {1104, 16, &rule103},- {1120, 1, &rule21},- {1121, 1, &rule22},- {1122, 1, &rule21},- {1123, 1, &rule22},- {1124, 1, &rule21},- {1125, 1, &rule22},- {1126, 1, &rule21},- {1127, 1, &rule22},- {1128, 1, &rule21},- {1129, 1, &rule22},- {1130, 1, &rule21},- {1131, 1, &rule22},- {1132, 1, &rule21},- {1133, 1, &rule22},- {1134, 1, &rule21},- {1135, 1, &rule22},- {1136, 1, &rule21},- {1137, 1, &rule22},- {1138, 1, &rule21},- {1139, 1, &rule22},- {1140, 1, &rule21},- {1141, 1, &rule22},- {1142, 1, &rule21},- {1143, 1, &rule22},- {1144, 1, &rule21},- {1145, 1, &rule22},- {1146, 1, &rule21},- {1147, 1, &rule22},- {1148, 1, &rule21},- {1149, 1, &rule22},- {1150, 1, &rule21},- {1151, 1, &rule22},- {1152, 1, &rule21},- {1153, 1, &rule22},- {1162, 1, &rule21},- {1163, 1, &rule22},- {1164, 1, &rule21},- {1165, 1, &rule22},- {1166, 1, &rule21},- {1167, 1, &rule22},- {1168, 1, &rule21},- {1169, 1, &rule22},- {1170, 1, &rule21},- {1171, 1, &rule22},- {1172, 1, &rule21},- {1173, 1, &rule22},- {1174, 1, &rule21},- {1175, 1, &rule22},- {1176, 1, &rule21},- {1177, 1, &rule22},- {1178, 1, &rule21},- {1179, 1, &rule22},- {1180, 1, &rule21},- {1181, 1, &rule22},- {1182, 1, &rule21},- {1183, 1, &rule22},- {1184, 1, &rule21},- {1185, 1, &rule22},- {1186, 1, &rule21},- {1187, 1, &rule22},- {1188, 1, &rule21},- {1189, 1, &rule22},- {1190, 1, &rule21},- {1191, 1, &rule22},- {1192, 1, &rule21},- {1193, 1, &rule22},- {1194, 1, &rule21},- {1195, 1, &rule22},- {1196, 1, &rule21},- {1197, 1, &rule22},- {1198, 1, &rule21},- {1199, 1, &rule22},- {1200, 1, &rule21},- {1201, 1, &rule22},- {1202, 1, &rule21},- {1203, 1, &rule22},- {1204, 1, &rule21},- {1205, 1, &rule22},- {1206, 1, &rule21},- {1207, 1, &rule22},- {1208, 1, &rule21},- {1209, 1, &rule22},- {1210, 1, &rule21},- {1211, 1, &rule22},- {1212, 1, &rule21},- {1213, 1, &rule22},- {1214, 1, &rule21},- {1215, 1, &rule22},- {1216, 1, &rule110},- {1217, 1, &rule21},- {1218, 1, &rule22},- {1219, 1, &rule21},- {1220, 1, &rule22},- {1221, 1, &rule21},- {1222, 1, &rule22},- {1223, 1, &rule21},- {1224, 1, &rule22},- {1225, 1, &rule21},- {1226, 1, &rule22},- {1227, 1, &rule21},- {1228, 1, &rule22},- {1229, 1, &rule21},- {1230, 1, &rule22},- {1231, 1, &rule111},- {1232, 1, &rule21},- {1233, 1, &rule22},- {1234, 1, &rule21},- {1235, 1, &rule22},- {1236, 1, &rule21},- {1237, 1, &rule22},- {1238, 1, &rule21},- {1239, 1, &rule22},- {1240, 1, &rule21},- {1241, 1, &rule22},- {1242, 1, &rule21},- {1243, 1, &rule22},- {1244, 1, &rule21},- {1245, 1, &rule22},- {1246, 1, &rule21},- {1247, 1, &rule22},- {1248, 1, &rule21},- {1249, 1, &rule22},- {1250, 1, &rule21},- {1251, 1, &rule22},- {1252, 1, &rule21},- {1253, 1, &rule22},- {1254, 1, &rule21},- {1255, 1, &rule22},- {1256, 1, &rule21},- {1257, 1, &rule22},- {1258, 1, &rule21},- {1259, 1, &rule22},- {1260, 1, &rule21},- {1261, 1, &rule22},- {1262, 1, &rule21},- {1263, 1, &rule22},- {1264, 1, &rule21},- {1265, 1, &rule22},- {1266, 1, &rule21},- {1267, 1, &rule22},- {1268, 1, &rule21},- {1269, 1, &rule22},- {1270, 1, &rule21},- {1271, 1, &rule22},- {1272, 1, &rule21},- {1273, 1, &rule22},- {1274, 1, &rule21},- {1275, 1, &rule22},- {1276, 1, &rule21},- {1277, 1, &rule22},- {1278, 1, &rule21},- {1279, 1, &rule22},- {1280, 1, &rule21},- {1281, 1, &rule22},- {1282, 1, &rule21},- {1283, 1, &rule22},- {1284, 1, &rule21},- {1285, 1, &rule22},- {1286, 1, &rule21},- {1287, 1, &rule22},- {1288, 1, &rule21},- {1289, 1, &rule22},- {1290, 1, &rule21},- {1291, 1, &rule22},- {1292, 1, &rule21},- {1293, 1, &rule22},- {1294, 1, &rule21},- {1295, 1, &rule22},- {1296, 1, &rule21},- {1297, 1, &rule22},- {1298, 1, &rule21},- {1299, 1, &rule22},- {1300, 1, &rule21},- {1301, 1, &rule22},- {1302, 1, &rule21},- {1303, 1, &rule22},- {1304, 1, &rule21},- {1305, 1, &rule22},- {1306, 1, &rule21},- {1307, 1, &rule22},- {1308, 1, &rule21},- {1309, 1, &rule22},- {1310, 1, &rule21},- {1311, 1, &rule22},- {1312, 1, &rule21},- {1313, 1, &rule22},- {1314, 1, &rule21},- {1315, 1, &rule22},- {1316, 1, &rule21},- {1317, 1, &rule22},- {1318, 1, &rule21},- {1319, 1, &rule22},- {1329, 38, &rule112},- {1377, 38, &rule113},- {4256, 38, &rule115},- {7545, 1, &rule117},- {7549, 1, &rule118},- {7680, 1, &rule21},- {7681, 1, &rule22},- {7682, 1, &rule21},- {7683, 1, &rule22},- {7684, 1, &rule21},- {7685, 1, &rule22},- {7686, 1, &rule21},- {7687, 1, &rule22},- {7688, 1, &rule21},- {7689, 1, &rule22},- {7690, 1, &rule21},- {7691, 1, &rule22},- {7692, 1, &rule21},- {7693, 1, &rule22},- {7694, 1, &rule21},- {7695, 1, &rule22},- {7696, 1, &rule21},- {7697, 1, &rule22},- {7698, 1, &rule21},- {7699, 1, &rule22},- {7700, 1, &rule21},- {7701, 1, &rule22},- {7702, 1, &rule21},- {7703, 1, &rule22},- {7704, 1, &rule21},- {7705, 1, &rule22},- {7706, 1, &rule21},- {7707, 1, &rule22},- {7708, 1, &rule21},- {7709, 1, &rule22},- {7710, 1, &rule21},- {7711, 1, &rule22},- {7712, 1, &rule21},- {7713, 1, &rule22},- {7714, 1, &rule21},- {7715, 1, &rule22},- {7716, 1, &rule21},- {7717, 1, &rule22},- {7718, 1, &rule21},- {7719, 1, &rule22},- {7720, 1, &rule21},- {7721, 1, &rule22},- {7722, 1, &rule21},- {7723, 1, &rule22},- {7724, 1, &rule21},- {7725, 1, &rule22},- {7726, 1, &rule21},- {7727, 1, &rule22},- {7728, 1, &rule21},- {7729, 1, &rule22},- {7730, 1, &rule21},- {7731, 1, &rule22},- {7732, 1, &rule21},- {7733, 1, &rule22},- {7734, 1, &rule21},- {7735, 1, &rule22},- {7736, 1, &rule21},- {7737, 1, &rule22},- {7738, 1, &rule21},- {7739, 1, &rule22},- {7740, 1, &rule21},- {7741, 1, &rule22},- {7742, 1, &rule21},- {7743, 1, &rule22},- {7744, 1, &rule21},- {7745, 1, &rule22},- {7746, 1, &rule21},- {7747, 1, &rule22},- {7748, 1, &rule21},- {7749, 1, &rule22},- {7750, 1, &rule21},- {7751, 1, &rule22},- {7752, 1, &rule21},- {7753, 1, &rule22},- {7754, 1, &rule21},- {7755, 1, &rule22},- {7756, 1, &rule21},- {7757, 1, &rule22},- {7758, 1, &rule21},- {7759, 1, &rule22},- {7760, 1, &rule21},- {7761, 1, &rule22},- {7762, 1, &rule21},- {7763, 1, &rule22},- {7764, 1, &rule21},- {7765, 1, &rule22},- {7766, 1, &rule21},- {7767, 1, &rule22},- {7768, 1, &rule21},- {7769, 1, &rule22},- {7770, 1, &rule21},- {7771, 1, &rule22},- {7772, 1, &rule21},- {7773, 1, &rule22},- {7774, 1, &rule21},- {7775, 1, &rule22},- {7776, 1, &rule21},- {7777, 1, &rule22},- {7778, 1, &rule21},- {7779, 1, &rule22},- {7780, 1, &rule21},- {7781, 1, &rule22},- {7782, 1, &rule21},- {7783, 1, &rule22},- {7784, 1, &rule21},- {7785, 1, &rule22},- {7786, 1, &rule21},- {7787, 1, &rule22},- {7788, 1, &rule21},- {7789, 1, &rule22},- {7790, 1, &rule21},- {7791, 1, &rule22},- {7792, 1, &rule21},- {7793, 1, &rule22},- {7794, 1, &rule21},- {7795, 1, &rule22},- {7796, 1, &rule21},- {7797, 1, &rule22},- {7798, 1, &rule21},- {7799, 1, &rule22},- {7800, 1, &rule21},- {7801, 1, &rule22},- {7802, 1, &rule21},- {7803, 1, &rule22},- {7804, 1, &rule21},- {7805, 1, &rule22},- {7806, 1, &rule21},- {7807, 1, &rule22},- {7808, 1, &rule21},- {7809, 1, &rule22},- {7810, 1, &rule21},- {7811, 1, &rule22},- {7812, 1, &rule21},- {7813, 1, &rule22},- {7814, 1, &rule21},- {7815, 1, &rule22},- {7816, 1, &rule21},- {7817, 1, &rule22},- {7818, 1, &rule21},- {7819, 1, &rule22},- {7820, 1, &rule21},- {7821, 1, &rule22},- {7822, 1, &rule21},- {7823, 1, &rule22},- {7824, 1, &rule21},- {7825, 1, &rule22},- {7826, 1, &rule21},- {7827, 1, &rule22},- {7828, 1, &rule21},- {7829, 1, &rule22},- {7835, 1, &rule119},- {7838, 1, &rule120},- {7840, 1, &rule21},- {7841, 1, &rule22},- {7842, 1, &rule21},- {7843, 1, &rule22},- {7844, 1, &rule21},- {7845, 1, &rule22},- {7846, 1, &rule21},- {7847, 1, &rule22},- {7848, 1, &rule21},- {7849, 1, &rule22},- {7850, 1, &rule21},- {7851, 1, &rule22},- {7852, 1, &rule21},- {7853, 1, &rule22},- {7854, 1, &rule21},- {7855, 1, &rule22},- {7856, 1, &rule21},- {7857, 1, &rule22},- {7858, 1, &rule21},- {7859, 1, &rule22},- {7860, 1, &rule21},- {7861, 1, &rule22},- {7862, 1, &rule21},- {7863, 1, &rule22},- {7864, 1, &rule21},- {7865, 1, &rule22},- {7866, 1, &rule21},- {7867, 1, &rule22},- {7868, 1, &rule21},- {7869, 1, &rule22},- {7870, 1, &rule21},- {7871, 1, &rule22},- {7872, 1, &rule21},- {7873, 1, &rule22},- {7874, 1, &rule21},- {7875, 1, &rule22},- {7876, 1, &rule21},- {7877, 1, &rule22},- {7878, 1, &rule21},- {7879, 1, &rule22},- {7880, 1, &rule21},- {7881, 1, &rule22},- {7882, 1, &rule21},- {7883, 1, &rule22},- {7884, 1, &rule21},- {7885, 1, &rule22},- {7886, 1, &rule21},- {7887, 1, &rule22},- {7888, 1, &rule21},- {7889, 1, &rule22},- {7890, 1, &rule21},- {7891, 1, &rule22},- {7892, 1, &rule21},- {7893, 1, &rule22},- {7894, 1, &rule21},- {7895, 1, &rule22},- {7896, 1, &rule21},- {7897, 1, &rule22},- {7898, 1, &rule21},- {7899, 1, &rule22},- {7900, 1, &rule21},- {7901, 1, &rule22},- {7902, 1, &rule21},- {7903, 1, &rule22},- {7904, 1, &rule21},- {7905, 1, &rule22},- {7906, 1, &rule21},- {7907, 1, &rule22},- {7908, 1, &rule21},- {7909, 1, &rule22},- {7910, 1, &rule21},- {7911, 1, &rule22},- {7912, 1, &rule21},- {7913, 1, &rule22},- {7914, 1, &rule21},- {7915, 1, &rule22},- {7916, 1, &rule21},- {7917, 1, &rule22},- {7918, 1, &rule21},- {7919, 1, &rule22},- {7920, 1, &rule21},- {7921, 1, &rule22},- {7922, 1, &rule21},- {7923, 1, &rule22},- {7924, 1, &rule21},- {7925, 1, &rule22},- {7926, 1, &rule21},- {7927, 1, &rule22},- {7928, 1, &rule21},- {7929, 1, &rule22},- {7930, 1, &rule21},- {7931, 1, &rule22},- {7932, 1, &rule21},- {7933, 1, &rule22},- {7934, 1, &rule21},- {7935, 1, &rule22},- {7936, 8, &rule121},- {7944, 8, &rule122},- {7952, 6, &rule121},- {7960, 6, &rule122},- {7968, 8, &rule121},- {7976, 8, &rule122},- {7984, 8, &rule121},- {7992, 8, &rule122},- {8000, 6, &rule121},- {8008, 6, &rule122},- {8017, 1, &rule121},- {8019, 1, &rule121},- {8021, 1, &rule121},- {8023, 1, &rule121},- {8025, 1, &rule122},- {8027, 1, &rule122},- {8029, 1, &rule122},- {8031, 1, &rule122},- {8032, 8, &rule121},- {8040, 8, &rule122},- {8048, 2, &rule123},- {8050, 4, &rule124},- {8054, 2, &rule125},- {8056, 2, &rule126},- {8058, 2, &rule127},- {8060, 2, &rule128},- {8064, 8, &rule121},- {8072, 8, &rule129},- {8080, 8, &rule121},- {8088, 8, &rule129},- {8096, 8, &rule121},- {8104, 8, &rule129},- {8112, 2, &rule121},- {8115, 1, &rule130},- {8120, 2, &rule122},- {8122, 2, &rule131},- {8124, 1, &rule132},- {8126, 1, &rule133},- {8131, 1, &rule130},- {8136, 4, &rule134},- {8140, 1, &rule132},- {8144, 2, &rule121},- {8152, 2, &rule122},- {8154, 2, &rule135},- {8160, 2, &rule121},- {8165, 1, &rule104},- {8168, 2, &rule122},- {8170, 2, &rule136},- {8172, 1, &rule107},- {8179, 1, &rule130},- {8184, 2, &rule137},- {8186, 2, &rule138},- {8188, 1, &rule132},- {8486, 1, &rule141},- {8490, 1, &rule142},- {8491, 1, &rule143},- {8498, 1, &rule144},- {8526, 1, &rule145},- {8544, 16, &rule146},- {8560, 16, &rule147},- {8579, 1, &rule21},- {8580, 1, &rule22},- {9398, 26, &rule148},- {9424, 26, &rule149},- {11264, 47, &rule112},- {11312, 47, &rule113},- {11360, 1, &rule21},- {11361, 1, &rule22},- {11362, 1, &rule150},- {11363, 1, &rule151},- {11364, 1, &rule152},- {11365, 1, &rule153},- {11366, 1, &rule154},- {11367, 1, &rule21},- {11368, 1, &rule22},- {11369, 1, &rule21},- {11370, 1, &rule22},- {11371, 1, &rule21},- {11372, 1, &rule22},- {11373, 1, &rule155},- {11374, 1, &rule156},- {11375, 1, &rule157},- {11376, 1, &rule158},- {11378, 1, &rule21},- {11379, 1, &rule22},- {11381, 1, &rule21},- {11382, 1, &rule22},- {11390, 2, &rule159},- {11392, 1, &rule21},- {11393, 1, &rule22},- {11394, 1, &rule21},- {11395, 1, &rule22},- {11396, 1, &rule21},- {11397, 1, &rule22},- {11398, 1, &rule21},- {11399, 1, &rule22},- {11400, 1, &rule21},- {11401, 1, &rule22},- {11402, 1, &rule21},- {11403, 1, &rule22},- {11404, 1, &rule21},- {11405, 1, &rule22},- {11406, 1, &rule21},- {11407, 1, &rule22},- {11408, 1, &rule21},- {11409, 1, &rule22},- {11410, 1, &rule21},- {11411, 1, &rule22},- {11412, 1, &rule21},- {11413, 1, &rule22},- {11414, 1, &rule21},- {11415, 1, &rule22},- {11416, 1, &rule21},- {11417, 1, &rule22},- {11418, 1, &rule21},- {11419, 1, &rule22},- {11420, 1, &rule21},- {11421, 1, &rule22},- {11422, 1, &rule21},- {11423, 1, &rule22},- {11424, 1, &rule21},- {11425, 1, &rule22},- {11426, 1, &rule21},- {11427, 1, &rule22},- {11428, 1, &rule21},- {11429, 1, &rule22},- {11430, 1, &rule21},- {11431, 1, &rule22},- {11432, 1, &rule21},- {11433, 1, &rule22},- {11434, 1, &rule21},- {11435, 1, &rule22},- {11436, 1, &rule21},- {11437, 1, &rule22},- {11438, 1, &rule21},- {11439, 1, &rule22},- {11440, 1, &rule21},- {11441, 1, &rule22},- {11442, 1, &rule21},- {11443, 1, &rule22},- {11444, 1, &rule21},- {11445, 1, &rule22},- {11446, 1, &rule21},- {11447, 1, &rule22},- {11448, 1, &rule21},- {11449, 1, &rule22},- {11450, 1, &rule21},- {11451, 1, &rule22},- {11452, 1, &rule21},- {11453, 1, &rule22},- {11454, 1, &rule21},- {11455, 1, &rule22},- {11456, 1, &rule21},- {11457, 1, &rule22},- {11458, 1, &rule21},- {11459, 1, &rule22},- {11460, 1, &rule21},- {11461, 1, &rule22},- {11462, 1, &rule21},- {11463, 1, &rule22},- {11464, 1, &rule21},- {11465, 1, &rule22},- {11466, 1, &rule21},- {11467, 1, &rule22},- {11468, 1, &rule21},- {11469, 1, &rule22},- {11470, 1, &rule21},- {11471, 1, &rule22},- {11472, 1, &rule21},- {11473, 1, &rule22},- {11474, 1, &rule21},- {11475, 1, &rule22},- {11476, 1, &rule21},- {11477, 1, &rule22},- {11478, 1, &rule21},- {11479, 1, &rule22},- {11480, 1, &rule21},- {11481, 1, &rule22},- {11482, 1, &rule21},- {11483, 1, &rule22},- {11484, 1, &rule21},- {11485, 1, &rule22},- {11486, 1, &rule21},- {11487, 1, &rule22},- {11488, 1, &rule21},- {11489, 1, &rule22},- {11490, 1, &rule21},- {11491, 1, &rule22},- {11499, 1, &rule21},- {11500, 1, &rule22},- {11501, 1, &rule21},- {11502, 1, &rule22},- {11520, 38, &rule160},- {42560, 1, &rule21},- {42561, 1, &rule22},- {42562, 1, &rule21},- {42563, 1, &rule22},- {42564, 1, &rule21},- {42565, 1, &rule22},- {42566, 1, &rule21},- {42567, 1, &rule22},- {42568, 1, &rule21},- {42569, 1, &rule22},- {42570, 1, &rule21},- {42571, 1, &rule22},- {42572, 1, &rule21},- {42573, 1, &rule22},- {42574, 1, &rule21},- {42575, 1, &rule22},- {42576, 1, &rule21},- {42577, 1, &rule22},- {42578, 1, &rule21},- {42579, 1, &rule22},- {42580, 1, &rule21},- {42581, 1, &rule22},- {42582, 1, &rule21},- {42583, 1, &rule22},- {42584, 1, &rule21},- {42585, 1, &rule22},- {42586, 1, &rule21},- {42587, 1, &rule22},- {42588, 1, &rule21},- {42589, 1, &rule22},- {42590, 1, &rule21},- {42591, 1, &rule22},- {42592, 1, &rule21},- {42593, 1, &rule22},- {42594, 1, &rule21},- {42595, 1, &rule22},- {42596, 1, &rule21},- {42597, 1, &rule22},- {42598, 1, &rule21},- {42599, 1, &rule22},- {42600, 1, &rule21},- {42601, 1, &rule22},- {42602, 1, &rule21},- {42603, 1, &rule22},- {42604, 1, &rule21},- {42605, 1, &rule22},- {42624, 1, &rule21},- {42625, 1, &rule22},- {42626, 1, &rule21},- {42627, 1, &rule22},- {42628, 1, &rule21},- {42629, 1, &rule22},- {42630, 1, &rule21},- {42631, 1, &rule22},- {42632, 1, &rule21},- {42633, 1, &rule22},- {42634, 1, &rule21},- {42635, 1, &rule22},- {42636, 1, &rule21},- {42637, 1, &rule22},- {42638, 1, &rule21},- {42639, 1, &rule22},- {42640, 1, &rule21},- {42641, 1, &rule22},- {42642, 1, &rule21},- {42643, 1, &rule22},- {42644, 1, &rule21},- {42645, 1, &rule22},- {42646, 1, &rule21},- {42647, 1, &rule22},- {42786, 1, &rule21},- {42787, 1, &rule22},- {42788, 1, &rule21},- {42789, 1, &rule22},- {42790, 1, &rule21},- {42791, 1, &rule22},- {42792, 1, &rule21},- {42793, 1, &rule22},- {42794, 1, &rule21},- {42795, 1, &rule22},- {42796, 1, &rule21},- {42797, 1, &rule22},- {42798, 1, &rule21},- {42799, 1, &rule22},- {42802, 1, &rule21},- {42803, 1, &rule22},- {42804, 1, &rule21},- {42805, 1, &rule22},- {42806, 1, &rule21},- {42807, 1, &rule22},- {42808, 1, &rule21},- {42809, 1, &rule22},- {42810, 1, &rule21},- {42811, 1, &rule22},- {42812, 1, &rule21},- {42813, 1, &rule22},- {42814, 1, &rule21},- {42815, 1, &rule22},- {42816, 1, &rule21},- {42817, 1, &rule22},- {42818, 1, &rule21},- {42819, 1, &rule22},- {42820, 1, &rule21},- {42821, 1, &rule22},- {42822, 1, &rule21},- {42823, 1, &rule22},- {42824, 1, &rule21},- {42825, 1, &rule22},- {42826, 1, &rule21},- {42827, 1, &rule22},- {42828, 1, &rule21},- {42829, 1, &rule22},- {42830, 1, &rule21},- {42831, 1, &rule22},- {42832, 1, &rule21},- {42833, 1, &rule22},- {42834, 1, &rule21},- {42835, 1, &rule22},- {42836, 1, &rule21},- {42837, 1, &rule22},- {42838, 1, &rule21},- {42839, 1, &rule22},- {42840, 1, &rule21},- {42841, 1, &rule22},- {42842, 1, &rule21},- {42843, 1, &rule22},- {42844, 1, &rule21},- {42845, 1, &rule22},- {42846, 1, &rule21},- {42847, 1, &rule22},- {42848, 1, &rule21},- {42849, 1, &rule22},- {42850, 1, &rule21},- {42851, 1, &rule22},- {42852, 1, &rule21},- {42853, 1, &rule22},- {42854, 1, &rule21},- {42855, 1, &rule22},- {42856, 1, &rule21},- {42857, 1, &rule22},- {42858, 1, &rule21},- {42859, 1, &rule22},- {42860, 1, &rule21},- {42861, 1, &rule22},- {42862, 1, &rule21},- {42863, 1, &rule22},- {42873, 1, &rule21},- {42874, 1, &rule22},- {42875, 1, &rule21},- {42876, 1, &rule22},- {42877, 1, &rule161},- {42878, 1, &rule21},- {42879, 1, &rule22},- {42880, 1, &rule21},- {42881, 1, &rule22},- {42882, 1, &rule21},- {42883, 1, &rule22},- {42884, 1, &rule21},- {42885, 1, &rule22},- {42886, 1, &rule21},- {42887, 1, &rule22},- {42891, 1, &rule21},- {42892, 1, &rule22},- {42893, 1, &rule162},- {42896, 1, &rule21},- {42897, 1, &rule22},- {42912, 1, &rule21},- {42913, 1, &rule22},- {42914, 1, &rule21},- {42915, 1, &rule22},- {42916, 1, &rule21},- {42917, 1, &rule22},- {42918, 1, &rule21},- {42919, 1, &rule22},- {42920, 1, &rule21},- {42921, 1, &rule22},- {65313, 26, &rule9},- {65345, 26, &rule12},- {66560, 40, &rule165},- {66600, 40, &rule166}-};-static const struct _charblock_ spacechars[]={- {32, 1, &rule1},- {160, 1, &rule1},- {5760, 1, &rule1},- {6158, 1, &rule1},- {8192, 11, &rule1},- {8239, 1, &rule1},- {8287, 1, &rule1},- {12288, 1, &rule1}-};--/*- Obtain the reference to character rule by doing- binary search over the specified array of blocks.- To make checkattr shorter, the address of- nullrule is returned if the search fails:- this rule defines no category and no conversion- distances. The compare function returns 0 when- key->start is within the block. Otherwise- result of comparison of key->start and start of the- current block is returned as usual.-*/--static const struct _convrule_ nullrule={0,NUMCAT_CN,0,0,0,0};--int blkcmp(const void *vk,const void *vb)-{- const struct _charblock_ *key,*cur;- key=vk;- cur=vb;- if((key->start>=cur->start)&&(key->start<(cur->start+cur->length)))- {- return 0;- }- if(key->start>cur->start) return 1;- return -1;-}--static const struct _convrule_ *getrule(- const struct _charblock_ *blocks,- int numblocks,- int unichar)-{- struct _charblock_ key={unichar,1,(void *)0};- struct _charblock_ *cb=bsearch(&key,blocks,numblocks,sizeof(key),blkcmp);- if(cb==(void *)0) return &nullrule;- return cb->rule;-}- ---/*- Check whether a character (internal code) has certain attributes.- Attributes (category flags) may be ORed. The function ANDs- character category flags and the mask and returns the result.- If the character belongs to one of the categories requested,- the result will be nonzero.-*/--inline static int checkattr(int c,unsigned int catmask)-{- return (catmask & (getrule(allchars,(c<256)?NUM_LAT1BLOCKS:NUM_BLOCKS,c)->category));-}--inline static int checkattr_s(int c,unsigned int catmask)-{- return (catmask & (getrule(spacechars,NUM_SPACEBLOCKS,c)->category));-}--/*- Define predicate functions for some combinations of categories.-*/--#define unipred(p,m) \-int p(int c) \-{ \- return checkattr(c,m); \-}--#define unipred_s(p,m) \-int p(int c) \-{ \- return checkattr_s(c,m); \-}--/*- Make these rules as close to Hugs as possible.-*/--unipred(u_iswcntrl,GENCAT_CC)-unipred(u_iswprint, (GENCAT_MC | GENCAT_NO | GENCAT_SK | GENCAT_ME | GENCAT_ND | GENCAT_PO | GENCAT_LT | GENCAT_PC | GENCAT_SM | GENCAT_ZS | GENCAT_LU | GENCAT_PD | GENCAT_SO | GENCAT_PE | GENCAT_PF | GENCAT_PS | GENCAT_SC | GENCAT_LL | GENCAT_LM | GENCAT_PI | GENCAT_NL | GENCAT_MN | GENCAT_LO))-unipred_s(u_iswspace,GENCAT_ZS)-unipred(u_iswupper,(GENCAT_LU|GENCAT_LT))-unipred(u_iswlower,GENCAT_LL)-unipred(u_iswalpha,(GENCAT_LL|GENCAT_LU|GENCAT_LT|GENCAT_LM|GENCAT_LO))-unipred(u_iswdigit,GENCAT_ND)--unipred(u_iswalnum,(GENCAT_LT|GENCAT_LU|GENCAT_LL|GENCAT_LM|GENCAT_LO|- GENCAT_MC|GENCAT_ME|GENCAT_MN|- GENCAT_NO|GENCAT_ND|GENCAT_NL))--#define caseconv(p,to) \-int p(int c) \-{ \- const struct _convrule_ *rule=getrule(convchars,NUM_CONVBLOCKS,c);\- if(rule==&nullrule) return c;\- return c+rule->to;\-}--caseconv(u_towupper,updist)-caseconv(u_towlower,lowdist)-caseconv(u_towtitle,titledist)--int u_gencat(int c)-{- return getrule(allchars,NUM_BLOCKS,c)->catnumber;-}-
@@ -1,132 +0,0 @@-/* ----------------------------------------------------------------------------- (c) The University of Glasgow 2006- - Useful Win32 bits- ------------------------------------------------------------------------- */--#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)--#include "HsBase.h"--/* This is the error table that defines the mapping between OS error- codes and errno values */--struct errentry {- unsigned long oscode; /* OS return value */- int errnocode; /* System V error code */-};--static struct errentry errtable[] = {- { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */- { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */- { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */- { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */- { ERROR_ACCESS_DENIED, EACCES }, /* 5 */- { ERROR_INVALID_HANDLE, EBADF }, /* 6 */- { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */- { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */- { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */- { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */- { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */- { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */- { ERROR_INVALID_DATA, EINVAL }, /* 13 */- { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */- { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */- { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */- { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */- { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */- { ERROR_BAD_NETPATH, ENOENT }, /* 53 */- { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */- { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */- { ERROR_FILE_EXISTS, EEXIST }, /* 80 */- { ERROR_CANNOT_MAKE, EACCES }, /* 82 */- { ERROR_FAIL_I24, EACCES }, /* 83 */- { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */- { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */- { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */- { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */- { ERROR_DISK_FULL, ENOSPC }, /* 112 */- { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */- { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */- { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */- { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */- { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */- { ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */- { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */- { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */- { ERROR_NOT_LOCKED, EACCES }, /* 158 */- { ERROR_BAD_PATHNAME, ENOENT }, /* 161 */- { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */- { ERROR_LOCK_FAILED, EACCES }, /* 167 */- { ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */- { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */- { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */- /* Windows returns this when the read end of a pipe is- * closed (or closing) and we write to it. */- { ERROR_NO_DATA, EPIPE }, /* 232 */- { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */-};--/* size of the table */-#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))--/* The following two constants must be the minimum and maximum- values in the (contiguous) range of Exec Failure errors. */-#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG-#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN--/* These are the low and high value in the range of errors that are- access violations */-#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT-#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED--void maperrno (void)-{- int i;- DWORD dwErrorCode;-- dwErrorCode = GetLastError();-- /* check the table for the OS error code */- for (i = 0; i < ERRTABLESIZE; ++i)- {- if (dwErrorCode == errtable[i].oscode)- {- errno = errtable[i].errnocode;- return;- }- }-- /* The error code wasn't in the table. We check for a range of */- /* EACCES errors or exec failure errors (ENOEXEC). Otherwise */- /* EINVAL is returned. */-- if (dwErrorCode >= MIN_EACCES_RANGE && dwErrorCode <= MAX_EACCES_RANGE)- errno = EACCES;- else- if (dwErrorCode >= MIN_EXEC_ERROR && dwErrorCode <= MAX_EXEC_ERROR)- errno = ENOEXEC;- else- errno = EINVAL;-}--HsWord64 getUSecOfDay(void)-{- HsWord64 t;- FILETIME ft;- GetSystemTimeAsFileTime(&ft);- t = ((HsWord64)ft.dwHighDateTime << 32) | ft.dwLowDateTime;- t = t / 10LL;- /* FILETIMES are in units of 100ns,- so we divide by 10 to get microseconds */- return t;-}--BOOL file_exists(LPCTSTR path)-{- DWORD r = GetFileAttributes(path);- return r != INVALID_FILE_ATTRIBUTES;-}--#endif-
@@ -1,111 +0,0 @@-/* - * (c) The University of Glasgow 2002- *- * Win32 Console API support- */-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32) || defined(__CYGWIN__)-/* to the end */--#include "consUtils.h"-#include <windows.h>-#include <io.h>--#if defined(__CYGWIN__)-#define _get_osfhandle get_osfhandle-#endif--int is_console__(int fd) {- DWORD st;- HANDLE h;- if (!_isatty(fd)) {- /* TTY must be a character device */- return 0;- }- h = (HANDLE)_get_osfhandle(fd);- if (h == INVALID_HANDLE_VALUE) {- /* Broken handle can't be terminal */- return 0;- }- if (!GetConsoleMode(h, &st)) {- /* GetConsoleMode appears to fail when it's not a TTY. In- particular, it's what most of our terminal functions- assume works, so if it doesn't work for all intents- and purposes we're not dealing with a terminal. */- return 0;- }- return 1;-}---int-set_console_buffering__(int fd, int cooked)-{- HANDLE h;- DWORD st;- /* According to GetConsoleMode() docs, it is not possible to- leave ECHO_INPUT enabled without also having LINE_INPUT,- so we have to turn both off here. */- DWORD flgs = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;- - if ( (h = (HANDLE)_get_osfhandle(fd)) != INVALID_HANDLE_VALUE ) {- if ( GetConsoleMode(h,&st) &&- SetConsoleMode(h, cooked ? (st | ENABLE_LINE_INPUT) : st & ~flgs) ) {- return 0;- }- }- return -1;-}--int-set_console_echo__(int fd, int on)-{- HANDLE h;- DWORD st;- DWORD flgs = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;- - if ( (h = (HANDLE)_get_osfhandle(fd)) != INVALID_HANDLE_VALUE ) {- if ( GetConsoleMode(h,&st) && - SetConsoleMode(h,( on ? (st | flgs) : (st & ~ENABLE_ECHO_INPUT))) ) {- return 0;- }- }- return -1;-}--int-get_console_echo__(int fd)-{- HANDLE h;- DWORD st;- - if ( (h = (HANDLE)_get_osfhandle(fd)) != INVALID_HANDLE_VALUE ) {- if ( GetConsoleMode(h,&st) ) {- return (st & ENABLE_ECHO_INPUT ? 1 : 0);- }- }- return -1;-}--int-flush_input_console__(int fd)-{- HANDLE h = (HANDLE)_get_osfhandle(fd);- - if ( h != INVALID_HANDLE_VALUE ) {- /* If the 'fd' isn't connected to a console; treat the flush- * operation as a NOP.- */- DWORD unused;- if ( !GetConsoleMode(h,&unused) &&- GetLastError() == ERROR_INVALID_HANDLE ) {- return 0;- }- if ( FlushConsoleInputBuffer(h) ) {- return 0;- }- }- /* ToDo: translate GetLastError() into something errno-friendly */- return -1;-}--#endif /* defined(__MINGW32__) || ... */
@@ -1,25 +0,0 @@-#ifndef __MINGW32__--#include <stdlib.h>-#include <iconv.h>--iconv_t hs_iconv_open(const char* tocode,- const char* fromcode)-{- return iconv_open(tocode, fromcode);-}--size_t hs_iconv(iconv_t cd,- const char* * inbuf, size_t * inbytesleft,- char* * outbuf, size_t * outbytesleft)-{- // (void*) cast avoids a warning. Some iconvs use (const- // char**inbuf), other use (char **inbuf).- return iconv(cd, (void*)inbuf, inbytesleft, outbuf, outbytesleft);-}--int hs_iconv_close(iconv_t cd) {- return iconv_close(cd);-}--#endif
@@ -1,168 +0,0 @@-/* - * (c) The GRASP/AQUA Project, Glasgow University, 1994-2002- *- * hWaitForInput Runtime Support- */--/* select and supporting types is not Posix */-/* #include "PosixSource.h" */-#include "HsBase.h"--/*- * inputReady(fd) checks to see whether input is available on the file- * descriptor 'fd'. Input meaning 'can I safely read at least a- * *character* from this file object without blocking?'- */-int-fdReady(int fd, int write, int msecs, int isSock)-{- if -#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)- ( isSock ) {-#else- ( 1 ) {-#endif- int maxfd, ready;- fd_set rfd, wfd;- struct timeval tv;- - FD_ZERO(&rfd);- FD_ZERO(&wfd);- if (write) {- FD_SET(fd, &wfd);- } else {- FD_SET(fd, &rfd);- }- - /* select() will consider the descriptor set in the range of 0 to- * (maxfd-1) - */- maxfd = fd + 1;- tv.tv_sec = msecs / 1000;- tv.tv_usec = (msecs % 1000) * 1000;- - while ((ready = select(maxfd, &rfd, &wfd, NULL, &tv)) < 0 ) {- if (errno != EINTR ) {- return -1;- }- }- - /* 1 => Input ready, 0 => not ready, -1 => error */- return (ready);- }-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)- else {- DWORD rc;- HANDLE hFile = (HANDLE)_get_osfhandle(fd);- DWORD avail;-- switch (GetFileType(hFile)) {-- case FILE_TYPE_CHAR:- {- INPUT_RECORD buf[1];- DWORD count;-- // nightmare. A Console Handle will appear to be ready- // (WaitForSingleObject() returned WAIT_OBJECT_0) when- // it has events in its input buffer, but these events might- // not be keyboard events, so when we read from the Handle the- // read() will block. So here we try to discard non-keyboard- // events from a console handle's input buffer and then try- // the WaitForSingleObject() again.-- while (1) // keep trying until we find a real key event- {- rc = WaitForSingleObject( hFile, msecs );- switch (rc) {- case WAIT_TIMEOUT: return 0;- case WAIT_OBJECT_0: break;- default: /* WAIT_FAILED */ maperrno(); return -1;- }-- while (1) // discard non-key events- {- rc = PeekConsoleInput(hFile, buf, 1, &count);- // printf("peek, rc=%d, count=%d, type=%d\n", rc, count, buf[0].EventType);- if (rc == 0) {- rc = GetLastError();- if (rc == ERROR_INVALID_HANDLE || rc == ERROR_INVALID_FUNCTION) {- return 1;- } else {- maperrno();- return -1;- }- }-- if (count == 0) break; // no more events => wait again-- // discard console events that are not "key down", because- // these will also be discarded by ReadFile().- if (buf[0].EventType == KEY_EVENT &&- buf[0].Event.KeyEvent.bKeyDown &&- buf[0].Event.KeyEvent.uChar.AsciiChar != '\0')- {- // it's a proper keypress:- return 1;- }- else- {- // it's a non-key event, a key up event, or a- // non-character key (e.g. shift). discard it.- rc = ReadConsoleInput(hFile, buf, 1, &count);- if (rc == 0) {- rc = GetLastError();- if (rc == ERROR_INVALID_HANDLE || rc == ERROR_INVALID_FUNCTION) {- return 1;- } else {- maperrno();- return -1;- }- }- }- }- }- }-- case FILE_TYPE_DISK:- // assume that disk files are always ready:- return 1;-- case FILE_TYPE_PIPE:- // WaitForMultipleObjects() doesn't work for pipes (it- // always returns WAIT_OBJECT_0 even when no data is- // available). If the HANDLE is a pipe, therefore, we try- // PeekNamedPipe:- //- rc = PeekNamedPipe( hFile, NULL, 0, NULL, &avail, NULL );- if (rc != 0) {- if (avail != 0) {- return 1;- } else {- return 0;- }- } else {- rc = GetLastError();- if (rc == ERROR_BROKEN_PIPE) {- return 1; // this is probably what we want- }- if (rc != ERROR_INVALID_HANDLE && rc != ERROR_INVALID_FUNCTION) {- maperrno();- return -1;- }- }- /* PeekNamedPipe didn't work - fall through to the general case */-- default:- rc = WaitForSingleObject( hFile, msecs );-- /* 1 => Input ready, 0 => not ready, -1 => error */- switch (rc) {- case WAIT_TIMEOUT: return 0;- case WAIT_OBJECT_0: return 1;- default: /* WAIT_FAILED */ maperrno(); return -1;- }- }- }-#endif-}
@@ -1,238 +0,0 @@-/*- * This code implements the MD5 message-digest algorithm.- * The algorithm is due to Ron Rivest. This code was- * written by Colin Plumb in 1993, no copyright is claimed.- * This code is in the public domain; do with it what you wish.- *- * Equivalent code is available from RSA Data Security, Inc.- * This code has been tested against that, and is equivalent,- * except that you don't need to include two pages of legalese- * with every copy.- *- * To compute the message digest of a chunk of bytes, declare an- * MD5Context structure, pass it to MD5Init, call MD5Update as- * needed on buffers full of bytes, and then call MD5Final, which- * will fill a supplied 16-byte array with the digest.- */--#include "HsFFI.h"-#include "md5.h"-#include <string.h>--void MD5Init(struct MD5Context *context);-void MD5Update(struct MD5Context *context, byte const *buf, int len);-void MD5Final(byte digest[16], struct MD5Context *context);-void MD5Transform(word32 buf[4], word32 const in[16]);---/*- * Shuffle the bytes into little-endian order within words, as per the- * MD5 spec. Note: this code works regardless of the byte order.- */-void-byteSwap(word32 *buf, unsigned words)-{- byte *p = (byte *)buf;-- do {- *buf++ = (word32)((unsigned)p[3] << 8 | p[2]) << 16 |- ((unsigned)p[1] << 8 | p[0]);- p += 4;- } while (--words);-}--/*- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious- * initialization constants.- */-void-MD5Init(struct MD5Context *ctx)-{- ctx->buf[0] = 0x67452301;- ctx->buf[1] = 0xefcdab89;- ctx->buf[2] = 0x98badcfe;- ctx->buf[3] = 0x10325476;-- ctx->bytes[0] = 0;- ctx->bytes[1] = 0;-}--/*- * Update context to reflect the concatenation of another buffer full- * of bytes.- */-void-MD5Update(struct MD5Context *ctx, byte const *buf, int len)-{- word32 t;-- /* Update byte count */-- t = ctx->bytes[0];- if ((ctx->bytes[0] = t + len) < t)- ctx->bytes[1]++; /* Carry from low to high */-- t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */- if ((unsigned)t > len) {- memcpy((byte *)ctx->in + 64 - (unsigned)t, buf, len);- return;- }- /* First chunk is an odd size */- memcpy((byte *)ctx->in + 64 - (unsigned)t, buf, (unsigned)t);- byteSwap(ctx->in, 16);- MD5Transform(ctx->buf, ctx->in);- buf += (unsigned)t;- len -= (unsigned)t;-- /* Process data in 64-byte chunks */- while (len >= 64) {- memcpy(ctx->in, buf, 64);- byteSwap(ctx->in, 16);- MD5Transform(ctx->buf, ctx->in);- buf += 64;- len -= 64;- }-- /* Handle any remaining bytes of data. */- memcpy(ctx->in, buf, len);-}--/*- * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first)- */-void-MD5Final(byte digest[16], struct MD5Context *ctx)-{- int count = (int)(ctx->bytes[0] & 0x3f); /* Bytes in ctx->in */- byte *p = (byte *)ctx->in + count; /* First unused byte */-- /* Set the first char of padding to 0x80. There is always room. */- *p++ = 0x80;-- /* Bytes of padding needed to make 56 bytes (-8..55) */- count = 56 - 1 - count;-- if (count < 0) { /* Padding forces an extra block */- memset(p, 0, count+8);- byteSwap(ctx->in, 16);- MD5Transform(ctx->buf, ctx->in);- p = (byte *)ctx->in;- count = 56;- }- memset(p, 0, count+8);- byteSwap(ctx->in, 14);-- /* Append length in bits and transform */- ctx->in[14] = ctx->bytes[0] << 3;- ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;- MD5Transform(ctx->buf, ctx->in);-- byteSwap(ctx->buf, 4);- memcpy(digest, ctx->buf, 16);- memset(ctx,0,sizeof(ctx));-}---/* The four core functions - F1 is optimized somewhat */--/* #define F1(x, y, z) (x & y | ~x & z) */-#define F1(x, y, z) (z ^ (x & (y ^ z)))-#define F2(x, y, z) F1(z, x, y)-#define F3(x, y, z) (x ^ y ^ z)-#define F4(x, y, z) (y ^ (x | ~z))--/* This is the central step in the MD5 algorithm. */-#define MD5STEP(f,w,x,y,z,in,s) \- (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)--/*- * The core of the MD5 algorithm, this alters an existing MD5 hash to- * reflect the addition of 16 longwords of new data. MD5Update blocks- * the data and converts bytes into longwords for this routine.- */--void-MD5Transform(word32 buf[4], word32 const in[16])-{- register word32 a, b, c, d;-- a = buf[0];- b = buf[1];- c = buf[2];- d = buf[3];-- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);-- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);-- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);-- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);-- buf[0] += a;- buf[1] += b;- buf[2] += c;- buf[3] += d;-}-
@@ -1,532 +0,0 @@-/* ------------------------------------------------------------------------------ *- * (c) Lennart Augustsson- * (c) The GHC Team, 1998-2000- *- * Miscellaneous support for floating-point primitives- *- * ---------------------------------------------------------------------------*/--#include "HsFFI.h"-#include "Rts.h" // XXX wrong (for IEEE_FLOATING_POINT and WORDS_BIGENDIAN)--#define IEEE_FLOATING_POINT 1--union stg_ieee754_flt-{- float f;- struct {--#if WORDS_BIGENDIAN- unsigned int negative:1;- unsigned int exponent:8;- unsigned int mantissa:23;-#else- unsigned int mantissa:23;- unsigned int exponent:8;- unsigned int negative:1;-#endif- } ieee;- struct {--#if WORDS_BIGENDIAN- unsigned int negative:1;- unsigned int exponent:8;- unsigned int quiet_nan:1;- unsigned int mantissa:22;-#else- unsigned int mantissa:22;- unsigned int quiet_nan:1;- unsigned int exponent:8;- unsigned int negative:1;-#endif- } ieee_nan;-};--/*-- To recap, here's the representation of a double precision- IEEE floating point number:-- sign 63 sign bit (0==positive, 1==negative)- exponent 62-52 exponent (biased by 1023)- fraction 51-0 fraction (bits to right of binary point)-*/--union stg_ieee754_dbl-{- double d;- struct {--#if WORDS_BIGENDIAN- unsigned int negative:1;- unsigned int exponent:11;- unsigned int mantissa0:20;- unsigned int mantissa1:32;-#else-#if FLOAT_WORDS_BIGENDIAN- unsigned int mantissa0:20;- unsigned int exponent:11;- unsigned int negative:1;- unsigned int mantissa1:32;-#else- unsigned int mantissa1:32;- unsigned int mantissa0:20;- unsigned int exponent:11;- unsigned int negative:1;-#endif-#endif- } ieee;- /* This format makes it easier to see if a NaN is a signalling NaN. */- struct {--#if WORDS_BIGENDIAN- unsigned int negative:1;- unsigned int exponent:11;- unsigned int quiet_nan:1;- unsigned int mantissa0:19;- unsigned int mantissa1:32;-#else-#if FLOAT_WORDS_BIGENDIAN- unsigned int mantissa0:19;- unsigned int quiet_nan:1;- unsigned int exponent:11;- unsigned int negative:1;- unsigned int mantissa1:32;-#else- unsigned int mantissa1:32;- unsigned int mantissa0:19;- unsigned int quiet_nan:1;- unsigned int exponent:11;- unsigned int negative:1;-#endif-#endif- } ieee_nan;-};--/*- * Predicates for testing for extreme IEEE fp values.- */--/* In case you don't suppport IEEE, you'll just get dummy defs.. */-#ifdef IEEE_FLOATING_POINT--HsInt-isDoubleFinite(HsDouble d)-{- union stg_ieee754_dbl u;-- u.d = d;-- return u.ieee.exponent != 2047;-}--HsInt-isDoubleNaN(HsDouble d)-{- union stg_ieee754_dbl u;-- u.d = d;-- return (- u.ieee.exponent == 2047 /* 2^11 - 1 */ && /* Is the exponent all ones? */- (u.ieee.mantissa0 != 0 || u.ieee.mantissa1 != 0)- /* and the mantissa non-zero? */- );-}--HsInt-isDoubleInfinite(HsDouble d)-{- union stg_ieee754_dbl u;-- u.d = d;-- /* Inf iff exponent is all ones, mantissa all zeros */- return (- u.ieee.exponent == 2047 /* 2^11 - 1 */ &&- u.ieee.mantissa0 == 0 &&- u.ieee.mantissa1 == 0- );-}--HsInt-isDoubleDenormalized(HsDouble d)-{- union stg_ieee754_dbl u;-- u.d = d;-- /* A (single/double/quad) precision floating point number- is denormalised iff:- - exponent is zero- - mantissa is non-zero.- - (don't care about setting of sign bit.)-- */- return (- u.ieee.exponent == 0 &&- (u.ieee.mantissa0 != 0 ||- u.ieee.mantissa1 != 0)- );--}--HsInt-isDoubleNegativeZero(HsDouble d)-{- union stg_ieee754_dbl u;-- u.d = d;- /* sign (bit 63) set (only) => negative zero */-- return (- u.ieee.negative == 1 &&- u.ieee.exponent == 0 &&- u.ieee.mantissa0 == 0 &&- u.ieee.mantissa1 == 0);-}--/* Same tests, this time for HsFloats. */--/*- To recap, here's the representation of a single precision- IEEE floating point number:-- sign 31 sign bit (0 == positive, 1 == negative)- exponent 30-23 exponent (biased by 127)- fraction 22-0 fraction (bits to right of binary point)-*/---HsInt-isFloatFinite(HsFloat f)-{- union stg_ieee754_flt u;- u.f = f;- return u.ieee.exponent != 255;-}--HsInt-isFloatNaN(HsFloat f)-{- union stg_ieee754_flt u;- u.f = f;-- /* Floating point NaN iff exponent is all ones, mantissa is- non-zero (but see below.) */- return (- u.ieee.exponent == 255 /* 2^8 - 1 */ &&- u.ieee.mantissa != 0);-}--HsInt-isFloatInfinite(HsFloat f)-{- union stg_ieee754_flt u;- u.f = f;-- /* A float is Inf iff exponent is max (all ones),- and mantissa is min(all zeros.) */- return (- u.ieee.exponent == 255 /* 2^8 - 1 */ &&- u.ieee.mantissa == 0);-}--HsInt-isFloatDenormalized(HsFloat f)-{- union stg_ieee754_flt u;- u.f = f;-- /* A (single/double/quad) precision floating point number- is denormalised iff:- - exponent is zero- - mantissa is non-zero.- - (don't care about setting of sign bit.)-- */- return (- u.ieee.exponent == 0 &&- u.ieee.mantissa != 0);-}--HsInt-isFloatNegativeZero(HsFloat f)-{- union stg_ieee754_flt u;- u.f = f;-- /* sign (bit 31) set (only) => negative zero */- return (- u.ieee.negative &&- u.ieee.exponent == 0 &&- u.ieee.mantissa == 0);-}--/*- There are glibc versions around with buggy rintf or rint, hence we- provide our own. We always round ties to even, so we can be simpler.-*/--#define FLT_HIDDEN 0x800000-#define FLT_POWER2 0x1000000--HsFloat-rintFloat(HsFloat f)-{- union stg_ieee754_flt u;- u.f = f;- /* if real exponent > 22, it's already integral, infinite or nan */- if (u.ieee.exponent > 149) /* 22 + 127 */- {- return u.f;- }- if (u.ieee.exponent < 126) /* (-1) + 127, abs(f) < 0.5 */- {- /* only used for rounding to Integral a, so don't care about -0.0 */- return 0.0;- }- /* 0.5 <= abs(f) < 2^23 */- unsigned int half, mask, mant, frac;- half = 1 << (149 - u.ieee.exponent); /* bit for 0.5 */- mask = 2*half - 1; /* fraction bits */- mant = u.ieee.mantissa | FLT_HIDDEN; /* add hidden bit */- frac = mant & mask; /* get fraction */- mant ^= frac; /* truncate mantissa */- if ((frac < half) || ((frac == half) && ((mant & (2*half)) == 0)))- {- /* this means we have to truncate */- if (mant == 0)- {- /* f == ±0.5, return 0.0 */- return 0.0;- }- else- {- /* remove hidden bit and set mantissa */- u.ieee.mantissa = mant ^ FLT_HIDDEN;- return u.f;- }- }- else- {- /* round away from zero, increment mantissa */- mant += 2*half;- if (mant == FLT_POWER2)- {- /* next power of 2, increase exponent an set mantissa to 0 */- u.ieee.mantissa = 0;- u.ieee.exponent += 1;- return u.f;- }- else- {- /* remove hidden bit and set mantissa */- u.ieee.mantissa = mant ^ FLT_HIDDEN;- return u.f;- }- }-}--#define DBL_HIDDEN 0x100000-#define DBL_POWER2 0x200000-#define LTOP_BIT 0x80000000--HsDouble-rintDouble(HsDouble d)-{- union stg_ieee754_dbl u;- u.d = d;- /* if real exponent > 51, it's already integral, infinite or nan */- if (u.ieee.exponent > 1074) /* 51 + 1023 */- {- return u.d;- }- if (u.ieee.exponent < 1022) /* (-1) + 1023, abs(d) < 0.5 */- {- /* only used for rounding to Integral a, so don't care about -0.0 */- return 0.0;- }- unsigned int half, mask, mant, frac;- if (u.ieee.exponent < 1043) /* 20 + 1023, real exponent < 20 */- {- /* the fractional part meets the higher part of the mantissa */- half = 1 << (1042 - u.ieee.exponent); /* bit for 0.5 */- mask = 2*half - 1; /* fraction bits */- mant = u.ieee.mantissa0 | DBL_HIDDEN; /* add hidden bit */- frac = mant & mask; /* get fraction */- mant ^= frac; /* truncate mantissa */- if ((frac < half) ||- ((frac == half) && (u.ieee.mantissa1 == 0) /* a tie */- && ((mant & (2*half)) == 0)))- {- /* truncate */- if (mant == 0)- {- /* d = ±0.5, return 0.0 */- return 0.0;- }- /* remove hidden bit and set mantissa */- u.ieee.mantissa0 = mant ^ DBL_HIDDEN;- u.ieee.mantissa1 = 0;- return u.d;- }- else /* round away from zero */- {- /* zero low mantissa bits */- u.ieee.mantissa1 = 0;- /* increment integer part of mantissa */- mant += 2*half;- if (mant == DBL_POWER2)- {- /* power of 2, increment exponent and zero mantissa */- u.ieee.mantissa0 = 0;- u.ieee.exponent += 1;- return u.d;- }- /* remove hidden bit */- u.ieee.mantissa0 = mant ^ DBL_HIDDEN;- return u.d;- }- }- else- {- /* 20 <= real exponent < 52, fractional part entirely in mantissa1 */- half = 1 << (1074 - u.ieee.exponent); /* bit for 0.5 */- mask = 2*half - 1; /* fraction bits */- mant = u.ieee.mantissa1; /* no hidden bit here */- frac = mant & mask; /* get fraction */- mant ^= frac; /* truncate mantissa */- if ((frac < half) ||- ((frac == half) && /* tie */- (((half == LTOP_BIT) ? (u.ieee.mantissa0 & 1) /* yuck */- : (mant & (2*half)))- == 0)))- {- /* truncate */- u.ieee.mantissa1 = mant;- return u.d;- }- else- {- /* round away from zero */- /* increment mantissa */- mant += 2*half;- u.ieee.mantissa1 = mant;- if (mant == 0)- {- /* low part of mantissa overflowed */- /* increment high part of mantissa */- mant = u.ieee.mantissa0 + 1;- if (mant == DBL_HIDDEN)- {- /* hit power of 2 */- /* zero mantissa */- u.ieee.mantissa0 = 0;- /* and increment exponent */- u.ieee.exponent += 1;- return u.d;- }- else- {- u.ieee.mantissa0 = mant;- return u.d;- }- }- else- {- return u.d;- }- }- }-}--#else /* ! IEEE_FLOATING_POINT */--/* Dummy definitions of predicates - they all return "normal" values */-HsInt isDoubleFinite(HsDouble d) { return 1;}-HsInt isDoubleNaN(HsDouble d) { return 0; }-HsInt isDoubleInfinite(HsDouble d) { return 0; }-HsInt isDoubleDenormalized(HsDouble d) { return 0; }-HsInt isDoubleNegativeZero(HsDouble d) { return 0; }-HsInt isFloatFinite(HsFloat f) { return 1; }-HsInt isFloatNaN(HsFloat f) { return 0; }-HsInt isFloatInfinite(HsFloat f) { return 0; }-HsInt isFloatDenormalized(HsFloat f) { return 0; }-HsInt isFloatNegativeZero(HsFloat f) { return 0; }---/* For exotic floating point formats, we can't do much */-/* We suppose the format has not too many bits */-/* I hope nobody tries to build GHC where this is wrong */--#define FLT_UPP 536870912.0--HsFloat-rintFloat(HsFloat f)-{- if ((f > FLT_UPP) || (f < (-FLT_UPP)))- {- return f;- }- else- {- int i = (int)f;- float g = i;- float d = f - g;- if (d > 0.5)- {- return g + 1.0;- }- if (d == 0.5)- {- return (i & 1) ? (g + 1.0) : g;- }- if (d == -0.5)- {- return (i & 1) ? (g - 1.0) : g;- }- if (d < -0.5)- {- return g - 1.0;- }- return g;- }-}--#define DBL_UPP 2305843009213693952.0--HsDouble-rintDouble(HsDouble d)-{- if ((d > DBL_UPP) || (d < (-DBL_UPP)))- {- return d;- }- else- {- HsInt64 i = (HsInt64)d;- double e = i;- double r = d - e;- if (r > 0.5)- {- return e + 1.0;- }- if (r == 0.5)- {- return (i & 1) ? (e + 1.0) : e;- }- if (r == -0.5)- {- return (i & 1) ? (e - 1.0) : e;- }- if (r < -0.5)- {- return e - 1.0;- }- return e;- }-}--#endif /* ! IEEE_FLOATING_POINT */
@@ -1,3 +0,0 @@--#include "HsBase.h"-void hsFD_ZERO(fd_set *fds) { FD_ZERO(fds); }
@@ -1,1500 +0,0 @@-#! /bin/sh-# Attempt to guess a canonical system name.-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,-# Inc.--timestamp='2006-07-02'--# This file is free software; you can redistribute it and/or modify it-# under the terms of the GNU General Public License as published by-# the Free Software Foundation; either version 2 of the License, or-# (at your option) any later version.-#-# This program is distributed in the hope that it will be useful, but-# WITHOUT ANY WARRANTY; without even the implied warranty of-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU-# General Public License for more details.-#-# You should have received a copy of the GNU General Public License-# along with this program; if not, write to the Free Software-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA-# 02110-1301, USA.-#-# As a special exception to the GNU General Public License, if you-# distribute this file as part of a program that contains a-# configuration script generated by Autoconf, you may include it under-# the same distribution terms that you use for the rest of that program.---# Originally written by Per Bothner <per@bothner.com>.-# Please send patches to <config-patches@gnu.org>. Submit a context-# diff and a properly formatted ChangeLog entry.-#-# This script attempts to guess a canonical system name similar to-# config.sub. If it succeeds, it prints the system name on stdout, and-# exits with 0. Otherwise, it exits with 1.-#-# The plan is that this can be called by configure scripts if you-# don't specify an explicit build system type.--me=`echo "$0" | sed -e 's,.*/,,'`--usage="\-Usage: $0 [OPTION]--Output the configuration name of the system \`$me' is run on.--Operation modes:- -h, --help print this help, then exit- -t, --time-stamp print date of last modification, then exit- -v, --version print version number, then exit--Report bugs and patches to <config-patches@gnu.org>."--version="\-GNU config.guess ($timestamp)--Originally written by Per Bothner.-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005-Free Software Foundation, Inc.--This is free software; see the source for copying conditions. There is NO-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."--help="-Try \`$me --help' for more information."--# Parse command line-while test $# -gt 0 ; do- case $1 in- --time-stamp | --time* | -t )- echo "$timestamp" ; exit ;;- --version | -v )- echo "$version" ; exit ;;- --help | --h* | -h )- echo "$usage"; exit ;;- -- ) # Stop option processing- shift; break ;;- - ) # Use stdin as input.- break ;;- -* )- echo "$me: invalid option $1$help" >&2- exit 1 ;;- * )- break ;;- esac-done--if test $# != 0; then- echo "$me: too many arguments$help" >&2- exit 1-fi--trap 'exit 1' 1 2 15--# CC_FOR_BUILD -- compiler used by this script. Note that the use of a-# compiler to aid in system detection is discouraged as it requires-# temporary files to be created and, as you can see below, it is a-# headache to deal with in a portable fashion.--# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still-# use `HOST_CC' if defined, but it is deprecated.--# Portable tmp directory creation inspired by the Autoconf team.--set_cc_for_build='-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;-: ${TMPDIR=/tmp} ;- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;-dummy=$tmp/dummy ;-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;-case $CC_FOR_BUILD,$HOST_CC,$CC in- ,,) echo "int x;" > $dummy.c ;- for c in cc gcc c89 c99 ; do- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then- CC_FOR_BUILD="$c"; break ;- fi ;- done ;- if test x"$CC_FOR_BUILD" = x ; then- CC_FOR_BUILD=no_compiler_found ;- fi- ;;- ,,*) CC_FOR_BUILD=$CC ;;- ,*,*) CC_FOR_BUILD=$HOST_CC ;;-esac ; set_cc_for_build= ;'--# This is needed to find uname on a Pyramid OSx when run in the BSD universe.-# (ghazi@noc.rutgers.edu 1994-08-24)-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then- PATH=$PATH:/.attbin ; export PATH-fi--UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown--# Note: order is significant - the case branches are not exclusive.--case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in- *:NetBSD:*:*)- # NetBSD (nbsd) targets should (where applicable) match one or- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently- # switched to ELF, *-*-netbsd* would select the old- # object file format. This provides both forward- # compatibility and a consistent mechanism for selecting the- # object file format.- #- # Note: NetBSD doesn't particularly care about the vendor- # portion of the name. We always set it to "unknown".- sysctl="sysctl -n hw.machine_arch"- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`- case "${UNAME_MACHINE_ARCH}" in- armeb) machine=armeb-unknown ;;- arm*) machine=arm-unknown ;;- sh3el) machine=shl-unknown ;;- sh3eb) machine=sh-unknown ;;- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;- esac- # The Operating System including object format, if it has switched- # to ELF recently, or will in the future.- case "${UNAME_MACHINE_ARCH}" in- arm*|i386|m68k|ns32k|sh3*|sparc|vax)- eval $set_cc_for_build- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \- | grep __ELF__ >/dev/null- then- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).- # Return netbsd for either. FIX?- os=netbsd- else- os=netbsdelf- fi- ;;- *)- os=netbsd- ;;- esac- # The OS release- # Debian GNU/NetBSD machines have a different userland, and- # thus, need a distinct triplet. However, they do not need- # kernel version information, so it can be replaced with a- # suitable tag, in the style of linux-gnu.- case "${UNAME_VERSION}" in- Debian*)- release='-gnu'- ;;- *)- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`- ;;- esac- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:- # contains redundant information, the shorter form:- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.- echo "${machine}-${os}${release}"- exit ;;- *:OpenBSD:*:*)- UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}- exit ;;- *:ekkoBSD:*:*)- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}- exit ;;- *:SolidBSD:*:*)- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}- exit ;;- macppc:MirBSD:*:*)- echo powerpc-unknown-mirbsd${UNAME_RELEASE}- exit ;;- *:MirBSD:*:*)- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}- exit ;;- alpha:OSF1:*:*)- case $UNAME_RELEASE in- *4.0)- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`- ;;- *5.*)- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`- ;;- esac- # According to Compaq, /usr/sbin/psrinfo has been available on- # OSF/1 and Tru64 systems produced since 1995. I hope that- # covers most systems running today. This code pipes the CPU- # types through head -n 1, so we only detect the type of CPU 0.- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`- case "$ALPHA_CPU_TYPE" in- "EV4 (21064)")- UNAME_MACHINE="alpha" ;;- "EV4.5 (21064)")- UNAME_MACHINE="alpha" ;;- "LCA4 (21066/21068)")- UNAME_MACHINE="alpha" ;;- "EV5 (21164)")- UNAME_MACHINE="alphaev5" ;;- "EV5.6 (21164A)")- UNAME_MACHINE="alphaev56" ;;- "EV5.6 (21164PC)")- UNAME_MACHINE="alphapca56" ;;- "EV5.7 (21164PC)")- UNAME_MACHINE="alphapca57" ;;- "EV6 (21264)")- UNAME_MACHINE="alphaev6" ;;- "EV6.7 (21264A)")- UNAME_MACHINE="alphaev67" ;;- "EV6.8CB (21264C)")- UNAME_MACHINE="alphaev68" ;;- "EV6.8AL (21264B)")- UNAME_MACHINE="alphaev68" ;;- "EV6.8CX (21264D)")- UNAME_MACHINE="alphaev68" ;;- "EV6.9A (21264/EV69A)")- UNAME_MACHINE="alphaev69" ;;- "EV7 (21364)")- UNAME_MACHINE="alphaev7" ;;- "EV7.9 (21364A)")- UNAME_MACHINE="alphaev79" ;;- esac- # A Pn.n version is a patched version.- # A Vn.n version is a released version.- # A Tn.n version is a released field test version.- # A Xn.n version is an unreleased experimental baselevel.- # 1.2 uses "1.2" for uname -r.- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`- exit ;;- Alpha\ *:Windows_NT*:*)- # How do we know it's Interix rather than the generic POSIX subsystem?- # Should we change UNAME_MACHINE based on the output of uname instead- # of the specific Alpha model?- echo alpha-pc-interix- exit ;;- 21064:Windows_NT:50:3)- echo alpha-dec-winnt3.5- exit ;;- Amiga*:UNIX_System_V:4.0:*)- echo m68k-unknown-sysv4- exit ;;- *:[Aa]miga[Oo][Ss]:*:*)- echo ${UNAME_MACHINE}-unknown-amigaos- exit ;;- *:[Mm]orph[Oo][Ss]:*:*)- echo ${UNAME_MACHINE}-unknown-morphos- exit ;;- *:OS/390:*:*)- echo i370-ibm-openedition- exit ;;- *:z/VM:*:*)- echo s390-ibm-zvmoe- exit ;;- *:OS400:*:*)- echo powerpc-ibm-os400- exit ;;- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)- echo arm-acorn-riscix${UNAME_RELEASE}- exit ;;- arm:riscos:*:*|arm:RISCOS:*:*)- echo arm-unknown-riscos- exit ;;- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)- echo hppa1.1-hitachi-hiuxmpp- exit ;;- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.- if test "`(/bin/universe) 2>/dev/null`" = att ; then- echo pyramid-pyramid-sysv3- else- echo pyramid-pyramid-bsd- fi- exit ;;- NILE*:*:*:dcosx)- echo pyramid-pyramid-svr4- exit ;;- DRS?6000:unix:4.0:6*)- echo sparc-icl-nx6- exit ;;- DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)- case `/usr/bin/uname -p` in- sparc) echo sparc-icl-nx7; exit ;;- esac ;;- sun4H:SunOS:5.*:*)- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`- exit ;;- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`- exit ;;- i86pc:SunOS:5.*:*)- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`- exit ;;- sun4*:SunOS:6*:*)- # According to config.sub, this is the proper way to canonicalize- # SunOS6. Hard to guess exactly what SunOS6 will be like, but- # it's likely to be more like Solaris than SunOS4.- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`- exit ;;- sun4*:SunOS:*:*)- case "`/usr/bin/arch -k`" in- Series*|S4*)- UNAME_RELEASE=`uname -v`- ;;- esac- # Japanese Language versions have a version number like `4.1.3-JL'.- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`- exit ;;- sun3*:SunOS:*:*)- echo m68k-sun-sunos${UNAME_RELEASE}- exit ;;- sun*:*:4.2BSD:*)- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3- case "`/bin/arch`" in- sun3)- echo m68k-sun-sunos${UNAME_RELEASE}- ;;- sun4)- echo sparc-sun-sunos${UNAME_RELEASE}- ;;- esac- exit ;;- aushp:SunOS:*:*)- echo sparc-auspex-sunos${UNAME_RELEASE}- exit ;;- # The situation for MiNT is a little confusing. The machine name- # can be virtually everything (everything which is not- # "atarist" or "atariste" at least should have a processor- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"- # to the lowercase version "mint" (or "freemint"). Finally- # the system name "TOS" denotes a system which is actually not- # MiNT. But MiNT is downward compatible to TOS, so this should- # be no problem.- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)- echo m68k-atari-mint${UNAME_RELEASE}- exit ;;- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)- echo m68k-atari-mint${UNAME_RELEASE}- exit ;;- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)- echo m68k-atari-mint${UNAME_RELEASE}- exit ;;- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)- echo m68k-milan-mint${UNAME_RELEASE}- exit ;;- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)- echo m68k-hades-mint${UNAME_RELEASE}- exit ;;- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)- echo m68k-unknown-mint${UNAME_RELEASE}- exit ;;- m68k:machten:*:*)- echo m68k-apple-machten${UNAME_RELEASE}- exit ;;- powerpc:machten:*:*)- echo powerpc-apple-machten${UNAME_RELEASE}- exit ;;- RISC*:Mach:*:*)- echo mips-dec-mach_bsd4.3- exit ;;- RISC*:ULTRIX:*:*)- echo mips-dec-ultrix${UNAME_RELEASE}- exit ;;- VAX*:ULTRIX*:*:*)- echo vax-dec-ultrix${UNAME_RELEASE}- exit ;;- 2020:CLIX:*:* | 2430:CLIX:*:*)- echo clipper-intergraph-clix${UNAME_RELEASE}- exit ;;- mips:*:*:UMIPS | mips:*:*:RISCos)- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c-#ifdef __cplusplus-#include <stdio.h> /* for printf() prototype */- int main (int argc, char *argv[]) {-#else- int main (argc, argv) int argc; char *argv[]; {-#endif- #if defined (host_mips) && defined (MIPSEB)- #if defined (SYSTYPE_SYSV)- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);- #endif- #if defined (SYSTYPE_SVR4)- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);- #endif- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);- #endif- #endif- exit (-1);- }-EOF- $CC_FOR_BUILD -o $dummy $dummy.c &&- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&- SYSTEM_NAME=`$dummy $dummyarg` &&- { echo "$SYSTEM_NAME"; exit; }- echo mips-mips-riscos${UNAME_RELEASE}- exit ;;- Motorola:PowerMAX_OS:*:*)- echo powerpc-motorola-powermax- exit ;;- Motorola:*:4.3:PL8-*)- echo powerpc-harris-powermax- exit ;;- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)- echo powerpc-harris-powermax- exit ;;- Night_Hawk:Power_UNIX:*:*)- echo powerpc-harris-powerunix- exit ;;- m88k:CX/UX:7*:*)- echo m88k-harris-cxux7- exit ;;- m88k:*:4*:R4*)- echo m88k-motorola-sysv4- exit ;;- m88k:*:3*:R3*)- echo m88k-motorola-sysv3- exit ;;- AViiON:dgux:*:*)- # DG/UX returns AViiON for all architectures- UNAME_PROCESSOR=`/usr/bin/uname -p`- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]- then- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \- [ ${TARGET_BINARY_INTERFACE}x = x ]- then- echo m88k-dg-dgux${UNAME_RELEASE}- else- echo m88k-dg-dguxbcs${UNAME_RELEASE}- fi- else- echo i586-dg-dgux${UNAME_RELEASE}- fi- exit ;;- M88*:DolphinOS:*:*) # DolphinOS (SVR3)- echo m88k-dolphin-sysv3- exit ;;- M88*:*:R3*:*)- # Delta 88k system running SVR3- echo m88k-motorola-sysv3- exit ;;- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)- echo m88k-tektronix-sysv3- exit ;;- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)- echo m68k-tektronix-bsd- exit ;;- *:IRIX*:*:*)- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`- exit ;;- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '- i*86:AIX:*:*)- echo i386-ibm-aix- exit ;;- ia64:AIX:*:*)- if [ -x /usr/bin/oslevel ] ; then- IBM_REV=`/usr/bin/oslevel`- else- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}- fi- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}- exit ;;- *:AIX:2:3)- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c- #include <sys/systemcfg.h>-- main()- {- if (!__power_pc())- exit(1);- puts("powerpc-ibm-aix3.2.5");- exit(0);- }-EOF- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`- then- echo "$SYSTEM_NAME"- else- echo rs6000-ibm-aix3.2.5- fi- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then- echo rs6000-ibm-aix3.2.4- else- echo rs6000-ibm-aix3.2- fi- exit ;;- *:AIX:*:[45])- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then- IBM_ARCH=rs6000- else- IBM_ARCH=powerpc- fi- if [ -x /usr/bin/oslevel ] ; then- IBM_REV=`/usr/bin/oslevel`- else- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}- fi- echo ${IBM_ARCH}-ibm-aix${IBM_REV}- exit ;;- *:AIX:*:*)- echo rs6000-ibm-aix- exit ;;- ibmrt:4.4BSD:*|romp-ibm:BSD:*)- echo romp-ibm-bsd4.4- exit ;;- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to- exit ;; # report: romp-ibm BSD 4.3- *:BOSX:*:*)- echo rs6000-bull-bosx- exit ;;- DPX/2?00:B.O.S.:*:*)- echo m68k-bull-sysv3- exit ;;- 9000/[34]??:4.3bsd:1.*:*)- echo m68k-hp-bsd- exit ;;- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)- echo m68k-hp-bsd4.4- exit ;;- 9000/[34678]??:HP-UX:*:*)- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`- case "${UNAME_MACHINE}" in- 9000/31? ) HP_ARCH=m68000 ;;- 9000/[34]?? ) HP_ARCH=m68k ;;- 9000/[678][0-9][0-9])- if [ -x /usr/bin/getconf ]; then- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`- case "${sc_cpu_version}" in- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1- 532) # CPU_PA_RISC2_0- case "${sc_kernel_bits}" in- 32) HP_ARCH="hppa2.0n" ;;- 64) HP_ARCH="hppa2.0w" ;;- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20- esac ;;- esac- fi- if [ "${HP_ARCH}" = "" ]; then- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c-- #define _HPUX_SOURCE- #include <stdlib.h>- #include <unistd.h>-- int main ()- {- #if defined(_SC_KERNEL_BITS)- long bits = sysconf(_SC_KERNEL_BITS);- #endif- long cpu = sysconf (_SC_CPU_VERSION);-- switch (cpu)- {- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;- case CPU_PA_RISC2_0:- #if defined(_SC_KERNEL_BITS)- switch (bits)- {- case 64: puts ("hppa2.0w"); break;- case 32: puts ("hppa2.0n"); break;- default: puts ("hppa2.0"); break;- } break;- #else /* !defined(_SC_KERNEL_BITS) */- puts ("hppa2.0"); break;- #endif- default: puts ("hppa1.0"); break;- }- exit (0);- }-EOF- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`- test -z "$HP_ARCH" && HP_ARCH=hppa- fi ;;- esac- if [ ${HP_ARCH} = "hppa2.0w" ]- then- eval $set_cc_for_build-- # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating- # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler- # generating 64-bit code. GNU and HP use different nomenclature:- #- # $ CC_FOR_BUILD=cc ./config.guess- # => hppa2.0w-hp-hpux11.23- # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess- # => hppa64-hp-hpux11.23-- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |- grep __LP64__ >/dev/null- then- HP_ARCH="hppa2.0w"- else- HP_ARCH="hppa64"- fi- fi- echo ${HP_ARCH}-hp-hpux${HPUX_REV}- exit ;;- ia64:HP-UX:*:*)- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`- echo ia64-hp-hpux${HPUX_REV}- exit ;;- 3050*:HI-UX:*:*)- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c- #include <unistd.h>- int- main ()- {- long cpu = sysconf (_SC_CPU_VERSION);- /* The order matters, because CPU_IS_HP_MC68K erroneously returns- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct- results, however. */- if (CPU_IS_PA_RISC (cpu))- {- switch (cpu)- {- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;- default: puts ("hppa-hitachi-hiuxwe2"); break;- }- }- else if (CPU_IS_HP_MC68K (cpu))- puts ("m68k-hitachi-hiuxwe2");- else puts ("unknown-hitachi-hiuxwe2");- exit (0);- }-EOF- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&- { echo "$SYSTEM_NAME"; exit; }- echo unknown-hitachi-hiuxwe2- exit ;;- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )- echo hppa1.1-hp-bsd- exit ;;- 9000/8??:4.3bsd:*:*)- echo hppa1.0-hp-bsd- exit ;;- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)- echo hppa1.0-hp-mpeix- exit ;;- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )- echo hppa1.1-hp-osf- exit ;;- hp8??:OSF1:*:*)- echo hppa1.0-hp-osf- exit ;;- i*86:OSF1:*:*)- if [ -x /usr/sbin/sysversion ] ; then- echo ${UNAME_MACHINE}-unknown-osf1mk- else- echo ${UNAME_MACHINE}-unknown-osf1- fi- exit ;;- parisc*:Lites*:*:*)- echo hppa1.1-hp-lites- exit ;;- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)- echo c1-convex-bsd- exit ;;- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)- if getsysinfo -f scalar_acc- then echo c32-convex-bsd- else echo c2-convex-bsd- fi- exit ;;- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)- echo c34-convex-bsd- exit ;;- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)- echo c38-convex-bsd- exit ;;- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)- echo c4-convex-bsd- exit ;;- CRAY*Y-MP:*:*:*)- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'- exit ;;- CRAY*[A-Z]90:*:*:*)- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \- -e 's/\.[^.]*$/.X/'- exit ;;- CRAY*TS:*:*:*)- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'- exit ;;- CRAY*T3E:*:*:*)- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'- exit ;;- CRAY*SV1:*:*:*)- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'- exit ;;- *:UNICOS/mp:*:*)- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'- exit ;;- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"- exit ;;- 5000:UNIX_System_V:4.*:*)- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"- exit ;;- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}- exit ;;- sparc*:BSD/OS:*:*)- echo sparc-unknown-bsdi${UNAME_RELEASE}- exit ;;- *:BSD/OS:*:*)- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}- exit ;;- *:FreeBSD:*:*)- case ${UNAME_MACHINE} in- pc98)- echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;- amd64)- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;- *)- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;- esac- exit ;;- i*:CYGWIN*:*)- echo ${UNAME_MACHINE}-pc-cygwin- exit ;;- i*:MINGW*:*)- echo ${UNAME_MACHINE}-pc-mingw32- exit ;;- i*:windows32*:*)- # uname -m includes "-pc" on this system.- echo ${UNAME_MACHINE}-mingw32- exit ;;- i*:PW*:*)- echo ${UNAME_MACHINE}-pc-pw32- exit ;;- x86:Interix*:[3456]*)- echo i586-pc-interix${UNAME_RELEASE}- exit ;;- EM64T:Interix*:[3456]*)- echo x86_64-unknown-interix${UNAME_RELEASE}- exit ;;- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)- echo i${UNAME_MACHINE}-pc-mks- exit ;;- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)- # How do we know it's Interix rather than the generic POSIX subsystem?- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we- # UNAME_MACHINE based on the output of uname instead of i386?- echo i586-pc-interix- exit ;;- i*:UWIN*:*)- echo ${UNAME_MACHINE}-pc-uwin- exit ;;- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)- echo x86_64-unknown-cygwin- exit ;;- p*:CYGWIN*:*)- echo powerpcle-unknown-cygwin- exit ;;- prep*:SunOS:5.*:*)- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`- exit ;;- *:GNU:*:*)- # the GNU system- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`- exit ;;- *:GNU/*:*:*)- # other systems with GNU libc and userland- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu- exit ;;- i*86:Minix:*:*)- echo ${UNAME_MACHINE}-pc-minix- exit ;;- arm*:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- avr32*:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- cris:Linux:*:*)- echo cris-axis-linux-gnu- exit ;;- crisv32:Linux:*:*)- echo crisv32-axis-linux-gnu- exit ;;- frv:Linux:*:*)- echo frv-unknown-linux-gnu- exit ;;- ia64:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- m32r*:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- m68*:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- mips:Linux:*:*)- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c- #undef CPU- #undef mips- #undef mipsel- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)- CPU=mipsel- #else- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)- CPU=mips- #else- CPU=- #endif- #endif-EOF- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '- /^CPU/{- s: ::g- p- }'`"- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }- ;;- mips64:Linux:*:*)- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c- #undef CPU- #undef mips64- #undef mips64el- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)- CPU=mips64el- #else- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)- CPU=mips64- #else- CPU=- #endif- #endif-EOF- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '- /^CPU/{- s: ::g- p- }'`"- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }- ;;- or32:Linux:*:*)- echo or32-unknown-linux-gnu- exit ;;- ppc:Linux:*:*)- echo powerpc-unknown-linux-gnu- exit ;;- ppc64:Linux:*:*)- echo powerpc64-unknown-linux-gnu- exit ;;- alpha:Linux:*:*)- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in- EV5) UNAME_MACHINE=alphaev5 ;;- EV56) UNAME_MACHINE=alphaev56 ;;- PCA56) UNAME_MACHINE=alphapca56 ;;- PCA57) UNAME_MACHINE=alphapca56 ;;- EV6) UNAME_MACHINE=alphaev6 ;;- EV67) UNAME_MACHINE=alphaev67 ;;- EV68*) UNAME_MACHINE=alphaev68 ;;- esac- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}- exit ;;- parisc:Linux:*:* | hppa:Linux:*:*)- # Look for CPU level- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in- PA7*) echo hppa1.1-unknown-linux-gnu ;;- PA8*) echo hppa2.0-unknown-linux-gnu ;;- *) echo hppa-unknown-linux-gnu ;;- esac- exit ;;- parisc64:Linux:*:* | hppa64:Linux:*:*)- echo hppa64-unknown-linux-gnu- exit ;;- s390:Linux:*:* | s390x:Linux:*:*)- echo ${UNAME_MACHINE}-ibm-linux- exit ;;- sh64*:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- sh*:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- sparc:Linux:*:* | sparc64:Linux:*:*)- echo ${UNAME_MACHINE}-unknown-linux-gnu- exit ;;- vax:Linux:*:*)- echo ${UNAME_MACHINE}-dec-linux-gnu- exit ;;- x86_64:Linux:*:*)- echo x86_64-unknown-linux-gnu- exit ;;- i*86:Linux:*:*)- # The BFD linker knows what the default object file format is, so- # first see if it will tell us. cd to the root directory to prevent- # problems with other programs or directories called `ld' in the path.- # Set LC_ALL=C to ensure ld outputs messages in English.- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \- | sed -ne '/supported targets:/!d- s/[ ][ ]*/ /g- s/.*supported targets: *//- s/ .*//- p'`- case "$ld_supported_targets" in- elf32-i386)- TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"- ;;- a.out-i386-linux)- echo "${UNAME_MACHINE}-pc-linux-gnuaout"- exit ;;- coff-i386)- echo "${UNAME_MACHINE}-pc-linux-gnucoff"- exit ;;- "")- # Either a pre-BFD a.out linker (linux-gnuoldld) or- # one that does not give us useful --help.- echo "${UNAME_MACHINE}-pc-linux-gnuoldld"- exit ;;- esac- # Determine whether the default compiler is a.out or elf- eval $set_cc_for_build- sed 's/^ //' << EOF >$dummy.c- #include <features.h>- #ifdef __ELF__- # ifdef __GLIBC__- # if __GLIBC__ >= 2- LIBC=gnu- # else- LIBC=gnulibc1- # endif- # else- LIBC=gnulibc1- # endif- #else- #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)- LIBC=gnu- #else- LIBC=gnuaout- #endif- #endif- #ifdef __dietlibc__- LIBC=dietlibc- #endif-EOF- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '- /^LIBC/{- s: ::g- p- }'`"- test x"${LIBC}" != x && {- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"- exit- }- test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }- ;;- i*86:DYNIX/ptx:4*:*)- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.- # earlier versions are messed up and put the nodename in both- # sysname and nodename.- echo i386-sequent-sysv4- exit ;;- i*86:UNIX_SV:4.2MP:2.*)- # Unixware is an offshoot of SVR4, but it has its own version- # number series starting with 2...- # I am not positive that other SVR4 systems won't match this,- # I just have to hope. -- rms.- # Use sysv4.2uw... so that sysv4* matches it.- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}- exit ;;- i*86:OS/2:*:*)- # If we were able to find `uname', then EMX Unix compatibility- # is probably installed.- echo ${UNAME_MACHINE}-pc-os2-emx- exit ;;- i*86:XTS-300:*:STOP)- echo ${UNAME_MACHINE}-unknown-stop- exit ;;- i*86:atheos:*:*)- echo ${UNAME_MACHINE}-unknown-atheos- exit ;;- i*86:syllable:*:*)- echo ${UNAME_MACHINE}-pc-syllable- exit ;;- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)- echo i386-unknown-lynxos${UNAME_RELEASE}- exit ;;- i*86:*DOS:*:*)- echo ${UNAME_MACHINE}-pc-msdosdjgpp- exit ;;- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}- else- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}- fi- exit ;;- i*86:*:5:[678]*)- # UnixWare 7.x, OpenUNIX and OpenServer 6.- case `/bin/uname -X | grep "^Machine"` in- *486*) UNAME_MACHINE=i486 ;;- *Pentium) UNAME_MACHINE=i586 ;;- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;- esac- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}- exit ;;- i*86:*:3.2:*)- if test -f /usr/options/cb.name; then- UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL- elif /bin/uname -X 2>/dev/null >/dev/null ; then- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \- && UNAME_MACHINE=i586- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \- && UNAME_MACHINE=i686- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \- && UNAME_MACHINE=i686- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL- else- echo ${UNAME_MACHINE}-pc-sysv32- fi- exit ;;- pc:*:*:*)- # Left here for compatibility:- # uname -m prints for DJGPP always 'pc', but it prints nothing about- # the processor, so we play safe by assuming i386.- echo i386-pc-msdosdjgpp- exit ;;- Intel:Mach:3*:*)- echo i386-pc-mach3- exit ;;- paragon:*:*:*)- echo i860-intel-osf1- exit ;;- i860:*:4.*:*) # i860-SVR4- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4- else # Add other i860-SVR4 vendors below as they are discovered.- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4- fi- exit ;;- mini*:CTIX:SYS*5:*)- # "miniframe"- echo m68010-convergent-sysv- exit ;;- mc68k:UNIX:SYSTEM5:3.51m)- echo m68k-convergent-sysv- exit ;;- M680?0:D-NIX:5.3:*)- echo m68k-diab-dnix- exit ;;- M68*:*:R3V[5678]*:*)- test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)- OS_REL=''- test -r /etc/.relid \- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \- && { echo i486-ncr-sysv4; exit; } ;;- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)- echo m68k-unknown-lynxos${UNAME_RELEASE}- exit ;;- mc68030:UNIX_System_V:4.*:*)- echo m68k-atari-sysv4- exit ;;- TSUNAMI:LynxOS:2.*:*)- echo sparc-unknown-lynxos${UNAME_RELEASE}- exit ;;- rs6000:LynxOS:2.*:*)- echo rs6000-unknown-lynxos${UNAME_RELEASE}- exit ;;- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)- echo powerpc-unknown-lynxos${UNAME_RELEASE}- exit ;;- SM[BE]S:UNIX_SV:*:*)- echo mips-dde-sysv${UNAME_RELEASE}- exit ;;- RM*:ReliantUNIX-*:*:*)- echo mips-sni-sysv4- exit ;;- RM*:SINIX-*:*:*)- echo mips-sni-sysv4- exit ;;- *:SINIX-*:*:*)- if uname -p 2>/dev/null >/dev/null ; then- UNAME_MACHINE=`(uname -p) 2>/dev/null`- echo ${UNAME_MACHINE}-sni-sysv4- else- echo ns32k-sni-sysv- fi- exit ;;- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort- # says <Richard.M.Bartel@ccMail.Census.GOV>- echo i586-unisys-sysv4- exit ;;- *:UNIX_System_V:4*:FTX*)- # From Gerald Hewes <hewes@openmarket.com>.- # How about differentiating between stratus architectures? -djm- echo hppa1.1-stratus-sysv4- exit ;;- *:*:*:FTX*)- # From seanf@swdc.stratus.com.- echo i860-stratus-sysv4- exit ;;- i*86:VOS:*:*)- # From Paul.Green@stratus.com.- echo ${UNAME_MACHINE}-stratus-vos- exit ;;- *:VOS:*:*)- # From Paul.Green@stratus.com.- echo hppa1.1-stratus-vos- exit ;;- mc68*:A/UX:*:*)- echo m68k-apple-aux${UNAME_RELEASE}- exit ;;- news*:NEWS-OS:6*:*)- echo mips-sony-newsos6- exit ;;- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)- if [ -d /usr/nec ]; then- echo mips-nec-sysv${UNAME_RELEASE}- else- echo mips-unknown-sysv${UNAME_RELEASE}- fi- exit ;;- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.- echo powerpc-be-beos- exit ;;- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.- echo powerpc-apple-beos- exit ;;- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.- echo i586-pc-beos- exit ;;- SX-4:SUPER-UX:*:*)- echo sx4-nec-superux${UNAME_RELEASE}- exit ;;- SX-5:SUPER-UX:*:*)- echo sx5-nec-superux${UNAME_RELEASE}- exit ;;- SX-6:SUPER-UX:*:*)- echo sx6-nec-superux${UNAME_RELEASE}- exit ;;- Power*:Rhapsody:*:*)- echo powerpc-apple-rhapsody${UNAME_RELEASE}- exit ;;- *:Rhapsody:*:*)- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}- exit ;;- *:Darwin:*:*)- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown- case $UNAME_PROCESSOR in- unknown) UNAME_PROCESSOR=powerpc ;;- esac- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}- exit ;;- *:procnto*:*:* | *:QNX:[0123456789]*:*)- UNAME_PROCESSOR=`uname -p`- if test "$UNAME_PROCESSOR" = "x86"; then- UNAME_PROCESSOR=i386- UNAME_MACHINE=pc- fi- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}- exit ;;- *:QNX:*:4*)- echo i386-pc-qnx- exit ;;- NSE-?:NONSTOP_KERNEL:*:*)- echo nse-tandem-nsk${UNAME_RELEASE}- exit ;;- NSR-?:NONSTOP_KERNEL:*:*)- echo nsr-tandem-nsk${UNAME_RELEASE}- exit ;;- *:NonStop-UX:*:*)- echo mips-compaq-nonstopux- exit ;;- BS2000:POSIX*:*:*)- echo bs2000-siemens-sysv- exit ;;- DS/*:UNIX_System_V:*:*)- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}- exit ;;- *:Plan9:*:*)- # "uname -m" is not consistent, so use $cputype instead. 386- # is converted to i386 for consistency with other x86- # operating systems.- if test "$cputype" = "386"; then- UNAME_MACHINE=i386- else- UNAME_MACHINE="$cputype"- fi- echo ${UNAME_MACHINE}-unknown-plan9- exit ;;- *:TOPS-10:*:*)- echo pdp10-unknown-tops10- exit ;;- *:TENEX:*:*)- echo pdp10-unknown-tenex- exit ;;- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)- echo pdp10-dec-tops20- exit ;;- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)- echo pdp10-xkl-tops20- exit ;;- *:TOPS-20:*:*)- echo pdp10-unknown-tops20- exit ;;- *:ITS:*:*)- echo pdp10-unknown-its- exit ;;- SEI:*:*:SEIUX)- echo mips-sei-seiux${UNAME_RELEASE}- exit ;;- *:DragonFly:*:*)- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`- exit ;;- *:*VMS:*:*)- UNAME_MACHINE=`(uname -p) 2>/dev/null`- case "${UNAME_MACHINE}" in- A*) echo alpha-dec-vms ; exit ;;- I*) echo ia64-dec-vms ; exit ;;- V*) echo vax-dec-vms ; exit ;;- esac ;;- *:XENIX:*:SysV)- echo i386-pc-xenix- exit ;;- i*86:skyos:*:*)- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'- exit ;;- i*86:rdos:*:*)- echo ${UNAME_MACHINE}-pc-rdos- exit ;;-esac--#echo '(No uname command or uname output not recognized.)' 1>&2-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2--eval $set_cc_for_build-cat >$dummy.c <<EOF-#ifdef _SEQUENT_-# include <sys/types.h>-# include <sys/utsname.h>-#endif-main ()-{-#if defined (sony)-#if defined (MIPSEB)- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,- I don't know.... */- printf ("mips-sony-bsd\n"); exit (0);-#else-#include <sys/param.h>- printf ("m68k-sony-newsos%s\n",-#ifdef NEWSOS4- "4"-#else- ""-#endif- ); exit (0);-#endif-#endif--#if defined (__arm) && defined (__acorn) && defined (__unix)- printf ("arm-acorn-riscix\n"); exit (0);-#endif--#if defined (hp300) && !defined (hpux)- printf ("m68k-hp-bsd\n"); exit (0);-#endif--#if defined (NeXT)-#if !defined (__ARCHITECTURE__)-#define __ARCHITECTURE__ "m68k"-#endif- int version;- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;- if (version < 4)- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);- else- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);- exit (0);-#endif--#if defined (MULTIMAX) || defined (n16)-#if defined (UMAXV)- printf ("ns32k-encore-sysv\n"); exit (0);-#else-#if defined (CMU)- printf ("ns32k-encore-mach\n"); exit (0);-#else- printf ("ns32k-encore-bsd\n"); exit (0);-#endif-#endif-#endif--#if defined (__386BSD__)- printf ("i386-pc-bsd\n"); exit (0);-#endif--#if defined (sequent)-#if defined (i386)- printf ("i386-sequent-dynix\n"); exit (0);-#endif-#if defined (ns32000)- printf ("ns32k-sequent-dynix\n"); exit (0);-#endif-#endif--#if defined (_SEQUENT_)- struct utsname un;-- uname(&un);-- if (strncmp(un.version, "V2", 2) == 0) {- printf ("i386-sequent-ptx2\n"); exit (0);- }- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */- printf ("i386-sequent-ptx1\n"); exit (0);- }- printf ("i386-sequent-ptx\n"); exit (0);--#endif--#if defined (vax)-# if !defined (ultrix)-# include <sys/param.h>-# if defined (BSD)-# if BSD == 43- printf ("vax-dec-bsd4.3\n"); exit (0);-# else-# if BSD == 199006- printf ("vax-dec-bsd4.3reno\n"); exit (0);-# else- printf ("vax-dec-bsd\n"); exit (0);-# endif-# endif-# else- printf ("vax-dec-bsd\n"); exit (0);-# endif-# else- printf ("vax-dec-ultrix\n"); exit (0);-# endif-#endif--#if defined (alliant) && defined (i860)- printf ("i860-alliant-bsd\n"); exit (0);-#endif-- exit (1);-}-EOF--$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&- { echo "$SYSTEM_NAME"; exit; }--# Apollos put the system type in the environment.--test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }--# Convex versions that predate uname can use getsysinfo(1)--if [ -x /usr/convex/getsysinfo ]-then- case `getsysinfo -f cpu_type` in- c1*)- echo c1-convex-bsd- exit ;;- c2*)- if getsysinfo -f scalar_acc- then echo c32-convex-bsd- else echo c2-convex-bsd- fi- exit ;;- c34*)- echo c34-convex-bsd- exit ;;- c38*)- echo c38-convex-bsd- exit ;;- c4*)- echo c4-convex-bsd- exit ;;- esac-fi--cat >&2 <<EOF-$0: unable to guess system type--This script, last modified $timestamp, has failed to recognize-the operating system you are using. It is advised that you-download the most up to date version of the config scripts from-- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess-and- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub--If the version you run ($0) is already up to date, please-send the following data and any information you think might be-pertinent to <config-patches@gnu.org> in order to provide the needed-information to handle your system.--config.guess timestamp = $timestamp--uname -m = `(uname -m) 2>/dev/null || echo unknown`-uname -r = `(uname -r) 2>/dev/null || echo unknown`-uname -s = `(uname -s) 2>/dev/null || echo unknown`-uname -v = `(uname -v) 2>/dev/null || echo unknown`--/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`--hostinfo = `(hostinfo) 2>/dev/null`-/bin/universe = `(/bin/universe) 2>/dev/null`-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`-/bin/arch = `(/bin/arch) 2>/dev/null`-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`--UNAME_MACHINE = ${UNAME_MACHINE}-UNAME_RELEASE = ${UNAME_RELEASE}-UNAME_SYSTEM = ${UNAME_SYSTEM}-UNAME_VERSION = ${UNAME_VERSION}-EOF--exit 1--# Local variables:-# eval: (add-hook 'write-file-hooks 'time-stamp)-# time-stamp-start: "timestamp='"-# time-stamp-format: "%:y-%02m-%02d"-# time-stamp-end: "'"-# End:
@@ -1,1608 +0,0 @@-#! /bin/sh-# Configuration validation subroutine script.-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,-# Inc.--timestamp='2006-07-02'--# This file is (in principle) common to ALL GNU software.-# The presence of a machine in this file suggests that SOME GNU software-# can handle that machine. It does not imply ALL GNU software can.-#-# This file is free software; you can redistribute it and/or modify-# it under the terms of the GNU General Public License as published by-# the Free Software Foundation; either version 2 of the License, or-# (at your option) any later version.-#-# This program is distributed in the hope that it will be useful,-# but WITHOUT ANY WARRANTY; without even the implied warranty of-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-# GNU General Public License for more details.-#-# You should have received a copy of the GNU General Public License-# along with this program; if not, write to the Free Software-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA-# 02110-1301, USA.-#-# As a special exception to the GNU General Public License, if you-# distribute this file as part of a program that contains a-# configuration script generated by Autoconf, you may include it under-# the same distribution terms that you use for the rest of that program.---# Please send patches to <config-patches@gnu.org>. Submit a context-# diff and a properly formatted ChangeLog entry.-#-# Configuration subroutine to validate and canonicalize a configuration type.-# Supply the specified configuration type as an argument.-# If it is invalid, we print an error message on stderr and exit with code 1.-# Otherwise, we print the canonical config type on stdout and succeed.--# This file is supposed to be the same for all GNU packages-# and recognize all the CPU types, system types and aliases-# that are meaningful with *any* GNU software.-# Each package is responsible for reporting which valid configurations-# it does not support. The user should be able to distinguish-# a failure to support a valid configuration from a meaningless-# configuration.--# The goal of this file is to map all the various variations of a given-# machine specification into a single specification in the form:-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM-# or in some cases, the newer four-part form:-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM-# It is wrong to echo any other type of specification.--me=`echo "$0" | sed -e 's,.*/,,'`--usage="\-Usage: $0 [OPTION] CPU-MFR-OPSYS- $0 [OPTION] ALIAS--Canonicalize a configuration name.--Operation modes:- -h, --help print this help, then exit- -t, --time-stamp print date of last modification, then exit- -v, --version print version number, then exit--Report bugs and patches to <config-patches@gnu.org>."--version="\-GNU config.sub ($timestamp)--Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005-Free Software Foundation, Inc.--This is free software; see the source for copying conditions. There is NO-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."--help="-Try \`$me --help' for more information."--# Parse command line-while test $# -gt 0 ; do- case $1 in- --time-stamp | --time* | -t )- echo "$timestamp" ; exit ;;- --version | -v )- echo "$version" ; exit ;;- --help | --h* | -h )- echo "$usage"; exit ;;- -- ) # Stop option processing- shift; break ;;- - ) # Use stdin as input.- break ;;- -* )- echo "$me: invalid option $1$help"- exit 1 ;;-- *local*)- # First pass through any local machine types.- echo $1- exit ;;-- * )- break ;;- esac-done--case $# in- 0) echo "$me: missing argument$help" >&2- exit 1;;- 1) ;;- *) echo "$me: too many arguments$help" >&2- exit 1;;-esac--# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).-# Here we must recognize all the valid KERNEL-OS combinations.-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`-case $maybe_os in- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \- storm-chaos* | os2-emx* | rtmk-nova*)- os=-$maybe_os- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`- ;;- *)- basic_machine=`echo $1 | sed 's/-[^-]*$//'`- if [ $basic_machine != $1 ]- then os=`echo $1 | sed 's/.*-/-/'`- else os=; fi- ;;-esac--### Let's recognize common machines as not being operating systems so-### that things like config.sub decstation-3100 work. We also-### recognize some manufacturers as not being operating systems, so we-### can provide default operating systems below.-case $os in- -sun*os*)- # Prevent following clause from handling this invalid input.- ;;- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \- -apple | -axis | -knuth | -cray)- os=- basic_machine=$1- ;;- -sim | -cisco | -oki | -wec | -winbond)- os=- basic_machine=$1- ;;- -scout)- ;;- -wrs)- os=-vxworks- basic_machine=$1- ;;- -chorusos*)- os=-chorusos- basic_machine=$1- ;;- -chorusrdb)- os=-chorusrdb- basic_machine=$1- ;;- -hiux*)- os=-hiuxwe2- ;;- -sco6)- os=-sco5v6- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -sco5)- os=-sco3.2v5- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -sco4)- os=-sco3.2v4- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -sco3.2.[4-9]*)- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -sco3.2v[4-9]*)- # Don't forget version if it is 3.2v4 or newer.- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -sco5v6*)- # Don't forget version if it is 3.2v4 or newer.- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -sco*)- os=-sco3.2v2- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -udk*)- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -isc)- os=-isc2.2- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -clix*)- basic_machine=clipper-intergraph- ;;- -isc*)- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`- ;;- -lynx*)- os=-lynxos- ;;- -ptx*)- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`- ;;- -windowsnt*)- os=`echo $os | sed -e 's/windowsnt/winnt/'`- ;;- -psos*)- os=-psos- ;;- -mint | -mint[0-9]*)- basic_machine=m68k-atari- os=-mint- ;;-esac--# Decode aliases for certain CPU-COMPANY combinations.-case $basic_machine in- # Recognize the basic CPU types without company name.- # Some are omitted here because they have special meanings below.- 1750a | 580 \- | a29k \- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \- | am33_2.0 \- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \- | bfin \- | c4x | clipper \- | d10v | d30v | dlx | dsp16xx \- | fr30 | frv \- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \- | i370 | i860 | i960 | ia64 \- | ip2k | iq2000 \- | m32c | m32r | m32rle | m68000 | m68k | m88k \- | maxq | mb | microblaze | mcore \- | mips | mipsbe | mipseb | mipsel | mipsle \- | mips16 \- | mips64 | mips64el \- | mips64vr | mips64vrel \- | mips64orion | mips64orionel \- | mips64vr4100 | mips64vr4100el \- | mips64vr4300 | mips64vr4300el \- | mips64vr5000 | mips64vr5000el \- | mips64vr5900 | mips64vr5900el \- | mipsisa32 | mipsisa32el \- | mipsisa32r2 | mipsisa32r2el \- | mipsisa64 | mipsisa64el \- | mipsisa64r2 | mipsisa64r2el \- | mipsisa64sb1 | mipsisa64sb1el \- | mipsisa64sr71k | mipsisa64sr71kel \- | mipstx39 | mipstx39el \- | mn10200 | mn10300 \- | mt \- | msp430 \- | nios | nios2 \- | ns16k | ns32k \- | or32 \- | pdp10 | pdp11 | pj | pjl \- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \- | pyramid \- | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \- | sh64 | sh64le \- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \- | spu | strongarm \- | tahoe | thumb | tic4x | tic80 | tron \- | v850 | v850e \- | we32k \- | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \- | z8k)- basic_machine=$basic_machine-unknown- ;;- m6811 | m68hc11 | m6812 | m68hc12)- # Motorola 68HC11/12.- basic_machine=$basic_machine-unknown- os=-none- ;;- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)- ;;- ms1)- basic_machine=mt-unknown- ;;-- # We use `pc' rather than `unknown'- # because (1) that's what they normally are, and- # (2) the word "unknown" tends to confuse beginning users.- i*86 | x86_64)- basic_machine=$basic_machine-pc- ;;- # Object if more than one company name word.- *-*-*)- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2- exit 1- ;;- # Recognize the basic CPU types with company name.- 580-* \- | a29k-* \- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \- | avr-* | avr32-* \- | bfin-* | bs2000-* \- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \- | clipper-* | craynv-* | cydra-* \- | d10v-* | d30v-* | dlx-* \- | elxsi-* \- | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \- | h8300-* | h8500-* \- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \- | i*86-* | i860-* | i960-* | ia64-* \- | ip2k-* | iq2000-* \- | m32c-* | m32r-* | m32rle-* \- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \- | m88110-* | m88k-* | maxq-* | mcore-* \- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \- | mips16-* \- | mips64-* | mips64el-* \- | mips64vr-* | mips64vrel-* \- | mips64orion-* | mips64orionel-* \- | mips64vr4100-* | mips64vr4100el-* \- | mips64vr4300-* | mips64vr4300el-* \- | mips64vr5000-* | mips64vr5000el-* \- | mips64vr5900-* | mips64vr5900el-* \- | mipsisa32-* | mipsisa32el-* \- | mipsisa32r2-* | mipsisa32r2el-* \- | mipsisa64-* | mipsisa64el-* \- | mipsisa64r2-* | mipsisa64r2el-* \- | mipsisa64sb1-* | mipsisa64sb1el-* \- | mipsisa64sr71k-* | mipsisa64sr71kel-* \- | mipstx39-* | mipstx39el-* \- | mmix-* \- | mt-* \- | msp430-* \- | nios-* | nios2-* \- | none-* | np1-* | ns16k-* | ns32k-* \- | orion-* \- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \- | pyramid-* \- | romp-* | rs6000-* \- | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \- | sparclite-* \- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \- | tahoe-* | thumb-* \- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \- | tron-* \- | v850-* | v850e-* | vax-* \- | we32k-* \- | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \- | xstormy16-* | xtensa-* \- | ymp-* \- | z8k-*)- ;;- # Recognize the various machine names and aliases which stand- # for a CPU type and a company and sometimes even an OS.- 386bsd)- basic_machine=i386-unknown- os=-bsd- ;;- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)- basic_machine=m68000-att- ;;- 3b*)- basic_machine=we32k-att- ;;- a29khif)- basic_machine=a29k-amd- os=-udi- ;;- abacus)- basic_machine=abacus-unknown- ;;- adobe68k)- basic_machine=m68010-adobe- os=-scout- ;;- alliant | fx80)- basic_machine=fx80-alliant- ;;- altos | altos3068)- basic_machine=m68k-altos- ;;- am29k)- basic_machine=a29k-none- os=-bsd- ;;- amd64)- basic_machine=x86_64-pc- ;;- amd64-*)- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- amdahl)- basic_machine=580-amdahl- os=-sysv- ;;- amiga | amiga-*)- basic_machine=m68k-unknown- ;;- amigaos | amigados)- basic_machine=m68k-unknown- os=-amigaos- ;;- amigaunix | amix)- basic_machine=m68k-unknown- os=-sysv4- ;;- apollo68)- basic_machine=m68k-apollo- os=-sysv- ;;- apollo68bsd)- basic_machine=m68k-apollo- os=-bsd- ;;- aux)- basic_machine=m68k-apple- os=-aux- ;;- balance)- basic_machine=ns32k-sequent- os=-dynix- ;;- c90)- basic_machine=c90-cray- os=-unicos- ;;- convex-c1)- basic_machine=c1-convex- os=-bsd- ;;- convex-c2)- basic_machine=c2-convex- os=-bsd- ;;- convex-c32)- basic_machine=c32-convex- os=-bsd- ;;- convex-c34)- basic_machine=c34-convex- os=-bsd- ;;- convex-c38)- basic_machine=c38-convex- os=-bsd- ;;- cray | j90)- basic_machine=j90-cray- os=-unicos- ;;- craynv)- basic_machine=craynv-cray- os=-unicosmp- ;;- cr16c)- basic_machine=cr16c-unknown- os=-elf- ;;- crds | unos)- basic_machine=m68k-crds- ;;- crisv32 | crisv32-* | etraxfs*)- basic_machine=crisv32-axis- ;;- cris | cris-* | etrax*)- basic_machine=cris-axis- ;;- crx)- basic_machine=crx-unknown- os=-elf- ;;- da30 | da30-*)- basic_machine=m68k-da30- ;;- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)- basic_machine=mips-dec- ;;- decsystem10* | dec10*)- basic_machine=pdp10-dec- os=-tops10- ;;- decsystem20* | dec20*)- basic_machine=pdp10-dec- os=-tops20- ;;- delta | 3300 | motorola-3300 | motorola-delta \- | 3300-motorola | delta-motorola)- basic_machine=m68k-motorola- ;;- delta88)- basic_machine=m88k-motorola- os=-sysv3- ;;- djgpp)- basic_machine=i586-pc- os=-msdosdjgpp- ;;- dpx20 | dpx20-*)- basic_machine=rs6000-bull- os=-bosx- ;;- dpx2* | dpx2*-bull)- basic_machine=m68k-bull- os=-sysv3- ;;- ebmon29k)- basic_machine=a29k-amd- os=-ebmon- ;;- elxsi)- basic_machine=elxsi-elxsi- os=-bsd- ;;- encore | umax | mmax)- basic_machine=ns32k-encore- ;;- es1800 | OSE68k | ose68k | ose | OSE)- basic_machine=m68k-ericsson- os=-ose- ;;- fx2800)- basic_machine=i860-alliant- ;;- genix)- basic_machine=ns32k-ns- ;;- gmicro)- basic_machine=tron-gmicro- os=-sysv- ;;- go32)- basic_machine=i386-pc- os=-go32- ;;- h3050r* | hiux*)- basic_machine=hppa1.1-hitachi- os=-hiuxwe2- ;;- h8300hms)- basic_machine=h8300-hitachi- os=-hms- ;;- h8300xray)- basic_machine=h8300-hitachi- os=-xray- ;;- h8500hms)- basic_machine=h8500-hitachi- os=-hms- ;;- harris)- basic_machine=m88k-harris- os=-sysv3- ;;- hp300-*)- basic_machine=m68k-hp- ;;- hp300bsd)- basic_machine=m68k-hp- os=-bsd- ;;- hp300hpux)- basic_machine=m68k-hp- os=-hpux- ;;- hp3k9[0-9][0-9] | hp9[0-9][0-9])- basic_machine=hppa1.0-hp- ;;- hp9k2[0-9][0-9] | hp9k31[0-9])- basic_machine=m68000-hp- ;;- hp9k3[2-9][0-9])- basic_machine=m68k-hp- ;;- hp9k6[0-9][0-9] | hp6[0-9][0-9])- basic_machine=hppa1.0-hp- ;;- hp9k7[0-79][0-9] | hp7[0-79][0-9])- basic_machine=hppa1.1-hp- ;;- hp9k78[0-9] | hp78[0-9])- # FIXME: really hppa2.0-hp- basic_machine=hppa1.1-hp- ;;- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)- # FIXME: really hppa2.0-hp- basic_machine=hppa1.1-hp- ;;- hp9k8[0-9][13679] | hp8[0-9][13679])- basic_machine=hppa1.1-hp- ;;- hp9k8[0-9][0-9] | hp8[0-9][0-9])- basic_machine=hppa1.0-hp- ;;- hppa-next)- os=-nextstep3- ;;- hppaosf)- basic_machine=hppa1.1-hp- os=-osf- ;;- hppro)- basic_machine=hppa1.1-hp- os=-proelf- ;;- i370-ibm* | ibm*)- basic_machine=i370-ibm- ;;-# I'm not sure what "Sysv32" means. Should this be sysv3.2?- i*86v32)- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`- os=-sysv32- ;;- i*86v4*)- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`- os=-sysv4- ;;- i*86v)- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`- os=-sysv- ;;- i*86sol2)- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`- os=-solaris2- ;;- i386mach)- basic_machine=i386-mach- os=-mach- ;;- i386-vsta | vsta)- basic_machine=i386-unknown- os=-vsta- ;;- iris | iris4d)- basic_machine=mips-sgi- case $os in- -irix*)- ;;- *)- os=-irix4- ;;- esac- ;;- isi68 | isi)- basic_machine=m68k-isi- os=-sysv- ;;- m88k-omron*)- basic_machine=m88k-omron- ;;- magnum | m3230)- basic_machine=mips-mips- os=-sysv- ;;- merlin)- basic_machine=ns32k-utek- os=-sysv- ;;- mingw32)- basic_machine=i386-pc- os=-mingw32- ;;- miniframe)- basic_machine=m68000-convergent- ;;- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)- basic_machine=m68k-atari- os=-mint- ;;- mips3*-*)- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`- ;;- mips3*)- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown- ;;- monitor)- basic_machine=m68k-rom68k- os=-coff- ;;- morphos)- basic_machine=powerpc-unknown- os=-morphos- ;;- msdos)- basic_machine=i386-pc- os=-msdos- ;;- ms1-*)- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`- ;;- mvs)- basic_machine=i370-ibm- os=-mvs- ;;- ncr3000)- basic_machine=i486-ncr- os=-sysv4- ;;- netbsd386)- basic_machine=i386-unknown- os=-netbsd- ;;- netwinder)- basic_machine=armv4l-rebel- os=-linux- ;;- news | news700 | news800 | news900)- basic_machine=m68k-sony- os=-newsos- ;;- news1000)- basic_machine=m68030-sony- os=-newsos- ;;- news-3600 | risc-news)- basic_machine=mips-sony- os=-newsos- ;;- necv70)- basic_machine=v70-nec- os=-sysv- ;;- next | m*-next )- basic_machine=m68k-next- case $os in- -nextstep* )- ;;- -ns2*)- os=-nextstep2- ;;- *)- os=-nextstep3- ;;- esac- ;;- nh3000)- basic_machine=m68k-harris- os=-cxux- ;;- nh[45]000)- basic_machine=m88k-harris- os=-cxux- ;;- nindy960)- basic_machine=i960-intel- os=-nindy- ;;- mon960)- basic_machine=i960-intel- os=-mon960- ;;- nonstopux)- basic_machine=mips-compaq- os=-nonstopux- ;;- np1)- basic_machine=np1-gould- ;;- nsr-tandem)- basic_machine=nsr-tandem- ;;- op50n-* | op60c-*)- basic_machine=hppa1.1-oki- os=-proelf- ;;- openrisc | openrisc-*)- basic_machine=or32-unknown- ;;- os400)- basic_machine=powerpc-ibm- os=-os400- ;;- OSE68000 | ose68000)- basic_machine=m68000-ericsson- os=-ose- ;;- os68k)- basic_machine=m68k-none- os=-os68k- ;;- pa-hitachi)- basic_machine=hppa1.1-hitachi- os=-hiuxwe2- ;;- paragon)- basic_machine=i860-intel- os=-osf- ;;- pbd)- basic_machine=sparc-tti- ;;- pbb)- basic_machine=m68k-tti- ;;- pc532 | pc532-*)- basic_machine=ns32k-pc532- ;;- pc98)- basic_machine=i386-pc- ;;- pc98-*)- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- pentium | p5 | k5 | k6 | nexgen | viac3)- basic_machine=i586-pc- ;;- pentiumpro | p6 | 6x86 | athlon | athlon_*)- basic_machine=i686-pc- ;;- pentiumii | pentium2 | pentiumiii | pentium3)- basic_machine=i686-pc- ;;- pentium4)- basic_machine=i786-pc- ;;- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- pentiumpro-* | p6-* | 6x86-* | athlon-*)- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- pentium4-*)- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- pn)- basic_machine=pn-gould- ;;- power) basic_machine=power-ibm- ;;- ppc) basic_machine=powerpc-unknown- ;;- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- ppcle | powerpclittle | ppc-le | powerpc-little)- basic_machine=powerpcle-unknown- ;;- ppcle-* | powerpclittle-*)- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- ppc64) basic_machine=powerpc64-unknown- ;;- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- ppc64le | powerpc64little | ppc64-le | powerpc64-little)- basic_machine=powerpc64le-unknown- ;;- ppc64le-* | powerpc64little-*)- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`- ;;- ps2)- basic_machine=i386-ibm- ;;- pw32)- basic_machine=i586-unknown- os=-pw32- ;;- rdos)- basic_machine=i386-pc- os=-rdos- ;;- rom68k)- basic_machine=m68k-rom68k- os=-coff- ;;- rm[46]00)- basic_machine=mips-siemens- ;;- rtpc | rtpc-*)- basic_machine=romp-ibm- ;;- s390 | s390-*)- basic_machine=s390-ibm- ;;- s390x | s390x-*)- basic_machine=s390x-ibm- ;;- sa29200)- basic_machine=a29k-amd- os=-udi- ;;- sb1)- basic_machine=mipsisa64sb1-unknown- ;;- sb1el)- basic_machine=mipsisa64sb1el-unknown- ;;- sei)- basic_machine=mips-sei- os=-seiux- ;;- sequent)- basic_machine=i386-sequent- ;;- sh)- basic_machine=sh-hitachi- os=-hms- ;;- sh64)- basic_machine=sh64-unknown- ;;- sparclite-wrs | simso-wrs)- basic_machine=sparclite-wrs- os=-vxworks- ;;- sps7)- basic_machine=m68k-bull- os=-sysv2- ;;- spur)- basic_machine=spur-unknown- ;;- st2000)- basic_machine=m68k-tandem- ;;- stratus)- basic_machine=i860-stratus- os=-sysv4- ;;- sun2)- basic_machine=m68000-sun- ;;- sun2os3)- basic_machine=m68000-sun- os=-sunos3- ;;- sun2os4)- basic_machine=m68000-sun- os=-sunos4- ;;- sun3os3)- basic_machine=m68k-sun- os=-sunos3- ;;- sun3os4)- basic_machine=m68k-sun- os=-sunos4- ;;- sun4os3)- basic_machine=sparc-sun- os=-sunos3- ;;- sun4os4)- basic_machine=sparc-sun- os=-sunos4- ;;- sun4sol2)- basic_machine=sparc-sun- os=-solaris2- ;;- sun3 | sun3-*)- basic_machine=m68k-sun- ;;- sun4)- basic_machine=sparc-sun- ;;- sun386 | sun386i | roadrunner)- basic_machine=i386-sun- ;;- sv1)- basic_machine=sv1-cray- os=-unicos- ;;- symmetry)- basic_machine=i386-sequent- os=-dynix- ;;- t3e)- basic_machine=alphaev5-cray- os=-unicos- ;;- t90)- basic_machine=t90-cray- os=-unicos- ;;- tic54x | c54x*)- basic_machine=tic54x-unknown- os=-coff- ;;- tic55x | c55x*)- basic_machine=tic55x-unknown- os=-coff- ;;- tic6x | c6x*)- basic_machine=tic6x-unknown- os=-coff- ;;- tx39)- basic_machine=mipstx39-unknown- ;;- tx39el)- basic_machine=mipstx39el-unknown- ;;- toad1)- basic_machine=pdp10-xkl- os=-tops20- ;;- tower | tower-32)- basic_machine=m68k-ncr- ;;- tpf)- basic_machine=s390x-ibm- os=-tpf- ;;- udi29k)- basic_machine=a29k-amd- os=-udi- ;;- ultra3)- basic_machine=a29k-nyu- os=-sym1- ;;- v810 | necv810)- basic_machine=v810-nec- os=-none- ;;- vaxv)- basic_machine=vax-dec- os=-sysv- ;;- vms)- basic_machine=vax-dec- os=-vms- ;;- vpp*|vx|vx-*)- basic_machine=f301-fujitsu- ;;- vxworks960)- basic_machine=i960-wrs- os=-vxworks- ;;- vxworks68)- basic_machine=m68k-wrs- os=-vxworks- ;;- vxworks29k)- basic_machine=a29k-wrs- os=-vxworks- ;;- w65*)- basic_machine=w65-wdc- os=-none- ;;- w89k-*)- basic_machine=hppa1.1-winbond- os=-proelf- ;;- xbox)- basic_machine=i686-pc- os=-mingw32- ;;- xps | xps100)- basic_machine=xps100-honeywell- ;;- ymp)- basic_machine=ymp-cray- os=-unicos- ;;- z8k-*-coff)- basic_machine=z8k-unknown- os=-sim- ;;- none)- basic_machine=none-none- os=-none- ;;--# Here we handle the default manufacturer of certain CPU types. It is in-# some cases the only manufacturer, in others, it is the most popular.- w89k)- basic_machine=hppa1.1-winbond- ;;- op50n)- basic_machine=hppa1.1-oki- ;;- op60c)- basic_machine=hppa1.1-oki- ;;- romp)- basic_machine=romp-ibm- ;;- mmix)- basic_machine=mmix-knuth- ;;- rs6000)- basic_machine=rs6000-ibm- ;;- vax)- basic_machine=vax-dec- ;;- pdp10)- # there are many clones, so DEC is not a safe bet- basic_machine=pdp10-unknown- ;;- pdp11)- basic_machine=pdp11-dec- ;;- we32k)- basic_machine=we32k-att- ;;- sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)- basic_machine=sh-unknown- ;;- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)- basic_machine=sparc-sun- ;;- cydra)- basic_machine=cydra-cydrome- ;;- orion)- basic_machine=orion-highlevel- ;;- orion105)- basic_machine=clipper-highlevel- ;;- mac | mpw | mac-mpw)- basic_machine=m68k-apple- ;;- pmac | pmac-mpw)- basic_machine=powerpc-apple- ;;- *-unknown)- # Make sure to match an already-canonicalized machine name.- ;;- *)- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2- exit 1- ;;-esac--# Here we canonicalize certain aliases for manufacturers.-case $basic_machine in- *-digital*)- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`- ;;- *-commodore*)- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`- ;;- *)- ;;-esac--# Decode manufacturer-specific aliases for certain operating systems.--if [ x"$os" != x"" ]-then-case $os in- # First match some system type aliases- # that might get confused with valid system types.- # -solaris* is a basic system type, with this one exception.- -solaris1 | -solaris1.*)- os=`echo $os | sed -e 's|solaris1|sunos4|'`- ;;- -solaris)- os=-solaris2- ;;- -svr4*)- os=-sysv4- ;;- -unixware*)- os=-sysv4.2uw- ;;- -gnu/linux*)- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`- ;;- # First accept the basic system types.- # The portable systems comes first.- # Each alternative MUST END IN A *, to match a version number.- # -sysv* is not here because it comes later, after sysvr4.- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \- | -aos* \- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \- | -openbsd* | -solidbsd* \- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \- | -chorusos* | -chorusrdb* \- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \- | -uxpv* | -beos* | -mpeix* | -udk* \- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \- | -skyos* | -haiku* | -rdos* | -toppers*)- # Remember, each alternative MUST END IN *, to match a version number.- ;;- -qnx*)- case $basic_machine in- x86-* | i*86-*)- ;;- *)- os=-nto$os- ;;- esac- ;;- -nto-qnx*)- ;;- -nto*)- os=`echo $os | sed -e 's|nto|nto-qnx|'`- ;;- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)- ;;- -mac*)- os=`echo $os | sed -e 's|mac|macos|'`- ;;- -linux-dietlibc)- os=-linux-dietlibc- ;;- -linux*)- os=`echo $os | sed -e 's|linux|linux-gnu|'`- ;;- -sunos5*)- os=`echo $os | sed -e 's|sunos5|solaris2|'`- ;;- -sunos6*)- os=`echo $os | sed -e 's|sunos6|solaris3|'`- ;;- -opened*)- os=-openedition- ;;- -os400*)- os=-os400- ;;- -wince*)- os=-wince- ;;- -osfrose*)- os=-osfrose- ;;- -osf*)- os=-osf- ;;- -utek*)- os=-bsd- ;;- -dynix*)- os=-bsd- ;;- -acis*)- os=-aos- ;;- -atheos*)- os=-atheos- ;;- -syllable*)- os=-syllable- ;;- -386bsd)- os=-bsd- ;;- -ctix* | -uts*)- os=-sysv- ;;- -nova*)- os=-rtmk-nova- ;;- -ns2 )- os=-nextstep2- ;;- -nsk*)- os=-nsk- ;;- # Preserve the version number of sinix5.- -sinix5.*)- os=`echo $os | sed -e 's|sinix|sysv|'`- ;;- -sinix*)- os=-sysv4- ;;- -tpf*)- os=-tpf- ;;- -triton*)- os=-sysv3- ;;- -oss*)- os=-sysv3- ;;- -svr4)- os=-sysv4- ;;- -svr3)- os=-sysv3- ;;- -sysvr4)- os=-sysv4- ;;- # This must come after -sysvr4.- -sysv*)- ;;- -ose*)- os=-ose- ;;- -es1800*)- os=-ose- ;;- -xenix)- os=-xenix- ;;- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)- os=-mint- ;;- -aros*)- os=-aros- ;;- -kaos*)- os=-kaos- ;;- -zvmoe)- os=-zvmoe- ;;- -none)- ;;- *)- # Get rid of the `-' at the beginning of $os.- os=`echo $os | sed 's/[^-]*-//'`- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2- exit 1- ;;-esac-else--# Here we handle the default operating systems that come with various machines.-# The value should be what the vendor currently ships out the door with their-# machine or put another way, the most popular os provided with the machine.--# Note that if you're going to try to match "-MANUFACTURER" here (say,-# "-sun"), then you have to tell the case statement up towards the top-# that MANUFACTURER isn't an operating system. Otherwise, code above-# will signal an error saying that MANUFACTURER isn't an operating-# system, and we'll never get to this point.--case $basic_machine in- spu-*)- os=-elf- ;;- *-acorn)- os=-riscix1.2- ;;- arm*-rebel)- os=-linux- ;;- arm*-semi)- os=-aout- ;;- c4x-* | tic4x-*)- os=-coff- ;;- # This must come before the *-dec entry.- pdp10-*)- os=-tops20- ;;- pdp11-*)- os=-none- ;;- *-dec | vax-*)- os=-ultrix4.2- ;;- m68*-apollo)- os=-domain- ;;- i386-sun)- os=-sunos4.0.2- ;;- m68000-sun)- os=-sunos3- # This also exists in the configure program, but was not the- # default.- # os=-sunos4- ;;- m68*-cisco)- os=-aout- ;;- mips*-cisco)- os=-elf- ;;- mips*-*)- os=-elf- ;;- or32-*)- os=-coff- ;;- *-tti) # must be before sparc entry or we get the wrong os.- os=-sysv3- ;;- sparc-* | *-sun)- os=-sunos4.1.1- ;;- *-be)- os=-beos- ;;- *-haiku)- os=-haiku- ;;- *-ibm)- os=-aix- ;;- *-knuth)- os=-mmixware- ;;- *-wec)- os=-proelf- ;;- *-winbond)- os=-proelf- ;;- *-oki)- os=-proelf- ;;- *-hp)- os=-hpux- ;;- *-hitachi)- os=-hiux- ;;- i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)- os=-sysv- ;;- *-cbm)- os=-amigaos- ;;- *-dg)- os=-dgux- ;;- *-dolphin)- os=-sysv3- ;;- m68k-ccur)- os=-rtu- ;;- m88k-omron*)- os=-luna- ;;- *-next )- os=-nextstep- ;;- *-sequent)- os=-ptx- ;;- *-crds)- os=-unos- ;;- *-ns)- os=-genix- ;;- i370-*)- os=-mvs- ;;- *-next)- os=-nextstep3- ;;- *-gould)- os=-sysv- ;;- *-highlevel)- os=-bsd- ;;- *-encore)- os=-bsd- ;;- *-sgi)- os=-irix- ;;- *-siemens)- os=-sysv4- ;;- *-masscomp)- os=-rtu- ;;- f30[01]-fujitsu | f700-fujitsu)- os=-uxpv- ;;- *-rom68k)- os=-coff- ;;- *-*bug)- os=-coff- ;;- *-apple)- os=-macos- ;;- *-atari*)- os=-mint- ;;- *)- os=-none- ;;-esac-fi--# Here we handle the case where we know the os, and the CPU type, but not the-# manufacturer. We pick the logical manufacturer.-vendor=unknown-case $basic_machine in- *-unknown)- case $os in- -riscix*)- vendor=acorn- ;;- -sunos*)- vendor=sun- ;;- -aix*)- vendor=ibm- ;;- -beos*)- vendor=be- ;;- -hpux*)- vendor=hp- ;;- -mpeix*)- vendor=hp- ;;- -hiux*)- vendor=hitachi- ;;- -unos*)- vendor=crds- ;;- -dgux*)- vendor=dg- ;;- -luna*)- vendor=omron- ;;- -genix*)- vendor=ns- ;;- -mvs* | -opened*)- vendor=ibm- ;;- -os400*)- vendor=ibm- ;;- -ptx*)- vendor=sequent- ;;- -tpf*)- vendor=ibm- ;;- -vxsim* | -vxworks* | -windiss*)- vendor=wrs- ;;- -aux*)- vendor=apple- ;;- -hms*)- vendor=hitachi- ;;- -mpw* | -macos*)- vendor=apple- ;;- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)- vendor=atari- ;;- -vos*)- vendor=stratus- ;;- esac- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`- ;;-esac--echo $basic_machine$os-exit--# Local variables:-# eval: (add-hook 'write-file-hooks 'time-stamp)-# time-stamp-start: "timestamp='"-# time-stamp-format: "%:y-%02m-%02d"-# time-stamp-end: "'"-# End:
@@ -1,21596 +0,0 @@-#! /bin/sh-# Guess values for system-dependent variables and create Makefiles.-# Generated by GNU Autoconf 2.68 for Haskell base package 1.0.-#-# Report bugs to <libraries@haskell.org>.-#-#-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software-# Foundation, Inc.-#-#-# This configure script is free software; the Free Software Foundation-# gives unlimited permission to copy, distribute and modify it.-## -------------------- ##-## M4sh Initialization. ##-## -------------------- ##--# Be more Bourne compatible-DUALCASE=1; export DUALCASE # for MKS sh-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :- emulate sh- NULLCMD=:- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which- # is contrary to our usage. Disable this feature.- alias -g '${1+"$@"}'='"$@"'- setopt NO_GLOB_SUBST-else- case `(set -o) 2>/dev/null` in #(- *posix*) :- set -o posix ;; #(- *) :- ;;-esac-fi---as_nl='-'-export as_nl-# Printing a long string crashes Solaris 7 /usr/bin/printf.-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo-# Prefer a ksh shell builtin over an external printf program on Solaris,-# but without wasting forks for bash or zsh.-if test -z "$BASH_VERSION$ZSH_VERSION" \- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='print -r --'- as_echo_n='print -rn --'-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='printf %s\n'- as_echo_n='printf %s'-else- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'- as_echo_n='/usr/ucb/echo -n'- else- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'- as_echo_n_body='eval- arg=$1;- case $arg in #(- *"$as_nl"*)- expr "X$arg" : "X\\(.*\\)$as_nl";- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;- esac;- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"- '- export as_echo_n_body- as_echo_n='sh -c $as_echo_n_body as_echo'- fi- export as_echo_body- as_echo='sh -c $as_echo_body as_echo'-fi--# The user is always right.-if test "${PATH_SEPARATOR+set}" != set; then- PATH_SEPARATOR=:- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||- PATH_SEPARATOR=';'- }-fi---# IFS-# We need space, tab and new line, in precisely that order. Quoting is-# there to prevent editors from complaining about space-tab.-# (If _AS_PATH_WALK were called with IFS unset, it would disable word-# splitting by setting IFS to empty value.)-IFS=" "" $as_nl"--# Find who we are. Look in the path if we contain no directory separator.-as_myself=-case $0 in #((- *[\\/]* ) as_myself=$0 ;;- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break- done-IFS=$as_save_IFS-- ;;-esac-# We did not find ourselves, most probably we were run as `sh COMMAND'-# in which case we are not to be found in the path.-if test "x$as_myself" = x; then- as_myself=$0-fi-if test ! -f "$as_myself"; then- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2- exit 1-fi--# Unset variables that we do not need and which cause bugs (e.g. in-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"-# suppresses any "Segmentation fault" message there. '((' could-# trigger a bug in pdksh 5.2.14.-for as_var in BASH_ENV ENV MAIL MAILPATH-do eval test x\${$as_var+set} = xset \- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :-done-PS1='$ '-PS2='> '-PS4='+ '--# NLS nuisances.-LC_ALL=C-export LC_ALL-LANGUAGE=C-export LANGUAGE--# CDPATH.-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH--if test "x$CONFIG_SHELL" = x; then- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :- emulate sh- NULLCMD=:- # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which- # is contrary to our usage. Disable this feature.- alias -g '\${1+\"\$@\"}'='\"\$@\"'- setopt NO_GLOB_SUBST-else- case \`(set -o) 2>/dev/null\` in #(- *posix*) :- set -o posix ;; #(- *) :- ;;-esac-fi-"- as_required="as_fn_return () { (exit \$1); }-as_fn_success () { as_fn_return 0; }-as_fn_failure () { as_fn_return 1; }-as_fn_ret_success () { return 0; }-as_fn_ret_failure () { return 1; }--exitcode=0-as_fn_success || { exitcode=1; echo as_fn_success failed.; }-as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }-as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }-as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :--else- exitcode=1; echo positional parameters were not saved.-fi-test x\$exitcode = x0 || exit 1"- as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO- as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO- eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1-test \$(( 1 + 1 )) = 2 || exit 1"- if (eval "$as_required") 2>/dev/null; then :- as_have_required=yes-else- as_have_required=no-fi- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :--else- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-as_found=false-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- as_found=:- case $as_dir in #(- /*)- for as_base in sh bash ksh sh5; do- # Try only shells that exist, to save several forks.- as_shell=$as_dir/$as_base- if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :- CONFIG_SHELL=$as_shell as_have_required=yes- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :- break 2-fi-fi- done;;- esac- as_found=false-done-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :- CONFIG_SHELL=$SHELL as_have_required=yes-fi; }-IFS=$as_save_IFS--- if test "x$CONFIG_SHELL" != x; then :- # We cannot yet assume a decent shell, so we have to provide a- # neutralization value for shells without unset; and this also- # works around shells that cannot unset nonexistent variables.- # Preserve -v and -x to the replacement shell.- BASH_ENV=/dev/null- ENV=/dev/null- (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV- export CONFIG_SHELL- case $- in # ((((- *v*x* | *x*v* ) as_opts=-vx ;;- *v* ) as_opts=-v ;;- *x* ) as_opts=-x ;;- * ) as_opts= ;;- esac- exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}-fi-- if test x$as_have_required = xno; then :- $as_echo "$0: This script requires a shell more modern than all"- $as_echo "$0: the shells that I found on your system."- if test x${ZSH_VERSION+set} = xset ; then- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"- $as_echo "$0: be upgraded to zsh 4.3.4 or later."- else- $as_echo "$0: Please tell bug-autoconf@gnu.org and-$0: libraries@haskell.org about your system, including any-$0: error possibly output before this message. Then install-$0: a modern shell, or manually run the script under such a-$0: shell if you do have one."- fi- exit 1-fi-fi-fi-SHELL=${CONFIG_SHELL-/bin/sh}-export SHELL-# Unset more variables known to interfere with behavior of common tools.-CLICOLOR_FORCE= GREP_OPTIONS=-unset CLICOLOR_FORCE GREP_OPTIONS--## --------------------- ##-## M4sh Shell Functions. ##-## --------------------- ##-# as_fn_unset VAR-# ----------------# Portably unset VAR.-as_fn_unset ()-{- { eval $1=; unset $1;}-}-as_unset=as_fn_unset--# as_fn_set_status STATUS-# ------------------------# Set $? to STATUS, without forking.-as_fn_set_status ()-{- return $1-} # as_fn_set_status--# as_fn_exit STATUS-# ------------------# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.-as_fn_exit ()-{- set +e- as_fn_set_status $1- exit $1-} # as_fn_exit--# as_fn_mkdir_p-# --------------# Create "$as_dir" as a directory, including parents if necessary.-as_fn_mkdir_p ()-{-- case $as_dir in #(- -*) as_dir=./$as_dir;;- esac- test -d "$as_dir" || eval $as_mkdir_p || {- as_dirs=- while :; do- case $as_dir in #(- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(- *) as_qdir=$as_dir;;- esac- as_dirs="'$as_qdir' $as_dirs"- as_dir=`$as_dirname -- "$as_dir" ||-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$as_dir" : 'X\(//\)[^/]' \| \- X"$as_dir" : 'X\(//\)$' \| \- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$as_dir" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- test -d "$as_dir" && break- done- test -z "$as_dirs" || eval "mkdir $as_dirs"- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"---} # as_fn_mkdir_p-# as_fn_append VAR VALUE-# -----------------------# Append the text in VALUE to the end of the definition contained in VAR. Take-# advantage of any shell optimizations that allow amortized linear growth over-# repeated appends, instead of the typical quadratic growth present in naive-# implementations.-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :- eval 'as_fn_append ()- {- eval $1+=\$2- }'-else- as_fn_append ()- {- eval $1=\$$1\$2- }-fi # as_fn_append--# as_fn_arith ARG...-# -------------------# Perform arithmetic evaluation on the ARGs, and store the result in the-# global $as_val. Take advantage of shells that can avoid forks. The arguments-# must be portable across $(()) and expr.-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :- eval 'as_fn_arith ()- {- as_val=$(( $* ))- }'-else- as_fn_arith ()- {- as_val=`expr "$@" || test $? -eq 1`- }-fi # as_fn_arith---# as_fn_error STATUS ERROR [LINENO LOG_FD]-# -----------------------------------------# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the-# script with STATUS, using 1 if that was 0.-as_fn_error ()-{- as_status=$1; test $as_status -eq 0 && as_status=1- if test "$4"; then- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4- fi- $as_echo "$as_me: error: $2" >&2- as_fn_exit $as_status-} # as_fn_error--if expr a : '\(a\)' >/dev/null 2>&1 &&- test "X`expr 00001 : '.*\(...\)'`" = X001; then- as_expr=expr-else- as_expr=false-fi--if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then- as_basename=basename-else- as_basename=false-fi--if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then- as_dirname=dirname-else- as_dirname=false-fi--as_me=`$as_basename -- "$0" ||-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \- X"$0" : 'X\(//\)$' \| \- X"$0" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X/"$0" |- sed '/^.*\/\([^/][^/]*\)\/*$/{- s//\1/- q- }- /^X\/\(\/\/\)$/{- s//\1/- q- }- /^X\/\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`--# Avoid depending upon Character Ranges.-as_cr_letters='abcdefghijklmnopqrstuvwxyz'-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'-as_cr_Letters=$as_cr_letters$as_cr_LETTERS-as_cr_digits='0123456789'-as_cr_alnum=$as_cr_Letters$as_cr_digits--- as_lineno_1=$LINENO as_lineno_1a=$LINENO- as_lineno_2=$LINENO as_lineno_2a=$LINENO- eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&- test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {- # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)- sed -n '- p- /[$]LINENO/=- ' <$as_myself |- sed '- s/[$]LINENO.*/&-/- t lineno- b- :lineno- N- :loop- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/- t loop- s/-\n.*//- ' >$as_me.lineno &&- chmod +x "$as_me.lineno" ||- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }-- # Don't try to exec as it changes $[0], causing all sort of problems- # (the dirname of $[0] is not the place where we might find the- # original and so on. Autoconf is especially sensitive to this).- . "./$as_me.lineno"- # Exit status is that of the last command.- exit-}--ECHO_C= ECHO_N= ECHO_T=-case `echo -n x` in #(((((--n*)- case `echo 'xy\c'` in- *c*) ECHO_T=' ';; # ECHO_T is single tab character.- xy) ECHO_C='\c';;- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null- ECHO_T=' ';;- esac;;-*)- ECHO_N='-n';;-esac--rm -f conf$$ conf$$.exe conf$$.file-if test -d conf$$.dir; then- rm -f conf$$.dir/conf$$.file-else- rm -f conf$$.dir- mkdir conf$$.dir 2>/dev/null-fi-if (echo >conf$$.file) 2>/dev/null; then- if ln -s conf$$.file conf$$ 2>/dev/null; then- as_ln_s='ln -s'- # ... but there are two gotchas:- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.- # In both cases, we have to default to `cp -p'.- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||- as_ln_s='cp -p'- elif ln conf$$.file conf$$ 2>/dev/null; then- as_ln_s=ln- else- as_ln_s='cp -p'- fi-else- as_ln_s='cp -p'-fi-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file-rmdir conf$$.dir 2>/dev/null--if mkdir -p . 2>/dev/null; then- as_mkdir_p='mkdir -p "$as_dir"'-else- test -d ./-p && rmdir ./-p- as_mkdir_p=false-fi--if test -x / >/dev/null 2>&1; then- as_test_x='test -x'-else- if ls -dL / >/dev/null 2>&1; then- as_ls_L_option=L- else- as_ls_L_option=- fi- as_test_x='- eval sh -c '\''- if test -d "$1"; then- test -d "$1/.";- else- case $1 in #(- -*)set "./$1";;- esac;- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((- ???[sx]*):;;*)false;;esac;fi- '\'' sh- '-fi-as_executable_p=$as_test_x--# Sed expression to map a string onto a valid CPP name.-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"--# Sed expression to map a string onto a valid variable name.-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"---test -n "$DJDIR" || exec 7<&0 </dev/null-exec 6>&1--# Name of the host.-# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,-# so uname gets run too.-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`--#-# Initializations.-#-ac_default_prefix=/usr/local-ac_clean_files=-ac_config_libobj_dir=.-LIBOBJS=-cross_compiling=no-subdirs=-MFLAGS=-MAKEFLAGS=--# Identity of this package.-PACKAGE_NAME='Haskell base package'-PACKAGE_TARNAME='base'-PACKAGE_VERSION='1.0'-PACKAGE_STRING='Haskell base package 1.0'-PACKAGE_BUGREPORT='libraries@haskell.org'-PACKAGE_URL=''--ac_unique_file="include/HsBase.h"-# Factoring default headers for most tests.-ac_includes_default="\-#include <stdio.h>-#ifdef HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif-#ifdef HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif-#ifdef STDC_HEADERS-# include <stdlib.h>-# include <stddef.h>-#else-# ifdef HAVE_STDLIB_H-# include <stdlib.h>-# endif-#endif-#ifdef HAVE_STRING_H-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H-# include <memory.h>-# endif-# include <string.h>-#endif-#ifdef HAVE_STRINGS_H-# include <strings.h>-#endif-#ifdef HAVE_INTTYPES_H-# include <inttypes.h>-#endif-#ifdef HAVE_STDINT_H-# include <stdint.h>-#endif-#ifdef HAVE_UNISTD_H-# include <unistd.h>-#endif"--ac_subst_vars='LTLIBOBJS-LIBOBJS-EXTRA_LIBS-ICONV_LIB_DIRS-ICONV_INCLUDE_DIRS-EGREP-GREP-CPP-OBJEXT-EXEEXT-ac_ct_CC-CPPFLAGS-LDFLAGS-CFLAGS-CC-target_alias-host_alias-build_alias-LIBS-ECHO_T-ECHO_N-ECHO_C-DEFS-mandir-localedir-libdir-psdir-pdfdir-dvidir-htmldir-infodir-docdir-oldincludedir-includedir-localstatedir-sharedstatedir-sysconfdir-datadir-datarootdir-libexecdir-sbindir-bindir-program_transform_name-prefix-exec_prefix-PACKAGE_URL-PACKAGE_BUGREPORT-PACKAGE_STRING-PACKAGE_VERSION-PACKAGE_TARNAME-PACKAGE_NAME-PATH_SEPARATOR-SHELL'-ac_subst_files=''-ac_user_opts='-enable_option_checking-with_cc-enable_largefile-with_iconv_includes-with_iconv_libraries-'- ac_precious_vars='build_alias-host_alias-target_alias-CC-CFLAGS-LDFLAGS-LIBS-CPPFLAGS-CPP'---# Initialize some variables set by options.-ac_init_help=-ac_init_version=false-ac_unrecognized_opts=-ac_unrecognized_sep=-# The variables have the same names as the options, with-# dashes changed to underlines.-cache_file=/dev/null-exec_prefix=NONE-no_create=-no_recursion=-prefix=NONE-program_prefix=NONE-program_suffix=NONE-program_transform_name=s,x,x,-silent=-site=-srcdir=-verbose=-x_includes=NONE-x_libraries=NONE--# Installation directory options.-# These are left unexpanded so users can "make install exec_prefix=/foo"-# and all the variables that are supposed to be based on exec_prefix-# by default will actually change.-# Use braces instead of parens because sh, perl, etc. also accept them.-# (The list follows the same order as the GNU Coding Standards.)-bindir='${exec_prefix}/bin'-sbindir='${exec_prefix}/sbin'-libexecdir='${exec_prefix}/libexec'-datarootdir='${prefix}/share'-datadir='${datarootdir}'-sysconfdir='${prefix}/etc'-sharedstatedir='${prefix}/com'-localstatedir='${prefix}/var'-includedir='${prefix}/include'-oldincludedir='/usr/include'-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'-infodir='${datarootdir}/info'-htmldir='${docdir}'-dvidir='${docdir}'-pdfdir='${docdir}'-psdir='${docdir}'-libdir='${exec_prefix}/lib'-localedir='${datarootdir}/locale'-mandir='${datarootdir}/man'--ac_prev=-ac_dashdash=-for ac_option-do- # If the previous option needs an argument, assign it.- if test -n "$ac_prev"; then- eval $ac_prev=\$ac_option- ac_prev=- continue- fi-- case $ac_option in- *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;- *=) ac_optarg= ;;- *) ac_optarg=yes ;;- esac-- # Accept the important Cygnus configure options, so we can diagnose typos.-- case $ac_dashdash$ac_option in- --)- ac_dashdash=yes ;;-- -bindir | --bindir | --bindi | --bind | --bin | --bi)- ac_prev=bindir ;;- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)- bindir=$ac_optarg ;;-- -build | --build | --buil | --bui | --bu)- ac_prev=build_alias ;;- -build=* | --build=* | --buil=* | --bui=* | --bu=*)- build_alias=$ac_optarg ;;-- -cache-file | --cache-file | --cache-fil | --cache-fi \- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)- ac_prev=cache_file ;;- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)- cache_file=$ac_optarg ;;-- --config-cache | -C)- cache_file=config.cache ;;-- -datadir | --datadir | --datadi | --datad)- ac_prev=datadir ;;- -datadir=* | --datadir=* | --datadi=* | --datad=*)- datadir=$ac_optarg ;;-- -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \- | --dataroo | --dataro | --datar)- ac_prev=datarootdir ;;- -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \- | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)- datarootdir=$ac_optarg ;;-- -disable-* | --disable-*)- ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid feature name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"enable_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval enable_$ac_useropt=no ;;-- -docdir | --docdir | --docdi | --doc | --do)- ac_prev=docdir ;;- -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)- docdir=$ac_optarg ;;-- -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)- ac_prev=dvidir ;;- -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)- dvidir=$ac_optarg ;;-- -enable-* | --enable-*)- ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid feature name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"enable_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval enable_$ac_useropt=\$ac_optarg ;;-- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \- | --exec | --exe | --ex)- ac_prev=exec_prefix ;;- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \- | --exec=* | --exe=* | --ex=*)- exec_prefix=$ac_optarg ;;-- -gas | --gas | --ga | --g)- # Obsolete; use --with-gas.- with_gas=yes ;;-- -help | --help | --hel | --he | -h)- ac_init_help=long ;;- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)- ac_init_help=recursive ;;- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)- ac_init_help=short ;;-- -host | --host | --hos | --ho)- ac_prev=host_alias ;;- -host=* | --host=* | --hos=* | --ho=*)- host_alias=$ac_optarg ;;-- -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)- ac_prev=htmldir ;;- -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \- | --ht=*)- htmldir=$ac_optarg ;;-- -includedir | --includedir | --includedi | --included | --include \- | --includ | --inclu | --incl | --inc)- ac_prev=includedir ;;- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \- | --includ=* | --inclu=* | --incl=* | --inc=*)- includedir=$ac_optarg ;;-- -infodir | --infodir | --infodi | --infod | --info | --inf)- ac_prev=infodir ;;- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)- infodir=$ac_optarg ;;-- -libdir | --libdir | --libdi | --libd)- ac_prev=libdir ;;- -libdir=* | --libdir=* | --libdi=* | --libd=*)- libdir=$ac_optarg ;;-- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \- | --libexe | --libex | --libe)- ac_prev=libexecdir ;;- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \- | --libexe=* | --libex=* | --libe=*)- libexecdir=$ac_optarg ;;-- -localedir | --localedir | --localedi | --localed | --locale)- ac_prev=localedir ;;- -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)- localedir=$ac_optarg ;;-- -localstatedir | --localstatedir | --localstatedi | --localstated \- | --localstate | --localstat | --localsta | --localst | --locals)- ac_prev=localstatedir ;;- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \- | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)- localstatedir=$ac_optarg ;;-- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)- ac_prev=mandir ;;- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)- mandir=$ac_optarg ;;-- -nfp | --nfp | --nf)- # Obsolete; use --without-fp.- with_fp=no ;;-- -no-create | --no-create | --no-creat | --no-crea | --no-cre \- | --no-cr | --no-c | -n)- no_create=yes ;;-- -no-recursion | --no-recursion | --no-recursio | --no-recursi \- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)- no_recursion=yes ;;-- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \- | --oldin | --oldi | --old | --ol | --o)- ac_prev=oldincludedir ;;- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)- oldincludedir=$ac_optarg ;;-- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)- ac_prev=prefix ;;- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)- prefix=$ac_optarg ;;-- -program-prefix | --program-prefix | --program-prefi | --program-pref \- | --program-pre | --program-pr | --program-p)- ac_prev=program_prefix ;;- -program-prefix=* | --program-prefix=* | --program-prefi=* \- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)- program_prefix=$ac_optarg ;;-- -program-suffix | --program-suffix | --program-suffi | --program-suff \- | --program-suf | --program-su | --program-s)- ac_prev=program_suffix ;;- -program-suffix=* | --program-suffix=* | --program-suffi=* \- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)- program_suffix=$ac_optarg ;;-- -program-transform-name | --program-transform-name \- | --program-transform-nam | --program-transform-na \- | --program-transform-n | --program-transform- \- | --program-transform | --program-transfor \- | --program-transfo | --program-transf \- | --program-trans | --program-tran \- | --progr-tra | --program-tr | --program-t)- ac_prev=program_transform_name ;;- -program-transform-name=* | --program-transform-name=* \- | --program-transform-nam=* | --program-transform-na=* \- | --program-transform-n=* | --program-transform-=* \- | --program-transform=* | --program-transfor=* \- | --program-transfo=* | --program-transf=* \- | --program-trans=* | --program-tran=* \- | --progr-tra=* | --program-tr=* | --program-t=*)- program_transform_name=$ac_optarg ;;-- -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)- ac_prev=pdfdir ;;- -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)- pdfdir=$ac_optarg ;;-- -psdir | --psdir | --psdi | --psd | --ps)- ac_prev=psdir ;;- -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)- psdir=$ac_optarg ;;-- -q | -quiet | --quiet | --quie | --qui | --qu | --q \- | -silent | --silent | --silen | --sile | --sil)- silent=yes ;;-- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)- ac_prev=sbindir ;;- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \- | --sbi=* | --sb=*)- sbindir=$ac_optarg ;;-- -sharedstatedir | --sharedstatedir | --sharedstatedi \- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \- | --sharedst | --shareds | --shared | --share | --shar \- | --sha | --sh)- ac_prev=sharedstatedir ;;- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \- | --sha=* | --sh=*)- sharedstatedir=$ac_optarg ;;-- -site | --site | --sit)- ac_prev=site ;;- -site=* | --site=* | --sit=*)- site=$ac_optarg ;;-- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)- ac_prev=srcdir ;;- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)- srcdir=$ac_optarg ;;-- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \- | --syscon | --sysco | --sysc | --sys | --sy)- ac_prev=sysconfdir ;;- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)- sysconfdir=$ac_optarg ;;-- -target | --target | --targe | --targ | --tar | --ta | --t)- ac_prev=target_alias ;;- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)- target_alias=$ac_optarg ;;-- -v | -verbose | --verbose | --verbos | --verbo | --verb)- verbose=yes ;;-- -version | --version | --versio | --versi | --vers | -V)- ac_init_version=: ;;-- -with-* | --with-*)- ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid package name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"with_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval with_$ac_useropt=\$ac_optarg ;;-- -without-* | --without-*)- ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid package name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"with_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval with_$ac_useropt=no ;;-- --x)- # Obsolete; use --with-x.- with_x=yes ;;-- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \- | --x-incl | --x-inc | --x-in | --x-i)- ac_prev=x_includes ;;- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)- x_includes=$ac_optarg ;;-- -x-libraries | --x-libraries | --x-librarie | --x-librari \- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)- ac_prev=x_libraries ;;- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)- x_libraries=$ac_optarg ;;-- -*) as_fn_error $? "unrecognized option: \`$ac_option'-Try \`$0 --help' for more information"- ;;-- *=*)- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`- # Reject names that are not valid shell variable names.- case $ac_envvar in #(- '' | [0-9]* | *[!_$as_cr_alnum]* )- as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;- esac- eval $ac_envvar=\$ac_optarg- export $ac_envvar ;;-- *)- # FIXME: should be removed in autoconf 3.0.- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2- : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"- ;;-- esac-done--if test -n "$ac_prev"; then- ac_option=--`echo $ac_prev | sed 's/_/-/g'`- as_fn_error $? "missing argument to $ac_option"-fi--if test -n "$ac_unrecognized_opts"; then- case $enable_option_checking in- no) ;;- fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;- esac-fi--# Check all directory arguments for consistency.-for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \- datadir sysconfdir sharedstatedir localstatedir includedir \- oldincludedir docdir infodir htmldir dvidir pdfdir psdir \- libdir localedir mandir-do- eval ac_val=\$$ac_var- # Remove trailing slashes.- case $ac_val in- */ )- ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`- eval $ac_var=\$ac_val;;- esac- # Be sure to have absolute directory names.- case $ac_val in- [\\/$]* | ?:[\\/]* ) continue;;- NONE | '' ) case $ac_var in *prefix ) continue;; esac;;- esac- as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"-done--# There might be people who depend on the old broken behavior: `$host'-# used to hold the argument of --host etc.-# FIXME: To remove some day.-build=$build_alias-host=$host_alias-target=$target_alias--# FIXME: To remove some day.-if test "x$host_alias" != x; then- if test "x$build_alias" = x; then- cross_compiling=maybe- $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.- If a cross compiler is detected then cross compile mode will be used" >&2- elif test "x$build_alias" != "x$host_alias"; then- cross_compiling=yes- fi-fi--ac_tool_prefix=-test -n "$host_alias" && ac_tool_prefix=$host_alias---test "$silent" = yes && exec 6>/dev/null---ac_pwd=`pwd` && test -n "$ac_pwd" &&-ac_ls_di=`ls -di .` &&-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||- as_fn_error $? "working directory cannot be determined"-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||- as_fn_error $? "pwd does not report name of working directory"---# Find the source files, if location was not specified.-if test -z "$srcdir"; then- ac_srcdir_defaulted=yes- # Try the directory containing this script, then the parent directory.- ac_confdir=`$as_dirname -- "$as_myself" ||-$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$as_myself" : 'X\(//\)[^/]' \| \- X"$as_myself" : 'X\(//\)$' \| \- X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$as_myself" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- srcdir=$ac_confdir- if test ! -r "$srcdir/$ac_unique_file"; then- srcdir=..- fi-else- ac_srcdir_defaulted=no-fi-if test ! -r "$srcdir/$ac_unique_file"; then- test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."- as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"-fi-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"-ac_abs_confdir=`(- cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"- pwd)`-# When building in place, set srcdir=.-if test "$ac_abs_confdir" = "$ac_pwd"; then- srcdir=.-fi-# Remove unnecessary trailing slashes from srcdir.-# Double slashes in file names in object file debugging info-# mess up M-x gdb in Emacs.-case $srcdir in-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;-esac-for ac_var in $ac_precious_vars; do- eval ac_env_${ac_var}_set=\${${ac_var}+set}- eval ac_env_${ac_var}_value=\$${ac_var}- eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}- eval ac_cv_env_${ac_var}_value=\$${ac_var}-done--#-# Report the --help message.-#-if test "$ac_init_help" = "long"; then- # Omit some internal or obsolete options to make the list less imposing.- # This message is too long to be a string in the A/UX 3.1 sh.- cat <<_ACEOF-\`configure' configures Haskell base package 1.0 to adapt to many kinds of systems.--Usage: $0 [OPTION]... [VAR=VALUE]...--To assign environment variables (e.g., CC, CFLAGS...), specify them as-VAR=VALUE. See below for descriptions of some of the useful variables.--Defaults for the options are specified in brackets.--Configuration:- -h, --help display this help and exit- --help=short display options specific to this package- --help=recursive display the short help of all the included packages- -V, --version display version information and exit- -q, --quiet, --silent do not print \`checking ...' messages- --cache-file=FILE cache test results in FILE [disabled]- -C, --config-cache alias for \`--cache-file=config.cache'- -n, --no-create do not create output files- --srcdir=DIR find the sources in DIR [configure dir or \`..']--Installation directories:- --prefix=PREFIX install architecture-independent files in PREFIX- [$ac_default_prefix]- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX- [PREFIX]--By default, \`make install' will install all the files in-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify-an installation prefix other than \`$ac_default_prefix' using \`--prefix',-for instance \`--prefix=\$HOME'.--For better control, use the options below.--Fine tuning of the installation directories:- --bindir=DIR user executables [EPREFIX/bin]- --sbindir=DIR system admin executables [EPREFIX/sbin]- --libexecdir=DIR program executables [EPREFIX/libexec]- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]- --localstatedir=DIR modifiable single-machine data [PREFIX/var]- --libdir=DIR object code libraries [EPREFIX/lib]- --includedir=DIR C header files [PREFIX/include]- --oldincludedir=DIR C header files for non-gcc [/usr/include]- --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]- --datadir=DIR read-only architecture-independent data [DATAROOTDIR]- --infodir=DIR info documentation [DATAROOTDIR/info]- --localedir=DIR locale-dependent data [DATAROOTDIR/locale]- --mandir=DIR man documentation [DATAROOTDIR/man]- --docdir=DIR documentation root [DATAROOTDIR/doc/base]- --htmldir=DIR html documentation [DOCDIR]- --dvidir=DIR dvi documentation [DOCDIR]- --pdfdir=DIR pdf documentation [DOCDIR]- --psdir=DIR ps documentation [DOCDIR]-_ACEOF-- cat <<\_ACEOF-_ACEOF-fi--if test -n "$ac_init_help"; then- case $ac_init_help in- short | recursive ) echo "Configuration of Haskell base package 1.0:";;- esac- cat <<\_ACEOF--Optional Features:- --disable-option-checking ignore unrecognized --enable/--with options- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]- --disable-largefile omit support for large files--Optional Packages:- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)-C compiler- --with-iconv-includes directory containing iconv.h- --with-iconv-libraries directory containing iconv library--Some influential environment variables:- CC C compiler command- CFLAGS C compiler flags- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a- nonstandard directory <lib dir>- LIBS libraries to pass to the linker, e.g. -l<library>- CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if- you have headers in a nonstandard directory <include dir>- CPP C preprocessor--Use these variables to override the choices made by `configure' or to help-it to find libraries and programs with nonstandard names/locations.--Report bugs to <libraries@haskell.org>.-_ACEOF-ac_status=$?-fi--if test "$ac_init_help" = "recursive"; then- # If there are subdirs, report their specific --help.- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue- test -d "$ac_dir" ||- { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||- continue- ac_builddir=.--case "$ac_dir" in-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;-*)- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`- # A ".." for each directory in $ac_dir_suffix.- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`- case $ac_top_builddir_sub in- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;- esac ;;-esac-ac_abs_top_builddir=$ac_pwd-ac_abs_builddir=$ac_pwd$ac_dir_suffix-# for backward compatibility:-ac_top_builddir=$ac_top_build_prefix--case $srcdir in- .) # We are building in place.- ac_srcdir=.- ac_top_srcdir=$ac_top_builddir_sub- ac_abs_top_srcdir=$ac_pwd ;;- [\\/]* | ?:[\\/]* ) # Absolute name.- ac_srcdir=$srcdir$ac_dir_suffix;- ac_top_srcdir=$srcdir- ac_abs_top_srcdir=$srcdir ;;- *) # Relative name.- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix- ac_top_srcdir=$ac_top_build_prefix$srcdir- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;-esac-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix-- cd "$ac_dir" || { ac_status=$?; continue; }- # Check for guested configure.- if test -f "$ac_srcdir/configure.gnu"; then- echo &&- $SHELL "$ac_srcdir/configure.gnu" --help=recursive- elif test -f "$ac_srcdir/configure"; then- echo &&- $SHELL "$ac_srcdir/configure" --help=recursive- else- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2- fi || ac_status=$?- cd "$ac_pwd" || { ac_status=$?; break; }- done-fi--test -n "$ac_init_help" && exit $ac_status-if $ac_init_version; then- cat <<\_ACEOF-Haskell base package configure 1.0-generated by GNU Autoconf 2.68--Copyright (C) 2010 Free Software Foundation, Inc.-This configure script is free software; the Free Software Foundation-gives unlimited permission to copy, distribute and modify it.-_ACEOF- exit-fi--## ------------------------ ##-## Autoconf initialization. ##-## ------------------------ ##--# ac_fn_c_try_compile LINENO-# ---------------------------# Try to compile conftest.$ac_ext, and return whether this succeeded.-ac_fn_c_try_compile ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- rm -f conftest.$ac_objext- if { { ac_try="$ac_compile"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_compile") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- grep -v '^ *+' conftest.err >conftest.er1- cat conftest.er1 >&5- mv -f conftest.er1 conftest.err- fi- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } && {- test -z "$ac_c_werror_flag" ||- test ! -s conftest.err- } && test -s conftest.$ac_objext; then :- ac_retval=0-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=1-fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_compile--# ac_fn_c_check_type LINENO TYPE VAR INCLUDES-# --------------------------------------------# Tests whether TYPE exists after having included INCLUDES, setting cache-# variable VAR accordingly.-ac_fn_c_check_type ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- eval "$3=no"- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-if (sizeof ($2))- return 0;- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-if (sizeof (($2)))- return 0;- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :--else- eval "$3=yes"-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_type--# ac_fn_c_try_cpp LINENO-# -----------------------# Try to preprocess conftest.$ac_ext, and return whether this succeeded.-ac_fn_c_try_cpp ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if { { ac_try="$ac_cpp conftest.$ac_ext"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- grep -v '^ *+' conftest.err >conftest.er1- cat conftest.er1 >&5- mv -f conftest.er1 conftest.err- fi- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } > conftest.i && {- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||- test ! -s conftest.err- }; then :- ac_retval=0-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=1-fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_cpp--# ac_fn_c_try_run LINENO-# -----------------------# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes-# that executables *can* be run.-ac_fn_c_try_run ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'- { { case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_try") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; }; then :- ac_retval=0-else- $as_echo "$as_me: program exited with status $ac_status" >&5- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=$ac_status-fi- rm -rf conftest.dSYM conftest_ipa8_conftest.oo- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_run--# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES-# --------------------------------------------------------# Tests whether HEADER exists and can be compiled using the include files in-# INCLUDES, setting the cache variable VAR accordingly.-ac_fn_c_check_header_compile ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-#include <$2>-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- eval "$3=yes"-else- eval "$3=no"-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_header_compile--# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES-# --------------------------------------------------------# Tests whether HEADER exists, giving a warning if it cannot be compiled using-# the include files in INCLUDES and setting the cache variable VAR-# accordingly.-ac_fn_c_check_header_mongrel ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if eval \${$3+:} false; then :- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }-else- # Is the header compilable?-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5-$as_echo_n "checking $2 usability... " >&6; }-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-#include <$2>-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_header_compiler=yes-else- ac_header_compiler=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5-$as_echo "$ac_header_compiler" >&6; }--# Is the header present?-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5-$as_echo_n "checking $2 presence... " >&6; }-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <$2>-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :- ac_header_preproc=yes-else- ac_header_preproc=no-fi-rm -f conftest.err conftest.i conftest.$ac_ext-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5-$as_echo "$ac_header_preproc" >&6; }--# So? What about this header?-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((- yes:no: )- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}- ;;- no:yes:* )- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}-( $as_echo "## ------------------------------------ ##-## Report this to libraries@haskell.org ##-## ------------------------------------ ##"- ) | sed "s/^/$as_me: WARNING: /" >&2- ;;-esac- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- eval "$3=\$ac_header_compiler"-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }-fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_header_mongrel--# ac_fn_c_try_link LINENO-# ------------------------# Try to link conftest.$ac_ext, and return whether this succeeded.-ac_fn_c_try_link ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- rm -f conftest.$ac_objext conftest$ac_exeext- if { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- grep -v '^ *+' conftest.err >conftest.er1- cat conftest.er1 >&5- mv -f conftest.er1 conftest.err- fi- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } && {- test -z "$ac_c_werror_flag" ||- test ! -s conftest.err- } && test -s conftest$ac_exeext && {- test "$cross_compiling" = yes ||- $as_test_x conftest$ac_exeext- }; then :- ac_retval=0-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=1-fi- # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information- # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would- # interfere with the next link command; also delete a directory that is- # left behind by Apple's compiler. We do this before executing the actions.- rm -rf conftest.dSYM conftest_ipa8_conftest.oo- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_link--# ac_fn_c_check_func LINENO FUNC VAR-# -----------------------------------# Tests whether FUNC exists, setting the cache variable VAR accordingly-ac_fn_c_check_func ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.- For example, HP-UX 11i <limits.h> declares gettimeofday. */-#define $2 innocuous_$2--/* System header to define __stub macros and hopefully few prototypes,- which can conflict with char $2 (); below.- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since- <limits.h> exists even on freestanding compilers. */--#ifdef __STDC__-# include <limits.h>-#else-# include <assert.h>-#endif--#undef $2--/* Override any GCC internal prototype to avoid an error.- Use char because int might match the return type of a GCC- builtin and then its argument prototype would still apply. */-#ifdef __cplusplus-extern "C"-#endif-char $2 ();-/* The GNU C library defines this for functions which it implements- to always fail with ENOSYS. Some functions are actually named- something starting with __ and the normal name is an alias. */-#if defined __stub_$2 || defined __stub___$2-choke me-#endif--int-main ()-{-return $2 ();- ;- return 0;-}-_ACEOF-if ac_fn_c_try_link "$LINENO"; then :- eval "$3=yes"-else- eval "$3=no"-fi-rm -f core conftest.err conftest.$ac_objext \- conftest$ac_exeext conftest.$ac_ext-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_func--# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES-# ---------------------------------------------# Tries to find the compile-time value of EXPR in a program that includes-# INCLUDES, setting VAR accordingly. Returns whether the value could be-# computed-ac_fn_c_compute_int ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if test "$cross_compiling" = yes; then- # Depending upon the size, compute the lo and hi bounds.-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-static int test_array [1 - 2 * !(($2) >= 0)];-test_array [0] = 0-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_lo=0 ac_mid=0- while :; do- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-static int test_array [1 - 2 * !(($2) <= $ac_mid)];-test_array [0] = 0-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_hi=$ac_mid; break-else- as_fn_arith $ac_mid + 1 && ac_lo=$as_val- if test $ac_lo -le $ac_mid; then- ac_lo= ac_hi=- break- fi- as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- done-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-static int test_array [1 - 2 * !(($2) < 0)];-test_array [0] = 0-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_hi=-1 ac_mid=-1- while :; do- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-static int test_array [1 - 2 * !(($2) >= $ac_mid)];-test_array [0] = 0-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_lo=$ac_mid; break-else- as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val- if test $ac_mid -le $ac_hi; then- ac_lo= ac_hi=- break- fi- as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- done-else- ac_lo= ac_hi=-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-# Binary search between lo and hi bounds.-while test "x$ac_lo" != "x$ac_hi"; do- as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-int-main ()-{-static int test_array [1 - 2 * !(($2) <= $ac_mid)];-test_array [0] = 0-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_hi=$ac_mid-else- as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-done-case $ac_lo in #((-?*) eval "$3=\$ac_lo"; ac_retval=0 ;;-'') ac_retval=1 ;;-esac- else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-static long int longval () { return $2; }-static unsigned long int ulongval () { return $2; }-#include <stdio.h>-#include <stdlib.h>-int-main ()-{-- FILE *f = fopen ("conftest.val", "w");- if (! f)- return 1;- if (($2) < 0)- {- long int i = longval ();- if (i != ($2))- return 1;- fprintf (f, "%ld", i);- }- else- {- unsigned long int i = ulongval ();- if (i != ($2))- return 1;- fprintf (f, "%lu", i);- }- /* Do not output a trailing newline, as this causes \r\n confusion- on some platforms. */- return ferror (f) || fclose (f) != 0;-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_run "$LINENO"; then :- echo >>conftest.val; read $3 <conftest.val; ac_retval=0-else- ac_retval=1-fi-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \- conftest.$ac_objext conftest.beam conftest.$ac_ext-rm -f conftest.val-- fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_compute_int-cat >config.log <<_ACEOF-This file contains any messages produced by compilers while-running configure, to aid debugging if configure makes a mistake.--It was created by Haskell base package $as_me 1.0, which was-generated by GNU Autoconf 2.68. Invocation command line was-- $ $0 $@--_ACEOF-exec 5>>config.log-{-cat <<_ASUNAME-## --------- ##-## Platform. ##-## --------- ##--hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`-uname -m = `(uname -m) 2>/dev/null || echo unknown`-uname -r = `(uname -r) 2>/dev/null || echo unknown`-uname -s = `(uname -s) 2>/dev/null || echo unknown`-uname -v = `(uname -v) 2>/dev/null || echo unknown`--/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`--/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`-/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`--_ASUNAME--as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- $as_echo "PATH: $as_dir"- done-IFS=$as_save_IFS--} >&5--cat >&5 <<_ACEOF---## ----------- ##-## Core tests. ##-## ----------- ##--_ACEOF---# Keep a trace of the command line.-# Strip out --no-create and --no-recursion so they do not pile up.-# Strip out --silent because we don't want to record it for future runs.-# Also quote any args containing shell meta-characters.-# Make two passes to allow for proper duplicate-argument suppression.-ac_configure_args=-ac_configure_args0=-ac_configure_args1=-ac_must_keep_next=false-for ac_pass in 1 2-do- for ac_arg- do- case $ac_arg in- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;- -q | -quiet | --quiet | --quie | --qui | --qu | --q \- | -silent | --silent | --silen | --sile | --sil)- continue ;;- *\'*)- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;- esac- case $ac_pass in- 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;- 2)- as_fn_append ac_configure_args1 " '$ac_arg'"- if test $ac_must_keep_next = true; then- ac_must_keep_next=false # Got value, back to normal.- else- case $ac_arg in- *=* | --config-cache | -C | -disable-* | --disable-* \- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \- | -with-* | --with-* | -without-* | --without-* | --x)- case "$ac_configure_args0 " in- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;- esac- ;;- -* ) ac_must_keep_next=true ;;- esac- fi- as_fn_append ac_configure_args " '$ac_arg'"- ;;- esac- done-done-{ ac_configure_args0=; unset ac_configure_args0;}-{ ac_configure_args1=; unset ac_configure_args1;}--# When interrupted or exit'd, cleanup temporary files, and complete-# config.log. We remove comments because anyway the quotes in there-# would cause problems or look ugly.-# WARNING: Use '\'' to represent an apostrophe within the trap.-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.-trap 'exit_status=$?- # Save into config.log some information that might help in debugging.- {- echo-- $as_echo "## ---------------- ##-## Cache variables. ##-## ---------------- ##"- echo- # The following way of writing the cache mishandles newlines in values,-(- for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do- eval ac_val=\$$ac_var- case $ac_val in #(- *${as_nl}*)- case $ac_var in #(- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;- esac- case $ac_var in #(- _ | IFS | as_nl) ;; #(- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(- *) { eval $ac_var=; unset $ac_var;} ;;- esac ;;- esac- done- (set) 2>&1 |- case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(- *${as_nl}ac_space=\ *)- sed -n \- "s/'\''/'\''\\\\'\'''\''/g;- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"- ;; #(- *)- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"- ;;- esac |- sort-)- echo-- $as_echo "## ----------------- ##-## Output variables. ##-## ----------------- ##"- echo- for ac_var in $ac_subst_vars- do- eval ac_val=\$$ac_var- case $ac_val in- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;- esac- $as_echo "$ac_var='\''$ac_val'\''"- done | sort- echo-- if test -n "$ac_subst_files"; then- $as_echo "## ------------------- ##-## File substitutions. ##-## ------------------- ##"- echo- for ac_var in $ac_subst_files- do- eval ac_val=\$$ac_var- case $ac_val in- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;- esac- $as_echo "$ac_var='\''$ac_val'\''"- done | sort- echo- fi-- if test -s confdefs.h; then- $as_echo "## ----------- ##-## confdefs.h. ##-## ----------- ##"- echo- cat confdefs.h- echo- fi- test "$ac_signal" != 0 &&- $as_echo "$as_me: caught signal $ac_signal"- $as_echo "$as_me: exit $exit_status"- } >&5- rm -f core *.core core.conftest.* &&- rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&- exit $exit_status-' 0-for ac_signal in 1 2 13 15; do- trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal-done-ac_signal=0--# confdefs.h avoids OS command line length limits that DEFS can exceed.-rm -f -r conftest* confdefs.h--$as_echo "/* confdefs.h */" > confdefs.h--# Predefined preprocessor variables.--cat >>confdefs.h <<_ACEOF-#define PACKAGE_NAME "$PACKAGE_NAME"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_VERSION "$PACKAGE_VERSION"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_STRING "$PACKAGE_STRING"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_URL "$PACKAGE_URL"-_ACEOF---# Let the site file select an alternate cache file if it wants to.-# Prefer an explicitly selected file to automatically selected ones.-ac_site_file1=NONE-ac_site_file2=NONE-if test -n "$CONFIG_SITE"; then- # We do not want a PATH search for config.site.- case $CONFIG_SITE in #((- -*) ac_site_file1=./$CONFIG_SITE;;- */*) ac_site_file1=$CONFIG_SITE;;- *) ac_site_file1=./$CONFIG_SITE;;- esac-elif test "x$prefix" != xNONE; then- ac_site_file1=$prefix/share/config.site- ac_site_file2=$prefix/etc/config.site-else- ac_site_file1=$ac_default_prefix/share/config.site- ac_site_file2=$ac_default_prefix/etc/config.site-fi-for ac_site_file in "$ac_site_file1" "$ac_site_file2"-do- test "x$ac_site_file" = xNONE && continue- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5-$as_echo "$as_me: loading site script $ac_site_file" >&6;}- sed 's/^/| /' "$ac_site_file" >&5- . "$ac_site_file" \- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "failed to load site script $ac_site_file-See \`config.log' for more details" "$LINENO" 5; }- fi-done--if test -r "$cache_file"; then- # Some versions of bash will fail to source /dev/null (special files- # actually), so we avoid doing that. DJGPP emulates it as a regular file.- if test /dev/null != "$cache_file" && test -f "$cache_file"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5-$as_echo "$as_me: loading cache $cache_file" >&6;}- case $cache_file in- [\\/]* | ?:[\\/]* ) . "$cache_file";;- *) . "./$cache_file";;- esac- fi-else- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5-$as_echo "$as_me: creating cache $cache_file" >&6;}- >$cache_file-fi--# Check that the precious variables saved in the cache have kept the same-# value.-ac_cache_corrupted=false-for ac_var in $ac_precious_vars; do- eval ac_old_set=\$ac_cv_env_${ac_var}_set- eval ac_new_set=\$ac_env_${ac_var}_set- eval ac_old_val=\$ac_cv_env_${ac_var}_value- eval ac_new_val=\$ac_env_${ac_var}_value- case $ac_old_set,$ac_new_set in- set,)- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}- ac_cache_corrupted=: ;;- ,set)- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}- ac_cache_corrupted=: ;;- ,);;- *)- if test "x$ac_old_val" != "x$ac_new_val"; then- # differences in whitespace do not lead to failure.- ac_old_val_w=`echo x $ac_old_val`- ac_new_val_w=`echo x $ac_new_val`- if test "$ac_old_val_w" != "$ac_new_val_w"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}- ac_cache_corrupted=:- else- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}- eval $ac_var=\$ac_old_val- fi- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}- fi;;- esac- # Pass precious variables to config.status.- if test "$ac_new_set" = set; then- case $ac_new_val in- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;- *) ac_arg=$ac_var=$ac_new_val ;;- esac- case " $ac_configure_args " in- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.- *) as_fn_append ac_configure_args " '$ac_arg'" ;;- esac- fi-done-if $ac_cache_corrupted; then- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5-fi-## -------------------- ##-## Main body of script. ##-## -------------------- ##--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu----# Safety check: Ensure that we are in the correct source directory.---ac_config_headers="$ac_config_headers include/HsBaseConfig.h include/EventConfig.h"----# Check whether --with-cc was given.-if test "${with_cc+set}" = set; then :- withval=$with_cc; CC=$withval-fi--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu-if test -n "$ac_tool_prefix"; then- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.-set dummy ${ac_tool_prefix}gcc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then- ac_cv_prog_CC="${ac_tool_prefix}gcc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi---fi-if test -z "$ac_cv_prog_CC"; then- ac_ct_CC=$CC- # Extract the first word of "gcc", so it can be a program name with args.-set dummy gcc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_ac_ct_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$ac_ct_CC"; then- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then- ac_cv_prog_ac_ct_CC="gcc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-ac_ct_CC=$ac_cv_prog_ac_ct_CC-if test -n "$ac_ct_CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5-$as_echo "$ac_ct_CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi-- if test "x$ac_ct_CC" = x; then- CC=""- else- case $cross_compiling:$ac_tool_warned in-yes:)-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}-ac_tool_warned=yes ;;-esac- CC=$ac_ct_CC- fi-else- CC="$ac_cv_prog_CC"-fi--if test -z "$CC"; then- if test -n "$ac_tool_prefix"; then- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.-set dummy ${ac_tool_prefix}cc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then- ac_cv_prog_CC="${ac_tool_prefix}cc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi--- fi-fi-if test -z "$CC"; then- # Extract the first word of "cc", so it can be a program name with args.-set dummy cc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else- ac_prog_rejected=no-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then- ac_prog_rejected=yes- continue- fi- ac_cv_prog_CC="cc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--if test $ac_prog_rejected = yes; then- # We found a bogon in the path, so make sure we never use it.- set dummy $ac_cv_prog_CC- shift- if test $# != 0; then- # We chose a different compiler from the bogus one.- # However, it has the same basename, so the bogon will be chosen- # first if we set CC to just the basename; use the full file name.- shift- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"- fi-fi-fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi---fi-if test -z "$CC"; then- if test -n "$ac_tool_prefix"; then- for ac_prog in cl.exe- do- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.-set dummy $ac_tool_prefix$ac_prog; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi--- test -n "$CC" && break- done-fi-if test -z "$CC"; then- ac_ct_CC=$CC- for ac_prog in cl.exe-do- # Extract the first word of "$ac_prog", so it can be a program name with args.-set dummy $ac_prog; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_ac_ct_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$ac_ct_CC"; then- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then- ac_cv_prog_ac_ct_CC="$ac_prog"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-ac_ct_CC=$ac_cv_prog_ac_ct_CC-if test -n "$ac_ct_CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5-$as_echo "$ac_ct_CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi--- test -n "$ac_ct_CC" && break-done-- if test "x$ac_ct_CC" = x; then- CC=""- else- case $cross_compiling:$ac_tool_warned in-yes:)-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}-ac_tool_warned=yes ;;-esac- CC=$ac_ct_CC- fi-fi--fi---test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "no acceptable C compiler found in \$PATH-See \`config.log' for more details" "$LINENO" 5; }--# Provide some information about the compiler.-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5-set X $ac_compile-ac_compiler=$2-for ac_option in --version -v -V -qversion; do- { { ac_try="$ac_compiler $ac_option >&5"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_compiler $ac_option >&5") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- sed '10a\-... rest of stderr output deleted ...- 10q' conftest.err >conftest.er1- cat conftest.er1 >&5- fi- rm -f conftest.er1 conftest.err- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }-done--cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-ac_clean_files_save=$ac_clean_files-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"-# Try to create an executable without -o first, disregard a.out.-# It will help us diagnose broken compilers, and finding out an intuition-# of exeext.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5-$as_echo_n "checking whether the C compiler works... " >&6; }-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`--# The possible output files:-ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"--ac_rmfiles=-for ac_file in $ac_files-do- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;- * ) ac_rmfiles="$ac_rmfiles $ac_file";;- esac-done-rm -f $ac_rmfiles--if { { ac_try="$ac_link_default"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link_default") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; then :- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'-# in a Makefile. We should not override ac_cv_exeext if it was cached,-# so that the user can short-circuit this test for compilers unknown to-# Autoconf.-for ac_file in $ac_files ''-do- test -f "$ac_file" || continue- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )- ;;- [ab].out )- # We found the default executable, but exeext='' is most- # certainly right.- break;;- *.* )- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;- then :; else- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`- fi- # We set ac_cv_exeext here because the later test for it is not- # safe: cross compilers may not add the suffix if given an `-o'- # argument, so we may need to know it at that point already.- # Even if this section looks crufty: it has the advantage of- # actually working.- break;;- * )- break;;- esac-done-test "$ac_cv_exeext" = no && ac_cv_exeext=--else- ac_file=''-fi-if test -z "$ac_file"; then :- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-$as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5--{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error 77 "C compiler cannot create executables-See \`config.log' for more details" "$LINENO" 5; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5-$as_echo "yes" >&6; }-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5-$as_echo_n "checking for C compiler default output file name... " >&6; }-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5-$as_echo "$ac_file" >&6; }-ac_exeext=$ac_cv_exeext--rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out-ac_clean_files=$ac_clean_files_save-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5-$as_echo_n "checking for suffix of executables... " >&6; }-if { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; then :- # If both `conftest.exe' and `conftest' are `present' (well, observable)-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will-# work properly (i.e., refer to `conftest.exe'), while it won't with-# `rm'.-for ac_file in conftest.exe conftest conftest.*; do- test -f "$ac_file" || continue- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`- break;;- * ) break;;- esac-done-else- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "cannot compute suffix of executables: cannot compile and link-See \`config.log' for more details" "$LINENO" 5; }-fi-rm -f conftest conftest$ac_cv_exeext-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5-$as_echo "$ac_cv_exeext" >&6; }--rm -f conftest.$ac_ext-EXEEXT=$ac_cv_exeext-ac_exeext=$EXEEXT-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdio.h>-int-main ()-{-FILE *f = fopen ("conftest.out", "w");- return ferror (f) || fclose (f) != 0;-- ;- return 0;-}-_ACEOF-ac_clean_files="$ac_clean_files conftest.out"-# Check that the compiler produces executables we can run. If not, either-# the compiler is broken, or we cross compile.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5-$as_echo_n "checking whether we are cross compiling... " >&6; }-if test "$cross_compiling" != yes; then- { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }- if { ac_try='./conftest$ac_cv_exeext'- { { case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_try") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; }; then- cross_compiling=no- else- if test "$cross_compiling" = maybe; then- cross_compiling=yes- else- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "cannot run C compiled programs.-If you meant to cross compile, use \`--host'.-See \`config.log' for more details" "$LINENO" 5; }- fi- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5-$as_echo "$cross_compiling" >&6; }--rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out-ac_clean_files=$ac_clean_files_save-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5-$as_echo_n "checking for suffix of object files... " >&6; }-if ${ac_cv_objext+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-rm -f conftest.o conftest.obj-if { { ac_try="$ac_compile"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_compile") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; then :- for ac_file in conftest.o conftest.obj conftest.*; do- test -f "$ac_file" || continue;- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`- break;;- esac-done-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5--{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "cannot compute suffix of object files: cannot compile-See \`config.log' for more details" "$LINENO" 5; }-fi-rm -f conftest.$ac_cv_objext conftest.$ac_ext-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5-$as_echo "$ac_cv_objext" >&6; }-OBJEXT=$ac_cv_objext-ac_objext=$OBJEXT-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }-if ${ac_cv_c_compiler_gnu+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-#ifndef __GNUC__- choke me-#endif-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_compiler_gnu=yes-else- ac_compiler_gnu=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-ac_cv_c_compiler_gnu=$ac_compiler_gnu--fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5-$as_echo "$ac_cv_c_compiler_gnu" >&6; }-if test $ac_compiler_gnu = yes; then- GCC=yes-else- GCC=-fi-ac_test_CFLAGS=${CFLAGS+set}-ac_save_CFLAGS=$CFLAGS-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5-$as_echo_n "checking whether $CC accepts -g... " >&6; }-if ${ac_cv_prog_cc_g+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_save_c_werror_flag=$ac_c_werror_flag- ac_c_werror_flag=yes- ac_cv_prog_cc_g=no- CFLAGS="-g"- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_prog_cc_g=yes-else- CFLAGS=""- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :--else- ac_c_werror_flag=$ac_save_c_werror_flag- CFLAGS="-g"- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_prog_cc_g=yes-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- ac_c_werror_flag=$ac_save_c_werror_flag-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5-$as_echo "$ac_cv_prog_cc_g" >&6; }-if test "$ac_test_CFLAGS" = set; then- CFLAGS=$ac_save_CFLAGS-elif test $ac_cv_prog_cc_g = yes; then- if test "$GCC" = yes; then- CFLAGS="-g -O2"- else- CFLAGS="-g"- fi-else- if test "$GCC" = yes; then- CFLAGS="-O2"- else- CFLAGS=- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }-if ${ac_cv_prog_cc_c89+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_cv_prog_cc_c89=no-ac_save_CC=$CC-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdarg.h>-#include <stdio.h>-#include <sys/types.h>-#include <sys/stat.h>-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */-struct buf { int x; };-FILE * (*rcsopen) (struct buf *, struct stat *, int);-static char *e (p, i)- char **p;- int i;-{- return p[i];-}-static char *f (char * (*g) (char **, int), char **p, ...)-{- char *s;- va_list v;- va_start (v,p);- s = g (p, va_arg (v,int));- va_end (v);- return s;-}--/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has- function prototypes and stuff, but not '\xHH' hex character constants.- These don't provoke an error unfortunately, instead are silently treated- as 'x'. The following induces an error, until -std is added to get- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an- array size at least. It's necessary to write '\x00'==0 to get something- that's true only with -std. */-int osf4_cc_array ['\x00' == 0 ? 1 : -1];--/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters- inside strings and character constants. */-#define FOO(x) 'x'-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];--int test (int i, double x);-struct s1 {int (*f) (int a);};-struct s2 {int (*f) (double a);};-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);-int argc;-char **argv;-int-main ()-{-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];- ;- return 0;-}-_ACEOF-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"-do- CC="$ac_save_CC $ac_arg"- if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_prog_cc_c89=$ac_arg-fi-rm -f core conftest.err conftest.$ac_objext- test "x$ac_cv_prog_cc_c89" != "xno" && break-done-rm -f conftest.$ac_ext-CC=$ac_save_CC--fi-# AC_CACHE_VAL-case "x$ac_cv_prog_cc_c89" in- x)- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5-$as_echo "none needed" >&6; } ;;- xno)- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5-$as_echo "unsupported" >&6; } ;;- *)- CC="$CC $ac_cv_prog_cc_c89"- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;-esac-if test "x$ac_cv_prog_cc_c89" != xno; then :--fi--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu---case `uname -s` in- MINGW*|CYGWIN*)- WINDOWS=YES;;- *)- WINDOWS=NO;;-esac--# do we have long longs?--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5-$as_echo_n "checking how to run the C preprocessor... " >&6; }-# On Suns, sometimes $CPP names a directory.-if test -n "$CPP" && test -d "$CPP"; then- CPP=-fi-if test -z "$CPP"; then- if ${ac_cv_prog_CPP+:} false; then :- $as_echo_n "(cached) " >&6-else- # Double quotes because CPP needs to be expanded- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"- do- ac_preproc_ok=false-for ac_c_preproc_warn_flag in '' yes-do- # Use a header file that comes with gcc, so configuring glibc- # with a fresh cross-compiler works.- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since- # <limits.h> exists even on freestanding compilers.- # On the NeXT, cc -E runs the code through the compiler's parser,- # not just through cpp. "Syntax error" is here to catch this case.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#ifdef __STDC__-# include <limits.h>-#else-# include <assert.h>-#endif- Syntax error-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :--else- # Broken: fails on valid input.-continue-fi-rm -f conftest.err conftest.i conftest.$ac_ext-- # OK, works on sane cases. Now check whether nonexistent headers- # can be detected and how.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ac_nonexistent.h>-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :- # Broken: success on invalid input.-continue-else- # Passes both tests.-ac_preproc_ok=:-break-fi-rm -f conftest.err conftest.i conftest.$ac_ext--done-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.-rm -f conftest.i conftest.err conftest.$ac_ext-if $ac_preproc_ok; then :- break-fi-- done- ac_cv_prog_CPP=$CPP--fi- CPP=$ac_cv_prog_CPP-else- ac_cv_prog_CPP=$CPP-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5-$as_echo "$CPP" >&6; }-ac_preproc_ok=false-for ac_c_preproc_warn_flag in '' yes-do- # Use a header file that comes with gcc, so configuring glibc- # with a fresh cross-compiler works.- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since- # <limits.h> exists even on freestanding compilers.- # On the NeXT, cc -E runs the code through the compiler's parser,- # not just through cpp. "Syntax error" is here to catch this case.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#ifdef __STDC__-# include <limits.h>-#else-# include <assert.h>-#endif- Syntax error-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :--else- # Broken: fails on valid input.-continue-fi-rm -f conftest.err conftest.i conftest.$ac_ext-- # OK, works on sane cases. Now check whether nonexistent headers- # can be detected and how.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ac_nonexistent.h>-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :- # Broken: success on invalid input.-continue-else- # Passes both tests.-ac_preproc_ok=:-break-fi-rm -f conftest.err conftest.i conftest.$ac_ext--done-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.-rm -f conftest.i conftest.err conftest.$ac_ext-if $ac_preproc_ok; then :--else- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check-See \`config.log' for more details" "$LINENO" 5; }-fi--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }-if ${ac_cv_path_GREP+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -z "$GREP"; then- ac_path_GREP_found=false- # Loop through the user's path and test for each of PROGNAME-LIST- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_prog in grep ggrep; do- for ac_exec_ext in '' $ac_executable_extensions; do- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"- { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue-# Check for GNU ac_path_GREP and select it if it is found.- # Check for GNU $ac_path_GREP-case `"$ac_path_GREP" --version 2>&1` in-*GNU*)- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;-*)- ac_count=0- $as_echo_n 0123456789 >"conftest.in"- while :- do- cat "conftest.in" "conftest.in" >"conftest.tmp"- mv "conftest.tmp" "conftest.in"- cp "conftest.in" "conftest.nl"- $as_echo 'GREP' >> "conftest.nl"- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break- as_fn_arith $ac_count + 1 && ac_count=$as_val- if test $ac_count -gt ${ac_path_GREP_max-0}; then- # Best one so far, save it but keep looking for a better one- ac_cv_path_GREP="$ac_path_GREP"- ac_path_GREP_max=$ac_count- fi- # 10*(2^10) chars as input seems more than enough- test $ac_count -gt 10 && break- done- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;-esac-- $ac_path_GREP_found && break 3- done- done- done-IFS=$as_save_IFS- if test -z "$ac_cv_path_GREP"; then- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5- fi-else- ac_cv_path_GREP=$GREP-fi--fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5-$as_echo "$ac_cv_path_GREP" >&6; }- GREP="$ac_cv_path_GREP"---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5-$as_echo_n "checking for egrep... " >&6; }-if ${ac_cv_path_EGREP+:} false; then :- $as_echo_n "(cached) " >&6-else- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1- then ac_cv_path_EGREP="$GREP -E"- else- if test -z "$EGREP"; then- ac_path_EGREP_found=false- # Loop through the user's path and test for each of PROGNAME-LIST- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_prog in egrep; do- for ac_exec_ext in '' $ac_executable_extensions; do- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"- { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue-# Check for GNU ac_path_EGREP and select it if it is found.- # Check for GNU $ac_path_EGREP-case `"$ac_path_EGREP" --version 2>&1` in-*GNU*)- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;-*)- ac_count=0- $as_echo_n 0123456789 >"conftest.in"- while :- do- cat "conftest.in" "conftest.in" >"conftest.tmp"- mv "conftest.tmp" "conftest.in"- cp "conftest.in" "conftest.nl"- $as_echo 'EGREP' >> "conftest.nl"- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break- as_fn_arith $ac_count + 1 && ac_count=$as_val- if test $ac_count -gt ${ac_path_EGREP_max-0}; then- # Best one so far, save it but keep looking for a better one- ac_cv_path_EGREP="$ac_path_EGREP"- ac_path_EGREP_max=$ac_count- fi- # 10*(2^10) chars as input seems more than enough- test $ac_count -gt 10 && break- done- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;-esac-- $ac_path_EGREP_found && break 3- done- done- done-IFS=$as_save_IFS- if test -z "$ac_cv_path_EGREP"; then- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5- fi-else- ac_cv_path_EGREP=$EGREP-fi-- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5-$as_echo "$ac_cv_path_EGREP" >&6; }- EGREP="$ac_cv_path_EGREP"---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5-$as_echo_n "checking for ANSI C header files... " >&6; }-if ${ac_cv_header_stdc+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdlib.h>-#include <stdarg.h>-#include <string.h>-#include <float.h>--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_header_stdc=yes-else- ac_cv_header_stdc=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext--if test $ac_cv_header_stdc = yes; then- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <string.h>--_ACEOF-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |- $EGREP "memchr" >/dev/null 2>&1; then :--else- ac_cv_header_stdc=no-fi-rm -f conftest*--fi--if test $ac_cv_header_stdc = yes; then- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdlib.h>--_ACEOF-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |- $EGREP "free" >/dev/null 2>&1; then :--else- ac_cv_header_stdc=no-fi-rm -f conftest*--fi--if test $ac_cv_header_stdc = yes; then- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.- if test "$cross_compiling" = yes; then :- :-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ctype.h>-#include <stdlib.h>-#if ((' ' & 0x0FF) == 0x020)-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))-#else-# define ISLOWER(c) \- (('a' <= (c) && (c) <= 'i') \- || ('j' <= (c) && (c) <= 'r') \- || ('s' <= (c) && (c) <= 'z'))-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))-#endif--#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))-int-main ()-{- int i;- for (i = 0; i < 256; i++)- if (XOR (islower (i), ISLOWER (i))- || toupper (i) != TOUPPER (i))- return 2;- return 0;-}-_ACEOF-if ac_fn_c_try_run "$LINENO"; then :--else- ac_cv_header_stdc=no-fi-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \- conftest.$ac_objext conftest.beam conftest.$ac_ext-fi--fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5-$as_echo "$ac_cv_header_stdc" >&6; }-if test $ac_cv_header_stdc = yes; then--$as_echo "#define STDC_HEADERS 1" >>confdefs.h--fi--# On IRIX 5.3, sys/types and inttypes.h are conflicting.-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \- inttypes.h stdint.h unistd.h-do :- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default-"-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1-_ACEOF--fi--done---ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"-if test "x$ac_cv_type_long_long" = xyes; then :--cat >>confdefs.h <<_ACEOF-#define HAVE_LONG_LONG 1-_ACEOF---fi---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5-$as_echo_n "checking for ANSI C header files... " >&6; }-if ${ac_cv_header_stdc+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdlib.h>-#include <stdarg.h>-#include <string.h>-#include <float.h>--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_header_stdc=yes-else- ac_cv_header_stdc=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext--if test $ac_cv_header_stdc = yes; then- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <string.h>--_ACEOF-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |- $EGREP "memchr" >/dev/null 2>&1; then :--else- ac_cv_header_stdc=no-fi-rm -f conftest*--fi--if test $ac_cv_header_stdc = yes; then- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdlib.h>--_ACEOF-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |- $EGREP "free" >/dev/null 2>&1; then :--else- ac_cv_header_stdc=no-fi-rm -f conftest*--fi--if test $ac_cv_header_stdc = yes; then- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.- if test "$cross_compiling" = yes; then :- :-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ctype.h>-#include <stdlib.h>-#if ((' ' & 0x0FF) == 0x020)-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))-#else-# define ISLOWER(c) \- (('a' <= (c) && (c) <= 'i') \- || ('j' <= (c) && (c) <= 'r') \- || ('s' <= (c) && (c) <= 'z'))-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))-#endif--#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))-int-main ()-{- int i;- for (i = 0; i < 256; i++)- if (XOR (islower (i), ISLOWER (i))- || toupper (i) != TOUPPER (i))- return 2;- return 0;-}-_ACEOF-if ac_fn_c_try_run "$LINENO"; then :--else- ac_cv_header_stdc=no-fi-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \- conftest.$ac_objext conftest.beam conftest.$ac_ext-fi--fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5-$as_echo "$ac_cv_header_stdc" >&6; }-if test $ac_cv_header_stdc = yes; then--$as_echo "#define STDC_HEADERS 1" >>confdefs.h--fi---# check for specific header (.h) files that we are interested in-for ac_header in ctype.h errno.h fcntl.h inttypes.h limits.h signal.h sys/resource.h sys/select.h sys/stat.h sys/syscall.h sys/time.h sys/timeb.h sys/timers.h sys/times.h sys/types.h sys/utsname.h sys/wait.h termios.h time.h unistd.h utime.h windows.h winsock.h langinfo.h poll.h sys/epoll.h sys/event.h sys/eventfd.h-do :- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1-_ACEOF--fi--done---# Enable large file support. Do this before testing the types ino_t, off_t, and-# rlim_t, because it will affect the result of that test.-# Check whether --enable-largefile was given.-if test "${enable_largefile+set}" = set; then :- enableval=$enable_largefile;-fi--if test "$enable_largefile" != no; then-- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5-$as_echo_n "checking for special C compiler options needed for large files... " >&6; }-if ${ac_cv_sys_largefile_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_cv_sys_largefile_CC=no- if test "$GCC" != yes; then- ac_save_CC=$CC- while :; do- # IRIX 6.2 and later do not support large files by default,- # so use the C compiler's -n32 option if that helps.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <sys/types.h>- /* Check that off_t can represent 2**63 - 1 correctly.- We can't simply define LARGE_OFF_T to be 9223372036854775807,- since some C++ compilers masquerading as C compilers- incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721- && LARGE_OFF_T % 2147483647 == 1)- ? 1 : -1];-int-main ()-{-- ;- return 0;-}-_ACEOF- if ac_fn_c_try_compile "$LINENO"; then :- break-fi-rm -f core conftest.err conftest.$ac_objext- CC="$CC -n32"- if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_sys_largefile_CC=' -n32'; break-fi-rm -f core conftest.err conftest.$ac_objext- break- done- CC=$ac_save_CC- rm -f conftest.$ac_ext- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5-$as_echo "$ac_cv_sys_largefile_CC" >&6; }- if test "$ac_cv_sys_largefile_CC" != no; then- CC=$CC$ac_cv_sys_largefile_CC- fi-- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5-$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }-if ${ac_cv_sys_file_offset_bits+:} false; then :- $as_echo_n "(cached) " >&6-else- while :; do- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <sys/types.h>- /* Check that off_t can represent 2**63 - 1 correctly.- We can't simply define LARGE_OFF_T to be 9223372036854775807,- since some C++ compilers masquerading as C compilers- incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721- && LARGE_OFF_T % 2147483647 == 1)- ? 1 : -1];-int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_sys_file_offset_bits=no; break-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#define _FILE_OFFSET_BITS 64-#include <sys/types.h>- /* Check that off_t can represent 2**63 - 1 correctly.- We can't simply define LARGE_OFF_T to be 9223372036854775807,- since some C++ compilers masquerading as C compilers- incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721- && LARGE_OFF_T % 2147483647 == 1)- ? 1 : -1];-int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_sys_file_offset_bits=64; break-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- ac_cv_sys_file_offset_bits=unknown- break-done-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5-$as_echo "$ac_cv_sys_file_offset_bits" >&6; }-case $ac_cv_sys_file_offset_bits in #(- no | unknown) ;;- *)-cat >>confdefs.h <<_ACEOF-#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits-_ACEOF-;;-esac-rm -rf conftest*- if test $ac_cv_sys_file_offset_bits = unknown; then- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5-$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }-if ${ac_cv_sys_large_files+:} false; then :- $as_echo_n "(cached) " >&6-else- while :; do- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <sys/types.h>- /* Check that off_t can represent 2**63 - 1 correctly.- We can't simply define LARGE_OFF_T to be 9223372036854775807,- since some C++ compilers masquerading as C compilers- incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721- && LARGE_OFF_T % 2147483647 == 1)- ? 1 : -1];-int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_sys_large_files=no; break-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#define _LARGE_FILES 1-#include <sys/types.h>- /* Check that off_t can represent 2**63 - 1 correctly.- We can't simply define LARGE_OFF_T to be 9223372036854775807,- since some C++ compilers masquerading as C compilers- incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721- && LARGE_OFF_T % 2147483647 == 1)- ? 1 : -1];-int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_sys_large_files=1; break-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- ac_cv_sys_large_files=unknown- break-done-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5-$as_echo "$ac_cv_sys_large_files" >&6; }-case $ac_cv_sys_large_files in #(- no | unknown) ;;- *)-cat >>confdefs.h <<_ACEOF-#define _LARGE_FILES $ac_cv_sys_large_files-_ACEOF-;;-esac-rm -rf conftest*- fi-fi---for ac_header in wctype.h-do :- ac_fn_c_check_header_mongrel "$LINENO" "wctype.h" "ac_cv_header_wctype_h" "$ac_includes_default"-if test "x$ac_cv_header_wctype_h" = xyes; then :- cat >>confdefs.h <<_ACEOF-#define HAVE_WCTYPE_H 1-_ACEOF- for ac_func in iswspace-do :- ac_fn_c_check_func "$LINENO" "iswspace" "ac_cv_func_iswspace"-if test "x$ac_cv_func_iswspace" = xyes; then :- cat >>confdefs.h <<_ACEOF-#define HAVE_ISWSPACE 1-_ACEOF--fi-done--fi--done---for ac_func in lstat-do :- ac_fn_c_check_func "$LINENO" "lstat" "ac_cv_func_lstat"-if test "x$ac_cv_func_lstat" = xyes; then :- cat >>confdefs.h <<_ACEOF-#define HAVE_LSTAT 1-_ACEOF--fi-done--for ac_func in getclock getrusage times-do :- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1-_ACEOF--fi-done--for ac_func in _chsize ftruncate-do :- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1-_ACEOF--fi-done---for ac_func in epoll_ctl eventfd kevent kevent64 kqueue poll-do :- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1-_ACEOF--fi-done---# event-related fun--if test "$ac_cv_header_sys_epoll_h" = yes -a "$ac_cv_func_epoll_ctl" = yes; then--$as_echo "#define HAVE_EPOLL 1" >>confdefs.h--fi--if test "$ac_cv_header_sys_event_h" = yes -a "$ac_cv_func_kqueue" = yes; then--$as_echo "#define HAVE_KQUEUE 1" >>confdefs.h--fi--if test "$ac_cv_header_poll_h" = yes -a "$ac_cv_func_poll" = yes; then--$as_echo "#define HAVE_POLL 1" >>confdefs.h--fi----# Check whether --with-iconv-includes was given.-if test "${with_iconv_includes+set}" = set; then :- withval=$with_iconv_includes; ICONV_INCLUDE_DIRS=$withval; CPPFLAGS="-I$withval"-else- ICONV_INCLUDE_DIRS=-fi----# Check whether --with-iconv-libraries was given.-if test "${with_iconv_libraries+set}" = set; then :- withval=$with_iconv_libraries; ICONV_LIB_DIRS=$withval; LDFLAGS="-L$withval"-else- ICONV_LIB_DIRS=-fi------# map standard C types and ISO types to Haskell types--------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for char" >&5-$as_echo_n "checking Haskell type for char... " >&6; }- if ${fptools_cv_htype_char+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_char=yes- if ac_fn_c_compute_int "$LINENO" "((char)((int)((char)1.4))) == ((char)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_char=no-fi--- if test "$fptools_cv_htype_sup_char" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(char) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(char) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(char) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_char=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_char=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_char=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_char=LDouble- else- fptools_cv_htype_sup_char=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((char)(-1)) < ((char)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(char) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_char=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_char="Word$HTYPE_SIZE"- else- fptools_cv_htype_char="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_char" = no- then-- fptools_cv_htype_char=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_char" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_char" >&5-$as_echo "$fptools_cv_htype_char" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_CHAR $fptools_cv_htype_char-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for signed char" >&5-$as_echo_n "checking Haskell type for signed char... " >&6; }- if ${fptools_cv_htype_signed_char+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_signed_char=yes- if ac_fn_c_compute_int "$LINENO" "((signed char)((int)((signed char)1.4))) == ((signed char)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_signed_char=no-fi--- if test "$fptools_cv_htype_sup_signed_char" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(signed char) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_signed_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(signed char) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_signed_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(signed char) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_signed_char=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_signed_char=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_signed_char=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_signed_char=LDouble- else- fptools_cv_htype_sup_signed_char=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((signed char)(-1)) < ((signed char)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_signed_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(signed char) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_signed_char=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_signed_char="Word$HTYPE_SIZE"- else- fptools_cv_htype_signed_char="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_signed_char" = no- then-- fptools_cv_htype_signed_char=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_signed_char" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_signed_char" >&5-$as_echo "$fptools_cv_htype_signed_char" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SIGNED_CHAR $fptools_cv_htype_signed_char-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for unsigned char" >&5-$as_echo_n "checking Haskell type for unsigned char... " >&6; }- if ${fptools_cv_htype_unsigned_char+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_unsigned_char=yes- if ac_fn_c_compute_int "$LINENO" "((unsigned char)((int)((unsigned char)1.4))) == ((unsigned char)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_char=no-fi--- if test "$fptools_cv_htype_sup_unsigned_char" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned char) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned char) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned char) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_char=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_unsigned_char=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_unsigned_char=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_unsigned_char=LDouble- else- fptools_cv_htype_sup_unsigned_char=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((unsigned char)(-1)) < ((unsigned char)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_char=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned char) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_char=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_unsigned_char="Word$HTYPE_SIZE"- else- fptools_cv_htype_unsigned_char="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_unsigned_char" = no- then-- fptools_cv_htype_unsigned_char=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_unsigned_char" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_unsigned_char" >&5-$as_echo "$fptools_cv_htype_unsigned_char" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UNSIGNED_CHAR $fptools_cv_htype_unsigned_char-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for short" >&5-$as_echo_n "checking Haskell type for short... " >&6; }- if ${fptools_cv_htype_short+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_short=yes- if ac_fn_c_compute_int "$LINENO" "((short)((int)((short)1.4))) == ((short)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_short=no-fi--- if test "$fptools_cv_htype_sup_short" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(short) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_short=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(short) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_short=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(short) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_short=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_short=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_short=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_short=LDouble- else- fptools_cv_htype_sup_short=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((short)(-1)) < ((short)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_short=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(short) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_short=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_short="Word$HTYPE_SIZE"- else- fptools_cv_htype_short="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_short" = no- then-- fptools_cv_htype_short=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_short" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_short" >&5-$as_echo "$fptools_cv_htype_short" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SHORT $fptools_cv_htype_short-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for unsigned short" >&5-$as_echo_n "checking Haskell type for unsigned short... " >&6; }- if ${fptools_cv_htype_unsigned_short+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_unsigned_short=yes- if ac_fn_c_compute_int "$LINENO" "((unsigned short)((int)((unsigned short)1.4))) == ((unsigned short)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_short=no-fi--- if test "$fptools_cv_htype_sup_unsigned_short" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned short) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_short=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned short) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_short=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned short) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_short=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_unsigned_short=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_unsigned_short=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_unsigned_short=LDouble- else- fptools_cv_htype_sup_unsigned_short=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((unsigned short)(-1)) < ((unsigned short)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_short=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned short) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_short=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_unsigned_short="Word$HTYPE_SIZE"- else- fptools_cv_htype_unsigned_short="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_unsigned_short" = no- then-- fptools_cv_htype_unsigned_short=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_unsigned_short" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_unsigned_short" >&5-$as_echo "$fptools_cv_htype_unsigned_short" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UNSIGNED_SHORT $fptools_cv_htype_unsigned_short-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for int" >&5-$as_echo_n "checking Haskell type for int... " >&6; }- if ${fptools_cv_htype_int+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_int=yes- if ac_fn_c_compute_int "$LINENO" "((int)((int)((int)1.4))) == ((int)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_int=no-fi--- if test "$fptools_cv_htype_sup_int" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(int) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_int=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(int) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_int=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(int) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_int=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_int=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_int=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_int=LDouble- else- fptools_cv_htype_sup_int=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((int)(-1)) < ((int)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_int=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(int) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_int=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_int="Word$HTYPE_SIZE"- else- fptools_cv_htype_int="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_int" = no- then-- fptools_cv_htype_int=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_int" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_int" >&5-$as_echo "$fptools_cv_htype_int" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_INT $fptools_cv_htype_int-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for unsigned int" >&5-$as_echo_n "checking Haskell type for unsigned int... " >&6; }- if ${fptools_cv_htype_unsigned_int+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_unsigned_int=yes- if ac_fn_c_compute_int "$LINENO" "((unsigned int)((int)((unsigned int)1.4))) == ((unsigned int)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_int=no-fi--- if test "$fptools_cv_htype_sup_unsigned_int" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned int) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_int=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned int) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_int=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned int) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_int=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_unsigned_int=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_unsigned_int=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_unsigned_int=LDouble- else- fptools_cv_htype_sup_unsigned_int=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((unsigned int)(-1)) < ((unsigned int)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_int=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned int) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_int=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_unsigned_int="Word$HTYPE_SIZE"- else- fptools_cv_htype_unsigned_int="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_unsigned_int" = no- then-- fptools_cv_htype_unsigned_int=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_unsigned_int" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_unsigned_int" >&5-$as_echo "$fptools_cv_htype_unsigned_int" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UNSIGNED_INT $fptools_cv_htype_unsigned_int-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for long" >&5-$as_echo_n "checking Haskell type for long... " >&6; }- if ${fptools_cv_htype_long+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_long=yes- if ac_fn_c_compute_int "$LINENO" "((long)((int)((long)1.4))) == ((long)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long=no-fi--- if test "$fptools_cv_htype_sup_long" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(long) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(long) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(long) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_long=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_long=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_long=LDouble- else- fptools_cv_htype_sup_long=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((long)(-1)) < ((long)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(long) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_long="Word$HTYPE_SIZE"- else- fptools_cv_htype_long="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_long" = no- then-- fptools_cv_htype_long=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_long" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_long" >&5-$as_echo "$fptools_cv_htype_long" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_LONG $fptools_cv_htype_long-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for unsigned long" >&5-$as_echo_n "checking Haskell type for unsigned long... " >&6; }- if ${fptools_cv_htype_unsigned_long+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_unsigned_long=yes- if ac_fn_c_compute_int "$LINENO" "((unsigned long)((int)((unsigned long)1.4))) == ((unsigned long)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long=no-fi--- if test "$fptools_cv_htype_sup_unsigned_long" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_unsigned_long=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_unsigned_long=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_unsigned_long=LDouble- else- fptools_cv_htype_sup_unsigned_long=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((unsigned long)(-1)) < ((unsigned long)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_unsigned_long="Word$HTYPE_SIZE"- else- fptools_cv_htype_unsigned_long="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_unsigned_long" = no- then-- fptools_cv_htype_unsigned_long=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_unsigned_long" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_unsigned_long" >&5-$as_echo "$fptools_cv_htype_unsigned_long" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UNSIGNED_LONG $fptools_cv_htype_unsigned_long-_ACEOF-- fi---if test "$ac_cv_type_long_long" = yes; then--------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for long long" >&5-$as_echo_n "checking Haskell type for long long... " >&6; }- if ${fptools_cv_htype_long_long+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_long_long=yes- if ac_fn_c_compute_int "$LINENO" "((long long)((int)((long long)1.4))) == ((long long)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long_long=no-fi--- if test "$fptools_cv_htype_sup_long_long" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(long long) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(long long) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(long long) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long_long=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_long_long=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_long_long=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_long_long=LDouble- else- fptools_cv_htype_sup_long_long=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((long long)(-1)) < ((long long)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(long long) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_long_long=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_long_long="Word$HTYPE_SIZE"- else- fptools_cv_htype_long_long="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_long_long" = no- then-- fptools_cv_htype_long_long=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_long_long" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_long_long" >&5-$as_echo "$fptools_cv_htype_long_long" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_LONG_LONG $fptools_cv_htype_long_long-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for unsigned long long" >&5-$as_echo_n "checking Haskell type for unsigned long long... " >&6; }- if ${fptools_cv_htype_unsigned_long_long+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_unsigned_long_long=yes- if ac_fn_c_compute_int "$LINENO" "((unsigned long long)((int)((unsigned long long)1.4))) == ((unsigned long long)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long_long=no-fi--- if test "$fptools_cv_htype_sup_unsigned_long_long" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long long) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long long) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long long) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long_long=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_unsigned_long_long=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_unsigned_long_long=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_unsigned_long_long=LDouble- else- fptools_cv_htype_sup_unsigned_long_long=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((unsigned long long)(-1)) < ((unsigned long long)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long_long=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(unsigned long long) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_unsigned_long_long=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_unsigned_long_long="Word$HTYPE_SIZE"- else- fptools_cv_htype_unsigned_long_long="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_unsigned_long_long" = no- then-- fptools_cv_htype_unsigned_long_long=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_unsigned_long_long" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_unsigned_long_long" >&5-$as_echo "$fptools_cv_htype_unsigned_long_long" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UNSIGNED_LONG_LONG $fptools_cv_htype_unsigned_long_long-_ACEOF-- fi---fi--------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for float" >&5-$as_echo_n "checking Haskell type for float... " >&6; }- if ${fptools_cv_htype_float+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_float=yes- if ac_fn_c_compute_int "$LINENO" "((float)((int)((float)1.4))) == ((float)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_float=no-fi--- if test "$fptools_cv_htype_sup_float" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(float) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_float=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(float) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_float=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(float) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_float=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_float=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_float=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_float=LDouble- else- fptools_cv_htype_sup_float=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((float)(-1)) < ((float)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_float=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(float) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_float=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_float="Word$HTYPE_SIZE"- else- fptools_cv_htype_float="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_float" = no- then-- fptools_cv_htype_float=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_float" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_float" >&5-$as_echo "$fptools_cv_htype_float" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_FLOAT $fptools_cv_htype_float-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for double" >&5-$as_echo_n "checking Haskell type for double... " >&6; }- if ${fptools_cv_htype_double+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_double=yes- if ac_fn_c_compute_int "$LINENO" "((double)((int)((double)1.4))) == ((double)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_double=no-fi--- if test "$fptools_cv_htype_sup_double" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(double) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_double=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(double) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_double=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(double) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_double=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_double=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_double=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_double=LDouble- else- fptools_cv_htype_sup_double=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((double)(-1)) < ((double)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_double=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(double) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_double=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_double="Word$HTYPE_SIZE"- else- fptools_cv_htype_double="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_double" = no- then-- fptools_cv_htype_double=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_double" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_double" >&5-$as_echo "$fptools_cv_htype_double" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_DOUBLE $fptools_cv_htype_double-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for ptrdiff_t" >&5-$as_echo_n "checking Haskell type for ptrdiff_t... " >&6; }- if ${fptools_cv_htype_ptrdiff_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_ptrdiff_t=yes- if ac_fn_c_compute_int "$LINENO" "((ptrdiff_t)((int)((ptrdiff_t)1.4))) == ((ptrdiff_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ptrdiff_t=no-fi--- if test "$fptools_cv_htype_sup_ptrdiff_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(ptrdiff_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ptrdiff_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ptrdiff_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ptrdiff_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ptrdiff_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ptrdiff_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_ptrdiff_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_ptrdiff_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_ptrdiff_t=LDouble- else- fptools_cv_htype_sup_ptrdiff_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((ptrdiff_t)(-1)) < ((ptrdiff_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ptrdiff_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ptrdiff_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ptrdiff_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_ptrdiff_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_ptrdiff_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_ptrdiff_t" = no- then-- fptools_cv_htype_ptrdiff_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_ptrdiff_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_ptrdiff_t" >&5-$as_echo "$fptools_cv_htype_ptrdiff_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_PTRDIFF_T $fptools_cv_htype_ptrdiff_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for size_t" >&5-$as_echo_n "checking Haskell type for size_t... " >&6; }- if ${fptools_cv_htype_size_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_size_t=yes- if ac_fn_c_compute_int "$LINENO" "((size_t)((int)((size_t)1.4))) == ((size_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_size_t=no-fi--- if test "$fptools_cv_htype_sup_size_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(size_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_size_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(size_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_size_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(size_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_size_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_size_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_size_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_size_t=LDouble- else- fptools_cv_htype_sup_size_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((size_t)(-1)) < ((size_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_size_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(size_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_size_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_size_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_size_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_size_t" = no- then-- fptools_cv_htype_size_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_size_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_size_t" >&5-$as_echo "$fptools_cv_htype_size_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SIZE_T $fptools_cv_htype_size_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for wchar_t" >&5-$as_echo_n "checking Haskell type for wchar_t... " >&6; }- if ${fptools_cv_htype_wchar_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_wchar_t=yes- if ac_fn_c_compute_int "$LINENO" "((wchar_t)((int)((wchar_t)1.4))) == ((wchar_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_wchar_t=no-fi--- if test "$fptools_cv_htype_sup_wchar_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(wchar_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_wchar_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(wchar_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_wchar_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(wchar_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_wchar_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_wchar_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_wchar_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_wchar_t=LDouble- else- fptools_cv_htype_sup_wchar_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((wchar_t)(-1)) < ((wchar_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_wchar_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(wchar_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_wchar_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_wchar_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_wchar_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_wchar_t" = no- then-- fptools_cv_htype_wchar_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_wchar_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_wchar_t" >&5-$as_echo "$fptools_cv_htype_wchar_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_WCHAR_T $fptools_cv_htype_wchar_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for sig_atomic_t" >&5-$as_echo_n "checking Haskell type for sig_atomic_t... " >&6; }- if ${fptools_cv_htype_sig_atomic_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_sig_atomic_t=yes- if ac_fn_c_compute_int "$LINENO" "((sig_atomic_t)((int)((sig_atomic_t)1.4))) == ((sig_atomic_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_sig_atomic_t=no-fi--- if test "$fptools_cv_htype_sup_sig_atomic_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(sig_atomic_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_sig_atomic_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(sig_atomic_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_sig_atomic_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(sig_atomic_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_sig_atomic_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_sig_atomic_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_sig_atomic_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_sig_atomic_t=LDouble- else- fptools_cv_htype_sup_sig_atomic_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((sig_atomic_t)(-1)) < ((sig_atomic_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_sig_atomic_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(sig_atomic_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_sig_atomic_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_sig_atomic_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_sig_atomic_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_sig_atomic_t" = no- then-- fptools_cv_htype_sig_atomic_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_sig_atomic_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_sig_atomic_t" >&5-$as_echo "$fptools_cv_htype_sig_atomic_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SIG_ATOMIC_T $fptools_cv_htype_sig_atomic_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for clock_t" >&5-$as_echo_n "checking Haskell type for clock_t... " >&6; }- if ${fptools_cv_htype_clock_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_clock_t=yes- if ac_fn_c_compute_int "$LINENO" "((clock_t)((int)((clock_t)1.4))) == ((clock_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_clock_t=no-fi--- if test "$fptools_cv_htype_sup_clock_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(clock_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_clock_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(clock_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_clock_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(clock_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_clock_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_clock_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_clock_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_clock_t=LDouble- else- fptools_cv_htype_sup_clock_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((clock_t)(-1)) < ((clock_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_clock_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(clock_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_clock_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_clock_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_clock_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_clock_t" = no- then-- fptools_cv_htype_clock_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_clock_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_clock_t" >&5-$as_echo "$fptools_cv_htype_clock_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_CLOCK_T $fptools_cv_htype_clock_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for time_t" >&5-$as_echo_n "checking Haskell type for time_t... " >&6; }- if ${fptools_cv_htype_time_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_time_t=yes- if ac_fn_c_compute_int "$LINENO" "((time_t)((int)((time_t)1.4))) == ((time_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_time_t=no-fi--- if test "$fptools_cv_htype_sup_time_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(time_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_time_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(time_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_time_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(time_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_time_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_time_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_time_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_time_t=LDouble- else- fptools_cv_htype_sup_time_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((time_t)(-1)) < ((time_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_time_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(time_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_time_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_time_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_time_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_time_t" = no- then-- fptools_cv_htype_time_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_time_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_time_t" >&5-$as_echo "$fptools_cv_htype_time_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_TIME_T $fptools_cv_htype_time_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for useconds_t" >&5-$as_echo_n "checking Haskell type for useconds_t... " >&6; }- if ${fptools_cv_htype_useconds_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_useconds_t=yes- if ac_fn_c_compute_int "$LINENO" "((useconds_t)((int)((useconds_t)1.4))) == ((useconds_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_useconds_t=no-fi--- if test "$fptools_cv_htype_sup_useconds_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(useconds_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_useconds_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(useconds_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_useconds_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(useconds_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_useconds_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_useconds_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_useconds_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_useconds_t=LDouble- else- fptools_cv_htype_sup_useconds_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((useconds_t)(-1)) < ((useconds_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_useconds_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(useconds_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_useconds_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_useconds_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_useconds_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_useconds_t" = no- then-- fptools_cv_htype_useconds_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_useconds_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_useconds_t" >&5-$as_echo "$fptools_cv_htype_useconds_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_USECONDS_T $fptools_cv_htype_useconds_t-_ACEOF-- fi---------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for suseconds_t" >&5-$as_echo_n "checking Haskell type for suseconds_t... " >&6; }- if ${fptools_cv_htype_suseconds_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_suseconds_t=yes- if ac_fn_c_compute_int "$LINENO" "((suseconds_t)((int)((suseconds_t)1.4))) == ((suseconds_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_suseconds_t=no-fi--- if test "$fptools_cv_htype_sup_suseconds_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(suseconds_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_suseconds_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(suseconds_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_suseconds_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(suseconds_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_suseconds_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_suseconds_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_suseconds_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_suseconds_t=LDouble- else- fptools_cv_htype_sup_suseconds_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((suseconds_t)(-1)) < ((suseconds_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_suseconds_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(suseconds_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_suseconds_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_suseconds_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_suseconds_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_suseconds_t" = no- then- if test "$WINDOWS" = "YES"- then- fptools_cv_htype_suseconds_t=Int32- fptools_cv_htype_sup_suseconds_t=yes- else- as_fn_error $? "type not found" "$LINENO" 5- fi- fi-- if test "$fptools_cv_htype_sup_suseconds_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_suseconds_t" >&5-$as_echo "$fptools_cv_htype_suseconds_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SUSECONDS_T $fptools_cv_htype_suseconds_t-_ACEOF-- fi---------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for dev_t" >&5-$as_echo_n "checking Haskell type for dev_t... " >&6; }- if ${fptools_cv_htype_dev_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_dev_t=yes- if ac_fn_c_compute_int "$LINENO" "((dev_t)((int)((dev_t)1.4))) == ((dev_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_dev_t=no-fi--- if test "$fptools_cv_htype_sup_dev_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(dev_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_dev_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(dev_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_dev_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(dev_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_dev_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_dev_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_dev_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_dev_t=LDouble- else- fptools_cv_htype_sup_dev_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((dev_t)(-1)) < ((dev_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_dev_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(dev_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_dev_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_dev_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_dev_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_dev_t" = no- then-- fptools_cv_htype_dev_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_dev_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_dev_t" >&5-$as_echo "$fptools_cv_htype_dev_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_DEV_T $fptools_cv_htype_dev_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for ino_t" >&5-$as_echo_n "checking Haskell type for ino_t... " >&6; }- if ${fptools_cv_htype_ino_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_ino_t=yes- if ac_fn_c_compute_int "$LINENO" "((ino_t)((int)((ino_t)1.4))) == ((ino_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ino_t=no-fi--- if test "$fptools_cv_htype_sup_ino_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(ino_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ino_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ino_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ino_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ino_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ino_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_ino_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_ino_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_ino_t=LDouble- else- fptools_cv_htype_sup_ino_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((ino_t)(-1)) < ((ino_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ino_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ino_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ino_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_ino_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_ino_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_ino_t" = no- then-- fptools_cv_htype_ino_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_ino_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_ino_t" >&5-$as_echo "$fptools_cv_htype_ino_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_INO_T $fptools_cv_htype_ino_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for mode_t" >&5-$as_echo_n "checking Haskell type for mode_t... " >&6; }- if ${fptools_cv_htype_mode_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_mode_t=yes- if ac_fn_c_compute_int "$LINENO" "((mode_t)((int)((mode_t)1.4))) == ((mode_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_mode_t=no-fi--- if test "$fptools_cv_htype_sup_mode_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(mode_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_mode_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(mode_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_mode_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(mode_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_mode_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_mode_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_mode_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_mode_t=LDouble- else- fptools_cv_htype_sup_mode_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((mode_t)(-1)) < ((mode_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_mode_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(mode_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_mode_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_mode_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_mode_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_mode_t" = no- then-- fptools_cv_htype_mode_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_mode_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_mode_t" >&5-$as_echo "$fptools_cv_htype_mode_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_MODE_T $fptools_cv_htype_mode_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for off_t" >&5-$as_echo_n "checking Haskell type for off_t... " >&6; }- if ${fptools_cv_htype_off_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_off_t=yes- if ac_fn_c_compute_int "$LINENO" "((off_t)((int)((off_t)1.4))) == ((off_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_off_t=no-fi--- if test "$fptools_cv_htype_sup_off_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(off_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_off_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(off_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_off_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(off_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_off_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_off_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_off_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_off_t=LDouble- else- fptools_cv_htype_sup_off_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((off_t)(-1)) < ((off_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_off_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(off_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_off_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_off_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_off_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_off_t" = no- then-- fptools_cv_htype_off_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_off_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_off_t" >&5-$as_echo "$fptools_cv_htype_off_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_OFF_T $fptools_cv_htype_off_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for pid_t" >&5-$as_echo_n "checking Haskell type for pid_t... " >&6; }- if ${fptools_cv_htype_pid_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_pid_t=yes- if ac_fn_c_compute_int "$LINENO" "((pid_t)((int)((pid_t)1.4))) == ((pid_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_pid_t=no-fi--- if test "$fptools_cv_htype_sup_pid_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(pid_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_pid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(pid_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_pid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(pid_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_pid_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_pid_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_pid_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_pid_t=LDouble- else- fptools_cv_htype_sup_pid_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((pid_t)(-1)) < ((pid_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_pid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(pid_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_pid_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_pid_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_pid_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_pid_t" = no- then-- fptools_cv_htype_pid_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_pid_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_pid_t" >&5-$as_echo "$fptools_cv_htype_pid_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_PID_T $fptools_cv_htype_pid_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for gid_t" >&5-$as_echo_n "checking Haskell type for gid_t... " >&6; }- if ${fptools_cv_htype_gid_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_gid_t=yes- if ac_fn_c_compute_int "$LINENO" "((gid_t)((int)((gid_t)1.4))) == ((gid_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_gid_t=no-fi--- if test "$fptools_cv_htype_sup_gid_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(gid_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_gid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(gid_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_gid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(gid_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_gid_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_gid_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_gid_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_gid_t=LDouble- else- fptools_cv_htype_sup_gid_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((gid_t)(-1)) < ((gid_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_gid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(gid_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_gid_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_gid_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_gid_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_gid_t" = no- then-- fptools_cv_htype_gid_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_gid_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_gid_t" >&5-$as_echo "$fptools_cv_htype_gid_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_GID_T $fptools_cv_htype_gid_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for uid_t" >&5-$as_echo_n "checking Haskell type for uid_t... " >&6; }- if ${fptools_cv_htype_uid_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_uid_t=yes- if ac_fn_c_compute_int "$LINENO" "((uid_t)((int)((uid_t)1.4))) == ((uid_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uid_t=no-fi--- if test "$fptools_cv_htype_sup_uid_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(uid_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uid_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uid_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uid_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_uid_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_uid_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_uid_t=LDouble- else- fptools_cv_htype_sup_uid_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((uid_t)(-1)) < ((uid_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uid_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uid_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uid_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_uid_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_uid_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_uid_t" = no- then-- fptools_cv_htype_uid_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_uid_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_uid_t" >&5-$as_echo "$fptools_cv_htype_uid_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UID_T $fptools_cv_htype_uid_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for cc_t" >&5-$as_echo_n "checking Haskell type for cc_t... " >&6; }- if ${fptools_cv_htype_cc_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_cc_t=yes- if ac_fn_c_compute_int "$LINENO" "((cc_t)((int)((cc_t)1.4))) == ((cc_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_cc_t=no-fi--- if test "$fptools_cv_htype_sup_cc_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(cc_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_cc_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(cc_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_cc_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(cc_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_cc_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_cc_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_cc_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_cc_t=LDouble- else- fptools_cv_htype_sup_cc_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((cc_t)(-1)) < ((cc_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_cc_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(cc_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_cc_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_cc_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_cc_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_cc_t" = no- then-- fptools_cv_htype_cc_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_cc_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_cc_t" >&5-$as_echo "$fptools_cv_htype_cc_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_CC_T $fptools_cv_htype_cc_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for speed_t" >&5-$as_echo_n "checking Haskell type for speed_t... " >&6; }- if ${fptools_cv_htype_speed_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_speed_t=yes- if ac_fn_c_compute_int "$LINENO" "((speed_t)((int)((speed_t)1.4))) == ((speed_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_speed_t=no-fi--- if test "$fptools_cv_htype_sup_speed_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(speed_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_speed_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(speed_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_speed_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(speed_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_speed_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_speed_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_speed_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_speed_t=LDouble- else- fptools_cv_htype_sup_speed_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((speed_t)(-1)) < ((speed_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_speed_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(speed_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_speed_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_speed_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_speed_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_speed_t" = no- then-- fptools_cv_htype_speed_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_speed_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_speed_t" >&5-$as_echo "$fptools_cv_htype_speed_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SPEED_T $fptools_cv_htype_speed_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for tcflag_t" >&5-$as_echo_n "checking Haskell type for tcflag_t... " >&6; }- if ${fptools_cv_htype_tcflag_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_tcflag_t=yes- if ac_fn_c_compute_int "$LINENO" "((tcflag_t)((int)((tcflag_t)1.4))) == ((tcflag_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_tcflag_t=no-fi--- if test "$fptools_cv_htype_sup_tcflag_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(tcflag_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_tcflag_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(tcflag_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_tcflag_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(tcflag_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_tcflag_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_tcflag_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_tcflag_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_tcflag_t=LDouble- else- fptools_cv_htype_sup_tcflag_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((tcflag_t)(-1)) < ((tcflag_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_tcflag_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(tcflag_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_tcflag_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_tcflag_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_tcflag_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_tcflag_t" = no- then-- fptools_cv_htype_tcflag_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_tcflag_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_tcflag_t" >&5-$as_echo "$fptools_cv_htype_tcflag_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_TCFLAG_T $fptools_cv_htype_tcflag_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for nlink_t" >&5-$as_echo_n "checking Haskell type for nlink_t... " >&6; }- if ${fptools_cv_htype_nlink_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_nlink_t=yes- if ac_fn_c_compute_int "$LINENO" "((nlink_t)((int)((nlink_t)1.4))) == ((nlink_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_nlink_t=no-fi--- if test "$fptools_cv_htype_sup_nlink_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(nlink_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_nlink_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(nlink_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_nlink_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(nlink_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_nlink_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_nlink_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_nlink_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_nlink_t=LDouble- else- fptools_cv_htype_sup_nlink_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((nlink_t)(-1)) < ((nlink_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_nlink_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(nlink_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_nlink_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_nlink_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_nlink_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_nlink_t" = no- then-- fptools_cv_htype_nlink_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_nlink_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_nlink_t" >&5-$as_echo "$fptools_cv_htype_nlink_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_NLINK_T $fptools_cv_htype_nlink_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for ssize_t" >&5-$as_echo_n "checking Haskell type for ssize_t... " >&6; }- if ${fptools_cv_htype_ssize_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_ssize_t=yes- if ac_fn_c_compute_int "$LINENO" "((ssize_t)((int)((ssize_t)1.4))) == ((ssize_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ssize_t=no-fi--- if test "$fptools_cv_htype_sup_ssize_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(ssize_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ssize_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ssize_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ssize_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ssize_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ssize_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_ssize_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_ssize_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_ssize_t=LDouble- else- fptools_cv_htype_sup_ssize_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((ssize_t)(-1)) < ((ssize_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ssize_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(ssize_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_ssize_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_ssize_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_ssize_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_ssize_t" = no- then-- fptools_cv_htype_ssize_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_ssize_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_ssize_t" >&5-$as_echo "$fptools_cv_htype_ssize_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_SSIZE_T $fptools_cv_htype_ssize_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for rlim_t" >&5-$as_echo_n "checking Haskell type for rlim_t... " >&6; }- if ${fptools_cv_htype_rlim_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_rlim_t=yes- if ac_fn_c_compute_int "$LINENO" "((rlim_t)((int)((rlim_t)1.4))) == ((rlim_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_rlim_t=no-fi--- if test "$fptools_cv_htype_sup_rlim_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(rlim_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_rlim_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(rlim_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_rlim_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(rlim_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_rlim_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_rlim_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_rlim_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_rlim_t=LDouble- else- fptools_cv_htype_sup_rlim_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((rlim_t)(-1)) < ((rlim_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_rlim_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(rlim_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_rlim_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_rlim_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_rlim_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_rlim_t" = no- then-- fptools_cv_htype_rlim_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_rlim_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_rlim_t" >&5-$as_echo "$fptools_cv_htype_rlim_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_RLIM_T $fptools_cv_htype_rlim_t-_ACEOF-- fi------------ { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for intptr_t" >&5-$as_echo_n "checking Haskell type for intptr_t... " >&6; }- if ${fptools_cv_htype_intptr_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_intptr_t=yes- if ac_fn_c_compute_int "$LINENO" "((intptr_t)((int)((intptr_t)1.4))) == ((intptr_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intptr_t=no-fi--- if test "$fptools_cv_htype_sup_intptr_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(intptr_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intptr_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(intptr_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intptr_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(intptr_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intptr_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_intptr_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_intptr_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_intptr_t=LDouble- else- fptools_cv_htype_sup_intptr_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((intptr_t)(-1)) < ((intptr_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intptr_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(intptr_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intptr_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_intptr_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_intptr_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_intptr_t" = no- then-- fptools_cv_htype_intptr_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_intptr_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_intptr_t" >&5-$as_echo "$fptools_cv_htype_intptr_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_INTPTR_T $fptools_cv_htype_intptr_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for uintptr_t" >&5-$as_echo_n "checking Haskell type for uintptr_t... " >&6; }- if ${fptools_cv_htype_uintptr_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_uintptr_t=yes- if ac_fn_c_compute_int "$LINENO" "((uintptr_t)((int)((uintptr_t)1.4))) == ((uintptr_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintptr_t=no-fi--- if test "$fptools_cv_htype_sup_uintptr_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(uintptr_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintptr_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uintptr_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintptr_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uintptr_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintptr_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_uintptr_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_uintptr_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_uintptr_t=LDouble- else- fptools_cv_htype_sup_uintptr_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((uintptr_t)(-1)) < ((uintptr_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintptr_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uintptr_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintptr_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_uintptr_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_uintptr_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_uintptr_t" = no- then-- fptools_cv_htype_uintptr_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_uintptr_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_uintptr_t" >&5-$as_echo "$fptools_cv_htype_uintptr_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UINTPTR_T $fptools_cv_htype_uintptr_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for intmax_t" >&5-$as_echo_n "checking Haskell type for intmax_t... " >&6; }- if ${fptools_cv_htype_intmax_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_intmax_t=yes- if ac_fn_c_compute_int "$LINENO" "((intmax_t)((int)((intmax_t)1.4))) == ((intmax_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intmax_t=no-fi--- if test "$fptools_cv_htype_sup_intmax_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(intmax_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intmax_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(intmax_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intmax_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(intmax_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intmax_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_intmax_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_intmax_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_intmax_t=LDouble- else- fptools_cv_htype_sup_intmax_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((intmax_t)(-1)) < ((intmax_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intmax_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(intmax_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_intmax_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_intmax_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_intmax_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_intmax_t" = no- then-- fptools_cv_htype_intmax_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_intmax_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_intmax_t" >&5-$as_echo "$fptools_cv_htype_intmax_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_INTMAX_T $fptools_cv_htype_intmax_t-_ACEOF-- fi----------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Haskell type for uintmax_t" >&5-$as_echo_n "checking Haskell type for uintmax_t... " >&6; }- if ${fptools_cv_htype_uintmax_t+:} false; then :- $as_echo_n "(cached) " >&6-else-- fptools_cv_htype_sup_uintmax_t=yes- if ac_fn_c_compute_int "$LINENO" "((uintmax_t)((int)((uintmax_t)1.4))) == ((uintmax_t)1.4)" "HTYPE_IS_INTEGRAL" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintmax_t=no-fi--- if test "$fptools_cv_htype_sup_uintmax_t" = "yes"- then- if test "$HTYPE_IS_INTEGRAL" -eq 0- then- if ac_fn_c_compute_int "$LINENO" "sizeof(uintmax_t) == sizeof(float)" "HTYPE_IS_FLOAT" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintmax_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uintmax_t) == sizeof(double)" "HTYPE_IS_DOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintmax_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uintmax_t) == sizeof(long double)" "HTYPE_IS_LDOUBLE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintmax_t=no-fi--- if test "$HTYPE_IS_FLOAT" -eq 1- then- fptools_cv_htype_uintmax_t=Float- elif test "$HTYPE_IS_DOUBLE" -eq 1- then- fptools_cv_htype_uintmax_t=Double- elif test "$HTYPE_IS_LDOUBLE" -eq 1- then- fptools_cv_htype_uintmax_t=LDouble- else- fptools_cv_htype_sup_uintmax_t=no- fi- else- if ac_fn_c_compute_int "$LINENO" "((uintmax_t)(-1)) < ((uintmax_t)0)" "HTYPE_IS_SIGNED" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintmax_t=no-fi--- if ac_fn_c_compute_int "$LINENO" "sizeof(uintmax_t) * 8" "HTYPE_SIZE" "-#include <stdio.h>-#include <stddef.h>--#if HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif--#if HAVE_UNISTD_H-# include <unistd.h>-#endif--#if HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif--#if HAVE_FCNTL_H-# include <fcntl.h>-#endif--#if HAVE_SIGNAL_H-# include <signal.h>-#endif--#if HAVE_TIME_H-# include <time.h>-#endif--#if HAVE_TERMIOS_H-# include <termios.h>-#endif--#if HAVE_STRING_H-# include <string.h>-#endif--#if HAVE_CTYPE_H-# include <ctype.h>-#endif--#if HAVE_INTTYPES_H-# include <inttypes.h>-#else-# if HAVE_STDINT_H-# include <stdint.h>-# endif-#endif--#if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-#endif--#include <stdlib.h>-"; then :--else- fptools_cv_htype_sup_uintmax_t=no-fi--- if test "$HTYPE_IS_SIGNED" -eq 0- then- fptools_cv_htype_uintmax_t="Word$HTYPE_SIZE"- else- fptools_cv_htype_uintmax_t="Int$HTYPE_SIZE"- fi- fi- fi--fi-- if test "$fptools_cv_htype_sup_uintmax_t" = no- then-- fptools_cv_htype_uintmax_t=NotReallyAType- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5-$as_echo "not supported" >&6; }-- fi-- if test "$fptools_cv_htype_sup_uintmax_t" = yes; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fptools_cv_htype_uintmax_t" >&5-$as_echo "$fptools_cv_htype_uintmax_t" >&6; }--cat >>confdefs.h <<_ACEOF-#define HTYPE_UINTMAX_T $fptools_cv_htype_uintmax_t-_ACEOF-- fi----# test errno values-for fp_const_name in E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EADV EAFNOSUPPORT EAGAIN EALREADY EBADF EBADMSG EBADRPC EBUSY ECHILD ECOMM ECONNABORTED ECONNREFUSED ECONNRESET EDEADLK EDESTADDRREQ EDIRTY EDOM EDQUOT EEXIST EFAULT EFBIG EFTYPE EHOSTDOWN EHOSTUNREACH EIDRM EILSEQ EINPROGRESS EINTR EINVAL EIO EISCONN EISDIR ELOOP EMFILE EMLINK EMSGSIZE EMULTIHOP ENAMETOOLONG ENETDOWN ENETRESET ENETUNREACH ENFILE ENOBUFS ENODATA ENODEV ENOENT ENOEXEC ENOLCK ENOLINK ENOMEM ENOMSG ENONET ENOPROTOOPT ENOSPC ENOSR ENOSTR ENOSYS ENOTBLK ENOTCONN ENOTDIR ENOTEMPTY ENOTSOCK ENOTTY ENXIO EOPNOTSUPP EPERM EPFNOSUPPORT EPIPE EPROCLIM EPROCUNAVAIL EPROGMISMATCH EPROGUNAVAIL EPROTO EPROTONOSUPPORT EPROTOTYPE ERANGE EREMCHG EREMOTE EROFS ERPCMISMATCH ERREMOTE ESHUTDOWN ESOCKTNOSUPPORT ESPIPE ESRCH ESRMNT ESTALE ETIME ETIMEDOUT ETOOMANYREFS ETXTBSY EUSERS EWOULDBLOCK EXDEV ENOCIGAR-do-as_fp_Cache=`$as_echo "fp_cv_const_$fp_const_name" | $as_tr_sh`-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking value of $fp_const_name" >&5-$as_echo_n "checking value of $fp_const_name... " >&6; }-if eval \${$as_fp_Cache+:} false; then :- $as_echo_n "(cached) " >&6-else- if ac_fn_c_compute_int "$LINENO" "$fp_const_name" "fp_check_const_result" "#include <stdio.h>-#include <errno.h>-"; then :--else- fp_check_const_result='-1'-fi---eval "$as_fp_Cache=\$fp_check_const_result"-fi-eval ac_res=\$$as_fp_Cache- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }-cat >>confdefs.h <<_ACEOF-#define `$as_echo "CONST_$fp_const_name" | $as_tr_cpp` `eval 'as_val=${'$as_fp_Cache'};$as_echo "$as_val"'`-_ACEOF--done---# we need SIGINT in TopHandler.lhs-for fp_const_name in SIGINT-do-as_fp_Cache=`$as_echo "fp_cv_const_$fp_const_name" | $as_tr_sh`-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking value of $fp_const_name" >&5-$as_echo_n "checking value of $fp_const_name... " >&6; }-if eval \${$as_fp_Cache+:} false; then :- $as_echo_n "(cached) " >&6-else- if ac_fn_c_compute_int "$LINENO" "$fp_const_name" "fp_check_const_result" "-#if HAVE_SIGNAL_H-#include <signal.h>-#endif-"; then :--else- fp_check_const_result='-1'-fi---eval "$as_fp_Cache=\$fp_check_const_result"-fi-eval ac_res=\$$as_fp_Cache- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }-cat >>confdefs.h <<_ACEOF-#define `$as_echo "CONST_$fp_const_name" | $as_tr_cpp` `eval 'as_val=${'$as_fp_Cache'};$as_echo "$as_val"'`-_ACEOF--done---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking value of O_BINARY" >&5-$as_echo_n "checking value of O_BINARY... " >&6; }-if ${fp_cv_const_O_BINARY+:} false; then :- $as_echo_n "(cached) " >&6-else- if ac_fn_c_compute_int "$LINENO" "O_BINARY" "fp_check_const_result" "#include <fcntl.h>-"; then :--else- fp_check_const_result=0-fi---fp_cv_const_O_BINARY=$fp_check_const_result-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fp_cv_const_O_BINARY" >&5-$as_echo "$fp_cv_const_O_BINARY" >&6; }-cat >>confdefs.h <<_ACEOF-#define CONST_O_BINARY $fp_cv_const_O_BINARY-_ACEOF---# We don't use iconv or libcharset on Windows, but if configure finds-# them then it can cause problems. So we don't even try looking if-# we are on Windows.-# See http://www.haskell.org/pipermail/cvs-ghc/2011-September/065980.html-if test "$WINDOWS" = "NO"-then--# We can't just use AC_SEARCH_LIBS for this, as on OpenBSD the iconv.h-# header needs to be included as iconv_open is #define'd to something-# else. We therefore use our own FP_SEARCH_LIBS_PROTO, which allows us-# to give prototype text.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing iconv" >&5-$as_echo_n "checking for library containing iconv... " >&6; }-if ${ac_cv_search_iconv+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_func_search_save_LIBS=$LIBS-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--#include <stddef.h>-#include <iconv.h>--int-main ()-{-iconv_t cd;- cd = iconv_open("", "");- iconv(cd,NULL,NULL,NULL,NULL);- iconv_close(cd);- ;- return 0;-}-_ACEOF-for ac_lib in '' iconv; do- if test -z "$ac_lib"; then- ac_res="none required"- else- ac_res=-l$ac_lib- LIBS="-l$ac_lib $ac_func_search_save_LIBS"- fi- if ac_fn_c_try_link "$LINENO"; then :- ac_cv_search_iconv=$ac_res-fi-rm -f core conftest.err conftest.$ac_objext \- conftest$ac_exeext- if ${ac_cv_search_iconv+:} false; then :- break-fi-done-if ${ac_cv_search_iconv+:} false; then :--else- ac_cv_search_iconv=no-fi-rm conftest.$ac_ext-LIBS=$ac_func_search_save_LIBS-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_iconv" >&5-$as_echo "$ac_cv_search_iconv" >&6; }-ac_res=$ac_cv_search_iconv-if test "$ac_res" != no; then :- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"- EXTRA_LIBS="$EXTRA_LIBS $ac_lib"-else- as_fn_error $? "iconv is required on non-Windows platforms" "$LINENO" 5-fi--# If possible, we use libcharset instead of nl_langinfo(CODESET) to-# determine the current locale's character encoding.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing locale_charset" >&5-$as_echo_n "checking for library containing locale_charset... " >&6; }-if ${ac_cv_search_locale_charset+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_func_search_save_LIBS=$LIBS-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <libcharset.h>-int-main ()-{-const char* charset = locale_charset();- ;- return 0;-}-_ACEOF-for ac_lib in '' charset; do- if test -z "$ac_lib"; then- ac_res="none required"- else- ac_res=-l$ac_lib- LIBS="-l$ac_lib $ac_func_search_save_LIBS"- fi- if ac_fn_c_try_link "$LINENO"; then :- ac_cv_search_locale_charset=$ac_res-fi-rm -f core conftest.err conftest.$ac_objext \- conftest$ac_exeext- if ${ac_cv_search_locale_charset+:} false; then :- break-fi-done-if ${ac_cv_search_locale_charset+:} false; then :--else- ac_cv_search_locale_charset=no-fi-rm conftest.$ac_ext-LIBS=$ac_func_search_save_LIBS-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_locale_charset" >&5-$as_echo "$ac_cv_search_locale_charset" >&6; }-ac_res=$ac_cv_search_locale_charset-if test "$ac_res" != no; then :- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"--$as_echo "#define HAVE_LIBCHARSET 1" >>confdefs.h-- EXTRA_LIBS="$EXTRA_LIBS $ac_lib"-fi--fi--# Hack - md5.h needs HsFFI.h. Is there a better way to do this?-CFLAGS="-I../../includes $CFLAGS"-# The cast to long int works around a bug in the HP C Compiler-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.-# This bug is HP SR number 8606223364.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of struct MD5Context" >&5-$as_echo_n "checking size of struct MD5Context... " >&6; }-if ${ac_cv_sizeof_struct_MD5Context+:} false; then :- $as_echo_n "(cached) " >&6-else- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct MD5Context))" "ac_cv_sizeof_struct_MD5Context" "#include \"include/md5.h\"-"; then :--else- if test "$ac_cv_type_struct_MD5Context" = yes; then- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error 77 "cannot compute sizeof (struct MD5Context)-See \`config.log' for more details" "$LINENO" 5; }- else- ac_cv_sizeof_struct_MD5Context=0- fi-fi--fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_struct_MD5Context" >&5-$as_echo "$ac_cv_sizeof_struct_MD5Context" >&6; }----cat >>confdefs.h <<_ACEOF-#define SIZEOF_STRUCT_MD5CONTEXT $ac_cv_sizeof_struct_MD5Context-_ACEOF-----ac_config_files="$ac_config_files base.buildinfo"---cat >confcache <<\_ACEOF-# This file is a shell script that caches the results of configure-# tests run on this system so they can be shared between configure-# scripts and configure runs, see configure's option --config-cache.-# It is not useful on other systems. If it contains results you don't-# want to keep, you may remove or edit it.-#-# config.status only pays attention to the cache file if you give it-# the --recheck option to rerun configure.-#-# `ac_cv_env_foo' variables (set or unset) will be overridden when-# loading this file, other *unset* `ac_cv_foo' will be assigned the-# following values.--_ACEOF--# The following way of writing the cache mishandles newlines in values,-# but we know of no workaround that is simple, portable, and efficient.-# So, we kill variables containing newlines.-# Ultrix sh set writes to stderr and can't be redirected directly,-# and sets the high bit in the cache file unless we assign to the vars.-(- for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do- eval ac_val=\$$ac_var- case $ac_val in #(- *${as_nl}*)- case $ac_var in #(- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;- esac- case $ac_var in #(- _ | IFS | as_nl) ;; #(- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(- *) { eval $ac_var=; unset $ac_var;} ;;- esac ;;- esac- done-- (set) 2>&1 |- case $as_nl`(ac_space=' '; set) 2>&1` in #(- *${as_nl}ac_space=\ *)- # `set' does not quote correctly, so add quotes: double-quote- # substitution turns \\\\ into \\, and sed turns \\ into \.- sed -n \- "s/'/'\\\\''/g;- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"- ;; #(- *)- # `set' quotes correctly as required by POSIX, so do not add quotes.- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"- ;;- esac |- sort-) |- sed '- /^ac_cv_env_/b end- t clear- :clear- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/- t end- s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/- :end' >>confcache-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else- if test -w "$cache_file"; then- if test "x$cache_file" != "x/dev/null"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5-$as_echo "$as_me: updating cache $cache_file" >&6;}- if test ! -f "$cache_file" || test -h "$cache_file"; then- cat confcache >"$cache_file"- else- case $cache_file in #(- */* | ?:*)- mv -f confcache "$cache_file"$$ &&- mv -f "$cache_file"$$ "$cache_file" ;; #(- *)- mv -f confcache "$cache_file" ;;- esac- fi- fi- else- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}- fi-fi-rm -f confcache--test "x$prefix" = xNONE && prefix=$ac_default_prefix-# Let make expand exec_prefix.-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'--DEFS=-DHAVE_CONFIG_H--ac_libobjs=-ac_ltlibobjs=-U=-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue- # 1. Remove the extension, and $U if already installed.- ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`- # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR- # will be set to the directory where LIBOBJS objects are built.- as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"- as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'-done-LIBOBJS=$ac_libobjs--LTLIBOBJS=$ac_ltlibobjs----: "${CONFIG_STATUS=./config.status}"-ac_write_fail=0-ac_clean_files_save=$ac_clean_files-ac_clean_files="$ac_clean_files $CONFIG_STATUS"-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}-as_write_fail=0-cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1-#! $SHELL-# Generated by $as_me.-# Run this file to recreate the current configuration.-# Compiler output produced by configure, useful for debugging-# configure, is in config.log if it exists.--debug=false-ac_cs_recheck=false-ac_cs_silent=false--SHELL=\${CONFIG_SHELL-$SHELL}-export SHELL-_ASEOF-cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1-## -------------------- ##-## M4sh Initialization. ##-## -------------------- ##--# Be more Bourne compatible-DUALCASE=1; export DUALCASE # for MKS sh-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :- emulate sh- NULLCMD=:- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which- # is contrary to our usage. Disable this feature.- alias -g '${1+"$@"}'='"$@"'- setopt NO_GLOB_SUBST-else- case `(set -o) 2>/dev/null` in #(- *posix*) :- set -o posix ;; #(- *) :- ;;-esac-fi---as_nl='-'-export as_nl-# Printing a long string crashes Solaris 7 /usr/bin/printf.-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo-# Prefer a ksh shell builtin over an external printf program on Solaris,-# but without wasting forks for bash or zsh.-if test -z "$BASH_VERSION$ZSH_VERSION" \- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='print -r --'- as_echo_n='print -rn --'-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='printf %s\n'- as_echo_n='printf %s'-else- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'- as_echo_n='/usr/ucb/echo -n'- else- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'- as_echo_n_body='eval- arg=$1;- case $arg in #(- *"$as_nl"*)- expr "X$arg" : "X\\(.*\\)$as_nl";- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;- esac;- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"- '- export as_echo_n_body- as_echo_n='sh -c $as_echo_n_body as_echo'- fi- export as_echo_body- as_echo='sh -c $as_echo_body as_echo'-fi--# The user is always right.-if test "${PATH_SEPARATOR+set}" != set; then- PATH_SEPARATOR=:- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||- PATH_SEPARATOR=';'- }-fi---# IFS-# We need space, tab and new line, in precisely that order. Quoting is-# there to prevent editors from complaining about space-tab.-# (If _AS_PATH_WALK were called with IFS unset, it would disable word-# splitting by setting IFS to empty value.)-IFS=" "" $as_nl"--# Find who we are. Look in the path if we contain no directory separator.-as_myself=-case $0 in #((- *[\\/]* ) as_myself=$0 ;;- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break- done-IFS=$as_save_IFS-- ;;-esac-# We did not find ourselves, most probably we were run as `sh COMMAND'-# in which case we are not to be found in the path.-if test "x$as_myself" = x; then- as_myself=$0-fi-if test ! -f "$as_myself"; then- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2- exit 1-fi--# Unset variables that we do not need and which cause bugs (e.g. in-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"-# suppresses any "Segmentation fault" message there. '((' could-# trigger a bug in pdksh 5.2.14.-for as_var in BASH_ENV ENV MAIL MAILPATH-do eval test x\${$as_var+set} = xset \- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :-done-PS1='$ '-PS2='> '-PS4='+ '--# NLS nuisances.-LC_ALL=C-export LC_ALL-LANGUAGE=C-export LANGUAGE--# CDPATH.-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH---# as_fn_error STATUS ERROR [LINENO LOG_FD]-# -----------------------------------------# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the-# script with STATUS, using 1 if that was 0.-as_fn_error ()-{- as_status=$1; test $as_status -eq 0 && as_status=1- if test "$4"; then- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4- fi- $as_echo "$as_me: error: $2" >&2- as_fn_exit $as_status-} # as_fn_error---# as_fn_set_status STATUS-# ------------------------# Set $? to STATUS, without forking.-as_fn_set_status ()-{- return $1-} # as_fn_set_status--# as_fn_exit STATUS-# ------------------# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.-as_fn_exit ()-{- set +e- as_fn_set_status $1- exit $1-} # as_fn_exit--# as_fn_unset VAR-# ----------------# Portably unset VAR.-as_fn_unset ()-{- { eval $1=; unset $1;}-}-as_unset=as_fn_unset-# as_fn_append VAR VALUE-# -----------------------# Append the text in VALUE to the end of the definition contained in VAR. Take-# advantage of any shell optimizations that allow amortized linear growth over-# repeated appends, instead of the typical quadratic growth present in naive-# implementations.-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :- eval 'as_fn_append ()- {- eval $1+=\$2- }'-else- as_fn_append ()- {- eval $1=\$$1\$2- }-fi # as_fn_append--# as_fn_arith ARG...-# -------------------# Perform arithmetic evaluation on the ARGs, and store the result in the-# global $as_val. Take advantage of shells that can avoid forks. The arguments-# must be portable across $(()) and expr.-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :- eval 'as_fn_arith ()- {- as_val=$(( $* ))- }'-else- as_fn_arith ()- {- as_val=`expr "$@" || test $? -eq 1`- }-fi # as_fn_arith---if expr a : '\(a\)' >/dev/null 2>&1 &&- test "X`expr 00001 : '.*\(...\)'`" = X001; then- as_expr=expr-else- as_expr=false-fi--if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then- as_basename=basename-else- as_basename=false-fi--if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then- as_dirname=dirname-else- as_dirname=false-fi--as_me=`$as_basename -- "$0" ||-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \- X"$0" : 'X\(//\)$' \| \- X"$0" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X/"$0" |- sed '/^.*\/\([^/][^/]*\)\/*$/{- s//\1/- q- }- /^X\/\(\/\/\)$/{- s//\1/- q- }- /^X\/\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`--# Avoid depending upon Character Ranges.-as_cr_letters='abcdefghijklmnopqrstuvwxyz'-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'-as_cr_Letters=$as_cr_letters$as_cr_LETTERS-as_cr_digits='0123456789'-as_cr_alnum=$as_cr_Letters$as_cr_digits--ECHO_C= ECHO_N= ECHO_T=-case `echo -n x` in #(((((--n*)- case `echo 'xy\c'` in- *c*) ECHO_T=' ';; # ECHO_T is single tab character.- xy) ECHO_C='\c';;- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null- ECHO_T=' ';;- esac;;-*)- ECHO_N='-n';;-esac--rm -f conf$$ conf$$.exe conf$$.file-if test -d conf$$.dir; then- rm -f conf$$.dir/conf$$.file-else- rm -f conf$$.dir- mkdir conf$$.dir 2>/dev/null-fi-if (echo >conf$$.file) 2>/dev/null; then- if ln -s conf$$.file conf$$ 2>/dev/null; then- as_ln_s='ln -s'- # ... but there are two gotchas:- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.- # In both cases, we have to default to `cp -p'.- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||- as_ln_s='cp -p'- elif ln conf$$.file conf$$ 2>/dev/null; then- as_ln_s=ln- else- as_ln_s='cp -p'- fi-else- as_ln_s='cp -p'-fi-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file-rmdir conf$$.dir 2>/dev/null---# as_fn_mkdir_p-# --------------# Create "$as_dir" as a directory, including parents if necessary.-as_fn_mkdir_p ()-{-- case $as_dir in #(- -*) as_dir=./$as_dir;;- esac- test -d "$as_dir" || eval $as_mkdir_p || {- as_dirs=- while :; do- case $as_dir in #(- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(- *) as_qdir=$as_dir;;- esac- as_dirs="'$as_qdir' $as_dirs"- as_dir=`$as_dirname -- "$as_dir" ||-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$as_dir" : 'X\(//\)[^/]' \| \- X"$as_dir" : 'X\(//\)$' \| \- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$as_dir" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- test -d "$as_dir" && break- done- test -z "$as_dirs" || eval "mkdir $as_dirs"- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"---} # as_fn_mkdir_p-if mkdir -p . 2>/dev/null; then- as_mkdir_p='mkdir -p "$as_dir"'-else- test -d ./-p && rmdir ./-p- as_mkdir_p=false-fi--if test -x / >/dev/null 2>&1; then- as_test_x='test -x'-else- if ls -dL / >/dev/null 2>&1; then- as_ls_L_option=L- else- as_ls_L_option=- fi- as_test_x='- eval sh -c '\''- if test -d "$1"; then- test -d "$1/.";- else- case $1 in #(- -*)set "./$1";;- esac;- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((- ???[sx]*):;;*)false;;esac;fi- '\'' sh- '-fi-as_executable_p=$as_test_x--# Sed expression to map a string onto a valid CPP name.-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"--# Sed expression to map a string onto a valid variable name.-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"---exec 6>&1-## ----------------------------------- ##-## Main body of $CONFIG_STATUS script. ##-## ----------------------------------- ##-_ASEOF-test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-# Save the log message, to keep $0 and so on meaningful, and to-# report actual input values of CONFIG_FILES etc. instead of their-# values after options handling.-ac_log="-This file was extended by Haskell base package $as_me 1.0, which was-generated by GNU Autoconf 2.68. Invocation command line was-- CONFIG_FILES = $CONFIG_FILES- CONFIG_HEADERS = $CONFIG_HEADERS- CONFIG_LINKS = $CONFIG_LINKS- CONFIG_COMMANDS = $CONFIG_COMMANDS- $ $0 $@--on `(hostname || uname -n) 2>/dev/null | sed 1q`-"--_ACEOF--case $ac_config_files in *"-"*) set x $ac_config_files; shift; ac_config_files=$*;;-esac--case $ac_config_headers in *"-"*) set x $ac_config_headers; shift; ac_config_headers=$*;;-esac---cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-# Files that config.status was made for.-config_files="$ac_config_files"-config_headers="$ac_config_headers"--_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-ac_cs_usage="\-\`$as_me' instantiates files and other configuration actions-from templates according to the current configuration. Unless the files-and actions are specified as TAGs, all are instantiated by default.--Usage: $0 [OPTION]... [TAG]...-- -h, --help print this help, then exit- -V, --version print version number and configuration settings, then exit- --config print configuration, then exit- -q, --quiet, --silent- do not print progress messages- -d, --debug don't remove temporary files- --recheck update $as_me by reconfiguring in the same conditions- --file=FILE[:TEMPLATE]- instantiate the configuration file FILE- --header=FILE[:TEMPLATE]- instantiate the configuration header FILE--Configuration files:-$config_files--Configuration headers:-$config_headers--Report bugs to <libraries@haskell.org>."--_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"-ac_cs_version="\\-Haskell base package config.status 1.0-configured by $0, generated by GNU Autoconf 2.68,- with options \\"\$ac_cs_config\\"--Copyright (C) 2010 Free Software Foundation, Inc.-This config.status script is free software; the Free Software Foundation-gives unlimited permission to copy, distribute and modify it."--ac_pwd='$ac_pwd'-srcdir='$srcdir'-test -n "\$AWK" || AWK=awk-_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-# The default lists apply if the user does not specify any file.-ac_need_defaults=:-while test $# != 0-do- case $1 in- --*=?*)- ac_option=`expr "X$1" : 'X\([^=]*\)='`- ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`- ac_shift=:- ;;- --*=)- ac_option=`expr "X$1" : 'X\([^=]*\)='`- ac_optarg=- ac_shift=:- ;;- *)- ac_option=$1- ac_optarg=$2- ac_shift=shift- ;;- esac-- case $ac_option in- # Handling of the options.- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)- ac_cs_recheck=: ;;- --version | --versio | --versi | --vers | --ver | --ve | --v | -V )- $as_echo "$ac_cs_version"; exit ;;- --config | --confi | --conf | --con | --co | --c )- $as_echo "$ac_cs_config"; exit ;;- --debug | --debu | --deb | --de | --d | -d )- debug=: ;;- --file | --fil | --fi | --f )- $ac_shift- case $ac_optarg in- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;- '') as_fn_error $? "missing file argument" ;;- esac- as_fn_append CONFIG_FILES " '$ac_optarg'"- ac_need_defaults=false;;- --header | --heade | --head | --hea )- $ac_shift- case $ac_optarg in- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;- esac- as_fn_append CONFIG_HEADERS " '$ac_optarg'"- ac_need_defaults=false;;- --he | --h)- # Conflict between --help and --header- as_fn_error $? "ambiguous option: \`$1'-Try \`$0 --help' for more information.";;- --help | --hel | -h )- $as_echo "$ac_cs_usage"; exit ;;- -q | -quiet | --quiet | --quie | --qui | --qu | --q \- | -silent | --silent | --silen | --sile | --sil | --si | --s)- ac_cs_silent=: ;;-- # This is an error.- -*) as_fn_error $? "unrecognized option: \`$1'-Try \`$0 --help' for more information." ;;-- *) as_fn_append ac_config_targets " $1"- ac_need_defaults=false ;;-- esac- shift-done--ac_configure_extra_args=--if $ac_cs_silent; then- exec 6>/dev/null- ac_configure_extra_args="$ac_configure_extra_args --silent"-fi--_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-if \$ac_cs_recheck; then- set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion- shift- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6- CONFIG_SHELL='$SHELL'- export CONFIG_SHELL- exec "\$@"-fi--_ACEOF-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-exec 5>>config.log-{- echo- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX-## Running $as_me. ##-_ASBOX- $as_echo "$ac_log"-} >&5--_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1--# Handling of arguments.-for ac_config_target in $ac_config_targets-do- case $ac_config_target in- "include/HsBaseConfig.h") CONFIG_HEADERS="$CONFIG_HEADERS include/HsBaseConfig.h" ;;- "include/EventConfig.h") CONFIG_HEADERS="$CONFIG_HEADERS include/EventConfig.h" ;;- "base.buildinfo") CONFIG_FILES="$CONFIG_FILES base.buildinfo" ;;-- *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;- esac-done---# If the user did not use the arguments to specify the items to instantiate,-# then the envvar interface is used. Set only those that are not.-# We use the long form for the default assignment because of an extremely-# bizarre bug on SunOS 4.1.3.-if $ac_need_defaults; then- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers-fi--# Have a temporary directory for convenience. Make it in the build tree-# simply because there is no reason against having it here, and in addition,-# creating and moving files from /tmp can sometimes cause problems.-# Hook for its removal unless debugging.-# Note that there is a small window in which the directory will not be cleaned:-# after its creation but before its name has been assigned to `$tmp'.-$debug ||-{- tmp= ac_tmp=- trap 'exit_status=$?- : "${ac_tmp:=$tmp}"- { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status-' 0- trap 'as_fn_exit 1' 1 2 13 15-}-# Create a (secure) tmp directory for tmp files.--{- tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&- test -d "$tmp"-} ||-{- tmp=./conf$$-$RANDOM- (umask 077 && mkdir "$tmp")-} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5-ac_tmp=$tmp--# Set up the scripts for CONFIG_FILES section.-# No need to generate them if there are no CONFIG_FILES.-# This happens for instance with `./config.status config.h'.-if test -n "$CONFIG_FILES"; then---ac_cr=`echo X | tr X '\015'`-# On cygwin, bash can eat \r inside `` if the user requested igncr.-# But we know of no other shell where ac_cr would be empty at this-# point, so we can use a bashism as a fallback.-if test "x$ac_cr" = x; then- eval ac_cr=\$\'\\r\'-fi-ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`-if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then- ac_cs_awk_cr='\\r'-else- ac_cs_awk_cr=$ac_cr-fi--echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&-_ACEOF---{- echo "cat >conf$$subs.awk <<_ACEOF" &&- echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&- echo "_ACEOF"-} >conf$$subs.sh ||- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5-ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`-ac_delim='%!_!# '-for ac_last_try in false false false false false :; do- . ./conf$$subs.sh ||- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5-- ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`- if test $ac_delim_n = $ac_delim_num; then- break- elif $ac_last_try; then- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5- else- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "- fi-done-rm -f conf$$subs.sh--cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&-_ACEOF-sed -n '-h-s/^/S["/; s/!.*/"]=/-p-g-s/^[^!]*!//-:repl-t repl-s/'"$ac_delim"'$//-t delim-:nl-h-s/\(.\{148\}\)..*/\1/-t more1-s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/-p-n-b repl-:more1-s/["\\]/\\&/g; s/^/"/; s/$/"\\/-p-g-s/.\{148\}//-t nl-:delim-h-s/\(.\{148\}\)..*/\1/-t more2-s/["\\]/\\&/g; s/^/"/; s/$/"/-p-b-:more2-s/["\\]/\\&/g; s/^/"/; s/$/"\\/-p-g-s/.\{148\}//-t delim-' <conf$$subs.awk | sed '-/^[^""]/{- N- s/\n//-}-' >>$CONFIG_STATUS || ac_write_fail=1-rm -f conf$$subs.awk-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-_ACAWK-cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&- for (key in S) S_is_set[key] = 1- FS = ""--}-{- line = $ 0- nfields = split(line, field, "@")- substed = 0- len = length(field[1])- for (i = 2; i < nfields; i++) {- key = field[i]- keylen = length(key)- if (S_is_set[key]) {- value = S[key]- line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)- len += length(value) + length(field[++i])- substed = 1- } else- len += 1 + keylen- }-- print line-}--_ACAWK-_ACEOF-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then- sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"-else- cat-fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \- || as_fn_error $? "could not setup config files machinery" "$LINENO" 5-_ACEOF--# VPATH may cause trouble with some makes, so we remove sole $(srcdir),-# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and-# trailing colons and then remove the whole line if VPATH becomes empty-# (actually we leave an empty line to preserve line numbers).-if test "x$srcdir" = x.; then- ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{-h-s///-s/^/:/-s/[ ]*$/:/-s/:\$(srcdir):/:/g-s/:\${srcdir}:/:/g-s/:@srcdir@:/:/g-s/^:*//-s/:*$//-x-s/\(=[ ]*\).*/\1/-G-s/\n//-s/^[^=]*=[ ]*$//-}'-fi--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-fi # test -n "$CONFIG_FILES"--# Set up the scripts for CONFIG_HEADERS section.-# No need to generate them if there are no CONFIG_HEADERS.-# This happens for instance with `./config.status Makefile'.-if test -n "$CONFIG_HEADERS"; then-cat >"$ac_tmp/defines.awk" <<\_ACAWK ||-BEGIN {-_ACEOF--# Transform confdefs.h into an awk script `defines.awk', embedded as-# here-document in config.status, that substitutes the proper values into-# config.h.in to produce config.h.--# Create a delimiter string that does not exist in confdefs.h, to ease-# handling of long lines.-ac_delim='%!_!# '-for ac_last_try in false false :; do- ac_tt=`sed -n "/$ac_delim/p" confdefs.h`- if test -z "$ac_tt"; then- break- elif $ac_last_try; then- as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5- else- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "- fi-done--# For the awk script, D is an array of macro values keyed by name,-# likewise P contains macro parameters if any. Preserve backslash-# newline sequences.--ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*-sed -n '-s/.\{148\}/&'"$ac_delim"'/g-t rset-:rset-s/^[ ]*#[ ]*define[ ][ ]*/ /-t def-d-:def-s/\\$//-t bsnl-s/["\\]/\\&/g-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\-D["\1"]=" \3"/p-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p-d-:bsnl-s/["\\]/\\&/g-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\-D["\1"]=" \3\\\\\\n"\\/p-t cont-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p-t cont-d-:cont-n-s/.\{148\}/&'"$ac_delim"'/g-t clear-:clear-s/\\$//-t bsnlc-s/["\\]/\\&/g; s/^/"/; s/$/"/p-d-:bsnlc-s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p-b cont-' <confdefs.h | sed '-s/'"$ac_delim"'/"\\\-"/g' >>$CONFIG_STATUS || ac_write_fail=1--cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1- for (key in D) D_is_set[key] = 1- FS = ""-}-/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {- line = \$ 0- split(line, arg, " ")- if (arg[1] == "#") {- defundef = arg[2]- mac1 = arg[3]- } else {- defundef = substr(arg[1], 2)- mac1 = arg[2]- }- split(mac1, mac2, "(") #)- macro = mac2[1]- prefix = substr(line, 1, index(line, defundef) - 1)- if (D_is_set[macro]) {- # Preserve the white space surrounding the "#".- print prefix "define", macro P[macro] D[macro]- next- } else {- # Replace #undef with comments. This is necessary, for example,- # in the case of _POSIX_SOURCE, which is predefined and required- # on some systems where configure will not decide to define it.- if (defundef == "undef") {- print "/*", prefix defundef, macro, "*/"- next- }- }-}-{ print }-_ACAWK-_ACEOF-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1- as_fn_error $? "could not setup config headers machinery" "$LINENO" 5-fi # test -n "$CONFIG_HEADERS"---eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "-shift-for ac_tag-do- case $ac_tag in- :[FHLC]) ac_mode=$ac_tag; continue;;- esac- case $ac_mode$ac_tag in- :[FHL]*:*);;- :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;- :[FH]-) ac_tag=-:-;;- :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;- esac- ac_save_IFS=$IFS- IFS=:- set x $ac_tag- IFS=$ac_save_IFS- shift- ac_file=$1- shift-- case $ac_mode in- :L) ac_source=$1;;- :[FH])- ac_file_inputs=- for ac_f- do- case $ac_f in- -) ac_f="$ac_tmp/stdin";;- *) # Look for the file first in the build tree, then in the source tree- # (if the path is not absolute). The absolute path cannot be DOS-style,- # because $ac_f cannot contain `:'.- test -f "$ac_f" ||- case $ac_f in- [\\/$]*) false;;- *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;- esac ||- as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;- esac- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac- as_fn_append ac_file_inputs " '$ac_f'"- done-- # Let's still pretend it is `configure' which instantiates (i.e., don't- # use $as_me), people would be surprised to read:- # /* config.h. Generated by config.status. */- configure_input='Generated from '`- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'- `' by configure.'- if test x"$ac_file" != x-; then- configure_input="$ac_file. $configure_input"- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5-$as_echo "$as_me: creating $ac_file" >&6;}- fi- # Neutralize special characters interpreted by sed in replacement strings.- case $configure_input in #(- *\&* | *\|* | *\\* )- ac_sed_conf_input=`$as_echo "$configure_input" |- sed 's/[\\\\&|]/\\\\&/g'`;; #(- *) ac_sed_conf_input=$configure_input;;- esac-- case $ac_tag in- *:-:* | *:-) cat >"$ac_tmp/stdin" \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;- esac- ;;- esac-- ac_dir=`$as_dirname -- "$ac_file" ||-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$ac_file" : 'X\(//\)[^/]' \| \- X"$ac_file" : 'X\(//\)$' \| \- X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$ac_file" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- as_dir="$ac_dir"; as_fn_mkdir_p- ac_builddir=.--case "$ac_dir" in-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;-*)- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`- # A ".." for each directory in $ac_dir_suffix.- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`- case $ac_top_builddir_sub in- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;- esac ;;-esac-ac_abs_top_builddir=$ac_pwd-ac_abs_builddir=$ac_pwd$ac_dir_suffix-# for backward compatibility:-ac_top_builddir=$ac_top_build_prefix--case $srcdir in- .) # We are building in place.- ac_srcdir=.- ac_top_srcdir=$ac_top_builddir_sub- ac_abs_top_srcdir=$ac_pwd ;;- [\\/]* | ?:[\\/]* ) # Absolute name.- ac_srcdir=$srcdir$ac_dir_suffix;- ac_top_srcdir=$srcdir- ac_abs_top_srcdir=$srcdir ;;- *) # Relative name.- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix- ac_top_srcdir=$ac_top_build_prefix$srcdir- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;-esac-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix--- case $ac_mode in- :F)- #- # CONFIG_FILE- #--_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-# If the template does not know about datarootdir, expand it.-# FIXME: This hack should be removed a few years after 2.60.-ac_datarootdir_hack=; ac_datarootdir_seen=-ac_sed_dataroot='-/datarootdir/ {- p- q-}-/@datadir@/p-/@docdir@/p-/@infodir@/p-/@localedir@/p-/@mandir@/p'-case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in-*datarootdir*) ac_datarootdir_seen=yes;;-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}-_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1- ac_datarootdir_hack='- s&@datadir@&$datadir&g- s&@docdir@&$docdir&g- s&@infodir@&$infodir&g- s&@localedir@&$localedir&g- s&@mandir@&$mandir&g- s&\\\${datarootdir}&$datarootdir&g' ;;-esac-_ACEOF--# Neutralize VPATH when `$srcdir' = `.'.-# Shell code in configure.ac might set extrasub.-# FIXME: do we really want to maintain this feature?-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-ac_sed_extra="$ac_vpsub-$extrasub-_ACEOF-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-:t-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b-s|@configure_input@|$ac_sed_conf_input|;t t-s&@top_builddir@&$ac_top_builddir_sub&;t t-s&@top_build_prefix@&$ac_top_build_prefix&;t t-s&@srcdir@&$ac_srcdir&;t t-s&@abs_srcdir@&$ac_abs_srcdir&;t t-s&@top_srcdir@&$ac_top_srcdir&;t t-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t-s&@builddir@&$ac_builddir&;t t-s&@abs_builddir@&$ac_abs_builddir&;t t-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t-$ac_datarootdir_hack-"-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \- >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5--test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&- { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \- "$ac_tmp/out"`; test -z "$ac_out"; } &&- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'-which seems to be undefined. Please make sure it is defined" >&5-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'-which seems to be undefined. Please make sure it is defined" >&2;}-- rm -f "$ac_tmp/stdin"- case $ac_file in- -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;- *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;- esac \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5- ;;- :H)- #- # CONFIG_HEADER- #- if test x"$ac_file" != x-; then- {- $as_echo "/* $configure_input */" \- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"- } >"$ac_tmp/config.h" \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5- if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5-$as_echo "$as_me: $ac_file is unchanged" >&6;}- else- rm -f "$ac_file"- mv "$ac_tmp/config.h" "$ac_file" \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5- fi- else- $as_echo "/* $configure_input */" \- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \- || as_fn_error $? "could not create -" "$LINENO" 5- fi- ;;--- esac--done # for ac_tag---as_fn_exit 0-_ACEOF-ac_clean_files=$ac_clean_files_save--test $ac_write_fail = 0 ||- as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5---# configure is writing to config.log, and then calls config.status.-# config.status does its own redirection, appending to config.log.-# Unfortunately, on DOS this fails, as config.log is still kept open-# by configure, so config.status won't be able to write to it; its-# output is simply discarded. So we exec the FD to /dev/null,-# effectively closing config.log, so it can be properly (re)opened and-# appended to by config.status. When coming back to configure, we-# need to make the FD available again.-if test "$no_create" != yes; then- ac_cs_success=:- ac_config_status_args=- test "$silent" = yes &&- ac_config_status_args="$ac_config_status_args --quiet"- exec 5>/dev/null- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false- exec 5>>config.log- # Use ||, not &&, to avoid exiting from the if with $? = 1, which- # would make configure fail if this is the last instruction.- $ac_cs_success || as_fn_exit 1-fi-if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}-fi-
@@ -1,183 +0,0 @@-AC_INIT([Haskell base package], [1.0], [libraries@haskell.org], [base])--# Safety check: Ensure that we are in the correct source directory.-AC_CONFIG_SRCDIR([include/HsBase.h])--AC_CONFIG_HEADERS([include/HsBaseConfig.h include/EventConfig.h])--AC_ARG_WITH([cc],- [C compiler],- [CC=$withval])-AC_PROG_CC()--case `uname -s` in- MINGW*|CYGWIN*)- WINDOWS=YES;;- *)- WINDOWS=NO;;-esac--# do we have long longs?-AC_CHECK_TYPES([long long])--dnl ** check for full ANSI header (.h) files-AC_HEADER_STDC--# check for specific header (.h) files that we are interested in-AC_CHECK_HEADERS([ctype.h errno.h fcntl.h inttypes.h limits.h signal.h sys/resource.h sys/select.h sys/stat.h sys/syscall.h sys/time.h sys/timeb.h sys/timers.h sys/times.h sys/types.h sys/utsname.h sys/wait.h termios.h time.h unistd.h utime.h windows.h winsock.h langinfo.h poll.h sys/epoll.h sys/event.h sys/eventfd.h])--# Enable large file support. Do this before testing the types ino_t, off_t, and-# rlim_t, because it will affect the result of that test.-AC_SYS_LARGEFILE--dnl ** check for wide-char classifications-dnl FreeBSD has an emtpy wctype.h, so test one of the affected-dnl functions if it's really there.-AC_CHECK_HEADERS([wctype.h], [AC_CHECK_FUNCS(iswspace)])--AC_CHECK_FUNCS([lstat])-AC_CHECK_FUNCS([getclock getrusage times])-AC_CHECK_FUNCS([_chsize ftruncate])--AC_CHECK_FUNCS([epoll_ctl eventfd kevent kevent64 kqueue poll])--# event-related fun--if test "$ac_cv_header_sys_epoll_h" = yes -a "$ac_cv_func_epoll_ctl" = yes; then- AC_DEFINE([HAVE_EPOLL], [1], [Define if you have epoll support.])-fi--if test "$ac_cv_header_sys_event_h" = yes -a "$ac_cv_func_kqueue" = yes; then- AC_DEFINE([HAVE_KQUEUE], [1], [Define if you have kqueue support.])-fi--if test "$ac_cv_header_poll_h" = yes -a "$ac_cv_func_poll" = yes; then- AC_DEFINE([HAVE_POLL], [1], [Define if you have poll support.])-fi--dnl---------------------------------------------------------------------dnl * Deal with arguments telling us iconv is somewhere odd-dnl----------------------------------------------------------------------AC_ARG_WITH([iconv-includes],- [AC_HELP_STRING([--with-iconv-includes],- [directory containing iconv.h])],- [ICONV_INCLUDE_DIRS=$withval; CPPFLAGS="-I$withval"],- [ICONV_INCLUDE_DIRS=])--AC_ARG_WITH([iconv-libraries],- [AC_HELP_STRING([--with-iconv-libraries],- [directory containing iconv library])],- [ICONV_LIB_DIRS=$withval; LDFLAGS="-L$withval"],- [ICONV_LIB_DIRS=])--AC_SUBST(ICONV_INCLUDE_DIRS)-AC_SUBST(ICONV_LIB_DIRS)--# map standard C types and ISO types to Haskell types-FPTOOLS_CHECK_HTYPE(char)-FPTOOLS_CHECK_HTYPE(signed char)-FPTOOLS_CHECK_HTYPE(unsigned char)-FPTOOLS_CHECK_HTYPE(short)-FPTOOLS_CHECK_HTYPE(unsigned short)-FPTOOLS_CHECK_HTYPE(int)-FPTOOLS_CHECK_HTYPE(unsigned int)-FPTOOLS_CHECK_HTYPE(long)-FPTOOLS_CHECK_HTYPE(unsigned long)-if test "$ac_cv_type_long_long" = yes; then-FPTOOLS_CHECK_HTYPE(long long)-FPTOOLS_CHECK_HTYPE(unsigned long long)-fi-FPTOOLS_CHECK_HTYPE(float)-FPTOOLS_CHECK_HTYPE(double)-FPTOOLS_CHECK_HTYPE(ptrdiff_t)-FPTOOLS_CHECK_HTYPE(size_t)-FPTOOLS_CHECK_HTYPE(wchar_t)-FPTOOLS_CHECK_HTYPE(sig_atomic_t)-FPTOOLS_CHECK_HTYPE(clock_t)-FPTOOLS_CHECK_HTYPE(time_t)-FPTOOLS_CHECK_HTYPE(useconds_t)-FPTOOLS_CHECK_HTYPE_ELSE(suseconds_t,- [if test "$WINDOWS" = "YES"- then- AC_CV_NAME=Int32- AC_CV_NAME_supported=yes- else- AC_MSG_ERROR([type not found])- fi])-FPTOOLS_CHECK_HTYPE(dev_t)-FPTOOLS_CHECK_HTYPE(ino_t)-FPTOOLS_CHECK_HTYPE(mode_t)-FPTOOLS_CHECK_HTYPE(off_t)-FPTOOLS_CHECK_HTYPE(pid_t)-FPTOOLS_CHECK_HTYPE(gid_t)-FPTOOLS_CHECK_HTYPE(uid_t)-FPTOOLS_CHECK_HTYPE(cc_t)-FPTOOLS_CHECK_HTYPE(speed_t)-FPTOOLS_CHECK_HTYPE(tcflag_t)-FPTOOLS_CHECK_HTYPE(nlink_t)-FPTOOLS_CHECK_HTYPE(ssize_t)-FPTOOLS_CHECK_HTYPE(rlim_t)--FPTOOLS_CHECK_HTYPE(intptr_t)-FPTOOLS_CHECK_HTYPE(uintptr_t)-FPTOOLS_CHECK_HTYPE(intmax_t)-FPTOOLS_CHECK_HTYPE(uintmax_t)--# test errno values-FP_CHECK_CONSTS([E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EADV EAFNOSUPPORT EAGAIN EALREADY EBADF EBADMSG EBADRPC EBUSY ECHILD ECOMM ECONNABORTED ECONNREFUSED ECONNRESET EDEADLK EDESTADDRREQ EDIRTY EDOM EDQUOT EEXIST EFAULT EFBIG EFTYPE EHOSTDOWN EHOSTUNREACH EIDRM EILSEQ EINPROGRESS EINTR EINVAL EIO EISCONN EISDIR ELOOP EMFILE EMLINK EMSGSIZE EMULTIHOP ENAMETOOLONG ENETDOWN ENETRESET ENETUNREACH ENFILE ENOBUFS ENODATA ENODEV ENOENT ENOEXEC ENOLCK ENOLINK ENOMEM ENOMSG ENONET ENOPROTOOPT ENOSPC ENOSR ENOSTR ENOSYS ENOTBLK ENOTCONN ENOTDIR ENOTEMPTY ENOTSOCK ENOTTY ENXIO EOPNOTSUPP EPERM EPFNOSUPPORT EPIPE EPROCLIM EPROCUNAVAIL EPROGMISMATCH EPROGUNAVAIL EPROTO EPROTONOSUPPORT EPROTOTYPE ERANGE EREMCHG EREMOTE EROFS ERPCMISMATCH ERREMOTE ESHUTDOWN ESOCKTNOSUPPORT ESPIPE ESRCH ESRMNT ESTALE ETIME ETIMEDOUT ETOOMANYREFS ETXTBSY EUSERS EWOULDBLOCK EXDEV ENOCIGAR], [#include <stdio.h>-#include <errno.h>])--# we need SIGINT in TopHandler.lhs-FP_CHECK_CONSTS([SIGINT], [-#if HAVE_SIGNAL_H-#include <signal.h>-#endif])--dnl ** can we open files in binary mode?-FP_CHECK_CONST([O_BINARY], [#include <fcntl.h>], [0])--# We don't use iconv or libcharset on Windows, but if configure finds-# them then it can cause problems. So we don't even try looking if-# we are on Windows.-# See http://www.haskell.org/pipermail/cvs-ghc/2011-September/065980.html-if test "$WINDOWS" = "NO"-then--# We can't just use AC_SEARCH_LIBS for this, as on OpenBSD the iconv.h-# header needs to be included as iconv_open is #define'd to something-# else. We therefore use our own FP_SEARCH_LIBS_PROTO, which allows us-# to give prototype text.-FP_SEARCH_LIBS_PROTO(iconv,- [-#include <stddef.h>-#include <iconv.h>- ],- [iconv_t cd;- cd = iconv_open("", "");- iconv(cd,NULL,NULL,NULL,NULL);- iconv_close(cd);],- iconv,- [EXTRA_LIBS="$EXTRA_LIBS $ac_lib"],- [AC_MSG_ERROR([iconv is required on non-Windows platforms])])--# If possible, we use libcharset instead of nl_langinfo(CODESET) to-# determine the current locale's character encoding.-FP_SEARCH_LIBS_PROTO(- [locale_charset],- [#include <libcharset.h>],- [const char* charset = locale_charset();],- [charset],- [AC_DEFINE([HAVE_LIBCHARSET], [1], [Define to 1 if you have libcharset.])- EXTRA_LIBS="$EXTRA_LIBS $ac_lib"])--fi--# Hack - md5.h needs HsFFI.h. Is there a better way to do this?-CFLAGS="-I../../includes $CFLAGS"-AC_CHECK_SIZEOF([struct MD5Context], ,[#include "include/md5.h"])--AC_SUBST(EXTRA_LIBS)-AC_CONFIG_FILES([base.buildinfo])--AC_OUTPUT
@@ -1,35 +0,0 @@-/* this file is #included into both C (.c and .hc) and Haskell files */-- /* IEEE format floating-point */-#define IEEE_FLOATING_POINT 1-- /* Radix of exponent representation */-#ifndef FLT_RADIX-# define FLT_RADIX 2-#endif-- /* Number of base-FLT_RADIX digits in the significand of a float */-#ifndef FLT_MANT_DIG-# define FLT_MANT_DIG 24-#endif- /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */-#ifndef FLT_MIN_EXP-# define FLT_MIN_EXP (-125)-#endif- /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */-#ifndef FLT_MAX_EXP-# define FLT_MAX_EXP 128-#endif-- /* Number of base-FLT_RADIX digits in the significand of a double */-#ifndef DBL_MANT_DIG-# define DBL_MANT_DIG 53-#endif- /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */-#ifndef DBL_MIN_EXP-# define DBL_MIN_EXP (-1021)-#endif- /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */-#ifndef DBL_MAX_EXP-# define DBL_MAX_EXP 1024-#endif
@@ -1,214 +0,0 @@-{- ---------------------------------------------------------------------------// Dirty CPP hackery for CTypes/CTypesISO-//-// (c) The FFI task force, 2000-// ----------------------------------------------------------------------------}--#ifndef CTYPES__H-#define CTYPES__H--#include "Typeable.h"--{--// As long as there is no automatic derivation of classes for newtypes we resort-// to extremely dirty cpp-hackery. :-P Some care has to be taken when the-// macros below are modified, otherwise the layout rule will bite you.--}---- // A hacked version for GHC follows the Haskell 98 version...-#ifndef __GLASGOW_HASKELL__--#define ARITHMETIC_TYPE(T,C,S,B) \-newtype T = T B deriving (Eq, Ord) ; \-INSTANCE_NUM(T) ; \-INSTANCE_REAL(T) ; \-INSTANCE_READ(T,B) ; \-INSTANCE_SHOW(T,B) ; \-INSTANCE_ENUM(T) ; \-INSTANCE_STORABLE(T) ; \-INSTANCE_TYPEABLE0(T,C,S) ;--#define INTEGRAL_TYPE(T,C,S,B) \-ARITHMETIC_TYPE(T,C,S,B) ; \-INSTANCE_BOUNDED(T) ; \-INSTANCE_INTEGRAL(T) ; \-INSTANCE_BITS(T)--#define FLOATING_TYPE(T,C,S,B) \-ARITHMETIC_TYPE(T,C,S,B) ; \-INSTANCE_FRACTIONAL(T) ; \-INSTANCE_FLOATING(T) ; \-INSTANCE_REALFRAC(T) ; \-INSTANCE_REALFLOAT(T)--#ifndef __GLASGOW_HASKELL__-#define fakeMap map-#endif--#define INSTANCE_READ(T,B) \-instance Read T where { \- readsPrec p s = fakeMap (\(x, t) -> (T x, t)) (readsPrec p s) }--#define INSTANCE_SHOW(T,B) \-instance Show T where { \- showsPrec p (T x) = showsPrec p x }--#define INSTANCE_NUM(T) \-instance Num T where { \- (T i) + (T j) = T (i + j) ; \- (T i) - (T j) = T (i - j) ; \- (T i) * (T j) = T (i * j) ; \- negate (T i) = T (negate i) ; \- abs (T i) = T (abs i) ; \- signum (T i) = T (signum i) ; \- fromInteger x = T (fromInteger x) }--#define INSTANCE_BOUNDED(T) \-instance Bounded T where { \- minBound = T minBound ; \- maxBound = T maxBound }--#define INSTANCE_ENUM(T) \-instance Enum T where { \- succ (T i) = T (succ i) ; \- pred (T i) = T (pred i) ; \- toEnum x = T (toEnum x) ; \- fromEnum (T i) = fromEnum i ; \- enumFrom (T i) = fakeMap T (enumFrom i) ; \- enumFromThen (T i) (T j) = fakeMap T (enumFromThen i j) ; \- enumFromTo (T i) (T j) = fakeMap T (enumFromTo i j) ; \- enumFromThenTo (T i) (T j) (T k) = fakeMap T (enumFromThenTo i j k) }--#define INSTANCE_REAL(T) \-instance Real T where { \- toRational (T i) = toRational i }--#define INSTANCE_INTEGRAL(T) \-instance Integral T where { \- (T i) `quot` (T j) = T (i `quot` j) ; \- (T i) `rem` (T j) = T (i `rem` j) ; \- (T i) `div` (T j) = T (i `div` j) ; \- (T i) `mod` (T j) = T (i `mod` j) ; \- (T i) `quotRem` (T j) = let (q,r) = i `quotRem` j in (T q, T r) ; \- (T i) `divMod` (T j) = let (d,m) = i `divMod` j in (T d, T m) ; \- toInteger (T i) = toInteger i }--#define INSTANCE_BITS(T) \-instance Bits T where { \- (T x) .&. (T y) = T (x .&. y) ; \- (T x) .|. (T y) = T (x .|. y) ; \- (T x) `xor` (T y) = T (x `xor` y) ; \- complement (T x) = T (complement x) ; \- shift (T x) n = T (shift x n) ; \- unsafeShiftL (T x) n = T (unsafeShiftL x n) ; \- unsafeShiftR (T x) n = T (unsafeShiftR x n) ; \- rotate (T x) n = T (rotate x n) ; \- bit n = T (bit n) ; \- setBit (T x) n = T (setBit x n) ; \- clearBit (T x) n = T (clearBit x n) ; \- complementBit (T x) n = T (complementBit x n) ; \- testBit (T x) n = testBit x n ; \- bitSize (T x) = bitSize x ; \- isSigned (T x) = isSigned x ; \- popCount (T x) = popCount x }--#define INSTANCE_FRACTIONAL(T) \-instance Fractional T where { \- (T x) / (T y) = T (x / y) ; \- recip (T x) = T (recip x) ; \- fromRational r = T (fromRational r) }--#define INSTANCE_FLOATING(T) \-instance Floating T where { \- pi = pi ; \- exp (T x) = T (exp x) ; \- log (T x) = T (log x) ; \- sqrt (T x) = T (sqrt x) ; \- (T x) ** (T y) = T (x ** y) ; \- (T x) `logBase` (T y) = T (x `logBase` y) ; \- sin (T x) = T (sin x) ; \- cos (T x) = T (cos x) ; \- tan (T x) = T (tan x) ; \- asin (T x) = T (asin x) ; \- acos (T x) = T (acos x) ; \- atan (T x) = T (atan x) ; \- sinh (T x) = T (sinh x) ; \- cosh (T x) = T (cosh x) ; \- tanh (T x) = T (tanh x) ; \- asinh (T x) = T (asinh x) ; \- acosh (T x) = T (acosh x) ; \- atanh (T x) = T (atanh x) }--#define INSTANCE_REALFRAC(T) \-instance RealFrac T where { \- properFraction (T x) = let (m,y) = properFraction x in (m, T y) ; \- truncate (T x) = truncate x ; \- round (T x) = round x ; \- ceiling (T x) = ceiling x ; \- floor (T x) = floor x }--#define INSTANCE_REALFLOAT(T) \-instance RealFloat T where { \- floatRadix (T x) = floatRadix x ; \- floatDigits (T x) = floatDigits x ; \- floatRange (T x) = floatRange x ; \- decodeFloat (T x) = decodeFloat x ; \- encodeFloat m n = T (encodeFloat m n) ; \- exponent (T x) = exponent x ; \- significand (T x) = T (significand x) ; \- scaleFloat n (T x) = T (scaleFloat n x) ; \- isNaN (T x) = isNaN x ; \- isInfinite (T x) = isInfinite x ; \- isDenormalized (T x) = isDenormalized x ; \- isNegativeZero (T x) = isNegativeZero x ; \- isIEEE (T x) = isIEEE x ; \- (T x) `atan2` (T y) = T (x `atan2` y) }--#define INSTANCE_STORABLE(T) \-instance Storable T where { \- sizeOf (T x) = sizeOf x ; \- alignment (T x) = alignment x ; \- peekElemOff a i = liftM T (peekElemOff (castPtr a) i) ; \- pokeElemOff a i (T x) = pokeElemOff (castPtr a) i x }--#else /* __GLASGOW_HASKELL__ */---- // GHC can derive any class for a newtype, so we make use of that here...--#define ARITHMETIC_CLASSES Eq,Ord,Num,Enum,Storable,Real-#define INTEGRAL_CLASSES Bounded,Integral,Bits-#define FLOATING_CLASSES Fractional,Floating,RealFrac,RealFloat--#define ARITHMETIC_TYPE(T,C,S,B) \-newtype T = T B deriving (ARITHMETIC_CLASSES); \-INSTANCE_READ(T,B); \-INSTANCE_SHOW(T,B); \-INSTANCE_TYPEABLE0(T,C,S) ;--#define INTEGRAL_TYPE(T,C,S,B) \-newtype T = T B deriving (ARITHMETIC_CLASSES, INTEGRAL_CLASSES); \-INSTANCE_READ(T,B); \-INSTANCE_SHOW(T,B); \-INSTANCE_TYPEABLE0(T,C,S) ;--#define FLOATING_TYPE(T,C,S,B) \-newtype T = T B deriving (ARITHMETIC_CLASSES, FLOATING_CLASSES); \-INSTANCE_READ(T,B); \-INSTANCE_SHOW(T,B); \-INSTANCE_TYPEABLE0(T,C,S) ;--#define INSTANCE_READ(T,B) \-instance Read T where { \- readsPrec = unsafeCoerce# (readsPrec :: Int -> ReadS B); \- readList = unsafeCoerce# (readList :: ReadS [B]); }--#define INSTANCE_SHOW(T,B) \-instance Show T where { \- showsPrec = unsafeCoerce# (showsPrec :: Int -> B -> ShowS); \- show = unsafeCoerce# (show :: B -> String); \- showList = unsafeCoerce# (showList :: [B] -> ShowS); }--#endif /* __GLASGOW_HASKELL__ */--#endif
@@ -1,86 +0,0 @@-/* include/EventConfig.h. Generated from EventConfig.h.in by configure. */-/* include/EventConfig.h.in. Generated from configure.ac by autoheader. */--/* Define if you have epoll support. */-#define HAVE_EPOLL 1--/* Define to 1 if you have the `epoll_create1' function. */-/* #undef HAVE_EPOLL_CREATE1 */--/* Define to 1 if you have the `epoll_ctl' function. */-#define HAVE_EPOLL_CTL 1--/* Define to 1 if you have the `eventfd' function. */-#define HAVE_EVENTFD 1--/* Define to 1 if you have the <inttypes.h> header file. */-#define HAVE_INTTYPES_H 1--/* Define to 1 if you have the `kevent' function. */-/* #undef HAVE_KEVENT */--/* Define to 1 if you have the `kevent64' function. */-/* #undef HAVE_KEVENT64 */--/* Define if you have kqueue support. */-/* #undef HAVE_KQUEUE */--/* Define to 1 if you have the <memory.h> header file. */-#define HAVE_MEMORY_H 1--/* Define if you have poll support. */-#define HAVE_POLL 1--/* Define to 1 if you have the <poll.h> header file. */-#define HAVE_POLL_H 1--/* Define to 1 if you have the <signal.h> header file. */-#define HAVE_SIGNAL_H 1--/* Define to 1 if you have the <stdint.h> header file. */-#define HAVE_STDINT_H 1--/* Define to 1 if you have the <stdlib.h> header file. */-#define HAVE_STDLIB_H 1--/* Define to 1 if you have the <strings.h> header file. */-#define HAVE_STRINGS_H 1--/* Define to 1 if you have the <string.h> header file. */-#define HAVE_STRING_H 1--/* Define to 1 if you have the <sys/epoll.h> header file. */-#define HAVE_SYS_EPOLL_H 1--/* Define to 1 if you have the <sys/eventfd.h> header file. */-#define HAVE_SYS_EVENTFD_H 1--/* Define to 1 if you have the <sys/event.h> header file. */-/* #undef HAVE_SYS_EVENT_H */--/* Define to 1 if you have the <sys/stat.h> header file. */-#define HAVE_SYS_STAT_H 1--/* Define to 1 if you have the <sys/types.h> header file. */-#define HAVE_SYS_TYPES_H 1--/* Define to 1 if you have the <unistd.h> header file. */-#define HAVE_UNISTD_H 1--/* Define to the address where bug reports for this package should be sent. */-#define PACKAGE_BUGREPORT "libraries@haskell.org"--/* Define to the full name of this package. */-#define PACKAGE_NAME "Haskell base package"--/* Define to the full name and version of this package. */-#define PACKAGE_STRING "Haskell base package 1.0"--/* Define to the one symbol short name of this package. */-#define PACKAGE_TARNAME "base"--/* Define to the version of this package. */-#define PACKAGE_VERSION "1.0"--/* Define to 1 if you have the ANSI C header files. */-#define STDC_HEADERS 1
@@ -1,645 +0,0 @@-/* ------------------------------------------------------------------------------ *- * (c) The University of Glasgow 2001-2004- *- * Definitions for package `base' which are visible in Haskell land.- *- * ---------------------------------------------------------------------------*/--#ifndef __HSBASE_H__-#define __HSBASE_H__--#ifdef __NHC__-# include "Nhc98BaseConfig.h"-#else-#include "HsBaseConfig.h"-#endif--/* ultra-evil... */-#undef PACKAGE_BUGREPORT-#undef PACKAGE_NAME-#undef PACKAGE_STRING-#undef PACKAGE_TARNAME-#undef PACKAGE_VERSION--/* Needed to get the macro version of errno on some OSs (eg. Solaris).- We must do this, because these libs are only compiled once, but- must work in both single-threaded and multi-threaded programs. */-#define _REENTRANT 1--#include "HsFFI.h"--#include <stdio.h>-#include <stdlib.h>-#include <math.h>--#if HAVE_SYS_TYPES_H-#include <sys/types.h>-#endif-#if HAVE_UNISTD_H-#include <unistd.h>-#endif-#if HAVE_SYS_STAT_H-#include <sys/stat.h>-#endif-#if HAVE_FCNTL_H-# include <fcntl.h>-#endif-#if HAVE_TERMIOS_H-#include <termios.h>-#endif-#if HAVE_SIGNAL_H-#include <signal.h>-/* Ultra-ugly: OpenBSD uses broken macros for sigemptyset and sigfillset (missing casts) */-#if __OpenBSD__-#undef sigemptyset-#undef sigfillset-#endif-#endif-#if HAVE_ERRNO_H-#include <errno.h>-#endif-#if HAVE_STRING_H-#include <string.h>-#endif-#if HAVE_UTIME_H-#include <utime.h>-#endif-#if HAVE_SYS_UTSNAME_H-#include <sys/utsname.h>-#endif-#if HAVE_GETTIMEOFDAY-# if HAVE_SYS_TIME_H-# include <sys/time.h>-# endif-#elif HAVE_GETCLOCK-# if HAVE_SYS_TIMERS_H-# define POSIX_4D9 1-# include <sys/timers.h>-# endif-#endif-#if HAVE_TIME_H-#include <time.h>-#endif-#if HAVE_SYS_TIMEB_H-#include <sys/timeb.h>-#endif-#if HAVE_WINDOWS_H-#include <windows.h>-#endif-#if HAVE_SYS_TIMES_H-#include <sys/times.h>-#endif-#if HAVE_WINSOCK_H && defined(__MINGW32__)-#include <winsock.h>-#endif-#if HAVE_LIMITS_H-#include <limits.h>-#endif-#if HAVE_WCTYPE_H-#include <wctype.h>-#endif-#if HAVE_INTTYPES_H-# include <inttypes.h>-#elif HAVE_STDINT_H-# include <stdint.h>-#endif--#if !defined(__MINGW32__) && !defined(irix_HOST_OS)-# if HAVE_SYS_RESOURCE_H-# include <sys/resource.h>-# endif-#endif--#if !HAVE_GETRUSAGE && HAVE_SYS_SYSCALL_H-# include <sys/syscall.h>-# if defined(SYS_GETRUSAGE) /* hpux_HOST_OS */-# define getrusage(a, b) syscall(SYS_GETRUSAGE, a, b)-# define HAVE_GETRUSAGE 1-# endif-#endif--/* For System */-#if HAVE_SYS_WAIT_H-#include <sys/wait.h>-#endif-#if HAVE_VFORK_H-#include <vfork.h>-#endif-#include "WCsubst.h"--#if defined(__MINGW32__)-/* in Win32Utils.c */-extern void maperrno (void);-extern HsWord64 getUSecOfDay(void);-#endif--#if defined(__MINGW32__)-#include <io.h>-#include <fcntl.h>-#include <shlobj.h>-#include <share.h>-#endif--#if HAVE_SYS_SELECT_H-#include <sys/select.h>-#endif--/* in inputReady.c */-extern int fdReady(int fd, int write, int msecs, int isSock);--/* in Signals.c */-extern HsInt nocldstop;--/* ------------------------------------------------------------------------------ INLINE functions.-- These functions are given as inlines here for when compiling via C,- but we also generate static versions into the cbits library for- when compiling to native code.- -------------------------------------------------------------------------- */--#ifndef INLINE-# if defined(_MSC_VER)-# define INLINE extern __inline-# else-# define INLINE static inline-# endif-#endif--INLINE int __hscore_get_errno(void) { return errno; }-INLINE void __hscore_set_errno(int e) { errno = e; }--#if !defined(_MSC_VER)-INLINE int __hscore_s_isreg(mode_t m) { return S_ISREG(m); }-INLINE int __hscore_s_isdir(mode_t m) { return S_ISDIR(m); }-INLINE int __hscore_s_isfifo(mode_t m) { return S_ISFIFO(m); }-INLINE int __hscore_s_isblk(mode_t m) { return S_ISBLK(m); }-INLINE int __hscore_s_ischr(mode_t m) { return S_ISCHR(m); }-#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)-INLINE int __hscore_s_issock(mode_t m) { return S_ISSOCK(m); }-#endif-#endif--#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_WIN32)-INLINE int-__hscore_sigemptyset( sigset_t *set )-{ return sigemptyset(set); }--INLINE int-__hscore_sigfillset( sigset_t *set )-{ return sigfillset(set); }--INLINE int-__hscore_sigaddset( sigset_t * set, int s )-{ return sigaddset(set,s); }--INLINE int-__hscore_sigdelset( sigset_t * set, int s )-{ return sigdelset(set,s); }--INLINE int-__hscore_sigismember( sigset_t * set, int s )-{ return sigismember(set,s); }-#endif--INLINE void *-__hscore_memcpy_src_off( char *dst, char *src, int src_off, size_t sz )-{ return memcpy(dst, src+src_off, sz); }--INLINE HsInt-__hscore_bufsiz(void)-{- return BUFSIZ;-}--INLINE int-__hscore_seek_cur(void)-{- return SEEK_CUR;-}--INLINE int-__hscore_o_binary(void)-{-#if defined(_MSC_VER)- return O_BINARY;-#else- return CONST_O_BINARY;-#endif-}--INLINE int-__hscore_o_rdonly(void)-{-#ifdef O_RDONLY- return O_RDONLY;-#else- return 0;-#endif-}--INLINE int-__hscore_o_wronly( void )-{-#ifdef O_WRONLY- return O_WRONLY;-#else- return 0;-#endif-}--INLINE int-__hscore_o_rdwr( void )-{-#ifdef O_RDWR- return O_RDWR;-#else- return 0;-#endif-}--INLINE int-__hscore_o_append( void )-{-#ifdef O_APPEND- return O_APPEND;-#else- return 0;-#endif-}--INLINE int-__hscore_o_creat( void )-{-#ifdef O_CREAT- return O_CREAT;-#else- return 0;-#endif-}--INLINE int-__hscore_o_excl( void )-{-#ifdef O_EXCL- return O_EXCL;-#else- return 0;-#endif-}--INLINE int-__hscore_o_trunc( void )-{-#ifdef O_TRUNC- return O_TRUNC;-#else- return 0;-#endif-}--INLINE int-__hscore_o_noctty( void )-{-#ifdef O_NOCTTY- return O_NOCTTY;-#else- return 0;-#endif-}--INLINE int-__hscore_o_nonblock( void )-{-#ifdef O_NONBLOCK- return O_NONBLOCK;-#else- return 0;-#endif-}--INLINE int-__hscore_seek_set( void )-{- return SEEK_SET;-}--INLINE int-__hscore_seek_end( void )-{- return SEEK_END;-}--INLINE int-__hscore_ftruncate( int fd, off_t where )-{-#if defined(HAVE_FTRUNCATE)- return ftruncate(fd,where);-#elif defined(HAVE__CHSIZE)- return _chsize(fd,where);-#else-// ToDo: we should use _chsize_s() on Windows which allows a 64-bit-// offset, but it doesn't seem to be available from mingw at this time -// --SDM (01/2008)-#error at least ftruncate or _chsize functions are required to build-#endif-}--INLINE int-__hscore_setmode( int fd, HsBool toBin )-{-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)- return setmode(fd,(toBin == HS_BOOL_TRUE) ? _O_BINARY : _O_TEXT);-#else- return 0;-#endif-}--#if __GLASGOW_HASKELL__--#endif /* __GLASGOW_HASKELL__ */--#if defined(__MINGW32__)-// We want the versions of stat/fstat/lseek that use 64-bit offsets,-// and you have to ask for those explicitly. Unfortunately there-// doesn't seem to be a 64-bit version of truncate/ftruncate, so while-// hFileSize and hSeek will work with large files, hSetFileSize will not.-typedef struct _stati64 struct_stat;-typedef off64_t stsize_t;-#else-typedef struct stat struct_stat;-typedef off_t stsize_t;-#endif--INLINE HsInt-__hscore_sizeof_stat( void )-{- return sizeof(struct_stat);-}--INLINE time_t __hscore_st_mtime ( struct_stat* st ) { return st->st_mtime; }-INLINE stsize_t __hscore_st_size ( struct_stat* st ) { return st->st_size; }-#if !defined(_MSC_VER)-INLINE mode_t __hscore_st_mode ( struct_stat* st ) { return st->st_mode; }-INLINE dev_t __hscore_st_dev ( struct_stat* st ) { return st->st_dev; }-INLINE ino_t __hscore_st_ino ( struct_stat* st ) { return st->st_ino; }-#endif--#if defined(__MINGW32__)-INLINE int __hscore_stat(wchar_t *file, struct_stat *buf) {- return _wstati64(file,buf);-}--INLINE int __hscore_fstat(int fd, struct_stat *buf) {- return _fstati64(fd,buf);-}-INLINE int __hscore_lstat(wchar_t *fname, struct_stat *buf )-{- return _wstati64(fname,buf);-}-#else-INLINE int __hscore_stat(char *file, struct_stat *buf) {- return stat(file,buf);-}--INLINE int __hscore_fstat(int fd, struct_stat *buf) {- return fstat(fd,buf);-}--INLINE int __hscore_lstat( const char *fname, struct stat *buf )-{-#if HAVE_LSTAT- return lstat(fname, buf);-#else- return stat(fname, buf);-#endif-}-#endif--#if HAVE_TERMIOS_H-INLINE tcflag_t __hscore_lflag( struct termios* ts ) { return ts->c_lflag; }--INLINE void-__hscore_poke_lflag( struct termios* ts, tcflag_t t ) { ts->c_lflag = t; }--INLINE unsigned char*-__hscore_ptr_c_cc( struct termios* ts )-{ return (unsigned char*) &ts->c_cc; }--INLINE HsInt-__hscore_sizeof_termios( void )-{-#ifndef __MINGW32__- return sizeof(struct termios);-#else- return 0;-#endif-}-#endif--#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_WIN32)-INLINE HsInt-__hscore_sizeof_sigset_t( void )-{- return sizeof(sigset_t);-}-#endif--INLINE int-__hscore_echo( void )-{-#ifdef ECHO- return ECHO;-#else- return 0;-#endif--}--INLINE int-__hscore_tcsanow( void )-{-#ifdef TCSANOW- return TCSANOW;-#else- return 0;-#endif--}--INLINE int-__hscore_icanon( void )-{-#ifdef ICANON- return ICANON;-#else- return 0;-#endif-}--INLINE int __hscore_vmin( void )-{-#ifdef VMIN- return VMIN;-#else- return 0;-#endif-}--INLINE int __hscore_vtime( void )-{-#ifdef VTIME- return VTIME;-#else- return 0;-#endif-}--INLINE int __hscore_sigttou( void )-{-#ifdef SIGTTOU- return SIGTTOU;-#else- return 0;-#endif-}--INLINE int __hscore_sig_block( void )-{-#ifdef SIG_BLOCK- return SIG_BLOCK;-#else- return 0;-#endif-}--INLINE int __hscore_sig_setmask( void )-{-#ifdef SIG_SETMASK- return SIG_SETMASK;-#else- return 0;-#endif-}--#ifndef __MINGW32__-INLINE size_t __hscore_sizeof_siginfo_t (void)-{- return sizeof(siginfo_t);-}-#endif--INLINE int-__hscore_f_getfl( void )-{-#ifdef F_GETFL- return F_GETFL;-#else- return 0;-#endif-}--INLINE int-__hscore_f_setfl( void )-{-#ifdef F_SETFL- return F_SETFL;-#else- return 0;-#endif-}--INLINE int-__hscore_f_setfd( void )-{-#ifdef F_SETFD- return F_SETFD;-#else- return 0;-#endif-}--INLINE long-__hscore_fd_cloexec( void )-{-#ifdef FD_CLOEXEC- return FD_CLOEXEC;-#else- return 0;-#endif-}--// defined in rts/RtsStartup.c.-extern void* __hscore_get_saved_termios(int fd);-extern void __hscore_set_saved_termios(int fd, void* ts);--INLINE int __hscore_hs_fileno (FILE *f) { return fileno (f); }--#ifdef __MINGW32__-INLINE int __hscore_open(wchar_t *file, int how, mode_t mode) {- if ((how & O_WRONLY) || (how & O_RDWR) || (how & O_APPEND))- return _wsopen(file,how | _O_NOINHERIT,_SH_DENYRW,mode);- // _O_NOINHERIT: see #2650- else- return _wsopen(file,how | _O_NOINHERIT,_SH_DENYWR,mode);- // _O_NOINHERIT: see #2650-}-#else-INLINE int __hscore_open(char *file, int how, mode_t mode) {- return open(file,how,mode);-}-#endif--// These are wrapped because on some OSs (eg. Linux) they are-// macros which redirect to the 64-bit-off_t versions when large file-// support is enabled.-//-#if defined(__MINGW32__)-INLINE off64_t __hscore_lseek(int fd, off64_t off, int whence) {- return (_lseeki64(fd,off,whence));-}-#else-INLINE off_t __hscore_lseek(int fd, off_t off, int whence) {- return (lseek(fd,off,whence));-}-#endif--// select-related stuff--#if !defined(__MINGW32__)-INLINE int hsFD_SETSIZE(void) { return FD_SETSIZE; }-INLINE int hsFD_ISSET(int fd, fd_set *fds) { return FD_ISSET(fd, fds); }-INLINE void hsFD_SET(int fd, fd_set *fds) { FD_SET(fd, fds); }-INLINE HsInt sizeof_fd_set(void) { return sizeof(fd_set); }-extern void hsFD_ZERO(fd_set *fds);-#endif--INLINE int __hscore_select(int nfds, fd_set *readfds, fd_set *writefds,- fd_set *exceptfds, struct timeval *timeout) {- return (select(nfds,readfds,writefds,exceptfds,timeout));-}--#if darwin_HOST_OS-// You should not access _environ directly on Darwin in a bundle/shared library.-// See #2458 and http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man7/environ.7.html-#include <crt_externs.h>-INLINE char **__hscore_environ(void) { return *(_NSGetEnviron()); }-#else-/* ToDo: write a feature test that doesn't assume 'environ' to- * be in scope at link-time. */-extern char** environ;-INLINE char **__hscore_environ(void) { return environ; }-#endif--/* lossless conversions between pointers and integral types */-INLINE void * __hscore_from_uintptr(uintptr_t n) { return (void *)n; }-INLINE void * __hscore_from_intptr (intptr_t n) { return (void *)n; }-INLINE uintptr_t __hscore_to_uintptr (void *p) { return (uintptr_t)p; }-INLINE intptr_t __hscore_to_intptr (void *p) { return (intptr_t)p; }--void errorBelch2(const char*s, char *t);-void debugBelch2(const char*s, char *t);--#endif /* __HSBASE_H__ */-
@@ -1,599 +0,0 @@-/* include/HsBaseConfig.h. Generated from HsBaseConfig.h.in by configure. */-/* include/HsBaseConfig.h.in. Generated from configure.ac by autoheader. */--/* The value of E2BIG. */-#define CONST_E2BIG 7--/* The value of EACCES. */-#define CONST_EACCES 13--/* The value of EADDRINUSE. */-#define CONST_EADDRINUSE 98--/* The value of EADDRNOTAVAIL. */-#define CONST_EADDRNOTAVAIL 99--/* The value of EADV. */-#define CONST_EADV 68--/* The value of EAFNOSUPPORT. */-#define CONST_EAFNOSUPPORT 97--/* The value of EAGAIN. */-#define CONST_EAGAIN 11--/* The value of EALREADY. */-#define CONST_EALREADY 114--/* The value of EBADF. */-#define CONST_EBADF 9--/* The value of EBADMSG. */-#define CONST_EBADMSG 74--/* The value of EBADRPC. */-#define CONST_EBADRPC -1--/* The value of EBUSY. */-#define CONST_EBUSY 16--/* The value of ECHILD. */-#define CONST_ECHILD 10--/* The value of ECOMM. */-#define CONST_ECOMM 70--/* The value of ECONNABORTED. */-#define CONST_ECONNABORTED 103--/* The value of ECONNREFUSED. */-#define CONST_ECONNREFUSED 111--/* The value of ECONNRESET. */-#define CONST_ECONNRESET 104--/* The value of EDEADLK. */-#define CONST_EDEADLK 35--/* The value of EDESTADDRREQ. */-#define CONST_EDESTADDRREQ 89--/* The value of EDIRTY. */-#define CONST_EDIRTY -1--/* The value of EDOM. */-#define CONST_EDOM 33--/* The value of EDQUOT. */-#define CONST_EDQUOT 122--/* The value of EEXIST. */-#define CONST_EEXIST 17--/* The value of EFAULT. */-#define CONST_EFAULT 14--/* The value of EFBIG. */-#define CONST_EFBIG 27--/* The value of EFTYPE. */-#define CONST_EFTYPE -1--/* The value of EHOSTDOWN. */-#define CONST_EHOSTDOWN 112--/* The value of EHOSTUNREACH. */-#define CONST_EHOSTUNREACH 113--/* The value of EIDRM. */-#define CONST_EIDRM 43--/* The value of EILSEQ. */-#define CONST_EILSEQ 84--/* The value of EINPROGRESS. */-#define CONST_EINPROGRESS 115--/* The value of EINTR. */-#define CONST_EINTR 4--/* The value of EINVAL. */-#define CONST_EINVAL 22--/* The value of EIO. */-#define CONST_EIO 5--/* The value of EISCONN. */-#define CONST_EISCONN 106--/* The value of EISDIR. */-#define CONST_EISDIR 21--/* The value of ELOOP. */-#define CONST_ELOOP 40--/* The value of EMFILE. */-#define CONST_EMFILE 24--/* The value of EMLINK. */-#define CONST_EMLINK 31--/* The value of EMSGSIZE. */-#define CONST_EMSGSIZE 90--/* The value of EMULTIHOP. */-#define CONST_EMULTIHOP 72--/* The value of ENAMETOOLONG. */-#define CONST_ENAMETOOLONG 36--/* The value of ENETDOWN. */-#define CONST_ENETDOWN 100--/* The value of ENETRESET. */-#define CONST_ENETRESET 102--/* The value of ENETUNREACH. */-#define CONST_ENETUNREACH 101--/* The value of ENFILE. */-#define CONST_ENFILE 23--/* The value of ENOBUFS. */-#define CONST_ENOBUFS 105--/* The value of ENOCIGAR. */-#define CONST_ENOCIGAR -1--/* The value of ENODATA. */-#define CONST_ENODATA 61--/* The value of ENODEV. */-#define CONST_ENODEV 19--/* The value of ENOENT. */-#define CONST_ENOENT 2--/* The value of ENOEXEC. */-#define CONST_ENOEXEC 8--/* The value of ENOLCK. */-#define CONST_ENOLCK 37--/* The value of ENOLINK. */-#define CONST_ENOLINK 67--/* The value of ENOMEM. */-#define CONST_ENOMEM 12--/* The value of ENOMSG. */-#define CONST_ENOMSG 42--/* The value of ENONET. */-#define CONST_ENONET 64--/* The value of ENOPROTOOPT. */-#define CONST_ENOPROTOOPT 92--/* The value of ENOSPC. */-#define CONST_ENOSPC 28--/* The value of ENOSR. */-#define CONST_ENOSR 63--/* The value of ENOSTR. */-#define CONST_ENOSTR 60--/* The value of ENOSYS. */-#define CONST_ENOSYS 38--/* The value of ENOTBLK. */-#define CONST_ENOTBLK 15--/* The value of ENOTCONN. */-#define CONST_ENOTCONN 107--/* The value of ENOTDIR. */-#define CONST_ENOTDIR 20--/* The value of ENOTEMPTY. */-#define CONST_ENOTEMPTY 39--/* The value of ENOTSOCK. */-#define CONST_ENOTSOCK 88--/* The value of ENOTTY. */-#define CONST_ENOTTY 25--/* The value of ENXIO. */-#define CONST_ENXIO 6--/* The value of EOPNOTSUPP. */-#define CONST_EOPNOTSUPP 95--/* The value of EPERM. */-#define CONST_EPERM 1--/* The value of EPFNOSUPPORT. */-#define CONST_EPFNOSUPPORT 96--/* The value of EPIPE. */-#define CONST_EPIPE 32--/* The value of EPROCLIM. */-#define CONST_EPROCLIM -1--/* The value of EPROCUNAVAIL. */-#define CONST_EPROCUNAVAIL -1--/* The value of EPROGMISMATCH. */-#define CONST_EPROGMISMATCH -1--/* The value of EPROGUNAVAIL. */-#define CONST_EPROGUNAVAIL -1--/* The value of EPROTO. */-#define CONST_EPROTO 71--/* The value of EPROTONOSUPPORT. */-#define CONST_EPROTONOSUPPORT 93--/* The value of EPROTOTYPE. */-#define CONST_EPROTOTYPE 91--/* The value of ERANGE. */-#define CONST_ERANGE 34--/* The value of EREMCHG. */-#define CONST_EREMCHG 78--/* The value of EREMOTE. */-#define CONST_EREMOTE 66--/* The value of EROFS. */-#define CONST_EROFS 30--/* The value of ERPCMISMATCH. */-#define CONST_ERPCMISMATCH -1--/* The value of ERREMOTE. */-#define CONST_ERREMOTE -1--/* The value of ESHUTDOWN. */-#define CONST_ESHUTDOWN 108--/* The value of ESOCKTNOSUPPORT. */-#define CONST_ESOCKTNOSUPPORT 94--/* The value of ESPIPE. */-#define CONST_ESPIPE 29--/* The value of ESRCH. */-#define CONST_ESRCH 3--/* The value of ESRMNT. */-#define CONST_ESRMNT 69--/* The value of ESTALE. */-#define CONST_ESTALE 116--/* The value of ETIME. */-#define CONST_ETIME 62--/* The value of ETIMEDOUT. */-#define CONST_ETIMEDOUT 110--/* The value of ETOOMANYREFS. */-#define CONST_ETOOMANYREFS 109--/* The value of ETXTBSY. */-#define CONST_ETXTBSY 26--/* The value of EUSERS. */-#define CONST_EUSERS 87--/* The value of EWOULDBLOCK. */-#define CONST_EWOULDBLOCK 11--/* The value of EXDEV. */-#define CONST_EXDEV 18--/* The value of O_BINARY. */-#define CONST_O_BINARY 0--/* The value of SIGINT. */-#define CONST_SIGINT 2--/* Define to 1 if you have the <ctype.h> header file. */-#define HAVE_CTYPE_H 1--/* Define if you have epoll support. */-#define HAVE_EPOLL 1--/* Define to 1 if you have the `epoll_ctl' function. */-#define HAVE_EPOLL_CTL 1--/* Define to 1 if you have the <errno.h> header file. */-#define HAVE_ERRNO_H 1--/* Define to 1 if you have the `eventfd' function. */-#define HAVE_EVENTFD 1--/* Define to 1 if you have the <fcntl.h> header file. */-#define HAVE_FCNTL_H 1--/* Define to 1 if you have the `ftruncate' function. */-#define HAVE_FTRUNCATE 1--/* Define to 1 if you have the `getclock' function. */-/* #undef HAVE_GETCLOCK */--/* Define to 1 if you have the `getrusage' function. */-#define HAVE_GETRUSAGE 1--/* Define to 1 if you have the <inttypes.h> header file. */-#define HAVE_INTTYPES_H 1--/* Define to 1 if you have the `iswspace' function. */-#define HAVE_ISWSPACE 1--/* Define to 1 if you have the `kevent' function. */-/* #undef HAVE_KEVENT */--/* Define to 1 if you have the `kevent64' function. */-/* #undef HAVE_KEVENT64 */--/* Define if you have kqueue support. */-/* #undef HAVE_KQUEUE */--/* Define to 1 if you have the <langinfo.h> header file. */-#define HAVE_LANGINFO_H 1--/* Define to 1 if you have libcharset. */-/* #undef HAVE_LIBCHARSET */--/* Define to 1 if you have the <limits.h> header file. */-#define HAVE_LIMITS_H 1--/* Define to 1 if the system has the type `long long'. */-#define HAVE_LONG_LONG 1--/* Define to 1 if you have the `lstat' function. */-#define HAVE_LSTAT 1--/* Define to 1 if you have the <memory.h> header file. */-#define HAVE_MEMORY_H 1--/* Define if you have poll support. */-#define HAVE_POLL 1--/* Define to 1 if you have the <poll.h> header file. */-#define HAVE_POLL_H 1--/* Define to 1 if you have the <signal.h> header file. */-#define HAVE_SIGNAL_H 1--/* Define to 1 if you have the <stdint.h> header file. */-#define HAVE_STDINT_H 1--/* Define to 1 if you have the <stdlib.h> header file. */-#define HAVE_STDLIB_H 1--/* Define to 1 if you have the <strings.h> header file. */-#define HAVE_STRINGS_H 1--/* Define to 1 if you have the <string.h> header file. */-#define HAVE_STRING_H 1--/* Define to 1 if you have the <sys/epoll.h> header file. */-#define HAVE_SYS_EPOLL_H 1--/* Define to 1 if you have the <sys/eventfd.h> header file. */-#define HAVE_SYS_EVENTFD_H 1--/* Define to 1 if you have the <sys/event.h> header file. */-/* #undef HAVE_SYS_EVENT_H */--/* Define to 1 if you have the <sys/resource.h> header file. */-#define HAVE_SYS_RESOURCE_H 1--/* Define to 1 if you have the <sys/select.h> header file. */-#define HAVE_SYS_SELECT_H 1--/* Define to 1 if you have the <sys/stat.h> header file. */-#define HAVE_SYS_STAT_H 1--/* Define to 1 if you have the <sys/syscall.h> header file. */-#define HAVE_SYS_SYSCALL_H 1--/* Define to 1 if you have the <sys/timeb.h> header file. */-#define HAVE_SYS_TIMEB_H 1--/* Define to 1 if you have the <sys/timers.h> header file. */-/* #undef HAVE_SYS_TIMERS_H */--/* Define to 1 if you have the <sys/times.h> header file. */-#define HAVE_SYS_TIMES_H 1--/* Define to 1 if you have the <sys/time.h> header file. */-#define HAVE_SYS_TIME_H 1--/* Define to 1 if you have the <sys/types.h> header file. */-#define HAVE_SYS_TYPES_H 1--/* Define to 1 if you have the <sys/utsname.h> header file. */-#define HAVE_SYS_UTSNAME_H 1--/* Define to 1 if you have the <sys/wait.h> header file. */-#define HAVE_SYS_WAIT_H 1--/* Define to 1 if you have the <termios.h> header file. */-#define HAVE_TERMIOS_H 1--/* Define to 1 if you have the `times' function. */-#define HAVE_TIMES 1--/* Define to 1 if you have the <time.h> header file. */-#define HAVE_TIME_H 1--/* Define to 1 if you have the <unistd.h> header file. */-#define HAVE_UNISTD_H 1--/* Define to 1 if you have the <utime.h> header file. */-#define HAVE_UTIME_H 1--/* Define to 1 if you have the <wctype.h> header file. */-#define HAVE_WCTYPE_H 1--/* Define to 1 if you have the <windows.h> header file. */-/* #undef HAVE_WINDOWS_H */--/* Define to 1 if you have the <winsock.h> header file. */-/* #undef HAVE_WINSOCK_H */--/* Define to 1 if you have the `_chsize' function. */-/* #undef HAVE__CHSIZE */--/* Define to Haskell type for cc_t */-#define HTYPE_CC_T Word8--/* Define to Haskell type for char */-#define HTYPE_CHAR Int8--/* Define to Haskell type for clock_t */-#define HTYPE_CLOCK_T Int32--/* Define to Haskell type for dev_t */-#define HTYPE_DEV_T Word64--/* Define to Haskell type for double */-#define HTYPE_DOUBLE Double--/* Define to Haskell type for float */-#define HTYPE_FLOAT Float--/* Define to Haskell type for gid_t */-#define HTYPE_GID_T Word32--/* Define to Haskell type for ino_t */-#define HTYPE_INO_T Word64--/* Define to Haskell type for int */-#define HTYPE_INT Int32--/* Define to Haskell type for intmax_t */-#define HTYPE_INTMAX_T Int64--/* Define to Haskell type for intptr_t */-#define HTYPE_INTPTR_T Int32--/* Define to Haskell type for long */-#define HTYPE_LONG Int32--/* Define to Haskell type for long long */-#define HTYPE_LONG_LONG Int64--/* Define to Haskell type for mode_t */-#define HTYPE_MODE_T Word32--/* Define to Haskell type for nlink_t */-#define HTYPE_NLINK_T Word32--/* Define to Haskell type for off_t */-#define HTYPE_OFF_T Int64--/* Define to Haskell type for pid_t */-#define HTYPE_PID_T Int32--/* Define to Haskell type for ptrdiff_t */-#define HTYPE_PTRDIFF_T Int32--/* Define to Haskell type for rlim_t */-#define HTYPE_RLIM_T Word64--/* Define to Haskell type for short */-#define HTYPE_SHORT Int16--/* Define to Haskell type for signed char */-#define HTYPE_SIGNED_CHAR Int8--/* Define to Haskell type for sig_atomic_t */-#define HTYPE_SIG_ATOMIC_T Int32--/* Define to Haskell type for size_t */-#define HTYPE_SIZE_T Word32--/* Define to Haskell type for speed_t */-#define HTYPE_SPEED_T Word32--/* Define to Haskell type for ssize_t */-#define HTYPE_SSIZE_T Int32--/* Define to Haskell type for suseconds_t */-#define HTYPE_SUSECONDS_T Int32--/* Define to Haskell type for tcflag_t */-#define HTYPE_TCFLAG_T Word32--/* Define to Haskell type for time_t */-#define HTYPE_TIME_T Int32--/* Define to Haskell type for uid_t */-#define HTYPE_UID_T Word32--/* Define to Haskell type for uintmax_t */-#define HTYPE_UINTMAX_T Word64--/* Define to Haskell type for uintptr_t */-#define HTYPE_UINTPTR_T Word32--/* Define to Haskell type for unsigned char */-#define HTYPE_UNSIGNED_CHAR Word8--/* Define to Haskell type for unsigned int */-#define HTYPE_UNSIGNED_INT Word32--/* Define to Haskell type for unsigned long */-#define HTYPE_UNSIGNED_LONG Word32--/* Define to Haskell type for unsigned long long */-#define HTYPE_UNSIGNED_LONG_LONG Word64--/* Define to Haskell type for unsigned short */-#define HTYPE_UNSIGNED_SHORT Word16--/* Define to Haskell type for useconds_t */-#define HTYPE_USECONDS_T Word32--/* Define to Haskell type for wchar_t */-#define HTYPE_WCHAR_T Int32--/* Define to the address where bug reports for this package should be sent. */-#define PACKAGE_BUGREPORT "libraries@haskell.org"--/* Define to the full name of this package. */-#define PACKAGE_NAME "Haskell base package"--/* Define to the full name and version of this package. */-#define PACKAGE_STRING "Haskell base package 1.0"--/* Define to the one symbol short name of this package. */-#define PACKAGE_TARNAME "base"--/* Define to the home page for this package. */-#define PACKAGE_URL ""--/* Define to the version of this package. */-#define PACKAGE_VERSION "1.0"--/* The size of `struct MD5Context', as computed by sizeof. */-#define SIZEOF_STRUCT_MD5CONTEXT 88--/* Define to 1 if you have the ANSI C header files. */-#define STDC_HEADERS 1--/* Number of bits in a file offset, on hosts where this is settable. */-#define _FILE_OFFSET_BITS 64--/* Define for large files, on AIX-style hosts. */-/* #undef _LARGE_FILES */
@@ -1,123 +0,0 @@-{- ---------------------------------------------------------------------------// Macros to help make Typeable instances.-//-// INSTANCE_TYPEABLEn(tc,tcname,"tc") defines-//-// instance Typeable/n/ tc-// instance Typeable a => Typeable/n-1/ (tc a)-// instance (Typeable a, Typeable b) => Typeable/n-2/ (tc a b)-// ...-// instance (Typeable a1, ..., Typeable an) => Typeable (tc a1 ... an)-// ----------------------------------------------------------------------------}--#ifndef TYPEABLE_H-#define TYPEABLE_H--#ifdef __GLASGOW_HASKELL__---- // For GHC, we can use DeriveDataTypeable + StandaloneDeriving to--- // generate the instances.--#define INSTANCE_TYPEABLE0(tycon,tcname,str) deriving instance Typeable tycon-#define INSTANCE_TYPEABLE1(tycon,tcname,str) deriving instance Typeable1 tycon-#define INSTANCE_TYPEABLE2(tycon,tcname,str) deriving instance Typeable2 tycon-#define INSTANCE_TYPEABLE3(tycon,tcname,str) deriving instance Typeable3 tycon-#define INSTANCE_TYPEABLE4(tycon,tcname,str) deriving instance Typeable4 tycon-#define INSTANCE_TYPEABLE5(tycon,tcname,str) deriving instance Typeable5 tycon-#define INSTANCE_TYPEABLE6(tycon,tcname,str) deriving instance Typeable6 tycon-#define INSTANCE_TYPEABLE7(tycon,tcname,str) deriving instance Typeable7 tycon--#else /* !__GLASGOW_HASKELL__ */--#define INSTANCE_TYPEABLE0(tycon,tcname,str) \-tcname :: TyCon; \-tcname = mkTyCon str; \-instance Typeable tycon where { typeOf _ = mkTyConApp tcname [] }--#define INSTANCE_TYPEABLE1(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable1 tycon where { typeOf1 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable (tycon a) where { typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE2(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable2 tycon where { typeOf2 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable1 (tycon a) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b) => Typeable (tycon a b) where { \- typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE3(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable3 tycon where { typeOf3 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable2 (tycon a) where { \- typeOf2 = typeOf2Default }; \-instance (Typeable a, Typeable b) => Typeable1 (tycon a b) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b, Typeable c) => Typeable (tycon a b c) where { \- typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE4(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable4 tycon where { typeOf4 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable3 (tycon a) where { \- typeOf3 = typeOf3Default }; \-instance (Typeable a, Typeable b) => Typeable2 (tycon a b) where { \- typeOf2 = typeOf2Default }; \-instance (Typeable a, Typeable b, Typeable c) => Typeable1 (tycon a b c) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable (tycon a b c d) where { \- typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE5(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable5 tycon where { typeOf5 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable4 (tycon a) where { \- typeOf4 = typeOf4Default }; \-instance (Typeable a, Typeable b) => Typeable3 (tycon a b) where { \- typeOf3 = typeOf3Default }; \-instance (Typeable a, Typeable b, Typeable c) => Typeable2 (tycon a b c) where { \- typeOf2 = typeOf2Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable1 (tycon a b c d) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e) => Typeable (tycon a b c d e) where { \- typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE6(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable6 tycon where { typeOf6 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable5 (tycon a) where { \- typeOf5 = typeOf5Default }; \-instance (Typeable a, Typeable b) => Typeable4 (tycon a b) where { \- typeOf4 = typeOf4Default }; \-instance (Typeable a, Typeable b, Typeable c) => Typeable3 (tycon a b c) where { \- typeOf3 = typeOf3Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable2 (tycon a b c d) where { \- typeOf2 = typeOf2Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e) => Typeable1 (tycon a b c d e) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e, Typeable f) => Typeable (tycon a b c d e f) where { \- typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE7(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable7 tycon where { typeOf7 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable6 (tycon a) where { \- typeOf6 = typeOf6Default }; \-instance (Typeable a, Typeable b) => Typeable5 (tycon a b) where { \- typeOf5 = typeOf5Default }; \-instance (Typeable a, Typeable b, Typeable c) => Typeable4 (tycon a b c) where { \- typeOf4 = typeOf4Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable3 (tycon a b c d) where { \- typeOf3 = typeOf3Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e) => Typeable2 (tycon a b c d e) where { \- typeOf2 = typeOf2Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e, Typeable f) => Typeable1 (tycon a b c d e f) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e, Typeable f, Typeable g) => Typeable (tycon a b c d e f g) where { \- typeOf = typeOfDefault }--#endif /* !__GLASGOW_HASKELL__ */--#endif
@@ -1,24 +0,0 @@-#ifndef WCSUBST_INCL--#define WCSUBST_INCL--#include <stdlib.h>--int u_iswupper(int wc);-int u_iswdigit(int wc);-int u_iswalpha(int wc);-int u_iswcntrl(int wc);-int u_iswspace(int wc);-int u_iswprint(int wc);-int u_iswlower(int wc);--int u_iswalnum(int wc);--int u_towlower(int wc);-int u_towupper(int wc);-int u_towtitle(int wc);--int u_gencat(int wc);--#endif-
@@ -1,13 +0,0 @@-/* - * (c) The University of Glasgow, 2000-2002- *- * Win32 Console API helpers.- */-#ifndef __CONSUTILS_H__-#define __CONSUTILS_H__-extern int is_console__(int fd);-extern int set_console_buffering__(int fd, int cooked);-extern int set_console_echo__(int fd, int on);-extern int get_console_echo__(int fd);-extern int flush_input_console__ (int fd);-#endif
@@ -1,35 +0,0 @@-/* this file is #included into both C (.c and .hc) and Haskell files */-- /* IEEE format floating-point */-#define IEEE_FLOATING_POINT 1-- /* Radix of exponent representation */-#ifndef FLT_RADIX-# define FLT_RADIX 2-#endif-- /* Number of base-FLT_RADIX digits in the significand of a float */-#ifndef FLT_MANT_DIG-# define FLT_MANT_DIG 24-#endif- /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */-#ifndef FLT_MIN_EXP-# define FLT_MIN_EXP (-125)-#endif- /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */-#ifndef FLT_MAX_EXP-# define FLT_MAX_EXP 128-#endif-- /* Number of base-FLT_RADIX digits in the significand of a double */-#ifndef DBL_MANT_DIG-# define DBL_MANT_DIG 53-#endif- /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */-#ifndef DBL_MIN_EXP-# define DBL_MIN_EXP (-1021)-#endif- /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */-#ifndef DBL_MAX_EXP-# define DBL_MAX_EXP 1024-#endif
@@ -1,24 +0,0 @@-/* MD5 message digest */-#ifndef _MD5_H-#define _MD5_H--#include "HsFFI.h"--typedef HsWord32 word32;-typedef HsWord8 byte;--struct MD5Context {- word32 buf[4];- word32 bytes[2];- word32 in[16];-};--void MD5Init(struct MD5Context *context);-void MD5Update(struct MD5Context *context, byte const *buf, int len);-void MD5Final(byte digest[16], struct MD5Context *context);-void MD5Transform(word32 buf[4], word32 const in[16]);--#endif /* _MD5_H */---
@@ -1,507 +0,0 @@-#!/bin/sh-# install - install a program, script, or datafile--scriptversion=2006-10-14.15--# This originates from X11R5 (mit/util/scripts/install.sh), which was-# later released in X11R6 (xc/config/util/install.sh) with the-# following copyright and license.-#-# Copyright (C) 1994 X Consortium-#-# Permission is hereby granted, free of charge, to any person obtaining a copy-# of this software and associated documentation files (the "Software"), to-# deal in the Software without restriction, including without limitation the-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or-# sell copies of the Software, and to permit persons to whom the Software is-# furnished to do so, subject to the following conditions:-#-# The above copyright notice and this permission notice shall be included in-# all copies or substantial portions of the Software.-#-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC--# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.-#-# Except as contained in this notice, the name of the X Consortium shall not-# be used in advertising or otherwise to promote the sale, use or other deal--# ings in this Software without prior written authorization from the X Consor--# tium.-#-#-# FSF changes to this file are in the public domain.-#-# Calling this script install-sh is preferred over install.sh, to prevent-# `make' implicit rules from creating a file called install from it-# when there is no Makefile.-#-# This script is compatible with the BSD install script, but was written-# from scratch.--nl='-'-IFS=" "" $nl"--# set DOITPROG to echo to test this script--# Don't use :- since 4.3BSD and earlier shells don't like it.-doit="${DOITPROG-}"-if test -z "$doit"; then- doit_exec=exec-else- doit_exec=$doit-fi--# Put in absolute file names if you don't have them in your path;-# or use environment vars.--mvprog="${MVPROG-mv}"-cpprog="${CPPROG-cp}"-chmodprog="${CHMODPROG-chmod}"-chownprog="${CHOWNPROG-chown}"-chgrpprog="${CHGRPPROG-chgrp}"-stripprog="${STRIPPROG-strip}"-rmprog="${RMPROG-rm}"-mkdirprog="${MKDIRPROG-mkdir}"--posix_glob=-posix_mkdir=--# Desired mode of installed file.-mode=0755--chmodcmd=$chmodprog-chowncmd=-chgrpcmd=-stripcmd=-rmcmd="$rmprog -f"-mvcmd="$mvprog"-src=-dst=-dir_arg=-dstarg=-no_target_directory=--usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE- or: $0 [OPTION]... SRCFILES... DIRECTORY- or: $0 [OPTION]... -t DIRECTORY SRCFILES...- or: $0 [OPTION]... -d DIRECTORIES...--In the 1st form, copy SRCFILE to DSTFILE.-In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.-In the 4th, create DIRECTORIES.--Options:--c (ignored)--d create directories instead of installing files.--g GROUP $chgrpprog installed files to GROUP.--m MODE $chmodprog installed files to MODE.--o USER $chownprog installed files to USER.--s $stripprog installed files.--t DIRECTORY install into DIRECTORY.--T report an error if DSTFILE is a directory.---help display this help and exit.---version display version info and exit.--Environment variables override the default commands:- CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG-"--while test $# -ne 0; do- case $1 in- -c) shift- continue;;-- -d) dir_arg=true- shift- continue;;-- -g) chgrpcmd="$chgrpprog $2"- shift- shift- continue;;-- --help) echo "$usage"; exit $?;;-- -m) mode=$2- shift- shift- case $mode in- *' '* | *' '* | *'-'* | *'*'* | *'?'* | *'['*)- echo "$0: invalid mode: $mode" >&2- exit 1;;- esac- continue;;-- -o) chowncmd="$chownprog $2"- shift- shift- continue;;-- -s) stripcmd=$stripprog- shift- continue;;-- -t) dstarg=$2- shift- shift- continue;;-- -T) no_target_directory=true- shift- continue;;-- --version) echo "$0 $scriptversion"; exit $?;;-- --) shift- break;;-- -*) echo "$0: invalid option: $1" >&2- exit 1;;-- *) break;;- esac-done--if test $# -ne 0 && test -z "$dir_arg$dstarg"; then- # When -d is used, all remaining arguments are directories to create.- # When -t is used, the destination is already specified.- # Otherwise, the last argument is the destination. Remove it from $@.- for arg- do- if test -n "$dstarg"; then- # $@ is not empty: it contains at least $arg.- set fnord "$@" "$dstarg"- shift # fnord- fi- shift # arg- dstarg=$arg- done-fi--if test $# -eq 0; then- if test -z "$dir_arg"; then- echo "$0: no input file specified." >&2- exit 1- fi- # It's OK to call `install-sh -d' without argument.- # This can happen when creating conditional directories.- exit 0-fi--if test -z "$dir_arg"; then- trap '(exit $?); exit' 1 2 13 15-- # Set umask so as not to create temps with too-generous modes.- # However, 'strip' requires both read and write access to temps.- case $mode in- # Optimize common cases.- *644) cp_umask=133;;- *755) cp_umask=22;;-- *[0-7])- if test -z "$stripcmd"; then- u_plus_rw=- else- u_plus_rw='% 200'- fi- cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;- *)- if test -z "$stripcmd"; then- u_plus_rw=- else- u_plus_rw=,u+rw- fi- cp_umask=$mode$u_plus_rw;;- esac-fi--for src-do- # Protect names starting with `-'.- case $src in- -*) src=./$src ;;- esac-- if test -n "$dir_arg"; then- dst=$src- dstdir=$dst- test -d "$dstdir"- dstdir_status=$?- else-- # Waiting for this to be detected by the "$cpprog $src $dsttmp" command- # might cause directories to be created, which would be especially bad- # if $src (and thus $dsttmp) contains '*'.- if test ! -f "$src" && test ! -d "$src"; then- echo "$0: $src does not exist." >&2- exit 1- fi-- if test -z "$dstarg"; then- echo "$0: no destination specified." >&2- exit 1- fi-- dst=$dstarg- # Protect names starting with `-'.- case $dst in- -*) dst=./$dst ;;- esac-- # If destination is a directory, append the input filename; won't work- # if double slashes aren't ignored.- if test -d "$dst"; then- if test -n "$no_target_directory"; then- echo "$0: $dstarg: Is a directory" >&2- exit 1- fi- dstdir=$dst- dst=$dstdir/`basename "$src"`- dstdir_status=0- else- # Prefer dirname, but fall back on a substitute if dirname fails.- dstdir=`- (dirname "$dst") 2>/dev/null ||- expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$dst" : 'X\(//\)[^/]' \| \- X"$dst" : 'X\(//\)$' \| \- X"$dst" : 'X\(/\)' \| . 2>/dev/null ||- echo X"$dst" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'- `-- test -d "$dstdir"- dstdir_status=$?- fi- fi-- obsolete_mkdir_used=false-- if test $dstdir_status != 0; then- case $posix_mkdir in- '')- # Create intermediate dirs using mode 755 as modified by the umask.- # This is like FreeBSD 'install' as of 1997-10-28.- umask=`umask`- case $stripcmd.$umask in- # Optimize common cases.- *[2367][2367]) mkdir_umask=$umask;;- .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;-- *[0-7])- mkdir_umask=`expr $umask + 22 \- - $umask % 100 % 40 + $umask % 20 \- - $umask % 10 % 4 + $umask % 2- `;;- *) mkdir_umask=$umask,go-w;;- esac-- # With -d, create the new directory with the user-specified mode.- # Otherwise, rely on $mkdir_umask.- if test -n "$dir_arg"; then- mkdir_mode=-m$mode- else- mkdir_mode=- fi-- posix_mkdir=false- case $umask in- *[123567][0-7][0-7])- # POSIX mkdir -p sets u+wx bits regardless of umask, which- # is incompatible with FreeBSD 'install' when (umask & 300) != 0.- ;;- *)- tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0-- if (umask $mkdir_umask &&- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1- then- if test -z "$dir_arg" || {- # Check for POSIX incompatibilities with -m.- # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or- # other-writeable bit of parent directory when it shouldn't.- # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.- ls_ld_tmpdir=`ls -ld "$tmpdir"`- case $ls_ld_tmpdir in- d????-?r-*) different_mode=700;;- d????-?--*) different_mode=755;;- *) false;;- esac &&- $mkdirprog -m$different_mode -p -- "$tmpdir" && {- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`- test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"- }- }- then posix_mkdir=:- fi- rmdir "$tmpdir/d" "$tmpdir"- else- # Remove any dirs left behind by ancient mkdir implementations.- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null- fi- trap '' 0;;- esac;;- esac-- if- $posix_mkdir && (- umask $mkdir_umask &&- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"- )- then :- else-- # The umask is ridiculous, or mkdir does not conform to POSIX,- # or it failed possibly due to a race condition. Create the- # directory the slow way, step by step, checking for races as we go.-- case $dstdir in- /*) prefix=/ ;;- -*) prefix=./ ;;- *) prefix= ;;- esac-- case $posix_glob in- '')- if (set -f) 2>/dev/null; then- posix_glob=true- else- posix_glob=false- fi ;;- esac-- oIFS=$IFS- IFS=/- $posix_glob && set -f- set fnord $dstdir- shift- $posix_glob && set +f- IFS=$oIFS-- prefixes=-- for d- do- test -z "$d" && continue-- prefix=$prefix$d- if test -d "$prefix"; then- prefixes=- else- if $posix_mkdir; then- (umask=$mkdir_umask &&- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break- # Don't fail if two instances are running concurrently.- test -d "$prefix" || exit 1- else- case $prefix in- *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;- *) qprefix=$prefix;;- esac- prefixes="$prefixes '$qprefix'"- fi- fi- prefix=$prefix/- done-- if test -n "$prefixes"; then- # Don't fail if two instances are running concurrently.- (umask $mkdir_umask &&- eval "\$doit_exec \$mkdirprog $prefixes") ||- test -d "$dstdir" || exit 1- obsolete_mkdir_used=true- fi- fi- fi-- if test -n "$dir_arg"; then- { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&- { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&- { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||- test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1- else-- # Make a couple of temp file names in the proper directory.- dsttmp=$dstdir/_inst.$$_- rmtmp=$dstdir/_rm.$$_-- # Trap to clean up those temp files at exit.- trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0-- # Copy the file name to the temp name.- (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&-- # and set any options; do chmod last to preserve setuid bits.- #- # If any of these fail, we abort the whole thing. If we want to- # ignore errors from any of these, just make sure not to ignore- # errors from the above "$doit $cpprog $src $dsttmp" command.- #- { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \- && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \- && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \- && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&-- # Now rename the file to the real destination.- { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \- || {- # The rename failed, perhaps because mv can't rename something else- # to itself, or perhaps because mv is so ancient that it does not- # support -f.-- # Now remove or move aside any old file at destination location.- # We try this two ways since rm can't unlink itself on some- # systems and the destination file might be busy for other- # reasons. In this case, the final cleanup might fail but the new- # file should still install successfully.- {- if test -f "$dst"; then- $doit $rmcmd -f "$dst" 2>/dev/null \- || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \- && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\- || {- echo "$0: cannot unlink or rename $dst" >&2- (exit 1); exit 1- }- else- :- fi- } &&-- # Now rename the file to the real destination.- $doit $mvcmd "$dsttmp" "$dst"- }- } || exit 1-- trap '' 0- fi-done--# Local variables:-# eval: (add-hook 'write-file-hooks 'time-stamp)-# time-stamp-start: "scriptversion="-# time-stamp-format: "%:y-%02m-%02d.%02H"-# time-stamp-end: "$"-# End:
@@ -1,2380 +0,0 @@-{-# OPTIONS_GHC -cpp -fglasgow-exts -fno-warn-orphans #-}-{-@ LIQUID "--pruneunsorted" @-}-{-@ LIQUID "--no-totality" @-}---- #prune---- |--- Module : Data.ByteString--- Copyright : (c) The University of Glasgow 2001,--- (c) David Roundy 2003-2005,--- (c) Simon Marlow 2005--- (c) Don Stewart 2005-2006--- (c) Bjorn Bringert 2006------ Array fusion code:--- (c) 2001,2002 Manuel M T Chakravarty & Gabriele Keller--- (c) 2006 Manuel M T Chakravarty & Roman Leshchinskiy------ License : BSD-style------ Maintainer : dons@cse.unsw.edu.au--- Stability : experimental--- Portability : portable--- --- A time and space-efficient implementation of byte vectors using--- packed Word8 arrays, suitable for high performance use, both in terms--- of large data quantities, or high speed requirements. Byte vectors--- are encoded as strict 'Word8' arrays of bytes, held in a 'ForeignPtr',--- and can be passed between C and Haskell with little effort.------ This module is intended to be imported @qualified@, to avoid name--- clashes with "Prelude" functions. eg.------ > import qualified Data.ByteString as B------ Original GHC implementation by Bryan O\'Sullivan.--- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.--- Rewritten to support slices and use 'ForeignPtr' by David Roundy.--- Polished and extended by Don Stewart.-----module Data.ByteString (-- -- * The @ByteString@ type- ByteString, -- abstract, instances: Eq, Ord, Show, Read, Data, Typeable, Monoid-- -- * Introducing and eliminating 'ByteString's- empty, -- :: ByteString- singleton, -- :: Word8 -> ByteString- pack, -- :: [Word8] -> ByteString- unpack, -- :: ByteString -> [Word8]-- -- * Basic interface- cons, -- :: Word8 -> ByteString -> ByteString- snoc, -- :: ByteString -> Word8 -> ByteString- append, -- :: ByteString -> ByteString -> ByteString- head, -- :: ByteString -> Word8- uncons, -- :: ByteString -> Maybe (Word8, ByteString)- last, -- :: ByteString -> Word8- tail, -- :: ByteString -> ByteString- init, -- :: ByteString -> ByteString- null, -- :: ByteString -> Bool- length, -- :: ByteString -> Int-- -- * Transforming ByteStrings- map, -- :: (Word8 -> Word8) -> ByteString -> ByteString- reverse, -- :: ByteString -> ByteString- intersperse, -- :: Word8 -> ByteString -> ByteString- intercalate, -- :: ByteString -> [ByteString] -> ByteString- transpose, -- :: [ByteString] -> [ByteString]-- -- * Reducing 'ByteString's (folds)- foldl, -- :: (a -> Word8 -> a) -> a -> ByteString -> a- foldl', -- :: (a -> Word8 -> a) -> a -> ByteString -> a- foldl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8- foldl1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-- foldr, -- :: (Word8 -> a -> a) -> a -> ByteString -> a- foldr', -- :: (Word8 -> a -> a) -> a -> ByteString -> a- foldr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8- foldr1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-- -- ** Special folds- concat, -- :: [ByteString] -> ByteString- concatMap, -- :: (Word8 -> ByteString) -> ByteString -> ByteString- any, -- :: (Word8 -> Bool) -> ByteString -> Bool- all, -- :: (Word8 -> Bool) -> ByteString -> Bool- maximum, -- :: ByteString -> Word8- minimum, -- :: ByteString -> Word8-- -- * Building ByteStrings- -- ** Scans- scanl, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString- scanl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString- scanr, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString- scanr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-- -- ** Accumulating maps- mapAccumL, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)- mapAccumR, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)- mapIndexed, -- :: (Int -> Word8 -> Word8) -> ByteString -> ByteString-- -- ** Generating and unfolding ByteStrings- replicate, -- :: Int -> Word8 -> ByteString- unfoldr, -- :: (a -> Maybe (Word8, a)) -> a -> ByteString- unfoldrN, -- :: Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)-- -- * Substrings-- -- ** Breaking strings- take, -- :: Int -> ByteString -> ByteString- drop, -- :: Int -> ByteString -> ByteString- splitAt, -- :: Int -> ByteString -> (ByteString, ByteString)- takeWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString- dropWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString-- span, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- spanEnd, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- break, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- breakEnd, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- group, -- :: ByteString -> [ByteString]- groupBy, -- :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]- inits, -- :: ByteString -> [ByteString]- tails, -- :: ByteString -> [ByteString]-- -- ** Breaking into many substrings- split, -- :: Word8 -> ByteString -> [ByteString]- splitWith, -- :: (Word8 -> Bool) -> ByteString -> [ByteString]-- -- * Predicates- isPrefixOf, -- :: ByteString -> ByteString -> Bool- isSuffixOf, -- :: ByteString -> ByteString -> Bool- isInfixOf, -- :: ByteString -> ByteString -> Bool- isSubstringOf, -- :: ByteString -> ByteString -> Bool-- -- ** Search for arbitrary substrings- findSubstring, -- :: ByteString -> ByteString -> Maybe Int- findSubstrings, -- :: ByteString -> ByteString -> [Int]-- -- * Searching ByteStrings-- -- ** Searching by equality- elem, -- :: Word8 -> ByteString -> Bool- notElem, -- :: Word8 -> ByteString -> Bool-- -- ** Searching with a predicate- find, -- :: (Word8 -> Bool) -> ByteString -> Maybe Word8- filter, -- :: (Word8 -> Bool) -> ByteString -> ByteString- partition, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-- -- * Indexing ByteStrings- index, -- :: ByteString -> Int -> Word8- elemIndex, -- :: Word8 -> ByteString -> Maybe Int- elemIndices, -- :: Word8 -> ByteString -> [Int]- elemIndexEnd, -- :: Word8 -> ByteString -> Maybe Int- findIndex, -- :: (Word8 -> Bool) -> ByteString -> Maybe Int- findIndices, -- :: (Word8 -> Bool) -> ByteString -> [Int]- count, -- :: Word8 -> ByteString -> Int-- -- * Zipping and unzipping ByteStrings- zip, -- :: ByteString -> ByteString -> [(Word8,Word8)]- zipWith, -- :: (Word8 -> Word8 -> c) -> ByteString -> ByteString -> [c]- unzip, -- :: [(Word8,Word8)] -> (ByteString,ByteString)-- -- * Ordered ByteStrings--- LIQUID FAIL sort, -- :: ByteString -> ByteString-- -- * Low level conversions- -- ** Copying ByteStrings- copy, -- :: ByteString -> ByteString-- -- ** Packing 'CString's and pointers- packCString, -- :: CString -> IO ByteString- packCStringLen, -- :: CStringLen -> IO ByteString-- -- ** Using ByteStrings as 'CString's- useAsCString, -- :: ByteString -> (CString -> IO a) -> IO a- useAsCStringLen, -- :: ByteString -> (CStringLen -> IO a) -> IO a-- -- * I\/O with 'ByteString's-- -- ** Standard input and output- getLine, -- :: IO ByteString- getContents, -- :: IO ByteString- putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO ()- interact, -- :: (ByteString -> ByteString) -> IO ()-- -- ** Files- readFile, -- :: FilePath -> IO ByteString- writeFile, -- :: FilePath -> ByteString -> IO ()- appendFile, -- :: FilePath -> ByteString -> IO ()--- mmapFile, -- :: FilePath -> IO ByteString-- -- ** I\/O with Handles- hGetLine, -- :: Handle -> IO ByteString- hGetContents, -- :: Handle -> IO ByteString- hGet, -- :: Handle -> Int -> IO ByteString- hGetNonBlocking, -- :: Handle -> Int -> IO ByteString- hPut, -- :: Handle -> ByteString -> IO ()- hPutStr, -- :: Handle -> ByteString -> IO ()- hPutStrLn, -- :: Handle -> ByteString -> IO ()-- -- undocumented deprecated things:- join -- :: ByteString -> [ByteString] -> ByteString-- ) where--import Language.Haskell.Liquid.Prelude (unsafeError)-import qualified Prelude as P-import Prelude hiding (reverse,head,tail,last,init,null- ,length,map,lines,foldl,foldr,unlines- ,concat,any,take,drop,splitAt,takeWhile- ,dropWhile,span,break,elem,filter,maximum- ,minimum,all,concatMap,foldl1,foldr1- ,scanl,scanl1,scanr,scanr1- ,readFile,writeFile,appendFile,replicate- ,getContents,getLine,putStr,putStrLn,interact- ,zip,zipWith,unzip,notElem)--import Data.ByteString.Internal-import Data.ByteString.Unsafe-import Data.ByteString.Fusion--import qualified Data.List as List--import Data.Word (Word8)-import Data.Maybe (listToMaybe)-import Data.Array (listArray)-import qualified Data.Array as Array ((!))---- Control.Exception.bracket not available in yhc or nhc-#ifndef __NHC__-import Control.Exception (bracket, assert)-import qualified Control.Exception as Exception-#else-import IO (bracket)-#endif-import Control.Monad (when)--import Foreign.C.String (CString, CStringLen)-import Foreign.C.Types (CSize)-import Foreign.ForeignPtr-import Foreign.Marshal.Alloc (allocaBytes, mallocBytes, reallocBytes, finalizerFree)-import Foreign.Marshal.Array (allocaArray)-import Foreign.Ptr-import Foreign.Storable (Storable(..))---- hGetBuf and hPutBuf not available in yhc or nhc-import System.IO (stdin,stdout,hClose,hFileSize- ,hGetBuf,hPutBuf,openBinaryFile- ,Handle,IOMode(..))--import Data.Monoid (Monoid, mempty, mappend, mconcat)--#if !defined(__GLASGOW_HASKELL__)-import System.IO.Unsafe-import qualified System.Environment-import qualified System.IO (hGetLine)-#endif--#if defined(__GLASGOW_HASKELL__)--import System.IO (hGetBufNonBlocking)-import System.IO.Error (isEOFError)--import GHC.Exts (Word#, (+#), writeWord8OffAddr#)-import GHC.Base (build)-import GHC.Word hiding (Word8)-import GHC.Ptr (Ptr(..))-import GHC.ST (ST(..))--#endif-#if __GLASGOW_HASKELL__ >= 611-import Data.IORef-import GHC.IO.Handle.Internals-import GHC.IO.Handle.Types-import GHC.IO.Buffer-import GHC.IO.BufferedIO as Buffered-import GHC.IO (stToIO, unsafePerformIO)-import Data.Char (ord)-import Foreign.Marshal.Utils (copyBytes)-#else-import System.IO.Error (isEOFError)-import GHC.Handle-#endif--- An alternative to Control.Exception (assert) for nhc98-#ifdef __NHC__-#define assert assertS "__FILE__ : __LINE__"-assertS :: String -> Bool -> a -> a-assertS _ True = id-assertS s False = unsafeError ("assertion failed at "++s)-#endif---- LIQUID-import GHC.IO.Buffer-import Language.Haskell.Liquid.Prelude hiding (eq) -import Language.Haskell.Liquid.Foreign --{-@ include <Data/ByteString.hs.hquals> @-}--{-@ memcpy_ptr_baoff :: p:(Ptr a) - -> RawBuffer b - -> Int - -> {v:CSize | (OkPLen v p)} -> IO (Ptr ())- @-}-memcpy_ptr_baoff :: Ptr a -> RawBuffer b -> Int -> CSize -> IO (Ptr ())-memcpy_ptr_baoff = unsafeError "LIQUIDCOMPAT"--readCharFromBuffer :: RawBuffer b -> Int -> IO (Char, Int)-readCharFromBuffer x y = unsafeError "LIQUIDCOMPAT"--wantReadableHandleLIQUID :: String -> Handle -> (Handle__ -> IO a) -> IO a-wantReadableHandleLIQUID x y f = unsafeError $ show $ liquidCanaryFusion 12 -- "LIQUIDCOMPAT"--{- IN INCLUDE FILE qualif Gimme(v:a, n:b, acc:a): (len v) = (n + 1 + (len acc)) @-}-{- qualif Zog(v:a, p:a) : (plen p) <= (plen v) @-}-{- qualif Zog(v:a) : 0 <= (plen v) @-}---- for unfoldrN -{- IN INCLUDE FILE qualif PtrDiffUnfoldrN(v:int, i:int, p:Ptr a): (i - v) <= (plen p) @-}--{-@ lengths :: bs:[ByteString] -> {v:Nat | v = (bLengths bs)} @-}-lengths :: [ByteString] -> Int-lengths [] = 0-lengths (b:bs) = length b + lengths bs---- LIQUID HACK: this is to get all the quals from memchr. --- Quals needed because IO monad forces liquid-abstraction. --- Solution, scrape quals from predicate defs (e.g. SuffixPtr)-{-@ dummyForQuals1_elemIndex :: p:(Ptr a) -> n:Int -> (IO {v:(Ptr b) | (SuffixPtr v n p)}) @-}-dummyForQuals1_elemIndex :: Ptr a -> Int -> IO (Ptr b)-dummyForQuals1_elemIndex = undefined --{-@ dummyForQuals2_splitWith :: p:(ForeignPtr Word8) -> o:{v:Nat | v <= (fplen p)} -> {v:Nat | (BSValid p o v)} -> ByteString - @-}-dummyForQuals2_splitWith :: ForeignPtr Word8 -> Int -> Int -> ByteString-dummyForQuals2_splitWith = undefined---- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined---- -------------------------------------------------------------------------------instance Eq ByteString- where (==) = eq--instance Ord ByteString- where compare = compareBytes---- LIQUID instance Monoid ByteString where--- LIQUID mempty = empty--- LIQUID mappend = append--- LIQUID mconcat = concat--{--instance Arbitrary PackedString where- arbitrary = P.pack `fmap` arbitrary- coarbitrary s = coarbitrary (P.unpack s)--}---- | /O(n)/ Equality on the 'ByteString' type.-{-@ eq :: ByteString -> ByteString -> Bool @-}-eq :: ByteString -> ByteString -> Bool-eq a@(PS p s l) b@(PS p' s' l')- | l /= l' = False -- short cut on length- | p == p' && s == s' = True -- short cut for the same string- | otherwise = compareBytes a b == EQ-{-# INLINE eq #-}---- | /O(n)/ 'compareBytes' provides an 'Ordering' for 'ByteStrings' supporting slices. -compareBytes :: ByteString -> ByteString -> Ordering-compareBytes (PS x1 s1 l1) (PS x2 s2 l2)- | l1 == 0 && l2 == 0 = EQ -- short cut for empty strings- | x1 == x2 && s1 == s2 && l1 == l2 = EQ -- short cut for the same string- | otherwise = inlinePerformIO $- withForeignPtr x1 $ \p1 ->- withForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral $ min l1 l2)- return $! case i `compare` 0 of- EQ -> l1 `compare` l2- x -> x-{-# INLINE compareBytes #-}-- -{------- About 4x slower over 32M----compareBytes :: ByteString -> ByteString -> Ordering-compareBytes (PS fp1 off1 len1) (PS fp2 off2 len2) = inlinePerformIO $- withForeignPtr fp1 $ \p1 ->- withForeignPtr fp2 $ \p2 ->- cmp (p1 `plusPtr` off1)- (p2 `plusPtr` off2) 0 len1 len2--cmp :: Ptr Word8 -> Ptr Word8 -> Int -> Int -> Int-> IO Ordering-STRICT5(cmp)-cmp p1 p2 n len1 len2- | n == len1 = if n == len2 then return EQ else return LT- | n == len2 = return GT- | otherwise = do- (a :: Word8) <- peekByteOff p1 n- (b :: Word8) <- peekByteOff p2 n- case a `compare` b of- EQ -> cmp p1 p2 (n+1) len1 len2- LT -> return LT- GT -> return GT-{-# INLINE compareBytes #-}--}---- -------------------------------------------------------------------------------- Introducing and eliminating 'ByteString's---- | /O(1)/ The empty 'ByteString'-{-@ empty :: {v:ByteString | (bLength v) = 0} @-} -empty :: ByteString-empty = PS nullForeignPtr 0 0-- --- | /O(1)/ Convert a 'Word8' into a 'ByteString'--{-@ singleton :: Word8 -> {v:ByteString | (bLength v) = 1} @-}-singleton :: Word8 -> ByteString-singleton c = unsafeCreate 1 $ \p -> poke p c-{-# INLINE [1] singleton #-}------- XXX The unsafePerformIO is critical!------ Otherwise:------ singleton 255 `compare` singleton 127------ is compiled to:------ case mallocByteString 2 of --- ForeignPtr f internals -> --- case writeWord8OffAddr# f 0 255 of _ -> --- case writeWord8OffAddr# f 0 127 of _ ->--- case eqAddr# f f of --- False -> case compare (GHC.Prim.plusAddr# f 0) --- (GHC.Prim.plusAddr# f 0)---------- | /O(n)/ Convert a '[Word8]' into a 'ByteString'. ------ For applications with large numbers of string literals, pack can be a--- bottleneck. In such cases, consider using packAddress (GHC only).-{-@ pack :: cs:[Word8] -> {v:ByteString | (bLength v) = (len cs)} @-}-pack :: [Word8] -> ByteString--#if !defined(__GLASGOW_HASKELL__)--pack str = unsafeCreate (P.length str) $ \p -> go p str- where- go _ [] = return ()- go p (x:xs) = poke p x >> go (p `plusPtr` 1) xs -- less space than pokeElemOff--#else /* hack away */--pack str = unsafeCreate (P.length str) $ \(Ptr p) -> stToIO (goz str p 0# )- where- {- goz :: _ -> _ -> cs:_ -> _ / [len cs] -}- goz [] _ _ = return ()- goz (W8# c:cs) p i = writeByte p i c >> goz cs p (i +# 1#) -- writeByte p i c = ST $ \s# ->- case writeWord8OffAddr# p i c s# of s2# -> (# s2#, () #)--#endif----- | /O(n)/ Converts a 'ByteString' to a '[Word8]'.-{-@ unpack :: b:ByteString -> {v:[Word8] | (len v) = (bLength b)} @-}-unpack :: ByteString -> [Word8]--#if !defined(__GLASGOW_HASKELL__)--- LIQUID -- unpack (PS _ _ 0) = []--- LIQUID -- unpack (PS ps s l) = inlinePerformIO $ withForeignPtr ps $ \p ->--- LIQUID -- ugo (p `plusPtr` s) (l - 1) []--- LIQUID -- --- LIQUID -- ugo :: ForeignPtr Word8 -> Int -> [Word8] -> IO Word8 --- LIQUID -- ugo p 0 acc = peek p >>= \e -> return (e : acc)--- LIQUID -- ugo p n acc = peekByteOff p n >>= \e -> ugo p (n-1) (e : acc)-unpack (PS _ _ 0) = []-unpack (PS ps s l) = inlinePerformIO $ withForeignPtr ps $ \p ->- go (p `plusPtr` s) (l - 1) []- where- STRICT3(go)- go p 0 acc = peek p >>= \e -> return (e : acc)- go p n acc = peekByteOff p n >>= \e -> go p (n-1) (e : acc)-{-# INLINE unpack #-}--#else---- unpack ps = build (unpackFoldr ps)---- LIQUID TODO unpackFoldr :: forall <p :: Int -> a -> Bool>. --- b:ByteString --- -> (i:Int -> Word8 -> a<p i> -> a<p (i+1)>)--- -> (a<p 0>)--- -> (a<p (bLength b)>)-{-# INLINE unpack #-}---- LIQUID INLINED : unpack ps = build (unpackFoldr ps) = unpackFoldr ps (:) [] --- LIQUID INLINED : so inline `f` with `:` and `ch` with `[]`-unpack ps = unpackFoldrINLINED ps--unpackFoldrINLINED :: ByteString -> [Word8]-unpackFoldrINLINED (PS fp off len) = withPtr fp $ \p -> do- let loop _ q n _ | q `seq` n `seq` False = undefined -- n.b.- loop _ _ (-1) acc = return acc- {- LIQUID WITNESS -}- loop (d::Int) q n acc = do- a <- peekByteOff q n- loop (d-1) q (n-1) (a : acc)- loop len (p `plusPtr` off) (len-1) [] ---- critical this isn't strict in the acc--- as it will break in the presence of list fusion. this is a known--- issue with seq and build/foldr rewrite rules, which rely on lazy--- demanding to avoid bottoms in the list.----unpackFoldr :: ByteString -> (Word8 -> a -> a) -> a -> a-unpackFoldr (PS fp off len) f ch = withPtr fp $ \p -> do- let loop _ q n _ | q `seq` n `seq` False = undefined -- n.b.- loop _ _ (-1) acc = return acc- {- LIQUID WITNESS -}- loop (d :: Int) q n acc = do- a <- peekByteOff q n- loop (d-1) q (n-1) (a `f` acc)- loop len (p `plusPtr` off) (len-1) ch-{-# INLINE [0] unpackFoldr #-}--{-@ unpackList :: b:ByteString -> {v:[Word8] | (len v) = (bLength b)} @-}-unpackList :: ByteString -> [Word8]-unpackList (PS fp off len) = withPtr fp $ \p -> do- let STRICT4(loop)- loop _ _ (-1) acc = return acc- {- LIQUID WITNESS -}- loop (d::Int) q n acc = do- a <- peekByteOff q n- loop (d-1) q (n-1) (a : acc)- loop len (p `plusPtr` off) (len-1) []--{-# RULES- "FPS unpack-list" [1] forall p . unpackFoldr p (:) [] = unpackList p- #-}--#endif---- ------------------------------------------------------------------------ Basic interface---- | /O(1)/ Test whether a ByteString is empty.-{-@ null :: b:ByteString -> {v:Bool | (v <=> ((bLength b) = 0))} @-}-null :: ByteString -> Bool-null (PS _ _ l) = assert (l >= 0) $ l <= 0-{-# INLINE null #-}---- ------------------------------------------------------------------------ | /O(1)/ 'length' returns the length of a ByteString as an 'Int'.-{-@ length :: b:ByteString -> {v:Nat | v = (bLength b)} @-}-length :: ByteString -> Int-length (PS _ _ l) = assert (l >= 0) $ l-{-# INLINE length #-}------------------------------------------------------------------------------ | /O(n)/ 'cons' is analogous to (:) for lists, but of different--- complexity, as it requires a memcpy.--{-@ cons :: Word8 -> b:ByteString -> {v:ByteString | (bLength v) = 1 + (bLength b)} @-}-cons :: Word8 -> ByteString -> ByteString-cons c (PS x s l) = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do- poke p c- memcpy (p `plusPtr` 1) (f `plusPtr` s) (fromIntegral l)-{-# INLINE cons #-}---- | /O(n)/ Append a byte to the end of a 'ByteString'-{-@ snoc :: b:ByteString -> Word8 -> {v:ByteString | (bLength v) = 1 + (bLength b)} @-}-snoc :: ByteString -> Word8 -> ByteString-snoc (PS x s l) c = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do- memcpy p (f `plusPtr` s) (fromIntegral l)- poke (p `plusPtr` l) c-{-# INLINE snoc #-}---- todo fuse---- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.--- An exception will be thrown in the case of an empty ByteString.-{-@ head :: ByteStringNE -> Word8 @-}-head :: ByteString -> Word8-head (PS x s l)- | l <= 0 = errorEmptyList "head"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p s-{-# INLINE head #-}---- | /O(1)/ Extract the elements after the head of a ByteString, which must be non-empty.--- An exception will be thrown in the case of an empty ByteString.-{-@ tail :: b:ByteStringNE -> {v:ByteString | (bLength v) = (bLength b) - 1} @-}-tail :: ByteString -> ByteString-tail (PS p s l)- | l <= 0 = errorEmptyList "tail"- | otherwise = PS p (s+1) (l-1)-{-# INLINE tail #-}---- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing--- if it is empty.-{-@ uncons :: b:ByteString -> Maybe (Word8, {v:ByteString | (bLength v) = (bLength b) - 1}) @-}-uncons :: ByteString -> Maybe (Word8, ByteString)-uncons (PS x s l)- | l <= 0 = Nothing- | otherwise = Just (inlinePerformIO $ withForeignPtr x- $ \p -> peekByteOff p s,- PS x (s+1) (l-1))-{-# INLINE uncons #-}---- | /O(1)/ Extract the last element of a ByteString, which must be finite and non-empty.--- An exception will be thrown in the case of an empty ByteString.-{-@ last :: ByteStringNE -> Word8 @-}-last :: ByteString -> Word8-last ps@(PS x s l)- | null ps = errorEmptyList "last"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+l-1)-{-# INLINE last #-}---- | /O(1)/ Return all the elements of a 'ByteString' except the last one.--- An exception will be thrown in the case of an empty ByteString.-{-@ init :: b:ByteStringNE -> {v:ByteString | (bLength v) = (bLength b) - 1} @-}-init :: ByteString -> ByteString-init ps@(PS p s l)- | null ps = errorEmptyList "init"- | otherwise = PS p s (l-1)-{-# INLINE init #-}---- | /O(n)/ Append two ByteStrings-{-@ append :: b1:ByteString -> b2:ByteString - -> {v:ByteString | (bLength v) = (bLength b1) + (bLength b2)} - @-}-append :: ByteString -> ByteString -> ByteString-append xs ys | null xs = ys- | null ys = xs- | otherwise = concat [xs,ys]-{-# INLINE append #-}---- ------------------------------------------------------------------------ Transformations---- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each--- element of @xs@. This function is subject to array fusion.-{-@ map :: (Word8 -> Word8) -> b:ByteString -> (ByteStringSZ b) @-}-map :: (Word8 -> Word8) -> ByteString -> ByteString-map f (PS fp s len) = inlinePerformIO $ withForeignPtr fp $ \a ->- create len $ map_ len 0 (a `plusPtr` s)- where- map_ :: Int -> Int -> Ptr Word8 -> Ptr Word8 -> IO ()- STRICT4(map_)- {- LIQUID WITNESS -}- map_ (d :: Int) n p1 p2- | n >= len = return ()- | otherwise = do- x <- peekByteOff p1 n- pokeByteOff p2 n (f x)- map_ (d-1) (n+1) p1 p2-{-# INLINE map #-}---- | /O(n)/ 'reverse' @xs@ efficiently returns the elements of @xs@ in reverse order.--{-@ reverse :: b:ByteString -> (ByteStringSZ b) @-}-reverse :: ByteString -> ByteString-reverse (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->- c_reverse p (f `plusPtr` s) (fromIntegral l)---- | /O(n)/ The 'intersperse' function takes a 'Word8' and a--- 'ByteString' and \`intersperses\' that byte between the elements of--- the 'ByteString'. It is analogous to the intersperse function on--- Lists.-{-@ intersperse :: Word8 -> b:ByteString- -> {v:ByteString | bLength v = if bLength b > 0 then (2 * bLength b - 1) else 0 }- @-}-intersperse :: Word8 -> ByteString -> ByteString-intersperse c ps@(PS x s l)- | length ps < 2 = ps- | otherwise = unsafeCreate ({- 2*l -} (l + l) - 1) $ \p -> withForeignPtr x $ \f ->- c_intersperse p (f `plusPtr` s) (fromIntegral l) c--{--intersperse c = pack . List.intersperse c . unpack--}---- | The 'transpose' function transposes the rows and columns of its--- 'ByteString' argument.-transpose :: [ByteString] -> [ByteString]-transpose ps = P.map pack (List.transpose (P.map unpack ps))---- LIQUID TODO--- transpose :: bs:[ByteString] -> {v:[ByteString] | (bLengths v) = (bLengths bs)}--- transpose :: xs:[[a]] -> {v:[[a]] | (lens v) = (lens xs)}--- transpose ps = [pack p | p <- List.transpose [unpack p | p <- ps] ]----- ------------------------------------------------------------------------ Reducing 'ByteString's---- | 'foldl', applied to a binary operator, a starting value (typically--- the left-identity of the operator), and a ByteString, reduces the--- ByteString using the binary operator, from left to right.--- This function is subject to array fusion.--{-@ foldl :: (a -> Word8 -> a) -> a -> ByteString -> a @-}-foldl :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl f v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go v (ptr `plusPtr` s) (ptr `plusPtr` (s+l)) (ptrLen (ptr `plusPtr` s))- where- STRICT4(go)- {- LIQUID WITNESS -}- go z p q (d::Int)- | p == q = return z- | otherwise = do let p' = liquid_thm_ptr_cmp p q - c <- peek p'- go (f z c) (p' `plusPtr` 1) q (d-1)-{-# INLINE foldl #-}---- LIQUID: This will go away when we properly embed Ptr a as int -- only in--- fixpoint to avoid the Sort mismatch hassles. -{-@ liquid_thm_ptr_cmp :: p:PtrV a - -> q:{v:(PtrV a) | ((plen v) <= (plen p) && v != p && (pbase v) = (pbase p))} - -> {v: (PtrV a) | ((v = p) && ((plen q) < (plen p))) } - @-}-liquid_thm_ptr_cmp :: Ptr a -> Ptr a -> Ptr a-liquid_thm_ptr_cmp p q = undefined -- p -- LIQUID : make this undefined to suppress WARNING----- | 'foldl\'' is like 'foldl', but strict in the accumulator.--- Though actually foldl is also strict in the accumulator.-{-@ foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a @-}-foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl' = foldl-{-# INLINE foldl' #-}---- | 'foldr', applied to a binary operator, a starting value--- (typically the right-identity of the operator), and a ByteString,--- reduces the ByteString using the binary operator, from right to left.---- foldr/foldr' TERMINATION-{-@ qualif PtrDiff(v:int, p:Ptr a, q:Ptr a): v >= (plen p) - (plen q) @-}--{-@ foldr :: (Word8 -> a -> a) -> a -> ByteString -> a @-}-foldr :: (Word8 -> a -> a) -> a -> ByteString -> a-foldr k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1)) l- where- STRICT4(go)- {- LIQUID WITNESS -}- go z p q (d::Int)- | p == q = return z- | otherwise = do let p' = liquid_thm_ptr_cmp' p q - c <- peek p'- let n = 0 - 1 - go (c `k` z) (p' `plusPtr` n) q (d-1) -- tail recursive- -- LIQUID go z p q | p == q = return z- -- LIQUID | otherwise = do c <- peek p- -- LIQUID go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive-{-# INLINE foldr #-}--{-@ liquid_thm_ptr_cmp' :: p:PtrV a - -> q:{v:(PtrV a) | ((plen v) >= (plen p) && v != p && (pbase v) = (pbase p))} - -> {v: (PtrV a) | ((v = p) && ((plen v) > 0) && ((plen q) > (plen p))) } - @-}-liquid_thm_ptr_cmp' :: Ptr a -> Ptr a -> Ptr a-liquid_thm_ptr_cmp' p q = undefined ---- | 'foldr\'' is like 'foldr', but strict in the accumulator.-foldr' :: (Word8 -> a -> a) -> a -> ByteString -> a-foldr' k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1)) l- where- STRICT4(go)- {- LIQUID WITNESS -}- go z p q (d::Int)- | p == q = return z- | otherwise = do let p' = liquid_thm_ptr_cmp' p q - c <- peek p'- let n = 0 - 1 - go (c `k` z) (p' `plusPtr` n) q (d-1) -- tail recursive- -- LIQUID go z p q | p == q = return z- -- LIQUID | otherwise = do c <- peek p- -- LIQUID go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive-{-# INLINE foldr' #-}---- | 'foldl1' is a variant of 'foldl' that has no starting value--- argument, and thus must be applied to non-empty 'ByteStrings'.--- This function is subject to array fusion. --- An exception will be thrown in the case of an empty ByteString.-{-@ foldl1 :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldl1 f ps- | null ps = errorEmptyList "foldl1"- | otherwise = foldl f (unsafeHead ps) (unsafeTail ps)-{-# INLINE foldl1 #-}---- | 'foldl1\'' is like 'foldl1', but strict in the accumulator.--- An exception will be thrown in the case of an empty ByteString.-{-@ foldl1' :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldl1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldl1' f ps- | null ps = errorEmptyList "foldl1'"- | otherwise = foldl' f (unsafeHead ps) (unsafeTail ps)-{-# INLINE foldl1' #-}---- | 'foldr1' is a variant of 'foldr' that has no starting value argument,--- and thus must be applied to non-empty 'ByteString's--- An exception will be thrown in the case of an empty ByteString.--{-@ foldr1 :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldr1 f ps- | null ps = errorEmptyList "foldr1"- | otherwise = foldr f (last ps) (init ps)-{-# INLINE foldr1 #-}---- | 'foldr1\'' is a variant of 'foldr1', but is strict in the--- accumulator.-{-@ foldr1' :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldr1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldr1' f ps- | null ps = errorEmptyList "foldr1"- | otherwise = foldr' f (last ps) (init ps)-{-# INLINE foldr1' #-}---- ------------------------------------------------------------------------ Special folds---- | /O(n)/ Concatenate a list of ByteStrings.-{-@ concat :: bs:[ByteString] -> {v:ByteString | (bLength v) = (bLengths bs)} @-}-concat :: [ByteString] -> ByteString-concat [] = empty-concat [ps] = ps-concat xs = unsafeCreate len $ \ptr -> go xs ptr- where len = {- LIQUID P.sum . P.map length $ -} lengths xs- STRICT2(go)- go [] _ = return ()- go (PS p s l:ps) ptr = do- -- LIQUID: could instead use (also works)- -- LIQUID {- invariant {v: [ByteString] | 0 <= (bLengths v)} -}- let p' = liquidAssert (lengths ps >= 0) p- withForeignPtr p' $ \fp -> memcpy ptr (fp `plusPtr` s) (fromIntegral l)- go ps (ptr `plusPtr` l)---- | Map a function over a 'ByteString' and concatenate the results-concatMap :: (Word8 -> ByteString) -> ByteString -> ByteString-concatMap f = concat . foldr ((:) . f) []---- foldr (append . f) empty---- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if--- any element of the 'ByteString' satisfies the predicate.-any :: (Word8 -> Bool) -> ByteString -> Bool-any _ (PS _ _ 0) = False-any f (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go (ptr `plusPtr` s) (ptr `plusPtr` (s+l)) (ptrLen (ptr `plusPtr` s)) - where- STRICT3(go)- {- LIQUID WITNESS -}- go p q (d::Int) | p == q = return False- | otherwise = do let p' = liquid_thm_ptr_cmp p q -- LIQUID- c <- peek p'- if f c then return True- else go (p' `plusPtr` 1) q (d-1)-{-# INLINE any #-}---- todo fuse---- | /O(n)/ Applied to a predicate and a 'ByteString', 'all' determines--- if all elements of the 'ByteString' satisfy the predicate.-all :: (Word8 -> Bool) -> ByteString -> Bool-all _ (PS _ _ 0) = True-all f (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go (ptr `plusPtr` s) (ptr `plusPtr` (s+l)) (ptrLen (ptr `plusPtr` s))- where- STRICT3(go)- {- LIQUID WITNESS -}- go p q (d::Int)- | p == q = return True -- end of list- | otherwise = do let p' = liquid_thm_ptr_cmp p q -- LIQUID- c <- peek p'- if f c- then go (p' `plusPtr` 1) q (d-1)- else return False-{-# INLINE all #-}------------------------------------------------------------------------------ | /O(n)/ 'maximum' returns the maximum value from a 'ByteString'--- This function will fuse.--- An exception will be thrown in the case of an empty ByteString.-{-@ maximum :: ByteStringNE -> Word8 @-}-maximum :: ByteString -> Word8-maximum xs@(PS x s l)- | null xs = errorEmptyList "maximum"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p ->- c_maximum (p `plusPtr` s) (fromIntegral l)-{-# INLINE maximum #-}---- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString'--- This function will fuse.--- An exception will be thrown in the case of an empty ByteString.-{-@ minimum :: ByteStringNE -> Word8 @-}-minimum :: ByteString -> Word8-minimum xs@(PS x s l)- | null xs = errorEmptyList "minimum"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p ->- c_minimum (p `plusPtr` s) (fromIntegral l)-{-# INLINE minimum #-}------------------------------------------------------------------------------ | The 'mapAccumL' function behaves like a combination of 'map' and--- 'foldl'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from left to right, and returning a--- final value of this accumulator together with the new list.--{-@ mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> b:ByteString -> (acc, ByteStringSZ b) @-}-mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-#if !defined(LOOPU_FUSION)-mapAccumL f z b = unSP $ loopUp (mapAccumEFL f) z b-#else-mapAccumL f z b = unSP $ loopU (mapAccumEFL f) z b-#endif-{-# INLINE mapAccumL #-}---- | The 'mapAccumR' function behaves like a combination of 'map' and--- 'foldr'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from right to left, and returning a--- final value of this accumulator together with the new ByteString.--{-@ mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> b:ByteString -> (acc, ByteStringSZ b) @-}-mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumR f z b = unSP $ loopDown (mapAccumEFL f) z b-{-# INLINE mapAccumR #-}---- | /O(n)/ map Word8 functions, provided with the index at each position-{-@ mapIndexed :: (Int -> Word8 -> Word8) -> b:ByteString -> ByteStringSZ b @-}-mapIndexed :: (Int -> Word8 -> Word8) -> ByteString -> ByteString-mapIndexed f b = loopArr $ loopUp (mapIndexEFL f) 0 b-{-# INLINE mapIndexed #-}---- ------------------------------------------------------------------------ Building ByteStrings---- | 'scanl' is similar to 'foldl', but returns a list of successive--- reduced values from the left. This function will fuse.------ > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]------ Note that------ > last (scanl f z xs) == foldl f z xs.--{-@ scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> b:ByteString -> {v:ByteString | (bLength v) = 1 + (bLength b)} @-}-scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString-#if !defined(LOOPU_FUSION)-scanl f z ps = loopArr . loopUp (scanEFL f) z $ (ps `snoc` 0)-#else-scanl f z ps = loopArr . loopU (scanEFL f) z $ (ps `snoc` 0)-#endif-- -- n.b. haskell's List scan returns a list one bigger than the- -- input, so we need to snoc here to get some extra space, however,- -- it breaks map/up fusion (i.e. scanl . map no longer fuses)-{-# INLINE scanl #-}---- | 'scanl1' is a variant of 'scanl' that has no starting value argument.--- This function will fuse.------ > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]-{-@ scanl1 :: (Word8 -> Word8 -> Word8) -> b:ByteStringNE -> (ByteStringSZ b) @-}-scanl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-scanl1 f ps- | null ps = empty- | otherwise = scanl f (unsafeHead ps) (unsafeTail ps)-{-# INLINE scanl1 #-}---- | scanr is the right-to-left dual of scanl.-{-@ scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> b:ByteString -> {v:ByteStringNE | (bLength v) = 1 + (bLength b)} @-}-scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString-scanr f z ps = loopArr . loopDown (scanEFL (flip f)) z $ (0 `cons` ps) -- extra space-{-# INLINE scanr #-}---- | 'scanr1' is a variant of 'scanr' that has no starting value argument.-{-@ scanr1 :: (Word8 -> Word8 -> Word8) -> b:ByteStringNE -> (ByteStringSZ b) @-}-scanr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-scanr1 f ps- | null ps = empty- | otherwise = scanr f (last ps) (init ps) -- todo, unsafe versions-{-# INLINE scanr1 #-}---- ------------------------------------------------------------------------ Unfolds and replicates---- | /O(n)/ 'replicate' @n x@ is a ByteString of length @n@ with @x@--- the value of every element. The following holds:------ > replicate w c = unfoldr w (\u -> Just (u,u)) c------ This implemenation uses @memset(3)@-{- LIQUID this is SIMPLER ... : replicate :: n:Nat -> Word8 -> (ByteStringN n) @-}-{-@ replicate :: n:Nat -> Word8 -> {v:ByteString | (bLength v) = (if n > 0 then n else 0)} @-}-replicate :: Int -> Word8 -> ByteString-replicate w c- | w <= 0 = empty- | otherwise = unsafeCreate w $ \ptr ->- memset ptr c (fromIntegral w) >> return ()---- | /O(n)/, where /n/ is the length of the result. The 'unfoldr' --- function is analogous to the List \'unfoldr\'. 'unfoldr' builds a --- ByteString from a seed value. The function takes the element and --- returns 'Nothing' if it is done producing the ByteString or returns --- 'Just' @(a,b)@, in which case, @a@ is the next byte in the string, --- and @b@ is the seed value for further production.------ Examples:------ > unfoldr (\x -> if x <= 5 then Just (x, x + 1) else Nothing) 0--- > == pack [0, 1, 2, 3, 4, 5]--{-@ unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString @-}-{-@ lazy unfoldr @-}-unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString-unfoldr f = concat . unfoldChunk 32 64- where unfoldChunk n n' x =- case unfoldrN n f x of- (s, Nothing) -> s : []- (s, Just x') -> s : unfoldChunk n' (n+n') x'-{-# INLINE unfoldr #-}---- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a ByteString from a seed--- value. However, the length of the result is limited by the first--- argument to 'unfoldrN'. This function is more efficient than 'unfoldr'--- when the maximum length of the result is known.------ The following equation relates 'unfoldrN' and 'unfoldr':------ > unfoldrN n f s == take n (unfoldr f s)----{-@ unfoldrN :: i:Nat -> (a -> Maybe (Word8, a)) -> a -> ({v:ByteString | (bLength v) <= i}, Maybe a)<{\b m -> ((isJust m) => ((bLength b) = i))}> @-}-unfoldrN :: Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)-unfoldrN i f x0- | i < 0 = (empty, Just x0)- | otherwise = unsafePerformIO $ createAndTrimMEQ i $ \p -> go_unfoldrN i p x0 0- {-@ decrease go_unfoldrN 1 @-}- where STRICT4(go)- {- LIQUID WITNESS -}- go_unfoldrN (d::Int) p x n =- case f x of- Nothing -> return (0 :: Int {- LIQUID -}, n, Nothing)- Just (w,x')- | n == i -> return (0, n, Just x)- | otherwise -> do poke p w- go_unfoldrN (d-1) (p `plusPtr` 1) x' (n+1)-{-# INLINE unfoldrN #-}--{-@ unfoldqual :: l:Nat -> {v:(Nat, Nat, Maybe a) | (((tsnd v) <= (l-(tfst v)))- && ((isJust (ttrd v)) => ((tsnd v)=l)))} @-}-unfoldqual :: Int -> (Int, Int, Maybe a)-unfoldqual = undefined---- ------------------------------------------------------------------------ Substrings---- | /O(1)/ 'take' @n@, applied to a ByteString @xs@, returns the prefix--- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.--{-@ take :: n:Nat -> b:ByteString -> {v:ByteString | (bLength v) = (if (n <= (bLength b)) then n else (bLength b))} @-}-take :: Int -> ByteString -> ByteString-take n ps@(PS x s l)- | n <= 0 = empty- | n >= l = ps- | otherwise = PS x s n-{-# INLINE take #-}---- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@--- elements, or @[]@ if @n > 'length' xs@.--{-@ drop :: n:Nat -> b:ByteString -> {v:ByteString | (bLength v) = (if (n <= (bLength b)) then (bLength b) - n else 0)} @-}-drop :: Int -> ByteString -> ByteString-drop n ps@(PS x s l)- | n <= 0 = ps- | n >= l = empty- | otherwise = PS x (s+n) (l-n)-{-# INLINE drop #-}---- | /O(1)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.--{-@ splitAt :: n:Int- -> b:ByteString- -> ({v:ByteString | (Min (bLength v) (bLength b)- (if (n >= 0) then n else 0))}- , ByteString)<{\x y -> (bLength y) = ((bLength b) - (bLength x))}>- @-}-splitAt :: Int -> ByteString -> (ByteString, ByteString)-splitAt n ps@(PS x s l)- | n <= 0 = (empty, ps)- | n >= l = (ps, empty)- | otherwise = (PS x s n, PS x (s+n) (l-n))-{-# INLINE splitAt #-}---- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.--{-@ takeWhile :: (Word8 -> Bool) -> b:ByteString -> (ByteStringLE b) @-}-takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString-takeWhile f ps = unsafeTake (findIndexOrEnd (not . f) ps) ps-{-# INLINE takeWhile #-}---- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.-{-@ dropWhile :: (Word8 -> Bool) -> b:ByteString -> (ByteStringLE b) @-}-dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString-dropWhile f ps = unsafeDrop (findIndexOrEnd (not . f) ps) ps-{-# INLINE dropWhile #-}---- instead of findIndexOrEnd, we could use memchr here.---- | 'break' @p@ is equivalent to @'span' ('not' . p)@.-{-@ break :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-break p ps = case findIndexOrEnd p ps of n -> (unsafeTake n ps, unsafeDrop n ps)-#if __GLASGOW_HASKELL__ -{-# INLINE [1] break #-}--{-# RULES-"FPS specialise break (x==)" forall x.- break ((==) x) = breakByte x-"FPS specialise break (==x)" forall x.- break (==x) = breakByte x- #-}-#endif---- | 'breakByte' breaks its ByteString argument at the first occurence--- of the specified byte. It is more efficient than 'break' as it is--- implemented with @memchr(3)@. I.e.--- --- > break (=='c') "abcd" == breakByte 'c' "abcd"-----{-@ breakByte :: Word8 -> b:ByteString -> (ByteStringPair b) @-}-breakByte :: Word8 -> ByteString -> (ByteString, ByteString)-breakByte c p = case elemIndex c p of- Nothing -> (p,empty)- Just n -> (unsafeTake n p, unsafeDrop n p)-{-# INLINE breakByte #-}---- | 'breakEnd' behaves like 'break' but from the end of the 'ByteString'--- --- breakEnd p == spanEnd (not.p)--{-@ breakEnd :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-breakEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-breakEnd p ps = splitAt (findFromEndUntil p ps) ps---- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@-{-@ span :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-span p ps = break (not . p) ps-#if __GLASGOW_HASKELL__-{-# INLINE [1] span #-}-#endif---- | 'spanByte' breaks its ByteString argument at the first--- occurence of a byte other than its argument. It is more efficient--- than 'span (==)'------ > span (=='c') "abcd" == spanByte 'c' "abcd"----{-@ spanByte :: Word8 -> b:ByteString -> (ByteStringPair b) @-}-spanByte :: Word8 -> ByteString -> (ByteString, ByteString)-spanByte c ps@(PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->- go l (p `plusPtr` s) 0- where- STRICT3(go)- {- LIQUID WITNESS -}- go (d::Int) p i | i >= l = return (ps, empty)- | otherwise = do c' <- peekByteOff p i- if c /= c'- then return (unsafeTake i ps, unsafeDrop i ps)- else go (d-1) p (i+1)-{-# INLINE spanByte #-}--{-# RULES-"FPS specialise span (x==)" forall x.- span ((==) x) = spanByte x-"FPS specialise span (==x)" forall x.- span (==x) = spanByte x- #-}---- | 'spanEnd' behaves like 'span' but from the end of the 'ByteString'.--- We have------ > spanEnd (not.isSpace) "x y z" == ("x y ","z")------ and------ > spanEnd (not . isSpace) ps--- > == --- > let (x,y) = span (not.isSpace) (reverse ps) in (reverse y, reverse x) ----{-@ spanEnd :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-spanEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-spanEnd p ps = splitAt (findFromEndUntil (not . p) ps) ps---- | /O(n)/ Splits a 'ByteString' into components delimited by--- separators, where the predicate returns True for a separator element.--- The resulting components do not contain the separators. Two adjacent--- separators result in an empty component in the output. eg.------ > splitWith (=='a') "aabbaca" == ["","","bb","c",""]--- > splitWith (=='a') [] == []------ LIQUID: instead of NE, return [empty] in 0 case, or complicate spec.-{-@ splitWith :: (Word8 -> Bool) -> b:ByteStringNE -> (ByteStringSplit b) @-}-splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]--#if defined(__GLASGOW_HASKELL__)-splitWith _pred (PS _ _ 0) = []-splitWith pred_ (PS fp off len) = splitWith0 pred# off len fp 1- where pred# c# = pred_ (W8# c#)-- STRICT5(splitWith0)- {-@ decrease splitWith0 3 5 @-}- {- LIQUID WITNESS -}- splitWith0 pred' off' len' fp' (x::Int) = withPtr fp $ \p ->- splitLoop pred' p 0 off' len' fp' len' 0-- {-@ decrease splitLoop 7 8 @-}- splitLoop :: (Word# -> Bool)- -> Ptr Word8- -> Int -> Int -> Int- -> ForeignPtr Word8 -> Int -> Int- -> IO [ByteString]-- {- LIQUID WITNESS -}- splitLoop pred' p idx' off' len' fp' (d::Int) (x::Int)- | pred' `seq` p `seq` idx' `seq` off' `seq` len' `seq` fp' `seq` False = undefined- | idx' >= len' = return [PS fp' off' idx']- | otherwise = do- w <- peekElemOff p (off'+idx')- if pred' (case w of W8# w# -> w#)- then return (PS fp' off' idx' :- splitWith0 pred' (off'+idx'+1) (len'-idx'-1) fp' 1)- else splitLoop pred' p (idx'+1) off' len' fp' (d-1) 0-{-# INLINE splitWith #-}--#else-splitWith _ (PS _ _ 0) = []-splitWith p ps = loop p ps- where- STRICT2(loop)- loop q qs = if null rest then [chunk]- else chunk : loop q (unsafeTail rest)- where (chunk,rest) = break q qs-#endif---- | /O(n)/ Break a 'ByteString' into pieces separated by the byte--- argument, consuming the delimiter. I.e.------ > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]--- > split 'a' "aXaXaXa" == ["","X","X","X",""]--- > split 'x' "x" == ["",""]--- --- and------ > intercalate [c] . split c == id--- > split == splitWith . (==)--- --- As for all splitting functions in this library, this function does--- not copy the substrings, it just constructs new 'ByteStrings' that--- are slices of the original.----{-@ split :: Word8 -> b:ByteStringNE -> (ByteStringSplit b) @-}-split :: Word8 -> ByteString -> [ByteString]-split _ (PS _ _ 0) = []-split w (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let ptr = p `plusPtr` s-- STRICT2(loop)- {- LIQUID WITNESS -}- loop (d::Int) n =- -- LIQUID: else lose `plen` info due to subsequent @ Word8 application- let ptrn = (ptr `plusPtr` n) :: Ptr Word8 - q = inlinePerformIO $ memchr ptrn {- (ptr `plusPtr` n) -}- w (fromIntegral (l-n))- in if isNullPtr q {- LIQUID q == nullPtr -}- then [PS x (s+n) (l-n)]- else let i = q `minusPtr` ptr in PS x (s+n) (i-n) : loop (l - (i+1)) (i+1)-- return (loop l 0)-{-# INLINE split #-}---- -- A longer split out version of the above with explicit type--- -- annotations...--- {- splitO :: Word8 -> b:ByteStringNE -> (ByteStringSplit b) @-}--- splitO _ (PS _ _ 0) = []--- splitO w (PS xanadu s l) = inlinePerformIO $ withForeignPtr xanadu $ \pz -> do--- let p = liquidAssert (fpLen xanadu == pLen pz) pz--- let ptrGOBBLE_ = p `plusPtr` s--- let ptrGOBBLE = liquidAssert (l <= pLen ptrGOBBLE_) ptrGOBBLE_ --- return (splitLoop xanadu ptrGOBBLE w l s 0)---- {- splitLoop :: fp:(ForeignPtr Word8)--- -> p:(Ptr Word8) --- -> Word8 --- -> l:{v:Nat | v <= (plen p)} --- -> s:{v:Nat | v + l <= (fplen fp)}--- -> n:{v:Nat | v <= l} --- -> {v:[ByteString] | (bLengths v) + (len v) - 1 = l - n} --- @-}--- splitLoop :: ForeignPtr Word8 -> Ptr Word8 -> Word8 -> Int -> Int -> Int -> [ByteString]--- splitLoop xanadu ptrGOBBLE w l s n = --- let ptrn = ((ptrGOBBLE `plusPtr` n) :: Ptr Word8) --- -- NEEDED: else lose `plen` information without cast--- -- thanks to subsequent @ Word8 application--- q = inlinePerformIO $ memchr ptrn w (fromIntegral (l-n))--- in if isNullPtr q {- LIQUID q == nullPtr -}--- then [PS xanadu (s+n) (l-n)]--- else let i' = q `minusPtr` ptrGOBBLE--- i = liquidAssert (n <= i' && i' < l) i'--- in PS xanadu (s+n) (i-n) : splitLoop xanadu ptrGOBBLE w l s (i+1)---{---- slower. but stays inside Haskell.-split _ (PS _ _ 0) = []-split (W8# w#) (PS fp off len) = splitWith' off len fp- where- splitWith' off' len' fp' = withPtr fp $ \p ->- splitLoop p 0 off' len' fp'-- splitLoop :: Ptr Word8- -> Int -> Int -> Int- -> ForeignPtr Word8- -> IO [ByteString]-- STRICT5(splitLoop)- splitLoop p idx' off' len' fp'- | p `seq` idx' `seq` off' `seq` len' `seq` fp' `seq` False = undefined- | idx' >= len' = return [PS fp' off' idx']- | otherwise = do- (W8# x#) <- peekElemOff p (off'+idx')- if word2Int# w# ==# word2Int# x#- then return (PS fp' off' idx' :- splitWith' (off'+idx'+1) (len'-idx'-1) fp')- else splitLoop p (idx'+1) off' len' fp'--}--{---- | Like 'splitWith', except that sequences of adjacent separators are--- treated as a single separator. eg.--- --- > tokens (=='a') "aabbaca" == ["bb","c"]----tokens :: (Word8 -> Bool) -> ByteString -> [ByteString]-tokens f = P.filter (not.null) . splitWith f-{-# INLINE tokens #-}--}---- | The 'group' function takes a ByteString and returns a list of--- ByteStrings such that the concatenation of the result is equal to the--- argument. Moreover, each sublist in the result contains only equal--- elements. For example,------ > group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]------ It is a special case of 'groupBy', which allows the programmer to--- supply their own equality test. It is about 40% faster than --- /groupBy (==)/-{-@ group :: b:ByteString -> {v: [ByteStringNE] | (bLengths v) = (bLength b)} @-}-group :: ByteString -> [ByteString]-group xs- | null xs = []- | otherwise = let y = unsafeHead xs- (ys, zs) = spanByte (unsafeHead xs) (unsafeTail xs)- in (y `cons` ys) : group zs- -- LIQUID FIXME: a better spec for spanByte would say that if x- -- occurs at the head of xs, then `spanByte x xs` will return a- -- non-empty bytestring- -- LIQUID where- -- LIQUID (ys, zs) = spanByte (unsafeHead xs) xs----- | The 'groupBy' function is the non-overloaded version of 'group'.-{-@ groupBy :: (Word8 -> Word8 -> Bool) -> b:ByteString -> {v:[ByteStringNE] | (bLengths v) = (bLength b)} @-}-groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]-groupBy k xs- | null xs = []- | otherwise = let n = 1 + findIndexOrEnd (not . k (unsafeHead xs)) (unsafeTail xs) in- unsafeTake n xs : groupBy k (unsafeDrop n xs)- -- LIQUID LAZY: where- -- LIQUID LAZY: n = 1 + findIndexOrEnd (not . k (unsafeHead xs)) (unsafeTail xs)---- | /O(n)/ The 'intercalate' function takes a 'ByteString' and a list of--- 'ByteString's and concatenates the list after interspersing the first--- argument between each element of the list.--- LIQUID FAIL: NonLinear Invariant. --- LIQUID {- intercalate :: b:ByteString --- LIQUID -> bs:[ByteString] --- LIQUID -> {v:ByteString | (bLength v) = (bLengths bs) + ((len bs) - 1) * (bLength b)} -}--- LIQUID: If we INLINE intersperse then can show simpler--- LIQUID {- intersperse :: ByteString -> bs:[ByteString] -> {v:ByteString | (bLengths bs) <= (bLength v)}-intercalate :: ByteString -> [ByteString] -> ByteString-intercalate s = concat . (List.intersperse s)-{-# INLINE [1] intercalate #-}--join :: ByteString -> [ByteString] -> ByteString-join = intercalate-{-# DEPRECATED join "use intercalate" #-}--{-# RULES-"FPS specialise intercalate c -> intercalateByte" forall c s1 s2 .- intercalate (singleton c) (s1 : s2 : []) = intercalateWithByte c s1 s2- #-}---- | /O(n)/ intercalateWithByte. An efficient way to join to two ByteStrings--- with a char. Around 4 times faster than the generalised join.-----{-@ intercalateWithByte :: Word8 -> f:ByteString -> g:ByteString -> {v:ByteString | (bLength v) = (bLength f) + (bLength g) + 1} @-}-intercalateWithByte :: Word8 -> ByteString -> ByteString -> ByteString-intercalateWithByte c f@(PS ffp s l) g@(PS fgp t m) = unsafeCreate len $ \ptr ->- withForeignPtr ffp $ \fp ->- withForeignPtr fgp $ \gp -> do- memcpy ptr (fp `plusPtr` s) (fromIntegral l)- poke (ptr `plusPtr` l) c- memcpy (ptr `plusPtr` (l + 1)) (gp `plusPtr` t) (fromIntegral m)- where- len = length f + length g + 1-{-# INLINE intercalateWithByte #-}---- ------------------------------------------------------------------------ Indexing ByteStrings---- | /O(1)/ 'ByteString' index (subscript) operator, starting from 0.-{-@ index :: b:ByteString -> {v:Nat | v < (bLength b)} -> Word8 @-}-index :: ByteString -> Int -> Word8-index ps n- | n < 0 = moduleError "index" ("negative index: " ++ show n)- | n >= length ps = moduleError "index" ("index too large: " ++ show n- ++ ", length = " ++ show (length ps))- | otherwise = ps `unsafeIndex` n-{-# INLINE index #-}----- | /O(n)/ The 'elemIndex' function returns the index of the first--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. --- This implementation uses memchr(3).--{-@ elemIndex :: Word8 -> b:ByteString -> Maybe {v:Nat | v < (bLength b)} @-}-elemIndex :: Word8 -> ByteString -> Maybe Int-elemIndex c (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let p' = p `plusPtr` s- q <- memchr p' c (fromIntegral l)- return $! if isNullPtr q {- LIQUID: q == nullPtr -} then Nothing else Just $! q `minusPtr` p'-{-# INLINE elemIndex #-}---- | /O(n)/ The 'elemIndexEnd' function returns the last index of the--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. The following--- holds:------ > elemIndexEnd c xs == --- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)----{-@ elemIndexEnd :: Word8 -> b:ByteString -> Maybe {v:Nat | v < (bLength b) } @-}-elemIndexEnd :: Word8 -> ByteString -> Maybe Int-elemIndexEnd ch (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->- go l (p `plusPtr` s) (l-1)- where- STRICT3(go)- {- LIQUID WITNESS -}- go (d::Int) p i- | i < 0 = return Nothing- | otherwise = do ch' <- peekByteOff p i- if ch == ch'- then return $ Just i- else go (d-1) p (i-1)-{-# INLINE elemIndexEnd #-}---- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning--- the indices of all elements equal to the query element, in ascending order.--- This implementation uses memchr(3).-{-@ elemIndices :: Word8 -> b:ByteString -> [{v:Nat | v < (bLength b) }] @-}-elemIndices :: Word8 -> ByteString -> [Int]-elemIndices w (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let ptr = p `plusPtr` s-- STRICT2(loop)- {- LIQUID WITNESS -}- loop (d::Int) n- = let pn = ((ptr `plusPtr` n) :: Ptr Word8)- q = inlinePerformIO $ memchr pn- w (fromIntegral (l - n))- in if isNullPtr q {- == nullPtr -}- then []- else let i = q `minusPtr` ptr- in i : loop (l - (i+1)) (i+1)- return $! loop l 0-{-# INLINE elemIndices #-}--{---- much slower-elemIndices :: Word8 -> ByteString -> [Int]-elemIndices c ps = loop 0 ps- where STRICT2(loop)- loop _ ps' | null ps' = []- loop n ps' | c == unsafeHead ps' = n : loop (n+1) (unsafeTail ps')- | otherwise = loop (n+1) (unsafeTail ps')--}---- | count returns the number of times its argument appears in the ByteString------ > count = length . elemIndices------ But more efficiently than using length on the intermediate list.-{-@ count :: Word8 -> b:ByteString -> {v:Nat | v <= (bLength b) } @-}-count :: Word8 -> ByteString -> Int-count w (PS x s m) = inlinePerformIO $ withForeignPtr x $ \p ->- fmap fromIntegral $ c_count (p `plusPtr` s) (fromIntegral m) w-{-# INLINE count #-}--{------- around 30% slower----count w (PS x s m) = inlinePerformIO $ withForeignPtr x $ \p ->- go (p `plusPtr` s) (fromIntegral m) 0- where- go :: Ptr Word8 -> CSize -> Int -> IO Int- STRICT3(go)- go p l i = do- q <- memchr p w l- if q == nullPtr- then return i- else do let k = fromIntegral $ q `minusPtr` p- go (q `plusPtr` 1) (l-k-1) (i+1)--}---- | The 'findIndex' function takes a predicate and a 'ByteString' and--- returns the index of the first element in the ByteString--- satisfying the predicate.-{-@ findIndex :: (Word8 -> Bool) -> b:ByteString -> (Maybe {v:Nat | v < (bLength b)}) @-}-findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int-findIndex k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go l (f `plusPtr` s) 0- where- STRICT3(go)- {- LIQUID WITNESS -}- go (d::Int) ptr n- | n >= l = return Nothing- | otherwise = do w <- peek ptr- if k w- then return (Just n)- else go (d-1) (ptr `plusPtr` 1) (n+1)-{-# INLINE findIndex #-}---- | The 'findIndices' function extends 'findIndex', by returning the--- indices of all elements satisfying the predicate, in ascending order.-{-@ qualif FindIndices(v:ByteString,- p:ByteString,- n:Int):- (bLength v) = (bLength p) - n @-}-{-@ findIndices :: (Word8 -> Bool) -> b:ByteString -> [{v:Nat | v < (bLength b)}] @-}-findIndices :: (Word8 -> Bool) -> ByteString -> [Int]-findIndices p ps = loop 0 ps- where- {-@ decrease loop 2 @-}- STRICT2(loop)- loop (n :: Int) qs -- LIQUID CAST- | null qs = []- | p (unsafeHead qs) = n : loop (n+1) (unsafeTail qs)- | otherwise = loop (n+1) (unsafeTail qs)---- ------------------------------------------------------------------------ Searching ByteStrings---- | /O(n)/ 'elem' is the 'ByteString' membership predicate.-elem :: Word8 -> ByteString -> Bool-elem c ps = case elemIndex c ps of Nothing -> False ; _ -> True-{-# INLINE elem #-}---- | /O(n)/ 'notElem' is the inverse of 'elem'-notElem :: Word8 -> ByteString -> Bool-notElem c ps = not (elem c ps)-{-# INLINE notElem #-}---- | /O(n)/ 'filter', applied to a predicate and a ByteString,--- returns a ByteString containing those characters that satisfy the--- predicate. This function is subject to array fusion.-{-@ qualif FilterDecr(v:Ptr a, f:Ptr a, d:Int):- (plen v) >= (plen f) - d @-}-{-@ qualif FilterLoop(v:Ptr a, f:Ptr a, t:Ptr a):- (plen t) >= (plen f) - (plen v) @-}-{-@ filter :: (Word8 -> Bool) -> b:ByteString -> (ByteStringLE b) @-}-filter :: (Word8 -> Bool) -> ByteString -> ByteString-filter k ps@(PS x s l)- | null ps = ps- | otherwise = unsafePerformIO $ createAndTrim l $ \p -> withForeignPtr x $ \f -> do- t <- go l (f `plusPtr` s) p (f `plusPtr` (s + l))- return $! t `minusPtr` p -- actual length- where- STRICT4(go)- {- LIQUID WITNESS -}- go (d::Int) f' t end -- LIQUID TERMINATION- | f' == end = return t- | otherwise = do- let f = liquid_thm_ptr_cmp f' end- w <- peek f- if k w- then poke t w >> go (d-1) (f `plusPtr` 1) (t `plusPtr` 1) end- else go (d-1) (f `plusPtr` 1) t end-#if __GLASGOW_HASKELL__-{-# INLINE [1] filter #-}-#endif----- | /O(n)/ A first order equivalent of /filter . (==)/, for the common--- case of filtering a single byte. It is more efficient to use--- /filterByte/ in this case.------ > filterByte == filter . (==)------ filterByte is around 10x faster, and uses much less space, than its--- filter equivalent----{-@ filterByte :: Word8 -> b:ByteString -> {v:ByteString | (bLength v) <= (bLength b)} @-}-filterByte :: Word8 -> ByteString -> ByteString-filterByte w ps = replicate (count w ps) w-{-# INLINE filterByte #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter ((==) x) = filterByte x- #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter (== x) = filterByte x- #-}---- | /O(n)/ The 'find' function takes a predicate and a ByteString,--- and returns the first element in matching the predicate, or 'Nothing'--- if there is no such element.------ > find f p = case findIndex f p of Just n -> Just (p ! n) ; _ -> Nothing----find :: (Word8 -> Bool) -> ByteString -> Maybe Word8-find f p = case findIndex f p of- Just n -> Just (p `unsafeIndex` n)- _ -> Nothing-{-# INLINE find #-}--{------- fuseable, but we don't want to walk the whole array.--- -find k = foldl findEFL Nothing- where findEFL a@(Just _) _ = a- findEFL _ c | k c = Just c- | otherwise = Nothing--}---- | /O(n)/ The 'partition' function takes a predicate a ByteString and returns--- the pair of ByteStrings with elements which do and do not satisfy the--- predicate, respectively; i.e.,------ > partition p bs == (filter p xs, filter (not . p) xs)------ LIQUID FAIL: partition :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b)-{-@ partition :: (Word8 -> Bool) -> b:ByteString -> ((ByteStringLE b), (ByteStringLE b)) @-}-partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-partition p bs = (filter p bs, filter (not . p) bs)---TODO: use a better implementation---- ------------------------------------------------------------------------ Searching for substrings---- | /O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'--- iff the first is a prefix of the second.-{-@ isPrefixOf :: ByteString -> ByteString -> Bool @-}-isPrefixOf :: ByteString -> ByteString -> Bool-isPrefixOf (PS x1 s1 l1) (PS x2 s2 l2)- | l1 == 0 = True- | l2 < l1 = False- | otherwise = inlinePerformIO $ withForeignPtr x1 $ \p1 ->- withForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral l1)- return $! i == 0---- | /O(n)/ The 'isSuffixOf' function takes two ByteStrings and returns 'True'--- iff the first is a suffix of the second.--- --- The following holds:------ > isSuffixOf x y == reverse x `isPrefixOf` reverse y------ However, the real implemenation uses memcmp to compare the end of the--- string only, with no reverse required..-{-@ isSuffixOf :: ByteString -> ByteString -> Bool @-}-isSuffixOf :: ByteString -> ByteString -> Bool-isSuffixOf (PS x1 s1 l1) (PS x2 s2 l2)- | l1 == 0 = True- | l2 < l1 = False- | otherwise = inlinePerformIO $ withForeignPtr x1 $ \p1 ->- withForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2 `plusPtr` (l2 - l1)) (fromIntegral l1)- return $! i == 0---- | Alias of 'isSubstringOf'-isInfixOf :: ByteString -> ByteString -> Bool-isInfixOf = isSubstringOf---- | Check whether one string is a substring of another. @isSubstringOf--- p s@ is equivalent to @not (null (findSubstrings p s))@.-isSubstringOf :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to search in.- -> Bool-isSubstringOf p s = not $ P.null $ findSubstrings p s--{-# DEPRECATED findSubstring "Do not use. The ByteString searching api is about to be replaced." #-}--- | Get the first index of a substring in another string,--- or 'Nothing' if the string is not found.--- @findSubstring p s@ is equivalent to @listToMaybe (findSubstrings p s)@.-{-@ findSubstring :: pat:ByteString -> str:ByteString -> (Maybe {v:Nat | v <= (bLength str)}) @-}-findSubstring :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to seach in.- -> Maybe Int--- LIQUID ETA: findSubstring = (listToMaybe .) . findSubstrings-findSubstring pat str = listToMaybe $ findSubstrings pat str---{-# DEPRECATED findSubstrings "Do not use. The ByteString searching api is about to be replaced." #-}--- | Find the indexes of all (possibly overlapping) occurances of a--- substring in a string. This function uses the Knuth-Morris-Pratt--- string matching algorithm.--{-@ findSubstrings :: pat:ByteString -> str:ByteString -> [{v:Nat | v <= (bLength str)}] @-}--findSubstrings :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to seach in.- -> [Int]---- LIQUID LATEST -findSubstrings pat str- | null pat = rng 0 (length str - 1) -- LIQUID COMPREHENSIONS [0 .. (length str - 1)]- | otherwise = search 0 str- where- {-@ decrease search 2 @-}- STRICT2(search)- search (n :: Int) s- | null s = []- | pat `isPrefixOf` s = n : search (n+1) (unsafeTail s)- | otherwise = search (n+1) (unsafeTail s)---{- -findSubstrings pat@(PS _ _ m) str@(PS _ _ n) = search 0 0- where- patc x = pat `unsafeIndex` x- strc x = str `unsafeIndex` x-- -- maybe we should make kmpNext a UArray before using it in search?- kmpNext = listArray (0,m) (-1:kmpNextL pat (-1))- kmpNextL p _ | null p = []- kmpNextL p j = let j' = next (unsafeHead p) j + 1- ps = unsafeTail p- x = if not (null ps) && unsafeHead ps == patc j'- then kmpNext Array.! j' else j'- in x:kmpNextL ps j'- search i j = match ++ rest -- i: position in string, j: position in pattern- where match = if j == m then [(i - j)] else []- rest = if i == n then [] else search (i+1) (next (strc i) j + 1)- next c j | j >= 0 && (j == m || c /= patc j) = next c (kmpNext Array.! j)- | otherwise = j--}---- LIQUID: added to latest API-{-@ breakSubstring :: ByteString -> b:ByteString -> (ByteStringPair b) @-}--breakSubstring :: ByteString -- ^ String to search for- -> ByteString -- ^ String to search in- -> (ByteString,ByteString) -- ^ Head and tail of string broken at substring--breakSubstring pat src = search 0 src- where- {-@ decrease search 2 @-}- STRICT2(search)- search n s- | null s = (src, empty) -- not found- | pat `isPrefixOf` s = (take n src,s)- | otherwise = search (n+1) (unsafeTail s)------ ------------------------------------------------------------------------ Zipping---- | /O(n)/ 'zip' takes two ByteStrings and returns a list of--- corresponding pairs of bytes. If one input ByteString is short,--- excess elements of the longer ByteString are discarded. This is--- equivalent to a pair of 'unpack' operations.--{-@ predicate ZipLen V X Y = (len V) = (if (bLength X) <= (bLength Y) then (bLength X) else (bLength Y)) @-}-{-@ zip :: x:ByteString -> y:ByteString -> {v:[(Word8, Word8)] | (ZipLen v x y) } @-}-zip :: ByteString -> ByteString -> [(Word8,Word8)]-zip ps qs- | null ps || null qs = []- | otherwise = (unsafeHead ps, unsafeHead qs) : zip (unsafeTail ps) (unsafeTail qs)---- | 'zipWith' generalises 'zip' by zipping with the function given as--- the first argument, instead of a tupling function. For example,--- @'zipWith' (+)@ is applied to two ByteStrings to produce the list of--- corresponding sums. -{-@ zipWith :: (Word8 -> Word8 -> a) -> x:ByteString -> y:ByteString -> {v:[a] | (ZipLen v x y)} @-}-zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]-zipWith f ps qs- | null ps || null qs = []- | otherwise = f (unsafeHead ps) (unsafeHead qs) : zipWith f (unsafeTail ps) (unsafeTail qs)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] zipWith #-}-#endif----- | A specialised version of zipWith for the common case of a--- simultaneous map over two bytestrings, to build a 3rd. Rewrite rules--- are used to automatically covert zipWith into zipWith' when a pack is--- performed on the result of zipWith, but we also export it for--- convenience.---- LIQUID NICE-INFERENCE-EXAMPLE! -{-@ predicate ZipLenB V X Y = (bLength V) = (if (bLength X) <= (bLength Y) then (bLength X) else (bLength Y)) @-}-{-@ zipWith' :: (Word8 -> Word8 -> Word8) -> x:ByteString -> y:ByteString -> {v:ByteString | (ZipLenB v x y)} @-}-zipWith' :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString-zipWith' f (PS fp s l) (PS fq t m) = inlinePerformIO $- withForeignPtr fp $ \a ->- withForeignPtr fq $ \b ->- create len $ zipWith_ len 0 (a `plusPtr` s) (b `plusPtr` t)- where- zipWith_ :: Int -> Int -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> IO ()- STRICT5(zipWith_)- {- LIQUID WITNESS -}- zipWith_ (d::Int) n p1 p2 r -- LIQUID TERMINATION- | n >= len = return ()- | otherwise = do- x <- peekByteOff p1 n- y <- peekByteOff p2 n- pokeByteOff r n (f x y)- zipWith_ (d-1) (n+1) p1 p2 r-- len = min l m-{-# INLINE zipWith' #-}--{-# RULES--"FPS specialise zipWith" forall (f :: Word8 -> Word8 -> Word8) p q .- zipWith f p q = unpack (zipWith' f p q)-- #-}---- | /O(n)/ 'unzip' transforms a list of pairs of bytes into a pair of--- ByteStrings. Note that this performs two 'pack' operations.-{-@ unzip :: z:[(Word8,Word8)] -> ({v:ByteString | (bLength v) = (len z)}, {v:ByteString | (bLength v) = (len z) }) @-}-unzip :: [(Word8,Word8)] -> (ByteString,ByteString)-unzip ls = (pack (P.map fst ls), pack (P.map snd ls))-{-# INLINE unzip #-}- --- ------------------------------------------------------------------------ Special lists---- | /O(n)/ Return all initial segments of the given 'ByteString', shortest first.-{-@ inits :: b:ByteString -> [{v1:ByteString | (bLength v1) <= (bLength b)}]<{\ix iy -> (bLength ix) < (bLength iy)}> @-}-inits :: ByteString -> [ByteString]---LIQUID INLINE inits (PS x s l) = [PS x s n | n <- [0..l]]-inits (PS x s l) = PS x s 0 : go 0 (rng 1 l)- {-@ decrease go 2 @-}- where go _ [] = []- go n0 (n:ns) = PS x s n : go n ns---LIQUID rng a b | a > b = []---LIQUID | otherwise = a : rng (a+1) b--{-@ qualif RangeDecr(v:Int,x:Int, y:Int): v = 1 + x - y @-}-rng :: Int -> Int -> [Int]-rng lo hi = go (1 + hi - lo) lo- where- {- LIQUID WITNESS -}- go (d::Int) i- | i > hi = []- | otherwise = i : go (d-1) (i+1)----- | /O(n)/ Return all final segments of the given 'ByteString', longest first.-{- tails :: b:ByteString -> {v:[{v1:ByteString | (bLength v1) <= (bLength b)}] | (len v) = 1 + (bLength b)} @-}-tails :: ByteString -> [ByteString]-tails p | null p = [empty]- | otherwise = p : tails (unsafeTail p)---- less efficent spacewise: tails (PS x s l) = [PS x (s+n) (l-n) | n <- [0..l]]----- ------------------------------------------------------------------------ ** Ordered 'ByteString's---- | /O(n)/ Sort a ByteString efficiently, using counting sort.--- LIQUID FAIL: requires invariant that SUM of cells in intermediate array--- equals total len of outer array. WHOA. Due to Ptr issue, this gets--- "proved" safe. Oh boy. Still, can prove that output size = input size.----LIQUID sortCanary :: Int -> Int---LIQUID sortCanary x = liquidAssert (0 == 1) x--sort :: ByteString -> ByteString-sort (PS input s l) = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do-- memset (castPtr arr) 0 (256 * fromIntegral (sizeOf (undefined :: CSize)))- withForeignPtr input (\x -> countOccurrences arr (x `plusPtr` s) l)-- let STRICT2(go)- go 256 _ = return ()- go i ptr = do n <- peekElemOff arr i- when (n /= 0) $ memset ptr (fromIntegral i) n >> return ()- go (i + 1) (ptr `plusPtr` (fromIntegral n))- go 0 p- where- -- | Count the number of occurrences of each byte.- -- Used by 'sort'- --- countOccurrences :: Ptr CSize -> Ptr Word8 -> Int -> IO ()- STRICT3(countOccurrences)- countOccurrences counts str len = go 0- where- STRICT1(go)- go i | i == len = return ()- | otherwise = do k <- fromIntegral `fmap` peekElemOff str i- x <- peekElemOff counts k- pokeElemOff counts k (x + 1)- go (i + 1)--{--sort :: ByteString -> ByteString-sort (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f -> do- memcpy p (f `plusPtr` s) l- c_qsort p l -- inplace--}---- The 'sortBy' function is the non-overloaded version of 'sort'.------ Try some linear sorts: radix, counting--- Or mergesort.------ sortBy :: (Word8 -> Word8 -> Ordering) -> ByteString -> ByteString--- sortBy f ps = undefined---- ------------------------------------------------------------------------ Low level constructors---- | /O(n) construction/ Use a @ByteString@ with a function requiring a--- null-terminated @CString@. The @CString@ will be freed--- automatically. This is a memcpy(3).-{-@ useAsCString :: p:ByteString -> ({v:CString | (bLength p) + 1 = (plen v)} -> IO a) -> IO a @-}-useAsCString :: ByteString -> (CString -> IO a) -> IO a-useAsCString (PS fp o l) action = do- allocaBytes (l+1) $ \buf ->- withForeignPtr fp $ \p -> do- memcpy buf (p `plusPtr` o) (fromIntegral l)- pokeByteOff buf l (0::Word8)- action (castPtr buf)---- | /O(n) construction/ Use a @ByteString@ with a function requiring a @CStringLen@.--- As for @useAsCString@ this function makes a copy of the original @ByteString@.-{-@ useAsCStringLen :: b:ByteString -> ({v:CStringLen | (cStringLen v) = (bLength b)} -> IO a) -> IO a @-}-useAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a-useAsCStringLen p@(PS _ _ l) f = useAsCString p $ \cstr -> f (cstr,l)------------------------------------------------------------------------------ | /O(n)./ Construct a new @ByteString@ from a @CString@. The--- resulting @ByteString@ is an immutable copy of the original--- @CString@, and is managed on the Haskell heap. The original--- @CString@ must be null terminated.--{-@ packCString :: c:CString -> IO {v:ByteString | (bLength v) = (plen c)} @-}-packCString :: CString -> IO ByteString-packCString cstr = do- len <- c_strlen cstr- packCStringLen (cstr, fromIntegral len)---- | /O(n)./ Construct a new @ByteString@ from a @CStringLen@. The--- resulting @ByteString@ is an immutable copy of the original @CStringLen@.--- The @ByteString@ is a normal Haskell value and will be managed on the--- Haskell heap.-{-@ packCStringLen :: c:CStringLen -> (IO {v:ByteString | (bLength v) = (cStringLen c)}) @-}-packCStringLen :: CStringLen -> IO ByteString-packCStringLen (cstr, len) = create len $ \p ->- memcpy p (castPtr cstr) (fromIntegral len)------------------------------------------------------------------------------ | /O(n)/ Make a copy of the 'ByteString' with its own storage. --- This is mainly useful to allow the rest of the data pointed--- to by the 'ByteString' to be garbage collected, for example--- if a large string has been read in, and only a small part of it --- is needed in the rest of the program.--- -{-@ copy :: b:ByteString -> (ByteStringSZ b) @-}-copy :: ByteString -> ByteString-copy (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->- memcpy p (f `plusPtr` s) (fromIntegral l)---- ------------------------------------------------------------------------ line IO---- | Read a line from stdin.-getLine :: IO ByteString-getLine = hGetLine stdin--{---- | Lazily construct a list of lines of ByteStrings. This will be much--- better on memory consumption than using 'hGetContents >>= lines'--- If you're considering this, a better choice might be to use--- Data.ByteString.Lazy-hGetLines :: Handle -> IO [ByteString]-hGetLines h = go- where- go = unsafeInterleaveIO $ do- e <- hIsEOF h- if e- then return []- else do- x <- hGetLine h- xs <- go- return (x:xs)--}---- | Read a line from a handle--hGetLine :: Handle -> IO ByteString-#if !defined(__GLASGOW_HASKELL__)-hGetLine h = System.IO.hGetLine h >>= return . pack . P.map c2w-#else-hGetLine h = wantReadableHandleLIQUID "Data.ByteString.hGetLine" h $ \ handle_ -> do- case haBufferMode handle_ of- NoBuffering -> error "no buffering"- _other -> hGetLineBuffered handle_-- where- hGetLineBuffered handle_ = do- let ref = haCharBuffer handle_- buf <- readIORef ref- hGetLineBufferedLoop handle_ ref buf 0 []-- hGetLineBufferedLoop handle_ ref- buf@Buffer{ bufL=r, bufR=w, bufRaw=raw } len xss =- len `seq` do- off <- findEOL r w raw- let new_len = len + off - r- xs <- mkPS raw r off-- -- if eol == True, then off is the offset of the '\n'- -- otherwise off == w and the buffer is now empty.- if off /= w- then do if (w == off + 1)- then writeIORef ref buf{ bufL=0, bufR=0 }- else writeIORef ref buf{ bufL = off + 1 }- mkBigPS new_len (xs:xss)- else do- maybe_buf <- maybeFillReadBuffer ({- LIQUID COMPAT: haFD -} handle_) True ({- LIQUID COMPAT: haIsStream -} handle_)- buf{ bufR=0, bufL=0 }- case maybe_buf of- -- Nothing indicates we caught an EOF, and we may have a- -- partial line to return.- Nothing -> do- writeIORef ref buf{ bufL=0, bufR=0 }- if new_len > 0- then mkBigPS new_len (xs:xss)- else error "LIQUIDCOMPAT" -- ioe_EOF- Just new_buf ->- hGetLineBufferedLoop handle_ ref new_buf new_len (xs:xss)-- -- find the end-of-line character, if there is one- findEOL r w raw- | r == w = return w- | otherwise = do- (c,r') <- readCharFromBuffer raw r- if c == '\n'- then return r -- NB. not r': don't include the '\n'- else findEOL r' w raw-- -- LIQUID COMPAT- maybeFillReadBuffer fd is_line is_stream buf = return Nothing- -- maybeFillReadBuffer fd is_line is_stream buf = catch- -- (do buf' <- fillReadBuffer fd is_line is_stream buf- -- return (Just buf'))- -- (\e -> if isEOFError e then return Nothing else ioError e)---- TODO, rewrite to use normal memcpy-mkPS :: RawBuffer Char -> Int -> Int -> IO ByteString-mkPS buf start end =- let len = end - start- in create len $ \p -> do- memcpy_ptr_baoff p buf (fromIntegral start) ({- LIQUID fromIntegral-} intCSize len)- return ()----mkBigPS :: Int -> [ByteString] -> IO ByteString-mkBigPS _ [ps] = return ps-mkBigPS _ pss = return $! concat (P.reverse pss)--#endif---- ------------------------------------------------------------------------ Block IO---- | Outputs a 'ByteString' to the specified 'Handle'.-hPut :: Handle -> ByteString -> IO ()-hPut _ (PS _ _ 0) = return ()-hPut h (PS ps s l) = withForeignPtr ps $ \p-> hPutBuf h (p `plusPtr` s) l---- | A synonym for @hPut@, for compatibility -hPutStr :: Handle -> ByteString -> IO ()-hPutStr = hPut---- | Write a ByteString to a handle, appending a newline byte-hPutStrLn :: Handle -> ByteString -> IO ()-hPutStrLn h ps- | length ps < 1024 = hPut h (ps `snoc` 0x0a)- | otherwise = hPut h ps >> hPut h (singleton (0x0a)) -- don't copy---- | Write a ByteString to stdout-putStr :: ByteString -> IO ()-putStr = hPut stdout---- | Write a ByteString to stdout, appending a newline byte-putStrLn :: ByteString -> IO ()-putStrLn = hPutStrLn stdout---- | Read a 'ByteString' directly from the specified 'Handle'. This--- is far more efficient than reading the characters into a 'String'--- and then using 'pack'.-{-@ hGet :: Handle -> n:Nat -> IO {v:ByteString | (bLength v) <= n} @-}-hGet :: Handle -> Int -> IO ByteString-hGet _ 0 = return empty-hGet h i = createAndTrim i $ \p -> hGetBuf h p i---- | hGetNonBlocking is identical to 'hGet', except that it will never block--- waiting for data to become available, instead it returns only whatever data--- is available.---{-@ hGetNonBlocking :: Handle -> n:Nat -> IO {v:ByteString | (bLength v) <= n} @-}---hGetNonBlocking :: Handle -> Int -> IO ByteString-#if defined(__GLASGOW_HASKELL__)-hGetNonBlocking _ 0 = return empty-hGetNonBlocking h i = createAndTrim i $ \p -> hGetBufNonBlocking h p i-#else-hGetNonBlocking = hGet-#endif---- | Read entire handle contents into a 'ByteString'.--- This function reads chunks at a time, doubling the chunksize on each--- read. The final buffer is then realloced to the appropriate size. For--- files > half of available memory, this may lead to memory exhaustion.--- Consider using 'readFile' in this case.------ As with 'hGet', the string representation in the file is assumed to--- be ISO-8859-1.--{-@ assume Foreign.Marshal.Alloc.reallocBytes :: p:(Ptr a) -> n:Nat -> (IO (PtrN a n)) @-}-{-@ lazy hGetContents @-}-hGetContents :: Handle -> IO ByteString-hGetContents h = do- let start_size = 1024- p <- mallocBytes start_size- i <- hGetBuf h p start_size- if i < start_size- then do p' <- reallocBytes p i- fp <- newForeignPtr finalizerFree p'- return $! PS fp 0 i- else f p start_size- where- f p s = do- let s' = s + s -- 2 * s -- LIQUID MULTIPLY- p' <- reallocBytes p s'- i <- hGetBuf h (p' `plusPtr` s) s- if i < s- then do let i' = s + i- p'' <- reallocBytes p' i'- fp <- newForeignPtr finalizerFree p''- return $! PS fp 0 i'- else f p' s'---- | getContents. Equivalent to hGetContents stdin-getContents :: IO ByteString-getContents = hGetContents stdin---- | The interact function takes a function of type @ByteString -> ByteString@--- as its argument. The entire input from the standard input device is passed--- to this function as its argument, and the resulting string is output on the--- standard output device. It's great for writing one line programs!-interact :: (ByteString -> ByteString) -> IO ()-interact transformer = putStr . transformer =<< getContents---- | Read an entire file strictly into a 'ByteString'. This is far more--- efficient than reading the characters into a 'String' and then using--- 'pack'. It also may be more efficient than opening the file and--- reading it using hGet. Files are read using 'binary mode' on Windows,--- for 'text mode' use the Char8 version of this function.-readFile :: FilePath -> IO ByteString-readFile f = bracket (openBinaryFile f ReadMode) hClose- (\h -> hFileSize h >>= hGet h . fromIntegral)---- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\h -> hPut h txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\h -> hPut h txt)--{------- Disable until we can move it into a portable .hsc file------- | Like readFile, this reads an entire file directly into a--- 'ByteString', but it is even more efficient. It involves directly--- mapping the file to memory. This has the advantage that the contents--- of the file never need to be copied. Also, under memory pressure the--- page may simply be discarded, while in the case of readFile it would--- need to be written to swap. If you read many small files, mmapFile--- will be less memory-efficient than readFile, since each mmapFile--- takes up a separate page of memory. Also, you can run into bus--- errors if the file is modified. As with 'readFile', the string--- representation in the file is assumed to be ISO-8859-1.------ On systems without mmap, this is the same as a readFile.----mmapFile :: FilePath -> IO ByteString-mmapFile f = mmap f >>= \(fp,l) -> return $! PS fp 0 l--mmap :: FilePath -> IO (ForeignPtr Word8, Int)-mmap f = do- h <- openBinaryFile f ReadMode- l <- fromIntegral `fmap` hFileSize h- -- Don't bother mmaping small files because each mmapped file takes up- -- at least one full VM block.- if l < mmap_limit- then do thefp <- mallocByteString l- withForeignPtr thefp $ \p-> hGetBuf h p l- hClose h- return (thefp, l)- else do- -- unix only :(- fd <- fromIntegral `fmap` handleToFd h- p <- my_mmap l fd- fp <- if p == nullPtr- then do thefp <- mallocByteString l- withForeignPtr thefp $ \p' -> hGetBuf h p' l- return thefp- else do- -- The munmap leads to crashes on OpenBSD.- -- maybe there's a use after unmap in there somewhere?- -- Bulat suggests adding the hClose to the- -- finalizer, excellent idea.-#if !defined(__OpenBSD__)- let unmap = c_munmap p l >> return ()-#else- let unmap = return ()-#endif- fp <- newForeignPtr p unmap- return fp- c_close fd- hClose h- return (fp, l)- where mmap_limit = 16*1024--}---- ------------------------------------------------------------------------ Internal utilities---- | 'findIndexOrEnd' is a variant of findIndex, that returns the length--- of the string if no element is found, rather than Nothing.-{-@ findIndexOrEnd :: (Word8 -> Bool) -> b:ByteString -> {v:Nat | v <= (bLength b) } @-}-findIndexOrEnd :: (Word8 -> Bool) -> ByteString -> Int-findIndexOrEnd k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go l (f `plusPtr` s) 0- where- STRICT3(go)- {- LIQUID WITNESS -}- go (d::Int) ptr n | n >= l = return l- | otherwise = do w <- peek ptr- if k w- then return n- else go (d-1) (ptr `plusPtr` 1) (n+1)-{-# INLINE findIndexOrEnd #-}---- | Perform an operation with a temporary ByteString-withPtr :: ForeignPtr a -> (Ptr a -> IO b) -> b-withPtr fp io = inlinePerformIO (withForeignPtr fp io)-{-# INLINE withPtr #-}---- Common up near identical calls to `error' to reduce the number--- constant strings created when compiled:-{-@ errorEmptyList :: {v:String | false} -> a @-}-errorEmptyList :: String -> a-errorEmptyList fun = moduleError fun "empty ByteString"-{-# NOINLINE errorEmptyList #-}--moduleError :: String -> String -> a-moduleError fun msg = error ("Data.ByteString." ++ fun ++ ':':' ':msg)-{-# NOINLINE moduleError #-}---- Find from the end of the string using predicate-{-@ findFromEndUntil :: (Word8 -> Bool) -> b:ByteString -> {v:Nat | v <= (bLength b)} @-}-findFromEndUntil :: (Word8 -> Bool) -> ByteString -> Int-STRICT2(findFromEndUntil)-findFromEndUntil f ps@(PS x s l) =- if null ps then 0- else if f (last ps) then l- else findFromEndUntil f (PS x s (l-1))------ // for unfoldrN -{-@ qualif PLenNat(v:GHC.Ptr.Ptr a): (0 <= plen v) - @-}---- // for UnpackFoldrINLINED-{-@ qualif UnpackFoldrINLINED(v:List a, n:int, acc:List a): (len v = n + 1 + (len acc))- @-}---- // for ByteString.inits-{-@ qualif BLenGt(v:Data.ByteString.Internal.ByteString, n:int): ((bLength v) > n)- @-}---- // for ByteString.concat-{-@ qualif BLens(v:List Data.ByteString.Internal.ByteString) : (0 <= bLengths v)- @-}--{-@ qualif BLenLE(v:GHC.Ptr.Ptr a, bs:List Data.ByteString.Internal.ByteString): (bLengths bs <= plen v) - @-}---- // for ByteString.splitWith-{-@ qualif SplitWith(v:List Data.ByteString.Internal.ByteString, l:int): ((bLengths v) + (len v) - 1 = l)- @-}---- // for ByteString.unfoldrN-{-@ qualif PtrDiff(v:int, i:int, p:GHC.Ptr.Ptr a): (i - v <= plen p)- @-}---- // for ByteString.split-{-@ qualif BSValidOff(v:int,l:int,p:GHC.ForeignPtr.ForeignPtr a): (v + l <= fplen p) - @-}---{-@ qualif SplitLoop(v:List Data.ByteString.Internal.ByteString, l:int, n:int): ((bLengths v) + (len v) - 1 = l - n)- @-}
@@ -1,2335 +0,0 @@-{-@ LIQUID "--compile-spec" @-}-{-@ LIQUID "--no-totality" @-}-{-@ LIQUID "--notermination" @-}-{-@ LIQUID "--pruneunsorted" @-}--{-# OPTIONS_GHC -cpp -fglasgow-exts -fno-warn-orphans #-}---- #prune---- |--- Module : Data.ByteString--- Copyright : (c) The University of Glasgow 2001,--- (c) David Roundy 2003-2005,--- (c) Simon Marlow 2005--- (c) Don Stewart 2005-2006--- (c) Bjorn Bringert 2006------ Array fusion code:--- (c) 2001,2002 Manuel M T Chakravarty & Gabriele Keller--- (c) 2006 Manuel M T Chakravarty & Roman Leshchinskiy------ License : BSD-style------ Maintainer : dons@cse.unsw.edu.au--- Stability : experimental--- Portability : portable--- --- A time and space-efficient implementation of byte vectors using--- packed Word8 arrays, suitable for high performance use, both in terms--- of large data quantities, or high speed requirements. Byte vectors--- are encoded as strict 'Word8' arrays of bytes, held in a 'ForeignPtr',--- and can be passed between C and Haskell with little effort.------ This module is intended to be imported @qualified@, to avoid name--- clashes with "Prelude" functions. eg.------ > import qualified Data.ByteString as B------ Original GHC implementation by Bryan O\'Sullivan.--- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.--- Rewritten to support slices and use 'ForeignPtr' by David Roundy.--- Polished and extended by Don Stewart.-----module Data.ByteString (-- -- * The @ByteString@ type- ByteString, -- abstract, instances: Eq, Ord, Show, Read, Data, Typeable, Monoid-- -- * Introducing and eliminating 'ByteString's- empty, -- :: ByteString- singleton, -- :: Word8 -> ByteString- pack, -- :: [Word8] -> ByteString- unpack, -- :: ByteString -> [Word8]-- -- * Basic interface- cons, -- :: Word8 -> ByteString -> ByteString- snoc, -- :: ByteString -> Word8 -> ByteString- append, -- :: ByteString -> ByteString -> ByteString- head, -- :: ByteString -> Word8- uncons, -- :: ByteString -> Maybe (Word8, ByteString)- last, -- :: ByteString -> Word8- tail, -- :: ByteString -> ByteString- init, -- :: ByteString -> ByteString- null, -- :: ByteString -> Bool- length, -- :: ByteString -> Int-- -- * Transforming ByteStrings- map, -- :: (Word8 -> Word8) -> ByteString -> ByteString- reverse, -- :: ByteString -> ByteString- intersperse, -- :: Word8 -> ByteString -> ByteString- intercalate, -- :: ByteString -> [ByteString] -> ByteString- transpose, -- :: [ByteString] -> [ByteString]-- -- * Reducing 'ByteString's (folds)- foldl, -- :: (a -> Word8 -> a) -> a -> ByteString -> a- foldl', -- :: (a -> Word8 -> a) -> a -> ByteString -> a- foldl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8- foldl1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-- foldr, -- :: (Word8 -> a -> a) -> a -> ByteString -> a- foldr', -- :: (Word8 -> a -> a) -> a -> ByteString -> a- foldr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8- foldr1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-- -- ** Special folds- concat, -- :: [ByteString] -> ByteString- concatMap, -- :: (Word8 -> ByteString) -> ByteString -> ByteString- any, -- :: (Word8 -> Bool) -> ByteString -> Bool- all, -- :: (Word8 -> Bool) -> ByteString -> Bool- maximum, -- :: ByteString -> Word8- minimum, -- :: ByteString -> Word8-- -- * Building ByteStrings- -- ** Scans- scanl, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString- scanl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString- scanr, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString- scanr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-- -- ** Accumulating maps- mapAccumL, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)- mapAccumR, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)- mapIndexed, -- :: (Int -> Word8 -> Word8) -> ByteString -> ByteString-- -- ** Generating and unfolding ByteStrings- replicate, -- :: Int -> Word8 -> ByteString- unfoldr, -- :: (a -> Maybe (Word8, a)) -> a -> ByteString- unfoldrN, -- :: Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)-- -- * Substrings-- -- ** Breaking strings- take, -- :: Int -> ByteString -> ByteString- drop, -- :: Int -> ByteString -> ByteString- splitAt, -- :: Int -> ByteString -> (ByteString, ByteString)- takeWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString- dropWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString-- span, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- spanEnd, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- break, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- breakEnd, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- group, -- :: ByteString -> [ByteString]- groupBy, -- :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]- inits, -- :: ByteString -> [ByteString]- tails, -- :: ByteString -> [ByteString]-- -- ** Breaking into many substrings- split, -- :: Word8 -> ByteString -> [ByteString]- splitWith, -- :: (Word8 -> Bool) -> ByteString -> [ByteString]-- -- * Predicates- isPrefixOf, -- :: ByteString -> ByteString -> Bool- isSuffixOf, -- :: ByteString -> ByteString -> Bool- isInfixOf, -- :: ByteString -> ByteString -> Bool- isSubstringOf, -- :: ByteString -> ByteString -> Bool-- -- ** Search for arbitrary substrings- findSubstring, -- :: ByteString -> ByteString -> Maybe Int- findSubstrings, -- :: ByteString -> ByteString -> [Int]-- -- * Searching ByteStrings-- -- ** Searching by equality- elem, -- :: Word8 -> ByteString -> Bool- notElem, -- :: Word8 -> ByteString -> Bool-- -- ** Searching with a predicate- find, -- :: (Word8 -> Bool) -> ByteString -> Maybe Word8- filter, -- :: (Word8 -> Bool) -> ByteString -> ByteString- partition, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-- -- * Indexing ByteStrings- index, -- :: ByteString -> Int -> Word8- elemIndex, -- :: Word8 -> ByteString -> Maybe Int- elemIndices, -- :: Word8 -> ByteString -> [Int]- elemIndexEnd, -- :: Word8 -> ByteString -> Maybe Int- findIndex, -- :: (Word8 -> Bool) -> ByteString -> Maybe Int- findIndices, -- :: (Word8 -> Bool) -> ByteString -> [Int]- count, -- :: Word8 -> ByteString -> Int-- -- * Zipping and unzipping ByteStrings- zip, -- :: ByteString -> ByteString -> [(Word8,Word8)]- zipWith, -- :: (Word8 -> Word8 -> c) -> ByteString -> ByteString -> [c]- unzip, -- :: [(Word8,Word8)] -> (ByteString,ByteString)-- -- * Ordered ByteStrings--- LIQUID FAIL sort, -- :: ByteString -> ByteString-- -- * Low level conversions- -- ** Copying ByteStrings- copy, -- :: ByteString -> ByteString-- -- ** Packing 'CString's and pointers- packCString, -- :: CString -> IO ByteString- packCStringLen, -- :: CStringLen -> IO ByteString-- -- ** Using ByteStrings as 'CString's- useAsCString, -- :: ByteString -> (CString -> IO a) -> IO a- useAsCStringLen, -- :: ByteString -> (CStringLen -> IO a) -> IO a-- -- * I\/O with 'ByteString's-- -- ** Standard input and output- getLine, -- :: IO ByteString- getContents, -- :: IO ByteString- putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO ()- interact, -- :: (ByteString -> ByteString) -> IO ()-- -- ** Files- readFile, -- :: FilePath -> IO ByteString- writeFile, -- :: FilePath -> ByteString -> IO ()- appendFile, -- :: FilePath -> ByteString -> IO ()--- mmapFile, -- :: FilePath -> IO ByteString-- -- ** I\/O with Handles- hGetLine, -- :: Handle -> IO ByteString- hGetContents, -- :: Handle -> IO ByteString- hGet, -- :: Handle -> Int -> IO ByteString- hGetNonBlocking, -- :: Handle -> Int -> IO ByteString- hPut, -- :: Handle -> ByteString -> IO ()- hPutStr, -- :: Handle -> ByteString -> IO ()- hPutStrLn, -- :: Handle -> ByteString -> IO ()-- -- undocumented deprecated things:- join -- :: ByteString -> [ByteString] -> ByteString-- ) where--import Language.Haskell.Liquid.Prelude (unsafeError)-import qualified Prelude as P-import Prelude hiding (reverse,head,tail,last,init,null- ,length,map,lines,foldl,foldr,unlines- ,concat,any,take,drop,splitAt,takeWhile- ,dropWhile,span,break,elem,filter,maximum- ,minimum,all,concatMap,foldl1,foldr1- ,scanl,scanl1,scanr,scanr1- ,readFile,writeFile,appendFile,replicate- ,getContents,getLine,putStr,putStrLn,interact- ,zip,zipWith,unzip,notElem)--import Data.ByteString.Internal-import Data.ByteString.Unsafe-import Data.ByteString.Fusion--import qualified Data.List as List--import Data.Word (Word8,Word64)-import Data.Maybe (listToMaybe)-import Data.Array (listArray)-import qualified Data.Array as Array ((!))---- Control.Exception.bracket not available in yhc or nhc-#ifndef __NHC__-import Control.Exception (bracket, assert)-import qualified Control.Exception as Exception-#else-import IO (bracket)-#endif-import Control.Monad (when)--import Foreign.C.String (CString, CStringLen)-import Foreign.C.Types (CSize)-import Foreign.ForeignPtr-import Foreign.Marshal.Alloc (allocaBytes, mallocBytes, reallocBytes, finalizerFree)-import Foreign.Marshal.Array (allocaArray)-import Foreign.Ptr-import Foreign.Storable (Storable(..))---- hGetBuf and hPutBuf not available in yhc or nhc-import System.IO (stdin,stdout,hClose,hFileSize- ,hGetBuf,hPutBuf,openBinaryFile- ,Handle,IOMode(..))--import Data.Monoid (Monoid, mempty, mappend, mconcat)--#if !defined(__GLASGOW_HASKELL__)-import System.IO.Unsafe-import qualified System.Environment-import qualified System.IO (hGetLine)-#endif--#if defined(__GLASGOW_HASKELL__)--import System.IO (hGetBufNonBlocking)-import System.IO.Error (isEOFError)---- import GHC.Handle-import GHC.Exts (Word#, (+#), writeWord8OffAddr#)-import GHC.Base (build)-import GHC.Word hiding (Word8)-import GHC.Ptr (Ptr(..))-import GHC.ST (ST(..))--#endif--#if __GLASGOW_HASKELL__ >= 611-import Data.IORef-import GHC.IO.Handle.Internals-import GHC.IO.Handle.Types-import GHC.IO.Buffer-import GHC.IO.BufferedIO as Buffered-import GHC.IO (stToIO, unsafePerformIO)-import Data.Char (ord)-import Foreign.Marshal.Utils (copyBytes)-#else-import System.IO.Error (isEOFError)-import GHC.IOBase-import GHC.Handle-#endif---- An alternative to Control.Exception (assert) for nhc98-#ifdef __NHC__-#define assert assertS "__FILE__ : __LINE__"-assertS :: String -> Bool -> a -> a-assertS _ True = id-assertS s False = unsafeError ("assertion failed at "++s)-#endif---- LIQUID-import GHC.IO.Buffer-import Language.Haskell.Liquid.Prelude hiding (eq) -import Language.Haskell.Liquid.Foreign --{-@ include <Data/ByteString.hs.hquals> @-}--{-@ memcpy_ptr_baoff :: p:(Ptr a) - -> RawBuffer b - -> Int - -> {v:CSize | (OkPLen v p)} -> IO (Ptr ())- @-}-memcpy_ptr_baoff :: Ptr a -> RawBuffer b -> Int -> CSize -> IO (Ptr ())-memcpy_ptr_baoff = unsafeError "LIQUIDCOMPAT"--readCharFromBuffer :: RawBuffer b -> Int -> IO (Char, Int)-readCharFromBuffer x y = unsafeError "LIQUIDCOMPAT"--wantReadableHandleLIQUID :: String -> Handle -> (Handle__ -> IO a) -> IO a-wantReadableHandleLIQUID x y f = unsafeError $ show $ liquidCanaryFusion 12 -- "LIQUIDCOMPAT"---- for unfoldrN --{-@ lengths :: bs:[ByteString] -> {v:Nat | v = (bLengths bs)} @-}-lengths :: [ByteString] -> Int-lengths [] = 0-lengths (b:bs) = length b + lengths bs---- LIQUID HACK: this is to get all the quals from memchr. --- Quals needed because IO monad forces liquid-abstraction. --- Solution, scrape quals from predicate defs (e.g. SuffixPtr)-{-@ dummyForQuals1_elemIndex :: p:(Ptr a) -> n:Int -> (IO {v:(Ptr b) | (SuffixPtr v n p)}) @-}-dummyForQuals1_elemIndex :: Ptr a -> Int -> IO (Ptr b)-dummyForQuals1_elemIndex = undefined --{-@ dummyForQuals2_splitWith :: p:(ForeignPtr Word8) -> o:{v:Nat | v <= (fplen p)} -> {v:Nat | (BSValid p o v)} -> ByteString - @-}-dummyForQuals2_splitWith :: ForeignPtr Word8 -> Int -> Int -> ByteString-dummyForQuals2_splitWith = undefined---- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined---- -------------------------------------------------------------------------------instance Eq ByteString- where (==) = eq--instance Ord ByteString- where compare = compareBytes---- LIQUID instance Monoid ByteString where--- LIQUID mempty = empty--- LIQUID mappend = append--- LIQUID mconcat = concat--{--instance Arbitrary PackedString where- arbitrary = P.pack `fmap` arbitrary- coarbitrary s = coarbitrary (P.unpack s)--}---- | /O(n)/ Equality on the 'ByteString' type.-{-@ eq :: ByteString -> ByteString -> Bool @-}-eq :: ByteString -> ByteString -> Bool-eq a@(PS p s l) b@(PS p' s' l')- | l /= l' = False -- short cut on length- | p == p' && s == s' = True -- short cut for the same string- | otherwise = compareBytes a b == EQ-{-# INLINE eq #-}---- | /O(n)/ 'compareBytes' provides an 'Ordering' for 'ByteStrings' supporting slices. -compareBytes :: ByteString -> ByteString -> Ordering-compareBytes (PS x1 s1 l1) (PS x2 s2 l2)- | l1 == 0 && l2 == 0 = EQ -- short cut for empty strings- | x1 == x2 && s1 == s2 && l1 == l2 = EQ -- short cut for the same string- | otherwise = inlinePerformIO $- withForeignPtr x1 $ \p1 ->- withForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral $ min l1 l2)- return $! case i `compare` 0 of- EQ -> l1 `compare` l2- x -> x-{-# INLINE compareBytes #-}-- -{------- About 4x slower over 32M----compareBytes :: ByteString -> ByteString -> Ordering-compareBytes (PS fp1 off1 len1) (PS fp2 off2 len2) = inlinePerformIO $- withForeignPtr fp1 $ \p1 ->- withForeignPtr fp2 $ \p2 ->- cmp (p1 `plusPtr` off1)- (p2 `plusPtr` off2) 0 len1 len2--cmp :: Ptr Word8 -> Ptr Word8 -> Int -> Int -> Int-> IO Ordering-STRICT5(cmp)-cmp p1 p2 n len1 len2- | n == len1 = if n == len2 then return EQ else return LT- | n == len2 = return GT- | otherwise = do- (a :: Word8) <- peekByteOff p1 n- (b :: Word8) <- peekByteOff p2 n- case a `compare` b of- EQ -> cmp p1 p2 (n+1) len1 len2- LT -> return LT- GT -> return GT-{-# INLINE compareBytes #-}--}---- -------------------------------------------------------------------------------- Introducing and eliminating 'ByteString's---- | /O(1)/ The empty 'ByteString'-{-@ empty :: {v:ByteString | (bLength v) = 0} @-} -empty :: ByteString-empty = PS nullForeignPtr 0 0-- --- | /O(1)/ Convert a 'Word8' into a 'ByteString'--{-@ singleton :: Word8 -> {v:ByteString | (bLength v) = 1} @-}-singleton :: Word8 -> ByteString-singleton c = unsafeCreate 1 $ \p -> poke p c-{-# INLINE [1] singleton #-}------- XXX The unsafePerformIO is critical!------ Otherwise:------ singleton 255 `compare` singleton 127------ is compiled to:------ case mallocByteString 2 of --- ForeignPtr f internals -> --- case writeWord8OffAddr# f 0 255 of _ -> --- case writeWord8OffAddr# f 0 127 of _ ->--- case eqAddr# f f of --- False -> case compare (GHC.Prim.plusAddr# f 0) --- (GHC.Prim.plusAddr# f 0)---------- | /O(n)/ Convert a '[Word8]' into a 'ByteString'. ------ For applications with large numbers of string literals, pack can be a--- bottleneck. In such cases, consider using packAddress (GHC only).-{-@ pack :: cs:[Word8] -> {v:ByteString | (bLength v) = (len cs)} @-}-pack :: [Word8] -> ByteString--#if !defined(__GLASGOW_HASKELL__)--pack str = unsafeCreate (P.length str) $ \p -> go p str- where- go _ [] = return ()- go p (x:xs) = poke p x >> go (p `plusPtr` 1) xs -- less space than pokeElemOff--#else /* hack away */--pack str = unsafeCreate (P.length str) $ \(Ptr p) -> stToIO (go p 0# str)- where- go _ _ [] = return ()- go p i (W8# c:cs) = writeByte p i c >> go p (i +# 1#) cs-- writeByte p i c = ST $ \s# ->- case writeWord8OffAddr# p i c s# of s2# -> (# s2#, () #)--#endif----- | /O(n)/ Converts a 'ByteString' to a '[Word8]'.-{-@ unpack :: b:ByteString -> {v:[Word8] | (len v) = (bLength b)} @-}-unpack :: ByteString -> [Word8]--#if !defined(__GLASGOW_HASKELL__)--- LIQUID -- unpack (PS _ _ 0) = []--- LIQUID -- unpack (PS ps s l) = inlinePerformIO $ withForeignPtr ps $ \p ->--- LIQUID -- ugo (p `plusPtr` s) (l - 1) []--- LIQUID -- --- LIQUID -- ugo :: ForeignPtr Word8 -> Int -> [Word8] -> IO Word8 --- LIQUID -- ugo p 0 acc = peek p >>= \e -> return (e : acc)--- LIQUID -- ugo p n acc = peekByteOff p n >>= \e -> ugo p (n-1) (e : acc)-unpack (PS _ _ 0) = []-unpack (PS ps s l) = inlinePerformIO $ withForeignPtr ps $ \p ->- go (p `plusPtr` s) (l - 1) []- where- STRICT3(go)- go p 0 acc = peek p >>= \e -> return (e : acc)- go p n acc = peekByteOff p n >>= \e -> go p (n-1) (e : acc)-{-# INLINE unpack #-}--#else---- unpack ps = build (unpackFoldr ps)---- LIQUID TODO unpackFoldr :: forall <p :: Int -> a -> Bool>. --- b:ByteString --- -> (i:Int -> Word8 -> a<p i> -> a<p (i+1)>)--- -> (a<p 0>)--- -> (a<p (bLength b)>)-{-# INLINE unpack #-}---- LIQUID INLINED : unpack ps = build (unpackFoldr ps) = unpackFoldr ps (:) [] --- LIQUID INLINED : so inline `f` with `:` and `ch` with `[]`-unpack ps = unpackFoldrINLINED ps--unpackFoldrINLINED :: ByteString -> [Word8]-unpackFoldrINLINED (PS fp off len) = withPtr fp $ \p -> do- let loop q n _ | q `seq` n `seq` False = undefined -- n.b.- loop _ (-1) acc = return acc- loop q n acc = do- a <- peekByteOff q n- loop q (n-1) (a : acc)- loop (p `plusPtr` off) (len-1) [] ---- critical this isn't strict in the acc--- as it will break in the presence of list fusion. this is a known--- issue with seq and build/foldr rewrite rules, which rely on lazy--- demanding to avoid bottoms in the list.----unpackFoldr :: ByteString -> (Word8 -> a -> a) -> a -> a-unpackFoldr (PS fp off len) f ch = withPtr fp $ \p -> do- let loop q n _ | q `seq` n `seq` False = undefined -- n.b.- loop _ (-1) acc = return acc- loop q n acc = do- a <- peekByteOff q n- loop q (n-1) (a `f` acc)- loop (p `plusPtr` off) (len-1) ch-{-# INLINE [0] unpackFoldr #-}--{-@ unpackList :: b:ByteString -> {v:[Word8] | (len v) = (bLength b)} @-}-unpackList :: ByteString -> [Word8]-unpackList (PS fp off len) = withPtr fp $ \p -> do- let STRICT3(loop)- loop _ (-1) acc = return acc- loop q n acc = do- a <- peekByteOff q n- loop q (n-1) (a : acc)- loop (p `plusPtr` off) (len-1) []--{-# RULES- "FPS unpack-list" [1] forall p . unpackFoldr p (:) [] = unpackList p- #-}--#endif---- ------------------------------------------------------------------------ Basic interface---- | /O(1)/ Test whether a ByteString is empty.-{-@ null :: b:ByteString -> {v:Bool | v <=> (bLength b == 0)} @-}-null :: ByteString -> Bool-null (PS _ _ l) = assert (l >= 0) $ l <= 0-{-# INLINE null #-}---- ------------------------------------------------------------------------ | /O(1)/ 'length' returns the length of a ByteString as an 'Int'.-{-@ length :: b:ByteString -> {v:Nat | v = (bLength b)} @-}-length :: ByteString -> Int-length (PS _ _ l) = assert (l >= 0) $ l-{-# INLINE length #-}------------------------------------------------------------------------------ | /O(n)/ 'cons' is analogous to (:) for lists, but of different--- complexity, as it requires a memcpy.--{-@ cons :: Word8 -> b:ByteString -> {v:ByteString | (bLength v) = 1 + (bLength b)} @-}-cons :: Word8 -> ByteString -> ByteString-cons c (PS x s l) = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do- poke p c- memcpy (p `plusPtr` 1) (f `plusPtr` s) (fromIntegral l)-{-# INLINE cons #-}---- | /O(n)/ Append a byte to the end of a 'ByteString'-{-@ snoc :: b:ByteString -> Word8 -> {v:ByteString | (bLength v) = 1 + (bLength b)} @-}-snoc :: ByteString -> Word8 -> ByteString-snoc (PS x s l) c = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do- memcpy p (f `plusPtr` s) (fromIntegral l)- poke (p `plusPtr` l) c-{-# INLINE snoc #-}---- todo fuse---- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.--- An exception will be thrown in the case of an empty ByteString.-{-@ head :: ByteStringNE -> Word8 @-}-head :: ByteString -> Word8-head (PS x s l)- | l <= 0 = errorEmptyList "head"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p s-{-# INLINE head #-}---- | /O(1)/ Extract the elements after the head of a ByteString, which must be non-empty.--- An exception will be thrown in the case of an empty ByteString.-{-@ tail :: b:ByteStringNE -> {v:ByteString | (bLength v) = (bLength b) - 1} @-}-tail :: ByteString -> ByteString-tail (PS p s l)- | l <= 0 = errorEmptyList "tail"- | otherwise = PS p (s+1) (l-1)-{-# INLINE tail #-}---- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing--- if it is empty.-{-@ uncons :: b:ByteString -> Maybe (Word8, {v:ByteString | (bLength v) = (bLength b) - 1}) @-}-uncons :: ByteString -> Maybe (Word8, ByteString)-uncons (PS x s l)- | l <= 0 = Nothing- | otherwise = Just (inlinePerformIO $ withForeignPtr x- $ \p -> peekByteOff p s,- PS x (s+1) (l-1))-{-# INLINE uncons #-}---- | /O(1)/ Extract the last element of a ByteString, which must be finite and non-empty.--- An exception will be thrown in the case of an empty ByteString.-{-@ last :: ByteStringNE -> Word8 @-}-last :: ByteString -> Word8-last ps@(PS x s l)- | null ps = errorEmptyList "last"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+l-1)-{-# INLINE last #-}---- | /O(1)/ Return all the elements of a 'ByteString' except the last one.--- An exception will be thrown in the case of an empty ByteString.-{-@ init :: b:ByteStringNE -> {v:ByteString | (bLength v) = (bLength b) - 1} @-}-init :: ByteString -> ByteString-init ps@(PS p s l)- | null ps = errorEmptyList "init"- | otherwise = PS p s (l-1)-{-# INLINE init #-}---- | /O(n)/ Append two ByteStrings-{-@ append :: b1:ByteString -> b2:ByteString - -> {v:ByteString | (bLength v) = (bLength b1) + (bLength b2)} - @-}-append :: ByteString -> ByteString -> ByteString-append xs ys | null xs = ys- | null ys = xs- | otherwise = concat [xs,ys]-{-# INLINE append #-}---- ------------------------------------------------------------------------ Transformations---- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each--- element of @xs@. This function is subject to array fusion.-{-@ map :: (Word8 -> Word8) -> b:ByteString -> (ByteStringSZ b) @-}-map :: (Word8 -> Word8) -> ByteString -> ByteString-map f (PS fp s lenYYY) = inlinePerformIO $ withForeignPtr fp $ \a ->- create lenYYY $ map_ 0 (a `plusPtr` s)- where- map_ :: Int -> Ptr Word8 -> Ptr Word8 -> IO ()- STRICT3(map_)- map_ n p1 p2- | n >= lenYYY = return ()- | otherwise = do- x <- peekByteOff p1 n- pokeByteOff p2 n (f x)- map_ (n+1) p1 p2-{-# INLINE map #-}---- | /O(n)/ 'reverse' @xs@ efficiently returns the elements of @xs@ in reverse order.--{-@ reverse :: b:ByteString -> (ByteStringSZ b) @-}-reverse :: ByteString -> ByteString-reverse (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->- c_reverse p (f `plusPtr` s) (fromIntegral l)---- | /O(n)/ The 'intersperse' function takes a 'Word8' and a--- 'ByteString' and \`intersperses\' that byte between the elements of--- the 'ByteString'. It is analogous to the intersperse function on--- Lists.-{-@ intersperse :: Word8 -> b:ByteString- -> {v:ByteString | bLength v = if bLength b > 0 then (2 * bLength b - 1) else 0 }- @-}-intersperse :: Word8 -> ByteString -> ByteString-intersperse c ps@(PS x s l)- | length ps < 2 = ps- | otherwise = unsafeCreate ({- 2*l -} (l + l) - 1) $ \p -> withForeignPtr x $ \f ->- c_intersperse p (f `plusPtr` s) (fromIntegral l) c--{--intersperse c = pack . List.intersperse c . unpack--}---- | The 'transpose' function transposes the rows and columns of its--- 'ByteString' argument.-transpose :: [ByteString] -> [ByteString]-transpose ps = P.map pack (List.transpose (P.map unpack ps))---- LIQUID TODO--- transpose :: bs:[ByteString] -> {v:[ByteString] | (bLengths v) = (bLengths bs)}--- transpose :: xs:[[a]] -> {v:[[a]] | (lens v) = (lens xs)}--- transpose ps = [pack p | p <- List.transpose [unpack p | p <- ps] ]----- ------------------------------------------------------------------------ Reducing 'ByteString's---- | 'foldl', applied to a binary operator, a starting value (typically--- the left-identity of the operator), and a ByteString, reduces the--- ByteString using the binary operator, from left to right.--- This function is subject to array fusion.--{-@ foldl :: (a -> Word8 -> a) -> a -> ByteString -> a @-}-foldl :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl f v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- lgo v (ptr `plusPtr` s) (ptr `plusPtr` (s+l))- where- STRICT3(lgo)- lgo z p q | p == q = return z- | otherwise = do let p' = liquid_thm_ptr_cmp p q - c <- peek p'- lgo (f z c) (p' `plusPtr` 1) q-{-# INLINE foldl #-}---- LIQUID: This will go away when we properly embed Ptr a as int -- only in--- fixpoint to avoid the Sort mismatch hassles. -{-@ liquid_thm_ptr_cmp :: p:PtrV a - -> q:{v:(PtrV a) | ((plen v) <= (plen p) && v != p && (pbase v) = (pbase p))} - -> {v: (PtrV a) | ((v = p) && ((plen q) < (plen p))) } - @-}-liquid_thm_ptr_cmp :: Ptr a -> Ptr a -> Ptr a-liquid_thm_ptr_cmp p q = undefined -- p -- LIQUID : make this undefined to suppress WARNING----- | 'foldl\'' is like 'foldl', but strict in the accumulator.--- Though actually foldl is also strict in the accumulator.-{-@ foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a @-}-foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl' = foldl-{-# INLINE foldl' #-}---- | 'foldr', applied to a binary operator, a starting value--- (typically the right-identity of the operator), and a ByteString,--- reduces the ByteString using the binary operator, from right to left.-foldr :: (Word8 -> a -> a) -> a -> ByteString -> a-foldr k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1))- where- STRICT3(go)- go z p q | p == q = return z- | otherwise = do let p' = liquid_thm_ptr_cmp' p q - c <- peek p'- let n = 0 - 1 - go (c `k` z) (p' `plusPtr` n) q -- tail recursive- -- LIQUID go z p q | p == q = return z- -- LIQUID | otherwise = do c <- peek p- -- LIQUID go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive-{-# INLINE foldr #-}--{-@ liquid_thm_ptr_cmp' :: p:PtrV a - -> q:{v:(PtrV a) | ((plen v) >= (plen p) && v != p && (pbase v) = (pbase p))} - -> {v: (PtrV a) | ((v = p) && ((plen v) > 0) && ((plen q) > (plen p))) } - @-}-liquid_thm_ptr_cmp' :: Ptr a -> Ptr a -> Ptr a-liquid_thm_ptr_cmp' p q = undefined ---- | 'foldr\'' is like 'foldr', but strict in the accumulator.-foldr' :: (Word8 -> a -> a) -> a -> ByteString -> a-foldr' k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1))- where- STRICT3(go)- go z p q | p == q = return z- | otherwise = do let p' = liquid_thm_ptr_cmp' p q - c <- peek p'- let n = 0 - 1 - go (c `k` z) (p' `plusPtr` n) q -- tail recursive- -- LIQUID go z p q | p == q = return z- -- LIQUID | otherwise = do c <- peek p- -- LIQUID go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive-{-# INLINE foldr' #-}---- | 'foldl1' is a variant of 'foldl' that has no starting value--- argument, and thus must be applied to non-empty 'ByteStrings'.--- This function is subject to array fusion. --- An exception will be thrown in the case of an empty ByteString.-{-@ foldl1 :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldl1 f ps- | null ps = errorEmptyList "foldl1"- | otherwise = foldl f (unsafeHead ps) (unsafeTail ps)-{-# INLINE foldl1 #-}---- | 'foldl1\'' is like 'foldl1', but strict in the accumulator.--- An exception will be thrown in the case of an empty ByteString.-{-@ foldl1' :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldl1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldl1' f ps- | null ps = errorEmptyList "foldl1'"- | otherwise = foldl' f (unsafeHead ps) (unsafeTail ps)-{-# INLINE foldl1' #-}---- | 'foldr1' is a variant of 'foldr' that has no starting value argument,--- and thus must be applied to non-empty 'ByteString's--- An exception will be thrown in the case of an empty ByteString.--{-@ foldr1 :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldr1 f ps- | null ps = errorEmptyList "foldr1"- | otherwise = foldr f (last ps) (init ps)-{-# INLINE foldr1 #-}---- | 'foldr1\'' is a variant of 'foldr1', but is strict in the--- accumulator.-{-@ foldr1' :: (Word8 -> Word8 -> Word8) -> ByteStringNE -> Word8 @-}-foldr1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldr1' f ps- | null ps = errorEmptyList "foldr1"- | otherwise = foldr' f (last ps) (init ps)-{-# INLINE foldr1' #-}---- ------------------------------------------------------------------------ Special folds---- | /O(n)/ Concatenate a list of ByteStrings.-{-@ concat :: bs:[ByteString] -> {v:ByteString | (bLength v) = (bLengths bs)} @-}-concat :: [ByteString] -> ByteString-concat [] = empty-concat [ps] = ps-concat xs = unsafeCreate lenZZZ $ \ptr -> go xs ptr- where lenZZZ = {- LIQUID P.sum . P.map length $ -} lengths xs- STRICT2(go)- go [] _ = return ()- go (PS p s l:ps) ptr = do- -- LIQUID: could instead use (also works)- -- LIQUID {- invariant {v: [ByteString] | 0 <= (bLengths v)} -}- let p' = liquidAssert (lengths ps >= 0) p- withForeignPtr p' $ \fp -> memcpy ptr (fp `plusPtr` s) (fromIntegral l)- go ps (ptr `plusPtr` l)---- | Map a function over a 'ByteString' and concatenate the results-concatMap :: (Word8 -> ByteString) -> ByteString -> ByteString-concatMap f = concat . foldr ((:) . f) []---- foldr (append . f) empty---- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if--- any element of the 'ByteString' satisfies the predicate.-any :: (Word8 -> Bool) -> ByteString -> Bool-any _ (PS _ _ 0) = False-any f (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go (ptr `plusPtr` s) (ptr `plusPtr` (s+l))- where- STRICT2(go)- go p q | p == q = return False- | otherwise = do let p' = liquid_thm_ptr_cmp p q -- LIQUID- c <- peek p'- if f c then return True- else go (p' `plusPtr` 1) q-{-# INLINE any #-}---- todo fuse---- | /O(n)/ Applied to a predicate and a 'ByteString', 'all' determines--- if all elements of the 'ByteString' satisfy the predicate.-all :: (Word8 -> Bool) -> ByteString -> Bool-all _ (PS _ _ 0) = True-all f (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->- go (ptr `plusPtr` s) (ptr `plusPtr` (s+l))- where- STRICT2(go)- go p q | p == q = return True -- end of list- | otherwise = do let p' = liquid_thm_ptr_cmp p q -- LIQUID- c <- peek p'- if f c- then go (p' `plusPtr` 1) q- else return False-{-# INLINE all #-}------------------------------------------------------------------------------ | /O(n)/ 'maximum' returns the maximum value from a 'ByteString'--- This function will fuse.--- An exception will be thrown in the case of an empty ByteString.-{-@ maximum :: ByteStringNE -> Word8 @-}-maximum :: ByteString -> Word8-maximum xs@(PS x s l)- | null xs = errorEmptyList "maximum"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p ->- c_maximum (p `plusPtr` s) (fromIntegral l)-{-# INLINE maximum #-}---- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString'--- This function will fuse.--- An exception will be thrown in the case of an empty ByteString.-{-@ minimum :: ByteStringNE -> Word8 @-}-minimum :: ByteString -> Word8-minimum xs@(PS x s l)- | null xs = errorEmptyList "minimum"- | otherwise = inlinePerformIO $ withForeignPtr x $ \p ->- c_minimum (p `plusPtr` s) (fromIntegral l)-{-# INLINE minimum #-}------------------------------------------------------------------------------ | The 'mapAccumL' function behaves like a combination of 'map' and--- 'foldl'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from left to right, and returning a--- final value of this accumulator together with the new list.--{-@ mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> b:ByteString -> (acc, ByteStringSZ b) @-}-mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-#if !defined(LOOPU_FUSION)-mapAccumL f z b = unSP $ loopUp (mapAccumEFL f) z b-#else-mapAccumL f z b = unSP $ loopU (mapAccumEFL f) z b-#endif-{-# INLINE mapAccumL #-}---- | The 'mapAccumR' function behaves like a combination of 'map' and--- 'foldr'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from right to left, and returning a--- final value of this accumulator together with the new ByteString.--{-@ mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> b:ByteString -> (acc, ByteStringSZ b) @-}-mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumR f z b = unSP $ loopDown (mapAccumEFL f) z b-{-# INLINE mapAccumR #-}---- | /O(n)/ map Word8 functions, provided with the index at each position-{-@ mapIndexed :: (Int -> Word8 -> Word8) -> b:ByteString -> ByteStringSZ b @-}-mapIndexed :: (Int -> Word8 -> Word8) -> ByteString -> ByteString-mapIndexed f b = loopArr $ loopUp (mapIndexEFL f) 0 b-{-# INLINE mapIndexed #-}---- ------------------------------------------------------------------------ Building ByteStrings---- | 'scanl' is similar to 'foldl', but returns a list of successive--- reduced values from the left. This function will fuse.------ > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]------ Note that------ > last (scanl f z xs) == foldl f z xs.--{-@ scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> b:ByteString -> {v:ByteString | (bLength v) = 1 + (bLength b)} @-}-scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString-#if !defined(LOOPU_FUSION)-scanl f z ps = loopArr . loopUp (scanEFL f) z $ (ps `snoc` 0)-#else-scanl f z ps = loopArr . loopU (scanEFL f) z $ (ps `snoc` 0)-#endif-- -- n.b. haskell's List scan returns a list one bigger than the- -- input, so we need to snoc here to get some extra space, however,- -- it breaks map/up fusion (i.e. scanl . map no longer fuses)-{-# INLINE scanl #-}---- | 'scanl1' is a variant of 'scanl' that has no starting value argument.--- This function will fuse.------ > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]-{-@ scanl1 :: (Word8 -> Word8 -> Word8) -> b:ByteStringNE -> (ByteStringSZ b) @-}-scanl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-scanl1 f ps- | null ps = empty- | otherwise = scanl f (unsafeHead ps) (unsafeTail ps)-{-# INLINE scanl1 #-}---- | scanr is the right-to-left dual of scanl.-{-@ scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> b:ByteString -> {v:ByteStringNE | (bLength v) = 1 + (bLength b)} @-}-scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString-scanr f z ps = loopArr . loopDown (scanEFL (flip f)) z $ (0 `cons` ps) -- extra space-{-# INLINE scanr #-}---- | 'scanr1' is a variant of 'scanr' that has no starting value argument.-{-@ scanr1 :: (Word8 -> Word8 -> Word8) -> b:ByteStringNE -> (ByteStringSZ b) @-}-scanr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-scanr1 f ps- | null ps = empty- | otherwise = scanr f (last ps) (init ps) -- todo, unsafe versions-{-# INLINE scanr1 #-}---- ------------------------------------------------------------------------ Unfolds and replicates---- | /O(n)/ 'replicate' @n x@ is a ByteString of length @n@ with @x@--- the value of every element. The following holds:------ > replicate w c = unfoldr w (\u -> Just (u,u)) c------ This implemenation uses @memset(3)@-{- LIQUID this is SIMPLER ... : replicate :: n:Nat -> Word8 -> (ByteStringN n) @-}-{-@ replicate :: n:Nat -> Word8 -> {v:ByteString | (bLength v) = (if n > 0 then n else 0)} @-}-replicate :: Int -> Word8 -> ByteString-replicate w c- | w <= 0 = empty- | otherwise = unsafeCreate w $ \ptr ->- memset ptr c (fromIntegral w) >> return ()---- | /O(n)/, where /n/ is the length of the result. The 'unfoldr' --- function is analogous to the List \'unfoldr\'. 'unfoldr' builds a --- ByteString from a seed value. The function takes the element and --- returns 'Nothing' if it is done producing the ByteString or returns --- 'Just' @(a,b)@, in which case, @a@ is the next byte in the string, --- and @b@ is the seed value for further production.------ Examples:------ > unfoldr (\x -> if x <= 5 then Just (x, x + 1) else Nothing) 0--- > == pack [0, 1, 2, 3, 4, 5]--{-@ unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString @-}-unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString-unfoldr f = concat . unfoldChunk 32 64- where unfoldChunk n n' x =- case unfoldrN n f x of- (s, Nothing) -> s : []- (s, Just x') -> s : unfoldChunk n' (n+n') x'-{-# INLINE unfoldr #-}---- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a ByteString from a seed--- value. However, the length of the result is limited by the first--- argument to 'unfoldrN'. This function is more efficient than 'unfoldr'--- when the maximum length of the result is known.------ The following equation relates 'unfoldrN' and 'unfoldr':------ > unfoldrN n f s == take n (unfoldr f s)----{-@ unfoldrN :: i:Nat -> (a -> Maybe (Word8, a)) -> a -> ({v:ByteString | (bLength v) <= i}, Maybe a)<{\b m -> ((isJust m) => ((bLength b) = i))}> @-}-unfoldrN :: Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)-unfoldrN i f x0- | i < 0 = (empty, Just x0)- | otherwise = unsafePerformIO $ createAndTrimMEQ i $ \p -> go p x0 0- where STRICT3(go)- {-@ decrease go 4 @-}- go p x n =- case f x of- Nothing -> return (0 :: Int {- LIQUID -}, n, Nothing)- Just (w,x')- | n == i -> return (0, n, Just x)- | otherwise -> do poke p w- go (p `plusPtr` 1) x' (n+1)-{-# INLINE unfoldrN #-}--{-@ unfoldqual :: l:Nat -> {v:(Nat, Nat, Maybe a) | (((tsnd v) <= (l-(tfst v)))- && ((isJust (ttrd v)) => ((tsnd v)=l)))} @-}-unfoldqual :: Int -> (Int, Int, Maybe a)-unfoldqual = undefined---- ------------------------------------------------------------------------ Substrings---- | /O(1)/ 'take' @n@, applied to a ByteString @xs@, returns the prefix--- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.--{-@ take :: n:Nat -> b:ByteString -> {v:ByteString | (bLength v) = (if (n <= (bLength b)) then n else (bLength b))} @-}-take :: Int -> ByteString -> ByteString-take n ps@(PS x s l)- | n <= 0 = empty- | n >= l = ps- | otherwise = PS x s n-{-# INLINE take #-}---- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@--- elements, or @[]@ if @n > 'length' xs@.--{-@ drop :: n:Nat -> b:ByteString -> {v:ByteString | (bLength v) = (if (n <= (bLength b)) then (bLength b) - n else 0)} @-}-drop :: Int -> ByteString -> ByteString-drop n ps@(PS x s l)- | n <= 0 = ps- | n >= l = empty- | otherwise = PS x (s+n) (l-n)-{-# INLINE drop #-}---- | /O(1)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.--{-@ splitAt :: n:Int- -> b:ByteString- -> ({v:ByteString | (Min (bLength v) (bLength b)- (if (n >= 0) then n else 0))}- , ByteString)<{\x y -> (bLength y) = ((bLength b) - (bLength x))}>- @-}-splitAt :: Int -> ByteString -> (ByteString, ByteString)-splitAt n ps@(PS x s l)- | n <= 0 = (empty, ps)- | n >= l = (ps, empty)- | otherwise = (PS x s n, PS x (s+n) (l-n))-{-# INLINE splitAt #-}---- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.--{-@ takeWhile :: (Word8 -> Bool) -> b:ByteString -> (ByteStringLE b) @-}-takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString-takeWhile f ps = unsafeTake (findIndexOrEnd (not . f) ps) ps-{-# INLINE takeWhile #-}---- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.-{-@ dropWhile :: (Word8 -> Bool) -> b:ByteString -> (ByteStringLE b) @-}-dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString-dropWhile f ps = unsafeDrop (findIndexOrEnd (not . f) ps) ps-{-# INLINE dropWhile #-}---- instead of findIndexOrEnd, we could use memchr here.---- | 'break' @p@ is equivalent to @'span' ('not' . p)@.-{-@ break :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-break p ps = case findIndexOrEnd p ps of n -> (unsafeTake n ps, unsafeDrop n ps)-#if __GLASGOW_HASKELL__ -{-# INLINE [1] break #-}--{-# RULES-"FPS specialise break (x==)" forall x.- break ((==) x) = breakByte x-"FPS specialise break (==x)" forall x.- break (==x) = breakByte x- #-}-#endif---- | 'breakByte' breaks its ByteString argument at the first occurence--- of the specified byte. It is more efficient than 'break' as it is--- implemented with @memchr(3)@. I.e.--- --- > break (=='c') "abcd" == breakByte 'c' "abcd"-----{-@ breakByte :: Word8 -> b:ByteString -> (ByteStringPair b) @-}-breakByte :: Word8 -> ByteString -> (ByteString, ByteString)-breakByte c p = case elemIndex c p of- Nothing -> (p,empty)- Just n -> (unsafeTake n p, unsafeDrop n p)-{-# INLINE breakByte #-}---- | 'breakEnd' behaves like 'break' but from the end of the 'ByteString'--- --- breakEnd p == spanEnd (not.p)--{-@ breakEnd :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-breakEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-breakEnd p ps = splitAt (findFromEndUntil p ps) ps---- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@-{-@ span :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-span p ps = break (not . p) ps-#if __GLASGOW_HASKELL__-{-# INLINE [1] span #-}-#endif---- | 'spanByte' breaks its ByteString argument at the first--- occurence of a byte other than its argument. It is more efficient--- than 'span (==)'------ > span (=='c') "abcd" == spanByte 'c' "abcd"----{-@ spanByte :: Word8 -> b:ByteString -> (ByteStringPair b) @-}-spanByte :: Word8 -> ByteString -> (ByteString, ByteString)-spanByte c ps@(PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->- go (p `plusPtr` s) 0- where- STRICT2(go)- go p i | i >= l = return (ps, empty)- | otherwise = do c' <- peekByteOff p i- if c /= c'- then return (unsafeTake i ps, unsafeDrop i ps)- else go p (i+1)-{-# INLINE spanByte #-}--{-# RULES-"FPS specialise span (x==)" forall x.- span ((==) x) = spanByte x-"FPS specialise span (==x)" forall x.- span (==x) = spanByte x- #-}---- | 'spanEnd' behaves like 'span' but from the end of the 'ByteString'.--- We have------ > spanEnd (not.isSpace) "x y z" == ("x y ","z")------ and------ > spanEnd (not . isSpace) ps--- > == --- > let (x,y) = span (not.isSpace) (reverse ps) in (reverse y, reverse x) ----{-@ spanEnd :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b) @-}-spanEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-spanEnd p ps = splitAt (findFromEndUntil (not . p) ps) ps---- | /O(n)/ Splits a 'ByteString' into components delimited by--- separators, where the predicate returns True for a separator element.--- The resulting components do not contain the separators. Two adjacent--- separators result in an empty component in the output. eg.------ > splitWith (=='a') "aabbaca" == ["","","bb","c",""]--- > splitWith (=='a') [] == []------ LIQUID: instead of NE, return [empty] in 0 case, or complicate spec.-{-@ splitWith :: (Word8 -> Bool) -> b:ByteStringNE -> (ByteStringSplit b) @-}-splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]--#if defined(__GLASGOW_HASKELL__)-splitWith _pred (PS _ _ 0) = []-splitWith pred_ (PS fp off lenAAA) = splitWith0 pred# off lenAAA fp- where pred# c# = pred_ (W8# c#)-- STRICT4(splitWith0)- splitWith0 pred' off' len' fp' = withPtr fp $ \p ->- splitLoop pred' p 0 off' len' fp'-- splitLoop :: (Word# -> Bool)- -> Ptr Word8- -> Int -> Int -> Int- -> ForeignPtr Word8- -> IO [ByteString]-- splitLoop pred' p idx' off' len' fp'- | pred' `seq` p `seq` idx' `seq` off' `seq` len' `seq` fp' `seq` False = undefined- | idx' >= len' = return [PS fp' off' idx']- | otherwise = do- w <- peekElemOff p (off'+idx')- if pred' (case w of W8# w# -> w#)- then return (PS fp' off' idx' :- splitWith0 pred' (off'+idx'+1) (len'-idx'-1) fp')- else splitLoop pred' p (idx'+1) off' len' fp'-{-# INLINE splitWith #-}--#else-splitWith _ (PS _ _ 0) = []-splitWith p ps = loop p ps- where- STRICT2(loop)- loop q qs = if null rest then [chunk]- else chunk : loop q (unsafeTail rest)- where (chunk,rest) = break q qs-#endif---- | /O(n)/ Break a 'ByteString' into pieces separated by the byte--- argument, consuming the delimiter. I.e.------ > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]--- > split 'a' "aXaXaXa" == ["","X","X","X",""]--- > split 'x' "x" == ["",""]--- --- and------ > intercalate [c] . split c == id--- > split == splitWith . (==)--- --- As for all splitting functions in this library, this function does--- not copy the substrings, it just constructs new 'ByteStrings' that--- are slices of the original.----{-@ split :: Word8 -> b:ByteStringNE -> (ByteStringSplit b) @-}-split :: Word8 -> ByteString -> [ByteString]-split _ (PS _ _ 0) = []-split w (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let ptr = p `plusPtr` s- STRICT1(loop)- loop n =- -- LIQUID: else lose `plen` info due to subsequent @ Word8 application- let ptrn = (ptr `plusPtr` n) :: Ptr Word8 - q = inlinePerformIO $ memchr ptrn {- (ptr `plusPtr` n) -}- w (fromIntegral (l-n))- in if isNullPtr q {- LIQUID q == nullPtr -}- then [PS x (s+n) (l-n)]- else let i = q `minusPtr` ptr in PS x (s+n) (i-n) : loop (i+1)-- return (loop 0)-{-# INLINE split #-}---- A longer split out version of the above with explicit type--- annotations...-{-@ splitO :: Word8 -> b:ByteStringNE -> (ByteStringSplit b) @-}-splitO _ (PS _ _ 0) = []-splitO w (PS xanadu s l) = inlinePerformIO $ withForeignPtr xanadu $ \pz -> do- let p = liquidAssert (fpLen xanadu == pLen pz) pz- let ptrGOBBLE_ = p `plusPtr` s- let ptrGOBBLE = liquidAssert (l <= pLen ptrGOBBLE_) ptrGOBBLE_ - return (splitLoop xanadu ptrGOBBLE w l s 0)--{-@ splitLoop :: fp:(ForeignPtr Word8) - -> p:(Ptr Word8) - -> Word8 - -> l:{v:Nat | v <= (plen p)} - -> s:{v:Nat | v + l <= (fplen fp)}- -> n:{v:Nat | v <= l} - -> {v:[ByteString] | (bLengths v) + (len v) - 1 = l - n} - @-}-splitLoop :: ForeignPtr Word8 -> Ptr Word8 -> Word8 -> Int -> Int -> Int -> [ByteString]-splitLoop xanadu ptrGOBBLE w l s n = - let ptrn = ((ptrGOBBLE `plusPtr` n) :: Ptr Word8) - -- NEEDED: else lose `plen` information without cast- -- thanks to subsequent @ Word8 application- q = inlinePerformIO $ memchr ptrn w (fromIntegral (l-n))- in if isNullPtr q {- LIQUID q == nullPtr -}- then [PS xanadu (s+n) (l-n)]- else let i' = q `minusPtr` ptrGOBBLE- i = liquidAssert (n <= i' && i' < l) i'- in PS xanadu (s+n) (i-n) : splitLoop xanadu ptrGOBBLE w l s (i+1)---{---- slower. but stays inside Haskell.-split _ (PS _ _ 0) = []-split (W8# w#) (PS fp off len) = splitWith' off len fp- where- splitWith' off' len' fp' = withPtr fp $ \p ->- splitLoop p 0 off' len' fp'-- splitLoop :: Ptr Word8- -> Int -> Int -> Int- -> ForeignPtr Word8- -> IO [ByteString]-- STRICT5(splitLoop)- splitLoop p idx' off' len' fp'- | p `seq` idx' `seq` off' `seq` len' `seq` fp' `seq` False = undefined- | idx' >= len' = return [PS fp' off' idx']- | otherwise = do- (W8# x#) <- peekElemOff p (off'+idx')- if word2Int# w# ==# word2Int# x#- then return (PS fp' off' idx' :- splitWith' (off'+idx'+1) (len'-idx'-1) fp')- else splitLoop p (idx'+1) off' len' fp'--}--{---- | Like 'splitWith', except that sequences of adjacent separators are--- treated as a single separator. eg.--- --- > tokens (=='a') "aabbaca" == ["bb","c"]----tokens :: (Word8 -> Bool) -> ByteString -> [ByteString]-tokens f = P.filter (not.null) . splitWith f-{-# INLINE tokens #-}--}---- | The 'group' function takes a ByteString and returns a list of--- ByteStrings such that the concatenation of the result is equal to the--- argument. Moreover, each sublist in the result contains only equal--- elements. For example,------ > group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]------ It is a special case of 'groupBy', which allows the programmer to--- supply their own equality test. It is about 40% faster than --- /groupBy (==)/-{-@ group :: b:ByteString -> {v: [ByteStringNE] | (bLengths v) = (bLength b)} @-}-group :: ByteString -> [ByteString]-group xs- | null xs = []- | otherwise = let y = unsafeHead xs- (ys, zs) = spanByte (unsafeHead xs) (unsafeTail xs)- in (y `cons` ys) : group zs- -- LIQUID FIXME: a better spec for spanByte would say that if x- -- occurs at the head of xs, then `spanByte x xs` will return a- -- non-empty bytestring- -- LIQUID where- -- LIQUID (ys, zs) = spanByte (unsafeHead xs) xs----- | The 'groupBy' function is the non-overloaded version of 'group'.-{-@ groupBy :: (Word8 -> Word8 -> Bool) -> b:ByteString -> {v:[ByteStringNE] | (bLengths v) = (bLength b)} @-}-groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]-groupBy k xs- | null xs = []- | otherwise = let n = 1 + findIndexOrEnd (not . k (unsafeHead xs)) (unsafeTail xs) in- unsafeTake n xs : groupBy k (unsafeDrop n xs)- -- LIQUID LAZY: where- -- LIQUID LAZY: n = 1 + findIndexOrEnd (not . k (unsafeHead xs)) (unsafeTail xs)---- | /O(n)/ The 'intercalate' function takes a 'ByteString' and a list of--- 'ByteString's and concatenates the list after interspersing the first--- argument between each element of the list.--- LIQUID FAIL: NonLinear Invariant. --- LIQUID {- intercalate :: b:ByteString --- LIQUID -> bs:[ByteString] --- LIQUID -> {v:ByteString | (bLength v) = (bLengths bs) + ((len bs) - 1) * (bLength b)} -}--- LIQUID: If we INLINE intersperse then can show simpler--- LIQUID {- intersperse :: ByteString -> bs:[ByteString] -> {v:ByteString | (bLengths bs) <= (bLength v)}-intercalate :: ByteString -> [ByteString] -> ByteString-intercalate s = concat . (List.intersperse s)-{-# INLINE [1] intercalate #-}--join :: ByteString -> [ByteString] -> ByteString-join = intercalate-{-# DEPRECATED join "use intercalate" #-}--{-# RULES-"FPS specialise intercalate c -> intercalateByte" forall c s1 s2 .- intercalate (singleton c) (s1 : s2 : []) = intercalateWithByte c s1 s2- #-}---- | /O(n)/ intercalateWithByte. An efficient way to join to two ByteStrings--- with a char. Around 4 times faster than the generalised join.-----{-@ intercalateWithByte :: Word8 -> f:ByteString -> g:ByteString -> {v:ByteString | (bLength v) = (bLength f) + (bLength g) + 1} @-}-intercalateWithByte :: Word8 -> ByteString -> ByteString -> ByteString-intercalateWithByte c f@(PS ffp s l) g@(PS fgp t m) = unsafeCreate lenBBB $ \ptr ->- withForeignPtr ffp $ \fp ->- withForeignPtr fgp $ \gp -> do- memcpy ptr (fp `plusPtr` s) (fromIntegral l)- poke (ptr `plusPtr` l) c- memcpy (ptr `plusPtr` (l + 1)) (gp `plusPtr` t) (fromIntegral m)- where- lenBBB = length f + length g + 1-{-# INLINE intercalateWithByte #-}---- ------------------------------------------------------------------------ Indexing ByteStrings---- | /O(1)/ 'ByteString' index (subscript) operator, starting from 0.-{-@ index :: b:ByteString -> {v:Nat | v < (bLength b)} -> Word8 @-}-index :: ByteString -> Int -> Word8-index ps n- | n < 0 = moduleError "index" ("negative index: " ++ show n)- | n >= length ps = moduleError "index" ("index too large: " ++ show n- ++ ", length = " ++ show (length ps))- | otherwise = ps `unsafeIndex` n-{-# INLINE index #-}----- | /O(n)/ The 'elemIndex' function returns the index of the first--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. --- This implementation uses memchr(3).--{-@ elemIndex :: Word8 -> b:ByteString -> Maybe {v:Nat | v < (bLength b)} @-}-elemIndex :: Word8 -> ByteString -> Maybe Int-elemIndex c (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let p' = p `plusPtr` s- q <- memchr p' c (fromIntegral l)- return $! if isNullPtr q {- LIQUID: q == nullPtr -} then Nothing else Just $! q `minusPtr` p'-{-# INLINE elemIndex #-}---- | /O(n)/ The 'elemIndexEnd' function returns the last index of the--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. The following--- holds:------ > elemIndexEnd c xs == --- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)----{-@ elemIndexEnd :: Word8 -> b:ByteString -> Maybe {v:Nat | v < (bLength b) } @-}-elemIndexEnd :: Word8 -> ByteString -> Maybe Int-elemIndexEnd ch (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->- go (p `plusPtr` s) (l-1)- where- STRICT2(go)- go p i | i < 0 = return Nothing- | otherwise = do ch' <- peekByteOff p i- if ch == ch'- then return $ Just i- else go p (i-1)-{-# INLINE elemIndexEnd #-}---- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning--- the indices of all elements equal to the query element, in ascending order.--- This implementation uses memchr(3).-{-@ elemIndices :: Word8 -> b:ByteString -> [{v:Nat | v < (bLength b) }] @-}-elemIndices :: Word8 -> ByteString -> [Int]-elemIndices w (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let ptr = p `plusPtr` s-- STRICT1(loop)- loop n = let pn = ((ptr `plusPtr` n) :: Ptr Word8) -- LIQUID CAST- q = inlinePerformIO $ memchr pn- w (fromIntegral (l - n))- in if isNullPtr q {- == nullPtr -} -- LIQUID NULLPTR- then []- else let i = q `minusPtr` ptr- in i : loop (i+1)- return $! loop 0-{-# INLINE elemIndices #-}--{---- much slower-elemIndices :: Word8 -> ByteString -> [Int]-elemIndices c ps = loop 0 ps- where STRICT2(loop)- loop _ ps' | null ps' = []- loop n ps' | c == unsafeHead ps' = n : loop (n+1) (unsafeTail ps')- | otherwise = loop (n+1) (unsafeTail ps')--}---- | count returns the number of times its argument appears in the ByteString------ > count = length . elemIndices------ But more efficiently than using length on the intermediate list.-{-@ count :: Word8 -> b:ByteString -> {v:Nat | v <= (bLength b) } @-}-count :: Word8 -> ByteString -> Int-count w (PS x s m) = inlinePerformIO $ withForeignPtr x $ \p ->- fmap fromIntegral $ c_count (p `plusPtr` s) (fromIntegral m) w-{-# INLINE count #-}--{------- around 30% slower----count w (PS x s m) = inlinePerformIO $ withForeignPtr x $ \p ->- go (p `plusPtr` s) (fromIntegral m) 0- where- go :: Ptr Word8 -> CSize -> Int -> IO Int- STRICT3(go)- go p l i = do- q <- memchr p w l- if q == nullPtr- then return i- else do let k = fromIntegral $ q `minusPtr` p- go (q `plusPtr` 1) (l-k-1) (i+1)--}---- | The 'findIndex' function takes a predicate and a 'ByteString' and--- returns the index of the first element in the ByteString--- satisfying the predicate.-{-@ findIndex :: (Word8 -> Bool) -> b:ByteString -> (Maybe {v:Nat | v < (bLength b)}) @-}-findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int-findIndex k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go (f `plusPtr` s) 0- where- STRICT2(go)- go ptr n | n >= l = return Nothing- | otherwise = do w <- peek ptr- if k w- then return (Just n)- else go (ptr `plusPtr` 1) (n+1)-{-# INLINE findIndex #-}---- | The 'findIndices' function extends 'findIndex', by returning the--- indices of all elements satisfying the predicate, in ascending order.-{-@ findIndices :: (Word8 -> Bool) -> b:ByteString -> [{v:Nat | v < (bLength b)}] @-}-findIndices :: (Word8 -> Bool) -> ByteString -> [Int]-findIndices p ps = loop 0 ps- where- STRICT2(loop)- loop (n :: Int) qs -- LIQUID CAST - | null qs = []- | p (unsafeHead qs) = n : loop (n+1) (unsafeTail qs)- | otherwise = loop (n+1) (unsafeTail qs)---- ------------------------------------------------------------------------ Searching ByteStrings---- | /O(n)/ 'elem' is the 'ByteString' membership predicate.-elem :: Word8 -> ByteString -> Bool-elem c ps = case elemIndex c ps of Nothing -> False ; _ -> True-{-# INLINE elem #-}---- | /O(n)/ 'notElem' is the inverse of 'elem'-notElem :: Word8 -> ByteString -> Bool-notElem c ps = not (elem c ps)-{-# INLINE notElem #-}---- | /O(n)/ 'filter', applied to a predicate and a ByteString,--- returns a ByteString containing those characters that satisfy the--- predicate. This function is subject to array fusion.-{-@ qualif FilterLoop(v:Ptr a, f:Ptr a, t:Ptr a):- (plen t) >= (plen f) - (plen v) @-}-{-@ filter :: (Word8 -> Bool) -> b:ByteString -> (ByteStringLE b) @-}-filter :: (Word8 -> Bool) -> ByteString -> ByteString-filter k ps@(PS x s l)- | null ps = ps- | otherwise = unsafePerformIO $ createAndTrim l $ \p -> withForeignPtr x $ \f -> do- t <- go (f `plusPtr` s) p (f `plusPtr` (s + l))- return $! t `minusPtr` p -- actual length- where- STRICT3(go)- go f' t end | f' == end = return t- | otherwise = do- let f = liquid_thm_ptr_cmp f' end -- LIQUID THEOREM- w <- peek f- if k w- then poke t w >> go (f `plusPtr` 1) (t `plusPtr` 1) end- else go (f `plusPtr` 1) t end-#if __GLASGOW_HASKELL__-{-# INLINE [1] filter #-}-#endif----- | /O(n)/ A first order equivalent of /filter . (==)/, for the common--- case of filtering a single byte. It is more efficient to use--- /filterByte/ in this case.------ > filterByte == filter . (==)------ filterByte is around 10x faster, and uses much less space, than its--- filter equivalent----{-@ filterByte :: Word8 -> b:ByteString -> {v:ByteString | (bLength v) <= (bLength b)} @-}-filterByte :: Word8 -> ByteString -> ByteString-filterByte w ps = replicate (count w ps) w-{-# INLINE filterByte #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter ((==) x) = filterByte x- #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter (== x) = filterByte x- #-}---- | /O(n)/ The 'find' function takes a predicate and a ByteString,--- and returns the first element in matching the predicate, or 'Nothing'--- if there is no such element.------ > find f p = case findIndex f p of Just n -> Just (p ! n) ; _ -> Nothing----find :: (Word8 -> Bool) -> ByteString -> Maybe Word8-find f p = case findIndex f p of- Just n -> Just (p `unsafeIndex` n)- _ -> Nothing-{-# INLINE find #-}--{------- fuseable, but we don't want to walk the whole array.--- -find k = foldl findEFL Nothing- where findEFL a@(Just _) _ = a- findEFL _ c | k c = Just c- | otherwise = Nothing--}---- | /O(n)/ The 'partition' function takes a predicate a ByteString and returns--- the pair of ByteStrings with elements which do and do not satisfy the--- predicate, respectively; i.e.,------ > partition p bs == (filter p xs, filter (not . p) xs)------ LIQUID FAIL: partition :: (Word8 -> Bool) -> b:ByteString -> (ByteStringPair b)-{-@ partition :: (Word8 -> Bool) -> b:ByteString -> ((ByteStringLE b), (ByteStringLE b)) @-}-partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-partition p bs = (filter p bs, filter (not . p) bs)---TODO: use a better implementation---- ------------------------------------------------------------------------ Searching for substrings---- | /O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'--- iff the first is a prefix of the second.-{-@ isPrefixOf :: ByteString -> ByteString -> Bool @-}-isPrefixOf :: ByteString -> ByteString -> Bool-isPrefixOf (PS x1 s1 l1) (PS x2 s2 l2)- | l1 == 0 = True- | l2 < l1 = False- | otherwise = inlinePerformIO $ withForeignPtr x1 $ \p1 ->- withForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral l1)- return $! i == 0---- | /O(n)/ The 'isSuffixOf' function takes two ByteStrings and returns 'True'--- iff the first is a suffix of the second.--- --- The following holds:------ > isSuffixOf x y == reverse x `isPrefixOf` reverse y------ However, the real implemenation uses memcmp to compare the end of the--- string only, with no reverse required..-{-@ isSuffixOf :: ByteString -> ByteString -> Bool @-}-isSuffixOf :: ByteString -> ByteString -> Bool-isSuffixOf (PS x1 s1 l1) (PS x2 s2 l2)- | l1 == 0 = True- | l2 < l1 = False- | otherwise = inlinePerformIO $ withForeignPtr x1 $ \p1 ->- withForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2 `plusPtr` (l2 - l1)) (fromIntegral l1)- return $! i == 0---- | Alias of 'isSubstringOf'-isInfixOf :: ByteString -> ByteString -> Bool-isInfixOf = isSubstringOf---- | Check whether one string is a substring of another. @isSubstringOf--- p s@ is equivalent to @not (null (findSubstrings p s))@.-isSubstringOf :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to search in.- -> Bool-isSubstringOf p s = not $ P.null $ findSubstrings p s--{-# DEPRECATED findSubstring "Do not use. The ByteString searching api is about to be replaced." #-}--- | Get the first index of a substring in another string,--- or 'Nothing' if the string is not found.--- @findSubstring p s@ is equivalent to @listToMaybe (findSubstrings p s)@.-{-@ findSubstring :: pat:ByteString -> str:ByteString -> (Maybe {v:Nat | v <= (bLength str)}) @-}-findSubstring :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to seach in.- -> Maybe Int--- LIQUID ETA: findSubstring = (listToMaybe .) . findSubstrings-findSubstring pat str = listToMaybe $ findSubstrings pat str---{-# DEPRECATED findSubstrings "Do not use. The ByteString searching api is about to be replaced." #-}--- | Find the indexes of all (possibly overlapping) occurances of a--- substring in a string. This function uses the Knuth-Morris-Pratt--- string matching algorithm.--{-@ qualif FindIndices(v:Data.ByteString.Internal.ByteString,- p:Data.ByteString.Internal.ByteString,- n:int):- (bLength v) = (bLength p) - n @-}--{-@ findSubstrings :: pat:ByteString -> str:ByteString -> [{v:Nat | v <= (bLength str)}] @-}--findSubstrings :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to seach in.- -> [Int]---- LIQUID LATEST -findSubstrings pat str- | null pat = rng (length str - 1) -- LIQUID COMPREHENSIONS [0 .. (length str - 1)]- | otherwise = search 0 str- where- STRICT2(search)- search (n :: Int) s- | null s = []- | pat `isPrefixOf` s = n : search (n+1) (unsafeTail s)- | otherwise = search (n+1) (unsafeTail s)---{- -findSubstrings pat@(PS _ _ m) str@(PS _ _ n) = search 0 0- where- patc x = pat `unsafeIndex` x- strc x = str `unsafeIndex` x-- -- maybe we should make kmpNext a UArray before using it in search?- kmpNext = listArray (0,m) (-1:kmpNextL pat (-1))- kmpNextL p _ | null p = []- kmpNextL p j = let j' = next (unsafeHead p) j + 1- ps = unsafeTail p- x = if not (null ps) && unsafeHead ps == patc j'- then kmpNext Array.! j' else j'- in x:kmpNextL ps j'- search i j = match ++ rest -- i: position in string, j: position in pattern- where match = if j == m then [(i - j)] else []- rest = if i == n then [] else search (i+1) (next (strc i) j + 1)- next c j | j >= 0 && (j == m || c /= patc j) = next c (kmpNext Array.! j)- | otherwise = j--}---- LIQUID: added to latest API-{-@ breakSubstring :: ByteString -> b:ByteString -> (ByteStringPair b) @-}--breakSubstring :: ByteString -- ^ String to search for- -> ByteString -- ^ String to search in- -> (ByteString,ByteString) -- ^ Head and tail of string broken at substring--breakSubstring pat src = search 0 src- where- STRICT2(search)- search n s- | null s = (src, empty) -- not found- | pat `isPrefixOf` s = (take n src,s)- | otherwise = search (n+1) (unsafeTail s)------ ------------------------------------------------------------------------ Zipping---- | /O(n)/ 'zip' takes two ByteStrings and returns a list of--- corresponding pairs of bytes. If one input ByteString is short,--- excess elements of the longer ByteString are discarded. This is--- equivalent to a pair of 'unpack' operations.--{-@ predicate ZipLen V X Y = (len V) = (if (bLength X) <= (bLength Y) then (bLength X) else (bLength Y)) @-}-{-@ zip :: x:ByteString -> y:ByteString -> {v:[(Word8, Word8)] | (ZipLen v x y) } @-}-zip :: ByteString -> ByteString -> [(Word8,Word8)]-zip ps qs- | null ps || null qs = []- | otherwise = (unsafeHead ps, unsafeHead qs) : zip (unsafeTail ps) (unsafeTail qs)---- | 'zipWith' generalises 'zip' by zipping with the function given as--- the first argument, instead of a tupling function. For example,--- @'zipWith' (+)@ is applied to two ByteStrings to produce the list of--- corresponding sums. -{-@ zipWith :: (Word8 -> Word8 -> a) -> x:ByteString -> y:ByteString -> {v:[a] | (ZipLen v x y)} @-}-zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]-zipWith f ps qs- | null ps || null qs = []- | otherwise = f (unsafeHead ps) (unsafeHead qs) : zipWith f (unsafeTail ps) (unsafeTail qs)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] zipWith #-}-#endif----- | A specialised version of zipWith for the common case of a--- simultaneous map over two bytestrings, to build a 3rd. Rewrite rules--- are used to automatically covert zipWith into zipWith' when a pack is--- performed on the result of zipWith, but we also export it for--- convenience.---- LIQUID NICE-INFERENCE-EXAMPLE! -{-@ predicate ZipLenB V X Y = (bLength V) = (if (bLength X) <= (bLength Y) then (bLength X) else (bLength Y)) @-}-{-@ zipWith' :: (Word8 -> Word8 -> Word8) -> x:ByteString -> y:ByteString -> {v:ByteString | (ZipLenB v x y)} @-}-zipWith' :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString-zipWith' f (PS fp s l) (PS fq t m) = inlinePerformIO $- withForeignPtr fp $ \a ->- withForeignPtr fq $ \b ->- create lenCCC $ zipWith_ 0 (a `plusPtr` s) (b `plusPtr` t)- where- zipWith_ :: Int -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> IO ()- STRICT4(zipWith_)- zipWith_ n p1 p2 r- | n >= lenCCC = return ()- | otherwise = do- x <- peekByteOff p1 n- y <- peekByteOff p2 n- pokeByteOff r n (f x y)- zipWith_ (n+1) p1 p2 r-- lenCCC = min l m-{-# INLINE zipWith' #-}--{-# RULES--"FPS specialise zipWith" forall (f :: Word8 -> Word8 -> Word8) p q .- zipWith f p q = unpack (zipWith' f p q)-- #-}---- | /O(n)/ 'unzip' transforms a list of pairs of bytes into a pair of--- ByteStrings. Note that this performs two 'pack' operations.-{-@ unzip :: z:[(Word8,Word8)] -> ({v:ByteString | (bLength v) = (len z)}, {v:ByteString | (bLength v) = (len z) }) @-}-unzip :: [(Word8,Word8)] -> (ByteString,ByteString)-unzip ls = (pack (P.map fst ls), pack (P.map snd ls))-{-# INLINE unzip #-}- --- ------------------------------------------------------------------------ Special lists---- | /O(n)/ Return all initial segments of the given 'ByteString', shortest first.-{-@ inits :: b:ByteString -> [{v1:ByteString | (bLength v1) <= (bLength b)}]<{\ix iy -> (bLength ix) < (bLength iy)}> @-}-inits :: ByteString -> [ByteString]---LIQUID INLINE inits (PS x s l) = [PS x s n | n <- [0..l]]-inits (PS x s l) = PS x s 0 : go 0 (rng 1 l)- where go _ [] = []- go n0 (n:ns) = PS x s n : go n ns- rng a b | a > b = []- | otherwise = a : rng (a+1) b--{- rng :: n:Nat -> {v:[{v1:Nat | v1 <= n }] | (len v) = n + 1} @-}-rng :: Int -> [Int]-rng 0 = [0]-rng n = n : rng (n-1) ----- | /O(n)/ Return all final segments of the given 'ByteString', longest first.-{- tails :: b:ByteString -> {v:[{v1:ByteString | (bLength v1) <= (bLength b)}] | (len v) = 1 + (bLength b)} @-}-tails :: ByteString -> [ByteString]-tails p | null p = [empty]- | otherwise = p : tails (unsafeTail p)---- less efficent spacewise: tails (PS x s l) = [PS x (s+n) (l-n) | n <- [0..l]]----- ------------------------------------------------------------------------ ** Ordered 'ByteString's---- | /O(n)/ Sort a ByteString efficiently, using counting sort.--- LIQUID FAIL: requires invariant that SUM of cells in intermediate array--- equals total len of outer array. WHOA. Due to Ptr issue, this gets--- "proved" safe. Oh boy. Still, can prove that output size = input size.----LIQUID sortCanary :: Int -> Int---LIQUID sortCanary x = liquidAssert (0 == 1) x--sort :: ByteString -> ByteString-sort (PS input s l) = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do-- memset (castPtr arr) 0 (256 * fromIntegral (sizeOf (undefined :: CSize)))- withForeignPtr input (\x -> countOccurrences arr (x `plusPtr` s) l)-- let STRICT2(go)- go 256 _ = return ()- go i ptr = do n <- peekElemOff arr i- when (n /= 0) $ memset ptr (fromIntegral i) n >> return ()- go (i + 1) (ptr `plusPtr` (fromIntegral n))- go 0 p- where- -- | Count the number of occurrences of each byte.- -- Used by 'sort'- --- countOccurrences :: Ptr CSize -> Ptr Word8 -> Int -> IO ()- STRICT3(countOccurrences)- countOccurrences counts str lenDDD = go 0- where- STRICT1(go)- go i | i == lenDDD = return ()- | otherwise = do k <- fromIntegral `fmap` peekElemOff str i- x <- peekElemOff counts k- pokeElemOff counts k (x + 1)- go (i + 1)--{--sort :: ByteString -> ByteString-sort (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f -> do- memcpy p (f `plusPtr` s) l- c_qsort p l -- inplace--}---- The 'sortBy' function is the non-overloaded version of 'sort'.------ Try some linear sorts: radix, counting--- Or mergesort.------ sortBy :: (Word8 -> Word8 -> Ordering) -> ByteString -> ByteString--- sortBy f ps = undefined---- ------------------------------------------------------------------------ Low level constructors---- | /O(n) construction/ Use a @ByteString@ with a function requiring a--- null-terminated @CString@. The @CString@ will be freed--- automatically. This is a memcpy(3).-{-@ useAsCString :: p:_ -> ({v:_ | (bLength p) + 1 = (plen v)} -> IO a) -> IO a @-}-useAsCString :: ByteString -> (CString -> IO a) -> IO a-useAsCString (PS fp o l) action = do- allocaBytes (l+1) $ \buf ->- withForeignPtr fp $ \p -> do- memcpy buf (p `plusPtr` o) (fromIntegral l)- pokeByteOff buf l (0::Word8)- action (castPtr buf)---- | /O(n) construction/ Use a @ByteString@ with a function requiring a @CStringLen@.--- As for @useAsCString@ this function makes a copy of the original @ByteString@.-{-@ useAsCStringLen :: b:_ -> ({v:_ | (cStringLen v) = (bLength b)} -> IO a) -> IO a @-}-useAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a-useAsCStringLen p@(PS _ _ l) f = useAsCString p $ \cstr -> f (cstr,l)------------------------------------------------------------------------------ | /O(n)./ Construct a new @ByteString@ from a @CString@. The--- resulting @ByteString@ is an immutable copy of the original--- @CString@, and is managed on the Haskell heap. The original--- @CString@ must be null terminated.--{-@ packCString :: c:_ -> IO {v:_ | (bLength v) = (plen c)} @-}-packCString :: CString -> IO ByteString-packCString cstr = do- lenEEE <- c_strlen cstr- packCStringLen (cstr, fromIntegral lenEEE)---- | /O(n)./ Construct a new @ByteString@ from a @CStringLen@. The--- resulting @ByteString@ is an immutable copy of the original @CStringLen@.--- The @ByteString@ is a normal Haskell value and will be managed on the--- Haskell heap.-{- packCStringLen :: c:_ -> (IO {v:_ | (bLength v) = (cStringLen c)}) @-}-{-@ packCStringLen :: c:CStringLen -> (IO {v:ByteString | (bLength v) = (cStringLen c)}) @-}-packCStringLen :: CStringLen -> IO ByteString-packCStringLen (cstr, lenFFF) = create lenFFF $ \p ->- memcpy p (castPtr cstr) (fromIntegral lenFFF)------------------------------------------------------------------------------ | /O(n)/ Make a copy of the 'ByteString' with its own storage. --- This is mainly useful to allow the rest of the data pointed--- to by the 'ByteString' to be garbage collected, for example--- if a large string has been read in, and only a small part of it --- is needed in the rest of the program.--- -{-@ copy :: b:ByteString -> (ByteStringSZ b) @-}-copy :: ByteString -> ByteString-copy (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->- memcpy p (f `plusPtr` s) (fromIntegral l)---- ------------------------------------------------------------------------ line IO---- | Read a line from stdin.-getLine :: IO ByteString-getLine = hGetLine stdin--{---- | Lazily construct a list of lines of ByteStrings. This will be much--- better on memory consumption than using 'hGetContents >>= lines'--- If you're considering this, a better choice might be to use--- Data.ByteString.Lazy-hGetLines :: Handle -> IO [ByteString]-hGetLines h = go- where- go = unsafeInterleaveIO $ do- e <- hIsEOF h- if e- then return []- else do- x <- hGetLine h- xs <- go- return (x:xs)--}---- | Read a line from a handle--hGetLine :: Handle -> IO ByteString-#if !defined(__GLASGOW_HASKELL__)-hGetLine h = System.IO.hGetLine h >>= return . pack . P.map c2w-#else-hGetLine h = wantReadableHandleLIQUID "Data.ByteString.hGetLine" h $ \ handle_ -> do- case haBufferMode handle_ of- NoBuffering -> error "no buffering"- _other -> hGetLineBuffered handle_-- where- hGetLineBuffered handle_ = do- let ref = haCharBuffer handle_- buf <- readIORef ref- hGetLineBufferedLoop handle_ ref buf 0 []-- hGetLineBufferedLoop handle_ ref- buf@Buffer{ bufL=r, bufR=w, bufRaw=raw } lenGGG xss =- lenGGG `seq` do- off <- findEOL r w raw- let new_len = lenGGG + off - r- xs <- mkPS raw r off-- -- if eol == True, then off is the offset of the '\n'- -- otherwise off == w and the buffer is now empty.- if off /= w- then do if (w == off + 1)- then writeIORef ref buf{ bufL=0, bufR=0 }- else writeIORef ref buf{ bufL = off + 1 }- mkBigPS new_len (xs:xss)- else do- maybe_buf <- maybeFillReadBuffer ({- LIQUID COMPAT: haFD -} handle_) True ({- LIQUID COMPAT: haIsStream -} handle_)- buf{ bufR=0, bufL=0 }- case maybe_buf of- -- Nothing indicates we caught an EOF, and we may have a- -- partial line to return.- Nothing -> do- writeIORef ref buf{ bufL=0, bufR=0 }- if new_len > 0- then mkBigPS new_len (xs:xss)- else error "LIQUIDCOMPAT" -- ioe_EOF- Just new_buf ->- hGetLineBufferedLoop handle_ ref new_buf new_len (xs:xss)-- -- find the end-of-line character, if there is one- findEOL r w raw- | r == w = return w- | otherwise = do- (c,r') <- readCharFromBuffer raw r- if c == '\n'- then return r -- NB. not r': don't include the '\n'- else findEOL r' w raw-- -- LIQUID COMPAT- maybeFillReadBuffer fd is_line is_stream buf = return Nothing- -- maybeFillReadBuffer fd is_line is_stream buf = catch- -- (do buf' <- fillReadBuffer fd is_line is_stream buf- -- return (Just buf'))- -- (\e -> if isEOFError e then return Nothing else ioError e)---- TODO, rewrite to use normal memcpy-mkPS :: RawBuffer Char -> Int -> Int -> IO ByteString-mkPS buf start end =- let lenXXX = end - start- in create lenXXX $ \p -> do- memcpy_ptr_baoff p buf (fromIntegral start) ({- LIQUID fromIntegral-} intCSize lenXXX)- return ()----mkBigPS :: Int -> [ByteString] -> IO ByteString-mkBigPS _ [ps] = return ps-mkBigPS _ pss = return $! concat (P.reverse pss)--#endif---- ------------------------------------------------------------------------ Block IO---- | Outputs a 'ByteString' to the specified 'Handle'.-hPut :: Handle -> ByteString -> IO ()-hPut _ (PS _ _ 0) = return ()-hPut h (PS ps s l) = withForeignPtr ps $ \p-> hPutBuf h (p `plusPtr` s) l---- | A synonym for @hPut@, for compatibility -hPutStr :: Handle -> ByteString -> IO ()-hPutStr = hPut---- | Write a ByteString to a handle, appending a newline byte-hPutStrLn :: Handle -> ByteString -> IO ()-hPutStrLn h ps- | length ps < 1024 = hPut h (ps `snoc` 0x0a)- | otherwise = hPut h ps >> hPut h (singleton (0x0a)) -- don't copy---- | Write a ByteString to stdout-putStr :: ByteString -> IO ()-putStr = hPut stdout---- | Write a ByteString to stdout, appending a newline byte-putStrLn :: ByteString -> IO ()-putStrLn = hPutStrLn stdout---- | Read a 'ByteString' directly from the specified 'Handle'. This--- is far more efficient than reading the characters into a 'String'--- and then using 'pack'.-{-@ hGet :: Handle -> n:Nat -> IO {v:ByteString | (bLength v) <= n} @-}-hGet :: Handle -> Int -> IO ByteString-hGet _ 0 = return empty-hGet h i = createAndTrim i $ \p -> hGetBuf h p i---- | hGetNonBlocking is identical to 'hGet', except that it will never block--- waiting for data to become available, instead it returns only whatever data--- is available.---{-@ hGetNonBlocking :: Handle -> n:Nat -> IO {v:ByteString | (bLength v) <= n} @-}---hGetNonBlocking :: Handle -> Int -> IO ByteString-#if defined(__GLASGOW_HASKELL__)-hGetNonBlocking _ 0 = return empty-hGetNonBlocking h i = createAndTrim i $ \p -> hGetBufNonBlocking h p i-#else-hGetNonBlocking = hGet-#endif---- | Read entire handle contents into a 'ByteString'.--- This function reads chunks at a time, doubling the chunksize on each--- read. The final buffer is then realloced to the appropriate size. For--- files > half of available memory, this may lead to memory exhaustion.--- Consider using 'readFile' in this case.------ As with 'hGet', the string representation in the file is assumed to--- be ISO-8859-1.--{-@ assume Foreign.Marshal.Alloc.reallocBytes :: p:(Ptr a) -> n:Nat -> (IO (PtrN a n)) @-}-hGetContents :: Handle -> IO ByteString-hGetContents h = do- let start_size = 1024- p <- mallocBytes start_size- i <- hGetBuf h p start_size- if i < start_size- then do p' <- reallocBytes p i- fp <- newForeignPtr finalizerFree p'- return $! PS fp 0 i- else f p start_size- where- f p s = do- let s' = s + s -- 2 * s -- LIQUID MULTIPLY- p' <- reallocBytes p s'- i <- hGetBuf h (p' `plusPtr` s) s- if i < s- then do let i' = s + i- p'' <- reallocBytes p' i'- fp <- newForeignPtr finalizerFree p''- return $! PS fp 0 i'- else f p' s'---- | getContents. Equivalent to hGetContents stdin-getContents :: IO ByteString-getContents = hGetContents stdin---- | The interact function takes a function of type @ByteString -> ByteString@--- as its argument. The entire input from the standard input device is passed--- to this function as its argument, and the resulting string is output on the--- standard output device. It's great for writing one line programs!-interact :: (ByteString -> ByteString) -> IO ()-interact transformer = putStr . transformer =<< getContents---- | Read an entire file strictly into a 'ByteString'. This is far more--- efficient than reading the characters into a 'String' and then using--- 'pack'. It also may be more efficient than opening the file and--- reading it using hGet. Files are read using 'binary mode' on Windows,--- for 'text mode' use the Char8 version of this function.-readFile :: FilePath -> IO ByteString-readFile f = bracket (openBinaryFile f ReadMode) hClose- (\h -> hFileSize h >>= hGet h . fromIntegral)---- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\h -> hPut h txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\h -> hPut h txt)--{------- Disable until we can move it into a portable .hsc file------- | Like readFile, this reads an entire file directly into a--- 'ByteString', but it is even more efficient. It involves directly--- mapping the file to memory. This has the advantage that the contents--- of the file never need to be copied. Also, under memory pressure the--- page may simply be discarded, while in the case of readFile it would--- need to be written to swap. If you read many small files, mmapFile--- will be less memory-efficient than readFile, since each mmapFile--- takes up a separate page of memory. Also, you can run into bus--- errors if the file is modified. As with 'readFile', the string--- representation in the file is assumed to be ISO-8859-1.------ On systems without mmap, this is the same as a readFile.----mmapFile :: FilePath -> IO ByteString-mmapFile f = mmap f >>= \(fp,l) -> return $! PS fp 0 l--mmap :: FilePath -> IO (ForeignPtr Word8, Int)-mmap f = do- h <- openBinaryFile f ReadMode- l <- fromIntegral `fmap` hFileSize h- -- Don't bother mmaping small files because each mmapped file takes up- -- at least one full VM block.- if l < mmap_limit- then do thefp <- mallocByteString l- withForeignPtr thefp $ \p-> hGetBuf h p l- hClose h- return (thefp, l)- else do- -- unix only :(- fd <- fromIntegral `fmap` handleToFd h- p <- my_mmap l fd- fp <- if p == nullPtr- then do thefp <- mallocByteString l- withForeignPtr thefp $ \p' -> hGetBuf h p' l- return thefp- else do- -- The munmap leads to crashes on OpenBSD.- -- maybe there's a use after unmap in there somewhere?- -- Bulat suggests adding the hClose to the- -- finalizer, excellent idea.-#if !defined(__OpenBSD__)- let unmap = c_munmap p l >> return ()-#else- let unmap = return ()-#endif- fp <- newForeignPtr p unmap- return fp- c_close fd- hClose h- return (fp, l)- where mmap_limit = 16*1024--}---- ------------------------------------------------------------------------ Internal utilities---- | 'findIndexOrEnd' is a variant of findIndex, that returns the length--- of the string if no element is found, rather than Nothing.-{-@ findIndexOrEnd :: (Word8 -> Bool) -> b:ByteString -> {v:Nat | v <= (bLength b) } @-}-findIndexOrEnd :: (Word8 -> Bool) -> ByteString -> Int-findIndexOrEnd k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go (f `plusPtr` s) 0- where- STRICT2(go)- go ptr n | n >= l = return l- | otherwise = do w <- peek ptr- if k w- then return n- else go (ptr `plusPtr` 1) (n+1)-{-# INLINE findIndexOrEnd #-}---- | Perform an operation with a temporary ByteString-withPtr :: ForeignPtr a -> (Ptr a -> IO b) -> b-withPtr fp io = inlinePerformIO (withForeignPtr fp io)-{-# INLINE withPtr #-}---- Common up near identical calls to `error' to reduce the number--- constant strings created when compiled:-{-@ errorEmptyList :: {v:String | false} -> a @-}-errorEmptyList :: String -> a-errorEmptyList fun = moduleError fun "empty ByteString"-{-# NOINLINE errorEmptyList #-}--moduleError :: String -> String -> a-moduleError fun msg = error ("Data.ByteString." ++ fun ++ ':':' ':msg)-{-# NOINLINE moduleError #-}---- Find from the end of the string using predicate-{-@ findFromEndUntil :: (Word8 -> Bool) -> b:ByteString -> {v:Nat | v <= (bLength b)} @-}-findFromEndUntil :: (Word8 -> Bool) -> ByteString -> Int-STRICT2(findFromEndUntil)-findFromEndUntil f ps@(PS x s l) =- if null ps then 0- else if f (last ps) then l- else findFromEndUntil f (PS x s (l-1))------ // for unfoldrN -{-@ qualif PLenNat(v:GHC.Ptr.Ptr a): (0 <= plen v) - @-}---- // for UnpackFoldrINLINED-{-@ qualif UnpackFoldrINLINED(v:List a, n:int, acc:List a): (len v = n + 1 + (len acc))- @-}---- // for ByteString.inits-{-@ qualif BLenGt(v:Data.ByteString.Internal.ByteString, n:int): ((bLength v) > n)- @-}---- // for ByteString.concat-{-@ qualif BLens(v:List Data.ByteString.Internal.ByteString) : (0 <= bLengths v)- @-}--{-@ qualif BLenLE(v:GHC.Ptr.Ptr a, bs:List Data.ByteString.Internal.ByteString): (bLengths bs <= plen v) - @-}---- // for ByteString.splitWith-{-@ qualif SplitWith(v:List Data.ByteString.Internal.ByteString, l:int): ((bLengths v) + (len v) - 1 = l)- @-}---- // for ByteString.unfoldrN-{-@ qualif PtrDiff(v:int, i:int, p:GHC.Ptr.Ptr a): (i - v <= plen p)- @-}---- // for ByteString.split-{-@ qualif BSValidOff(v:int,l:int,p:GHC.ForeignPtr.ForeignPtr a): (v + l <= fplen p) - @-}---{-@ qualif SplitLoop(v:List Data.ByteString.Internal.ByteString, l:int, n:int): ((bLengths v) + (len v) - 1 = l - n)- @-}
@@ -1,33 +0,0 @@--// for unfoldrN -qualif PLenNat(v:GHC.Ptr.Ptr a) : (0 <= plen v)--// for UnpackFoldrINLINED-qualif UnpackFoldrINLINED(v:List a, n:int, acc:List a): (len v = n + 1 + (len acc))--// for ByteString.inits-qualif BLenGt(v:Data.ByteString.Internal.ByteString, n:int): ((bLength v) > n)--// for ByteString.concat-qualif BLens(v:List Data.ByteString.Internal.ByteString) : - (0 <= bLengths v)--qualif BLenLE(v:GHC.Ptr.Ptr a, bs:List Data.ByteString.Internal.ByteString):- (bLengths bs <= plen v) --// for ByteString.splitWith-qualif SplitWith(v:List Data.ByteString.Internal.ByteString, l:int):- ((bLengths v) + (len v) - 1 = l)--// for ByteString.unfoldrN-qualif PtrDiff(v:int, i:int, p:GHC.Ptr.Ptr a): - (i - v <= plen p)---// for ByteString.split-qualif BSValidOff(v:int,l:int,p:GHC.ForeignPtr.ForeignPtr a): - (v + l <= fplen p) --qualif SplitLoop(v:List Data.ByteString.Internal.ByteString, l:int, n:int): - ((bLengths v) + (len v) - 1 = l - n)-
@@ -1,1097 +0,0 @@-{-@ LIQUID "--notermination" @-}-{-@ LIQUID "--no-totality" @-}-{-@ LIQUID "--pruneunsorted" @-}---{-# OPTIONS_GHC -cpp -fglasgow-exts #-}---- #prune---- |--- Module : Data.ByteString.Char8--- Copyright : (c) Don Stewart 2006--- License : BSD-style------ Maintainer : dons@cse.unsw.edu.au--- Stability : experimental--- Portability : portable------ Manipulate 'ByteString's using 'Char' operations. All Chars will be--- truncated to 8 bits. It can be expected that these functions will run--- at identical speeds to their 'Word8' equivalents in "Data.ByteString".------ More specifically these byte strings are taken to be in the--- subset of Unicode covered by code points 0-255. This covers--- Unicode Basic Latin, Latin-1 Supplement and C0+C1 Controls.--- --- See: ------ * <http://www.unicode.org/charts/>------ * <http://www.unicode.org/charts/PDF/U0000.pdf>------ * <http://www.unicode.org/charts/PDF/U0080.pdf>------ This module is intended to be imported @qualified@, to avoid name--- clashes with "Prelude" functions. eg.------ > import qualified Data.ByteString.Char8 as B-----module Data.ByteString.Char8 (-- -- * The @ByteString@ type- ByteString, -- abstract, instances: Eq, Ord, Show, Read, Data, Typeable, Monoid-- -- * Introducing and eliminating 'ByteString's- empty, -- :: ByteString- singleton, -- :: Char -> ByteString- pack, -- :: String -> ByteString- unpack, -- :: ByteString -> String-- -- * Basic interface- cons, -- :: Char -> ByteString -> ByteString- snoc, -- :: ByteString -> Char -> ByteString- append, -- :: ByteString -> ByteString -> ByteString- head, -- :: ByteString -> Char- uncons, -- :: ByteString -> Maybe (Char, ByteString)- last, -- :: ByteString -> Char- tail, -- :: ByteString -> ByteString- init, -- :: ByteString -> ByteString- null, -- :: ByteString -> Bool- length, -- :: ByteString -> Int-- -- * Transformating ByteStrings- map, -- :: (Char -> Char) -> ByteString -> ByteString- reverse, -- :: ByteString -> ByteString- intersperse, -- :: Char -> ByteString -> ByteString- intercalate, -- :: ByteString -> [ByteString] -> ByteString- transpose, -- :: [ByteString] -> [ByteString]-- -- * Reducing 'ByteString's (folds)- foldl, -- :: (a -> Char -> a) -> a -> ByteString -> a- foldl', -- :: (a -> Char -> a) -> a -> ByteString -> a- foldl1, -- :: (Char -> Char -> Char) -> ByteString -> Char- foldl1', -- :: (Char -> Char -> Char) -> ByteString -> Char-- foldr, -- :: (Char -> a -> a) -> a -> ByteString -> a- foldr', -- :: (Char -> a -> a) -> a -> ByteString -> a- foldr1, -- :: (Char -> Char -> Char) -> ByteString -> Char- foldr1', -- :: (Char -> Char -> Char) -> ByteString -> Char-- -- ** Special folds- concat, -- :: [ByteString] -> ByteString- concatMap, -- :: (Char -> ByteString) -> ByteString -> ByteString- any, -- :: (Char -> Bool) -> ByteString -> Bool- all, -- :: (Char -> Bool) -> ByteString -> Bool- maximum, -- :: ByteString -> Char- minimum, -- :: ByteString -> Char-- -- * Building ByteStrings- -- ** Scans- scanl, -- :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString- scanl1, -- :: (Char -> Char -> Char) -> ByteString -> ByteString- scanr, -- :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString- scanr1, -- :: (Char -> Char -> Char) -> ByteString -> ByteString-- -- ** Accumulating maps- mapAccumL, -- :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)- mapAccumR, -- :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)- mapIndexed, -- :: (Int -> Char -> Char) -> ByteString -> ByteString-- -- ** Generating and unfolding ByteStrings- replicate, -- :: Int -> Char -> ByteString- unfoldr, -- :: (a -> Maybe (Char, a)) -> a -> ByteString- unfoldrN, -- :: Int -> (a -> Maybe (Char, a)) -> a -> (ByteString, Maybe a)-- -- * Substrings-- -- ** Breaking strings- take, -- :: Int -> ByteString -> ByteString- drop, -- :: Int -> ByteString -> ByteString- splitAt, -- :: Int -> ByteString -> (ByteString, ByteString)- takeWhile, -- :: (Char -> Bool) -> ByteString -> ByteString- dropWhile, -- :: (Char -> Bool) -> ByteString -> ByteString- span, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)- spanEnd, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)- break, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)- breakEnd, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)- group, -- :: ByteString -> [ByteString]- groupBy, -- :: (Char -> Char -> Bool) -> ByteString -> [ByteString]- inits, -- :: ByteString -> [ByteString]- tails, -- :: ByteString -> [ByteString]-- -- ** Breaking into many substrings- split, -- :: Char -> ByteString -> [ByteString]- splitWith, -- :: (Char -> Bool) -> ByteString -> [ByteString]-- -- ** Breaking into lines and words- lines, -- :: ByteString -> [ByteString]- words, -- :: ByteString -> [ByteString]- unlines, -- :: [ByteString] -> ByteString- unwords, -- :: ByteString -> [ByteString]-- -- * Predicates- isPrefixOf, -- :: ByteString -> ByteString -> Bool- isSuffixOf, -- :: ByteString -> ByteString -> Bool- isInfixOf, -- :: ByteString -> ByteString -> Bool- isSubstringOf, -- :: ByteString -> ByteString -> Bool-- -- ** Search for arbitrary substrings- findSubstring, -- :: ByteString -> ByteString -> Maybe Int- findSubstrings, -- :: ByteString -> ByteString -> [Int]-- -- * Searching ByteStrings-- -- ** Searching by equality- elem, -- :: Char -> ByteString -> Bool- notElem, -- :: Char -> ByteString -> Bool-- -- ** Searching with a predicate- find, -- :: (Char -> Bool) -> ByteString -> Maybe Char- filter, -- :: (Char -> Bool) -> ByteString -> ByteString--- partition -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-- -- * Indexing ByteStrings- index, -- :: ByteString -> Int -> Char- elemIndex, -- :: Char -> ByteString -> Maybe Int- elemIndices, -- :: Char -> ByteString -> [Int]- elemIndexEnd, -- :: Char -> ByteString -> Maybe Int- findIndex, -- :: (Char -> Bool) -> ByteString -> Maybe Int- findIndices, -- :: (Char -> Bool) -> ByteString -> [Int]- count, -- :: Char -> ByteString -> Int-- -- * Zipping and unzipping ByteStrings- zip, -- :: ByteString -> ByteString -> [(Char,Char)]- zipWith, -- :: (Char -> Char -> c) -> ByteString -> ByteString -> [c]- unzip, -- :: [(Char,Char)] -> (ByteString,ByteString)-- -- * Ordered ByteStrings---LIQUID sort, -- :: ByteString -> ByteString-- -- * Reading from ByteStrings- readInt, -- :: ByteString -> Maybe (Int, ByteString)- readInteger, -- :: ByteString -> Maybe (Integer, ByteString)-- -- * Low level CString conversions-- -- ** Copying ByteStrings- copy, -- :: ByteString -> ByteString-- -- ** Packing CStrings and pointers- packCString, -- :: CString -> IO ByteString- packCStringLen, -- :: CStringLen -> IO ByteString-- -- ** Using ByteStrings as CStrings- useAsCString, -- :: ByteString -> (CString -> IO a) -> IO a- useAsCStringLen, -- :: ByteString -> (CStringLen -> IO a) -> IO a-- -- * I\/O with 'ByteString's-- -- ** Standard input and output- getLine, -- :: IO ByteString- getContents, -- :: IO ByteString- putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO ()- interact, -- :: (ByteString -> ByteString) -> IO ()-- -- ** Files- readFile, -- :: FilePath -> IO ByteString- writeFile, -- :: FilePath -> ByteString -> IO ()- appendFile, -- :: FilePath -> ByteString -> IO ()--- mmapFile, -- :: FilePath -> IO ByteString-- -- ** I\/O with Handles- hGetLine, -- :: Handle -> IO ByteString- hGetContents, -- :: Handle -> IO ByteString- hGet, -- :: Handle -> Int -> IO ByteString- hGetNonBlocking, -- :: Handle -> Int -> IO ByteString- hPut, -- :: Handle -> ByteString -> IO ()- hPutStr, -- :: Handle -> ByteString -> IO ()- hPutStrLn, -- :: Handle -> ByteString -> IO ()-- -- undocumented deprecated things:- join -- :: ByteString -> [ByteString] -> ByteString-- ) where--import qualified Prelude as P-import Prelude hiding (reverse,head,tail,last,init,null- ,length,map,lines,foldl,foldr,unlines- ,concat,any,take,drop,splitAt,takeWhile- ,dropWhile,span,break,elem,filter,unwords- ,words,maximum,minimum,all,concatMap- ,scanl,scanl1,scanr,scanr1- ,appendFile,readFile,writeFile- ,foldl1,foldr1,replicate- ,getContents,getLine,putStr,putStrLn,interact- ,zip,zipWith,unzip,notElem)--import qualified Data.ByteString as B-import qualified Data.ByteString.Internal as B-import qualified Data.ByteString.Unsafe as B--import qualified Data.ByteString.Lazy.Internal as TODO_REBARE -- ; this exposes `Chunk` and friends---- Listy functions transparently exported-import Data.ByteString (empty,null,length,tail,init,append- ,inits,tails,reverse,transpose- ,concat,take,drop,splitAt,intercalate- ,{-LIQUID sort,-}isPrefixOf,isSuffixOf,isInfixOf,isSubstringOf- ,findSubstring,findSubstrings,copy,group-- ,getLine, getContents, putStr, putStrLn, interact- ,hGetContents, hGet, hPut, hPutStr, hPutStrLn- ,hGetLine, hGetNonBlocking- ,packCString,packCStringLen- ,useAsCString,useAsCStringLen- )--import Data.ByteString.Internal (ByteString(PS), c2w, w2c, isSpaceWord8- ,inlinePerformIO)--#if defined(__GLASGOW_HASKELL__)-import Data.ByteString.Unsafe (unsafePackAddress) -- for the rule-#endif--import Data.Char ( isSpace )-import qualified Data.List as List (intersperse)--import System.IO (openFile,hClose,hFileSize,IOMode(..))-#ifndef __NHC__-import Control.Exception (bracket)-#else-import IO (bracket)-#endif-import Foreign--#if defined(__GLASGOW_HASKELL__)-import GHC.Base (Char(..),unpackCString#,ord#,int2Word#)-import GHC.Exts (Addr#,writeWord8OffAddr#,plusAddr#)-import GHC.Ptr (Ptr(..))-import GHC.ST (ST(..))-#endif--#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#if __GLASGOW_HASKELL__ >= 611-import Data.IORef-import GHC.IO.Handle.Internals-import GHC.IO.Handle.Types-import GHC.IO.Buffer-import GHC.IO.BufferedIO as Buffered-import GHC.IO (stToIO, unsafePerformIO)-import Data.Char (ord)-import Foreign.Marshal.Utils (copyBytes)-#else-import System.IO.Error (isEOFError)-import GHC.IOBase-import GHC.Handle-#endif----LIQUID-import Data.ByteString.Fusion (PairS(..), MaybeS(..))-import System.IO (Handle)-import Foreign.ForeignPtr-import Foreign.Ptr-import Data.Word (Word64)--import Language.Haskell.Liquid.Prelude------------------------------------------------------------------------------ | /O(1)/ Convert a 'Char' into a 'ByteString'-singleton :: Char -> ByteString-singleton = B.singleton . c2w-{-# INLINE singleton #-}---- | /O(n)/ Convert a 'String' into a 'ByteString'------ For applications with large numbers of string literals, pack can be a--- bottleneck.-pack :: String -> ByteString-#if !defined(__GLASGOW_HASKELL__)--pack str = B.unsafeCreate (P.length str) $ \p -> go p str- where go _ [] = return ()- go p (x:xs) = poke p (c2w x) >> go (p `plusPtr` 1) xs--#else /* hack away */--pack str = B.unsafeCreate (P.length str) $ \(Ptr p) -> stToIO (pack_go p str)- where- {-@ decrease pack_go 2 @-}- pack_go :: Addr# -> [Char] -> ST a ()- pack_go _ [] = return ()- pack_go p (C# c:cs) = writeByte p (int2Word# (ord# c)) >> pack_go (p `plusAddr#` 1#) cs-- writeByte p c = ST $ \s# ->- case writeWord8OffAddr# p 0# c s# of s2# -> (# s2#, () #)- {-# INLINE writeByte #-}-{-# INLINE [1] pack #-}--{-# RULES- "FPS pack/packAddress" forall s .- pack (unpackCString# s) = inlinePerformIO (B.unsafePackAddress s)- #-}--#endif---- | /O(n)/ Converts a 'ByteString' to a 'String'.-unpack :: ByteString -> [Char]-unpack = P.map w2c . B.unpack-{-# INLINE unpack #-}---- | /O(n)/ 'cons' is analogous to (:) for lists, but of different--- complexity, as it requires a memcpy.-cons :: Char -> ByteString -> ByteString-cons = B.cons . c2w-{-# INLINE cons #-}---- | /O(n)/ Append a Char to the end of a 'ByteString'. Similar to--- 'cons', this function performs a memcpy.-snoc :: ByteString -> Char -> ByteString-snoc p = B.snoc p . c2w-{-# INLINE snoc #-}---- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing--- if it is empty.-uncons :: ByteString -> Maybe (Char, ByteString)-uncons bs = case B.uncons bs of- Nothing -> Nothing- Just (w, bs') -> Just (w2c w, bs')-{-# INLINE uncons #-}---- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.-{-@ head :: ByteStringNE -> Char @-}-head :: ByteString -> Char-head = w2c . B.head-{-# INLINE head #-}---- | /O(1)/ Extract the last element of a packed string, which must be non-empty.-{-@ last :: ByteStringNE -> Char @-}-last :: ByteString -> Char-last = w2c . B.last-{-# INLINE last #-}---- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each element of @xs@-map :: (Char -> Char) -> ByteString -> ByteString-map f = B.map (c2w . f . w2c)-{-# INLINE map #-}---- | /O(n)/ The 'intersperse' function takes a Char and a 'ByteString'--- and \`intersperses\' that Char between the elements of the--- 'ByteString'. It is analogous to the intersperse function on Lists.-intersperse :: Char -> ByteString -> ByteString-intersperse = B.intersperse . c2w-{-# INLINE intersperse #-}--join :: ByteString -> [ByteString] -> ByteString-join = intercalate-{-# DEPRECATED join "use intercalate" #-}---- | 'foldl', applied to a binary operator, a starting value (typically--- the left-identity of the operator), and a ByteString, reduces the--- ByteString using the binary operator, from left to right.-foldl :: (a -> Char -> a) -> a -> ByteString -> a-foldl f = B.foldl (\a c -> f a (w2c c))-{-# INLINE foldl #-}---- | 'foldl\'' is like foldl, but strict in the accumulator.-foldl' :: (a -> Char -> a) -> a -> ByteString -> a-foldl' f = B.foldl' (\a c -> f a (w2c c))-{-# INLINE foldl' #-}---- | 'foldr', applied to a binary operator, a starting value--- (typically the right-identity of the operator), and a packed string,--- reduces the packed string using the binary operator, from right to left.-foldr :: (Char -> a -> a) -> a -> ByteString -> a-foldr f = B.foldr (\c a -> f (w2c c) a)-{-# INLINE foldr #-}---- | 'foldr\'' is a strict variant of foldr-foldr' :: (Char -> a -> a) -> a -> ByteString -> a-foldr' f = B.foldr' (\c a -> f (w2c c) a)-{-# INLINE foldr' #-}---- | 'foldl1' is a variant of 'foldl' that has no starting value--- argument, and thus must be applied to non-empty 'ByteStrings'.-{-@ foldl1 :: (Char -> Char -> Char) -> ByteStringNE -> Char @-}-foldl1 :: (Char -> Char -> Char) -> ByteString -> Char-foldl1 f ps = w2c (B.foldl1 (\x y -> c2w (f (w2c x) (w2c y))) ps)-{-# INLINE foldl1 #-}---- | A strict version of 'foldl1'-{-@ foldl1' :: (Char -> Char -> Char) -> ByteStringNE -> Char @-}-foldl1' :: (Char -> Char -> Char) -> ByteString -> Char-foldl1' f ps = w2c (B.foldl1' (\x y -> c2w (f (w2c x) (w2c y))) ps)-{-# INLINE foldl1' #-}---- | 'foldr1' is a variant of 'foldr' that has no starting value argument,--- and thus must be applied to non-empty 'ByteString's-{-@ foldr1 :: (Char -> Char -> Char) -> ByteStringNE -> Char @-}-foldr1 :: (Char -> Char -> Char) -> ByteString -> Char-foldr1 f ps = w2c (B.foldr1 (\x y -> c2w (f (w2c x) (w2c y))) ps)-{-# INLINE foldr1 #-}---- | A strict variant of foldr1-{-@ foldr1' :: (Char -> Char -> Char) -> ByteStringNE -> Char @-}-foldr1' :: (Char -> Char -> Char) -> ByteString -> Char-foldr1' f ps = w2c (B.foldr1' (\x y -> c2w (f (w2c x) (w2c y))) ps)-{-# INLINE foldr1' #-}---- | Map a function over a 'ByteString' and concatenate the results-concatMap :: (Char -> ByteString) -> ByteString -> ByteString-concatMap f = B.concatMap (f . w2c)-{-# INLINE concatMap #-}---- | Applied to a predicate and a ByteString, 'any' determines if--- any element of the 'ByteString' satisfies the predicate.-any :: (Char -> Bool) -> ByteString -> Bool-any f = B.any (f . w2c)-{-# INLINE any #-}---- | Applied to a predicate and a 'ByteString', 'all' determines if--- all elements of the 'ByteString' satisfy the predicate.-all :: (Char -> Bool) -> ByteString -> Bool-all f = B.all (f . w2c)-{-# INLINE all #-}---- | 'maximum' returns the maximum value from a 'ByteString'-{-@ maximum :: ByteStringNE -> Char @-}-maximum :: ByteString -> Char-maximum = w2c . B.maximum-{-# INLINE maximum #-}---- | 'minimum' returns the minimum value from a 'ByteString'-{-@ minimum :: ByteStringNE -> Char @-}-minimum :: ByteString -> Char-minimum = w2c . B.minimum-{-# INLINE minimum #-}---- | /O(n)/ map Char functions, provided with the index at each position-mapIndexed :: (Int -> Char -> Char) -> ByteString -> ByteString-mapIndexed f = B.mapIndexed (\i c -> c2w (f i (w2c c)))-{-# INLINE mapIndexed #-}---- | The 'mapAccumL' function behaves like a combination of 'map' and--- 'foldl'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from left to right, and returning a--- final value of this accumulator together with the new list.-mapAccumL :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)-mapAccumL f = B.mapAccumL (\acc w -> case f acc (w2c w) of (acc', c) -> (acc', c2w c))---- | The 'mapAccumR' function behaves like a combination of 'map' and--- 'foldr'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from right to left, and returning a--- final value of this accumulator together with the new ByteString.-mapAccumR :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)-mapAccumR f = B.mapAccumR (\acc w -> case f acc (w2c w) of (acc', c) -> (acc', c2w c))---- | 'scanl' is similar to 'foldl', but returns a list of successive--- reduced values from the left:------ > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]------ Note that------ > last (scanl f z xs) == foldl f z xs.-scanl :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString-scanl f z = B.scanl (\a b -> c2w (f (w2c a) (w2c b))) (c2w z)---- | 'scanl1' is a variant of 'scanl' that has no starting value argument:------ > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]-{-@ scanl1 :: (Char -> Char -> Char) -> ByteStringNE -> ByteString @-}-scanl1 :: (Char -> Char -> Char) -> ByteString -> ByteString-scanl1 f = B.scanl1 (\a b -> c2w (f (w2c a) (w2c b)))---- | scanr is the right-to-left dual of scanl.-scanr :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString-scanr f z = B.scanr (\a b -> c2w (f (w2c a) (w2c b))) (c2w z)---- | 'scanr1' is a variant of 'scanr' that has no starting value argument.-{-@ scanr1 :: (Char -> Char -> Char) -> ByteStringNE -> ByteString @-}-scanr1 :: (Char -> Char -> Char) -> ByteString -> ByteString-scanr1 f = B.scanr1 (\a b -> c2w (f (w2c a) (w2c b)))---- | /O(n)/ 'replicate' @n x@ is a ByteString of length @n@ with @x@--- the value of every element. The following holds:------ > replicate w c = unfoldr w (\u -> Just (u,u)) c------ This implemenation uses @memset(3)@-{-@ replicate :: n:Nat -> Char -> {v:ByteString | (bLength v) = (if n > 0 then n else 0)} @-}-replicate :: Int -> Char -> ByteString-replicate w = B.replicate w . c2w-{-# INLINE replicate #-}---- | /O(n)/, where /n/ is the length of the result. The 'unfoldr' --- function is analogous to the List \'unfoldr\'. 'unfoldr' builds a --- ByteString from a seed value. The function takes the element and --- returns 'Nothing' if it is done producing the ByteString or returns --- 'Just' @(a,b)@, in which case, @a@ is the next character in the string, --- and @b@ is the seed value for further production.------ Examples:------ > unfoldr (\x -> if x <= '9' then Just (x, succ x) else Nothing) '0' == "0123456789"-unfoldr :: (a -> Maybe (Char, a)) -> a -> ByteString-unfoldr f x0 = B.unfoldr (fmap k . f) x0- where k (i, j) = (c2w i, j)---- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a ByteString from a seed--- value. However, the length of the result is limited by the first--- argument to 'unfoldrN'. This function is more efficient than 'unfoldr'--- when the maximum length of the result is known.------ The following equation relates 'unfoldrN' and 'unfoldr':------ > unfoldrN n f s == take n (unfoldr f s)-{-@ unfoldrN :: i:Nat -> (a -> Maybe (Char, a)) -> a -> ({v:ByteString | (bLength v) <= i}, Maybe a) @-}-unfoldrN :: Int -> (a -> Maybe (Char, a)) -> a -> (ByteString, Maybe a)-unfoldrN n f w = B.unfoldrN n ((k `fmap`) . f) w- where k (i,j) = (c2w i, j)-{-# INLINE unfoldrN #-}---- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.-takeWhile :: (Char -> Bool) -> ByteString -> ByteString-takeWhile f = B.takeWhile (f . w2c)-{-# INLINE takeWhile #-}---- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.-dropWhile :: (Char -> Bool) -> ByteString -> ByteString-dropWhile f = B.dropWhile (f . w2c)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] dropWhile #-}-#endif---- | 'break' @p@ is equivalent to @'span' ('not' . p)@.-break :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-break f = B.break (f . w2c)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] break #-}-#endif---- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@-span :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-span f = B.span (f . w2c)-{-# INLINE span #-}---- | 'spanEnd' behaves like 'span' but from the end of the 'ByteString'.--- We have------ > spanEnd (not.isSpace) "x y z" == ("x y ","z")------ and------ > spanEnd (not . isSpace) ps--- > == --- > let (x,y) = span (not.isSpace) (reverse ps) in (reverse y, reverse x) ----spanEnd :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-spanEnd f = B.spanEnd (f . w2c)-{-# INLINE spanEnd #-}---- | 'breakEnd' behaves like 'break' but from the end of the 'ByteString'--- --- breakEnd p == spanEnd (not.p)-breakEnd :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-breakEnd f = B.breakEnd (f . w2c)-{-# INLINE breakEnd #-}--{---- | 'breakChar' breaks its ByteString argument at the first occurence--- of the specified Char. It is more efficient than 'break' as it is--- implemented with @memchr(3)@. I.e.--- --- > break (=='c') "abcd" == breakChar 'c' "abcd"----breakChar :: Char -> ByteString -> (ByteString, ByteString)-breakChar = B.breakByte . c2w-{-# INLINE breakChar #-}---- | 'spanChar' breaks its ByteString argument at the first--- occurence of a Char other than its argument. It is more efficient--- than 'span (==)'------ > span (=='c') "abcd" == spanByte 'c' "abcd"----spanChar :: Char -> ByteString -> (ByteString, ByteString)-spanChar = B.spanByte . c2w-{-# INLINE spanChar #-}--}---- | /O(n)/ Break a 'ByteString' into pieces separated by the byte--- argument, consuming the delimiter. I.e.------ > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]--- > split 'a' "aXaXaXa" == ["","X","X","X",""]--- > split 'x' "x" == ["",""]--- --- and------ > intercalate [c] . split c == id--- > split == splitWith . (==)--- --- As for all splitting functions in this library, this function does--- not copy the substrings, it just constructs new 'ByteStrings' that--- are slices of the original.----{-@ split :: Char -> b:ByteStringNE -> (ByteStringSplit b) @-}-split :: Char -> ByteString -> [ByteString]-split = B.split . c2w-{-# INLINE split #-}---- | /O(n)/ Splits a 'ByteString' into components delimited by--- separators, where the predicate returns True for a separator element.--- The resulting components do not contain the separators. Two adjacent--- separators result in an empty component in the output. eg.------ > splitWith (=='a') "aabbaca" == ["","","bb","c",""]----{-@ splitWith :: (Char -> Bool) -> b:ByteStringNE -> (ByteStringSplit b) @-}-splitWith :: (Char -> Bool) -> ByteString -> [ByteString]-splitWith f = B.splitWith (f . w2c)-{-# INLINE splitWith #-}--- the inline makes a big difference here.--{---- | Like 'splitWith', except that sequences of adjacent separators are--- treated as a single separator. eg.--- --- > tokens (=='a') "aabbaca" == ["bb","c"]----tokens :: (Char -> Bool) -> ByteString -> [ByteString]-tokens f = B.tokens (f . w2c)-{-# INLINE tokens #-}--}---- | The 'groupBy' function is the non-overloaded version of 'group'.-groupBy :: (Char -> Char -> Bool) -> ByteString -> [ByteString]-groupBy k = B.groupBy (\a b -> k (w2c a) (w2c b))---- | /O(1)/ 'ByteString' index (subscript) operator, starting from 0.-{-@ index :: b:ByteString -> {v:Nat | v < (bLength b)} -> Char @-}-index :: ByteString -> Int -> Char---LIQUID index = (w2c .) . B.index-index b i = w2c $ B.index b i-{-# INLINE index #-}---- | /O(n)/ The 'elemIndex' function returns the index of the first--- element in the given 'ByteString' which is equal (by memchr) to the--- query element, or 'Nothing' if there is no such element.-{-@ elemIndex :: Char -> b:ByteString -> Maybe {v:Nat | v < (bLength b)} @-}-elemIndex :: Char -> ByteString -> Maybe Int-elemIndex = B.elemIndex . c2w-{-# INLINE elemIndex #-}---- | /O(n)/ The 'elemIndexEnd' function returns the last index of the--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. The following--- holds:------ > elemIndexEnd c xs == --- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)----elemIndexEnd :: Char -> ByteString -> Maybe Int-elemIndexEnd = B.elemIndexEnd . c2w-{-# INLINE elemIndexEnd #-}---- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning--- the indices of all elements equal to the query element, in ascending order.-elemIndices :: Char -> ByteString -> [Int]-elemIndices = B.elemIndices . c2w-{-# INLINE elemIndices #-}---- | The 'findIndex' function takes a predicate and a 'ByteString' and--- returns the index of the first element in the ByteString satisfying the predicate.-findIndex :: (Char -> Bool) -> ByteString -> Maybe Int-findIndex f = B.findIndex (f . w2c)-{-# INLINE findIndex #-}---- | The 'findIndices' function extends 'findIndex', by returning the--- indices of all elements satisfying the predicate, in ascending order.-findIndices :: (Char -> Bool) -> ByteString -> [Int]-findIndices f = B.findIndices (f . w2c)---- | count returns the number of times its argument appears in the ByteString------ > count = length . elemIndices--- --- Also--- --- > count '\n' == length . lines------ But more efficiently than using length on the intermediate list.-count :: Char -> ByteString -> Int-count c = B.count (c2w c)---- | /O(n)/ 'elem' is the 'ByteString' membership predicate. This--- implementation uses @memchr(3)@.-elem :: Char -> ByteString -> Bool-elem c = B.elem (c2w c)-{-# INLINE elem #-}---- | /O(n)/ 'notElem' is the inverse of 'elem'-notElem :: Char -> ByteString -> Bool-notElem c = B.notElem (c2w c)-{-# INLINE notElem #-}---- | /O(n)/ 'filter', applied to a predicate and a ByteString,--- returns a ByteString containing those characters that satisfy the--- predicate.-filter :: (Char -> Bool) -> ByteString -> ByteString-filter f = B.filter (f . w2c)-{-# INLINE [1] filter #-}---- | /O(n)/ and /O(n\/c) space/ A first order equivalent of /filter .--- (==)/, for the common case of filtering a single Char. It is more--- efficient to use /filterChar/ in this case.------ > filterByte == filter . (==)------ filterChar is around 10x faster, and uses much less space, than its--- filter equivalent----filterChar :: Char -> ByteString -> ByteString-filterChar c ps = replicate (count c ps) c-{-# INLINE filterChar #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter ((==) x) = filterChar x- #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter (== x) = filterChar x- #-}---- | /O(n)/ The 'find' function takes a predicate and a ByteString,--- and returns the first element in matching the predicate, or 'Nothing'--- if there is no such element.-find :: (Char -> Bool) -> ByteString -> Maybe Char-find f ps = w2c `fmap` B.find (f . w2c) ps-{-# INLINE find #-}--{---- | /O(n)/ A first order equivalent of /filter . (==)/, for the common--- case of filtering a single Char. It is more efficient to use--- filterChar in this case.------ > filterChar == filter . (==)------ filterChar is around 10x faster, and uses much less space, than its--- filter equivalent----filterChar :: Char -> ByteString -> ByteString-filterChar c = B.filterByte (c2w c)-{-# INLINE filterChar #-}---- | /O(n)/ A first order equivalent of /filter . (\/=)/, for the common--- case of filtering a single Char out of a list. It is more efficient--- to use /filterNotChar/ in this case.------ > filterNotChar == filter . (/=)------ filterNotChar is around 3x faster, and uses much less space, than its--- filter equivalent----filterNotChar :: Char -> ByteString -> ByteString-filterNotChar c = B.filterNotByte (c2w c)-{-# INLINE filterNotChar #-}--}---- | /O(n)/ 'zip' takes two ByteStrings and returns a list of--- corresponding pairs of Chars. If one input ByteString is short,--- excess elements of the longer ByteString are discarded. This is--- equivalent to a pair of 'unpack' operations, and so space--- usage may be large for multi-megabyte ByteStrings-{-@ zip :: ByteString -> ByteString -> [(Char,Char)] @-}-zip :: ByteString -> ByteString -> [(Char,Char)]-zip ps qs- | B.null ps || B.null qs = []- | otherwise = (unsafeHead ps, unsafeHead qs) : zip (B.unsafeTail ps) (B.unsafeTail qs)---- | 'zipWith' generalises 'zip' by zipping with the function given as--- the first argument, instead of a tupling function. For example,--- @'zipWith' (+)@ is applied to two ByteStrings to produce the list--- of corresponding sums.-zipWith :: (Char -> Char -> a) -> ByteString -> ByteString -> [a]-zipWith f = B.zipWith ((. w2c) . f . w2c)---- | 'unzip' transforms a list of pairs of Chars into a pair of--- ByteStrings. Note that this performs two 'pack' operations.-unzip :: [(Char,Char)] -> (ByteString,ByteString)-unzip ls = (pack (P.map fst ls), pack (P.map snd ls))-{-# INLINE unzip #-}---- | A variety of 'head' for non-empty ByteStrings. 'unsafeHead' omits--- the check for the empty case, which is good for performance, but--- there is an obligation on the programmer to provide a proof that the--- ByteString is non-empty.-{-@ unsafeHead :: ByteStringNE -> Char @-}-unsafeHead :: ByteString -> Char-unsafeHead = w2c . B.unsafeHead-{-# INLINE unsafeHead #-}---- ------------------------------------------------------------------------ Things that depend on the encoding--{-# RULES- "FPS specialise break -> breakSpace"- break isSpace = breakSpace- #-}---- | 'breakSpace' returns the pair of ByteStrings when the argument is--- broken at the first whitespace byte. I.e.--- --- > break isSpace == breakSpace----breakSpace :: ByteString -> (ByteString,ByteString)-breakSpace (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- i <- firstspace (p `plusPtr` s) 0 l- return $! case () of {_- | i == 0 -> (empty, PS x s l)- | i == l -> (PS x s l, empty)- | otherwise -> (PS x s i, PS x (s+i) (l-i))- }-{-# INLINE breakSpace #-}--firstspace :: Ptr Word8 -> Int -> Int -> IO Int-STRICT3(firstspace)---LIQUID GHOST firstspace ptr n m---LIQUID GHOST | n >= m = return n---LIQUID GHOST | otherwise = do w <- peekByteOff ptr n---LIQUID GHOST if (not $ isSpaceWord8 w) then firstspace ptr (n+1) m else return n-firstspace ptr n m = go m ptr n m- {- LIQUID WITNESS -}- where go (d :: Int) ptr n m- | n >= m = return n- | otherwise = do w <- peekByteOff ptr n- if (not $ isSpaceWord8 w) then go (d-1) ptr (n+1) m else return n--{-# RULES- "FPS specialise dropWhile isSpace -> dropSpace"- dropWhile isSpace = dropSpace- #-}---- | 'dropSpace' efficiently returns the 'ByteString' argument with--- white space Chars removed from the front. It is more efficient than--- calling dropWhile for removing whitespace. I.e.--- --- > dropWhile isSpace == dropSpace----dropSpace :: ByteString -> ByteString-dropSpace (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- i <- firstnonspace (p `plusPtr` s) 0 l- return $! if i == l then empty else PS x (s+i) (l-i)-{-# INLINE dropSpace #-}--firstnonspace :: Ptr Word8 -> Int -> Int -> IO Int-STRICT3(firstnonspace)---LIQUID GHOST firstnonspace ptr n m---LIQUID GHOST | n >= m = return n---LIQUID GHOST | otherwise = do w <- peekElemOff ptr n---LIQUID GHOST if isSpaceWord8 w then firstnonspace ptr (n+1) m else return n-firstnonspace ptr n m = go m ptr n m- {- LIQUID WITNESS -}- where go (d :: Int) ptr n m- | n >= m = return n- | otherwise = do w <- peekElemOff ptr n- if isSpaceWord8 w then go (d-1) ptr (n+1) m else return n--{---- | 'dropSpaceEnd' efficiently returns the 'ByteString' argument with--- white space removed from the end. I.e.--- --- > reverse . (dropWhile isSpace) . reverse == dropSpaceEnd------ but it is more efficient than using multiple reverses.----dropSpaceEnd :: ByteString -> ByteString-dropSpaceEnd (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- i <- lastnonspace (p `plusPtr` s) (l-1)- return $! if i == (-1) then empty else PS x s (i+1)-{-# INLINE dropSpaceEnd #-}--lastnonspace :: Ptr Word8 -> Int -> IO Int-STRICT2(lastnonspace)-lastnonspace ptr n- | n < 0 = return n- | otherwise = do w <- peekElemOff ptr n- if isSpaceWord8 w then lastnonspace ptr (n-1) else return n--}---- | 'lines' breaks a ByteString up into a list of ByteStrings at--- newline Chars. The resulting strings do not contain newlines.----{-@ lines :: ByteString -> [ByteString] @-}-lines :: ByteString -> [ByteString]-lines ps- | null ps = []- | otherwise = case search ps of- Nothing -> [ps]- Just n -> take n ps : lines (drop (n+1) ps)- where search = elemIndex '\n'-{-# INLINE lines #-}--{---- Just as fast, but more complex. Should be much faster, I thought.-lines :: ByteString -> [ByteString]-lines (PS _ _ 0) = []-lines (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do- let ptr = p `plusPtr` s-- STRICT1(loop)- loop n = do- let q = memchr (ptr `plusPtr` n) 0x0a (fromIntegral (l-n))- if q == nullPtr- then return [PS x (s+n) (l-n)]- else do let i = q `minusPtr` ptr- ls <- loop (i+1)- return $! PS x (s+n) (i-n) : ls- loop 0--}---- | 'unlines' is an inverse operation to 'lines'. It joins lines,--- after appending a terminating newline to each.-unlines :: [ByteString] -> ByteString-unlines [] = empty-unlines ss = (concat $ List.intersperse nl ss) `append` nl -- half as much space- where nl = singleton '\n'---- | 'words' breaks a ByteString up into a list of words, which--- were delimited by Chars representing white space.---LIQUID FIXME: splitWith requires non-empty bytestrings for now..-{-@ words :: ByteStringNE -> [ByteString] @-}-words :: ByteString -> [ByteString]-words = P.filter (not . B.null) . B.splitWith isSpaceWord8-{-# INLINE words #-}---- | The 'unwords' function is analogous to the 'unlines' function, on words.-unwords :: [ByteString] -> ByteString-unwords = intercalate (singleton ' ')-{-# INLINE unwords #-}---- ------------------------------------------------------------------------ Reading from ByteStrings---- | readInt reads an Int from the beginning of the ByteString. If there is no--- integer at the beginning of the string, it returns Nothing, otherwise--- it just returns the int read, and the rest of the string.-readInt :: ByteString -> Maybe (Int, ByteString)-readInt as- | null as = Nothing- | otherwise =- case unsafeHead as of- '-' -> loop True 0 0 (B.unsafeTail as)- '+' -> loop False 0 0 (B.unsafeTail as)- _ -> loop False 0 0 as-- where loop :: Bool -> Int -> Int -> ByteString -> Maybe (Int, ByteString)- {-@ decrease loop 4 @-}- STRICT4(loop)- loop neg i n ps- | null ps = end neg i n ps- | otherwise =- case B.unsafeHead ps of- w | w >= 0x30- && w <= 0x39 -> loop neg (i+1)- (n * 10 + (fromIntegral w - 0x30))- (B.unsafeTail ps)- | otherwise -> end neg i n ps-- end _ 0 _ _ = Nothing- end True _ n ps = Just (negate n, ps)- end _ _ n ps = Just (n, ps)---- | readInteger reads an Integer from the beginning of the ByteString. If--- there is no integer at the beginning of the string, it returns Nothing,--- otherwise it just returns the int read, and the rest of the string.-readInteger :: ByteString -> Maybe (Integer, ByteString)-readInteger as- | null as = Nothing- | otherwise =- case unsafeHead as of- '-' -> first (B.unsafeTail as) >>= \(n, bs) -> return (-n, bs)- '+' -> first (B.unsafeTail as)- _ -> first as-- where first ps | null ps = Nothing- | otherwise =- case B.unsafeHead ps of- w | w >= 0x30 && w <= 0x39 -> Just $- loop 1 (fromIntegral w - 0x30) [] (B.unsafeTail ps)- | otherwise -> Nothing-- loop :: Int -> Int -> [Integer]- -> ByteString -> (Integer, ByteString)- {-@ decrease loop 4 @-}- STRICT4(loop)- loop d acc ns ps- | null ps = combine d acc ns empty- | otherwise =- case B.unsafeHead ps of- w | w >= 0x30 && w <= 0x39 ->- if d == 9 then loop 1 (fromIntegral w - 0x30)- (toInteger acc : ns)- (B.unsafeTail ps)- else loop (d+1)- (10*acc + (fromIntegral w - 0x30))- ns (B.unsafeTail ps)- | otherwise -> combine d acc ns ps-- combine _ acc [] ps = (toInteger acc, ps)- combine d acc ns ps =- ((10^d * combine1 1000000000 ns + toInteger acc), ps)-- --LIQUID combine1 _ [n] = n- --LIQUID combine1 b ns = combine1 (b*b) $ combine2 b ns- --LIQUID - --LIQUID combine2 b (n:m:ns) = let t = m*b + n in t `seq` (t : combine2 b ns)- --LIQUID combine2 _ ns = ns--{-@ combine1 :: Integer -> x:{v:[Integer] | (len v) > 0}- -> Integer- @-}-{-@ decrease combine1 2 @-}-combine1 :: Integer -> [Integer] -> Integer-combine1 _ [] = unsafeError "impossible"-combine1 _ [n] = n-combine1 b ns = combine1 (b*b) $ combine2 b ns--{-@ combine2 :: Integer -> x:[Integer]- -> {v:[Integer] | if len x > 1- then (len v < len x && len v > 0)- else (len v <= len x)}- @-}-{-@ decrease combine2 2 @-}-combine2 :: Integer -> [Integer] -> [Integer]-combine2 b (n:m:ns) = let t = m*b + n in t `seq` (t : combine2 b ns)-combine2 _ ns = ns---- | Read an entire file strictly into a 'ByteString'. This is far more--- efficient than reading the characters into a 'String' and then using--- 'pack'. It also may be more efficient than opening the file and--- reading it using hGet.-readFile :: FilePath -> IO ByteString-readFile f = bracket (openFile f ReadMode) hClose- (\h -> hFileSize h >>= hGet h . fromIntegral)---- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openFile f WriteMode) hClose- (\h -> hPut h txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openFile f AppendMode) hClose- (\h -> hPut h txt)-
@@ -1,808 +0,0 @@-{-# OPTIONS_GHC -cpp -fglasgow-exts -fno-warn-orphans #-}--{-@ LIQUID "--prune-unsorted" @-}---- |--- Module : Data.ByteString.Fusion--- License : BSD-style--- Maintainer : dons@cse.unsw.edu.au--- Stability : experimental--- Portability : portable------ Functional array fusion for ByteStrings.------ Originally based on code from the Data Parallel Haskell project, --- <http://www.cse.unsw.edu.au/~chak/project/dph>------- #hide-module Data.ByteString.Fusion (-- liquidCanaryFusion,-- -- * Fusion utilities- loopU, loopL, fuseEFL,- NoAcc(NoAcc), loopArr, loopAcc, loopSndAcc, unSP,- mapEFL, filterEFL, foldEFL, foldEFL', scanEFL, mapAccumEFL, mapIndexEFL,-- -- ** Alternative Fusion stuff- -- | This replaces 'loopU' with 'loopUp'- -- and adds several further special cases of loops.- loopUp, loopDown, loopNoAcc, loopMap, loopFilter,- loopWrapper, loopWrapperLE, sequenceLoops,- doUpLoop, doDownLoop, doNoAccLoop, doMapLoop, doFilterLoop,-- -- | These are the special fusion cases for combining each loop form perfectly. - fuseAccAccEFL, fuseAccNoAccEFL, fuseNoAccAccEFL, fuseNoAccNoAccEFL,- fuseMapAccEFL, fuseAccMapEFL, fuseMapNoAccEFL, fuseNoAccMapEFL,- fuseMapMapEFL, fuseAccFilterEFL, fuseFilterAccEFL, fuseNoAccFilterEFL,- fuseFilterNoAccEFL, fuseFilterFilterEFL, fuseMapFilterEFL, fuseFilterMapEFL,-- -- * Strict pairs and sums- PairS(..), MaybeS(..)-- ) where--import Data.ByteString.Internal-import qualified Data.ByteString.Lazy.Internal as L--import Foreign.ForeignPtr-import Foreign.Ptr-import Foreign.Storable (Storable(..))--import Data.Word (Word8, Word64)-import System.IO.Unsafe (unsafePerformIO)---- LIQUID-import Language.Haskell.Liquid.Prelude (liquidAssume, liquidAssert) --{-@ qualif PlusOnePos(v: int): 0 <= (v + 1) @-}-{-@ qualif LePlusOne(v: int, x: int): v <= (x + 1) @-}-{-@ qualif LeDiff(v: int, x: int, y:int): v <= (x - y) @-}-{-@ qualif PlenEq(v: Ptr a, x: int): x <= (plen v) @-}-{-@ qualif BlenEq(v: int, x:ByteString): v = (bLength x) @-}-{-@ qualif PSnd(v: a, x:b): v = (psnd x) @-}--{-@ data PairS a b <p :: x0:a -> b -> Bool> = (:*:) (x::a) (y::b<p x>) @-}--{-@ measure pfst :: (PairS a b) -> a - pfst ((:*:) x y) = x - @-} --{-@ measure psnd :: (PairS a b) -> b - psnd ((:*:) x y) = y - @-} --{-@ measure isJustS :: (MaybeS a) -> Bool- isJustS (JustS x) = true- isJustS NothingS = false- @-}--{-@ qualif PlusOne(v:int, x:int): v = x + 1 @-} --{-@ type MaybeSJ a = {v: MaybeS a | (isJustS v)} @-} --{-@ type AccEFLJ acc = acc -> Word8 -> (PairS acc (MaybeSJ Word8)) @-}-{-@ type NoAccEFLJ = Word8 -> (MaybeSJ Word8) @-}--{- liquidCanaryFusion :: x:Int -> {v: Int | v > x} @-}-liquidCanaryFusion :: Int -> Int-liquidCanaryFusion x = x - 1----- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined--infixl 2 :*:---- |Strict pair-data PairS a b = !a :*: !b deriving (Eq,Ord,Show)---- |Strict Maybe-data MaybeS a = NothingS | JustS !a deriving (Eq,Ord,Show)---- |Data type for accumulators which can be ignored. The rewrite rules rely on--- the fact that no bottoms of this type are ever constructed; hence, we can--- assume @(_ :: NoAcc) `seq` x = x@.----data NoAcc = NoAcc---- |Type of loop functions-type AccEFL acc = acc -> Word8 -> (PairS acc (MaybeS Word8))-type NoAccEFL = Word8 -> MaybeS Word8-type MapEFL = Word8 -> Word8-type FilterEFL = Word8 -> Bool--infixr 9 `fuseEFL`---- |Fuse to flat loop functions-fuseEFL :: AccEFL acc1 -> AccEFL acc2 -> AccEFL (PairS acc1 acc2)-fuseEFL f g (acc1 :*: acc2) e1 =- case f acc1 e1 of- acc1' :*: NothingS -> (acc1' :*: acc2) :*: NothingS- acc1' :*: JustS e2 ->- case g acc2 e2 of- acc2' :*: res -> (acc1' :*: acc2') :*: res-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] fuseEFL #-}-#endif---- | Special forms of loop arguments------ * These are common special cases for the three function arguments of gen--- and loop; we give them special names to make it easier to trigger RULES--- applying in the special cases represented by these arguments. The--- "INLINE [1]" makes sure that these functions are only inlined in the last--- two simplifier phases.------ * In the case where the accumulator is not needed, it is better to always--- explicitly return a value `()', rather than just copy the input to the--- output, as the former gives GHC better local information.--- ---- | Element function expressing a mapping only-#if !defined(LOOPNOACC_FUSION)-mapEFL :: (Word8 -> Word8) -> AccEFL NoAcc-mapEFL f = \_ e -> (NoAcc :*: (JustS $ f e))-#else-mapEFL :: (Word8 -> Word8) -> NoAccEFL-mapEFL f = \e -> JustS (f e)-#endif-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] mapEFL #-}-#endif---- | Element function implementing a filter function only-#if !defined(LOOPNOACC_FUSION)-filterEFL :: (Word8 -> Bool) -> AccEFL NoAcc-filterEFL p = \_ e -> if p e then (NoAcc :*: JustS e) else (NoAcc :*: NothingS)-#else-filterEFL :: (Word8 -> Bool) -> NoAccEFL-filterEFL p = \e -> if p e then JustS e else NothingS-#endif--#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] filterEFL #-}-#endif---- |Element function expressing a reduction only-foldEFL :: (acc -> Word8 -> acc) -> AccEFL acc-foldEFL f = \a e -> (f a e :*: NothingS)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] foldEFL #-}-#endif---- | A strict foldEFL.-foldEFL' :: (acc -> Word8 -> acc) -> AccEFL acc-foldEFL' f = \a e -> let a' = f a e in a' `seq` (a' :*: NothingS)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] foldEFL' #-}-#endif---- | Element function expressing a prefix reduction only-----{-@ scanEFL :: (Word8 -> Word8 -> Word8) -> AccEFLJ Word8 @-}-scanEFL :: (Word8 -> Word8 -> Word8) -> AccEFL Word8-scanEFL f = \a e -> (f a e :*: JustS a)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] scanEFL #-}-#endif---- | Element function implementing a map and fold----{-@ mapAccumEFL :: (acc -> Word8 -> (acc, Word8)) -> AccEFLJ acc @-}-mapAccumEFL :: (acc -> Word8 -> (acc, Word8)) -> AccEFL acc-mapAccumEFL f = \a e -> case f a e of (a', e') -> (a' :*: JustS e')-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] mapAccumEFL #-}-#endif---- | Element function implementing a map with index----{-@ mapIndexEFL :: (Int -> Word8 -> Word8) -> AccEFLJ Int @-}-mapIndexEFL :: (Int -> Word8 -> Word8) -> AccEFL Int-mapIndexEFL f = \i e -> let i' = i+1 in i' `seq` (i' :*: JustS (f i e))-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] mapIndexEFL #-}-#endif---- | Projection functions that are fusion friendly (as in, we determine when--- they are inlined)-{-@ loopArr :: p:(PairS acc arr) -> {v:arr | v = (psnd p)} @-}-loopArr :: (PairS acc arr) -> arr-loopArr (_ :*: arr) = arr-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopArr #-}-#endif--{-@ loopAcc :: p:(PairS acc arr) -> {v:acc | v = (pfst p)} @-}-loopAcc :: (PairS acc arr) -> acc-loopAcc (acc :*: _) = acc-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopAcc #-}-#endif--loopSndAcc :: (PairS (PairS acc1 acc2) arr) -> (PairS acc2 arr)-loopSndAcc ((_ :*: acc) :*: arr) = (acc :*: arr)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopSndAcc #-}-#endif--{-@ unSP :: p:(PairS acc arr) -> ({v:acc | v = (pfst p)}, {v:arr | v = (psnd p)}) @-}-unSP :: (PairS acc arr) -> (acc, arr)-unSP (acc :*: arr) = (acc, arr)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] unSP #-}-#endif-------------------------------------------------------------------------------- Loop combinator and fusion rules for flat arrays--- |Iteration over over ByteStrings----- | Iteration over over ByteStrings-loopU :: AccEFL acc -- ^ mapping & folding, once per elem- -> acc -- ^ initial acc value- -> ByteString -- ^ input ByteString- -> (PairS acc ByteString)--{-@ loopU :: AccEFLJ acc -> acc -> b:ByteString -> (PairS acc (ByteStringSZ b)) @-}--loopU f start (PS z s i) = unsafePerformIO $ withForeignPtr z $ \a -> do- (ps, acc) <- createAndTrimEQ i $ \p -> do- (acc' :*: i') <- go (a `plusPtr` s) p start- return (0 :: Int, i', acc')- return (acc :*: ps)-- where- go p ma = trans i 0 0- where- STRICT4(trans)- {- LIQUID WITNESS -}- trans (d :: Int) a_off ma_off acc- | a_off >= i = return (acc :*: ma_off)- | otherwise = do- x <- peekByteOff p a_off- let (acc' :*: oe) = f acc x- ma_off' <- case oe of- NothingS -> return ma_off- JustS e -> do pokeByteOff ma ma_off e- return $ ma_off + 1- trans (d-1) (a_off+1) ma_off' acc'---- a_off = i - d-{-@ qualif Decr(v:Int, x: Int, y:Int): v = x - y @-} --#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopU #-}-#endif--{- RULES--"FPS loop/loop fusion!" forall em1 em2 start1 start2 arr.- loopU em2 start2 (loopArr (loopU em1 start1 arr)) =- loopSndAcc (loopU (em1 `fuseEFL` em2) (start1 :*: start2) arr)-- #-}---- Functional list/array fusion for lazy ByteStrings.----{-@ loopL :: (AccEFLJ acc) -> acc -> b:L.ByteString -> (PairS acc (LByteStringSZ b)) @-}-loopL :: AccEFL acc -- ^ mapping & folding, once per elem- -> acc -- ^ initial acc value- -> L.ByteString -- ^ input ByteString- -> PairS acc L.ByteString-loopL f = loop- where loop s L.Empty = (s :*: L.Empty)- loop s (L.Chunk x xs)- | l == 0 = (s'' :*: ys)- | otherwise = (s'' :*: L.Chunk y ys)- where (s' :*: y@(PS _ _ l)) = loopU f s x -- avoid circular dep on S.null- (s'' :*: ys) = loop s' xs--#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopL #-}-#endif--{- RULES--"FPS lazy loop/loop fusion!" forall em1 em2 start1 start2 arr.- loopL em2 start2 (loopArr (loopL em1 start1 arr)) =- loopSndAcc (loopL (em1 `fuseEFL` em2) (start1 :*: start2) arr)-- #-}---{---Alternate experimental formulation of loopU which partitions it into-an allocating wrapper and an imperitive array-mutating loop.--The point in doing this split is that we might be able to fuse multiple-loops into a single wrapper. This would save reallocating another buffer.-It should also give better cache locality by reusing the buffer.--Note that this stuff needs ghc-6.5 from May 26 or later for the RULES to-really work reliably.---}--{-@ loopUp :: AccEFLJ acc -> acc -> b:ByteString -> (PairS acc (ByteStringSZ b)) @-}-loopUp :: AccEFL acc -> acc -> ByteString -> PairS acc ByteString-loopUp f a arr = loopWrapper (doUpLoop f a) arr-{-# INLINE loopUp #-}--{-@ loopDown :: AccEFLJ acc -> acc -> b:ByteString -> (PairS acc (ByteStringSZ b)) @-}-loopDown :: AccEFL acc -> acc -> ByteString -> PairS acc ByteString-loopDown f a arr = loopWrapper (doDownLoop f a) arr-{-# INLINE loopDown #-}--{-@ loopNoAcc :: NoAccEFLJ -> b:ByteString -> (PairS NoAcc (ByteStringSZ b)) @-}-loopNoAcc :: NoAccEFL -> ByteString -> PairS NoAcc ByteString-loopNoAcc f arr = loopWrapper (doNoAccLoop f NoAcc) arr-{-# INLINE loopNoAcc #-}--{-@ loopMap :: MapEFL -> b:ByteString -> (PairS NoAcc (ByteStringSZ b)) @-}-loopMap :: MapEFL -> ByteString -> PairS NoAcc ByteString-loopMap f arr = loopWrapper (doMapLoop f NoAcc) arr-{-# INLINE loopMap #-}--{-@ loopFilter :: FilterEFL -> b:ByteString -> (PairS NoAcc (ByteStringLE b)) @-}-loopFilter :: FilterEFL -> ByteString -> PairS NoAcc ByteString-loopFilter f arr = loopWrapperLE (doFilterLoop f NoAcc) arr-{-# INLINE loopFilter #-}---- The type of imperitive loops that fill in a destination array by--- reading a source array. They may not fill in the whole of the dest--- array if the loop is behaving as a filter, this is why we return--- the length that was filled in. The loop may also accumulate some--- value as it loops over the source array.--{-@ type TripleSLE a N = PairS <{\z v -> v <= (N - (psnd z))}> (PairS <{\x y -> true}> a Nat) {v:Nat | v <= N} @-} -{-@ type TripleS a N = PairS <{\z v -> v <= (N - (psnd z))}> (PairS <{\x y -> true}> a Nat) {v:Nat | v = N} @-} ---{-@ type ImperativeLoopLE acc = s:(PtrV Word8) - -> d:(PtrV Word8)- -> n:{v: Nat | ((v <= (plen d)) && (v <= (plen s))) }- -> IO (TripleSLE acc n)- @-}--{-@ type ImperativeLoop acc = s:(PtrV Word8) - -> d:(PtrV Word8)- -> n:{v: Nat | ((v <= (plen d)) && (v <= (plen s))) }- -> IO (TripleS acc n)- @-}---type ImperativeLoop acc =- Ptr Word8 -- pointer to the start of the source byte array- -> Ptr Word8 -- pointer to ther start of the destination byte array- -> Int -- length of the source byte array- -> IO (PairS (PairS acc Int) Int) -- result and offset, length of dest that was filled--{-@ loopWrapperLE :: ImperativeLoopLE acc -> b:ByteString -> PairS acc (ByteStringLE b) @-}-loopWrapperLE :: ImperativeLoop acc -> ByteString -> PairS acc ByteString-loopWrapperLE body (PS srcFPtr srcOffset srcLen) = unsafePerformIO $- withForeignPtr srcFPtr $ \srcPtr -> do- (ps, acc) <- createAndTrim' srcLen $ \destPtr -> do- (acc :*: destOffset :*: destLen) <- body (srcPtr `plusPtr` srcOffset) destPtr srcLen- return $ (destOffset, destLen, acc)- return (acc :*: ps)---- LIQUID DUPLICATECODE-{-@ loopWrapper :: ImperativeLoop acc -> b:ByteString -> PairS acc (ByteStringSZ b) @-}-loopWrapper :: ImperativeLoop acc -> ByteString -> PairS acc ByteString-loopWrapper body (PS srcFPtr srcOffset srcLen) = unsafePerformIO $- withForeignPtr srcFPtr $ \srcPtr -> do- (ps, acc) <- createAndTrimEQ srcLen $ \destPtr -> do- (acc :*: destOffset :*: destLen) <- body (srcPtr `plusPtr` srcOffset) destPtr srcLen- return $ (destOffset, id destLen, acc)- return (acc :*: ps)-----{-@ doUpLoop :: AccEFLJ acc -> acc -> ImperativeLoop acc @-}-doUpLoop :: AccEFL acc -> acc -> ImperativeLoop acc-doUpLoop f acc0 src dest len = loop len 0 0 acc0- {-@ decrease loop 1 @-} -- LIQUID TRANSFORMATION- where STRICT4(loop)- {- LIQUID WITNESS -}- loop (d :: Int) src_off dest_off acc- | src_off >= len = return (acc :*: (0 :: Int) {- LIQUID CAST -} :*: dest_off)- | otherwise = do- x <- peekByteOff src src_off- case f acc x of- (acc' :*: NothingS) -> loop (d-1) (src_off+1) dest_off acc'- (acc' :*: JustS x') -> pokeByteOff dest dest_off x'- >> loop (d-1) (src_off+1) (dest_off+1) acc'--{-@ doDownLoop :: AccEFLJ acc -> acc -> ImperativeLoop acc @-}-doDownLoop :: AccEFL acc -> acc -> ImperativeLoop acc-doDownLoop f acc0 src dest len = loop len (len-1) (len-1) acc0- {-@ decrease loop 1 @-} -- LIQUID TRANSFORMATION- where STRICT4(loop)- {- LIQUID WITNESS -}- loop (d :: Int) src_offDOWN dest_offDOWN acc- | src_offDOWN < 0 = return (acc :*: dest_offDOWN + 1 :*: len - (dest_offDOWN + 1))- | otherwise = do- x <- peekByteOff src src_offDOWN- case f acc x of- (acc' :*: NothingS) -> loop (d-1) (src_offDOWN - 1) dest_offDOWN acc'- (acc' :*: JustS x') -> pokeByteOff dest dest_offDOWN x'- >> loop (d-1) (src_offDOWN - 1) (dest_offDOWN - 1) acc'--{-@ doNoAccLoop :: NoAccEFLJ -> noAcc -> ImperativeLoop noAcc @-}-doNoAccLoop :: NoAccEFL -> noAcc -> ImperativeLoop noAcc-doNoAccLoop f noAcc src dest len = loop len 0 0- {-@ decrease loop 1 @-} -- LIQUID TRANSFORMATION- where STRICT3(loop)- {- LIQUID WITNESS -}- loop (d :: Int) src_off dest_off- | src_off >= len = return (noAcc :*: (0 :: Int) {- LIQUID CAST -} :*: dest_off)- | otherwise = do- x <- peekByteOff src src_off- case f x of- NothingS -> loop (d-1) (src_off+1) dest_off- JustS x' -> pokeByteOff dest dest_off x'- >> loop (d-1) (src_off+1) (dest_off+1)--{-@ doMapLoop :: MapEFL -> noAcc -> ImperativeLoop noAcc @-}-doMapLoop :: MapEFL -> noAcc -> ImperativeLoop noAcc-doMapLoop f noAcc src dest len = loop len 0- {-@ decrease loop 1 @-} -- LIQUID TRANSFORMATION- where STRICT2(loop)- {- LIQUID WITNESS -}- loop (d :: Int) n- | n >= len = return (noAcc :*: (0 :: Int) {- LIQUID CAST -} :*: len)- | otherwise = do- x <- peekByteOff src n- pokeByteOff dest n (f x)- loop (d-1) (n+1) -- offset always the same, only pass 1 arg--{-@ doFilterLoop :: FilterEFL -> noAcc -> ImperativeLoopLE noAcc @-}-doFilterLoop :: FilterEFL -> noAcc -> ImperativeLoop noAcc-doFilterLoop f noAcc src dest len = loop len 0 0- {-@ decrease loop 1 @-} -- LIQUID TRANSFORMATION- where STRICT3(loop)- {- LIQUID WITNESS -}- loop (d :: Int) src_off dest_off- | src_off >= len = return (noAcc :*: (0 :: Int) {- LIQUID CAST -} :*: dest_off)- | otherwise = do- x <- peekByteOff src src_off- if f x- then pokeByteOff dest dest_off x- >> loop (d-1) (src_off+1) (dest_off+1)- else loop (d-1) (src_off+1) dest_off---- LIQUID--- run two loops in sequence,--- think of it as: loop1 >> loop2--{-@ sequenceLoops :: ImperativeLoop acc1 -> ImperativeLoop acc2 -> ImperativeLoop (PairS acc1 acc2) @-}-sequenceLoops :: ImperativeLoop acc1- -> ImperativeLoop acc2- -> ImperativeLoop (PairS acc1 acc2)-sequenceLoops loop1 loop2 src dest len0 = do- (acc1 :*: off1 :*: len1) <- loop1 src dest len0- (acc2 :*: off2 :*: len2) <-- let src' = dest `plusPtr` off1- dest' = src' -- note that we are using dest == src- -- for the second loop as we are- -- mutating the dest array in-place!- in loop2 src' dest' len1- return ((acc1 :*: acc2) :*: off1 + off2 :*: len2)- -- TODO: prove that this is associative! (I think it is)- -- since we can't be sure how the RULES will combine loops.--#if defined(__GLASGOW_HASKELL__)--{-# INLINE [1] doUpLoop #-}-{-# INLINE [1] doDownLoop #-}-{-# INLINE [1] doNoAccLoop #-}-{-# INLINE [1] doMapLoop #-}-{-# INLINE [1] doFilterLoop #-}--{-# INLINE [1] loopWrapper #-}-{-# INLINE [1] sequenceLoops #-}--{-# INLINE [1] fuseAccAccEFL #-}-{-# INLINE [1] fuseAccNoAccEFL #-}-{-# INLINE [1] fuseNoAccAccEFL #-}-{-# INLINE [1] fuseNoAccNoAccEFL #-}-{-# INLINE [1] fuseMapAccEFL #-}-{-# INLINE [1] fuseAccMapEFL #-}-{-# INLINE [1] fuseMapNoAccEFL #-}-{-# INLINE [1] fuseNoAccMapEFL #-}-{-# INLINE [1] fuseMapMapEFL #-}-{-# INLINE [1] fuseAccFilterEFL #-}-{-# INLINE [1] fuseFilterAccEFL #-}-{-# INLINE [1] fuseNoAccFilterEFL #-}-{-# INLINE [1] fuseFilterNoAccEFL #-}-{-# INLINE [1] fuseFilterFilterEFL #-}-{-# INLINE [1] fuseMapFilterEFL #-}-{-# INLINE [1] fuseFilterMapEFL #-}--#endif--{- RULES--"FPS loopArr/loopSndAcc" forall x.- loopArr (loopSndAcc x) = loopArr x--"FPS seq/NoAcc" forall (u::NoAcc) e.- u `seq` e = e--"FPS loop/loop wrapper elimination" forall loop1 loop2 arr.- loopWrapper loop2 (loopArr (loopWrapper loop1 arr)) =- loopSndAcc (loopWrapper (sequenceLoops loop1 loop2) arr)------- n.b in the following, when reading n/m fusion, recall sequenceLoops--- is monadic, so its really n >> m fusion (i.e. m.n), not n . m fusion.-----"FPS up/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseAccAccEFL` f2) (acc1 :*: acc2)--"FPS map/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doMapLoop f2 acc2) =- doMapLoop (f1 `fuseMapMapEFL` f2) (acc1 :*: acc2)--"FPS filter/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doFilterLoop f2 acc2) =- doFilterLoop (f1 `fuseFilterFilterEFL` f2) (acc1 :*: acc2)--"FPS map/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doFilterLoop f2 acc2) =- doNoAccLoop (f1 `fuseMapFilterEFL` f2) (acc1 :*: acc2)--"FPS filter/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doMapLoop f2 acc2) =- doNoAccLoop (f1 `fuseFilterMapEFL` f2) (acc1 :*: acc2)--"FPS map/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseMapAccEFL` f2) (acc1 :*: acc2)--"FPS up/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doMapLoop f2 acc2) =- doUpLoop (f1 `fuseAccMapEFL` f2) (acc1 :*: acc2)--"FPS filter/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseFilterAccEFL` f2) (acc1 :*: acc2)--"FPS up/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doFilterLoop f2 acc2) =- doUpLoop (f1 `fuseAccFilterEFL` f2) (acc1 :*: acc2)--"FPS down/down loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseAccAccEFL` f2) (acc1 :*: acc2)--"FPS map/down fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseMapAccEFL` f2) (acc1 :*: acc2)--"FPS down/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doMapLoop f2 acc2) =- doDownLoop (f1 `fuseAccMapEFL` f2) (acc1 :*: acc2)--"FPS filter/down fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseFilterAccEFL` f2) (acc1 :*: acc2)--"FPS down/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doFilterLoop f2 acc2) =- doDownLoop (f1 `fuseAccFilterEFL` f2) (acc1 :*: acc2)--"FPS noAcc/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doNoAccLoop f2 acc2) =- doNoAccLoop (f1 `fuseNoAccNoAccEFL` f2) (acc1 :*: acc2)--"FPS noAcc/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseNoAccAccEFL` f2) (acc1 :*: acc2)--"FPS up/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doNoAccLoop f2 acc2) =- doUpLoop (f1 `fuseAccNoAccEFL` f2) (acc1 :*: acc2)--"FPS map/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doNoAccLoop f2 acc2) =- doNoAccLoop (f1 `fuseMapNoAccEFL` f2) (acc1 :*: acc2)--"FPS noAcc/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doMapLoop f2 acc2) =- doNoAccLoop (f1 `fuseNoAccMapEFL` f2) (acc1 :*: acc2)--"FPS filter/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doNoAccLoop f2 acc2) =- doNoAccLoop (f1 `fuseFilterNoAccEFL` f2) (acc1 :*: acc2)--"FPS noAcc/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doFilterLoop f2 acc2) =- doNoAccLoop (f1 `fuseNoAccFilterEFL` f2) (acc1 :*: acc2)--"FPS noAcc/down loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseNoAccAccEFL` f2) (acc1 :*: acc2)--"FPS down/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doNoAccLoop f2 acc2) =- doDownLoop (f1 `fuseAccNoAccEFL` f2) (acc1 :*: acc2)-- #-}--{---up = up loop-down = down loop-map = map special case-filter = filter special case-noAcc = noAcc undirectional loop (unused)--heirarchy:- up down- ^ ^- \ /- noAcc- ^ ^- / \- map filter--each is a special case of the things above--so we get rules that combine things on the same level-and rules that combine things on different levels-to get something on the higher level--so all the cases:-up/up --> up fuseAccAccEFL-down/down --> down fuseAccAccEFL-noAcc/noAcc --> noAcc fuseNoAccNoAccEFL--noAcc/up --> up fuseNoAccAccEFL-up/noAcc --> up fuseAccNoAccEFL-noAcc/down --> down fuseNoAccAccEFL-down/noAcc --> down fuseAccNoAccEFL--and if we do the map, filter special cases then it adds a load more:--map/map --> map fuseMapMapEFL-filter/filter --> filter fuseFilterFilterEFL--map/filter --> noAcc fuseMapFilterEFL-filter/map --> noAcc fuseFilterMapEFL--map/noAcc --> noAcc fuseMapNoAccEFL-noAcc/map --> noAcc fuseNoAccMapEFL--map/up --> up fuseMapAccEFL-up/map --> up fuseAccMapEFL--map/down --> down fuseMapAccEFL-down/map --> down fuseAccMapEFL--filter/noAcc --> noAcc fuseNoAccFilterEFL-noAcc/filter --> noAcc fuseFilterNoAccEFL--filter/up --> up fuseFilterAccEFL-up/filter --> up fuseAccFilterEFL--filter/down --> down fuseFilterAccEFL-down/filter --> down fuseAccFilterEFL--}--fuseAccAccEFL :: AccEFL acc1 -> AccEFL acc2 -> AccEFL (PairS acc1 acc2)-fuseAccAccEFL f g (acc1 :*: acc2) e1 =- case f acc1 e1 of- acc1' :*: NothingS -> (acc1' :*: acc2) :*: NothingS- acc1' :*: JustS e2 ->- case g acc2 e2 of- acc2' :*: res -> (acc1' :*: acc2') :*: res--fuseAccNoAccEFL :: AccEFL acc -> NoAccEFL -> AccEFL (PairS acc noAcc)-fuseAccNoAccEFL f g (acc :*: noAcc) e1 =- case f acc e1 of- acc' :*: NothingS -> (acc' :*: noAcc) :*: NothingS- acc' :*: JustS e2 -> (acc' :*: noAcc) :*: g e2--fuseNoAccAccEFL :: NoAccEFL -> AccEFL acc -> AccEFL (PairS noAcc acc)-fuseNoAccAccEFL f g (noAcc :*: acc) e1 =- case f e1 of- NothingS -> (noAcc :*: acc) :*: NothingS- JustS e2 ->- case g acc e2 of- acc' :*: res -> (noAcc :*: acc') :*: res--fuseNoAccNoAccEFL :: NoAccEFL -> NoAccEFL -> NoAccEFL-fuseNoAccNoAccEFL f g e1 =- case f e1 of- NothingS -> NothingS- JustS e2 -> g e2--fuseMapAccEFL :: MapEFL -> AccEFL acc -> AccEFL (PairS noAcc acc)-fuseMapAccEFL f g (noAcc :*: acc) e1 =- case g acc (f e1) of- (acc' :*: res) -> (noAcc :*: acc') :*: res--fuseAccMapEFL :: AccEFL acc -> MapEFL -> AccEFL (PairS acc noAcc)-fuseAccMapEFL f g (acc :*: noAcc) e1 =- case f acc e1 of- (acc' :*: NothingS) -> (acc' :*: noAcc) :*: NothingS- (acc' :*: JustS e2) -> (acc' :*: noAcc) :*: JustS (g e2)--fuseMapMapEFL :: MapEFL -> MapEFL -> MapEFL-fuseMapMapEFL f g e1 = g (f e1) -- n.b. perfect fusion--fuseMapNoAccEFL :: MapEFL -> NoAccEFL -> NoAccEFL-fuseMapNoAccEFL f g e1 = g (f e1)--fuseNoAccMapEFL :: NoAccEFL -> MapEFL -> NoAccEFL-fuseNoAccMapEFL f g e1 =- case f e1 of- NothingS -> NothingS- JustS e2 -> JustS (g e2)--fuseAccFilterEFL :: AccEFL acc -> FilterEFL -> AccEFL (PairS acc noAcc)-fuseAccFilterEFL f g (acc :*: noAcc) e1 =- case f acc e1 of- acc' :*: NothingS -> (acc' :*: noAcc) :*: NothingS- acc' :*: JustS e2 ->- case g e2 of- False -> (acc' :*: noAcc) :*: NothingS- True -> (acc' :*: noAcc) :*: JustS e2--fuseFilterAccEFL :: FilterEFL -> AccEFL acc -> AccEFL (PairS noAcc acc)-fuseFilterAccEFL f g (noAcc :*: acc) e1 =- case f e1 of- False -> (noAcc :*: acc) :*: NothingS- True ->- case g acc e1 of- acc' :*: res -> (noAcc :*: acc') :*: res--fuseNoAccFilterEFL :: NoAccEFL -> FilterEFL -> NoAccEFL-fuseNoAccFilterEFL f g e1 =- case f e1 of- NothingS -> NothingS- JustS e2 ->- case g e2 of- False -> NothingS- True -> JustS e2--fuseFilterNoAccEFL :: FilterEFL -> NoAccEFL -> NoAccEFL-fuseFilterNoAccEFL f g e1 =- case f e1 of- False -> NothingS- True -> g e1--fuseFilterFilterEFL :: FilterEFL -> FilterEFL -> FilterEFL-fuseFilterFilterEFL f g e1 = f e1 && g e1--fuseMapFilterEFL :: MapEFL -> FilterEFL -> NoAccEFL-fuseMapFilterEFL f g e1 =- case f e1 of- e2 -> case g e2 of- False -> NothingS- True -> JustS e2--fuseFilterMapEFL :: FilterEFL -> MapEFL -> NoAccEFL-fuseFilterMapEFL f g e1 =- case f e1 of- False -> NothingS- True -> JustS (g e1)-
@@ -1,802 +0,0 @@-{-@ LIQUID "--notermination" @-}-{-@ LIQUID "--pruneunsorted" @-}--{-# OPTIONS_GHC -cpp -fglasgow-exts -fno-warn-orphans #-}--- |--- Module : Data.ByteString.Fusion--- License : BSD-style--- Maintainer : dons@cse.unsw.edu.au--- Stability : experimental--- Portability : portable------ Functional array fusion for ByteStrings.------ Originally based on code from the Data Parallel Haskell project,--- <http://www.cse.unsw.edu.au/~chak/project/dph>------- #hide-module Data.ByteString.Fusion (-- liquidCanaryFusion,-- -- * Fusion utilities- loopU, loopL, fuseEFL,- NoAcc(NoAcc), loopArr, loopAcc, loopSndAcc, unSP,- mapEFL, filterEFL, foldEFL, foldEFL', scanEFL, mapAccumEFL, mapIndexEFL,-- -- ** Alternative Fusion stuff- -- | This replaces 'loopU' with 'loopUp'- -- and adds several further special cases of loops.- loopUp, loopDown, loopNoAcc, loopMap, loopFilter,- loopWrapper, loopWrapperLE, sequenceLoops,- doUpLoop, doDownLoop, doNoAccLoop, doMapLoop, doFilterLoop,-- -- | These are the special fusion cases for combining each loop form perfectly.- fuseAccAccEFL, fuseAccNoAccEFL, fuseNoAccAccEFL, fuseNoAccNoAccEFL,- fuseMapAccEFL, fuseAccMapEFL, fuseMapNoAccEFL, fuseNoAccMapEFL,- fuseMapMapEFL, fuseAccFilterEFL, fuseFilterAccEFL, fuseNoAccFilterEFL,- fuseFilterNoAccEFL, fuseFilterFilterEFL, fuseMapFilterEFL, fuseFilterMapEFL,-- -- * Strict pairs and sums- PairS(..), MaybeS(..)-- ) where--import Data.ByteString.Internal-import qualified Data.ByteString.Lazy.Internal as L--import Foreign.Ptr-import Foreign.ForeignPtr-import Foreign.Storable (Storable(..))--import Data.Word (Word8, Word64)-import System.IO.Unsafe (unsafePerformIO)---- LIQUID-import Prelude hiding (undefined)--- import Language.Haskell.Liquid.Prelude (liquidAssume, liquidAssert)--{-@ qualif PlusOnePos(v: int): 0 <= (v + 1) @-}-{-@ qualif LePlusOne(v: int, x: int): v <= (x + 1) @-}-{-@ qualif LeDiff(v: int, x: int, y:int): v <= (x - y) @-}-{-@ qualif PlenEq(v: Ptr a, x: int): x <= (plen v) @-}-{-@ qualif BlenEq(v: int, x:ByteString): v = (bLength x) @-}-{-@ qualif PSnd(v: a, x:b): v = (psnd x) @-}--{-@ data PairS a b <p :: x0:a -> b -> Bool> = (:*:) (x::a) (y::b<p x>) @-}--{-@ measure pfst :: (PairS a b) -> a- pfst ((:*:) x y) = x- @-}--{-@ measure psnd :: (PairS a b) -> b- psnd ((:*:) x y) = y- @-}--{-@ measure isJustS :: (MaybeS a) -> Bool- isJustS (JustS x) = true- isJustS NothingS = false- @-}--{-@ qualif PlusOne(v:int, x:int): v = x + 1 @-}--{-@ type MaybeSJ a = {v: MaybeS a | (isJustS v)} @-}--{-@ type AccEFLJ acc = acc -> Word8 -> (PairS acc (MaybeSJ Word8)) @-}-{-@ type NoAccEFLJ = Word8 -> (MaybeSJ Word8) @-}--{- liquidCanaryFusion :: x:Int -> {v: Int | v > x} @-}-liquidCanaryFusion :: Int -> Int-liquidCanaryFusion x = x - 1----- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----{-@ lazy undef @-}-undef :: a -> b-undef x = undef x--#define STRICT1(f) f a | a `seq` False = undef ()-#define STRICT2(f) f a b | a `seq` b `seq` False = undef ()-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undef ()-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undef ()-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undef ()--infixl 2 :*:---- |Strict pair-data PairS a b = !a :*: !b deriving (Eq,Ord,Show)---- |Strict Maybe-data MaybeS a = NothingS | JustS !a deriving (Eq,Ord,Show)---- |Data type for accumulators which can be ignored. The rewrite rules rely on--- the fact that no bottoms of this type are ever constructed; hence, we can--- assume @(_ :: NoAcc) `seq` x = x@.----data NoAcc = NoAcc---- |Type of loop functions-type AccEFL acc = acc -> Word8 -> (PairS acc (MaybeS Word8))-type NoAccEFL = Word8 -> MaybeS Word8-type MapEFL = Word8 -> Word8-type FilterEFL = Word8 -> Bool--infixr 9 `fuseEFL`---- |Fuse to flat loop functions-fuseEFL :: AccEFL acc1 -> AccEFL acc2 -> AccEFL (PairS acc1 acc2)-fuseEFL f g (acc1 :*: acc2) e1 =- case f acc1 e1 of- acc1' :*: NothingS -> (acc1' :*: acc2) :*: NothingS- acc1' :*: JustS e2 ->- case g acc2 e2 of- acc2' :*: res -> (acc1' :*: acc2') :*: res-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] fuseEFL #-}-#endif---- | Special forms of loop arguments------ * These are common special cases for the three function arguments of gen--- and loop; we give them special names to make it easier to trigger RULES--- applying in the special cases represented by these arguments. The--- "INLINE [1]" makes sure that these functions are only inlined in the last--- two simplifier phases.------ * In the case where the accumulator is not needed, it is better to always--- explicitly return a value `()', rather than just copy the input to the--- output, as the former gives GHC better local information.------- | Element function expressing a mapping only-#if !defined(LOOPNOACC_FUSION)-mapEFL :: (Word8 -> Word8) -> AccEFL NoAcc-mapEFL f = \_ e -> (NoAcc :*: (JustS $ f e))-#else-mapEFL :: (Word8 -> Word8) -> NoAccEFL-mapEFL f = \e -> JustS (f e)-#endif-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] mapEFL #-}-#endif---- | Element function implementing a filter function only-#if !defined(LOOPNOACC_FUSION)-filterEFL :: (Word8 -> Bool) -> AccEFL NoAcc-filterEFL p = \_ e -> if p e then (NoAcc :*: JustS e) else (NoAcc :*: NothingS)-#else-filterEFL :: (Word8 -> Bool) -> NoAccEFL-filterEFL p = \e -> if p e then JustS e else NothingS-#endif--#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] filterEFL #-}-#endif---- |Element function expressing a reduction only-foldEFL :: (acc -> Word8 -> acc) -> AccEFL acc-foldEFL f = \a e -> (f a e :*: NothingS)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] foldEFL #-}-#endif---- | A strict foldEFL.-foldEFL' :: (acc -> Word8 -> acc) -> AccEFL acc-foldEFL' f = \a e -> let a' = f a e in a' `seq` (a' :*: NothingS)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] foldEFL' #-}-#endif---- | Element function expressing a prefix reduction only-----{-@ scanEFL :: (Word8 -> Word8 -> Word8) -> AccEFLJ Word8 @-}-scanEFL :: (Word8 -> Word8 -> Word8) -> AccEFL Word8-scanEFL f = \a e -> (f a e :*: JustS a)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] scanEFL #-}-#endif---- | Element function implementing a map and fold----{-@ mapAccumEFL :: (acc -> Word8 -> (acc, Word8)) -> AccEFLJ acc @-}-mapAccumEFL :: (acc -> Word8 -> (acc, Word8)) -> AccEFL acc-mapAccumEFL f = \a e -> case f a e of (a', e') -> (a' :*: JustS e')-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] mapAccumEFL #-}-#endif---- | Element function implementing a map with index----{-@ mapIndexEFL :: (Int -> Word8 -> Word8) -> AccEFLJ Int @-}-mapIndexEFL :: (Int -> Word8 -> Word8) -> AccEFL Int-mapIndexEFL f = \i e -> let i' = i+1 in i' `seq` (i' :*: JustS (f i e))-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] mapIndexEFL #-}-#endif---- | Projection functions that are fusion friendly (as in, we determine when--- they are inlined)-{-@ loopArr :: p:(PairS acc arr) -> {v:arr | v = (psnd p)} @-}-loopArr :: (PairS acc arr) -> arr-loopArr (_ :*: arr) = arr-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopArr #-}-#endif--{-@ loopAcc :: p:(PairS acc arr) -> {v:acc | v = (pfst p)} @-}-loopAcc :: (PairS acc arr) -> acc-loopAcc (acc :*: _) = acc-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopAcc #-}-#endif--loopSndAcc :: (PairS (PairS acc1 acc2) arr) -> (PairS acc2 arr)-loopSndAcc ((_ :*: acc) :*: arr) = (acc :*: arr)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopSndAcc #-}-#endif--{-@ unSP :: p:(PairS acc arr) -> ({v:acc | v = (pfst p)}, {v:arr | v = (psnd p)}) @-}-unSP :: (PairS acc arr) -> (acc, arr)-unSP (acc :*: arr) = (acc, arr)-#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] unSP #-}-#endif-------------------------------------------------------------------------------- Loop combinator and fusion rules for flat arrays--- |Iteration over over ByteStrings----- | Iteration over over ByteStrings-loopU :: AccEFL acc -- ^ mapping & folding, once per elem- -> acc -- ^ initial acc value- -> ByteString -- ^ input ByteString- -> (PairS acc ByteString)--{-@ loopU :: AccEFLJ acc -> acc -> b:ByteString -> (PairS acc (ByteStringSZ b)) @-}--loopU f start (PS z s i) = unsafePerformIO $ withForeignPtr z $ \a -> do- (ps, acc) <- createAndTrimEQ i $ \p -> do- (acc' :*: i') <- go (a `plusPtr` s) p start- return (0 :: Int, i', acc')- return (acc :*: ps)-- where- go p ma = trans i 0 0- where- STRICT4(trans)- {- LIQUID WITNESS -}- trans (d :: Int) a_off ma_off acc- | a_off >= i = return (acc :*: ma_off)- | otherwise = do- x <- peekByteOff p a_off- let (acc' :*: oe) = f acc x- ma_off' <- case oe of- NothingS -> return ma_off- JustS e -> do pokeByteOff ma ma_off e- return $ ma_off + 1- trans (d-1) (a_off+1) ma_off' acc'---- a_off = i - d-{-@ qualif Decr(v:Int, x: Int, y:Int): v = x - y @-}--#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopU #-}-#endif--{-# RULES--"FPS loop/loop fusion!" forall em1 em2 start1 start2 arr.- loopU em2 start2 (loopArr (loopU em1 start1 arr)) =- loopSndAcc (loopU (em1 `fuseEFL` em2) (start1 :*: start2) arr)-- #-}---- Functional list/array fusion for lazy ByteStrings.----{-@ loopL :: (AccEFLJ acc) -> acc -> b:L.ByteString -> (PairS acc (LByteStringSZ b)) @-}-loopL :: AccEFL acc -- ^ mapping & folding, once per elem- -> acc -- ^ initial acc value- -> L.ByteString -- ^ input ByteString- -> PairS acc L.ByteString-loopL f = loop- where loop s L.Empty = (s :*: L.Empty)- loop s (L.Chunk x xs)- | l == 0 = (s'' :*: ys)- | otherwise = (s'' :*: L.Chunk y ys)- where (s' :*: y@(PS _ _ l)) = loopU f s x -- avoid circular dep on S.null- (s'' :*: ys) = loop s' xs--#if defined(__GLASGOW_HASKELL__)-{-# INLINE [1] loopL #-}-#endif--{-# RULES--"FPS lazy loop/loop fusion!" forall em1 em2 start1 start2 arr.- loopL em2 start2 (loopArr (loopL em1 start1 arr)) =- loopSndAcc (loopL (em1 `fuseEFL` em2) (start1 :*: start2) arr)-- #-}---{---Alternate experimental formulation of loopU which partitions it into-an allocating wrapper and an imperitive array-mutating loop.--The point in doing this split is that we might be able to fuse multiple-loops into a single wrapper. This would save reallocating another buffer.-It should also give better cache locality by reusing the buffer.--Note that this stuff needs ghc-6.5 from May 26 or later for the RULES to-really work reliably.---}--{-@ loopUp :: AccEFLJ acc -> acc -> b:ByteString -> (PairS acc (ByteStringSZ b)) @-}-loopUp :: AccEFL acc -> acc -> ByteString -> PairS acc ByteString-loopUp f a arr = loopWrapper (doUpLoop f a) arr-{-# INLINE loopUp #-}--{-@ loopDown :: AccEFLJ acc -> acc -> b:ByteString -> (PairS acc (ByteStringSZ b)) @-}-loopDown :: AccEFL acc -> acc -> ByteString -> PairS acc ByteString-loopDown f a arr = loopWrapper (doDownLoop f a) arr-{-# INLINE loopDown #-}--{-@ loopNoAcc :: NoAccEFLJ -> b:ByteString -> (PairS NoAcc (ByteStringSZ b)) @-}-loopNoAcc :: NoAccEFL -> ByteString -> PairS NoAcc ByteString-loopNoAcc f arr = loopWrapper (doNoAccLoop f NoAcc) arr-{-# INLINE loopNoAcc #-}--{-@ loopMap :: MapEFL -> b:ByteString -> (PairS NoAcc (ByteStringSZ b)) @-}-loopMap :: MapEFL -> ByteString -> PairS NoAcc ByteString-loopMap f arr = loopWrapper (doMapLoop f NoAcc) arr-{-# INLINE loopMap #-}--{-@ loopFilter :: FilterEFL -> b:ByteString -> (PairS NoAcc (ByteStringLE b)) @-}-loopFilter :: FilterEFL -> ByteString -> PairS NoAcc ByteString-loopFilter f arr = loopWrapperLE (doFilterLoop f NoAcc) arr-{-# INLINE loopFilter #-}---- The type of imperitive loops that fill in a destination array by--- reading a source array. They may not fill in the whole of the dest--- array if the loop is behaving as a filter, this is why we return--- the length that was filled in. The loop may also accumulate some--- value as it loops over the source array.--{-@ type TripleSLE a N = PairS <{\z v -> v <= (N - (psnd z))}> (PairS <{\x y -> true}> a Nat) {v:Nat | v <= N} @-}-{-@ type TripleS a N = PairS <{\z v -> v <= (N - (psnd z))}> (PairS <{\x y -> true}> a Nat) {v:Nat | v = N} @-}---{-@ type ImperativeLoopLE acc = s:(PtrV Word8)- -> d:(PtrV Word8)- -> n:{v: Nat | ((v <= (plen d)) && (v <= (plen s))) }- -> IO (TripleSLE acc n)- @-}--{-@ type ImperativeLoop acc = s:(PtrV Word8)- -> d:(PtrV Word8)- -> n:{v: Nat | ((v <= (plen d)) && (v <= (plen s))) }- -> IO (TripleS acc n)- @-}---type ImperativeLoop acc =- Ptr Word8 -- pointer to the start of the source byte array- -> Ptr Word8 -- pointer to ther start of the destination byte array- -> Int -- length of the source byte array- -> IO (PairS (PairS acc Int) Int) -- result and offset, length of dest that was filled--{-@ loopWrapperLE :: ImperativeLoopLE acc -> b:ByteString -> PairS acc (ByteStringLE b) @-}-loopWrapperLE :: ImperativeLoop acc -> ByteString -> PairS acc ByteString-loopWrapperLE body (PS srcFPtr srcOffset srcLen) = unsafePerformIO $- withForeignPtr srcFPtr $ \srcPtr -> do- (ps, acc) <- createAndTrim' srcLen $ \destPtr -> do- (acc :*: destOffset :*: destLen) <- body (srcPtr `plusPtr` srcOffset) destPtr srcLen- return $ (destOffset, destLen, acc)- return (acc :*: ps)---- LIQUID DUPLICATECODE-{-@ loopWrapper :: ImperativeLoop acc -> b:ByteString -> PairS acc (ByteStringSZ b) @-}-loopWrapper :: ImperativeLoop acc -> ByteString -> PairS acc ByteString-loopWrapper body (PS srcFPtr srcOffset srcLen) = unsafePerformIO $- withForeignPtr srcFPtr $ \srcPtr -> do- (ps, acc) <- createAndTrimEQ srcLen $ \destPtr -> do- (acc :*: destOffset :*: destLen) <- body (srcPtr `plusPtr` srcOffset) destPtr srcLen- return $ (destOffset, id destLen, acc)- return (acc :*: ps)-----{-@ doUpLoop :: AccEFLJ acc -> acc -> ImperativeLoop acc @-}-doUpLoop :: AccEFL acc -> acc -> ImperativeLoop acc-doUpLoop f acc0 src dest len = loop 0 0 acc0- where STRICT3(loop)- loop src_off dest_off acc- | src_off >= len = return (acc :*: (0 :: Int) {- LIQUID CAST -} :*: dest_off)- | otherwise = do- x <- peekByteOff src src_off- case f acc x of- (acc' :*: NothingS) -> loop (src_off+1) dest_off acc'- (acc' :*: JustS x') -> pokeByteOff dest dest_off x'- >> loop (src_off+1) (dest_off+1) acc'--{-@ doDownLoop :: AccEFLJ acc -> acc -> ImperativeLoop acc @-}-doDownLoop :: AccEFL acc -> acc -> ImperativeLoop acc-doDownLoop f acc0 src dest len = loop (len-1) (len-1) acc0- where STRICT3(loop)- loop src_offDOWN dest_offDOWN acc- | src_offDOWN < 0 = return (acc :*: dest_offDOWN + 1 :*: len - (dest_offDOWN + 1))- | otherwise = do- x <- peekByteOff src src_offDOWN- case f acc x of- (acc' :*: NothingS) -> loop (src_offDOWN - 1) dest_offDOWN acc'- (acc' :*: JustS x') -> pokeByteOff dest dest_offDOWN x'- >> loop (src_offDOWN - 1) (dest_offDOWN - 1) acc'--{-@ doNoAccLoop :: NoAccEFLJ -> noAcc -> ImperativeLoop noAcc @-}-doNoAccLoop :: NoAccEFL -> noAcc -> ImperativeLoop noAcc-doNoAccLoop f noAcc src dest len = loop 0 0- where STRICT2(loop)- loop src_off dest_off- | src_off >= len = return (noAcc :*: (0 :: Int) {- LIQUID CAST -} :*: dest_off)- | otherwise = do- x <- peekByteOff src src_off- case f x of- NothingS -> loop (src_off+1) dest_off- JustS x' -> pokeByteOff dest dest_off x'- >> loop (src_off+1) (dest_off+1)--{-@ doMapLoop :: MapEFL -> noAcc -> ImperativeLoop noAcc @-}-doMapLoop :: MapEFL -> noAcc -> ImperativeLoop noAcc-doMapLoop f noAcc src dest len = loop 0- where STRICT1(loop)- loop n- | n >= len = return (noAcc :*: (0 :: Int) {- LIQUID CAST -} :*: len)- | otherwise = do- x <- peekByteOff src n- pokeByteOff dest n (f x)- loop (n+1) -- offset always the same, only pass 1 arg--{-@ doFilterLoop :: FilterEFL -> noAcc -> ImperativeLoopLE noAcc @-}-doFilterLoop :: FilterEFL -> noAcc -> ImperativeLoop noAcc-doFilterLoop f noAcc src dest len = loop 0 0- where STRICT2(loop)- loop src_off dest_off- | src_off >= len = return (noAcc :*: (0 :: Int) {- LIQUID CAST -} :*: dest_off)- | otherwise = do- x <- peekByteOff src src_off- if f x- then pokeByteOff dest dest_off x- >> loop (src_off+1) (dest_off+1)- else loop (src_off+1) dest_off---- LIQUID--- run two loops in sequence,--- think of it as: loop1 >> loop2--{-@ sequenceLoops :: ImperativeLoop acc1 -> ImperativeLoop acc2 -> ImperativeLoop (PairS acc1 acc2) @-}-sequenceLoops :: ImperativeLoop acc1- -> ImperativeLoop acc2- -> ImperativeLoop (PairS acc1 acc2)-sequenceLoops loop1 loop2 src dest len0 = do- (acc1 :*: off1 :*: len1) <- loop1 src dest len0- (acc2 :*: off2 :*: len2) <-- let src' = dest `plusPtr` off1- dest' = src' -- note that we are using dest == src- -- for the second loop as we are- -- mutating the dest array in-place!- in loop2 src' dest' len1- return ((acc1 :*: acc2) :*: off1 + off2 :*: len2)- -- TODO: prove that this is associative! (I think it is)- -- since we can't be sure how the RULES will combine loops.--#if defined(__GLASGOW_HASKELL__)--{-# INLINE [1] doUpLoop #-}-{-# INLINE [1] doDownLoop #-}-{-# INLINE [1] doNoAccLoop #-}-{-# INLINE [1] doMapLoop #-}-{-# INLINE [1] doFilterLoop #-}--{-# INLINE [1] loopWrapper #-}-{-# INLINE [1] sequenceLoops #-}--{-# INLINE [1] fuseAccAccEFL #-}-{-# INLINE [1] fuseAccNoAccEFL #-}-{-# INLINE [1] fuseNoAccAccEFL #-}-{-# INLINE [1] fuseNoAccNoAccEFL #-}-{-# INLINE [1] fuseMapAccEFL #-}-{-# INLINE [1] fuseAccMapEFL #-}-{-# INLINE [1] fuseMapNoAccEFL #-}-{-# INLINE [1] fuseNoAccMapEFL #-}-{-# INLINE [1] fuseMapMapEFL #-}-{-# INLINE [1] fuseAccFilterEFL #-}-{-# INLINE [1] fuseFilterAccEFL #-}-{-# INLINE [1] fuseNoAccFilterEFL #-}-{-# INLINE [1] fuseFilterNoAccEFL #-}-{-# INLINE [1] fuseFilterFilterEFL #-}-{-# INLINE [1] fuseMapFilterEFL #-}-{-# INLINE [1] fuseFilterMapEFL #-}--#endif--{-# RULES--"FPS loopArr/loopSndAcc" forall x.- loopArr (loopSndAcc x) = loopArr x--"FPS seq/NoAcc" forall (u::NoAcc) e.- u `seq` e = e--"FPS loop/loop wrapper elimination" forall loop1 loop2 arr.- loopWrapper loop2 (loopArr (loopWrapper loop1 arr)) =- loopSndAcc (loopWrapper (sequenceLoops loop1 loop2) arr)------- n.b in the following, when reading n/m fusion, recall sequenceLoops--- is monadic, so its really n >> m fusion (i.e. m.n), not n . m fusion.-----"FPS up/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseAccAccEFL` f2) (acc1 :*: acc2)--"FPS map/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doMapLoop f2 acc2) =- doMapLoop (f1 `fuseMapMapEFL` f2) (acc1 :*: acc2)--"FPS filter/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doFilterLoop f2 acc2) =- doFilterLoop (f1 `fuseFilterFilterEFL` f2) (acc1 :*: acc2)--"FPS map/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doFilterLoop f2 acc2) =- doNoAccLoop (f1 `fuseMapFilterEFL` f2) (acc1 :*: acc2)--"FPS filter/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doMapLoop f2 acc2) =- doNoAccLoop (f1 `fuseFilterMapEFL` f2) (acc1 :*: acc2)--"FPS map/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseMapAccEFL` f2) (acc1 :*: acc2)--"FPS up/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doMapLoop f2 acc2) =- doUpLoop (f1 `fuseAccMapEFL` f2) (acc1 :*: acc2)--"FPS filter/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseFilterAccEFL` f2) (acc1 :*: acc2)--"FPS up/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doFilterLoop f2 acc2) =- doUpLoop (f1 `fuseAccFilterEFL` f2) (acc1 :*: acc2)--"FPS down/down loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseAccAccEFL` f2) (acc1 :*: acc2)--"FPS map/down fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseMapAccEFL` f2) (acc1 :*: acc2)--"FPS down/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doMapLoop f2 acc2) =- doDownLoop (f1 `fuseAccMapEFL` f2) (acc1 :*: acc2)--"FPS filter/down fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseFilterAccEFL` f2) (acc1 :*: acc2)--"FPS down/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doFilterLoop f2 acc2) =- doDownLoop (f1 `fuseAccFilterEFL` f2) (acc1 :*: acc2)--"FPS noAcc/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doNoAccLoop f2 acc2) =- doNoAccLoop (f1 `fuseNoAccNoAccEFL` f2) (acc1 :*: acc2)--"FPS noAcc/up loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doUpLoop f2 acc2) =- doUpLoop (f1 `fuseNoAccAccEFL` f2) (acc1 :*: acc2)--"FPS up/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doUpLoop f1 acc1) (doNoAccLoop f2 acc2) =- doUpLoop (f1 `fuseAccNoAccEFL` f2) (acc1 :*: acc2)--"FPS map/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doMapLoop f1 acc1) (doNoAccLoop f2 acc2) =- doNoAccLoop (f1 `fuseMapNoAccEFL` f2) (acc1 :*: acc2)--"FPS noAcc/map loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doMapLoop f2 acc2) =- doNoAccLoop (f1 `fuseNoAccMapEFL` f2) (acc1 :*: acc2)--"FPS filter/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doFilterLoop f1 acc1) (doNoAccLoop f2 acc2) =- doNoAccLoop (f1 `fuseFilterNoAccEFL` f2) (acc1 :*: acc2)--"FPS noAcc/filter loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doFilterLoop f2 acc2) =- doNoAccLoop (f1 `fuseNoAccFilterEFL` f2) (acc1 :*: acc2)--"FPS noAcc/down loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doNoAccLoop f1 acc1) (doDownLoop f2 acc2) =- doDownLoop (f1 `fuseNoAccAccEFL` f2) (acc1 :*: acc2)--"FPS down/noAcc loop fusion" forall f1 f2 acc1 acc2.- sequenceLoops (doDownLoop f1 acc1) (doNoAccLoop f2 acc2) =- doDownLoop (f1 `fuseAccNoAccEFL` f2) (acc1 :*: acc2)-- #-}--{---up = up loop-down = down loop-map = map special case-filter = filter special case-noAcc = noAcc undirectional loop (unused)--heirarchy:- up down- ^ ^- \ /- noAcc- ^ ^- / \- map filter--each is a special case of the things above--so we get rules that combine things on the same level-and rules that combine things on different levels-to get something on the higher level--so all the cases:-up/up --> up fuseAccAccEFL-down/down --> down fuseAccAccEFL-noAcc/noAcc --> noAcc fuseNoAccNoAccEFL--noAcc/up --> up fuseNoAccAccEFL-up/noAcc --> up fuseAccNoAccEFL-noAcc/down --> down fuseNoAccAccEFL-down/noAcc --> down fuseAccNoAccEFL--and if we do the map, filter special cases then it adds a load more:--map/map --> map fuseMapMapEFL-filter/filter --> filter fuseFilterFilterEFL--map/filter --> noAcc fuseMapFilterEFL-filter/map --> noAcc fuseFilterMapEFL--map/noAcc --> noAcc fuseMapNoAccEFL-noAcc/map --> noAcc fuseNoAccMapEFL--map/up --> up fuseMapAccEFL-up/map --> up fuseAccMapEFL--map/down --> down fuseMapAccEFL-down/map --> down fuseAccMapEFL--filter/noAcc --> noAcc fuseNoAccFilterEFL-noAcc/filter --> noAcc fuseFilterNoAccEFL--filter/up --> up fuseFilterAccEFL-up/filter --> up fuseAccFilterEFL--filter/down --> down fuseFilterAccEFL-down/filter --> down fuseAccFilterEFL--}--fuseAccAccEFL :: AccEFL acc1 -> AccEFL acc2 -> AccEFL (PairS acc1 acc2)-fuseAccAccEFL f g (acc1 :*: acc2) e1 =- case f acc1 e1 of- acc1' :*: NothingS -> (acc1' :*: acc2) :*: NothingS- acc1' :*: JustS e2 ->- case g acc2 e2 of- acc2' :*: res -> (acc1' :*: acc2') :*: res--fuseAccNoAccEFL :: AccEFL acc -> NoAccEFL -> AccEFL (PairS acc noAcc)-fuseAccNoAccEFL f g (acc :*: noAcc) e1 =- case f acc e1 of- acc' :*: NothingS -> (acc' :*: noAcc) :*: NothingS- acc' :*: JustS e2 -> (acc' :*: noAcc) :*: g e2--fuseNoAccAccEFL :: NoAccEFL -> AccEFL acc -> AccEFL (PairS noAcc acc)-fuseNoAccAccEFL f g (noAcc :*: acc) e1 =- case f e1 of- NothingS -> (noAcc :*: acc) :*: NothingS- JustS e2 ->- case g acc e2 of- acc' :*: res -> (noAcc :*: acc') :*: res--fuseNoAccNoAccEFL :: NoAccEFL -> NoAccEFL -> NoAccEFL-fuseNoAccNoAccEFL f g e1 =- case f e1 of- NothingS -> NothingS- JustS e2 -> g e2--fuseMapAccEFL :: MapEFL -> AccEFL acc -> AccEFL (PairS noAcc acc)-fuseMapAccEFL f g (noAcc :*: acc) e1 =- case g acc (f e1) of- (acc' :*: res) -> (noAcc :*: acc') :*: res--fuseAccMapEFL :: AccEFL acc -> MapEFL -> AccEFL (PairS acc noAcc)-fuseAccMapEFL f g (acc :*: noAcc) e1 =- case f acc e1 of- (acc' :*: NothingS) -> (acc' :*: noAcc) :*: NothingS- (acc' :*: JustS e2) -> (acc' :*: noAcc) :*: JustS (g e2)--fuseMapMapEFL :: MapEFL -> MapEFL -> MapEFL-fuseMapMapEFL f g e1 = g (f e1) -- n.b. perfect fusion--fuseMapNoAccEFL :: MapEFL -> NoAccEFL -> NoAccEFL-fuseMapNoAccEFL f g e1 = g (f e1)--fuseNoAccMapEFL :: NoAccEFL -> MapEFL -> NoAccEFL-fuseNoAccMapEFL f g e1 =- case f e1 of- NothingS -> NothingS- JustS e2 -> JustS (g e2)--fuseAccFilterEFL :: AccEFL acc -> FilterEFL -> AccEFL (PairS acc noAcc)-fuseAccFilterEFL f g (acc :*: noAcc) e1 =- case f acc e1 of- acc' :*: NothingS -> (acc' :*: noAcc) :*: NothingS- acc' :*: JustS e2 ->- case g e2 of- False -> (acc' :*: noAcc) :*: NothingS- True -> (acc' :*: noAcc) :*: JustS e2--fuseFilterAccEFL :: FilterEFL -> AccEFL acc -> AccEFL (PairS noAcc acc)-fuseFilterAccEFL f g (noAcc :*: acc) e1 =- case f e1 of- False -> (noAcc :*: acc) :*: NothingS- True ->- case g acc e1 of- acc' :*: res -> (noAcc :*: acc') :*: res--fuseNoAccFilterEFL :: NoAccEFL -> FilterEFL -> NoAccEFL-fuseNoAccFilterEFL f g e1 =- case f e1 of- NothingS -> NothingS- JustS e2 ->- case g e2 of- False -> NothingS- True -> JustS e2--fuseFilterNoAccEFL :: FilterEFL -> NoAccEFL -> NoAccEFL-fuseFilterNoAccEFL f g e1 =- case f e1 of- False -> NothingS- True -> g e1--fuseFilterFilterEFL :: FilterEFL -> FilterEFL -> FilterEFL-fuseFilterFilterEFL f g e1 = f e1 && g e1--fuseMapFilterEFL :: MapEFL -> FilterEFL -> NoAccEFL-fuseMapFilterEFL f g e1 =- case f e1 of- e2 -> case g e2 of- False -> NothingS- True -> JustS e2--fuseFilterMapEFL :: FilterEFL -> MapEFL -> NoAccEFL-fuseFilterMapEFL f g e1 =- case f e1 of- False -> NothingS- True -> JustS (g e1)
@@ -1,636 +0,0 @@-{-@ LIQUID "--pruneunsorted" @-}-{- LIQUID "--trust-sizes" @-}--{-# LANGUAGE CPP, ForeignFunctionInterface, DeriveDataTypeable #-}--- We cannot actually specify all the language pragmas, see ghc ticket #--- If we could, these are what they would be:-{-# LANGUAGE UnliftedFFITypes, MagicHash,- UnboxedTuples, DeriveDataTypeable #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.ByteString.Internal--- License : BSD-style--- Maintainer : Don Stewart <dons@galois.com>--- Stability : experimental--- Portability : portable------ A module containing semi-public 'ByteString' internals. This exposes the--- 'ByteString' representation and low level construction functions. As such--- all the functions in this module are unsafe. The API is also not stable.------ Where possible application should instead use the functions from the normal--- public interface modules, such as "Data.ByteString.Unsafe". Packages that--- extend the ByteString system at a low level will need to use this module.----module Data.ByteString.Internal (-- liquidCanary, -- LIQUID- ptrLen, -- LIQUID GHOST for getting a pointer's length- packWith, -- LIQUID, because we hid the Read instance... FIX.-- -- * The @ByteString@ type and representation- ByteString(..), -- instances: Eq, Ord, Show, Read, Data, Typeable-- -- * Low level introduction and elimination- create, -- :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString- createAndTrim, -- :: Int -> (Ptr Word8 -> IO Int) -> IO ByteString- createAndTrim', -- :: Int -> (Ptr Word8 -> IO (Int, Int, a)) -> IO (ByteString, a)- createAndTrimEQ, -- :: Int -> (Ptr Word8 -> IO (Int, Int, a)) -> IO (Int, ByteString, a)- createAndTrimMEQ, -- :: Int -> (Ptr Word8 -> IO (Int, Int, Maybe a)) -> IO (Int, ByteString, Maybe a)- unsafeCreate, -- :: Int -> (Ptr Word8 -> IO ()) -> ByteString- mallocByteString, -- :: Int -> IO (ForeignPtr a)-- -- * Conversion to and from ForeignPtrs- fromForeignPtr, -- :: ForeignPtr Word8 -> Int -> Int -> ByteString- toForeignPtr, -- :: ByteString -> (ForeignPtr Word8, Int, Int)-- -- * Utilities- inlinePerformIO, -- :: IO a -> a- nullForeignPtr, -- :: ForeignPtr Word8-- -- * Standard C Functions- c_strlen, -- :: CString -> IO CInt- c_free_finalizer, -- :: FunPtr (Ptr Word8 -> IO ())-- memchr, -- :: Ptr Word8 -> Word8 -> CSize -> IO Ptr Word8- memcmp, -- :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt- memcpy, -- :: Ptr Word8 -> Ptr Word8 -> CSize -> IO ()- memset, -- :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)-- -- * cbits functions- c_reverse, -- :: Ptr Word8 -> Ptr Word8 -> CInt -> IO ()- c_intersperse, -- :: Ptr Word8 -> Ptr Word8 -> CInt -> Word8 -> IO ()- c_maximum, -- :: Ptr Word8 -> CInt -> IO Word8- c_minimum, -- :: Ptr Word8 -> CInt -> IO Word8- c_count, -- :: Ptr Word8 -> CInt -> Word8 -> IO CInt-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 611- -- * Internal GHC magic- memcpy_ptr_baoff, -- :: Ptr a -> RawBuffer -> CInt -> CSize -> IO (Ptr ())-#endif-- -- * Chars- w2c, c2w, isSpaceWord8, isSpaceChar8-- ) where--import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr, FunPtr, plusPtr)-import Foreign.Storable (Storable(..))-import Foreign.C.Types (CInt(..), CSize(..), CULong(..))-import Foreign.C.String (CString)--import Foreign.Marshal.Alloc (finalizerFree) --LIQUID: added-import Language.Haskell.Liquid.Prelude (liquidAssert)-import Language.Haskell.Liquid.Foreign (intCSize)--#ifndef __NHC__-import Control.Exception (assert)-#endif--import Data.Char (ord)-import Data.Word (Word8)--#if defined(__GLASGOW_HASKELL__)-import Data.Typeable (Typeable)-#if __GLASGOW_HASKELL__ >= 610-import Data.Data (Data)-#else-import Data.Generics (Data)-#endif-import GHC.Base (realWorld#, unsafeChr)-#if __GLASGOW_HASKELL__ >= 611-import GHC.IO (IO(IO))-#else-import GHC.IOBase (IO(IO),RawBuffer)-#endif-#if __GLASGOW_HASKELL__ >= 611-import GHC.IO (unsafeDupablePerformIO)-#else-import GHC.IOBase (unsafeDupablePerformIO)-#endif-#else-import Data.Char (chr)-import System.IO.Unsafe (unsafePerformIO)-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.ForeignPtr (mallocPlainForeignPtrBytes)-#else-import Foreign.ForeignPtr (mallocForeignPtrBytes)-#endif--#ifdef __GLASGOW_HASKELL__-import GHC.ForeignPtr (ForeignPtr(ForeignPtr))-import GHC.Base (nullAddr#)-#else-import Foreign.Ptr (nullPtr)-#endif--#if __HUGS__-import Hugs.ForeignPtr (newForeignPtr_)-#elif __GLASGOW_HASKELL__<=604-import Foreign.ForeignPtr (newForeignPtr_)-#endif---- CFILES stuff is Hugs only-{-# CFILES cbits/fpstring.c #-}---- An alternative to Control.Exception (assert) for nhc98-#ifdef __NHC__-#define assert assertS "__FILE__ : __LINE__"-assertS :: String -> Bool -> a -> a-assertS _ True = id-assertS s False = error ("assertion failed at "++s)-#endif---- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined---- --------------------------------------------------------------------------------- | A space-efficient representation of a Word8 vector, supporting many--- efficient operations. A 'ByteString' contains 8-bit characters only.------ Instances of Eq, Ord, Read, Show, Data, Typeable----data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload- {-# UNPACK #-} !Int -- offset- {-# UNPACK #-} !Int -- length---- LIQUID #if defined(__GLASGOW_HASKELL__)--- LIQUID deriving (Data, Typeable)--- LIQUID #endif--- LIQUID WIERD CONSTANTS like--- LIQUID (scc<CAF> Data.Typeable.Internal.mkTyCon)--- LIQUID (scc<CAF> __word64 5047387852870479354))--- LIQUID (scc<CAF> __word64 13413741352319211914))------------------------------------------------------------------------------ LiquidHaskell Specifications ---------------------------------------------------------------------------------------------------------------------{-@ measure bLength :: ByteString -> Int - bLength (PS p o l) = l - @-} - -{-@ measure bOffset :: ByteString -> Int- bOffset (PS p o l) = o- @-}---{-@ measure bPayload :: ByteString -> (ForeignPtr Word8)- bPayload (PS p o l) = p- @-}--{-@ predicate BSValid Payload Offset Length = (Offset + Length <= (fplen Payload)) @-}--{-@ predicate OkPLen N P = (N <= (plen P)) @-}--{-@ data ByteString [bLength]- = PS { payload :: (ForeignPtr Word8)- , offset :: {v: Nat | (v <= (fplen payload)) }- , length :: {v: Nat | (BSValid payload offset v) }- }- @-}--{-@ invariant {v:ByteString | 0 <= (bLength v)} @-}--{-@ type ByteStringSplit B = {v:[ByteString] | ((bLengths v) + (len v) - 1) = (bLength B) }- @-}--{-@ type ByteStringPair B = (ByteString, ByteString)<{\x1 x2 -> (bLength x1) + (bLength x2) = (bLength B)}>- @-}---{-@ measure bLengths :: [ByteString] -> Int- bLengths [] = 0- bLengths (x:xs) = (bLength x) + (bLengths xs)- @-}---{-@ type ByteStringN N = {v : Data.ByteString.Internal.ByteString | (bLength v) = N} @-}-{-@ type ByteStringNE = {v : Data.ByteString.Internal.ByteString | (bLength v) > 0} @-}-{-@ type ByteStringSZ B = {v : Data.ByteString.Internal.ByteString | (bLength v) = (bLength B)} @-}-{-@ type ByteStringLE B = {v : Data.ByteString.Internal.ByteString | (bLength v) <= (bLength B)} @-}--{-@ predicate SuffixPtr V N P = ((isNullPtr V) || ((NNLen V N P) && (NNBase V P))) @-}-{-@ predicate NNLen V N P = ((((plen P) - N) < (plen V)) && (plen V) <= (plen P)) @-}-{-@ predicate NNBase V P = ((pbase V) = (pbase P)) @-}----- These qualifs were unsorted-{-@ qualif EqFPLen(v: int, x: ForeignPtr b): v = (fplen x) @-}-{-@ qualif EqPLen(v: int, x: Ptr b): v = (plen x) @-}----{-@ qualif EqPLen(v:Ptr a, l:int): (plen v) = l @-}-{-@ qualif EqPLen(v: ForeignPtr a, x: Ptr b): (fplen v) = (plen x) @-}-{-@ qualif EqPLen(v: Ptr a, x: ForeignPtr b): (plen v) = (fplen x) @-}-{-@ qualif PValid(v: int, p: Ptr a): v <= (plen p) @-}-{-@ qualif PLLen(v:a, p:b) : (len v) <= (plen p) @-}-{-@ qualif FPLenPos(v: ForeignPtr a): 0 <= (fplen v) @-}-{-@ qualif PLenPos(v: Ptr a): 0 <= (plen v) @-}-{-@ qualif LTPLen(v: int, p:Ptr a): v < (plen p) @-}--{-@ ptrLen :: p:(PtrV a) -> {v:Nat | v = (plen p)} @-}-ptrLen :: Ptr a -> Int-ptrLen = undefined------------------------------------------------------------------------------instance Show ByteString where- showsPrec p ps r = showsPrec p (unpackWith w2c ps) r---- LIQUID instance Read ByteString where--- LIQUID readsPrec p str = [ (packWith c2w x, y) | (x, y) <- readsPrec p str ]---- | /O(n)/ Converts a 'ByteString' to a '[a]', using a conversion function.--{-@ unpackWith :: (Word8 -> a) -> ByteString -> [a] @-}-unpackWith :: (Word8 -> a) -> ByteString -> [a]-unpackWith _ (PS _ _ 0) = []-unpackWith k (PS ps s l) = inlinePerformIO $ withForeignPtr ps $ \p ->- go (p `plusPtr` s) (l - 1) []- where- STRICT3(go)- go p 0 acc = peek p >>= \e -> return (k e : acc)- go p n acc = peekByteOff p n >>= \e -> go p (n-1) (k e : acc)-{-# INLINE unpackWith #-}------- | /O(n)/ Convert a '[a]' into a 'ByteString' using some--- conversion function--{-@ packWith :: (a -> Word8) -> [a] -> ByteString @-}-packWith :: (a -> Word8) -> [a] -> ByteString-packWith k str = unsafeCreate (length str) $ \p -> go p str- where- {-@ decrease go 2 @-}- STRICT2(go)- go _ [] = return ()- go p (x:xs) = poke p (k x) >> go (p `plusPtr` 1) xs -- less space than pokeElemOff-{-# INLINE packWith #-}------------------------------------------------------------------------------ | The 0 pointer. Used to indicate the empty Bytestring.-{-@ assume nullForeignPtr :: {v: ForeignPtr Word8 | (fplen v) = 0} @-}-nullForeignPtr :: ForeignPtr Word8-#ifdef __GLASGOW_HASKELL__-nullForeignPtr = ForeignPtr nullAddr# undefined --TODO: should ForeignPtrContents be strict?-#else-nullForeignPtr = unsafePerformIO $ newForeignPtr_ nullPtr-{-# NOINLINE nullForeignPtr #-}-#endif---- ------------------------------------------------------------------------ Low level constructors---- | /O(1)/ Build a ByteString from a ForeignPtr.------ If you do not need the offset parameter then you do should be using--- 'Data.ByteString.Unsafe.unsafePackCStringLen' or--- 'Data.ByteString.Unsafe.unsafePackCStringFinalizer' instead.-----{-@ fromForeignPtr :: p:(ForeignPtr Word8)- -> o:{v:Nat | v <= (fplen p)}- -> l:{v:Nat | (BSValid p o v)}- -> ByteStringN l- @-}-fromForeignPtr :: ForeignPtr Word8- -> Int -- ^ Offset- -> Int -- ^ Length- -> ByteString-fromForeignPtr fp s l = PS fp s l-{-# INLINE fromForeignPtr #-}---- | /O(1)/ Deconstruct a ForeignPtr from a ByteString--{-@ toForeignPtr :: b:ByteString- -> ( {v:(ForeignPtr Word8) | v = (bPayload b)}- , {v:Int | v = (bOffset b)}- , {v:Int | v = (bLength b)} )- @-}-toForeignPtr :: ByteString -> (ForeignPtr Word8, Int, Int) -- ^ (ptr, offset, length)-toForeignPtr (PS ps s l) = (ps, s, l)-{-# INLINE toForeignPtr #-}---- | A way of creating ByteStrings outside the IO monad. The @Int@--- argument gives the final size of the ByteString. Unlike--- 'createAndTrim' the ByteString is not reallocated if the final size--- is less than the estimated size.--{-@ unsafeCreate :: l:Nat -> ((PtrN Word8 l) -> IO ()) -> (ByteStringN l) @-}-unsafeCreate :: Int -> (Ptr Word8 -> IO ()) -> ByteString-unsafeCreate l f = unsafeDupablePerformIO (create l f)-{-# INLINE unsafeCreate #-}--#ifndef __GLASGOW_HASKELL__--- for Hugs, NHC etc-unsafeDupablePerformIO :: IO a -> a-unsafeDupablePerformIO = unsafePerformIO-#endif---- | Create ByteString of size @l@ and use action @f@ to fill it's contents.-{-@ create :: l:Nat -> ((PtrN Word8 l) -> IO ()) -> IO (ByteStringN l) @-}-create :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString-create l f = do- fp <- mallocByteString l- withForeignPtr fp $ \p -> f p- return $! PS fp 0 l-{-# INLINE create #-}---- | Given the maximum size needed and a function to make the contents--- of a ByteString, createAndTrim makes the 'ByteString'. The generating--- function is required to return the actual final size (<= the maximum--- size), and the resulting byte array is realloced to this size.------ createAndTrim is the main mechanism for creating custom, efficient--- ByteString functions, using Haskell or C functions to fill the space.---{-@ createAndTrim :: l:Nat- -> ((PtrN Word8 l) -> IO {v:Nat | v <= l})- -> IO {v:ByteString | (bLength v) <= l}- @-}-createAndTrim :: Int -> (Ptr Word8 -> IO Int) -> IO ByteString-createAndTrim l f = do- fp <- mallocByteString l- withForeignPtr fp $ \p -> do- l' <- f p- if assert (l' <= l) $ l' >= l- then return $! PS fp 0 l- else create l' $ \p' -> memcpy p' p ({- LIQUID fromIntegral -} intCSize l')-{-# INLINE createAndTrim #-}--{-@ createAndTrim' :: l:Nat- -> ((PtrN Word8 l) -> IO ((Nat, Nat, a)<{\o v -> (v <= l - o)}, {\o l v -> true}>))- -> IO ({v:ByteString | (bLength v) <= l}, a)- @-}-createAndTrim' :: Int -> (Ptr Word8 -> IO (Int, Int, a)) -> IO (ByteString, a)-createAndTrim' l f = do- fp <- mallocByteString l- withForeignPtr fp $ \p -> do- (off, l', res) <- f p- if assert (l' <= l) $ l' >= l- then return $! (PS fp 0 l, res)- else do ps <- create l' $ \p' ->- memcpy p' (p `plusPtr` off) ({- LIQUID fromIntegral -} intCSize l')- return $! (ps, res)---- LIQUID DUPLICATECODE-{-@ createAndTrimEQ :: l:Nat- -> ((PtrN Word8 l) -> IO ((Nat, {v:Nat | v=l}, a)<{\o v -> (v <= l - o)}, {\o l v -> true}>))- -> IO ({v:ByteString | (bLength v) = l}, a)- @-}-createAndTrimEQ :: Int -> (Ptr Word8 -> IO (Int, Int, a)) -> IO (ByteString, a)-createAndTrimEQ l f = do- fp <- mallocByteString l- withForeignPtr fp $ \p -> do- (off, l', res) <- f p- if assert (l' <= l) $ l' >= l- then return $! (PS fp 0 l, res)- else do ps <- create l' $ \p' ->- memcpy p' (p `plusPtr` off) ({- LIQUID fromIntegral -} intCSize l')- return $! (ps, res)--{-@ createAndTrimMEQ :: l:Nat- -> ((PtrN Word8 l)- -> IO ({v:(Nat, {v0:Nat | v0<=l}, Maybe a) |- (((tsnd v) <= (l-(tfst v)))- && ((isJust (ttrd v)) => ((tsnd v)=l)))}))- -> IO ({v:ByteString | (bLength v) <= l}, Maybe a)<{\b m ->- ((isJust m) => ((bLength b) = l))}>- @-}-createAndTrimMEQ :: Int -> (Ptr Word8 -> IO (Int, Int, Maybe a)) -> IO (ByteString, Maybe a)-createAndTrimMEQ l f = do- fp <- mallocByteString l- withForeignPtr fp $ \p -> do- (off, l', res) <- f p- if assert (l' <= l) $ l' >= l- then return $! (PS fp 0 l, res)- else do ps <- create l' $ \p' ->- memcpy p' (p `plusPtr` off) ({- LIQUID fromIntegral -} intCSize l')- return $! (ps, res)--{-@ measure tfst :: (a,b,c) -> a- tfst (a,b,c) = a- @-}--{-@ measure tsnd :: (a,b,c) -> b- tsnd (a,b,c) = b- @-}--{-@ measure ttrd :: (a,b,c) -> c- ttrd (a,b,c) = c- @-}------ LIQUID CONSTRUCTIVE VERSION (Till we support pred-applications properly,--- cf. tests/pos/cont2.hs--{-@ createAndTrim'' :: forall <p :: Int -> Bool>.- l:Nat<p>- -> ((PtrN Word8 l) -> IO ((Nat, Nat<p>, a)<{\o v -> (v <= l - o)}, {\o l v -> true}>))- -> IO ({v:Nat<p> | v <= l}, ByteString, a)<{\sz v -> (bLength v) = sz},{\o l v -> true}>- @-}--createAndTrim'' :: Int -> (Ptr Word8 -> IO (Int, Int, a)) -> IO (Int, ByteString, a)-createAndTrim'' l f = do- fp <- mallocByteString l- withForeignPtr fp $ \p -> do- (off, l', res) <- f p- if assert (l' <= l) $ l' >= l- then return $! (l, PS fp 0 l, res)- else do ps <- create l' $ \p' ->- memcpy p' (p `plusPtr` off) ({- LIQUID fromIntegral -} intCSize l')- return $! (l', ps, res)-------- | Wrapper of 'mallocForeignPtrBytes' with faster implementation for GHC----{-@ mallocByteString :: l:Nat -> IO (ForeignPtrN a l) @-}-mallocByteString :: Int -> IO (ForeignPtr a)-mallocByteString l = do-#ifdef __GLASGOW_HASKELL__- mallocPlainForeignPtrBytes l-#else- mallocForeignPtrBytes l-#endif-{-# INLINE mallocByteString #-}------------------------------------------------------------------------------ | Conversion between 'Word8' and 'Char'. Should compile to a no-op.-w2c :: Word8 -> Char-#if !defined(__GLASGOW_HASKELL__)-w2c = chr . fromIntegral-#else-w2c = unsafeChr . fromIntegral-#endif-{-# INLINE w2c #-}---- | Unsafe conversion between 'Char' and 'Word8'. This is a no-op and--- silently truncates to 8 bits Chars > '\255'. It is provided as--- convenience for ByteString construction.-c2w :: Char -> Word8-c2w = fromIntegral . ord-{-# INLINE c2w #-}---- | Selects words corresponding to white-space characters in the Latin-1 range--- ordered by frequency.-isSpaceWord8 :: Word8 -> Bool-isSpaceWord8 w =- w == 0x20 ||- w == 0x0A || -- LF, \n- w == 0x09 || -- HT, \t- w == 0x0C || -- FF, \f- w == 0x0D || -- CR, \r- w == 0x0B || -- VT, \v- w == 0xA0 -- spotted by QC..-{-# INLINE isSpaceWord8 #-}---- | Selects white-space characters in the Latin-1 range-isSpaceChar8 :: Char -> Bool-isSpaceChar8 c =- c == ' ' ||- c == '\t' ||- c == '\n' ||- c == '\r' ||- c == '\f' ||- c == '\v' ||- c == '\xa0'-{-# INLINE isSpaceChar8 #-}------------------------------------------------------------------------------ | Just like unsafePerformIO, but we inline it. Big performance gains as--- it exposes lots of things to further inlining. /Very unsafe/. In--- particular, you should do no memory allocation inside an--- 'inlinePerformIO' block. On Hugs this is just @unsafePerformIO@.----{-# INLINE inlinePerformIO #-}-{-@ assume inlinePerformIO :: IO a -> a @-}-inlinePerformIO :: IO a -> a-#if defined(__GLASGOW_HASKELL__)-inlinePerformIO (IO m) = case m realWorld# of (# _, r #) -> r-#else-inlinePerformIO = unsafePerformIO-#endif---- --------------------------------------------------------------------------- Standard C functions------- LIQUID ANFTransform scope wierdness, see Internal0.hs--- LIQUID-foreign import ccall unsafe "string.h strlen" c_strlen- :: CString -> IO CSize-{-@ assume c_strlen :: s:_ -> IO {v: CSize | (0 <= v && v = plen s) } @-}---- LIQUID: for some reason this foreign import causes an infinite loop...--- foreign import ccall unsafe "static stdlib.h &free" c_free_finalizer--- :: Ptr Word8 -> IO ()-c_free_finalizer = finalizerFree--foreign import ccall unsafe "string.h memchr" c_memchr- :: Ptr Word8 -> CInt -> CSize -> IO (Ptr Word8)-{-@ assume c_memchr :: p:(Ptr Word8) -> CInt -> n:{v:CSize| (0 <= v && v <= (plen p))} -> (IO {v:(Ptr Word8) | (SuffixPtr v n p)}) @-}---{-@ memchr :: p:(Ptr Word8) -> Word8 -> n:{v:CSize| (0 <= v && v <= (plen p))} -> (IO {v:(Ptr Word8) | (SuffixPtr v n p)}) @-}-memchr :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)-memchr p w s = c_memchr p (fromIntegral w) s--foreign import ccall unsafe "string.h memcmp" memcmp- :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt-{-@ assume memcmp :: p:(Ptr Word8) -> q:(Ptr Word8) -> {v:CSize | (v <= (plen p) && v <= (plen q)) } -> IO Foreign.C.Types.CInt @-}--foreign import ccall unsafe "string.h memcpy" c_memcpy- :: Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)-{-@ assume- memcpy :: dst:(PtrV Word8)- -> src:(PtrV Word8)- -> size: {v:CSize| (v <= (plen src) && v <= (plen dst))}- -> IO ()- @-}-memcpy :: Ptr Word8 -> Ptr Word8 -> CSize -> IO ()-memcpy p q s = c_memcpy p q s >> return ()---{- liquidCanary :: x:Int -> {v: Int | v > x} @-}-liquidCanary :: Int -> Int-liquidCanary x = x - 1--{--foreign import ccall unsafe "string.h memmove" c_memmove- :: Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)--memmove :: Ptr Word8 -> Ptr Word8 -> CSize -> IO ()-memmove p q s = do c_memmove p q s- return ()--}--foreign import ccall unsafe "string.h memset" c_memset- :: Ptr Word8 -> CInt -> CSize -> IO (Ptr Word8)--memset :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)-memset p w s = c_memset p (fromIntegral w) s---- --------------------------------------------------------------------------- Uses our C code-----foreign import ccall unsafe "static fpstring.h fps_reverse" c_reverse- :: Ptr Word8 -> Ptr Word8 -> CULong -> IO ()--{-@ assume c_reverse :: dst:(PtrV Word8) -> src:(PtrV Word8) -> {v:CULong | ((OkPLen v src) && (OkPLen v dst)) } -> IO () @-}--foreign import ccall unsafe "static fpstring.h fps_intersperse" c_intersperse- :: Ptr Word8 -> Ptr Word8 -> CULong -> Word8 -> IO ()-{-@ assume c_intersperse :: dst:(Ptr Word8) -> src:(Ptr Word8) -> {v: CULong | ((OkPLen v src) && ((v+v-1) <= (plen dst)))} -> Word8 -> IO () @-}---foreign import ccall unsafe "static fpstring.h fps_maximum" c_maximum- :: Ptr Word8 -> CULong -> IO Word8-{-@ assume c_maximum :: p:(Ptr Word8) -> {v:CULong | (OkPLen v p)} -> IO Word8 @-}--foreign import ccall unsafe "static fpstring.h fps_minimum" c_minimum- :: Ptr Word8 -> CULong -> IO Word8-{-@ assume c_minimum :: p:(Ptr Word8) -> {v:CULong | (OkPLen v p)} -> IO Word8 @-}--foreign import ccall unsafe "static fpstring.h fps_count" c_count- :: Ptr Word8 -> CULong -> Word8 -> IO CULong-{-@ assume- c_count :: p:(Ptr Word8)- -> n:{v:CULong | (OkPLen v p)}- -> Word8- -> (IO {v:CULong | ((0 <= v) && (v <= n)) }) @-}----- ------------------------------------------------------------------------ Internal GHC Haskell magic--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 611-foreign import ccall unsafe "__hscore_memcpy_src_off"- memcpy_ptr_baoff :: Ptr a -> RawBuffer -> CInt -> CSize -> IO (Ptr ())-#endif
@@ -1,1705 +0,0 @@-{-@ LIQUID "--no-totality" @-}-{-@ LIQUID "--pruneunsorted" @-}--{-# OPTIONS_GHC -cpp -fglasgow-exts -fno-warn-orphans -fno-warn-incomplete-patterns #-}---- #prune---- |--- Module : Data.ByteString.Lazy--- Copyright : (c) Don Stewart 2006--- (c) Duncan Coutts 2006--- License : BSD-style------ Maintainer : dons@galois.com--- Stability : experimental--- Portability : portable--- --- A time and space-efficient implementation of lazy byte vectors--- using lists of packed 'Word8' arrays, suitable for high performance--- use, both in terms of large data quantities, or high speed--- requirements. Byte vectors are encoded as lazy lists of strict 'Word8'--- arrays of bytes. They provide a means to manipulate large byte vectors--- without requiring the entire vector be resident in memory.------ Some operations, such as concat, append, reverse and cons, have--- better complexity than their "Data.ByteString" equivalents, due to--- optimisations resulting from the list spine structure. And for other--- operations lazy ByteStrings are usually within a few percent of--- strict ones, but with better heap usage. For data larger than the--- available memory, or if you have tight memory constraints, this--- module will be the only option. The default chunk size is 64k, which--- should be good in most circumstances. For people with large L2--- caches, you may want to increase this to fit your cache.------ This module is intended to be imported @qualified@, to avoid name--- clashes with "Prelude" functions. eg.------ > import qualified Data.ByteString.Lazy as B------ Original GHC implementation by Bryan O\'Sullivan.--- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.--- Rewritten to support slices and use 'Foreign.ForeignPtr.ForeignPtr'--- by David Roundy.--- Polished and extended by Don Stewart.--- Lazy variant by Duncan Coutts and Don Stewart.-----module Data.ByteString.Lazy (-- -- * The @ByteString@ type- ByteString, -- instances: Eq, Ord, Show, Read, Data, Typeable-- -- * Introducing and eliminating 'ByteString's- empty, -- :: ByteString- singleton, -- :: Word8 -> ByteString- pack, -- :: [Word8] -> ByteString- unpack, -- :: ByteString -> [Word8]- fromChunks, -- :: [Strict.ByteString] -> ByteString- toChunks, -- :: ByteString -> [Strict.ByteString]-- -- * Basic interface- cons, -- :: Word8 -> ByteString -> ByteString- cons', -- :: Word8 -> ByteString -> ByteString- snoc, -- :: ByteString -> Word8 -> ByteString- append, -- :: ByteString -> ByteString -> ByteString- head, -- :: ByteString -> Word8- uncons, -- :: ByteString -> Maybe (Word8, ByteString)- last, -- :: ByteString -> Word8- tail, -- :: ByteString -> ByteString- init, -- :: ByteString -> ByteString- null, -- :: ByteString -> Bool- length, -- :: ByteString -> Int64-- -- * Transforming ByteStrings- map, -- :: (Word8 -> Word8) -> ByteString -> ByteString- reverse, -- :: ByteString -> ByteString- intersperse, -- :: Word8 -> ByteString -> ByteString- intercalate, -- :: ByteString -> [ByteString] -> ByteString- transpose, -- :: [ByteString] -> [ByteString]-- -- * Reducing 'ByteString's (folds)- foldl, -- :: (a -> Word8 -> a) -> a -> ByteString -> a- foldl', -- :: (a -> Word8 -> a) -> a -> ByteString -> a- foldl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8- foldl1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8- foldr, -- :: (Word8 -> a -> a) -> a -> ByteString -> a- foldr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-- -- ** Special folds- concat, -- :: [ByteString] -> ByteString- concatMap, -- :: (Word8 -> ByteString) -> ByteString -> ByteString- any, -- :: (Word8 -> Bool) -> ByteString -> Bool- all, -- :: (Word8 -> Bool) -> ByteString -> Bool- maximum, -- :: ByteString -> Word8- minimum, -- :: ByteString -> Word8-- -- * Building ByteStrings- -- ** Scans- scanl, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString--- scanl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString--- scanr, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString--- scanr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString-- -- ** Accumulating maps- mapAccumL, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)- mapAccumR, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)- mapIndexed, -- :: (Int64 -> Word8 -> Word8) -> ByteString -> ByteString-- -- ** Infinite ByteStrings- repeat, -- :: Word8 -> ByteString- replicate, -- :: Int64 -> Word8 -> ByteString- cycle, -- :: ByteString -> ByteString- iterate, -- :: (Word8 -> Word8) -> Word8 -> ByteString-- -- ** Unfolding ByteStrings- unfoldr, -- :: (a -> Maybe (Word8, a)) -> a -> ByteString-- -- * Substrings-- -- ** Breaking strings- take, -- :: Int64 -> ByteString -> ByteString- drop, -- :: Int64 -> ByteString -> ByteString- splitAt, -- :: Int64 -> ByteString -> (ByteString, ByteString)- takeWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString- dropWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString- span, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- break, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)- group, -- :: ByteString -> [ByteString]- groupBy, -- :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]- inits, -- :: ByteString -> [ByteString]- tails, -- :: ByteString -> [ByteString]-- -- ** Breaking into many substrings- split, -- :: Word8 -> ByteString -> [ByteString]- splitWith, -- :: (Word8 -> Bool) -> ByteString -> [ByteString]-- -- * Predicates- isPrefixOf, -- :: ByteString -> ByteString -> Bool- isSuffixOf, -- :: ByteString -> ByteString -> Bool--- isInfixOf, -- :: ByteString -> ByteString -> Bool-- -- ** Search for arbitrary substrings--- isSubstringOf, -- :: ByteString -> ByteString -> Bool--- findSubstring, -- :: ByteString -> ByteString -> Maybe Int--- findSubstrings, -- :: ByteString -> ByteString -> [Int]-- -- * Searching ByteStrings-- -- ** Searching by equality- elem, -- :: Word8 -> ByteString -> Bool- notElem, -- :: Word8 -> ByteString -> Bool-- -- ** Searching with a predicate- find, -- :: (Word8 -> Bool) -> ByteString -> Maybe Word8- filter, -- :: (Word8 -> Bool) -> ByteString -> ByteString- partition, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-- -- * Indexing ByteStrings- index, -- :: ByteString -> Int64 -> Word8- elemIndex, -- :: Word8 -> ByteString -> Maybe Int64- elemIndices, -- :: Word8 -> ByteString -> [Int64]- findIndex, -- :: (Word8 -> Bool) -> ByteString -> Maybe Int64- findIndices, -- :: (Word8 -> Bool) -> ByteString -> [Int64]- count, -- :: Word8 -> ByteString -> Int64-- -- * Zipping and unzipping ByteStrings- zip, -- :: ByteString -> ByteString -> [(Word8,Word8)]- zipWith, -- :: (Word8 -> Word8 -> c) -> ByteString -> ByteString -> [c]- unzip, -- :: [(Word8,Word8)] -> (ByteString,ByteString)-- -- * Ordered ByteStrings--- sort, -- :: ByteString -> ByteString-- -- * Low level conversions- -- ** Copying ByteStrings- copy, -- :: ByteString -> ByteString--- defrag, -- :: ByteString -> ByteString-- -- * I\/O with 'ByteString's-- -- ** Standard input and output- getContents, -- :: IO ByteString- putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO ()- interact, -- :: (ByteString -> ByteString) -> IO ()-- -- ** Files- readFile, -- :: FilePath -> IO ByteString- writeFile, -- :: FilePath -> ByteString -> IO ()- appendFile, -- :: FilePath -> ByteString -> IO ()-- -- ** I\/O with Handles- hGetContents, -- :: Handle -> IO ByteString- hGet, -- :: Handle -> Int -> IO ByteString- hGetNonBlocking, -- :: Handle -> Int -> IO ByteString- hPut, -- :: Handle -> ByteString -> IO ()- hPutStr, -- :: Handle -> ByteString -> IO ()---- hGetN, -- :: Int -> Handle -> Int -> IO ByteString--- hGetContentsN, -- :: Int -> Handle -> IO ByteString--- hGetNonBlockingN, -- :: Int -> Handle -> IO ByteString-- -- undocumented deprecated things:- join -- :: ByteString -> [ByteString] -> ByteString-- ) where--import Language.Haskell.Liquid.Prelude (unsafeError)-import qualified Prelude-import Prelude hiding- (reverse,head,tail,last,init,null,length,map,lines,foldl,foldr,unlines- ,concat,any,take,drop,splitAt,takeWhile,dropWhile,span,break,elem,filter,maximum- ,minimum,all,concatMap,foldl1,foldr1,scanl, scanl1, scanr, scanr1- ,repeat, cycle, interact, iterate,readFile,writeFile,appendFile,replicate- ,getContents,getLine,putStr,putStrLn ,zip,zipWith,unzip,notElem)--import qualified Data.List as L -- L for list/lazy-import qualified Data.ByteString as S -- S for strict (hmm...)-import qualified Data.ByteString.Internal as S-import qualified Data.ByteString.Unsafe as S-import Data.ByteString.Lazy.Internal-import qualified Data.ByteString.Fusion as F--import Data.Monoid (Monoid(..))--import Data.Word (Word8,Word64)-import Data.Int (Int64)-import qualified Data.List-import System.IO (Handle,stdin,stdout,openBinaryFile,IOMode(..)- ,hClose,hWaitForInput,hIsEOF)-import System.IO.Unsafe-#ifndef __NHC__-import Control.Exception (bracket)-#else-import IO (bracket)-#endif--import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr-import Foreign.Storable----LIQUID-import Data.ByteString.Fusion (PairS(..), MaybeS(..))-import Data.Int-import Data.Word (Word, Word8, Word16, Word32, Word64)-import Foreign.ForeignPtr (ForeignPtr)---{-@ measure sumLens :: [[a]] -> Int- sumLens [] = 0- sumLens (x:xs) = len x + (sumLens xs)- @-}-{-@ invariant {v:[[a]] | sumLens v >= 0} @-}-{-@ qualif SumLensEq(v:List (List a), x:List (List a)): (sumLens v) = (sumLens x) @-}-{-@ qualif SumLensEq(v:List (List a), x:List a): (sumLens v) = (len x) @-}-{-@ qualif SumLensLe(v:List (List a), x:List (List a)): (sumLens v) <= (sumLens x) @-}---- ByteString qualifiers-{-@ qualif LBLensAcc(v:ByteString,- bs:List ByteString,- b:ByteString):- lbLength(v) = lbLengths(bs) + lbLength(b)- @-}--{-@ qualif ByteStringNE(v:Data.ByteString.Internal.ByteString): (bLength v) > 0 @-}-{-@ qualif BLengthsAcc(v:List Data.ByteString.Internal.ByteString,- c:Data.ByteString.Internal.ByteString,- cs:List Data.ByteString.Internal.ByteString):- (bLengths v) = (bLength c) + (bLengths cs)- @-}--{-@ qualif BLengthsSum(v:List (List a), bs:List Data.ByteString.Internal.ByteString):- (sumLens v) = (bLengths bs)- @-}--{-@ qualif BLenLE(v:Data.ByteString.Internal.ByteString, n:int): (bLength v) <= n @-}-{-@ qualif BLenEq(v:Data.ByteString.Internal.ByteString,- b:Data.ByteString.Internal.ByteString):- (bLength v) = (bLength b)- @-}--{-@ qualif BLenAcc(v:int,- b1:Data.ByteString.Internal.ByteString,- b2:Data.ByteString.Internal.ByteString):- v = (bLength b1) + (bLength b2)- @-}-{-@ qualif BLenAcc(v:int,- b:Data.ByteString.Internal.ByteString,- n:int):- v = (bLength b) + n- @-}---- lazy ByteString qualifiers-{-@ qualif LByteStringN(v:ByteString, n:int): (lbLength v) = n @-}-{-@ qualif LByteStringNE(v:ByteString): (lbLength v) > 0 @-}-{-@ qualif LByteStringSZ(v:ByteString,- b:ByteString):- (lbLength v) = (lbLength b)- @-}--{-@ qualif LBLenAcc(v:int,- b1:ByteString,- b2:ByteString):- v = (lbLength b1) + (lbLength b2)- @-}--{-@ qualif LBLenAcc(v:int,- b:ByteString,- n:int):- v = (lbLength b) + n- @-}--{-@ qualif Chunk(v:ByteString,- sb:Data.ByteString.Internal.ByteString,- lb:ByteString):- (lbLength v) = (bLength sb) + (lbLength lb)- @-}----LIQUID for the myriad `comb` inner functions-{-@ qualif LBComb(v:List ByteString,- acc:List Data.ByteString.Internal.ByteString,- ss:List Data.ByteString.Internal.ByteString,- cs:ByteString):- ((lbLengths v) + (len v) - 1) = ((bLengths acc) + ((bLengths ss) + (len ss) - 1) + (lbLength cs))- @-}--{-@ qualif LBGroup(v:List ByteString,- acc:List Data.ByteString.Internal.ByteString,- ss:List Data.ByteString.Internal.ByteString,- cs:ByteString):- (lbLengths v) = ((bLengths acc) + (bLengths ss) + (lbLength cs))- @-}--{-@ qualif LBLenIntersperse(v:ByteString,- sb:Data.ByteString.Internal.ByteString,- lb:ByteString):- (lbLength v) = ((bLength sb) * 2) + (lbLength lb)- @-}--{-@ qualif BLenDouble(v:Data.ByteString.Internal.ByteString,- b:Data.ByteString.Internal.ByteString):- (bLength v) = (bLength b) * 2- @-}--{-@ qualif LBLenDouble(v:ByteString,- b:ByteString):- (lbLength v) = (lbLength b) * 2- @-}--{-@ qualif RevChunksAcc(v:ByteString,- acc:ByteString,- cs:List Data.ByteString.Internal.ByteString):- (lbLength v) = (lbLength acc) + (bLengths cs)- @-}--{-@ qualif LBSumLens(v:ByteString,- z:ByteString,- cs:List (List a)):- (lbLength v) = (lbLength z) + (sumLens cs)- @-}-{-@ qualif LBCountAcc(v:int,- c:Data.ByteString.Internal.ByteString,- cs:ByteString):- v <= (bLength c) + (lbLength cs)- @-}----- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined---- -------------------------------------------------------------------------------instance Eq ByteString- where (==) = eq--instance Ord ByteString- where compare = cmp--instance Semigroup ByteString where -- REBARE - x <> y = append x y -- REBARE--instance Monoid ByteString where- mempty = empty- -- REBARE mappend = append- -- REBARE mconcat = concat--{-@ eq :: ByteString -> ByteString -> Bool @-}-eq :: ByteString -> ByteString -> Bool-eq Empty Empty = True-eq Empty _ = False-eq _ Empty = False-eq (Chunk a as) (Chunk b bs) =- case compare (S.length a) (S.length b) of- LT -> a == (S.take (S.length a) b) && eq as (Chunk (S.drop (S.length a) b) bs)- EQ -> a == b && eq as bs- GT -> (S.take (S.length b) a) == b && eq (Chunk (S.drop (S.length b) a) as) bs--{-@ cmp :: ByteString -> ByteString -> Ordering @-}-cmp :: ByteString -> ByteString -> Ordering-cmp Empty Empty = EQ-cmp Empty _ = LT-cmp _ Empty = GT-cmp (Chunk a as) (Chunk b bs) =- case compare (S.length a) (S.length b) of- LT -> case compare a (S.take (S.length a) b) of- EQ -> cmp as (Chunk (S.drop (S.length a) b) bs)- result -> result- EQ -> case compare a b of- EQ -> cmp as bs- result -> result- GT -> case compare (S.take (S.length b) a) b of- EQ -> cmp (Chunk (S.drop (S.length b) a) as) bs- result -> result---- -------------------------------------------------------------------------------- Introducing and eliminating 'ByteString's---- | /O(1)/ The empty 'ByteString'-{-@ empty :: {v:ByteString | (lbLength v) = 0} @-}-empty :: ByteString-empty = Empty-{-# INLINE empty #-}---- | /O(1)/ Convert a 'Word8' into a 'ByteString'-{-@ singleton :: Word8 -> {v:ByteString | (lbLength v) = 1} @-}-singleton :: Word8 -> ByteString-singleton w = Chunk (S.singleton w) Empty-{-# INLINE singleton #-}---- | /O(n)/ Convert a '[Word8]' into a 'ByteString'. -{-@ pack :: cs:[Word8] -> {v:ByteString | (lbLength v) = (len cs)} @-}-pack :: [Word8] -> ByteString---LIQUID INLINE pack ws = L.foldr (Chunk . S.pack) Empty (chunks defaultChunkSize ws)-pack ws = go Empty (chunks defaultChunkSize ws)- where- {-@ decrease go 2 @-}- go z [] = z- go z (c:cs) = Chunk (S.pack c) (go z cs)- {-@ decrease chunks 2 @-}- chunks :: Int -> [a] -> [[a]]- chunks _ [] = []- chunks size xs = case L.splitAt size xs of- (xs', xs'') -> xs' : chunks size xs''---- | /O(n)/ Converts a 'ByteString' to a '[Word8]'.--- TODO: disabled because type of `concat` changed between ghc 7.8 and 7.10-{-@ assume unpack :: b:_ -> {v:[_] | (len v) = (lbLength b)} @-}-unpack :: ByteString -> [Word8]---LIQUID INLINE unpack cs = L.concatMap S.unpack (toChunks cs)-unpack cs = L.concat $ mapINLINE $ toChunks cs- where mapINLINE [] = []- mapINLINE (c:cs) = S.unpack c : mapINLINE cs---TODO: we can do better here by integrating the concat with the unpack---- | /O(c)/ Convert a list of strict 'ByteString' into a lazy 'ByteString'-{-@ fromChunks :: bs:_ -> {v:_ | (lbLength v) = (bLengths bs)} @-}-fromChunks :: [S.ByteString] -> ByteString---LIQUID INLINE fromChunks cs = L.foldr chunk Empty cs-fromChunks [] = Empty-fromChunks (c:cs) = chunk c (fromChunks cs)---- | /O(n)/ Convert a lazy 'ByteString' into a list of strict 'ByteString'-{-@ toChunks :: b:_ -> {v:_ | (bLengths v) = (lbLength b)} @-}-toChunks :: ByteString -> [S.ByteString]---LIQUID GHOST toChunks cs = foldrChunks (:) [] cs-toChunks cs = foldrChunks (const (:)) [] cs----------------------------------------------------------------------------{---- | /O(n)/ Convert a '[a]' into a 'ByteString' using some--- conversion function-packWith :: (a -> Word8) -> [a] -> ByteString-packWith k str = LPS $ L.map (P.packWith k) (chunk defaultChunkSize str)-{-# INLINE packWith #-}-{-# SPECIALIZE packWith :: (Char -> Word8) -> [Char] -> ByteString #-}---- | /O(n)/ Converts a 'ByteString' to a '[a]', using a conversion function.-unpackWith :: (Word8 -> a) -> ByteString -> [a]-unpackWith k (LPS ss) = L.concatMap (S.unpackWith k) ss-{-# INLINE unpackWith #-}-{-# SPECIALIZE unpackWith :: (Word8 -> Char) -> ByteString -> [Char] #-}--}---- ------------------------------------------------------------------------ Basic interface---- | /O(1)/ Test whether a ByteString is empty.-{-@ null :: b:ByteString -> {v:Bool | v <=> (lbLength b = 0)} @-}-null :: ByteString -> Bool-null Empty = True-null _ = False-{-# INLINE null #-}---- | /O(n\/c)/ 'length' returns the length of a ByteString as an 'Int64'-{-@ length :: b:ByteString -> {v:Int64 | v = (lbLength b)} @-}-length :: ByteString -> Int64---LIQUID GHOST length cs = foldlChunks (\n c -> n + fromIntegral (S.length c)) 0 cs-length cs = foldrChunks (\_ c n -> n + fromIntegral (S.length c)) 0 cs-{-# INLINE length #-}---- | /O(1)/ 'cons' is analogous to '(:)' for lists.----{-@ cons :: Word8 -> b:ByteString -> {v:ByteString | (lbLength v) = ((lbLength b) + 1)}- @-}-cons :: Word8 -> ByteString -> ByteString-cons c cs = Chunk (S.singleton c) cs-{-# INLINE cons #-}---- | /O(1)/ Unlike 'cons', 'cons\'' is--- strict in the ByteString that we are consing onto. More precisely, it forces--- the head and the first chunk. It does this because, for space efficiency, it--- may coalesce the new byte onto the first \'chunk\' rather than starting a--- new \'chunk\'.------ So that means you can't use a lazy recursive contruction like this:------ > let xs = cons\' c xs in xs------ You can however use 'cons', as well as 'repeat' and 'cycle', to build--- infinite lazy ByteStrings.----{-@ cons' :: Word8 -> b:ByteString -> {v:ByteString | (lbLength v) = ((lbLength b) + 1)} @-}-cons' :: Word8 -> ByteString -> ByteString-cons' w (Chunk c cs) | S.length c < 16 = Chunk (S.cons w c) cs-cons' w cs = Chunk (S.singleton w) cs-{-# INLINE cons' #-}---- | /O(n\/c)/ Append a byte to the end of a 'ByteString'-{-@ snoc :: b:ByteString -> Word8 -> {v:ByteString | (lbLength v) = ((lbLength b) + 1)} @-}-snoc :: ByteString -> Word8 -> ByteString---LIQUID GHOST snoc cs w = foldrChunks Chunk (singleton w) cs-snoc cs w = foldrChunks (const Chunk) (singleton w) cs-{-# INLINE snoc #-}---- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.-{-@ head :: LByteStringNE -> Word8 @-}-head :: ByteString -> Word8-head Empty = errorEmptyList "head"-head (Chunk c _) = S.unsafeHead c-{-# INLINE head #-}---- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing--- if it is empty.-{-@ uncons :: b:ByteString- -> Maybe (Word8, {v:ByteString | (lbLength v) = (lbLength b) - 1})- @-}-uncons :: ByteString -> Maybe (Word8, ByteString)-uncons Empty = Nothing-uncons (Chunk c cs)- = Just (S.unsafeHead c,- if S.length c == 1 then cs else Chunk (S.unsafeTail c) cs)-{-# INLINE uncons #-}---- | /O(1)/ Extract the elements after the head of a ByteString, which must be--- non-empty.-{-@ tail :: b:LByteStringNE -> {v:ByteString | (lbLength v) = ((lbLength b) - 1)} @-}-tail :: ByteString -> ByteString-tail Empty = errorEmptyList "tail"-tail (Chunk c cs)- | S.length c == 1 = cs- | otherwise = Chunk (S.unsafeTail c) cs-{-# INLINE tail #-}---- | /O(n\/c)/ Extract the last element of a ByteString, which must be finite--- and non-empty.-{-@ last :: LByteStringNE -> Word8 @-}-last :: ByteString -> Word8-last Empty = errorEmptyList "last"-last (Chunk c0 cs0) = go c0 cs0- {-@ decrease go 2 @-}- where go c Empty = S.last c- go _ (Chunk c cs) = go c cs--- XXX Don't inline this. Something breaks with 6.8.2 (haven't investigated yet)--{-@ qualif LBLenAcc(v:ByteString,- sb:S.ByteString,- lb:ByteString):- (lbLength v) = ((bLength sb) + (lbLength lb) - 1)- @-}---- | /O(n\/c)/ Return all the elements of a 'ByteString' except the last one.-{-@ init :: b:LByteStringNE -> {v:ByteString | (lbLength v) = ((lbLength b) - 1)} @-}-init :: ByteString -> ByteString--- init Empty = errorEmptyList "init"-init (Chunk c0 cs0) = goInit c0 cs0- -{-@ goInit :: c:{Data.ByteString.Internal.ByteString | bLength c > 0} -> cs:ByteString -> {v:ByteString | lbLength v = bLength c + lbLength cs - 1} / [lbLength cs] @-}-goInit :: S.ByteString -> ByteString -> ByteString-goInit c Empty | S.length c == 1 = Empty- | otherwise = Chunk (S.init c) Empty-goInit c (Chunk c' cs) = Chunk c (goInit c' cs)----- | /O(n\/c)/ Append two ByteStrings-{-@ append :: b1:ByteString -> b2:ByteString- -> {v:ByteString | (lbLength v) = (lbLength b1) + (lbLength b2)}- @-}-append :: ByteString -> ByteString -> ByteString---LIQUID GHOST append xs ys = foldrChunks Chunk ys xs-append xs ys = foldrChunks (const Chunk) ys xs-{-# INLINE append #-}---- ------------------------------------------------------------------------ Transformations---- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each--- element of @xs@.-{-@ map :: (Word8 -> Word8) -> b:ByteString -> (LByteStringSZ b) @-}-map :: (Word8 -> Word8) -> ByteString -> ByteString-map f s = map_go s- where- --LIQUID RENAME- map_go Empty = Empty- map_go (Chunk x xs) = Chunk y ys- where- y = S.map f x- ys = map_go xs-{-# INLINE map #-}---- | /O(n)/ 'reverse' @xs@ returns the elements of @xs@ in reverse order.-{-@ reverse :: b:ByteString -> (LByteStringSZ b) @-}-reverse :: ByteString -> ByteString-reverse cs0 = rev Empty cs0- {-@ decrease rev 2 @-}- where rev a Empty = a- rev a (Chunk c cs) = rev (Chunk (S.reverse c) a) cs-{-# INLINE reverse #-}---- | The 'intersperse' function takes a 'Word8' and a 'ByteString' and--- \`intersperses\' that byte between the elements of the 'ByteString'.--- It is analogous to the intersperse function on Lists.-{-@ intersperse :: Word8 -> b:ByteString- -> {v:ByteString | if (lbLength b > 0) then (lbLength v = (2 * lbLength b) - 1) else (lbLength v = 0) }- @-}-intersperse :: Word8 -> ByteString -> ByteString-intersperse _ Empty = Empty-intersperse w (Chunk c cs) = Chunk (S.intersperse w c)- --LIQUID GHOST (foldrChunks (Chunk . intersperse') Empty cs)- (foldrChunks (\_ c cs -> Chunk (intersperse' c) cs) Empty cs)- where intersperse' :: S.ByteString -> S.ByteString- intersperse' (S.PS fp o l) =- S.unsafeCreate {-LIQUID MULTIPLY (2*l)-} (l+l) $ \p' -> withForeignPtr fp $ \p -> do- poke p' w- S.c_intersperse (p' `plusPtr` 1) (p `plusPtr` o) (fromIntegral l) w---- | The 'transpose' function transposes the rows and columns of its--- 'ByteString' argument.-transpose :: [ByteString] -> [ByteString]-transpose css = L.map (\ss -> Chunk (S.pack ss) Empty)- (L.transpose (L.map unpack css))---TODO: make this fast---- REBARE: somehow with GHC 8.4 importing Data.List actually ends up importing Data.OldList ... -{-@ assume Data.OldList.transpose :: [[a]] -> [{v:[a] | (len v) > 0}] @-}----- ------------------------------------------------------------------------ Reducing 'ByteString's---- | 'foldl', applied to a binary operator, a starting value (typically--- the left-identity of the operator), and a ByteString, reduces the--- ByteString using the binary operator, from left to right.-foldl :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl f z = go z- where go a Empty = a- go a (Chunk c cs) = go (S.foldl f a c) cs-{-# INLINE foldl #-}---- | 'foldl\'' is like 'foldl', but strict in the accumulator.-foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl' f z = go z- where go a _ | a `seq` False = undefined- go a Empty = a- go a (Chunk c cs) = go (S.foldl f a c) cs-{-# INLINE foldl' #-}---- | 'foldr', applied to a binary operator, a starting value--- (typically the right-identity of the operator), and a ByteString,--- reduces the ByteString using the binary operator, from right to left.-foldr :: (Word8 -> a -> a) -> a -> ByteString -> a---LIQUID GHOST foldr k z cs = foldrChunks (flip (S.foldr k)) z cs-foldr k z cs = foldrChunks (const $ flip (S.foldr k)) z cs-{-# INLINE foldr #-}---- | 'foldl1' is a variant of 'foldl' that has no starting value--- argument, and thus must be applied to non-empty 'ByteStrings'.--- This function is subject to array fusion.----LIQUID FIXME: S.unsafeTail breaks the lazy invariant, but since the---bytestring is immediately consumed by foldl it may actually be safe--{-@ foldl1 :: (Word8 -> Word8 -> Word8) -> LByteStringNE -> Word8 @-}-foldl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldl1 _ Empty = errorEmptyList "foldl1"---LIQUID SAFETY foldl1 f (Chunk c cs) = foldl f (S.unsafeHead c) (Chunk (S.unsafeTail c) cs)-foldl1 f (Chunk c cs) = foldl f (S.unsafeHead c)- (case S.unsafeTail c of- c' | S.null c' -> cs- | otherwise -> Chunk c cs)---- | 'foldl1\'' is like 'foldl1', but strict in the accumulator.-{-@ foldl1' :: (Word8 -> Word8 -> Word8) -> LByteStringNE -> Word8 @-}-foldl1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldl1' _ Empty = errorEmptyList "foldl1'"---LIQUID SAFETY foldl1' f (Chunk c cs) = foldl' f (S.unsafeHead c) (Chunk (S.unsafeTail c) cs)-foldl1' f (Chunk c cs) = foldl' f (S.unsafeHead c)- (case S.unsafeTail c of- c' | S.null c' -> cs- | otherwise -> Chunk c cs)---- | 'foldr1' is a variant of 'foldr' that has no starting value argument,--- and thus must be applied to non-empty 'ByteString's-{-@ foldr1 :: (Word8 -> Word8 -> Word8) -> LByteStringNE -> Word8 @-}-foldr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8-foldr1 _ Empty = errorEmptyList "foldr1"-foldr1 f (Chunk c0 cs0) = go c0 cs0- {-@ decrease go 2 @-}- where go c Empty = S.foldr1 f c- go c (Chunk c' cs) = S.foldr f (go c' cs) c---- ------------------------------------------------------------------------ Special folds---- | /O(n)/ Concatenate a list of ByteStrings.-{-@ lazy concat @-}-{-@ concat :: bs:[ByteString] -> {v:ByteString | (lbLength v) = (lbLengths bs)} @-}-concat :: [ByteString] -> ByteString-concat css0 = to css0- where- go Empty css = to css- go (Chunk c cs) css = Chunk c (go cs css)- to [] = Empty- to (cs:css) = go cs css---- | Map a function over a 'ByteString' and concatenate the results--{-@ lazy concatMap @-}-concatMap :: (Word8 -> ByteString) -> ByteString -> ByteString-concatMap _ Empty = Empty-concatMap f (Chunk c0 cs0) = to c0 cs0 0- where- {-@ decrease go 1 3 @-}- go :: S.ByteString -> ByteString -> ByteString -> Int -> ByteString- go c' cs' Empty _ = to c' cs' 0- go c' cs' (Chunk c cs) _ = Chunk c (go c' cs' cs 1)-- {-@ decrease to 2 3 @-}- to :: S.ByteString -> ByteString -> Int -> ByteString- to c cs _ | S.null c = case cs of- Empty -> Empty- (Chunk c' cs') -> to c' cs' 0- | otherwise = go (S.unsafeTail c) cs (f (S.unsafeHead c)) 1---- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if--- any element of the 'ByteString' satisfies the predicate.-any :: (Word8 -> Bool) -> ByteString -> Bool---LIQUID GHOST any f cs = foldrChunks (\c rest -> S.any f c || rest) False cs-any f cs = foldrChunks (\_ c rest -> S.any f c || rest) False cs-{-# INLINE any #-}--- todo fuse---- | /O(n)/ Applied to a predicate and a 'ByteString', 'all' determines--- if all elements of the 'ByteString' satisfy the predicate.-all :: (Word8 -> Bool) -> ByteString -> Bool---LIQUID GHOST all f cs = foldrChunks (\c rest -> S.all f c && rest) True cs-all f cs = foldrChunks (\_ c rest -> S.all f c && rest) True cs-{-# INLINE all #-}--- todo fuse---- | /O(n)/ 'maximum' returns the maximum value from a 'ByteString'-{-@ maximum :: LByteStringNE -> Word8 @-}-maximum :: ByteString -> Word8-maximum Empty = errorEmptyList "maximum"-maximum (Chunk c cs) = foldlChunks (\n c' -> n `max` S.maximum c')- (S.maximum c) cs-{-# INLINE maximum #-}---- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString'-{-@ minimum :: LByteStringNE -> Word8 @-}-minimum :: ByteString -> Word8-minimum Empty = errorEmptyList "minimum"-minimum (Chunk c cs) = foldlChunks (\n c' -> n `min` S.minimum c')- (S.minimum c) cs-{-# INLINE minimum #-}---- | The 'mapAccumL' function behaves like a combination of 'map' and--- 'foldl'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from left to right, and returning a--- final value of this accumulator together with the new ByteString.-{-@ mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> b:ByteString -> (acc, LByteStringSZ b) @-}-mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumL f s0 cs0 = mapAccum_go s0 cs0- where- --LIQUID RENAME- {-@ decrease mapAccum_go 2 @-}- mapAccum_go s Empty = (s, Empty)- mapAccum_go s (Chunk c cs) = (s'', Chunk c' cs')- where (s', c') = S.mapAccumL f s c- (s'', cs') = mapAccum_go s' cs---- | The 'mapAccumR' function behaves like a combination of 'map' and--- 'foldr'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from right to left, and returning a--- final value of this accumulator together with the new ByteString.-{-@ mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> b:ByteString -> (acc, LByteStringSZ b) @-}-mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumR f s0 cs0 = go s0 cs0- where- {-@ decrease go 2 @-}- go s Empty = (s, Empty)- go s (Chunk c cs) = (s'', Chunk c' cs')- where (s'', c') = S.mapAccumR f s' c- (s', cs') = go s cs---- | /O(n)/ map Word8 functions, provided with the index at each position-{-@ mapIndexed :: (Int -> Word8 -> Word8) -> ByteString -> ByteString @-}-mapIndexed :: (Int -> Word8 -> Word8) -> ByteString -> ByteString-mapIndexed f = F.loopArr . F.loopL (F.mapIndexEFL f) 0---- ------------------------------------------------------------------------ Building ByteStrings---- | 'scanl' is similar to 'foldl', but returns a list of successive--- reduced values from the left. This function will fuse.------ > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]------ Note that------ > last (scanl f z xs) == foldl f z xs.-{-LIQUID scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> b:ByteString- -> {v:ByteString | (lbLength v) = 1 + (lbLength b)}- @-}-scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString-scanl f z ps = F.loopArr . F.loopL (F.scanEFL f) z $ (ps `snoc` 0)-{-# INLINE scanl #-}---- ------------------------------------------------------------------------ Unfolds and replicates---- | @'iterate' f x@ returns an infinite ByteString of repeated applications--- of @f@ to @x@:------ > iterate f x == [x, f x, f (f x), ...]----{-@ iterate :: (Word8 -> Word8) -> Word8 -> ByteString @-}-{-@ lazy Data.ByteString.Lazy.iterate @-}-iterate :: (Word8 -> Word8) -> Word8 -> ByteString-iterate f = unfoldr (\x -> case f x of x' -> x' `seq` Just (x', x'))---- | @'repeat' x@ is an infinite ByteString, with @x@ the value of every--- element.----{-@ repeat :: Word8 -> ByteString @-}-{-@ lazy Data.ByteString.Lazy.repeat @-}-repeat :: Word8 -> ByteString-repeat w = cs where cs = Chunk (S.replicate smallChunkSize w) cs---- | /O(n)/ @'replicate' n x@ is a ByteString of length @n@ with @x@--- the value of every element.------LIQUID FIXME: can we somehow sneak multiplication into `nChunks`?-{- replicate :: n:Nat64 -> Word8 -> {v:ByteString | (lbLength v) = (if n > 0 then n else 0)} @-}-replicate :: Int64 -> Word8 -> ByteString-replicate n w- | n <= 0 = Empty- | n < fromIntegral smallChunkSize = Chunk (S.replicate (fromIntegral n) w) Empty- | otherwise =- let c = S.replicate smallChunkSize w- cs = nChunks q- (q, r) = quotRem n (fromIntegral smallChunkSize)- --LIQUID CAST- nChunks (0 :: Int64) = Empty- nChunks m = Chunk c (nChunks (m-1))- in if r == 0 then cs -- preserve invariant- else Chunk (S.unsafeTake (fromIntegral r) c) cs---LIQUID LAZY | r == 0 = cs -- preserve invariant---LIQUID LAZY | otherwise = Chunk (S.unsafeTake (fromIntegral r) c) cs---LIQUID LAZY where---LIQUID LAZY c = S.replicate smallChunkSize w---LIQUID LAZY cs = nChunks q---LIQUID LAZY (q, r) = quotRem n (fromIntegral smallChunkSize)---LIQUID LAZY nChunks 0 = Empty---LIQUID LAZY nChunks m = Chunk c (nChunks (m-1))---- | 'cycle' ties a finite ByteString into a circular one, or equivalently,--- the infinite repetition of the original ByteString.----{-@ cycle :: ByteString -> ByteString @-}-{-@ lazy Data.ByteString.Lazy.cycle @-}-cycle :: ByteString -> ByteString-cycle Empty = errorEmptyList "cycle"---LIQUID GHOST cycle cs = cs' where cs' = foldrChunks Chunk cs' cs-cycle cs = cs' where cs' = foldrChunks (const Chunk) cs' cs---- | /O(n)/ The 'unfoldr' function is analogous to the List \'unfoldr\'.--- 'unfoldr' builds a ByteString from a seed value. The function takes--- the element and returns 'Nothing' if it is done producing the--- ByteString or returns 'Just' @(a,b)@, in which case, @a@ is a--- prepending to the ByteString and @b@ is used as the next element in a--- recursive call.-{-@ lazy Data.ByteString.Lazy.unfoldr @-}-unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString-unfoldr f s0 = unfoldChunk 32 s0- where unfoldChunk n s =- case S.unfoldrN n f s of- (c, Nothing)- | S.null c -> Empty- | otherwise -> Chunk c Empty- (c, Just s') -> Chunk c (unfoldChunk (n*2) s')---- ------------------------------------------------------------------------ Substrings---- | /O(n\/c)/ 'take' @n@, applied to a ByteString @xs@, returns the prefix--- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.-{-@ take :: n:Nat64- -> b:ByteString- -> {v:ByteString | (Min (lbLength v) (lbLength b) n)}- @-}-take :: Int64 -> ByteString -> ByteString-take i _ | i <= 0 = Empty-take i cs0 = take' i cs0- where --LIQUID CAST FIXME: (Num a) isn't embedded as int so this loses some- --LIQUID refinements without the explicit type- take' :: Int64 -> ByteString -> ByteString- take' 0 _ = Empty- take' _ Empty = Empty- take' n (Chunk c cs) =- if n < fromIntegral (S.length c)- then Chunk (S.take (fromIntegral n) c) Empty- else Chunk c (take' (n - fromIntegral (S.length c)) cs)---- | /O(n\/c)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@--- elements, or @[]@ if @n > 'length' xs@.-{-@ drop :: n:Nat64- -> b:ByteString- -> {v:ByteString | lbLength v = (if lbLength b <= n then 0 else (lbLength b - n))}- @-}-drop :: Int64 -> ByteString -> ByteString-drop i p | i <= 0 = p-drop i cs0 = drop' i cs0- where drop' :: Int64 -> ByteString -> ByteString- drop' 0 cs = cs- drop' _ Empty = Empty- drop' n (Chunk c cs) =- if n < fromIntegral (S.length c)- then Chunk (S.drop (fromIntegral n) c) cs- else drop' (n - fromIntegral (S.length c)) cs---- | /O(n\/c)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.-{-@ splitAt :: n:Nat64- -> b:ByteString- -> ( {v:ByteString | (Min (lbLength v) (lbLength b) n)}- , ByteString)<{\x y -> ((lbLength y) = ((lbLength b) - (lbLength x)))}>- @-}-splitAt :: Int64 -> ByteString -> (ByteString, ByteString)-splitAt i cs0 | i <= 0 = (Empty, cs0)-splitAt i cs0 = splitAt' i cs0- where splitAt' :: Int64 -> ByteString -> (ByteString, ByteString)- splitAt' 0 cs = (Empty, cs)- splitAt' _ Empty = (Empty, Empty)- splitAt' n (Chunk c cs) =- if n < fromIntegral (S.length c)- then (Chunk (S.take (fromIntegral n) c) Empty - ,Chunk (S.drop (fromIntegral n) c) cs)- else let (cs', cs'') = splitAt' (n - fromIntegral (S.length c)) cs- in (Chunk c cs', cs'')----- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.-{-@ takeWhile :: (Word8 -> Bool) -> b:ByteString -> (LByteStringLE b) @-}-takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString-takeWhile f cs0 = takeWhile' cs0- where takeWhile' Empty = Empty- takeWhile' (Chunk c cs) =- case findIndexOrEnd (not . f) c of- 0 -> Empty- n | n < S.length c -> Chunk (S.take n c) Empty- | otherwise -> Chunk c (takeWhile' cs)---- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.-{-@ dropWhile :: (Word8 -> Bool) -> b:ByteString -> (LByteStringLE b) @-}-dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString-dropWhile f cs0 = dropWhile' cs0- where dropWhile' Empty = Empty- dropWhile' (Chunk c cs) =- case findIndexOrEnd (not . f) c of- n | n < S.length c -> Chunk (S.drop n c) cs- | otherwise -> dropWhile' cs---- | 'break' @p@ is equivalent to @'span' ('not' . p)@.-{-@ break :: (Word8 -> Bool) -> b:ByteString -> (LByteStringPair b) @-}-break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-break f cs0 = break' cs0- where break' Empty = (Empty, Empty)- break' (Chunk c cs) =- case findIndexOrEnd f c of- 0 -> (Empty, Chunk c cs)- n | n < S.length c -> (Chunk (S.take n c) Empty- ,Chunk (S.drop n c) cs)- | otherwise -> let (cs', cs'') = break' cs- in (Chunk c cs', cs'')------- TODO------ Add rules-----{---- | 'breakByte' breaks its ByteString argument at the first occurence--- of the specified byte. It is more efficient than 'break' as it is--- implemented with @memchr(3)@. I.e.--- --- > break (=='c') "abcd" == breakByte 'c' "abcd"----breakByte :: Word8 -> ByteString -> (ByteString, ByteString)-breakByte c (LPS ps) = case (breakByte' ps) of (a,b) -> (LPS a, LPS b)- where breakByte' [] = ([], [])- breakByte' (x:xs) =- case P.elemIndex c x of- Just 0 -> ([], x : xs)- Just n -> (P.take n x : [], P.drop n x : xs)- Nothing -> let (xs', xs'') = breakByte' xs- in (x : xs', xs'')---- | 'spanByte' breaks its ByteString argument at the first--- occurence of a byte other than its argument. It is more efficient--- than 'span (==)'------ > span (=='c') "abcd" == spanByte 'c' "abcd"----spanByte :: Word8 -> ByteString -> (ByteString, ByteString)-spanByte c (LPS ps) = case (spanByte' ps) of (a,b) -> (LPS a, LPS b)- where spanByte' [] = ([], [])- spanByte' (x:xs) =- case P.spanByte c x of- (x', x'') | P.null x' -> ([], x : xs)- | P.null x'' -> let (xs', xs'') = spanByte' xs- in (x : xs', xs'')- | otherwise -> (x' : [], x'' : xs)--}---- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@-{-@ span :: (Word8 -> Bool) -> b:ByteString -> (LByteStringPair b) @-}-span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-span p = break (not . p)---- | /O(n)/ Splits a 'ByteString' into components delimited by--- separators, where the predicate returns True for a separator element.--- The resulting components do not contain the separators. Two adjacent--- separators result in an empty component in the output. eg.------ > splitWith (=='a') "aabbaca" == ["","","bb","c",""]--- > splitWith (=='a') [] == []----{-@ splitWith :: (Word8 -> Bool) -> b:LByteStringNE -> (LByteStringSplit b) @-}-splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]-splitWith _ Empty = []---LIQUID PARAM splitWith w (Chunk c0 cs0) = comb [] (S.splitWith w c0) cs0---LIQUID PARAM where comb :: [S.ByteString] -> [S.ByteString] -> ByteString -> [ByteString]---LIQUID PARAM comb acc (s:[]) Empty = revChunks (s:acc) : []---LIQUID PARAM comb acc (s:[]) (Chunk c cs) = comb (s:acc) (S.splitWith w c) cs---LIQUID PARAM comb acc (s:ss) cs = revChunks (s:acc) : comb [] ss cs-splitWith w (Chunk c0 cs0) = comb [] cs0 (S.splitWith w c0)- {-@ decrease comb 2 3 @-}- where comb :: [S.ByteString] -> ByteString -> [S.ByteString] -> [ByteString]- comb acc Empty (s:[]) = revChunks (s:acc) : []- comb acc (Chunk c cs) (s:[]) = comb (s:acc) cs (S.splitWith w c)- comb acc cs (s:ss) = revChunks (s:acc) : comb [] cs ss--{-# INLINE splitWith #-}---- | /O(n)/ Break a 'ByteString' into pieces separated by the byte--- argument, consuming the delimiter. I.e.------ > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]--- > split 'a' "aXaXaXa" == ["","X","X","X",""]--- > split 'x' "x" == ["",""]--- --- and------ > intercalate [c] . split c == id--- > split == splitWith . (==)--- --- As for all splitting functions in this library, this function does--- not copy the substrings, it just constructs new 'ByteStrings' that--- are slices of the original.----{-@ split :: Word8 -> b:LByteStringNE -> (LByteStringSplit b) @-}-split :: Word8 -> ByteString -> [ByteString]-split _ Empty = []---LIQUID PARAM split w (Chunk c0 cs0) = comb [] (S.split w c0) cs0---LIQUID PARAM where comb :: [S.ByteString] -> [S.ByteString] -> ByteString -> [ByteString]---LIQUID PARAM comb acc (s:[]) Empty = revChunks (s:acc) : []---LIQUID PARAM comb acc (s:[]) (Chunk c cs) = comb (s:acc) (S.split w c) cs---LIQUID PARAM comb acc (s:ss) cs = revChunks (s:acc) : comb [] ss cs-split w (Chunk c0 cs0) = comb [] cs0 (S.split w c0)- {-@ decrease comb 2 3 @-}- where comb :: [S.ByteString] -> ByteString -> [S.ByteString] -> [ByteString]- comb acc Empty (s:[]) = revChunks (s:acc) : []- comb acc (Chunk c cs) (s:[]) = comb (s:acc) cs (S.split w c)- comb acc cs (s:ss) = revChunks (s:acc) : comb [] cs ss-{-# INLINE split #-}--{---- | Like 'splitWith', except that sequences of adjacent separators are--- treated as a single separator. eg.--- --- > tokens (=='a') "aabbaca" == ["bb","c"]----tokens :: (Word8 -> Bool) -> ByteString -> [ByteString]-tokens f = L.filter (not.null) . splitWith f--}---- | The 'group' function takes a ByteString and returns a list of--- ByteStrings such that the concatenation of the result is equal to the--- argument. Moreover, each sublist in the result contains only equal--- elements. For example,------ > group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]------ It is a special case of 'groupBy', which allows the programmer to--- supply their own equality test.-{-@ group :: b:ByteString -> {v: [ByteString] | (lbLengths v) = (lbLength b)} @-}-group :: ByteString -> [ByteString]-group Empty = []---LIQUID PARAM group (Chunk c0 cs0) = group' [] (S.group c0) cs0---LIQUID PARAM where ---LIQUID PARAM group' :: [S.ByteString] -> [S.ByteString] -> ByteString -> [ByteString]---LIQUID PARAM group' acc@(s':_) ss@(s:_) cs---LIQUID PARAM | S.unsafeHead s'---LIQUID PARAM /= S.unsafeHead s = revNonEmptyChunks acc : group' [] ss cs---LIQUID PARAM group' acc (s:[]) Empty = revNonEmptyChunks (s:acc) : []---LIQUID PARAM group' acc (s:[]) (Chunk c cs) = group' (s:acc) (S.group c) cs---LIQUID PARAM group' acc (s:ss) cs = revNonEmptyChunks (s:acc) : group' [] ss cs-group (Chunk c0 cs0) = group_go cs0 (S.group c0) []- where- {-@ decrease group_go 1 2 3 @-}- group_go :: ByteString -> [S.ByteString] -> [S.ByteString] -> [ByteString]- group_go cs ss@(s:_) acc@(s':_)- | S.unsafeHead s'- /= S.unsafeHead s = revNonEmptyChunks acc : group_go cs ss []- group_go Empty (s:[]) acc = revNonEmptyChunks (s:acc) : []- group_go (Chunk c cs) (s:[]) acc = group_go cs (S.group c) (s:acc)- group_go cs (s:ss) acc = revNonEmptyChunks (s:acc) : group_go cs ss []--{--TODO: check if something like this might be faster--group :: ByteString -> [ByteString]-group xs- | null xs = []- | otherwise = ys : group zs- where- (ys, zs) = spanByte (unsafeHead xs) xs--}---- | The 'groupBy' function is the non-overloaded version of 'group'.----{-@ groupBy :: (Word8 -> Word8 -> Bool) -> b:ByteString -> {v:[ByteString] | (lbLengths v) = (lbLength b)} @-}-groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]-groupBy _ Empty = []---LIQUID PARAM groupBy k (Chunk c0 cs0) = groupBy' [] 0 (S.groupBy k c0) cs0---LIQUID PARAM where---LIQUID PARAM groupBy' :: [S.ByteString] -> Word8 -> [S.ByteString] -> ByteString -> [ByteString]---LIQUID PARAM groupBy' acc@(_:_) c ss@(s:_) cs---LIQUID PARAM | not (c `k` S.unsafeHead s) = revNonEmptyChunks acc : groupBy' [] 0 ss cs---LIQUID PARAM groupBy' acc _ (s:[]) Empty = revNonEmptyChunks (s : acc) : []---LIQUID PARAM groupBy' acc w (s:[]) (Chunk c cs) = groupBy' (s:acc) w' (S.groupBy k c) cs---LIQUID PARAM where w' | L.null acc = S.unsafeHead s---LIQUID PARAM | otherwise = w---LIQUID PARAM groupBy' acc _ (s:ss) cs = revNonEmptyChunks (s : acc) : groupBy' [] 0 ss cs-groupBy k (Chunk c0 cs0) = groupBy_go cs0 (S.groupBy k c0) []- where- {-@ decrease groupBy_go 1 2 3 @-}- groupBy_go :: ByteString -> [S.ByteString] -> [S.ByteString] -> [ByteString]- groupBy_go cs ss@(s:_) acc@(s':_)- | S.unsafeHead s'- /= S.unsafeHead s = revNonEmptyChunks acc : groupBy_go cs ss []- groupBy_go Empty (s:[]) acc = revNonEmptyChunks (s:acc) : []- groupBy_go (Chunk c cs) (s:[]) acc = groupBy_go cs (S.groupBy k c) (s:acc)- groupBy_go cs (s:ss) acc = revNonEmptyChunks (s:acc) : groupBy_go cs ss []--{--TODO: check if something like this might be faster--groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]-groupBy k xs- | null xs = []- | otherwise = take n xs : groupBy k (drop n xs)- where- n = 1 + findIndexOrEnd (not . k (head xs)) (tail xs)--}---- | /O(n)/ The 'intercalate' function takes a 'ByteString' and a list of--- 'ByteString's and concatenates the list after interspersing the first--- argument between each element of the list.-intercalate :: ByteString -> [ByteString] -> ByteString-intercalate s = concat . (L.intersperse s)--join :: ByteString -> [ByteString] -> ByteString-join = intercalate-{-# DEPRECATED join "use intercalate" #-}---- ------------------------------------------------------------------------ Indexing ByteStrings---- | /O(c)/ 'ByteString' index (subscript) operator, starting from 0.-{-@ index :: b:ByteString -> n:{v:Nat64 | (LBValid b v)} -> Word8 @-}-index :: ByteString -> Int64 -> Word8-index _ i | i < 0 = moduleError "index" ("negative index: " ++ show i)-index cs0 i = index' cs0 i- where index' Empty n = moduleError "index" ("index too large: " ++ show n)- index' (Chunk c cs) n- | n >= fromIntegral (S.length c) = - index' cs (n - fromIntegral (S.length c))- | otherwise = S.unsafeIndex c (fromIntegral n)---- | /O(n)/ The 'elemIndex' function returns the index of the first--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. --- This implementation uses memchr(3).-{-@ elemIndex :: Word8 -> b:ByteString -> Maybe {v:Nat64 | v < (lbLength b)} @-}-elemIndex :: Word8 -> ByteString -> Maybe Int64-elemIndex w cs0 = elemIndex_go 0 cs0- --LIQUID RENAME- {-@ decrease elemIndex_go 2 @-}- where elemIndex_go _ Empty = Nothing- elemIndex_go (n::Int64) (Chunk c cs) = --LIQUID CAST- case S.elemIndex w c of- Nothing -> elemIndex_go (n + fromIntegral (S.length c)) cs- Just i -> Just (n + fromIntegral i)--{---- | /O(n)/ The 'elemIndexEnd' function returns the last index of the--- element in the given 'ByteString' which is equal to the query--- element, or 'Nothing' if there is no such element. The following--- holds:------ > elemIndexEnd c xs == --- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)----elemIndexEnd :: Word8 -> ByteString -> Maybe Int-elemIndexEnd ch (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->- go (p `plusPtr` s) (l-1)- where- STRICT2(go)- go p i | i < 0 = return Nothing- | otherwise = do ch' <- peekByteOff p i- if ch == ch'- then return $ Just i- else go p (i-1)--}---- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning--- the indices of all elements equal to the query element, in ascending order.--- This implementation uses memchr(3).-{-@ elemIndices :: Word8 -> b:ByteString -> [{v:Nat64 | v < (lbLength b) }] @-}-elemIndices :: Word8 -> ByteString -> [Int64]-elemIndices w cs0 = elemIndices_go 0 cs0- --LIQUID RENAME- {-@ decrease elemIndices_go 2 @-}- where elemIndices_go _ Empty = []- elemIndices_go (n::Int64) (Chunk c cs) = --LIQUID CAST- L.map ((+n).fromIntegral) (S.elemIndices w c)- ++ elemIndices_go (n + fromIntegral (S.length c)) cs---- | count returns the number of times its argument appears in the ByteString------ > count = length . elemIndices------ But more efficiently than using length on the intermediate list.-{-@ count :: Word8 -> b:ByteString -> {v:Nat64 | v <= (lbLength b) } @-}-count :: Word8 -> ByteString -> Int64---LIQUID GHOST count w cs = foldlChunks (\n c -> n + fromIntegral (S.count w c)) 0 cs-count w cs = foldrChunks (\_ c n -> n + fromIntegral (S.count w c)) 0 cs---- | The 'findIndex' function takes a predicate and a 'ByteString' and--- returns the index of the first element in the ByteString--- satisfying the predicate.-{-@ findIndex :: (Word8 -> Bool) -> b:ByteString -> (Maybe {v:Nat64 | v < (lbLength b)}) @-}-findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int64-findIndex k cs0 = findIndex_go 0 cs0- --LIQUID RENAME- {-@ decrease findIndex_go 2 @-}- where findIndex_go _ Empty = Nothing- findIndex_go (n::Int64) (Chunk c cs) = --LIQUID CAST- case S.findIndex k c of- Nothing -> findIndex_go (n + fromIntegral (S.length c)) cs- Just i -> Just (n + fromIntegral i)-{-# INLINE findIndex #-}---- | /O(n)/ The 'find' function takes a predicate and a ByteString,--- and returns the first element in matching the predicate, or 'Nothing'--- if there is no such element.------ > find f p = case findIndex f p of Just n -> Just (p ! n) ; _ -> Nothing----find :: (Word8 -> Bool) -> ByteString -> Maybe Word8-find f cs0 = find' cs0- where find' Empty = Nothing- find' (Chunk c cs) = case S.find f c of- Nothing -> find' cs- Just w -> Just w-{-# INLINE find #-}---- | The 'findIndices' function extends 'findIndex', by returning the--- indices of all elements satisfying the predicate, in ascending order.-{-@ findIndices :: (Word8 -> Bool) -> b:ByteString -> [{v:Nat64 | v < (lbLength b)}] @-}-findIndices :: (Word8 -> Bool) -> ByteString -> [Int64]-findIndices k cs0 = findIndices_go 0 cs0- --LIQUID RENAME- {-@ decrease findIndices_go 2 @-}- where findIndices_go _ Empty = []- findIndices_go (n::Int64) (Chunk c cs) = --LIQUID CAST- L.map ((+n).fromIntegral) (S.findIndices k c)- ++ findIndices_go (n + fromIntegral (S.length c)) cs---- ------------------------------------------------------------------------ Searching ByteStrings---- | /O(n)/ 'elem' is the 'ByteString' membership predicate.-elem :: Word8 -> ByteString -> Bool-elem w cs = case elemIndex w cs of Nothing -> False ; _ -> True---- | /O(n)/ 'notElem' is the inverse of 'elem'-notElem :: Word8 -> ByteString -> Bool-notElem w cs = not (elem w cs)---- | /O(n)/ 'filter', applied to a predicate and a ByteString,--- returns a ByteString containing those characters that satisfy the--- predicate.-{-@ filter :: (Word8 -> Bool) -> b:ByteString -> (LByteStringLE b) @-}-filter :: (Word8 -> Bool) -> ByteString -> ByteString-filter p s = filter_go s- where- --LIQUID RENAME- filter_go Empty = Empty- filter_go (Chunk x xs) = chunk (S.filter p x) (filter_go xs)-#if __GLASGOW_HASKELL__-{-# INLINE [1] filter #-}-#endif---- | /O(n)/ and /O(n\/c) space/ A first order equivalent of /filter .--- (==)/, for the common case of filtering a single byte. It is more--- efficient to use /filterByte/ in this case.------ > filterByte == filter . (==)------ filterByte is around 10x faster, and uses much less space, than its--- filter equivalent---LIQUID TODO: needs the spec for replicate-{- filterByte :: Word8 -> b:ByteString -> (LByteStringLE b) @-}-filterByte :: Word8 -> ByteString -> ByteString-filterByte w ps = replicate (count w ps) w-{-# INLINE filterByte #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter ((==) x) = filterByte x- #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter (== x) = filterByte x- #-}--{---- | /O(n)/ A first order equivalent of /filter . (\/=)/, for the common--- case of filtering a single byte out of a list. It is more efficient--- to use /filterNotByte/ in this case.------ > filterNotByte == filter . (/=)------ filterNotByte is around 2x faster than its filter equivalent.-filterNotByte :: Word8 -> ByteString -> ByteString-filterNotByte w (LPS xs) = LPS (filterMap (P.filterNotByte w) xs)--}---- | /O(n)/ The 'partition' function takes a predicate a ByteString and returns--- the pair of ByteStrings with elements which do and do not satisfy the--- predicate, respectively; i.e.,------ > partition p bs == (filter p xs, filter (not . p) xs)----{-@ partition :: (Word8 -> Bool) -> b:ByteString -> ((LByteStringLE b), (LByteStringLE b)) @-}-partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)-partition f p = (filter f p, filter (not . f) p)---TODO: use a better implementation---- ------------------------------------------------------------------------ Searching for substrings---- | /O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'--- iff the first is a prefix of the second.-{-@ isPrefixOf :: ByteString -> ByteString -> Bool @-}-isPrefixOf :: ByteString -> ByteString -> Bool-isPrefixOf Empty _ = True-isPrefixOf _ Empty = False-isPrefixOf (Chunk x xs) (Chunk y ys)- | S.length x == S.length y = x == y && isPrefixOf xs ys---LIQUID LAZY pushing bindings inward for safety---LIQUID LAZY | S.length x < S.length y = x == yh && isPrefixOf xs (Chunk yt ys)---LIQUID LAZY | otherwise = xh == y && isPrefixOf (Chunk xt xs) ys---LIQUID LAZY where (xh,xt) = S.splitAt (S.length y) x---LIQUID LAZY (yh,yt) = S.splitAt (S.length x) y- | otherwise = if S.length x < S.length y- then let (xh,xt) = S.splitAt (S.length y) x- (yh,yt) = S.splitAt (S.length x) y- in x == yh && isPrefixOf xs (Chunk yt ys)- else let (xh,xt) = S.splitAt (S.length y) x- (yh,yt) = S.splitAt (S.length x) y- in xh == y && isPrefixOf (Chunk xt xs) ys----- | /O(n)/ The 'isSuffixOf' function takes two ByteStrings and returns 'True'--- iff the first is a suffix of the second.--- --- The following holds:------ > isSuffixOf x y == reverse x `isPrefixOf` reverse y----isSuffixOf :: ByteString -> ByteString -> Bool-isSuffixOf x y = reverse x `isPrefixOf` reverse y---TODO: a better implementation---- ------------------------------------------------------------------------ Zipping----LIQUID TODO: zip and zipWith are in LazyZip.hs because they need a---qualifier that takes 4 parameters and this module is slow enough to---verify as is.---- | /O(n)/ 'zip' takes two ByteStrings and returns a list of--- corresponding pairs of bytes. If one input ByteString is short,--- excess elements of the longer ByteString are discarded. This is--- equivalent to a pair of 'unpack' operations.-{-@ predicate LZipLen V X Y = (len V) = (if (lbLength X) <= (lbLength Y) then (lbLength X) else (lbLength Y)) @-}-{-@ zip :: x:ByteString -> y:ByteString -> {v:[(Word8, Word8)] | (LZipLen v x y) } @-}-zip :: ByteString -> ByteString -> [(Word8,Word8)]-zip = zipWith (,)---- | 'zipWith' generalises 'zip' by zipping with the function given as--- the first argument, instead of a tupling function. For example,--- @'zipWith' (+)@ is applied to two ByteStrings to produce the list of--- corresponding sums.-{-@ zipWith :: (Word8 -> Word8 -> a) -> x:ByteString -> y:ByteString -> {v:[a] | (LZipLen v x y)} @-}---LIQUID see LazyZip.hs-zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]-zipWith = undefined---LIQUID zipWith _ Empty _ = []---LIQUID zipWith _ _ Empty = []---LIQUID zipWith f (Chunk a as) (Chunk b bs) = go a as b bs---LIQUID where---LIQUID go x xs y ys = f (S.unsafeHead x) (S.unsafeHead y)---LIQUID : to (S.unsafeTail x) xs (S.unsafeTail y) ys---LIQUID ---LIQUID to x Empty _ _ | S.null x = []---LIQUID to _ _ y Empty | S.null y = []---LIQUID to x xs y ys | not (S.null x)---LIQUID && not (S.null y) = go x xs y ys---LIQUID to x xs _ (Chunk y' ys) | not (S.null x) = go x xs y' ys---LIQUID to _ (Chunk x' xs) y ys | not (S.null y) = go x' xs y ys---LIQUID to _ (Chunk x' xs) _ (Chunk y' ys) = go x' xs y' ys---- | /O(n)/ 'unzip' transforms a list of pairs of bytes into a pair of--- ByteStrings. Note that this performs two 'pack' operations.-{-@ unzip :: z:[(Word8,Word8)] -> ({v:ByteString | (lbLength v) = (len z)}, {v:ByteString | (lbLength v) = (len z) }) @-}-unzip :: [(Word8,Word8)] -> (ByteString,ByteString)-unzip ls = (pack (L.map fst ls), pack (L.map snd ls))-{-# INLINE unzip #-}---- ------------------------------------------------------------------------ Special lists---- | /O(n)/ Return all initial segments of the given 'ByteString', shortest first.-{-@ inits :: ByteString -> [ByteString] @-}-inits :: ByteString -> [ByteString]-inits = (Empty :) . inits'-- where inits' Empty = []- inits' (Chunk c cs) = let (c':cs') = S.inits c in- L.map (\c' -> Chunk c' Empty) cs' --LIQUID INLINE (L.tail (S.inits c))- ++ L.map (Chunk c) (inits' cs)---- | /O(n)/ Return all final segments of the given 'ByteString', longest first.-{-@ tails :: ByteString -> [ByteString] @-}-tails :: ByteString -> [ByteString]-tails Empty = Empty : []-tails cs@(Chunk c cs')- | S.length c == 1 = cs : tails cs'- | otherwise = cs : tails (Chunk (S.unsafeTail c) cs')---- ------------------------------------------------------------------------ Low level constructors---- | /O(n)/ Make a copy of the 'ByteString' with its own storage.--- This is mainly useful to allow the rest of the data pointed--- to by the 'ByteString' to be garbage collected, for example--- if a large string has been read in, and only a small part of it--- is needed in the rest of the program.-{-@ copy :: b:ByteString -> LByteStringSZ b @-}-copy :: ByteString -> ByteString---LIQUID GHOST copy cs = foldrChunks (Chunk . S.copy) Empty cs-copy cs = foldrChunks (\_ c cs -> Chunk (S.copy c) cs) Empty cs---TODO, we could coalese small blocks here---FIXME: probably not strict enough, if we're doing this to avoid retaining--- the parent blocks then we'd better copy strictly.---- ------------------------------------------------------------------------- TODO defrag func that concatenates block together that are below a threshold--- defrag :: ByteString -> ByteString---- ------------------------------------------------------------------------ Lazy ByteString IO---- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks--- are read on demand, in at most @k@-sized chunks. It does not block--- waiting for a whole @k@-sized chunk, so if less than @k@ bytes are--- available then they will be returned immediately as a smaller chunk.-{-@ hGetContentsN :: Nat -> Handle -> IO ByteString @-}-hGetContentsN :: Int -> Handle -> IO ByteString-hGetContentsN k h = lazyRead- where- {-@ lazy lazyRead @-}- lazyRead = unsafeInterleaveIO loop- {-@ lazy loop @-}- loop = do- c <- S.hGetNonBlocking h k- --TODO: I think this should distinguish EOF from no data available- -- the underlying POSIX call makes this distincion, returning either- -- 0 or EAGAIN- if S.null c- then do eof <- hIsEOF h- if eof then return Empty- else hWaitForInput h (-1)- >> loop- else do cs <- lazyRead- return (Chunk c cs)---- | Read @n@ bytes into a 'ByteString', directly from the--- specified 'Handle', in chunks of size @k@.-{-@ hGetN :: Nat -> Handle -> n:Nat -> IO {v:ByteString | (lbLength v) <= n} @-}-hGetN :: Int -> Handle -> Int -> IO ByteString-hGetN _ _ 0 = return empty-hGetN k h n = readChunks n- where- STRICT1(readChunks)- readChunks i = do- c <- S.hGet h (min k i)- case S.length c of- 0 -> return Empty- m -> do cs <- readChunks (i - m)- return (Chunk c cs)---- | hGetNonBlockingN is similar to 'hGetContentsN', except that it will never block--- waiting for data to become available, instead it returns only whatever data--- is available. Chunks are read on demand, in @k@-sized chunks.-{-@ hGetNonBlockingN :: Nat -> Handle -> n:Nat -> IO {v:ByteString | (lbLength v) <= n} @-}-hGetNonBlockingN :: Int -> Handle -> Int -> IO ByteString-#if defined(__GLASGOW_HASKELL__)-hGetNonBlockingN _ _ 0 = return empty-hGetNonBlockingN k h n = readChunks n- where- STRICT1(readChunks)- readChunks i = do- c <- S.hGetNonBlocking h (min k i)- case S.length c of- 0 -> return Empty- m -> do cs <- readChunks (i - m)- return (Chunk c cs)-#else-hGetNonBlockingN = hGetN-#endif---- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks--- are read on demand, using the default chunk size.-hGetContents :: Handle -> IO ByteString-hGetContents = hGetContentsN defaultChunkSize---- | Read @n@ bytes into a 'ByteString', directly from the specified 'Handle'.-{-@ hGet :: Handle -> Nat -> IO ByteString @-}-hGet :: Handle -> Int -> IO ByteString-hGet = hGetN defaultChunkSize---- | hGetNonBlocking is similar to 'hGet', except that it will never block--- waiting for data to become available, instead it returns only whatever data--- is available.-#if defined(__GLASGOW_HASKELL__)-{-@ hGetNonBlocking :: Handle -> Nat -> IO ByteString @-}-hGetNonBlocking :: Handle -> Int -> IO ByteString-hGetNonBlocking = hGetNonBlockingN defaultChunkSize-#else-hGetNonBlocking = hGet-#endif---- | Read an entire file /lazily/ into a 'ByteString'.-readFile :: FilePath -> IO ByteString-readFile f = openBinaryFile f ReadMode >>= hGetContents---- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\hdl -> hPut hdl txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\hdl -> hPut hdl txt)---- | getContents. Equivalent to hGetContents stdin. Will read /lazily/-getContents :: IO ByteString-getContents = hGetContents stdin---- | Outputs a 'ByteString' to the specified 'Handle'.-hPut :: Handle -> ByteString -> IO ()---LIQUID GHOST hPut h cs = foldrChunks (\c rest -> S.hPut h c >> rest) (return ()) cs-hPut h cs = foldrChunks (\_ c rest -> S.hPut h c >> rest) (return ()) cs---- | A synonym for @hPut@, for compatibility-hPutStr :: Handle -> ByteString -> IO ()-hPutStr = hPut---- | Write a ByteString to stdout-putStr :: ByteString -> IO ()-putStr = hPut stdout---- | Write a ByteString to stdout, appending a newline byte-putStrLn :: ByteString -> IO ()-putStrLn ps = hPut stdout ps >> hPut stdout (singleton 0x0a)---- | The interact function takes a function of type @ByteString -> ByteString@--- as its argument. The entire input from the standard input device is passed--- to this function as its argument, and the resulting string is output on the--- standard output device. It's great for writing one line programs!-interact :: (ByteString -> ByteString) -> IO ()-interact transformer = putStr . transformer =<< getContents---- ------------------------------------------------------------------------ Internal utilities---- Common up near identical calls to `error' to reduce the number--- constant strings created when compiled:-errorEmptyList :: String -> a-errorEmptyList fun = moduleError fun "empty ByteString"--{-@ moduleError :: String -> String -> a @-}-moduleError :: String -> String -> a-moduleError fun msg = unsafeError ("Data.ByteString.Lazy." ++ fun ++ ':':' ':msg)----- reverse a list of non-empty chunks into a lazy ByteString-{-@ revNonEmptyChunks :: bs:[ByteStringNE] -> {v:ByteString | (lbLength v) = (bLengths bs)} @-}-revNonEmptyChunks :: [S.ByteString] -> ByteString---LIQUID INLINE revNonEmptyChunks cs = L.foldl' (flip Chunk) Empty cs-revNonEmptyChunks cs = go Empty cs- {-@ decrease go 2 @-}- where go acc [] = acc- go acc (c:cs) = go (Chunk c acc) cs---- reverse a list of possibly-empty chunks into a lazy ByteString-{-@ revChunks :: bs:_ -> {v:_ | (lbLength v) = (bLengths bs)} @-}-revChunks :: [S.ByteString] -> ByteString---LIQUID INLINE revChunks cs = L.foldl' (flip chunk) Empty cs-revChunks cs = go Empty cs- {-@ decrease go 2 @-}- where go acc [] = acc- go acc (c:cs) = go (chunk c acc) cs--{-@ qualif Blah(v:int, l:int, p:Ptr a): (v + (plen p)) >= l @-}---- | 'findIndexOrEnd' is a variant of findIndex, that returns the length--- of the string if no element is found, rather than Nothing.-findIndexOrEnd :: (Word8 -> Bool) -> S.ByteString -> Int-findIndexOrEnd k (S.PS x s l) = S.inlinePerformIO $ withForeignPtr x $ \f -> go l (f `plusPtr` s) 0- where- --LIQUID GHOST- STRICT3(go)- {- LIQUID WITNESS -}- go (d::Int) ptr n- | n >= l = return l- | otherwise = do w <- peek ptr- if k w- then return n- else go (d-1) (ptr `plusPtr` 1) (n+1)-{-# INLINE findIndexOrEnd #-}--{- liquidCanary :: x:Int -> {v: Int | v > x} @-}-liquidCanary :: Int -> Int-liquidCanary x = x - 1
@@ -1,874 +0,0 @@-{-@ LIQUID "--notermination" @-}-{-@ LIQUID "--no-totality" @-}-{-@ LIQUID "--pruneunsorted" @-}---{-# OPTIONS_GHC -cpp -fno-warn-orphans #-}---- #prune---- |--- Module : Data.ByteString.Lazy.Char8--- Copyright : (c) Don Stewart 2006--- License : BSD-style------ Maintainer : dons@cse.unsw.edu.au--- Stability : experimental--- Portability : non-portable (imports Data.ByteString.Lazy)------ Manipulate /lazy/ 'ByteString's using 'Char' operations. All Chars will--- be truncated to 8 bits. It can be expected that these functions will--- run at identical speeds to their 'Data.Word.Word8' equivalents in--- "Data.ByteString.Lazy".------ This module is intended to be imported @qualified@, to avoid name--- clashes with "Prelude" functions. eg.------ > import qualified Data.ByteString.Lazy.Char8 as C-----module Data.ByteString.Lazy.Char8 (-- -- * The @ByteString@ type- ByteString, -- instances: Eq, Ord, Show, Read, Data, Typeable-- -- * Introducing and eliminating 'ByteString's- empty, -- :: ByteString- singleton, -- :: Char -> ByteString- pack, -- :: String -> ByteString- unpack, -- :: ByteString -> String- fromChunks, -- :: [Strict.ByteString] -> ByteString- toChunks, -- :: ByteString -> [Strict.ByteString]-- -- * Basic interface- cons, -- :: Char -> ByteString -> ByteString- cons', -- :: Char -> ByteString -> ByteString- snoc, -- :: ByteString -> Char -> ByteString- append, -- :: ByteString -> ByteString -> ByteString- head, -- :: ByteString -> Char- uncons, -- :: ByteString -> Maybe (Char, ByteString)- last, -- :: ByteString -> Char- tail, -- :: ByteString -> ByteString- init, -- :: ByteString -> ByteString- null, -- :: ByteString -> Bool- length, -- :: ByteString -> Int64-- -- * Transforming ByteStrings- map, -- :: (Char -> Char) -> ByteString -> ByteString- reverse, -- :: ByteString -> ByteString- intersperse, -- :: Char -> ByteString -> ByteString- intercalate, -- :: ByteString -> [ByteString] -> ByteString- transpose, -- :: [ByteString] -> [ByteString]-- -- * Reducing 'ByteString's (folds)- foldl, -- :: (a -> Char -> a) -> a -> ByteString -> a- foldl', -- :: (a -> Char -> a) -> a -> ByteString -> a- foldl1, -- :: (Char -> Char -> Char) -> ByteString -> Char- foldl1', -- :: (Char -> Char -> Char) -> ByteString -> Char- foldr, -- :: (Char -> a -> a) -> a -> ByteString -> a- foldr1, -- :: (Char -> Char -> Char) -> ByteString -> Char-- -- ** Special folds- concat, -- :: [ByteString] -> ByteString- concatMap, -- :: (Char -> ByteString) -> ByteString -> ByteString- any, -- :: (Char -> Bool) -> ByteString -> Bool- all, -- :: (Char -> Bool) -> ByteString -> Bool- maximum, -- :: ByteString -> Char- minimum, -- :: ByteString -> Char-- -- * Building ByteStrings- -- ** Scans- scanl, -- :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString--- scanl1, -- :: (Char -> Char -> Char) -> ByteString -> ByteString--- scanr, -- :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString--- scanr1, -- :: (Char -> Char -> Char) -> ByteString -> ByteString-- -- ** Accumulating maps- mapAccumL, -- :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)- mapIndexed, -- :: (Int64 -> Char -> Char) -> ByteString -> ByteString-- -- ** Infinite ByteStrings- repeat, -- :: Char -> ByteString- replicate, -- :: Int64 -> Char -> ByteString- cycle, -- :: ByteString -> ByteString- iterate, -- :: (Char -> Char) -> Char -> ByteString-- -- ** Unfolding ByteStrings- unfoldr, -- :: (a -> Maybe (Char, a)) -> a -> ByteString-- -- * Substrings-- -- ** Breaking strings- take, -- :: Int64 -> ByteString -> ByteString- drop, -- :: Int64 -> ByteString -> ByteString- splitAt, -- :: Int64 -> ByteString -> (ByteString, ByteString)- takeWhile, -- :: (Char -> Bool) -> ByteString -> ByteString- dropWhile, -- :: (Char -> Bool) -> ByteString -> ByteString- span, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)- break, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)- group, -- :: ByteString -> [ByteString]- groupBy, -- :: (Char -> Char -> Bool) -> ByteString -> [ByteString]- inits, -- :: ByteString -> [ByteString]- tails, -- :: ByteString -> [ByteString]-- -- ** Breaking into many substrings- split, -- :: Char -> ByteString -> [ByteString]- splitWith, -- :: (Char -> Bool) -> ByteString -> [ByteString]-- -- ** Breaking into lines and words- lines, -- :: ByteString -> [ByteString]- words, -- :: ByteString -> [ByteString]- unlines, -- :: [ByteString] -> ByteString- unwords, -- :: ByteString -> [ByteString]-- -- * Predicates- isPrefixOf, -- :: ByteString -> ByteString -> Bool--- isSuffixOf, -- :: ByteString -> ByteString -> Bool-- -- * Searching ByteStrings-- -- ** Searching by equality- elem, -- :: Char -> ByteString -> Bool- notElem, -- :: Char -> ByteString -> Bool-- -- ** Searching with a predicate- find, -- :: (Char -> Bool) -> ByteString -> Maybe Char- filter, -- :: (Char -> Bool) -> ByteString -> ByteString--- partition -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-- -- * Indexing ByteStrings- index, -- :: ByteString -> Int64 -> Char- elemIndex, -- :: Char -> ByteString -> Maybe Int64- elemIndices, -- :: Char -> ByteString -> [Int64]- findIndex, -- :: (Char -> Bool) -> ByteString -> Maybe Int64- findIndices, -- :: (Char -> Bool) -> ByteString -> [Int64]- count, -- :: Char -> ByteString -> Int64-- -- * Zipping and unzipping ByteStrings- zip, -- :: ByteString -> ByteString -> [(Char,Char)]- zipWith, -- :: (Char -> Char -> c) -> ByteString -> ByteString -> [c]--- unzip, -- :: [(Char,Char)] -> (ByteString,ByteString)-- -- * Ordered ByteStrings--- sort, -- :: ByteString -> ByteString-- -- * Low level conversions- -- ** Copying ByteStrings- copy, -- :: ByteString -> ByteString-- -- * Reading from ByteStrings- readInt,- readInteger,-- -- * I\/O with 'ByteString's-- -- ** Standard input and output- getContents, -- :: IO ByteString- putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO ()- interact, -- :: (ByteString -> ByteString) -> IO ()-- -- ** Files- readFile, -- :: FilePath -> IO ByteString- writeFile, -- :: FilePath -> ByteString -> IO ()- appendFile, -- :: FilePath -> ByteString -> IO ()-- -- ** I\/O with Handles- hGetContents, -- :: Handle -> IO ByteString- hGet, -- :: Handle -> Int64 -> IO ByteString- hGetNonBlocking, -- :: Handle -> Int64 -> IO ByteString- hPut, -- :: Handle -> ByteString -> IO ()---- hGetN, -- :: Int -> Handle -> Int64 -> IO ByteString--- hGetContentsN, -- :: Int -> Handle -> IO ByteString--- hGetNonBlockingN, -- :: Int -> Handle -> IO ByteString-- -- undocumented deprecated things:- join -- :: ByteString -> [ByteString] -> ByteString-- ) where--import Language.Haskell.Liquid.Prelude (unsafeError)---- Functions transparently exported-import Data.ByteString.Lazy - (ByteString, fromChunks, toChunks- ,empty,null,length,tail,init,append,reverse,transpose,cycle- ,concat,take,drop,splitAt,intercalate,isPrefixOf,group,inits,tails,copy- ,hGetContents, hGet, hPut, getContents- ,hGetNonBlocking- ,putStr, putStrLn, interact)---- Functions we need to wrap.-import qualified Data.ByteString.Lazy as L-import qualified Data.ByteString as B-import qualified Data.ByteString.Internal as B-import qualified Data.ByteString.Unsafe as B-import Data.ByteString.Lazy.Internal--import Data.ByteString.Internal (w2c, c2w, isSpaceWord8)--import Data.Int (Int64)-import qualified Data.List as List--import Prelude hiding - (reverse,head,tail,last,init,null,length,map,lines,foldl,foldr,unlines- ,concat,any,take,drop,splitAt,takeWhile,dropWhile,span,break,elem,filter- ,unwords,words,maximum,minimum,all,concatMap,scanl,scanl1,foldl1,foldr1- ,readFile,writeFile,appendFile,replicate,getContents,getLine,putStr,putStrLn- ,zip,zipWith,unzip,notElem,repeat,iterate,interact,cycle)--import System.IO (hClose,openFile,IOMode(..))-#ifndef __NHC__-import Control.Exception (bracket)-#else-import IO (bracket)-#endif--#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined----LIQUID-import Data.ByteString.Fusion (PairS(..), MaybeS(..))-import Data.Int-import Data.Word-import Foreign.ForeignPtr-import Foreign.Ptr-import System.IO (Handle)------------------------------------------------------------------------------ | /O(1)/ Convert a 'Char' into a 'ByteString'-singleton :: Char -> ByteString-singleton = L.singleton . c2w-{-# INLINE singleton #-}---- | /O(n)/ Convert a 'String' into a 'ByteString'. -pack :: [Char] -> ByteString-pack = L.pack. List.map c2w---- | /O(n)/ Converts a 'ByteString' to a 'String'.-unpack :: ByteString -> [Char]-unpack = List.map w2c . L.unpack-{-# INLINE unpack #-}---- | /O(1)/ 'cons' is analogous to '(:)' for lists.-cons :: Char -> ByteString -> ByteString-cons = L.cons . c2w-{-# INLINE cons #-}---- | /O(1)/ Unlike 'cons', 'cons\'' is--- strict in the ByteString that we are consing onto. More precisely, it forces--- the head and the first chunk. It does this because, for space efficiency, it--- may coalesce the new byte onto the first \'chunk\' rather than starting a--- new \'chunk\'.------ So that means you can't use a lazy recursive contruction like this:------ > let xs = cons\' c xs in xs------ You can however use 'cons', as well as 'repeat' and 'cycle', to build--- infinite lazy ByteStrings.----cons' :: Char -> ByteString -> ByteString-cons' = L.cons' . c2w-{-# INLINE cons' #-}---- | /O(n)/ Append a Char to the end of a 'ByteString'. Similar to--- 'cons', this function performs a memcpy.-snoc :: ByteString -> Char -> ByteString-snoc p = L.snoc p . c2w-{-# INLINE snoc #-}---- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.-{-@ head :: LByteStringNE -> Char @-}-head :: ByteString -> Char-head = w2c . L.head-{-# INLINE head #-}---- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing--- if it is empty.-uncons :: ByteString -> Maybe (Char, ByteString)-uncons bs = case L.uncons bs of- Nothing -> Nothing- Just (w, bs') -> Just (w2c w, bs')-{-# INLINE uncons #-}---- | /O(1)/ Extract the last element of a packed string, which must be non-empty.-{-@ last :: LByteStringNE -> Char @-}-last :: ByteString -> Char-last = w2c . L.last-{-# INLINE last #-}---- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each element of @xs@-map :: (Char -> Char) -> ByteString -> ByteString-map f = L.map (c2w . f . w2c)-{-# INLINE map #-}---- | /O(n)/ The 'intersperse' function takes a Char and a 'ByteString'--- and \`intersperses\' that Char between the elements of the--- 'ByteString'. It is analogous to the intersperse function on Lists.-intersperse :: Char -> ByteString -> ByteString-intersperse = L.intersperse . c2w-{-# INLINE intersperse #-}--join :: ByteString -> [ByteString] -> ByteString-join = intercalate-{-# DEPRECATED join "use intercalate" #-}---- | 'foldl', applied to a binary operator, a starting value (typically--- the left-identity of the operator), and a ByteString, reduces the--- ByteString using the binary operator, from left to right.-foldl :: (a -> Char -> a) -> a -> ByteString -> a-foldl f = L.foldl (\a c -> f a (w2c c))-{-# INLINE foldl #-}---- | 'foldl\'' is like foldl, but strict in the accumulator.-foldl' :: (a -> Char -> a) -> a -> ByteString -> a-foldl' f = L.foldl' (\a c -> f a (w2c c))-{-# INLINE foldl' #-}---- | 'foldr', applied to a binary operator, a starting value--- (typically the right-identity of the operator), and a packed string,--- reduces the packed string using the binary operator, from right to left.-foldr :: (Char -> a -> a) -> a -> ByteString -> a-foldr f = L.foldr (\c a -> f (w2c c) a)-{-# INLINE foldr #-}---- | 'foldl1' is a variant of 'foldl' that has no starting value--- argument, and thus must be applied to non-empty 'ByteStrings'.-{-@ foldl1 :: (Char -> Char -> Char) -> LByteStringNE -> Char @-}-foldl1 :: (Char -> Char -> Char) -> ByteString -> Char-foldl1 f ps = w2c (L.foldl1 (\x y -> c2w (f (w2c x) (w2c y))) ps)-{-# INLINE foldl1 #-}---- | 'foldl1\'' is like 'foldl1', but strict in the accumulator.-{-@ foldl1' :: (Char -> Char -> Char) -> LByteStringNE -> Char @-}-foldl1' :: (Char -> Char -> Char) -> ByteString -> Char-foldl1' f ps = w2c (L.foldl1' (\x y -> c2w (f (w2c x) (w2c y))) ps)---- | 'foldr1' is a variant of 'foldr' that has no starting value argument,--- and thus must be applied to non-empty 'ByteString's-{-@ foldr1 :: (Char -> Char -> Char) -> LByteStringNE -> Char @-}-foldr1 :: (Char -> Char -> Char) -> ByteString -> Char-foldr1 f ps = w2c (L.foldr1 (\x y -> c2w (f (w2c x) (w2c y))) ps)-{-# INLINE foldr1 #-}---- | Map a function over a 'ByteString' and concatenate the results-concatMap :: (Char -> ByteString) -> ByteString -> ByteString-concatMap f = L.concatMap (f . w2c)-{-# INLINE concatMap #-}---- | Applied to a predicate and a ByteString, 'any' determines if--- any element of the 'ByteString' satisfies the predicate.-any :: (Char -> Bool) -> ByteString -> Bool-any f = L.any (f . w2c)-{-# INLINE any #-}---- | Applied to a predicate and a 'ByteString', 'all' determines if--- all elements of the 'ByteString' satisfy the predicate.-all :: (Char -> Bool) -> ByteString -> Bool-all f = L.all (f . w2c)-{-# INLINE all #-}---- | 'maximum' returns the maximum value from a 'ByteString'-{-@ maximum :: LByteStringNE -> Char @-}-maximum :: ByteString -> Char-maximum = w2c . L.maximum-{-# INLINE maximum #-}---- | 'minimum' returns the minimum value from a 'ByteString'-{-@ minimum :: LByteStringNE -> Char @-}-minimum :: ByteString -> Char-minimum = w2c . L.minimum-{-# INLINE minimum #-}---- ------------------------------------------------------------------------ Building ByteStrings---- | 'scanl' is similar to 'foldl', but returns a list of successive--- reduced values from the left. This function will fuse.------ > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]------ Note that------ > last (scanl f z xs) == foldl f z xs.-scanl :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString-scanl f z = L.scanl (\a b -> c2w (f (w2c a) (w2c b))) (c2w z)---- | The 'mapAccumL' function behaves like a combination of 'map' and--- 'foldl'; it applies a function to each element of a ByteString,--- passing an accumulating parameter from left to right, and returning a--- final value of this accumulator together with the new ByteString.-mapAccumL :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)-mapAccumL f = L.mapAccumL (\a w -> case f a (w2c w) of (a',c) -> (a', c2w c))---- | /O(n)/ map Char functions, provided with the index at each position-mapIndexed :: (Int -> Char -> Char) -> ByteString -> ByteString-mapIndexed f = L.mapIndexed (\i w -> c2w (f i (w2c w)))----------------------------------------------------------------------------- Generating and unfolding ByteStrings---- | @'iterate' f x@ returns an infinite ByteString of repeated applications--- of @f@ to @x@:------ > iterate f x == [x, f x, f (f x), ...]----iterate :: (Char -> Char) -> Char -> ByteString-iterate f = L.iterate (c2w . f . w2c) . c2w---- | @'repeat' x@ is an infinite ByteString, with @x@ the value of every--- element.----repeat :: Char -> ByteString-repeat = L.repeat . c2w---- | /O(n)/ @'replicate' n x@ is a ByteString of length @n@ with @x@--- the value of every element.----replicate :: Int64 -> Char -> ByteString-replicate w c = L.replicate w (c2w c)---- | /O(n)/ The 'unfoldr' function is analogous to the List \'unfoldr\'.--- 'unfoldr' builds a ByteString from a seed value. The function takes--- the element and returns 'Nothing' if it is done producing the--- ByteString or returns 'Just' @(a,b)@, in which case, @a@ is a--- prepending to the ByteString and @b@ is used as the next element in a--- recursive call.-unfoldr :: (a -> Maybe (Char, a)) -> a -> ByteString-unfoldr f = L.unfoldr $ \a -> case f a of- Nothing -> Nothing- Just (c, a') -> Just (c2w c, a')------------------------------------------------------------------------------ | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.-takeWhile :: (Char -> Bool) -> ByteString -> ByteString-takeWhile f = L.takeWhile (f . w2c)-{-# INLINE takeWhile #-}---- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.-dropWhile :: (Char -> Bool) -> ByteString -> ByteString-dropWhile f = L.dropWhile (f . w2c)-{-# INLINE dropWhile #-}---- | 'break' @p@ is equivalent to @'span' ('not' . p)@.-break :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-break f = L.break (f . w2c)-{-# INLINE break #-}---- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@-span :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)-span f = L.span (f . w2c)-{-# INLINE span #-}--{---- | 'breakChar' breaks its ByteString argument at the first occurence--- of the specified Char. It is more efficient than 'break' as it is--- implemented with @memchr(3)@. I.e.--- --- > break (=='c') "abcd" == breakChar 'c' "abcd"----breakChar :: Char -> ByteString -> (ByteString, ByteString)-breakChar = L.breakByte . c2w-{-# INLINE breakChar #-}---- | 'spanChar' breaks its ByteString argument at the first--- occurence of a Char other than its argument. It is more efficient--- than 'span (==)'------ > span (=='c') "abcd" == spanByte 'c' "abcd"----spanChar :: Char -> ByteString -> (ByteString, ByteString)-spanChar = L.spanByte . c2w-{-# INLINE spanChar #-}--}------- TODO, more rules for breakChar*------- | /O(n)/ Break a 'ByteString' into pieces separated by the byte--- argument, consuming the delimiter. I.e.------ > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]--- > split 'a' "aXaXaXa" == ["","X","X","X"]--- > split 'x' "x" == ["",""]--- --- and------ > intercalate [c] . split c == id--- > split == splitWith . (==)--- --- As for all splitting functions in this library, this function does--- not copy the substrings, it just constructs new 'ByteStrings' that--- are slices of the original.----{-@ split :: Char -> b:LByteStringNE -> (LByteStringSplit b) @-}-split :: Char -> ByteString -> [ByteString]-split = L.split . c2w-{-# INLINE split #-}---- | /O(n)/ Splits a 'ByteString' into components delimited by--- separators, where the predicate returns True for a separator element.--- The resulting components do not contain the separators. Two adjacent--- separators result in an empty component in the output. eg.------ > splitWith (=='a') "aabbaca" == ["","","bb","c",""]----{-@ splitWith :: (Char -> Bool) -> b:LByteStringNE -> (LByteStringSplit b) @-}-splitWith :: (Char -> Bool) -> ByteString -> [ByteString]-splitWith f = L.splitWith (f . w2c)-{-# INLINE splitWith #-}---- | The 'groupBy' function is the non-overloaded version of 'group'.-groupBy :: (Char -> Char -> Bool) -> ByteString -> [ByteString]-groupBy k = L.groupBy (\a b -> k (w2c a) (w2c b))---- | /O(1)/ 'ByteString' index (subscript) operator, starting from 0.-{-@ index :: b:L.ByteString -> n:{v:Nat64 | (LBValid b v)} -> Char @-}-index :: ByteString -> Int64 -> Char---LIQUID index = (w2c .) . L.index-index b i = w2c $ L.index b i-{-# INLINE index #-}---- | /O(n)/ The 'elemIndex' function returns the index of the first--- element in the given 'ByteString' which is equal (by memchr) to the--- query element, or 'Nothing' if there is no such element.-elemIndex :: Char -> ByteString -> Maybe Int64-elemIndex = L.elemIndex . c2w-{-# INLINE elemIndex #-}---- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning--- the indices of all elements equal to the query element, in ascending order.-elemIndices :: Char -> ByteString -> [Int64]-elemIndices = L.elemIndices . c2w-{-# INLINE elemIndices #-}---- | The 'findIndex' function takes a predicate and a 'ByteString' and--- returns the index of the first element in the ByteString satisfying the predicate.-findIndex :: (Char -> Bool) -> ByteString -> Maybe Int64-findIndex f = L.findIndex (f . w2c)-{-# INLINE findIndex #-}---- | The 'findIndices' function extends 'findIndex', by returning the--- indices of all elements satisfying the predicate, in ascending order.-findIndices :: (Char -> Bool) -> ByteString -> [Int64]-findIndices f = L.findIndices (f . w2c)---- | count returns the number of times its argument appears in the ByteString------ > count == length . elemIndices--- > count '\n' == length . lines------ But more efficiently than using length on the intermediate list.-count :: Char -> ByteString -> Int64-count c = L.count (c2w c)---- | /O(n)/ 'elem' is the 'ByteString' membership predicate. This--- implementation uses @memchr(3)@.-elem :: Char -> ByteString -> Bool-elem c = L.elem (c2w c)-{-# INLINE elem #-}---- | /O(n)/ 'notElem' is the inverse of 'elem'-notElem :: Char -> ByteString -> Bool-notElem c = L.notElem (c2w c)-{-# INLINE notElem #-}---- | /O(n)/ 'filter', applied to a predicate and a ByteString,--- returns a ByteString containing those characters that satisfy the--- predicate.-filter :: (Char -> Bool) -> ByteString -> ByteString-filter f = L.filter (f . w2c)-{-# INLINE [1] filter #-}---- | /O(n)/ and /O(n\/c) space/ A first order equivalent of /filter .--- (==)/, for the common case of filtering a single Char. It is more--- efficient to use /filterChar/ in this case.------ > filterByte == filter . (==)------ filterChar is around 10x faster, and uses much less space, than its--- filter equivalent----filterChar :: Char -> ByteString -> ByteString-filterChar c ps = replicate (count c ps) c-{-# INLINE filterChar #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter ((==) x) = filterChar x- #-}--{-# RULES- "FPS specialise filter (== x)" forall x.- filter (== x) = filterChar x- #-}---- | /O(n)/ The 'find' function takes a predicate and a ByteString,--- and returns the first element in matching the predicate, or 'Nothing'--- if there is no such element.-find :: (Char -> Bool) -> ByteString -> Maybe Char-find f ps = w2c `fmap` L.find (f . w2c) ps-{-# INLINE find #-}--{---- | /O(n)/ A first order equivalent of /filter . (==)/, for the common--- case of filtering a single Char. It is more efficient to use--- filterChar in this case.------ > filterChar == filter . (==)------ filterChar is around 10x faster, and uses much less space, than its--- filter equivalent----filterChar :: Char -> ByteString -> ByteString-filterChar c = L.filterByte (c2w c)-{-# INLINE filterChar #-}---- | /O(n)/ A first order equivalent of /filter . (\/=)/, for the common--- case of filtering a single Char out of a list. It is more efficient--- to use /filterNotChar/ in this case.------ > filterNotChar == filter . (/=)------ filterNotChar is around 3x faster, and uses much less space, than its--- filter equivalent----filterNotChar :: Char -> ByteString -> ByteString-filterNotChar c = L.filterNotByte (c2w c)-{-# INLINE filterNotChar #-}--}---- | /O(n)/ 'zip' takes two ByteStrings and returns a list of--- corresponding pairs of Chars. If one input ByteString is short,--- excess elements of the longer ByteString are discarded. This is--- equivalent to a pair of 'unpack' operations, and so space--- usage may be large for multi-megabyte ByteStrings-{-@ zip :: L.ByteString -> L.ByteString -> [(Char,Char)] @-}-zip :: ByteString -> ByteString -> [(Char,Char)]-zip ps qs- | L.null ps || L.null qs = []- | otherwise = (head ps, head qs) : zip (L.tail ps) (L.tail qs)---- | 'zipWith' generalises 'zip' by zipping with the function given as--- the first argument, instead of a tupling function. For example,--- @'zipWith' (+)@ is applied to two ByteStrings to produce the list--- of corresponding sums.-zipWith :: (Char -> Char -> a) -> ByteString -> ByteString -> [a]-zipWith f = L.zipWith ((. w2c) . f . w2c)---- | 'lines' breaks a ByteString up into a list of ByteStrings at--- newline Chars. The resulting strings do not contain newlines.----lines :: ByteString -> [ByteString]-lines Empty = []-lines (Chunk c0 cs0) = loop0 c0 cs0- where- -- this is a really performance sensitive function but the- -- chunked representation makes the general case a bit expensive- -- however assuming a large chunk size and normalish line lengths- -- we will find line endings much more frequently than chunk- -- endings so it makes sense to optimise for that common case.- -- So we partition into two special cases depending on whether we- -- are keeping back a list of chunks that will eventually be output- -- once we get to the end of the current line.-- -- the common special case where we have no existing chunks of- -- the current line- loop0 :: B.ByteString -> ByteString -> [ByteString]- STRICT2(loop0)- loop0 c cs =- case B.elemIndex (c2w '\n') c of- Nothing -> case cs of- Empty | B.null c -> []- | otherwise -> Chunk c Empty : []- (Chunk c' cs')- | B.null c -> loop0 c' cs'- | otherwise -> loop c' [c] cs'-- Just n | n /= 0 -> Chunk (B.unsafeTake n c) Empty- : loop0 (B.unsafeDrop (n+1) c) cs- | otherwise -> Empty- : loop0 (B.unsafeTail c) cs-- -- the general case when we are building a list of chunks that are- -- part of the same line- loop :: B.ByteString -> [B.ByteString] -> ByteString -> [ByteString]- STRICT3(loop)- loop c line cs =- case B.elemIndex (c2w '\n') c of- Nothing ->- case cs of- Empty -> let c' = revChunks (c : line)- in c' `seq` (c' : [])-- (Chunk c' cs') -> loop c' (c : line) cs'-- Just n ->- let c' = revChunks (B.unsafeTake n c : line)- in c' `seq` (c' : loop0 (B.unsafeDrop (n+1) c) cs)---- | 'unlines' is an inverse operation to 'lines'. It joins lines,--- after appending a terminating newline to each.-unlines :: [ByteString] -> ByteString-unlines [] = empty-unlines ss = (concat $ List.intersperse nl ss) `append` nl -- half as much space- where nl = singleton '\n'---- | 'words' breaks a ByteString up into a list of words, which--- were delimited by Chars representing white space. And------ > tokens isSpace = words------LIQUID FIXME: splitWith requires non-empty bytestring for now..-{-@ words :: LByteStringNE -> [L.ByteString] @-}-words :: ByteString -> [ByteString]-words = List.filter (not . L.null) . L.splitWith isSpaceWord8-{-# INLINE words #-}---- | The 'unwords' function is analogous to the 'unlines' function, on words.-unwords :: [ByteString] -> ByteString-unwords = intercalate (singleton ' ')-{-# INLINE unwords #-}---- | readInt reads an Int from the beginning of the ByteString. If--- there is no integer at the beginning of the string, it returns--- Nothing, otherwise it just returns the int read, and the rest of the--- string.-readInt :: ByteString -> Maybe (Int, ByteString)-readInt Empty = Nothing-readInt (Chunk x xs) =- case w2c (B.unsafeHead x) of- '-' -> loop True 0 0 xs (B.unsafeTail x)- '+' -> loop False 0 0 xs (B.unsafeTail x)- _ -> loop False 0 0 xs x-- where loop :: Bool -> Int -> Int -> ByteString -> B.ByteString -> Maybe (Int, ByteString)- --LIQUID swap params 4 and 5- {-@ decrease loop 4 5 @-}- STRICT5(loop)- loop neg i n cs c- | B.null c = case cs of- Empty -> end neg i n c cs- (Chunk c' cs') -> loop neg i n cs' c'- | otherwise =- case B.unsafeHead c of- w | w >= 0x30- && w <= 0x39 -> loop neg (i+1)- (n * 10 + (fromIntegral w - 0x30))- cs (B.unsafeTail c)- | otherwise -> end neg i n c cs-- end _ 0 _ _ _ = Nothing- end neg _ n c cs = let n' | neg = negate n- | otherwise = n- c' = chunk c cs- in n' `seq` c' `seq` Just $! (n', c')----- | readInteger reads an Integer from the beginning of the ByteString. If--- there is no integer at the beginning of the string, it returns Nothing,--- otherwise it just returns the int read, and the rest of the string.-readInteger :: ByteString -> Maybe (Integer, ByteString)-readInteger Empty = Nothing-readInteger (Chunk c0 cs0) =- case w2c (B.unsafeHead c0) of- '-' -> first (B.unsafeTail c0) cs0 >>= \(n, cs') -> return (-n, cs')- '+' -> first (B.unsafeTail c0) cs0- _ -> first c0 cs0-- where first c cs- | B.null c = case cs of- Empty -> Nothing- (Chunk c' cs') -> first' c' cs'- | otherwise = first' c cs-- first' c cs = case B.unsafeHead c of- w | w >= 0x30 && w <= 0x39 -> Just $- loop 1 (fromIntegral w - 0x30) [] cs (B.unsafeTail c)- | otherwise -> Nothing-- --LIQUID swap params 4 and 5- loop :: Int -> Int -> [Integer]- -> ByteString -> B.ByteString -> (Integer, ByteString)- {-@ decrease loop 4 5 @-}- STRICT5(loop)- loop d acc ns cs c- | B.null c = case cs of- Empty -> combine d acc ns c cs- (Chunk c' cs') -> loop d acc ns cs' c'- | otherwise =- case B.unsafeHead c of- w | w >= 0x30 && w <= 0x39 ->- if d < 9 then loop (d+1)- (10*acc + (fromIntegral w - 0x30))- ns cs (B.unsafeTail c)- else loop 1 (fromIntegral w - 0x30)- (fromIntegral acc : ns)- cs (B.unsafeTail c)- | otherwise -> combine d acc ns c cs-- combine _ acc [] c cs = end (fromIntegral acc) c cs- combine d acc ns c cs =- end (10^d * combine1 1000000000 ns + fromIntegral acc) c cs-- --LIQUID combine1 _ [n] = n- --LIQUID combine1 b ns = combine1 (b*b) $ combine2 b ns- --LIQUID - --LIQUID combine2 b (n:m:ns) = let t = n+m*b in t `seq` (t : combine2 b ns)- --LIQUID combine2 _ ns = ns-- end n c cs = let c' = chunk c cs- in c' `seq` (n, c')--{-@ combine1 :: Integer -> x:{v:[Integer] | (len v) > 0}- -> Integer- @-}-{-@ decrease combine1 2 @-}-combine1 :: Integer -> [Integer] -> Integer-combine1 _ [] = error "impossible"-combine1 _ [n] = n-combine1 b ns = combine1 (b*b) $ combine2 b ns--{-@ combine2 :: Integer -> x:[Integer]- -> {v:[Integer] | if len x > 1- then (len v < len x && len v > 0)- else (len v <= len x) }- @-}-{-@ decrease combine2 2 @-}-combine2 :: Integer -> [Integer] -> [Integer]-combine2 b (n:m:ns) = let t = m*b + n in t `seq` (t : combine2 b ns)-combine2 _ ns = ns---- | Read an entire file /lazily/ into a 'ByteString'. Use 'text mode'--- on Windows to interpret newlines-readFile :: FilePath -> IO ByteString-readFile f = openFile f ReadMode >>= hGetContents---- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openFile f WriteMode) hClose- (\hdl -> hPut hdl txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openFile f AppendMode) hClose- (\hdl -> hPut hdl txt)----- ------------------------------------------------------------------------ Internal utilities---- reverse a list of possibly-empty chunks into a lazy ByteString-revChunks :: [B.ByteString] -> ByteString-revChunks cs = List.foldl' (flip chunk) Empty cs
@@ -1,200 +0,0 @@-{-@ LIQUID "--maxparams=3" @-}-{-@ LIQUID "--prune-unsorted" @-}-{- LIQUID "--trust-sizes" @-}--{-# OPTIONS_GHC -cpp -fglasgow-exts #-}--- |--- Module : Data.ByteString.Lazy.Internal--- License : BSD-style--- Maintainer : dons@cse.unsw.edu.au, duncan@haskell.org--- Stability : experimental--- Portability : portable--- --- A module containing semi-public 'ByteString' internals. This exposes--- the 'ByteString' representation and low level construction functions.--- Modules which extend the 'ByteString' system will need to use this module--- while ideally most users will be able to make do with the public interface--- modules.----module Data.ByteString.Lazy.Internal (-- liquidCanary, -- -- * The lazy @ByteString@ type and representation- ByteString(..), -- instances: Eq, Ord, Show, Read, Data, Typeable- chunk,- foldrChunks,- foldlChunks,-- -- * Data type invariant and abstraction function- invariant,- checkInvariant,-- -- * Chunk allocation sizes- defaultChunkSize,- smallChunkSize,- chunkOverhead, -- ) where--import qualified Data.ByteString.Internal as S---- LIQUID-import Language.Haskell.Liquid.Prelude (liquidError)-import GHC.Word (Word64)--- import qualified Data.ByteString.Internal--- import Foreign.ForeignPtr (ForeignPtr)--- import Data.Word (Word, Word8, Word16, Word32, Word64)--- import Foreign.Ptr (Ptr)--- import qualified Foreign.C.String--import Foreign.Storable (sizeOf)--#if defined(__GLASGOW_HASKELL__)-import Data.Generics (Data(..), Typeable(..))-#endif---- | A space-efficient representation of a Word8 vector, supporting many--- efficient operations. A 'ByteString' contains 8-bit characters only.------ Instances of Eq, Ord, Read, Show, Data, Typeable----data ByteString = Empty | Chunk {-# UNPACK #-} !S.ByteString ByteString- deriving (Show)--- LIQUID deriving (Show, Read--- LIQUID #if defined(__GLASGOW_HASKELL__)--- LIQUID ,Data, Typeable--- LIQUID #endif--- LIQUID )--{-@ data ByteString [lbLength]- = Empty- | Chunk {lbiHead :: ByteStringNE, lbiRest :: ByteString }- @-}--{-@ measure lbLength :: ByteString -> Int- lbLength Empty = 0 - lbLength (Chunk b bs) = (bLength b) + (lbLength bs)- @-}--{-@ measure lbLengths :: [ByteString] -> Int- lbLengths [] = 0- lbLengths (x:xs) = (lbLength x) + (lbLengths xs)- @-}--{-@ invariant {v:ByteString | (lbLength v) >= 0} @-}-{-@ invariant {v:[ByteString] | (lbLengths v) >= 0} @-}--{-@ type LByteStringSplit B = {v:[ByteString] | ((lbLengths v) + (len v) - 1) = (lbLength B) }- @-}--{-@ type LByteStringPair B = (ByteString, ByteString)<{\x1 x2 -> (lbLength x1) + (lbLength x2) = (lbLength B)}>- @-}--{-@ predicate LBValid B N = ((N >= 0) && (N < (lbLength B))) @-}--{-@ type LByteStringN N = {v:ByteString | (lbLength v) = N} @-}-{-@ type LByteStringNE = {v:ByteString | (lbLength v) > 0} @-}-{-@ type LByteStringSZ B = {v:ByteString | (lbLength v) = (lbLength B)} @-}-{-@ type LByteStringLE B = {v:ByteString | (lbLength v) <= (lbLength B)} @-}----------------------------------------------------------------------------{- liquidCanary :: x:Int -> {v: Int | v > x} @-}-liquidCanary :: Int -> Int-liquidCanary x = x - 1----- | The data type invariant:--- Every ByteString is either 'Empty' or consists of non-null 'S.ByteString's.--- All functions must preserve this, and the QC properties must check this.------- LIQUID RENAME: rename `invariant` to `invt` to avoid name clash!-{-@ invt :: ByteString -> {v: Bool | v} @-}-invt :: ByteString -> Bool-invt Empty = True -invt (Chunk (S.PS _ _ len) cs) = len > 0 && invt cs--invariant = invt---- | In a form that checks the invariant lazily.-{-@ checkInvariant :: ByteString -> ByteString @-}-checkInvariant :: ByteString -> ByteString-checkInvariant Empty = Empty-checkInvariant (Chunk c@(S.PS _ _ len) cs)- | len > 0 = Chunk c (checkInvariant cs)- | otherwise = liquidError $ "Data.ByteString.Lazy: invariant violation:"- ++ show (Chunk c cs)------------------------------------------------------------------------------ | Smart constructor for 'Chunk'. Guarantees the data type invariant.-{-@ chunk :: b:_ -> bs:ByteString- -> {v:ByteString | (lbLength v) = ((bLength b) + (lbLength bs))}- @-}-chunk :: S.ByteString -> ByteString -> ByteString-chunk c@(S.PS _ _ len) cs | len == 0 = cs- | otherwise = Chunk c cs-{-# INLINE chunk #-}---- | Consume the chunks of a lazy ByteString with a natural right fold.-{-@ foldrChunks :: forall <p :: ByteString -> a -> Bool>.- (bs:ByteString- -> b:ByteStringNE- -> a<p bs>- -> a<p (Chunk b bs)>)- -> a<p Empty>- -> b:ByteString- -> a<p b>- @-}---LIQUID GHOST added parameter to `f` for abstract refinement-foldrChunks :: (ByteString -> S.ByteString -> a -> a) -> a -> ByteString -> a-foldrChunks f z = go- where go Empty = z- go (Chunk c cs) = f cs c (go cs)-{-# INLINE foldrChunks #-}---- | Consume the chunks of a lazy ByteString with a strict, tail-recursive,--- accumulating left fold.-{-@ foldlChunks :: (a -> ByteStringNE -> a)- -> a- -> ByteString- -> a- @-}-foldlChunks :: (a -> S.ByteString -> a) -> a -> ByteString -> a-foldlChunks f z = go z- where go a _ | a `seq` False = undefined- go a Empty = a- go a (Chunk c cs) = go (f a c) cs-{-# INLINE foldlChunks #-}------------------------------------------------------------------------------ The representation uses lists of packed chunks. When we have to convert from--- a lazy list to the chunked representation, then by default we use this--- chunk size. Some functions give you more control over the chunk size.------ Measurements here:--- http://www.cse.unsw.edu.au/~dons/tmp/chunksize_v_cache.png------ indicate that a value around 0.5 to 1 x your L2 cache is best.--- The following value assumes people have something greater than 128k,--- and need to share the cache with other programs.---- | Currently set to 32k, less the memory management overhead-{-@ defaultChunkSize :: {v:Nat | v = 32752} @-}-defaultChunkSize :: Int-defaultChunkSize = {-LIUQID MULTIPLY 32 * k -} 32768 - chunkOverhead- where k = 1024---- | Currently set to 4k, less the memory management overhead-{-@ smallChunkSize :: {v:Nat | v = 4080} @-}-smallChunkSize :: Int-smallChunkSize = {-LIQUID MULTIPLY 4 * k -} 4096 - chunkOverhead- where k = 1024---- | The memory management overhead. Currently this is tuned for GHC only.-{-@ chunkOverhead :: {v:Nat | v = 16} @-}-chunkOverhead :: Int-chunkOverhead = 2 * sizeOf (undefined :: Int)
@@ -1,216 +0,0 @@-{-@ LIQUID "--maxparams=4" @-}-{-@ LIQUID "--pruneunsorted" @-}--{-# OPTIONS_GHC -cpp -fglasgow-exts -fno-warn-orphans -fno-warn-incomplete-patterns #-}--{-# LANGUAGE PartialTypeSignatures #-}---- #prune---- |--- Module : Data.ByteString.Lazy--- Copyright : (c) Don Stewart 2006--- (c) Duncan Coutts 2006--- License : BSD-style------ Maintainer : dons@galois.com--- Stability : experimental--- Portability : portable--- --- A time and space-efficient implementation of lazy byte vectors--- using lists of packed 'Word8' arrays, suitable for high performance--- use, both in terms of large data quantities, or high speed--- requirements. Byte vectors are encoded as lazy lists of strict 'Word8'--- arrays of bytes. They provide a means to manipulate large byte vectors--- without requiring the entire vector be resident in memory.------ Some operations, such as concat, append, reverse and cons, have--- better complexity than their "Data.ByteString" equivalents, due to--- optimisations resulting from the list spine structure. And for other--- operations lazy ByteStrings are usually within a few percent of--- strict ones, but with better heap usage. For data larger than the--- available memory, or if you have tight memory constraints, this--- module will be the only option. The default chunk size is 64k, which--- should be good in most circumstances. For people with large L2--- caches, you may want to increase this to fit your cache.------ This module is intended to be imported @qualified@, to avoid name--- clashes with "Prelude" functions. eg.------ > import qualified Data.ByteString.Lazy as B------ Original GHC implementation by Bryan O\'Sullivan.--- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.--- Rewritten to support slices and use 'Foreign.ForeignPtr.ForeignPtr'--- by David Roundy.--- Polished and extended by Don Stewart.--- Lazy variant by Duncan Coutts and Don Stewart.-----module Data.ByteString.LazyZip (- -- * Zipping and unzipping ByteStrings- zip, -- :: ByteString -> ByteString -> [(Word8,Word8)]- zipWith, -- :: (Word8 -> Word8 -> c) -> ByteString -> ByteString -> [c]-- ) where--import qualified Prelude-import Prelude hiding- (reverse,head,tail,last,init,null,length,map,lines,foldl,foldr,unlines- ,concat,any,take,drop,splitAt,takeWhile,dropWhile,span,break,elem,filter,maximum- ,minimum,all,concatMap,foldl1,foldr1,scanl, scanl1, scanr, scanr1- ,repeat, cycle, interact, iterate,readFile,writeFile,appendFile,replicate- ,getContents,getLine,putStr,putStrLn ,zip,zipWith,unzip,notElem)--import qualified Data.List as L -- L for list/lazy-import qualified Data.ByteString as S -- S for strict (hmm...)-import qualified Data.ByteString.Internal as S-import qualified Data.ByteString.Unsafe as S-import Data.ByteString.Lazy.Internal-import qualified Data.ByteString.Fusion as F--import Data.Monoid (Monoid(..))--import Data.Word (Word8,Word64)-import Data.Int (Int64)-import System.IO (Handle,stdin,stdout,openBinaryFile,IOMode(..)- ,hClose,hWaitForInput,hIsEOF)-import System.IO.Unsafe-#ifndef __NHC__-import Control.Exception (bracket)-#else-import IO (bracket)-#endif--import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr-import Foreign.Storable----LIQUID-import Data.ByteString.Fusion (PairS(..), MaybeS(..))-import Data.Int-import Data.Word (Word, Word8, Word16, Word32, Word64)-import Foreign.ForeignPtr (ForeignPtr)---- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined---- --------------------------------------------------------------------------------{-@ predicate LZipLen V X Y = (len V) = (if (lbLength X) <= (lbLength Y) then (lbLength X) else (lbLength Y)) @-}-{-@ zip :: x:ByteString -> y:LByteStringSZ x -> {v:[(Word8, Word8)] | (LZipLen v x y) } @-}-zip :: ByteString -> ByteString -> [(Word8,Word8)]-zip = zipWith (,)---- | 'zipWith' generalises 'zip' by zipping with the function given as--- the first argument, instead of a tupling function. For example,--- @'zipWith' (+)@ is applied to two ByteStrings to produce the list of--- corresponding sums.-{-@ zipWith :: (Word8 -> Word8 -> a) -> x:ByteString -> y:LByteStringSZ x -> {v:[a] | (LZipLen v x y)} @-}-zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]-zipWith _ Empty _ = []-zipWith _ _ Empty = []-zipWith f (Chunk a as) (Chunk b bs) = go a as b bs (sz a as b bs) 0- where- -- go x xs y ys = f (S.unsafeHead x) (S.unsafeHead y)- -- : to (S.unsafeTail x) xs (S.unsafeTail y) ys-- -- to x Empty _ _ | S.null x = []- -- to _ _ y Empty | S.null y = []- -- -- to x xs y ys | not (S.null x)- -- -- && not (S.null y) = go x xs y ys- -- to x xs _ (Chunk y' ys) | not (S.null x) = go x xs y' ys- -- --LIQUID to _ (Chunk x' xs) y ys | not (S.null y) = go x' xs y ys- -- --LIQUID to _ (Chunk x' xs) _ (Chunk y' ys) = go x' xs y' ys- -- --LIQUID FIXME: these guards "should" be implied by the above checks- -- to x (Chunk x' xs) y ys | not (S.null y)- -- && S.null x = go x' xs y ys- -- to x (Chunk x' xs) y (Chunk y' ys) | S.null x- -- && S.null y = go x' xs y' ys-- {-@ go :: x:ByteStringNE -> xs:ByteString- -> y:ByteStringNE -> ys:ByteString- -> ddd:{v:Nat64 | v = (bLength x) + (lbLength xs) + (bLength y) + (lbLength ys)}- -> zzz:{v:Nat64 | v = 0}- -> {v:[a] | (len v)- = (if (((bLength x) + (lbLength xs)) <= ((bLength y) + (lbLength ys)))- then ((bLength x) + (lbLength xs))- else ((bLength y) + (lbLength ys)))}- / [ddd, zzz] - @-}- {- decrease go 6 7 @-}- go :: _ -> _ - -> _ -> _ - -> Int64- -> Int64 - -> [_] - go x xs y ys d (z :: Int64)- = (f (S.unsafeHead x) (S.unsafeHead y))- : (to (S.unsafeTail x) xs (S.unsafeTail y) ys (sz (S.unsafeTail x) xs (S.unsafeTail y) ys) 1)- - {-@ to :: x:_ -> xs:ByteString- -> y:_ -> ys:ByteString- -> dda:{v:Nat64 | v = (bLength x) + (lbLength xs) + (bLength y) + (lbLength ys)}- -> zza:{v:Nat64 | v = 1}- -> {v:[a] | (len v)- = (if (((bLength x) + (lbLength xs)) <= ((bLength y) + (lbLength ys)))- then ((bLength x) + (lbLength xs))- else ((bLength y) + (lbLength ys)))}- / [dda, zza]- @-}- - {- decrease to 6 7 @-}- - to :: _ -- ByteString- -> _ -- ByteString- -> _ -- ByteString- -> _ -- ByteString- -> Int64 - -> Int64- -> [_] - - to x Empty _ _ d (_::Int64) | S.null x = []- to _ _ y Empty d _ | S.null y = []- to x xs y ys d _ | not (S.null x)- && not (S.null y) = go x xs y ys (sz x xs y ys) 0- to x xs _ (Chunk y' ys) d _ | not (S.null x) = go x xs y' ys (sz x xs y' ys) 0- --LIQUID to _ (Chunk x' xs) y ys | not (S.null y) = go x' xs y ys- --LIQUID to _ (Chunk x' xs) _ (Chunk y' ys) = go x' xs y' ys- --LIQUID FIXME: these guards "should" be implied by the above checks- to x (Chunk x' xs) y ys d _ | not (S.null y)- && S.null x = go x' xs y ys (sz x' xs y ys) 0- to x (Chunk x' xs) y (Chunk y' ys) d _ | S.null x- && S.null y = go x' xs y' ys (sz x' xs y' ys) 0- - -{-@ sz :: x:_ -> xs:_ - -> y:_ -> ys:_- -> {v:Nat64 | v = ((bLength x) + (lbLength xs) + (bLength y) + (lbLength ys))}- @-}-sz x xs y ys = fromIntegral (S.length x) + length xs- + fromIntegral (S.length y) + length ys- -{-@ qualif ByteStringNE(v:Data.ByteString.Internal.ByteString): (bLength v) > 0 @-}--{- qualif LBZip(v:List a,- x:S.ByteString,- xs:ByteString,- y:S.ByteString,- ys:ByteString):- (len v) = (if (((bLength x) + (lbLength xs)) <= ((bLength y) + (lbLength ys)))- then ((bLength x) + (lbLength xs))- else ((bLength y) + (lbLength ys)))- @-}--{-@ length :: b:ByteString -> {v:Int64 | v = (lbLength b)} @-}-length :: ByteString -> Int64-length = undefined
@@ -1,346 +0,0 @@-{-@ LIQUID "--prune-unsorted" @-}--{-# OPTIONS_GHC -cpp -fglasgow-exts #-}--- |--- Module : Data.ByteString.Unsafe--- License : BSD-style--- Maintainer : dons@cse.unsw.edu.au, duncan@haskell.org--- Stability : experimental--- Portability : portable------ A module containing unsafe 'ByteString' operations. This exposes--- the 'ByteString' representation and low level construction functions.--- Modules which extend the 'ByteString' system will need to use this module--- while ideally most users will be able to make do with the public interface--- modules.----module Data.ByteString.Unsafe (-- -- LIQUID- liquidCanary1,-- -- * Unchecked access- unsafeHead, -- :: ByteString -> Word8- unsafeTail, -- :: ByteString -> ByteString- unsafeIndex, -- :: ByteString -> Int -> Word8- unsafeTake, -- :: Int -> ByteString -> ByteString- unsafeDrop, -- :: Int -> ByteString -> ByteString-- -- * Low level interaction with CStrings- -- ** Using ByteStrings with functions for CStrings- unsafeUseAsCString, -- :: ByteString -> (CString -> IO a) -> IO a- unsafeUseAsCStringLen, -- :: ByteString -> (CStringLen -> IO a) -> IO a-- -- ** Converting CStrings to ByteStrings- unsafePackCString, -- :: CString -> IO ByteString- unsafePackCStringLen, -- :: CStringLen -> IO ByteString- unsafePackMallocCString,-- :: CString -> IO ByteString--#if defined(__GLASGOW_HASKELL__)- unsafePackAddress, -- :: Addr# -> IO ByteString- unsafePackAddressLen, -- :: Int -> Addr# -> IO ByteString- unsafePackCStringFinalizer, -- :: Ptr Word8 -> Int -> IO () -> IO ByteString- unsafeFinalize, -- :: ByteString -> IO ()-#endif-- ) where--import Data.ByteString.Internal--import Foreign.ForeignPtr (newForeignPtr_, newForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr, plusPtr, castPtr)--import Foreign.Storable (Storable(..))-import Foreign.C.String (CString, CStringLen)---- LIQUID-import Language.Haskell.Liquid.Prelude (liquidError)-import Language.Haskell.Liquid.Foreign (mkPtr, cSizeInt)-import Foreign.ForeignPtr (ForeignPtr)-import Data.Word-import Foreign.C.Types (CChar(..), CInt(..), CSize(..), CULong(..))-import GHC.Base--#ifndef __NHC__-import Control.Exception (assert)-#endif--import Data.Word (Word8)--#if defined(__GLASGOW_HASKELL__)-import qualified Foreign.ForeignPtr as FC (finalizeForeignPtr)-import qualified Foreign.Concurrent as FC (newForeignPtr)----import Data.Generics (Data(..), Typeable(..))--import GHC.Exts (Addr#)-import GHC.Ptr (Ptr(..))-#endif---- An alternative to Control.Exception (assert) for nhc98-#ifdef __NHC__-#define assert assertS "__FILE__ : __LINE__"-assertS :: String -> Bool -> a -> a-assertS _ True = id-assertS s False = error ("assertion failed at "++s)-#endif---- ----------------------------------------------------------------------------------- Useful macros, until we have bang patterns-----#define STRICT1(f) f a | a `seq` False = undefined-#define STRICT2(f) f a b | a `seq` b `seq` False = undefined-#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined-#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined-#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined---{- liquidCanary1 :: x:Int -> {v: Int | v > x} @-}-liquidCanary1 :: Int -> Int-liquidCanary1 x = x - 1---- --------------------------------------------------------------------------- Extensions to the basic interface------- | A variety of 'head' for non-empty ByteStrings. 'unsafeHead' omits the--- check for the empty case, so there is an obligation on the programmer--- to provide a proof that the ByteString is non-empty.-{-@ unsafeHead :: {v:ByteString | (bLength v) > 0} -> Word8 @-}-unsafeHead :: ByteString -> Word8-unsafeHead (PS x s l) = assert (l > 0) $- inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p s-{-# INLINE unsafeHead #-}---- | A variety of 'tail' for non-empty ByteStrings. 'unsafeTail' omits the--- check for the empty case. As with 'unsafeHead', the programmer must--- provide a separate proof that the ByteString is non-empty.-{-@ unsafeTail :: b:{v:ByteString | (bLength v) > 0}- -> {v:ByteString | (bLength v) = (bLength b) - 1} @-}-unsafeTail :: ByteString -> ByteString-unsafeTail (PS ps s l) = assert (l > 0) $ PS ps (s+1) (l-1)-{-# INLINE unsafeTail #-}---- | Unsafe 'ByteString' index (subscript) operator, starting from 0, returning a 'Word8'--- This omits the bounds check, which means there is an accompanying--- obligation on the programmer to ensure the bounds are checked in some--- other way.--{-@ unsafeIndex :: b:ByteString- -> {v:Nat | v < (bLength b)}- -> Word8- @-}-unsafeIndex :: ByteString -> Int -> Word8-unsafeIndex (PS x s l) i = assert (i >= 0 && i < l) $- inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+i)-{-# INLINE unsafeIndex #-}---- | A variety of 'take' which omits the checks on @n@ so there is an--- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.-{-@ unsafeTake :: n:Nat -> b:{v: ByteString | n <= (bLength v)} -> (ByteStringN n) @-}-unsafeTake :: Int -> ByteString -> ByteString-unsafeTake n (PS x s l) = assert (0 <= n && n <= l) $ PS x s n-{-# INLINE unsafeTake #-}---- | A variety of 'drop' which omits the checks on @n@ so there is an--- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.--{-@ unsafeDrop :: n:Nat- -> b:{v: ByteString | n <= (bLength v)}- -> {v:ByteString | (bLength v) = (bLength b) - n} @-}-unsafeDrop :: Int -> ByteString -> ByteString-unsafeDrop n (PS x s l) = assert (0 <= n && n <= l) $ PS x (s+n) (l-n)-{-# INLINE unsafeDrop #-}---#if defined(__GLASGOW_HASKELL__)--- | /O(n)/ Pack a null-terminated sequence of bytes, pointed to by an--- Addr\# (an arbitrary machine address assumed to point outside the--- garbage-collected heap) into a @ByteString@. A much faster way to--- create an Addr\# is with an unboxed string literal, than to pack a--- boxed string. A unboxed string literal is compiled to a static @char--- []@ by GHC. Establishing the length of the string requires a call to--- @strlen(3)@, so the Addr# must point to a null-terminated buffer (as--- is the case with "string"# literals in GHC). Use 'unsafePackAddress'--- if you know the length of the string statically.------ An example:------ > literalFS = unsafePackAddress "literal"#------ This function is /unsafe/. If you modify the buffer pointed to by the--- original Addr# this modification will be reflected in the resulting--- @ByteString@, breaking referential transparency.----{-@ unsafePackAddress :: a:Addr# -> IO {v:ByteString | (bLength v) = (addrLen a)} @-}-unsafePackAddress :: Addr# -> IO ByteString-unsafePackAddress addr# = do- p <- newForeignPtr_ cstr- l <- c_strlen cstr- return $ PS p 0 ({- LIQUID fromIntegral -} cSizeInt l)- where- cstr = {- LIQUID Ptr -} mkPtr addr#-{-# INLINE unsafePackAddress #-}------ | /O(1)/ 'unsafePackAddressLen' provides constant-time construction of--- 'ByteStrings' which is ideal for string literals. It packs a--- null-terminated sequence of bytes into a 'ByteString', given a raw--- 'Addr\#' to the string, and the length of the string.------ This function is /unsafe/ in two ways:------ * the length argument is assumed to be correct. If the length--- argument is incorrect, it is possible to overstep the end of the--- byte array.------ * if the underying Addr# is later modified, this change will be--- reflected in resulting @ByteString@, breaking referential--- transparency.------ If in doubt, don't use these functions.----{-@ unsafePackAddressLen :: len:Nat -> {v:Addr# | len <= (addrLen v)} -> IO {v: ByteString | ((bLength v) = len)} @-}-unsafePackAddressLen :: Int -> Addr# -> IO ByteString-unsafePackAddressLen len addr# = do- p <- newForeignPtr_ ({- LIQUID Ptr -} mkPtr addr#)- return $ PS p 0 len-{-# INLINE unsafePackAddressLen #-}---- | /O(1)/ Construct a 'ByteString' given a Ptr Word8 to a buffer, a--- length, and an IO action representing a finalizer. This function is--- not available on Hugs.------ This function is /unsafe/, it is possible to break referential--- transparency by modifying the underlying buffer pointed to by the--- first argument. Any changes to the original buffer will be reflected--- in the resulting @ByteString@.-----{-@ unsafePackCStringFinalizer :: p:(PtrV Word8) -> {v:Nat | v <= (plen p)} -> IO () -> IO ByteString @-}-unsafePackCStringFinalizer :: Ptr Word8 -> Int -> IO () -> IO ByteString-unsafePackCStringFinalizer p l f = do- fp <- FC.newForeignPtr p f- return $ PS fp 0 l------ | Explicitly run the finaliser associated with a 'ByteString'.--- References to this value after finalisation may generate invalid memory--- references.------ This function is /unsafe/, as there may be other--- 'ByteStrings' referring to the same underlying pages. If you use--- this, you need to have a proof of some kind that all 'ByteString's--- ever generated from the underlying byte array are no longer live.----unsafeFinalize :: ByteString -> IO ()-unsafeFinalize (PS p _ _) = FC.finalizeForeignPtr p--#endif----------------------------------------------------------------------------- Packing CStrings into ByteStrings---- | /O(n)/ Build a @ByteString@ from a @CString@. This value will have /no/--- finalizer associated to it, and will not be garbage collected by--- Haskell. The ByteString length is calculated using /strlen(3)/,--- and thus the complexity is a /O(n)/.------ This function is /unsafe/. If the @CString@ is later modified, this--- change will be reflected in the resulting @ByteString@, breaking--- referential transparency.-----{-@ unsafePackCString :: cstr:{v: _ | 0 <= (plen v)} -> IO {v: _ | (bLength v) = (plen cstr)} @-}-unsafePackCString :: CString -> IO ByteString-unsafePackCString cstr = do- fp <- newForeignPtr_ (castPtr cstr)- l <- c_strlen cstr- return $! PS fp 0 ({- LIQUID fromIntegral -} cSizeInt l)---- | /O(1)/ Build a @ByteString@ from a @CStringLen@. This value will--- have /no/ finalizer associated with it, and will not be garbage--- collected by Haskell. This operation has /O(1)/ complexity as we--- already know the final size, so no /strlen(3)/ is required.------ This funtion is /unsafe/. If the original @CStringLen@ is later--- modified, this change will be reflected in the resulting @ByteString@,--- breaking referential transparency.---- LIQUID: tighten spec to use @len@ as size of output ByteString-{-@ unsafePackCStringLen :: CStringLen -> IO ByteString @-}-unsafePackCStringLen :: CStringLen -> IO ByteString-unsafePackCStringLen (ptr,len) = do- fp <- newForeignPtr_ (castPtr ptr)- return $! PS fp 0 ({- fromIntegral -} len)---- | /O(n)/ Build a @ByteString@ from a malloced @CString@. This value will--- have a @free(3)@ finalizer associated to it.------ This funtion is /unsafe/. If the original @CStringLen@ is later--- modified, this change will be reflected in the resulting @ByteString@,--- breaking referential transparency.------ This function is also unsafe if you call its finalizer twice,--- which will result in a /double free/ error.----{-@ unsafePackMallocCString :: cstr:{v: _ | 0 <= (plen v)} -> IO {v: _ | (bLength v) = (plen cstr)} @-}-unsafePackMallocCString :: CString -> IO ByteString-unsafePackMallocCString cstr = do- fp <- newForeignPtr c_free_finalizer (castPtr cstr)- len <- c_strlen cstr- return $! PS fp 0 ({- LIQUID fromIntegral -} cSizeInt len)---- ------------------------------------------------------------------------- | /O(1) construction/ Use a @ByteString@ with a function requiring a--- @CString@.------ This function does zero copying, and merely unwraps a @ByteString@ to--- appear as a @CString@. It is /unsafe/ in two ways:------ * After calling this function the @CString@ shares the underlying--- byte buffer with the original @ByteString@. Thus modifying the--- @CString@, either in C, or using poke, will cause the contents of the--- @ByteString@ to change, breaking referential transparency. Other--- @ByteStrings@ created by sharing (such as those produced via 'take'--- or 'drop') will also reflect these changes. Modifying the @CString@--- will break referential transparency. To avoid this, use--- @useAsCString@, which makes a copy of the original @ByteString@.------ * @CStrings@ are often passed to functions that require them to be--- null-terminated. If the original @ByteString@ wasn't null terminated,--- neither will the @CString@ be. It is the programmers responsibility--- to guarantee that the @ByteString@ is indeed null terminated. If in--- doubt, use @useAsCString@.----{-@ unsafeUseAsCString :: p:ByteString -> ({v: (PtrV CChar) | (bLength p) <= (plen v) } -> IO a) -> IO a @-}-unsafeUseAsCString :: ByteString -> (CString -> IO a) -> IO a-unsafeUseAsCString (PS ps s _) ac = withForeignPtr ps $ \p -> ac (castPtr p `plusPtr` s)----- | /O(1) construction/ Use a @ByteString@ with a function requiring a--- @CStringLen@.------ This function does zero copying, and merely unwraps a @ByteString@ to--- appear as a @CStringLen@. It is /unsafe/:------ * After calling this function the @CStringLen@ shares the underlying--- byte buffer with the original @ByteString@. Thus modifying the--- @CStringLen@, either in C, or using poke, will cause the contents of the--- @ByteString@ to change, breaking referential transparency. Other--- @ByteStrings@ created by sharing (such as those produced via 'take'--- or 'drop') will also reflect these changes. Modifying the @CStringLen@--- will break referential transparency. To avoid this, use--- @useAsCStringLen@, which makes a copy of the original @ByteString@.------{-@ unsafeUseAsCStringLen :: b:ByteString -> ((CStringLenN (bLength b)) -> IO a) -> IO a @-}-unsafeUseAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a-unsafeUseAsCStringLen (PS ps s l) f = withForeignPtr ps $ \p -> f (castPtr p `plusPtr` s,l)
@@ -1,82 +0,0 @@-/*- * Copyright (c) 2003 David Roundy- * Copyright (c) 2005-6 Don Stewart- *- * All rights reserved.- *- * Redistribution and use in source and binary forms, with or without- * modification, are permitted provided that the following conditions- * are met:- * 1. Redistributions of source code must retain the above copyright- * notice, this list of conditions and the following disclaimer.- * 2. Redistributions in binary form must reproduce the above copyright- * notice, this list of conditions and the following disclaimer in the- * documentation and/or other materials provided with the distribution.- * 3. Neither the names of the authors or the names of any contributors- * may be used to endorse or promote products derived from this software- * without specific prior written permission.- *- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF- * SUCH DAMAGE.- */--#include "fpstring.h"--/* copy a string in reverse */-void fps_reverse(unsigned char *q, unsigned char *p, unsigned long n) {- p += n-1;- while (n-- != 0)- *q++ = *p--;-}--/* duplicate a string, interspersing the character through the elements- of the duplicated string */-void fps_intersperse(unsigned char *q,- unsigned char *p,- unsigned long n,- unsigned char c) {-- while (n > 1) {- *q++ = *p++;- *q++ = c;- n--;- }- if (n == 1)- *q = *p;-}--/* find maximum char in a packed string */-unsigned char fps_maximum(unsigned char *p, unsigned long len) {- unsigned char *q, c = *p;- for (q = p; q < p + len; q++)- if (*q > c)- c = *q;- return c;-}--/* find minimum char in a packed string */-unsigned char fps_minimum(unsigned char *p, unsigned long len) {- unsigned char *q, c = *p;- for (q = p; q < p + len; q++)- if (*q < c)- c = *q;- return c;-}--/* count the number of occurences of a char in a string */-unsigned long fps_count(unsigned char *p, unsigned long len, unsigned char w) {- unsigned long c;- for (c = 0; len-- != 0; ++p)- if (*p == w)- ++c;- return c;-}
@@ -1,37 +0,0 @@-#!/usr/bin/python--# used by count.sh--import re-import sys-import string--fname = sys.argv[1]-str = (open(fname, 'r')).read()--#measures = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ measure', str)) ]-other = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ (type|measure|data|include|predicate|decrease|lazy)', str)) ]-qualifs = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ qualif', str)) ]-tyspecs = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ (?!(type|measure|data|include|predicate|qualif|decrease|lazy))', str)) ]--#print measures-#print tyspecs-#print other-#print "Measures :\t\t count = %d \t chars = %d \t lines = %d" %(len(measures), sum(map(lambda x:len(x), measures)), sum(map(lambda x:(1+x.count('\n')), measures)))-print "Type specifications:\t\t count = %d \t lines = %d" %(len(tyspecs), sum(map(lambda x:(1+x.count('\n')), tyspecs)))-print "Qualifiers :\t\t count = %d \t lines = %d" %(len(qualifs), sum(map(lambda x:(1+x.count('\n')), qualifs)))-print "Other Annotations :\t\t count = %d \t lines = %d" %(len(other), sum(map(lambda x:(1+x.count('\n')), other)))---ftyspec = open('_'.join(["tyspec", fname.replace('/','_'), ".txt"]), 'w')-fother = open('_'.join(["other", fname.replace('/','_'), ".txt"]), 'w')--#tmp.write("TYSPECS\n\n")-tyspecsJoined = '\n'.join(tyspecs)-ftyspec.write(tyspecsJoined)--#tmp.write("\n\nOTHER\n\n")-otherJoined = '\n'.join(other)-fother.write(otherJoined)--
@@ -1,14 +0,0 @@-#!/bin/bash--shopt -s globstar--for file in $(ls Data/**/*.hs); do-content=`cat $file`-echo $file-lines= sloccount $file | grep "Total Physical Source"-echo $lines-python count.py $file $lines-#echo "Time = "-#time liquid $file > /dev/null | tail -n1-echo ""-done
@@ -1,6 +0,0 @@--void fps_reverse(unsigned char *dest, unsigned char *from, unsigned long len);-void fps_intersperse(unsigned char *dest, unsigned char *from, unsigned long len, unsigned char c);-unsigned char fps_maximum(unsigned char *p, unsigned long len);-unsigned char fps_minimum(unsigned char *p, unsigned long len);-unsigned long fps_count(unsigned char *p, unsigned long len, unsigned char w);
@@ -1,448 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE Rank2Types #-}-#endif-#if __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Graph--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ A version of the graph algorithms described in:------ /Lazy Depth-First Search and Linear Graph Algorithms in Haskell/,--- by David King and John Launchbury.-----------------------------------------------------------------------------------module Data.Graph(-- -- * External interface-- -- At present the only one with a "nice" external interface- stronglyConnComp, stronglyConnCompR, SCC(..), flattenSCC, flattenSCCs,-- -- * Graphs-- Graph, Table, Bounds, Edge, Vertex,-- -- ** Building graphs-- graphFromEdges, graphFromEdges', buildG, transposeG,- -- reverseE,-- -- ** Graph properties-- vertices, edges,- outdegree, indegree,-- -- * Algorithms-- dfs, dff,- topSort,- components,- scc,- bcc,- -- tree, back, cross, forward,- reachable, path,-- module Data.Tree-- ) where--#if __GLASGOW_HASKELL__-# define USE_ST_MONAD 1-#endif---- Extensions-#if USE_ST_MONAD-import Control.Monad.ST-import Data.Array.ST (STArray, newArray, readArray, writeArray)-#else-import Data.IntSet (IntSet)-import qualified Data.IntSet as Set-#endif-import Data.Tree (Tree(Node), Forest)---- std interfaces-import Control.DeepSeq (NFData(rnf))-import Data.Maybe-import Data.Array-import Data.List------------------------------------------------------------------------------ ---- External interface--- ------------------------------------------------------------------------------- | Strongly connected component.-data SCC vertex = AcyclicSCC vertex -- ^ A single vertex that is not- -- in any cycle.- | CyclicSCC [vertex] -- ^ A maximal set of mutually- -- reachable vertices.--instance NFData a => NFData (SCC a) where- rnf (AcyclicSCC v) = rnf v- rnf (CyclicSCC vs) = rnf vs---- | The vertices of a list of strongly connected components.-flattenSCCs :: [SCC a] -> [a]-flattenSCCs = concatMap flattenSCC---- | The vertices of a strongly connected component.-flattenSCC :: SCC vertex -> [vertex]-flattenSCC (AcyclicSCC v) = [v]-flattenSCC (CyclicSCC vs) = vs---- | The strongly connected components of a directed graph, topologically--- sorted.-stronglyConnComp- :: Ord key- => [(node, key, [key])]- -- ^ The graph: a list of nodes uniquely identified by keys,- -- with a list of keys of nodes this node has edges to.- -- The out-list may contain keys that don't correspond to- -- nodes of the graph; such edges are ignored.- -> [SCC node]--stronglyConnComp edges0- = map get_node (stronglyConnCompR edges0)- where- get_node (AcyclicSCC (n, _, _)) = AcyclicSCC n- get_node (CyclicSCC triples) = CyclicSCC [n | (n,_,_) <- triples]---- | The strongly connected components of a directed graph, topologically--- sorted. The function is the same as 'stronglyConnComp', except that--- all the information about each node retained.--- This interface is used when you expect to apply 'SCC' to--- (some of) the result of 'SCC', so you don't want to lose the--- dependency information.-stronglyConnCompR- :: Ord key- => [(node, key, [key])]- -- ^ The graph: a list of nodes uniquely identified by keys,- -- with a list of keys of nodes this node has edges to.- -- The out-list may contain keys that don't correspond to- -- nodes of the graph; such edges are ignored.- -> [SCC (node, key, [key])] -- ^ Topologically sorted--stronglyConnCompR [] = [] -- added to avoid creating empty array in graphFromEdges -- SOF-stronglyConnCompR edges0- = map decode forest- where- (graph, vertex_fn,_) = graphFromEdges edges0- forest = scc graph- decode (Node v []) | mentions_itself v = CyclicSCC [vertex_fn v]- | otherwise = AcyclicSCC (vertex_fn v)- decode other = CyclicSCC (dec other [])- where- dec (Node v ts) vs = vertex_fn v : foldr dec vs ts- mentions_itself v = v `elem` (graph ! v)------------------------------------------------------------------------------ ---- Graphs--- ------------------------------------------------------------------------------- | Abstract representation of vertices.-type Vertex = Int--- | Table indexed by a contiguous set of vertices.-type Table a = Array Vertex a--- | Adjacency list representation of a graph, mapping each vertex to its--- list of successors.-type Graph = Table [Vertex]--- | The bounds of a 'Table'.-type Bounds = (Vertex, Vertex)--- | An edge from the first vertex to the second.-type Edge = (Vertex, Vertex)---- | All vertices of a graph.-vertices :: Graph -> [Vertex]-vertices = indices---- | All edges of a graph.-edges :: Graph -> [Edge]-edges g = [ (v, w) | v <- vertices g, w <- g!v ]--mapT :: (Vertex -> a -> b) -> Table a -> Table b-mapT f t = array (bounds t) [ (,) v (f v (t!v)) | v <- indices t ]---- | Build a graph from a list of edges.-buildG :: Bounds -> [Edge] -> Graph-buildG bounds0 edges0 = accumArray (flip (:)) [] bounds0 edges0---- | The graph obtained by reversing all edges.-transposeG :: Graph -> Graph-transposeG g = buildG (bounds g) (reverseE g)--reverseE :: Graph -> [Edge]-reverseE g = [ (w, v) | (v, w) <- edges g ]---- | A table of the count of edges from each node.-outdegree :: Graph -> Table Int-outdegree = mapT numEdges- where numEdges _ ws = length ws---- | A table of the count of edges into each node.-indegree :: Graph -> Table Int-indegree = outdegree . transposeG---- | Identical to 'graphFromEdges', except that the return value--- does not include the function which maps keys to vertices. This--- version of 'graphFromEdges' is for backwards compatibility.-graphFromEdges'- :: Ord key- => [(node, key, [key])]- -> (Graph, Vertex -> (node, key, [key]))-graphFromEdges' x = (a,b) where- (a,b,_) = graphFromEdges x---- | Build a graph from a list of nodes uniquely identified by keys,--- with a list of keys of nodes this node should have edges to.--- The out-list may contain keys that don't correspond to--- nodes of the graph; they are ignored.-graphFromEdges- :: Ord key- => [(node, key, [key])]- -> (Graph, Vertex -> (node, key, [key]), key -> Maybe Vertex)-graphFromEdges edges0- = (graph, \v -> vertex_map ! v, key_vertex)- where- max_v = length edges0 - 1- bounds0 = (0,max_v) :: (Vertex, Vertex)- sorted_edges = sortBy lt edges0- edges1 = zipWith (,) [0..] sorted_edges-- graph = array bounds0 [(,) v (mapMaybe key_vertex ks) | (,) v (_, _, ks) <- edges1]- key_map = array bounds0 [(,) v k | (,) v (_, k, _ ) <- edges1]- vertex_map = array bounds0 edges1-- (_,k1,_) `lt` (_,k2,_) = k1 `compare` k2-- -- key_vertex :: key -> Maybe Vertex- -- returns Nothing for non-interesting vertices- key_vertex k = findVertex 0 max_v- where- findVertex a b | a > b- = Nothing- findVertex a b = case compare k (key_map ! mid) of- LT -> findVertex a (mid-1)- EQ -> Just mid- GT -> findVertex (mid+1) b- where- mid = (a + b) `div` 2------------------------------------------------------------------------------ ---- Depth first search--- ------------------------------------------------------------------------------- | A spanning forest of the graph, obtained from a depth-first search of--- the graph starting from each vertex in an unspecified order.-dff :: Graph -> Forest Vertex-dff g = dfs g (vertices g)---- | A spanning forest of the part of the graph reachable from the listed--- vertices, obtained from a depth-first search of the graph starting at--- each of the listed vertices in order.-dfs :: Graph -> [Vertex] -> Forest Vertex-dfs g vs = prune (bounds g) (map (generate g) vs)--generate :: Graph -> Vertex -> Tree Vertex-generate g v = Node v (map (generate g) (g!v))--prune :: Bounds -> Forest Vertex -> Forest Vertex-prune bnds ts = run bnds (chop ts)--chop :: Forest Vertex -> SetM s (Forest Vertex)-chop [] = return []-chop (Node v ts : us)- = do- visited <- contains v- if visited then- chop us- else do- include v- as <- chop ts- bs <- chop us- return (Node v as : bs)---- A monad holding a set of vertices visited so far.-#if USE_ST_MONAD---- Use the ST monad if available, for constant-time primitives.--newtype SetM s a = SetM { runSetM :: STArray s Vertex Bool -> ST s a }--instance Monad (SetM s) where- return x = SetM $ const (return x)- SetM v >>= f = SetM $ \ s -> do { x <- v s; runSetM (f x) s }--run :: Bounds -> (forall s. SetM s a) -> a-run bnds act = runST (newArray bnds False >>= runSetM act)--contains :: Vertex -> SetM s Bool-contains v = SetM $ \ m -> readArray m v--include :: Vertex -> SetM s ()-include v = SetM $ \ m -> writeArray m v True--#else /* !USE_ST_MONAD */---- Portable implementation using IntSet.--newtype SetM s a = SetM { runSetM :: IntSet -> (a, IntSet) }--instance Monad (SetM s) where- return x = SetM $ \ s -> (x, s)- SetM v >>= f = SetM $ \ s -> case v s of (x, s') -> runSetM (f x) s'--run :: Bounds -> SetM s a -> a-run _ act = fst (runSetM act Set.empty)--contains :: Vertex -> SetM s Bool-contains v = SetM $ \ m -> (Set.member v m, m)--include :: Vertex -> SetM s ()-include v = SetM $ \ m -> ((), Set.insert v m)--#endif /* !USE_ST_MONAD */------------------------------------------------------------------------------ ---- Algorithms--- -------------------------------------------------------------------------------------------------------------------------------------------- Algorithm 1: depth first search numbering---------------------------------------------------------------preorder' :: Tree a -> [a] -> [a]-preorder' (Node a ts) = (a :) . preorderF' ts--preorderF' :: Forest a -> [a] -> [a]-preorderF' ts = foldr (.) id $ map preorder' ts--preorderF :: Forest a -> [a]-preorderF ts = preorderF' ts []--tabulate :: Bounds -> [Vertex] -> Table Int-tabulate bnds vs = array bnds (zipWith (,) vs [1..])--preArr :: Bounds -> Forest Vertex -> Table Int-preArr bnds = tabulate bnds . preorderF----------------------------------------------------------------- Algorithm 2: topological sorting---------------------------------------------------------------postorder :: Tree a -> [a] -> [a]-postorder (Node a ts) = postorderF ts . (a :)--postorderF :: Forest a -> [a] -> [a]-postorderF ts = foldr (.) id $ map postorder ts--postOrd :: Graph -> [Vertex]-postOrd g = postorderF (dff g) []---- | A topological sort of the graph.--- The order is partially specified by the condition that a vertex /i/--- precedes /j/ whenever /j/ is reachable from /i/ but not vice versa.-topSort :: Graph -> [Vertex]-topSort = reverse . postOrd----------------------------------------------------------------- Algorithm 3: connected components----------------------------------------------------------------- | The connected components of a graph.--- Two vertices are connected if there is a path between them, traversing--- edges in either direction.-components :: Graph -> Forest Vertex-components = dff . undirected--undirected :: Graph -> Graph-undirected g = buildG (bounds g) (edges g ++ reverseE g)---- Algorithm 4: strongly connected components---- | The strongly connected components of a graph.-scc :: Graph -> Forest Vertex-scc g = dfs g (reverse (postOrd (transposeG g)))----------------------------------------------------------------- Algorithm 5: Classifying edges---------------------------------------------------------------{--XXX unused code--tree :: Bounds -> Forest Vertex -> Graph-tree bnds ts = buildG bnds (concat (map flat ts))- where flat (Node v ts') = [ (v, w) | Node w _us <- ts' ]- ++ concat (map flat ts')--back :: Graph -> Table Int -> Graph-back g post = mapT select g- where select v ws = [ w | w <- ws, post!v < post!w ]--cross :: Graph -> Table Int -> Table Int -> Graph-cross g pre post = mapT select g- where select v ws = [ w | w <- ws, post!v > post!w, pre!v > pre!w ]--forward :: Graph -> Graph -> Table Int -> Graph-forward g tree' pre = mapT select g- where select v ws = [ w | w <- ws, pre!v < pre!w ] \\ tree' ! v--}----------------------------------------------------------------- Algorithm 6: Finding reachable vertices----------------------------------------------------------------- | A list of vertices reachable from a given vertex.-reachable :: Graph -> Vertex -> [Vertex]-reachable g v = preorderF (dfs g [v])---- | Is the second vertex reachable from the first?-path :: Graph -> Vertex -> Vertex -> Bool-path g v w = w `elem` (reachable g v)----------------------------------------------------------------- Algorithm 7: Biconnected components----------------------------------------------------------------- | The biconnected components of a graph.--- An undirected graph is biconnected if the deletion of any vertex--- leaves it connected.-bcc :: Graph -> Forest [Vertex]-bcc g = (concat . map bicomps . map (do_label g dnum)) forest- where forest = dff g- dnum = preArr (bounds g) forest--do_label :: Graph -> Table Int -> Tree Vertex -> Tree (Vertex,Int,Int)-do_label g dnum (Node v ts) = Node (v,dnum!v,lv) us- where us = map (do_label g dnum) ts- lv = minimum ([dnum!v] ++ [dnum!w | w <- g!v]- ++ [lu | Node (_,_,lu) _ <- us])--bicomps :: Tree (Vertex,Int,Int) -> Forest [Vertex]-bicomps (Node (v,_,_) ts)- = [ Node (v:vs) us | (_,Node vs us) <- map collect ts]--collect :: Tree (Vertex,Int,Int) -> (Int, Tree [Vertex])-collect (Node (v,dv,lv) ts) = (lv, Node (v:vs) cs)- where collected = map collect ts- vs = concat [ ws | (lw, Node ws _) <- collected, lw<dv]- cs = concat [ if lw<dv then us else [Node (v:ws) us]- | (lw, Node ws us) <- collected ]
@@ -1,95 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.IntMap--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from integer keys to values--- (dictionaries).------ This module re-exports the value lazy 'Data.IntMap.Lazy' API, plus--- several value strict functions from 'Data.IntMap.Strict'.------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.IntMap (IntMap)--- > import qualified Data.IntMap as IntMap------ The implementation is based on /big-endian patricia trees/. This data--- structure performs especially well on binary operations like 'union'--- and 'intersection'. However, my benchmarks show that it is also--- (much) faster on insertions and deletions when compared to a generic--- size-balanced map implementation (see "Data.Map").------ * Chris Okasaki and Andy Gill, \"/Fast Mergeable Integer Maps/\",--- Workshop on ML, September 1998, pages 77-86,--- <http://citeseer.ist.psu.edu/okasaki98fast.html>------ * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve--- Information Coded In Alphanumeric/\", Journal of the ACM, 15(4),--- October 1968, pages 514-534.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.--- Many operations have a worst-case complexity of /O(min(n,W))/.--- This means that the operation can become linear in the number of--- elements with a maximum of /W/ -- the number of bits in an 'Int'--- (32 or 64).--------------------------------------------------------------------------------module Data.IntMap- ( module Data.IntMap.Lazy- , insertWith'- , insertWithKey'- , fold- , foldWithKey- ) where--import Prelude hiding (lookup,map,filter,foldr,foldl,null)-import Data.IntMap.Lazy-import qualified Data.IntMap.Strict as S---- | /Deprecated./ As of version 0.5, replaced by 'S.insertWith'.------ /O(log n)/. Same as 'insertWith', but the combining function is--- applied strictly. This function is deprecated, use 'insertWith' in--- "Data.IntMap.Strict" instead.-insertWith' :: (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a-insertWith' = S.insertWith-{-# INLINE insertWith' #-}---- | /Deprecated./ As of version 0.5, replaced by 'S.insertWithKey'.------ /O(log n)/. Same as 'insertWithKey', but the combining function is--- applied strictly. This function is deprecated, use 'insertWithKey'--- in "Data.IntMap.Strict" instead.-insertWithKey' :: (Key -> a -> a -> a) -> Key -> a -> IntMap a -> IntMap a-insertWithKey' = S.insertWithKey-{-# INLINE insertWithKey' #-}---- | /Deprecated./ As of version 0.5, replaced by 'foldr'.------ /O(n)/. Fold the values in the map using the given--- right-associative binary operator. This function is an equivalent--- of 'foldr' and is present for compatibility only.-fold :: (a -> b -> b) -> b -> IntMap a -> b-fold = foldr-{-# INLINE fold #-}---- | /Deprecated./ As of version 0.5, replaced by 'foldrWithKey'.------ /O(n)/. Fold the keys and values in the map using the given--- right-associative binary operator. This function is an equivalent--- of 'foldrWithKey' and is present for compatibility only.-foldWithKey :: (Int -> a -> b -> b) -> b -> IntMap a -> b-foldWithKey = foldrWithKey-{-# INLINE foldWithKey #-}
@@ -1,2171 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE MagicHash, DeriveDataTypeable, StandaloneDeriving #-}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.IntMap.Base--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ This defines the data structures and core (hidden) manipulations--- on representations.---------------------------------------------------------------------------------- [Note: INLINE bit fiddling]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~--- It is essential that the bit fiddling functions like mask, zero, branchMask--- etc are inlined. If they do not, the memory allocation skyrockets. The GHC--- usually gets it right, but it is disastrous if it does not. Therefore we--- explicitly mark these functions INLINE.----- [Note: Local 'go' functions and capturing]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- Care must be taken when using 'go' function which captures an argument.--- Sometimes (for example when the argument is passed to a data constructor,--- as in insert), GHC heap-allocates more than necessary. Therefore C-- code--- must be checked for increased allocation when creating and modifying such--- functions.----- [Note: Order of constructors]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- The order of constructors of IntMap matters when considering performance.--- Currently in GHC 7.0, when type has 3 constructors, they are matched from--- the first to the last -- the best performance is achieved when the--- constructors are ordered by frequency.--- On GHC 7.0, reordering constructors from Nil | Tip | Bin to Bin | Tip | Nil--- improves the benchmark by circa 10%.--module Data.IntMap.Base (- -- * Map type- IntMap(..), Key -- instance Eq,Show-- -- * Operators- , (!), (\\)-- -- * Query- , null- , size- , member- , notMember- , lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey- , mergeWithKey'-- -- * Traversal- -- ** Map- , map- , mapWithKey- , traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , foldr- , foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- , keysSet- , fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith-- -- * Internal types- , Mask, Prefix, Nat-- -- * Utility- , natFromInt- , intFromNat- , shiftRL- , shiftLL- , join- , bin- , zero- , nomatch- , match- , mask- , maskW- , shorter- , branchMask- , highestBitMask- , foldlStrict- ) where--import Data.Bits--import Prelude hiding (lookup,map,filter,foldr,foldl,null)-import qualified Data.IntSet.Base as IntSet-import Data.Monoid (Monoid(..))-import Data.Maybe (fromMaybe)-import Data.Typeable-import qualified Data.Foldable as Foldable-import Data.Traversable (Traversable(traverse))-import Control.Applicative (Applicative(pure,(<*>)),(<$>))-import Control.Monad ( liftM )-import Control.DeepSeq (NFData(rnf))--#if __GLASGOW_HASKELL__-import Text.Read-import Data.Data (Data(..), mkNoRepType)-#endif--#if __GLASGOW_HASKELL__-import GHC.Exts ( Word(..), Int(..), build )-import GHC.Prim ( uncheckedShiftL#, uncheckedShiftRL# )-#else-import Data.Word-#endif---- On GHC, include MachDeps.h to get WORD_SIZE_IN_BITS macro.-#if defined(__GLASGOW_HASKELL__)-#include "MachDeps.h"-#endif---- Use macros to define strictness of functions.--- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.--- We do not use BangPatterns, because they are not in any standard and we--- want the compilers to be compiled by as many compilers as possible.-#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined---- A "Nat" is a natural machine word (an unsigned Int)-type Nat = Word--natFromInt :: Key -> Nat-natFromInt = fromIntegral-{-# INLINE natFromInt #-}--intFromNat :: Nat -> Key-intFromNat = fromIntegral-{-# INLINE intFromNat #-}---- Right and left logical shifts.-shiftRL, shiftLL :: Nat -> Key -> Nat-#if __GLASGOW_HASKELL__-{--------------------------------------------------------------------- GHC: use unboxing to get @shiftRL@ inlined.---------------------------------------------------------------------}-shiftRL (W# x) (I# i) = W# (uncheckedShiftRL# x i)-shiftLL (W# x) (I# i) = W# (uncheckedShiftL# x i)-#else-shiftRL x i = shiftR x i-shiftLL x i = shiftL x i-#endif-{-# INLINE shiftRL #-}-{-# INLINE shiftLL #-}--{--------------------------------------------------------------------- Types---------------------------------------------------------------------}----- | A map of integers to values @a@.---- See Note: Order of constructors-data IntMap a = Bin {-# UNPACK #-} !Prefix {-# UNPACK #-} !Mask !(IntMap a) !(IntMap a)- | Tip {-# UNPACK #-} !Key a- | Nil--type Prefix = Int-type Mask = Int-type Key = Int--{--------------------------------------------------------------------- Operators---------------------------------------------------------------------}---- | /O(min(n,W))/. Find the value at a key.--- Calls 'error' when the element can not be found.------ > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map--- > fromList [(5,'a'), (3,'b')] ! 5 == 'a'--(!) :: IntMap a -> Key -> a-m ! k = find k m---- | Same as 'difference'.-(\\) :: IntMap a -> IntMap b -> IntMap a-m1 \\ m2 = difference m1 m2--infixl 9 \\{-This comment teaches CPP correct behaviour -}--{--------------------------------------------------------------------- Types---------------------------------------------------------------------}--instance Monoid (IntMap a) where- mempty = empty- mappend = union- mconcat = unions--instance Foldable.Foldable IntMap where- fold Nil = mempty- fold (Tip _ v) = v- fold (Bin _ _ l r) = Foldable.fold l `mappend` Foldable.fold r- foldr = foldr- foldl = foldl- foldMap _ Nil = mempty- foldMap f (Tip _k v) = f v- foldMap f (Bin _ _ l r) = Foldable.foldMap f l `mappend` Foldable.foldMap f r--instance Traversable IntMap where- traverse f = traverseWithKey (\_ -> f)--instance NFData a => NFData (IntMap a) where- rnf Nil = ()- rnf (Tip _ v) = rnf v- rnf (Bin _ _ l r) = rnf l `seq` rnf r--#if __GLASGOW_HASKELL__--{--------------------------------------------------------------------- A Data instance---------------------------------------------------------------------}---- This instance preserves data abstraction at the cost of inefficiency.--- We omit reflection services for the sake of data abstraction.--instance Data a => Data (IntMap a) where- gfoldl f z im = z fromList `f` (toList im)- toConstr _ = error "toConstr"- gunfold _ _ = error "gunfold"- dataTypeOf _ = mkNoRepType "Data.IntMap.IntMap"- dataCast1 f = gcast1 f--#endif--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}--- | /O(1)/. Is the map empty?------ > Data.IntMap.null (empty) == True--- > Data.IntMap.null (singleton 1 'a') == False--null :: IntMap a -> Bool-null Nil = True-null _ = False-{-# INLINE null #-}---- | /O(n)/. Number of elements in the map.------ > size empty == 0--- > size (singleton 1 'a') == 1--- > size (fromList([(1,'a'), (2,'c'), (3,'b')])) == 3-size :: IntMap a -> Int-size t- = case t of- Bin _ _ l r -> size l + size r- Tip _ _ -> 1- Nil -> 0---- | /O(min(n,W))/. Is the key a member of the map?------ > member 5 (fromList [(5,'a'), (3,'b')]) == True--- > member 1 (fromList [(5,'a'), (3,'b')]) == False---- See Note: Local 'go' functions and capturing]-member :: Key -> IntMap a -> Bool-member k = k `seq` go- where- go (Bin p m l r) | nomatch k p m = False- | zero k m = go l- | otherwise = go r- go (Tip kx _) = k == kx- go Nil = False---- | /O(min(n,W))/. Is the key not a member of the map?------ > notMember 5 (fromList [(5,'a'), (3,'b')]) == False--- > notMember 1 (fromList [(5,'a'), (3,'b')]) == True--notMember :: Key -> IntMap a -> Bool-notMember k m = not $ member k m---- | /O(min(n,W))/. Lookup the value at a key in the map. See also 'Data.Map.lookup'.---- See Note: Local 'go' functions and capturing]-lookup :: Key -> IntMap a -> Maybe a-lookup k = k `seq` go- where- go (Bin p m l r) | nomatch k p m = Nothing- | zero k m = go l- | otherwise = go r- go (Tip kx x) | k == kx = Just x- | otherwise = Nothing- go Nil = Nothing----- See Note: Local 'go' functions and capturing]-find :: Key -> IntMap a -> a-find k = k `seq` go- where- go (Bin p m l r) | nomatch k p m = not_found- | zero k m = go l- | otherwise = go r- go (Tip kx x) | k == kx = x- | otherwise = not_found- go Nil = not_found-- not_found = error ("IntMap.!: key " ++ show k ++ " is not an element of the map")---- | /O(min(n,W))/. The expression @('findWithDefault' def k map)@--- returns the value at key @k@ or returns @def@ when the key is not an--- element of the map.------ > findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) == 'x'--- > findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) == 'a'---- See Note: Local 'go' functions and capturing]-findWithDefault :: a -> Key -> IntMap a -> a-findWithDefault def k = k `seq` go- where- go (Bin p m l r) | nomatch k p m = def- | zero k m = go l- | otherwise = go r- go (Tip kx x) | k == kx = x- | otherwise = def- go Nil = def---- | /O(log n)/. Find largest key smaller than the given one and return the--- corresponding (key, value) pair.------ > lookupLT 3 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLT 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')---- See Note: Local 'go' functions and capturing.-lookupLT :: Key -> IntMap a -> Maybe (Key, a)-lookupLT k t = k `seq` case t of- Bin _ m l r | m < 0 -> if k >= 0 then go r l else go Nil r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch k p m = if k < p then unsafeFindMax def else unsafeFindMax r- | zero k m = go def l- | otherwise = go l r- go def (Tip ky y) | k <= ky = unsafeFindMax def- | otherwise = Just (ky, y)- go def Nil = unsafeFindMax def---- | /O(log n)/. Find smallest key greater than the given one and return the--- corresponding (key, value) pair.------ > lookupGT 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGT 5 (fromList [(3,'a'), (5,'b')]) == Nothing---- See Note: Local 'go' functions and capturing.-lookupGT :: Key -> IntMap a -> Maybe (Key, a)-lookupGT k t = k `seq` case t of- Bin _ m l r | m < 0 -> if k >= 0 then go Nil l else go l r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch k p m = if k < p then unsafeFindMin l else unsafeFindMin def- | zero k m = go r l- | otherwise = go def r- go def (Tip ky y) | k >= ky = unsafeFindMin def- | otherwise = Just (ky, y)- go def Nil = unsafeFindMin def---- | /O(log n)/. Find largest key smaller or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupLE 2 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLE 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupLE 5 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')---- See Note: Local 'go' functions and capturing.-lookupLE :: Key -> IntMap a -> Maybe (Key, a)-lookupLE k t = k `seq` case t of- Bin _ m l r | m < 0 -> if k >= 0 then go r l else go Nil r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch k p m = if k < p then unsafeFindMax def else unsafeFindMax r- | zero k m = go def l- | otherwise = go l r- go def (Tip ky y) | k < ky = unsafeFindMax def- | otherwise = Just (ky, y)- go def Nil = unsafeFindMax def---- | /O(log n)/. Find smallest key greater or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupGE 3 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupGE 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGE 6 (fromList [(3,'a'), (5,'b')]) == Nothing---- See Note: Local 'go' functions and capturing.-lookupGE :: Key -> IntMap a -> Maybe (Key, a)-lookupGE k t = k `seq` case t of- Bin _ m l r | m < 0 -> if k >= 0 then go Nil l else go l r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch k p m = if k < p then unsafeFindMin l else unsafeFindMin def- | zero k m = go r l- | otherwise = go def r- go def (Tip ky y) | k > ky = unsafeFindMin def- | otherwise = Just (ky, y)- go def Nil = unsafeFindMin def----- Helper function for lookupGE and lookupGT. It assumes that if a Bin node is--- given, it has m > 0.-unsafeFindMin :: IntMap a -> Maybe (Key, a)-unsafeFindMin Nil = Nothing-unsafeFindMin (Tip ky y) = Just (ky, y)-unsafeFindMin (Bin _ _ l _) = unsafeFindMin l---- Helper function for lookupLE and lookupLT. It assumes that if a Bin node is--- given, it has m > 0.-unsafeFindMax :: IntMap a -> Maybe (Key, a)-unsafeFindMax Nil = Nothing-unsafeFindMax (Tip ky y) = Just (ky, y)-unsafeFindMax (Bin _ _ _ r) = unsafeFindMax r--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. The empty map.------ > empty == fromList []--- > size empty == 0--empty :: IntMap a-empty- = Nil-{-# INLINE empty #-}---- | /O(1)/. A map of one element.------ > singleton 1 'a' == fromList [(1, 'a')]--- > size (singleton 1 'a') == 1--singleton :: Key -> a -> IntMap a-singleton k x- = Tip k x-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insert---------------------------------------------------------------------}--- | /O(min(n,W))/. Insert a new key\/value pair in the map.--- If the key is already present in the map, the associated value is--- replaced with the supplied value, i.e. 'insert' is equivalent to--- @'insertWith' 'const'@.------ > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]--- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]--- > insert 5 'x' empty == singleton 5 'x'--insert :: Key -> a -> IntMap a -> IntMap a-insert k x t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> join k (Tip k x) p t- | zero k m -> Bin p m (insert k x l) r- | otherwise -> Bin p m l (insert k x r)- Tip ky _- | k==ky -> Tip k x- | otherwise -> join k (Tip k x) ky t- Nil -> Tip k x---- right-biased insertion, used by 'union'--- | /O(min(n,W))/. Insert with a combining function.--- @'insertWith' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert @f new_value old_value@.------ > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]--- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"--insertWith :: (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a-insertWith f k x t- = insertWithKey (\_ x' y' -> f x' y') k x t---- | /O(min(n,W))/. Insert with a combining function.--- @'insertWithKey' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert @f key new_value old_value@.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]--- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"--insertWithKey :: (Key -> a -> a -> a) -> Key -> a -> IntMap a -> IntMap a-insertWithKey f k x t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> join k (Tip k x) p t- | zero k m -> Bin p m (insertWithKey f k x l) r- | otherwise -> Bin p m l (insertWithKey f k x r)- Tip ky y- | k==ky -> Tip k (f k x y)- | otherwise -> join k (Tip k x) ky t- Nil -> Tip k x---- | /O(min(n,W))/. The expression (@'insertLookupWithKey' f k x map@)--- is a pair where the first element is equal to (@'lookup' k map@)--- and the second element equal to (@'insertWithKey' f k x map@).------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])--- > insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])--- > insertLookupWithKey f 5 "xxx" empty == (Nothing, singleton 5 "xxx")------ This is how to define @insertLookup@ using @insertLookupWithKey@:------ > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t--- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])--- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])--insertLookupWithKey :: (Key -> a -> a -> a) -> Key -> a -> IntMap a -> (Maybe a, IntMap a)-insertLookupWithKey f k x t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> (Nothing,join k (Tip k x) p t)- | zero k m -> let (found,l') = insertLookupWithKey f k x l in (found,Bin p m l' r)- | otherwise -> let (found,r') = insertLookupWithKey f k x r in (found,Bin p m l r')- Tip ky y- | k==ky -> (Just y,Tip k (f k x y))- | otherwise -> (Nothing,join k (Tip k x) ky t)- Nil -> (Nothing,Tip k x)---{--------------------------------------------------------------------- Deletion---------------------------------------------------------------------}--- | /O(min(n,W))/. Delete a key and its value from the map. When the key is not--- a member of the map, the original map is returned.------ > delete 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > delete 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > delete 5 empty == empty--delete :: Key -> IntMap a -> IntMap a-delete k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> t- | zero k m -> bin p m (delete k l) r- | otherwise -> bin p m l (delete k r)- Tip ky _- | k==ky -> Nil- | otherwise -> t- Nil -> Nil---- | /O(min(n,W))/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjust ("new " ++) 7 empty == empty--adjust :: (a -> a) -> Key -> IntMap a -> IntMap a-adjust f k m- = adjustWithKey (\_ x -> f x) k m---- | /O(min(n,W))/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > let f key x = (show key) ++ ":new " ++ x--- > adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjustWithKey f 7 empty == empty--adjustWithKey :: (Key -> a -> a) -> Key -> IntMap a -> IntMap a-adjustWithKey f- = updateWithKey (\k' x -> Just (f k' x))---- | /O(min(n,W))/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f x = if x == "a" then Just "new a" else Nothing--- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--update :: (a -> Maybe a) -> Key -> IntMap a -> IntMap a-update f- = updateWithKey (\_ x -> f x)---- | /O(min(n,W))/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f k x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateWithKey :: (Key -> a -> Maybe a) -> Key -> IntMap a -> IntMap a-updateWithKey f k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> t- | zero k m -> bin p m (updateWithKey f k l) r- | otherwise -> bin p m l (updateWithKey f k r)- Tip ky y- | k==ky -> case (f k y) of- Just y' -> Tip ky y'- Nothing -> Nil- | otherwise -> t- Nil -> Nil---- | /O(min(n,W))/. Lookup and update.--- The function returns original value, if it is updated.--- This is different behavior than 'Data.Map.updateLookupWithKey'.--- Returns the original key value if the map entry is deleted.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:new a")])--- > updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a")])--- > updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) == (Just "b", singleton 5 "a")--updateLookupWithKey :: (Key -> a -> Maybe a) -> Key -> IntMap a -> (Maybe a,IntMap a)-updateLookupWithKey f k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> (Nothing,t)- | zero k m -> let (found,l') = updateLookupWithKey f k l in (found,bin p m l' r)- | otherwise -> let (found,r') = updateLookupWithKey f k r in (found,bin p m l r')- Tip ky y- | k==ky -> case (f k y) of- Just y' -> (Just y,Tip ky y')- Nothing -> (Just y,Nil)- | otherwise -> (Nothing,t)- Nil -> (Nothing,Nil)------ | /O(min(n,W))/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.--- 'alter' can be used to insert, delete, or update a value in an 'IntMap'.--- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.-alter :: (Maybe a -> Maybe a) -> Key -> IntMap a -> IntMap a-alter f k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> case f Nothing of- Nothing -> t- Just x -> join k (Tip k x) p t- | zero k m -> bin p m (alter f k l) r- | otherwise -> bin p m l (alter f k r)- Tip ky y- | k==ky -> case f (Just y) of- Just x -> Tip ky x- Nothing -> Nil- | otherwise -> case f Nothing of- Just x -> join k (Tip k x) ky t- Nothing -> Tip ky y- Nil -> case f Nothing of- Just x -> Tip k x- Nothing -> Nil---{--------------------------------------------------------------------- Union---------------------------------------------------------------------}--- | The union of a list of maps.------ > unions [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "b"), (5, "a"), (7, "C")]--- > unions [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]--- > == fromList [(3, "B3"), (5, "A3"), (7, "C")]--unions :: [IntMap a] -> IntMap a-unions xs- = foldlStrict union empty xs---- | The union of a list of maps, with a combining operation.------ > unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--unionsWith :: (a->a->a) -> [IntMap a] -> IntMap a-unionsWith f ts- = foldlStrict (unionWith f) empty ts---- | /O(n+m)/. The (left-biased) union of two maps.--- It prefers the first map when duplicate keys are encountered,--- i.e. (@'union' == 'unionWith' 'const'@).------ > union (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "a"), (7, "C")]--union :: IntMap a -> IntMap a -> IntMap a-union m1 m2- = mergeWithKey' Bin const id id m1 m2---- | /O(n+m)/. The union with a combining function.------ > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]--unionWith :: (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a-unionWith f m1 m2- = unionWithKey (\_ x y -> f x y) m1 m2---- | /O(n+m)/. The union with a combining function.------ > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]--unionWithKey :: (Key -> a -> a -> a) -> IntMap a -> IntMap a -> IntMap a-unionWithKey f m1 m2- = mergeWithKey' Bin (\(Tip k1 x1) (Tip _k2 x2) -> Tip k1 (f k1 x1 x2)) id id m1 m2--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}--- | /O(n+m)/. Difference between two maps (based on keys).------ > difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 3 "b"--difference :: IntMap a -> IntMap b -> IntMap a-difference m1 m2- = mergeWithKey (\_ _ _ -> Nothing) id (const Nil) m1 m2---- | /O(n+m)/. Difference with a combining function.------ > let f al ar = if al == "b" then Just (al ++ ":" ++ ar) else Nothing--- > differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])--- > == singleton 3 "b:B"--differenceWith :: (a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a-differenceWith f m1 m2- = differenceWithKey (\_ x y -> f x y) m1 m2---- | /O(n+m)/. Difference with a combining function. When two equal keys are--- encountered, the combining function is applied to the key and both values.--- If it returns 'Nothing', the element is discarded (proper set difference).--- If it returns (@'Just' y@), the element is updated with a new value @y@.------ > let f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--- > differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])--- > == singleton 3 "3:b|B"--differenceWithKey :: (Key -> a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a-differenceWithKey f m1 m2- = mergeWithKey f id (const Nil) m1 m2---{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}--- | /O(n+m)/. The (left-biased) intersection of two maps (based on keys).------ > intersection (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "a"--intersection :: IntMap a -> IntMap b -> IntMap a-intersection m1 m2- = mergeWithKey' bin const (const Nil) (const Nil) m1 m2---- | /O(n+m)/. The intersection with a combining function.------ > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"--intersectionWith :: (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c-intersectionWith f m1 m2- = intersectionWithKey (\_ x y -> f x y) m1 m2---- | /O(n+m)/. The intersection with a combining function.------ > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"--intersectionWithKey :: (Key -> a -> b -> c) -> IntMap a -> IntMap b -> IntMap c-intersectionWithKey f m1 m2- = mergeWithKey' bin (\(Tip k1 x1) (Tip _k2 x2) -> Tip k1 (f k1 x1 x2)) (const Nil) (const Nil) m1 m2--{--------------------------------------------------------------------- MergeWithKey---------------------------------------------------------------------}---- | /O(n+m)/. A high-performance universal combining function. Using--- 'mergeWithKey', all combining functions can be defined without any loss of--- efficiency (with exception of 'union', 'difference' and 'intersection',--- where sharing of some nodes is lost with 'mergeWithKey').------ Please make sure you know what is going on when using 'mergeWithKey',--- otherwise you can be surprised by unexpected code growth or even--- corruption of the data structure.------ When 'mergeWithKey' is given three arguments, it is inlined to the call--- site. You should therefore use 'mergeWithKey' only to define your custom--- combining functions. For example, you could define 'unionWithKey',--- 'differenceWithKey' and 'intersectionWithKey' as------ > myUnionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) id id m1 m2--- > myDifferenceWithKey f m1 m2 = mergeWithKey f id (const empty) m1 m2--- > myIntersectionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) (const empty) (const empty) m1 m2------ When calling @'mergeWithKey' combine only1 only2@, a function combining two--- 'IntMap's is created, such that------ * if a key is present in both maps, it is passed with both corresponding--- values to the @combine@ function. Depending on the result, the key is either--- present in the result with specified value, or is left out;------ * a nonempty subtree present only in the first map is passed to @only1@ and--- the output is added to the result;------ * a nonempty subtree present only in the second map is passed to @only2@ and--- the output is added to the result.------ The @only1@ and @only2@ methods /must return a map with a subset (possibly empty) of the keys of the given map/.--- The values can be modified arbitrarily. Most common variants of @only1@ and--- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@ or--- @'filterWithKey' f@ could be used for any @f@.--mergeWithKey :: (Key -> a -> b -> Maybe c) -> (IntMap a -> IntMap c) -> (IntMap b -> IntMap c)- -> IntMap a -> IntMap b -> IntMap c-mergeWithKey f g1 g2 = mergeWithKey' bin combine g1 g2- where -- We use the lambda form to avoid non-exhaustive pattern matches warning.- combine = \(Tip k1 x1) (Tip _k2 x2) -> case f k1 x1 x2 of Nothing -> Nil- Just x -> Tip k1 x- {-# INLINE combine #-}-{-# INLINE mergeWithKey #-}---- Slightly more general version of mergeWithKey. It differs in the following:------ * the combining function operates on maps instead of keys and values. The--- reason is to enable sharing in union, difference and intersection.------ * mergeWithKey' is given an equivalent of bin. The reason is that in union*,--- Bin constructor can be used, because we know both subtrees are nonempty.--mergeWithKey' :: (Prefix -> Mask -> IntMap c -> IntMap c -> IntMap c)- -> (IntMap a -> IntMap b -> IntMap c) -> (IntMap a -> IntMap c) -> (IntMap b -> IntMap c)- -> IntMap a -> IntMap b -> IntMap c-mergeWithKey' bin' f g1 g2 = go- where- go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)- | shorter m1 m2 = merge1- | shorter m2 m1 = merge2- | p1 == p2 = bin' p1 m1 (go l1 l2) (go r1 r2)- | otherwise = maybe_join p1 (g1 t1) p2 (g2 t2)- where- merge1 | nomatch p2 p1 m1 = maybe_join p1 (g1 t1) p2 (g2 t2)- | zero p2 m1 = bin' p1 m1 (go l1 t2) (g1 r1)- | otherwise = bin' p1 m1 (g1 l1) (go r1 t2)- merge2 | nomatch p1 p2 m2 = maybe_join p1 (g1 t1) p2 (g2 t2)- | zero p1 m2 = bin' p2 m2 (go t1 l2) (g2 r2)- | otherwise = bin' p2 m2 (g2 l2) (go t1 r2)-- go t1'@(Bin _ _ _ _) t2'@(Tip k2' _) = merge t2' k2' t1'- where merge t2 k2 t1@(Bin p1 m1 l1 r1) | nomatch k2 p1 m1 = maybe_join p1 (g1 t1) k2 (g2 t2)- | zero k2 m1 = bin' p1 m1 (merge t2 k2 l1) (g1 r1)- | otherwise = bin' p1 m1 (g1 l1) (merge t2 k2 r1)- merge t2 k2 t1@(Tip k1 _) | k1 == k2 = f t1 t2- | otherwise = maybe_join k1 (g1 t1) k2 (g2 t2)- merge t2 _ Nil = g2 t2-- go t1@(Bin _ _ _ _) Nil = g1 t1-- go t1'@(Tip k1' _) t2' = merge t1' k1' t2'- where merge t1 k1 t2@(Bin p2 m2 l2 r2) | nomatch k1 p2 m2 = maybe_join k1 (g1 t1) p2 (g2 t2)- | zero k1 m2 = bin' p2 m2 (merge t1 k1 l2) (g2 r2)- | otherwise = bin' p2 m2 (g2 l2) (merge t1 k1 r2)- merge t1 k1 t2@(Tip k2 _) | k1 == k2 = f t1 t2- | otherwise = maybe_join k1 (g1 t1) k2 (g2 t2)- merge t1 _ Nil = g1 t1-- go Nil t2 = g2 t2-- maybe_join _ Nil _ t2 = t2- maybe_join _ t1 _ Nil = t1- maybe_join p1 t1 p2 t2 = join p1 t1 p2 t2- {-# INLINE maybe_join #-}-{-# INLINE mergeWithKey' #-}--{--------------------------------------------------------------------- Min\/Max---------------------------------------------------------------------}---- | /O(min(n,W))/. Update the value at the minimal key.------ > updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"3:b"), (5,"a")]--- > updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMinWithKey :: (Key -> a -> Maybe a) -> IntMap a -> IntMap a-updateMinWithKey f t =- case t of Bin p m l r | m < 0 -> bin p m l (go f r)- _ -> go f t- where- go f' (Bin p m l r) = bin p m (go f' l) r- go f' (Tip k y) = case f' k y of- Just y' -> Tip k y'- Nothing -> Nil- go _ Nil = error "updateMinWithKey Nil"---- | /O(min(n,W))/. Update the value at the maximal key.------ > updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"b"), (5,"5:a")]--- > updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMaxWithKey :: (Key -> a -> Maybe a) -> IntMap a -> IntMap a-updateMaxWithKey f t =- case t of Bin p m l r | m < 0 -> bin p m (go f l) r- _ -> go f t- where- go f' (Bin p m l r) = bin p m l (go f' r)- go f' (Tip k y) = case f' k y of- Just y' -> Tip k y'- Nothing -> Nil- go _ Nil = error "updateMaxWithKey Nil"---- | /O(min(n,W))/. Retrieves the maximal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > maxViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((5,"a"), singleton 3 "b")--- > maxViewWithKey empty == Nothing--maxViewWithKey :: IntMap a -> Maybe ((Key, a), IntMap a)-maxViewWithKey t =- case t of Nil -> Nothing- Bin p m l r | m < 0 -> case go l of (result, l') -> Just (result, bin p m l' r)- _ -> Just (go t)- where- go (Bin p m l r) = case go r of (result, r') -> (result, bin p m l r')- go (Tip k y) = ((k, y), Nil)- go Nil = error "maxViewWithKey Nil"---- | /O(min(n,W))/. Retrieves the minimal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > minViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((3,"b"), singleton 5 "a")--- > minViewWithKey empty == Nothing--minViewWithKey :: IntMap a -> Maybe ((Key, a), IntMap a)-minViewWithKey t =- case t of Nil -> Nothing- Bin p m l r | m < 0 -> case go r of (result, r') -> Just (result, bin p m l r')- _ -> Just (go t)- where- go (Bin p m l r) = case go l of (result, l') -> (result, bin p m l' r)- go (Tip k y) = ((k, y), Nil)- go Nil = error "minViewWithKey Nil"---- | /O(min(n,W))/. Update the value at the maximal key.------ > updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "Xa")]--- > updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMax :: (a -> Maybe a) -> IntMap a -> IntMap a-updateMax f = updateMaxWithKey (const f)---- | /O(min(n,W))/. Update the value at the minimal key.------ > updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "Xb"), (5, "a")]--- > updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMin :: (a -> Maybe a) -> IntMap a -> IntMap a-updateMin f = updateMinWithKey (const f)---- Similar to the Arrow instance.-first :: (a -> c) -> (a, b) -> (c, b)-first f (x,y) = (f x,y)---- | /O(min(n,W))/. Retrieves the maximal key of the map, and the map--- stripped of that element, or 'Nothing' if passed an empty map.-maxView :: IntMap a -> Maybe (a, IntMap a)-maxView t = liftM (first snd) (maxViewWithKey t)---- | /O(min(n,W))/. Retrieves the minimal key of the map, and the map--- stripped of that element, or 'Nothing' if passed an empty map.-minView :: IntMap a -> Maybe (a, IntMap a)-minView t = liftM (first snd) (minViewWithKey t)---- | /O(min(n,W))/. Delete and find the maximal element.-deleteFindMax :: IntMap a -> ((Key, a), IntMap a)-deleteFindMax = fromMaybe (error "deleteFindMax: empty map has no maximal element") . maxViewWithKey---- | /O(min(n,W))/. Delete and find the minimal element.-deleteFindMin :: IntMap a -> ((Key, a), IntMap a)-deleteFindMin = fromMaybe (error "deleteFindMin: empty map has no minimal element") . minViewWithKey---- | /O(min(n,W))/. The minimal key of the map.-findMin :: IntMap a -> (Key, a)-findMin Nil = error $ "findMin: empty map has no minimal element"-findMin (Tip k v) = (k,v)-findMin (Bin _ m l r)- | m < 0 = go r- | otherwise = go l- where go (Tip k v) = (k,v)- go (Bin _ _ l' _) = go l'- go Nil = error "findMax Nil"---- | /O(min(n,W))/. The maximal key of the map.-findMax :: IntMap a -> (Key, a)-findMax Nil = error $ "findMax: empty map has no maximal element"-findMax (Tip k v) = (k,v)-findMax (Bin _ m l r)- | m < 0 = go l- | otherwise = go r- where go (Tip k v) = (k,v)- go (Bin _ _ _ r') = go r'- go Nil = error "findMax Nil"---- | /O(min(n,W))/. Delete the minimal key. An error is thrown if the IntMap is already empty.--- Note, this is not the same behavior Map.-deleteMin :: IntMap a -> IntMap a-deleteMin = maybe Nil snd . minView---- | /O(min(n,W))/. Delete the maximal key. An error is thrown if the IntMap is already empty.--- Note, this is not the same behavior Map.-deleteMax :: IntMap a -> IntMap a-deleteMax = maybe Nil snd . maxView---{--------------------------------------------------------------------- Submap---------------------------------------------------------------------}--- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).--- Defined as (@'isProperSubmapOf' = 'isProperSubmapOfBy' (==)@).-isProperSubmapOf :: Eq a => IntMap a -> IntMap a -> Bool-isProperSubmapOf m1 m2- = isProperSubmapOfBy (==) m1 m2--{- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).- The expression (@'isProperSubmapOfBy' f m1 m2@) returns 'True' when- @m1@ and @m2@ are not equal,- all keys in @m1@ are in @m2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isProperSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)])-- But the following are all 'False':-- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)])- > isProperSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)])--}-isProperSubmapOfBy :: (a -> b -> Bool) -> IntMap a -> IntMap b -> Bool-isProperSubmapOfBy predicate t1 t2- = case submapCmp predicate t1 t2 of- LT -> True- _ -> False--submapCmp :: (a -> b -> Bool) -> IntMap a -> IntMap b -> Ordering-submapCmp predicate t1@(Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- | shorter m1 m2 = GT- | shorter m2 m1 = submapCmpLt- | p1 == p2 = submapCmpEq- | otherwise = GT -- disjoint- where- submapCmpLt | nomatch p1 p2 m2 = GT- | zero p1 m2 = submapCmp predicate t1 l2- | otherwise = submapCmp predicate t1 r2- submapCmpEq = case (submapCmp predicate l1 l2, submapCmp predicate r1 r2) of- (GT,_ ) -> GT- (_ ,GT) -> GT- (EQ,EQ) -> EQ- _ -> LT--submapCmp _ (Bin _ _ _ _) _ = GT-submapCmp predicate (Tip kx x) (Tip ky y)- | (kx == ky) && predicate x y = EQ- | otherwise = GT -- disjoint-submapCmp predicate (Tip k x) t- = case lookup k t of- Just y | predicate x y -> LT- _ -> GT -- disjoint-submapCmp _ Nil Nil = EQ-submapCmp _ Nil _ = LT---- | /O(n+m)/. Is this a submap?--- Defined as (@'isSubmapOf' = 'isSubmapOfBy' (==)@).-isSubmapOf :: Eq a => IntMap a -> IntMap a -> Bool-isSubmapOf m1 m2- = isSubmapOfBy (==) m1 m2--{- | /O(n+m)/.- The expression (@'isSubmapOfBy' f m1 m2@) returns 'True' if- all keys in @m1@ are in @m2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)])-- But the following are all 'False':-- > isSubmapOfBy (==) (fromList [(1,2)]) (fromList [(1,1),(2,2)])- > isSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)])--}-isSubmapOfBy :: (a -> b -> Bool) -> IntMap a -> IntMap b -> Bool-isSubmapOfBy predicate t1@(Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- | shorter m1 m2 = False- | shorter m2 m1 = match p1 p2 m2 && (if zero p1 m2 then isSubmapOfBy predicate t1 l2- else isSubmapOfBy predicate t1 r2)- | otherwise = (p1==p2) && isSubmapOfBy predicate l1 l2 && isSubmapOfBy predicate r1 r2-isSubmapOfBy _ (Bin _ _ _ _) _ = False-isSubmapOfBy predicate (Tip k x) t = case lookup k t of- Just y -> predicate x y- Nothing -> False-isSubmapOfBy _ Nil _ = True--{--------------------------------------------------------------------- Mapping---------------------------------------------------------------------}--- | /O(n)/. Map a function over all values in the map.------ > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]--map :: (a -> b) -> IntMap a -> IntMap b-map f t- = case t of- Bin p m l r -> Bin p m (map f l) (map f r)- Tip k x -> Tip k (f x)- Nil -> Nil---- | /O(n)/. Map a function over all values in the map.------ > let f key x = (show key) ++ ":" ++ x--- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]--mapWithKey :: (Key -> a -> b) -> IntMap a -> IntMap b-mapWithKey f t- = case t of- Bin p m l r -> Bin p m (mapWithKey f l) (mapWithKey f r)- Tip k x -> Tip k (f k x)- Nil -> Nil---- | /O(n)/.--- @'traverseWithKey' f s == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@--- That is, behaves exactly like a regular 'traverse' except that the traversing--- function also has access to the key associated with a value.------ > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(1, 'a'), (5, 'e')]) == Just (fromList [(1, 'b'), (5, 'f')])--- > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(2, 'c')]) == Nothing-{-# INLINE traverseWithKey #-}-traverseWithKey :: Applicative t => (Key -> a -> t b) -> IntMap a -> t (IntMap b)-traverseWithKey f = go- where- go Nil = pure Nil- go (Tip k v) = Tip k <$> f k v- go (Bin p m l r) = Bin p m <$> go l <*> go r---- | /O(n)/. The function @'mapAccum'@ threads an accumulating--- argument through the map in ascending order of keys.------ > let f a b = (a ++ b, b ++ "X")--- > mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) == ("Everything: ba", fromList [(3, "bX"), (5, "aX")])--mapAccum :: (a -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccum f = mapAccumWithKey (\a' _ x -> f a' x)---- | /O(n)/. The function @'mapAccumWithKey'@ threads an accumulating--- argument through the map in ascending order of keys.------ > let f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--- > mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) == ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])--mapAccumWithKey :: (a -> Key -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccumWithKey f a t- = mapAccumL f a t---- | /O(n)/. The function @'mapAccumL'@ threads an accumulating--- argument through the map in ascending order of keys.-mapAccumL :: (a -> Key -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccumL f a t- = case t of- Bin p m l r -> let (a1,l') = mapAccumL f a l- (a2,r') = mapAccumL f a1 r- in (a2,Bin p m l' r')- Tip k x -> let (a',x') = f a k x in (a',Tip k x')- Nil -> (a,Nil)---- | /O(n)/. The function @'mapAccumR'@ threads an accumulating--- argument through the map in descending order of keys.-mapAccumRWithKey :: (a -> Key -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccumRWithKey f a t- = case t of- Bin p m l r -> let (a1,r') = mapAccumRWithKey f a r- (a2,l') = mapAccumRWithKey f a1 l- in (a2,Bin p m l' r')- Tip k x -> let (a',x') = f a k x in (a',Tip k x')- Nil -> (a,Nil)---- | /O(n*min(n,W))/.--- @'mapKeys' f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the value at the greatest of the--- original keys is retained.------ > mapKeys (+ 1) (fromList [(5,"a"), (3,"b")]) == fromList [(4, "b"), (6, "a")]--- > mapKeys (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "c"--- > mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "c"--mapKeys :: (Key->Key) -> IntMap a -> IntMap a-mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []---- | /O(n*min(n,W))/.--- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the associated values will be--- combined using @c@.------ > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"--- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"--mapKeysWith :: (a -> a -> a) -> (Key->Key) -> IntMap a -> IntMap a-mapKeysWith c f = fromListWith c . foldrWithKey (\k x xs -> (f k, x) : xs) []---- | /O(n*min(n,W))/.--- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@--- is strictly monotonic.--- That is, for any values @x@ and @y@, if @x@ < @y@ then @f x@ < @f y@.--- /The precondition is not checked./--- Semi-formally, we have:------ > and [x < y ==> f x < f y | x <- ls, y <- ls]--- > ==> mapKeysMonotonic f s == mapKeys f s--- > where ls = keys s------ This means that @f@ maps distinct original keys to distinct resulting keys.--- This function has slightly better performance than 'mapKeys'.------ > mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) == fromList [(6, "b"), (10, "a")]--mapKeysMonotonic :: (Key->Key) -> IntMap a -> IntMap a-mapKeysMonotonic f = fromDistinctAscList . foldrWithKey (\k x xs -> (f k, x) : xs) []--{--------------------------------------------------------------------- Filter---------------------------------------------------------------------}--- | /O(n)/. Filter all values that satisfy some predicate.------ > filter (> "a") (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > filter (> "x") (fromList [(5,"a"), (3,"b")]) == empty--- > filter (< "a") (fromList [(5,"a"), (3,"b")]) == empty--filter :: (a -> Bool) -> IntMap a -> IntMap a-filter p m- = filterWithKey (\_ x -> p x) m---- | /O(n)/. Filter all keys\/values that satisfy some predicate.------ > filterWithKey (\k _ -> k > 4) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--filterWithKey :: (Key -> a -> Bool) -> IntMap a -> IntMap a-filterWithKey predicate t- = case t of- Bin p m l r- -> bin p m (filterWithKey predicate l) (filterWithKey predicate r)- Tip k x- | predicate k x -> t- | otherwise -> Nil- Nil -> Nil---- | /O(n)/. Partition the map according to some predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partition (> "a") (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > partition (< "x") (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partition (> "x") (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--partition :: (a -> Bool) -> IntMap a -> (IntMap a,IntMap a)-partition p m- = partitionWithKey (\_ x -> p x) m---- | /O(n)/. Partition the map according to some predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partitionWithKey (\ k _ -> k > 3) (fromList [(5,"a"), (3,"b")]) == (singleton 5 "a", singleton 3 "b")--- > partitionWithKey (\ k _ -> k < 7) (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partitionWithKey (\ k _ -> k > 7) (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--partitionWithKey :: (Key -> a -> Bool) -> IntMap a -> (IntMap a,IntMap a)-partitionWithKey predicate t- = case t of- Bin p m l r- -> let (l1,l2) = partitionWithKey predicate l- (r1,r2) = partitionWithKey predicate r- in (bin p m l1 r1, bin p m l2 r2)- Tip k x- | predicate k x -> (t,Nil)- | otherwise -> (Nil,t)- Nil -> (Nil,Nil)---- | /O(n)/. Map values and collect the 'Just' results.------ > let f x = if x == "a" then Just "new a" else Nothing--- > mapMaybe f (fromList [(5,"a"), (3,"b")]) == singleton 5 "new a"--mapMaybe :: (a -> Maybe b) -> IntMap a -> IntMap b-mapMaybe f = mapMaybeWithKey (\_ x -> f x)---- | /O(n)/. Map keys\/values and collect the 'Just' results.------ > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"--mapMaybeWithKey :: (Key -> a -> Maybe b) -> IntMap a -> IntMap b-mapMaybeWithKey f (Bin p m l r)- = bin p m (mapMaybeWithKey f l) (mapMaybeWithKey f r)-mapMaybeWithKey f (Tip k x) = case f k x of- Just y -> Tip k y- Nothing -> Nil-mapMaybeWithKey _ Nil = Nil---- | /O(n)/. Map values and separate the 'Left' and 'Right' results.------ > let f a = if a < "c" then Left a else Right a--- > mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])--- >--- > mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--mapEither :: (a -> Either b c) -> IntMap a -> (IntMap b, IntMap c)-mapEither f m- = mapEitherWithKey (\_ x -> f x) m---- | /O(n)/. Map keys\/values and separate the 'Left' and 'Right' results.------ > let f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--- > mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])--- >--- > mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])--mapEitherWithKey :: (Key -> a -> Either b c) -> IntMap a -> (IntMap b, IntMap c)-mapEitherWithKey f (Bin p m l r)- = (bin p m l1 r1, bin p m l2 r2)- where- (l1,l2) = mapEitherWithKey f l- (r1,r2) = mapEitherWithKey f r-mapEitherWithKey f (Tip k x) = case f k x of- Left y -> (Tip k y, Nil)- Right z -> (Nil, Tip k z)-mapEitherWithKey _ Nil = (Nil, Nil)---- | /O(min(n,W))/. The expression (@'split' k map@) is a pair @(map1,map2)@--- where all keys in @map1@ are lower than @k@ and all keys in--- @map2@ larger than @k@. Any key equal to @k@ is found in neither @map1@ nor @map2@.------ > split 2 (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3,"b"), (5,"a")])--- > split 3 (fromList [(5,"a"), (3,"b")]) == (empty, singleton 5 "a")--- > split 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > split 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", empty)--- > split 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], empty)--split :: Key -> IntMap a -> (IntMap a, IntMap a)-split k t =- case t of Bin _ m l r | m < 0 -> if k >= 0 -- handle negative numbers.- then case go k l of (lt, gt) -> (union r lt, gt)- else case go k r of (lt, gt) -> (lt, union gt l)- _ -> go k t- where- go k' t'@(Bin p m l r) | nomatch k' p m = if k' > p then (t', Nil) else (Nil, t')- | zero k' m = case go k' l of (lt, gt) -> (lt, union gt r)- | otherwise = case go k' r of (lt, gt) -> (union l lt, gt)- go k' t'@(Tip ky _) | k' > ky = (t', Nil)- | k' < ky = (Nil, t')- | otherwise = (Nil, Nil)- go _ Nil = (Nil, Nil)---- | /O(min(n,W))/. Performs a 'split' but also returns whether the pivot--- key was found in the original map.------ > splitLookup 2 (fromList [(5,"a"), (3,"b")]) == (empty, Nothing, fromList [(3,"b"), (5,"a")])--- > splitLookup 3 (fromList [(5,"a"), (3,"b")]) == (empty, Just "b", singleton 5 "a")--- > splitLookup 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Nothing, singleton 5 "a")--- > splitLookup 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Just "a", empty)--- > splitLookup 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], Nothing, empty)--splitLookup :: Key -> IntMap a -> (IntMap a, Maybe a, IntMap a)-splitLookup k t =- case t of Bin _ m l r | m < 0 -> if k >= 0 -- handle negative numbers.- then case go k l of (lt, fnd, gt) -> (union r lt, fnd, gt)- else case go k r of (lt, fnd, gt) -> (lt, fnd, union gt l)- _ -> go k t- where- go k' t'@(Bin p m l r) | nomatch k' p m = if k' > p then (t', Nothing, Nil) else (Nil, Nothing, t')- | zero k' m = case go k' l of (lt, fnd, gt) -> (lt, fnd, union gt r)- | otherwise = case go k' r of (lt, fnd, gt) -> (union l lt, fnd, gt)- go k' t'@(Tip ky y) | k' > ky = (t', Nothing, Nil)- | k' < ky = (Nil, Nothing, t')- | otherwise = (Nil, Just y, Nil)- go _ Nil = (Nil, Nothing, Nil)--{--------------------------------------------------------------------- Fold---------------------------------------------------------------------}--- | /O(n)/. Fold the values in the map using the given right-associative--- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'elems'@.------ For example,------ > elems map = foldr (:) [] map------ > let f a len = len + (length a)--- > foldr f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldr :: (a -> b -> b) -> b -> IntMap a -> b-foldr f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z l) r -- put negative numbers before- | otherwise -> go (go z r) l- _ -> go z t- where- go z' Nil = z'- go z' (Tip _ x) = f x z'- go z' (Bin _ _ l r) = go (go z' r) l-{-# INLINE foldr #-}---- | /O(n)/. A strict version of 'foldr'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldr' :: (a -> b -> b) -> b -> IntMap a -> b-foldr' f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z l) r -- put negative numbers before- | otherwise -> go (go z r) l- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip _ x) = f x z'- go z' (Bin _ _ l r) = go (go z' r) l-{-# INLINE foldr' #-}---- | /O(n)/. Fold the values in the map using the given left-associative--- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.------ For example,------ > elems = reverse . foldl (flip (:)) []------ > let f len a = len + (length a)--- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldl :: (a -> b -> a) -> a -> IntMap b -> a-foldl f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z r) l -- put negative numbers before- | otherwise -> go (go z l) r- _ -> go z t- where- go z' Nil = z'- go z' (Tip _ x) = f z' x- go z' (Bin _ _ l r) = go (go z' l) r-{-# INLINE foldl #-}---- | /O(n)/. A strict version of 'foldl'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldl' :: (a -> b -> a) -> a -> IntMap b -> a-foldl' f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z r) l -- put negative numbers before- | otherwise -> go (go z l) r- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip _ x) = f z' x- go z' (Bin _ _ l r) = go (go z' l) r-{-# INLINE foldl' #-}---- | /O(n)/. Fold the keys and values in the map using the given right-associative--- binary operator, such that--- @'foldrWithKey' f z == 'Prelude.foldr' ('uncurry' f) z . 'toAscList'@.------ For example,------ > keys map = foldrWithKey (\k x ks -> k:ks) [] map------ > let f k a result = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldrWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (5:a)(3:b)"-foldrWithKey :: (Int -> a -> b -> b) -> b -> IntMap a -> b-foldrWithKey f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z l) r -- put negative numbers before- | otherwise -> go (go z r) l- _ -> go z t- where- go z' Nil = z'- go z' (Tip kx x) = f kx x z'- go z' (Bin _ _ l r) = go (go z' r) l-{-# INLINE foldrWithKey #-}---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldrWithKey' :: (Int -> a -> b -> b) -> b -> IntMap a -> b-foldrWithKey' f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z l) r -- put negative numbers before- | otherwise -> go (go z r) l- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip kx x) = f kx x z'- go z' (Bin _ _ l r) = go (go z' r) l-{-# INLINE foldrWithKey' #-}---- | /O(n)/. Fold the keys and values in the map using the given left-associative--- binary operator, such that--- @'foldlWithKey' f z == 'Prelude.foldl' (\\z' (kx, x) -> f z' kx x) z . 'toAscList'@.------ For example,------ > keys = reverse . foldlWithKey (\ks k x -> k:ks) []------ > let f result k a = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldlWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (3:b)(5:a)"-foldlWithKey :: (a -> Int -> b -> a) -> a -> IntMap b -> a-foldlWithKey f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z r) l -- put negative numbers before- | otherwise -> go (go z l) r- _ -> go z t- where- go z' Nil = z'- go z' (Tip kx x) = f z' kx x- go z' (Bin _ _ l r) = go (go z' l) r-{-# INLINE foldlWithKey #-}---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldlWithKey' :: (a -> Int -> b -> a) -> a -> IntMap b -> a-foldlWithKey' f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z r) l -- put negative numbers before- | otherwise -> go (go z l) r- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip kx x) = f z' kx x- go z' (Bin _ _ l r) = go (go z' l) r-{-# INLINE foldlWithKey' #-}--{--------------------------------------------------------------------- List variations---------------------------------------------------------------------}--- | /O(n)/.--- Return all elements of the map in the ascending order of their keys.--- Subject to list fusion.------ > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]--- > elems empty == []--elems :: IntMap a -> [a]-elems = foldr (:) []---- | /O(n)/. Return all keys of the map in ascending order. Subject to list--- fusion.------ > keys (fromList [(5,"a"), (3,"b")]) == [3,5]--- > keys empty == []--keys :: IntMap a -> [Key]-keys = foldrWithKey (\k _ ks -> k : ks) []---- | /O(n)/. An alias for 'toAscList'. Returns all key\/value pairs in the--- map in ascending key order. Subject to list fusion.------ > assocs (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > assocs empty == []--assocs :: IntMap a -> [(Key,a)]-assocs = toAscList---- | /O(n*min(n,W))/. The set of all keys of the map.------ > keysSet (fromList [(5,"a"), (3,"b")]) == Data.IntSet.fromList [3,5]--- > keysSet empty == Data.IntSet.empty--keysSet :: IntMap a -> IntSet.IntSet-keysSet Nil = IntSet.Nil-keysSet (Tip kx _) = IntSet.singleton kx-keysSet (Bin p m l r)- | m .&. IntSet.suffixBitMask == 0 = IntSet.Bin p m (keysSet l) (keysSet r)- | otherwise = IntSet.Tip (p .&. IntSet.prefixBitMask) (computeBm (computeBm 0 l) r)- where STRICT_1_OF_2(computeBm)- computeBm acc (Bin _ _ l' r') = computeBm (computeBm acc l') r'- computeBm acc (Tip kx _) = acc .|. IntSet.bitmapOf kx- computeBm _ Nil = error "Data.IntSet.keysSet: Nil"---- | /O(n)/. Build a map from a set of keys and a function which for each key--- computes its value.------ > fromSet (\k -> replicate k 'a') (Data.IntSet.fromList [3, 5]) == fromList [(5,"aaaaa"), (3,"aaa")]--- > fromSet undefined Data.IntSet.empty == empty--fromSet :: (Key -> a) -> IntSet.IntSet -> IntMap a-fromSet _ IntSet.Nil = Nil-fromSet f (IntSet.Bin p m l r) = Bin p m (fromSet f l) (fromSet f r)-fromSet f (IntSet.Tip kx bm) = buildTree f kx bm (IntSet.suffixBitMask + 1)- where -- This is slightly complicated, as we to convert the dense- -- representation of IntSet into tree representation of IntMap.- --- -- We are given a nonzero bit mask 'bmask' of 'bits' bits with prefix 'prefix'.- -- We split bmask into halves corresponding to left and right subtree.- -- If they are both nonempty, we create a Bin node, otherwise exactly- -- one of them is nonempty and we construct the IntMap from that half.- buildTree g prefix bmask bits = prefix `seq` bmask `seq` case bits of- 0 -> Tip prefix (g prefix)- _ -> case intFromNat ((natFromInt bits) `shiftRL` 1) of- bits2 | bmask .&. ((1 `shiftLL` bits2) - 1) == 0 ->- buildTree g (prefix + bits2) (bmask `shiftRL` bits2) bits2- | (bmask `shiftRL` bits2) .&. ((1 `shiftLL` bits2) - 1) == 0 ->- buildTree g prefix bmask bits2- | otherwise ->- Bin prefix bits2 (buildTree g prefix bmask bits2) (buildTree g (prefix + bits2) (bmask `shiftRL` bits2) bits2)--{--------------------------------------------------------------------- Lists---------------------------------------------------------------------}--- | /O(n)/. Convert the map to a list of key\/value pairs. Subject to list--- fusion.------ > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > toList empty == []--toList :: IntMap a -> [(Key,a)]-toList = toAscList---- | /O(n)/. Convert the map to a list of key\/value pairs where the--- keys are in ascending order. Subject to list fusion.------ > toAscList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--toAscList :: IntMap a -> [(Key,a)]-toAscList = foldrWithKey (\k x xs -> (k,x):xs) []---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys--- are in descending order. Subject to list fusion.------ > toDescList (fromList [(5,"a"), (3,"b")]) == [(5,"a"), (3,"b")]--toDescList :: IntMap a -> [(Key,a)]-toDescList = foldlWithKey (\xs k x -> (k,x):xs) []---- List fusion for the list generating functions.-#if __GLASGOW_HASKELL__--- The foldrFB and foldlFB are fold{r,l}WithKey equivalents, used for list fusion.--- They are important to convert unfused methods back, see mapFB in prelude.-foldrFB :: (Key -> a -> b -> b) -> b -> IntMap a -> b-foldrFB = foldrWithKey-{-# INLINE[0] foldrFB #-}-foldlFB :: (a -> Key -> b -> a) -> a -> IntMap b -> a-foldlFB = foldlWithKey-{-# INLINE[0] foldlFB #-}---- Inline assocs and toList, so that we need to fuse only toAscList.-{-# INLINE assocs #-}-{-# INLINE toList #-}---- The fusion is enabled up to phase 2 included. If it does not succeed,--- convert in phase 1 the expanded elems,keys,to{Asc,Desc}List calls back to--- elems,keys,to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were--- used in a list fusion, otherwise it would go away in phase 1), and let compiler--- do whatever it wants with elems,keys,to{Asc,Desc}List -- it was forbidden to--- inline it before phase 0, otherwise the fusion rules would not fire at all.-{-# NOINLINE[0] elems #-}-{-# NOINLINE[0] keys #-}-{-# NOINLINE[0] toAscList #-}-{-# NOINLINE[0] toDescList #-}-{-# RULES "IntMap.elems" [~1] forall m . elems m = build (\c n -> foldrFB (\_ x xs -> c x xs) n m) #-}-{-# RULES "IntMap.elemsBack" [1] foldrFB (\_ x xs -> x : xs) [] = elems #-}-{-# RULES "IntMap.keys" [~1] forall m . keys m = build (\c n -> foldrFB (\k _ xs -> c k xs) n m) #-}-{-# RULES "IntMap.keysBack" [1] foldrFB (\k _ xs -> k : xs) [] = keys #-}-{-# RULES "IntMap.toAscList" [~1] forall m . toAscList m = build (\c n -> foldrFB (\k x xs -> c (k,x) xs) n m) #-}-{-# RULES "IntMap.toAscListBack" [1] foldrFB (\k x xs -> (k, x) : xs) [] = toAscList #-}-{-# RULES "IntMap.toDescList" [~1] forall m . toDescList m = build (\c n -> foldlFB (\xs k x -> c (k,x) xs) n m) #-}-{-# RULES "IntMap.toDescListBack" [1] foldlFB (\xs k x -> (k, x) : xs) [] = toDescList #-}-#endif----- | /O(n*min(n,W))/. Create a map from a list of key\/value pairs.------ > fromList [] == empty--- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]--- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]--fromList :: [(Key,a)] -> IntMap a-fromList xs- = foldlStrict ins empty xs- where- ins t (k,x) = insert k x t---- | /O(n*min(n,W))/. Create a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"c")] == fromList [(3, "ab"), (5, "cba")]--- > fromListWith (++) [] == empty--fromListWith :: (a -> a -> a) -> [(Key,a)] -> IntMap a-fromListWith f xs- = fromListWithKey (\_ x y -> f x y) xs---- | /O(n*min(n,W))/. Build a map from a list of key\/value pairs with a combining function. See also fromAscListWithKey'.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"c")] == fromList [(3, "3:a|b"), (5, "5:c|5:b|a")]--- > fromListWithKey f [] == empty--fromListWithKey :: (Key -> a -> a -> a) -> [(Key,a)] -> IntMap a-fromListWithKey f xs- = foldlStrict ins empty xs- where- ins t (k,x) = insertWithKey f k x t---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order.------ > fromAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]--fromAscList :: [(Key,a)] -> IntMap a-fromAscList xs- = fromAscListWithKey (\_ x _ -> x) xs---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order, with a combining function on equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--fromAscListWith :: (a -> a -> a) -> [(Key,a)] -> IntMap a-fromAscListWith f xs- = fromAscListWithKey (\_ x y -> f x y) xs---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order, with a combining function on equal keys.--- /The precondition (input list is ascending) is not checked./------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "5:b|a")]--fromAscListWithKey :: (Key -> a -> a -> a) -> [(Key,a)] -> IntMap a-fromAscListWithKey _ [] = Nil-fromAscListWithKey f (x0 : xs0) = fromDistinctAscList (combineEq x0 xs0)- where- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]- combineEq z [] = [z]- combineEq z@(kz,zz) (x@(kx,xx):xs)- | kx==kz = let yy = f kx xx zz in combineEq (kx,yy) xs- | otherwise = z:combineEq x xs---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order and all distinct.--- /The precondition (input list is strictly ascending) is not checked./------ > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--fromDistinctAscList :: [(Key,a)] -> IntMap a-fromDistinctAscList [] = Nil-fromDistinctAscList (z0 : zs0) = work z0 zs0 Nada- where- work (kx,vx) [] stk = finish kx (Tip kx vx) stk- work (kx,vx) (z@(kz,_):zs) stk = reduce z zs (branchMask kx kz) kx (Tip kx vx) stk-- reduce :: (Key,a) -> [(Key,a)] -> Mask -> Prefix -> IntMap a -> Stack a -> IntMap a- reduce z zs _ px tx Nada = work z zs (Push px tx Nada)- reduce z zs m px tx stk@(Push py ty stk') =- let mxy = branchMask px py- pxy = mask px mxy- in if shorter m mxy- then reduce z zs m pxy (Bin pxy mxy ty tx) stk'- else work z zs (Push px tx stk)-- finish _ t Nada = t- finish px tx (Push py ty stk) = finish p (join py ty px tx) stk- where m = branchMask px py- p = mask px m--data Stack a = Push {-# UNPACK #-} !Prefix !(IntMap a) !(Stack a) | Nada---{--------------------------------------------------------------------- Eq---------------------------------------------------------------------}-instance Eq a => Eq (IntMap a) where- t1 == t2 = equal t1 t2- t1 /= t2 = nequal t1 t2--equal :: Eq a => IntMap a -> IntMap a -> Bool-equal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- = (m1 == m2) && (p1 == p2) && (equal l1 l2) && (equal r1 r2)-equal (Tip kx x) (Tip ky y)- = (kx == ky) && (x==y)-equal Nil Nil = True-equal _ _ = False--nequal :: Eq a => IntMap a -> IntMap a -> Bool-nequal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- = (m1 /= m2) || (p1 /= p2) || (nequal l1 l2) || (nequal r1 r2)-nequal (Tip kx x) (Tip ky y)- = (kx /= ky) || (x/=y)-nequal Nil Nil = False-nequal _ _ = True--{--------------------------------------------------------------------- Ord---------------------------------------------------------------------}--instance Ord a => Ord (IntMap a) where- compare m1 m2 = compare (toList m1) (toList m2)--{--------------------------------------------------------------------- Functor---------------------------------------------------------------------}--instance Functor IntMap where- fmap = map--{--------------------------------------------------------------------- Show---------------------------------------------------------------------}--instance Show a => Show (IntMap a) where- showsPrec d m = showParen (d > 10) $- showString "fromList " . shows (toList m)--{--------------------------------------------------------------------- Read---------------------------------------------------------------------}-instance (Read e) => Read (IntMap e) where-#ifdef __GLASGOW_HASKELL__- readPrec = parens $ prec 10 $ do- Ident "fromList" <- lexP- xs <- readPrec- return (fromList xs)-- readListPrec = readListPrecDefault-#else- readsPrec p = readParen (p > 10) $ \ r -> do- ("fromList",s) <- lex r- (xs,t) <- reads s- return (fromList xs,t)-#endif--{--------------------------------------------------------------------- Typeable---------------------------------------------------------------------}--#include "Typeable.h"-INSTANCE_TYPEABLE1(IntMap,intMapTc,"IntMap")--{--------------------------------------------------------------------- Helpers---------------------------------------------------------------------}-{--------------------------------------------------------------------- Join---------------------------------------------------------------------}-join :: Prefix -> IntMap a -> Prefix -> IntMap a -> IntMap a-join p1 t1 p2 t2- | zero p1 m = Bin p m t1 t2- | otherwise = Bin p m t2 t1- where- m = branchMask p1 p2- p = mask p1 m-{-# INLINE join #-}--{--------------------------------------------------------------------- @bin@ assures that we never have empty trees within a tree.---------------------------------------------------------------------}-bin :: Prefix -> Mask -> IntMap a -> IntMap a -> IntMap a-bin _ _ l Nil = l-bin _ _ Nil r = r-bin p m l r = Bin p m l r-{-# INLINE bin #-}---{--------------------------------------------------------------------- Endian independent bit twiddling---------------------------------------------------------------------}-zero :: Key -> Mask -> Bool-zero i m- = (natFromInt i) .&. (natFromInt m) == 0-{-# INLINE zero #-}--nomatch,match :: Key -> Prefix -> Mask -> Bool-nomatch i p m- = (mask i m) /= p-{-# INLINE nomatch #-}--match i p m- = (mask i m) == p-{-# INLINE match #-}--mask :: Key -> Mask -> Prefix-mask i m- = maskW (natFromInt i) (natFromInt m)-{-# INLINE mask #-}---{--------------------------------------------------------------------- Big endian operations---------------------------------------------------------------------}-maskW :: Nat -> Nat -> Prefix-maskW i m- = intFromNat (i .&. (complement (m-1) `xor` m))-{-# INLINE maskW #-}--shorter :: Mask -> Mask -> Bool-shorter m1 m2- = (natFromInt m1) > (natFromInt m2)-{-# INLINE shorter #-}--branchMask :: Prefix -> Prefix -> Mask-branchMask p1 p2- = intFromNat (highestBitMask (natFromInt p1 `xor` natFromInt p2))-{-# INLINE branchMask #-}--{----------------------------------------------------------------------- Finding the highest bit (mask) in a word [x] can be done efficiently in- three ways:- * convert to a floating point value and the mantissa tells us the- [log2(x)] that corresponds with the highest bit position. The mantissa- is retrieved either via the standard C function [frexp] or by some bit- twiddling on IEEE compatible numbers (float). Note that one needs to- use at least [double] precision for an accurate mantissa of 32 bit- numbers.- * use bit twiddling, a logarithmic sequence of bitwise or's and shifts (bit).- * use processor specific assembler instruction (asm).-- The most portable way would be [bit], but is it efficient enough?- I have measured the cycle counts of the different methods on an AMD- Athlon-XP 1800 (~ Pentium III 1.8Ghz) using the RDTSC instruction:-- highestBitMask: method cycles- --------------- frexp 200- float 33- bit 11- asm 12-- highestBit: method cycles- --------------- frexp 195- float 33- bit 11- asm 11-- Wow, the bit twiddling is on today's RISC like machines even faster- than a single CISC instruction (BSR)!-----------------------------------------------------------------------}--{----------------------------------------------------------------------- [highestBitMask] returns a word where only the highest bit is set.- It is found by first setting all bits in lower positions than the- highest bit and than taking an exclusive or with the original value.- Allthough the function may look expensive, GHC compiles this into- excellent C code that subsequently compiled into highly efficient- machine code. The algorithm is derived from Jorg Arndt's FXT library.-----------------------------------------------------------------------}-highestBitMask :: Nat -> Nat-highestBitMask x0- = case (x0 .|. shiftRL x0 1) of- x1 -> case (x1 .|. shiftRL x1 2) of- x2 -> case (x2 .|. shiftRL x2 4) of- x3 -> case (x3 .|. shiftRL x3 8) of- x4 -> case (x4 .|. shiftRL x4 16) of-#if !(defined(__GLASGOW_HASKELL__) && WORD_SIZE_IN_BITS==32)- x5 -> case (x5 .|. shiftRL x5 32) of -- for 64 bit platforms-#endif- x6 -> (x6 `xor` (shiftRL x6 1))-{-# INLINE highestBitMask #-}---{--------------------------------------------------------------------- Utilities---------------------------------------------------------------------}--foldlStrict :: (a -> b -> a) -> a -> [b] -> a-foldlStrict f = go- where- go z [] = z- go z (x:xs) = let z' = f z x in z' `seq` go z' xs-{-# INLINE foldlStrict #-}--{--------------------------------------------------------------------- Debugging---------------------------------------------------------------------}--- | /O(n)/. Show the tree that implements the map. The tree is shown--- in a compressed, hanging format.-showTree :: Show a => IntMap a -> String-showTree s- = showTreeWith True False s---{- | /O(n)/. The expression (@'showTreeWith' hang wide map@) shows- the tree that implements the map. If @hang@ is- 'True', a /hanging/ tree is shown otherwise a rotated tree is shown. If- @wide@ is 'True', an extra wide version is shown.--}-showTreeWith :: Show a => Bool -> Bool -> IntMap a -> String-showTreeWith hang wide t- | hang = (showsTreeHang wide [] t) ""- | otherwise = (showsTree wide [] [] t) ""--showsTree :: Show a => Bool -> [String] -> [String] -> IntMap a -> ShowS-showsTree wide lbars rbars t- = case t of- Bin p m l r- -> showsTree wide (withBar rbars) (withEmpty rbars) r .- showWide wide rbars .- showsBars lbars . showString (showBin p m) . showString "\n" .- showWide wide lbars .- showsTree wide (withEmpty lbars) (withBar lbars) l- Tip k x- -> showsBars lbars . showString " " . shows k . showString ":=" . shows x . showString "\n"- Nil -> showsBars lbars . showString "|\n"--showsTreeHang :: Show a => Bool -> [String] -> IntMap a -> ShowS-showsTreeHang wide bars t- = case t of- Bin p m l r- -> showsBars bars . showString (showBin p m) . showString "\n" .- showWide wide bars .- showsTreeHang wide (withBar bars) l .- showWide wide bars .- showsTreeHang wide (withEmpty bars) r- Tip k x- -> showsBars bars . showString " " . shows k . showString ":=" . shows x . showString "\n"- Nil -> showsBars bars . showString "|\n"--showBin :: Prefix -> Mask -> String-showBin _ _- = "*" -- ++ show (p,m)--showWide :: Bool -> [String] -> String -> String-showWide wide bars- | wide = showString (concat (reverse bars)) . showString "|\n"- | otherwise = id--showsBars :: [String] -> ShowS-showsBars bars- = case bars of- [] -> id- _ -> showString (concat (reverse (tail bars))) . showString node--node :: String-node = "+--"--withBar, withEmpty :: [String] -> [String]-withBar bars = "| ":bars-withEmpty bars = " ":bars
@@ -1,214 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.IntMap.Lazy--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from integer keys to values--- (dictionaries).------ API of this module is strict in the keys, but lazy in the values.--- If you need value-strict maps, use 'Data.IntMap.Strict' instead.--- The 'IntMap' type itself is shared between the lazy and strict modules,--- meaning that the same 'IntMap' value can be passed to functions in--- both modules (although that is rarely needed).------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.IntMap.Lazy (IntMap)--- > import qualified Data.IntMap.Lazy as IntMap------ The implementation is based on /big-endian patricia trees/. This data--- structure performs especially well on binary operations like 'union'--- and 'intersection'. However, my benchmarks show that it is also--- (much) faster on insertions and deletions when compared to a generic--- size-balanced map implementation (see "Data.Map").------ * Chris Okasaki and Andy Gill, \"/Fast Mergeable Integer Maps/\",--- Workshop on ML, September 1998, pages 77-86,--- <http://citeseer.ist.psu.edu/okasaki98fast.html>------ * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve--- Information Coded In Alphanumeric/\", Journal of the ACM, 15(4),--- October 1968, pages 514-534.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.--- Many operations have a worst-case complexity of /O(min(n,W))/.--- This means that the operation can become linear in the number of--- elements with a maximum of /W/ -- the number of bits in an 'Int'--- (32 or 64).--------------------------------------------------------------------------------module Data.IntMap.Lazy (- -- * Strictness properties- -- $strictness-- -- * Map type-#if !defined(TESTING)- IntMap, Key -- instance Eq,Show-#else- IntMap(..), Key -- instance Eq,Show-#endif-- -- * Operators- , (!), (\\)-- -- * Query- , IM.null- , size- , member- , notMember- , IM.lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , IM.map- , mapWithKey- , traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , IM.foldr- , IM.foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- , keysSet- , fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , IM.filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- ) where--import Data.IntMap.Base as IM---- $strictness------ This module satisfies the following strictness property:------ * Key arguments are evaluated to WHNF------ Here are some examples that illustrate the property:------ > insertWith (\ new old -> old) undefined v m == undefined--- > insertWith (\ new old -> old) k undefined m == OK--- > delete undefined m == undefined
@@ -1,964 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.IntMap.Strict--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from integer keys to values--- (dictionaries).------ API of this module is strict in both the keys and the values.--- If you need value-lazy maps, use 'Data.IntMap.Lazy' instead.--- The 'IntMap' type itself is shared between the lazy and strict modules,--- meaning that the same 'IntMap' value can be passed to functions in--- both modules (although that is rarely needed).------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.IntMap.Strict (IntMap)--- > import qualified Data.IntMap.Strict as IntMap------ The implementation is based on /big-endian patricia trees/. This data--- structure performs especially well on binary operations like 'union'--- and 'intersection'. However, my benchmarks show that it is also--- (much) faster on insertions and deletions when compared to a generic--- size-balanced map implementation (see "Data.Map").------ * Chris Okasaki and Andy Gill, \"/Fast Mergeable Integer Maps/\",--- Workshop on ML, September 1998, pages 77-86,--- <http://citeseer.ist.psu.edu/okasaki98fast.html>------ * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve--- Information Coded In Alphanumeric/\", Journal of the ACM, 15(4),--- October 1968, pages 514-534.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.--- Many operations have a worst-case complexity of /O(min(n,W))/.--- This means that the operation can become linear in the number of--- elements with a maximum of /W/ -- the number of bits in an 'Int'--- (32 or 64).------ Be aware that the 'Functor', 'Traversable' and 'Data' instances--- are the same as for the 'Data.IntMap.Lazy' module, so if they are used--- on strict maps, the resulting maps will be lazy.---------------------------------------------------------------------------------- See the notes at the beginning of Data.IntMap.Base.--module Data.IntMap.Strict (- -- * Strictness properties- -- $strictness-- -- * Map type-#if !defined(TESTING)- IntMap, Key -- instance Eq,Show-#else- IntMap(..), Key -- instance Eq,Show-#endif-- -- * Operators- , (!), (\\)-- -- * Query- , null- , size- , member- , notMember- , lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , map- , mapWithKey- , traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , foldr- , foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- , keysSet- , fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- ) where--import Prelude hiding (lookup,map,filter,foldr,foldl,null)--import Data.Bits-import Data.IntMap.Base hiding- ( findWithDefault- , singleton- , insert- , insertWith- , insertWithKey- , insertLookupWithKey- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter- , unionsWith- , unionWith- , unionWithKey- , differenceWith- , differenceWithKey- , intersectionWith- , intersectionWithKey- , mergeWithKey- , updateMinWithKey- , updateMaxWithKey- , updateMax- , updateMin- , map- , mapWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeysWith- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey- , fromSet- , fromList- , fromListWith- , fromListWithKey- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList- )-import qualified Data.IntSet.Base as IntSet-import Data.StrictPair---- $strictness------ This module satisfies the following strictness properties:------ 1. Key and value arguments are evaluated to WHNF;------ 2. Keys and values are evaluated to WHNF before they are stored in--- the map.------ Here are some examples that illustrate the first property:------ > insertWith (\ new old -> old) k undefined m == undefined--- > delete undefined m == undefined------ Here are some examples that illustrate the second property:------ > map (\ v -> undefined) m == undefined -- m is not empty--- > mapKeys (\ k -> undefined) m == undefined -- m is not empty--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}---- | /O(min(n,W))/. The expression @('findWithDefault' def k map)@--- returns the value at key @k@ or returns @def@ when the key is not an--- element of the map.------ > findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) == 'x'--- > findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) == 'a'---- See IntMap.Base.Note: Local 'go' functions and capturing]-findWithDefault :: a -> Key -> IntMap a -> a-findWithDefault def k = def `seq` k `seq` go- where- go (Bin p m l r) | nomatch k p m = def- | zero k m = go l- | otherwise = go r- go (Tip kx x) | k == kx = x- | otherwise = def- go Nil = def--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. A map of one element.------ > singleton 1 'a' == fromList [(1, 'a')]--- > size (singleton 1 'a') == 1--singleton :: Key -> a -> IntMap a-singleton k x- = x `seq` Tip k x-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insert---------------------------------------------------------------------}--- | /O(min(n,W))/. Insert a new key\/value pair in the map.--- If the key is already present in the map, the associated value is--- replaced with the supplied value, i.e. 'insert' is equivalent to--- @'insertWith' 'const'@.------ > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]--- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]--- > insert 5 'x' empty == singleton 5 'x'--insert :: Key -> a -> IntMap a -> IntMap a-insert k x t = k `seq` x `seq`- case t of- Bin p m l r- | nomatch k p m -> join k (Tip k x) p t- | zero k m -> Bin p m (insert k x l) r- | otherwise -> Bin p m l (insert k x r)- Tip ky _- | k==ky -> Tip k x- | otherwise -> join k (Tip k x) ky t- Nil -> Tip k x---- right-biased insertion, used by 'union'--- | /O(min(n,W))/. Insert with a combining function.--- @'insertWith' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert @f new_value old_value@.------ > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]--- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"--insertWith :: (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a-insertWith f k x t- = insertWithKey (\_ x' y' -> f x' y') k x t---- | /O(min(n,W))/. Insert with a combining function.--- @'insertWithKey' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert @f key new_value old_value@.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]--- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"------ If the key exists in the map, this function is lazy in @x@ but strict--- in the result of @f@.--insertWithKey :: (Key -> a -> a -> a) -> Key -> a -> IntMap a -> IntMap a-insertWithKey f k x t = k `seq` x `seq`- case t of- Bin p m l r- | nomatch k p m -> join k (Tip k x) p t- | zero k m -> Bin p m (insertWithKey f k x l) r- | otherwise -> Bin p m l (insertWithKey f k x r)- Tip ky y- | k==ky -> Tip k $! f k x y- | otherwise -> join k (Tip k x) ky t- Nil -> Tip k x---- | /O(min(n,W))/. The expression (@'insertLookupWithKey' f k x map@)--- is a pair where the first element is equal to (@'lookup' k map@)--- and the second element equal to (@'insertWithKey' f k x map@).------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])--- > insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])--- > insertLookupWithKey f 5 "xxx" empty == (Nothing, singleton 5 "xxx")------ This is how to define @insertLookup@ using @insertLookupWithKey@:------ > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t--- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])--- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])--insertLookupWithKey :: (Key -> a -> a -> a) -> Key -> a -> IntMap a -> (Maybe a, IntMap a)-insertLookupWithKey f k x t = k `seq` x `seq`- case t of- Bin p m l r- | nomatch k p m -> Nothing `strictPair` join k (Tip k x) p t- | zero k m -> let (found,l') = insertLookupWithKey f k x l in (found `strictPair` Bin p m l' r)- | otherwise -> let (found,r') = insertLookupWithKey f k x r in (found `strictPair` Bin p m l r')- Tip ky y- | k==ky -> (Just y `strictPair` (Tip k $! f k x y))- | otherwise -> (Nothing `strictPair` join k (Tip k x) ky t)- Nil -> Nothing `strictPair` Tip k x---{--------------------------------------------------------------------- Deletion---------------------------------------------------------------------}--- | /O(min(n,W))/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjust ("new " ++) 7 empty == empty--adjust :: (a -> a) -> Key -> IntMap a -> IntMap a-adjust f k m- = adjustWithKey (\_ x -> f x) k m---- | /O(min(n,W))/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > let f key x = (show key) ++ ":new " ++ x--- > adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjustWithKey f 7 empty == empty--adjustWithKey :: (Key -> a -> a) -> Key -> IntMap a -> IntMap a-adjustWithKey f- = updateWithKey (\k' x -> Just (f k' x))---- | /O(min(n,W))/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f x = if x == "a" then Just "new a" else Nothing--- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--update :: (a -> Maybe a) -> Key -> IntMap a -> IntMap a-update f- = updateWithKey (\_ x -> f x)---- | /O(min(n,W))/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f k x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateWithKey :: (Key -> a -> Maybe a) -> Key -> IntMap a -> IntMap a-updateWithKey f k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> t- | zero k m -> bin p m (updateWithKey f k l) r- | otherwise -> bin p m l (updateWithKey f k r)- Tip ky y- | k==ky -> case f k y of- Just y' -> y' `seq` Tip ky y'- Nothing -> Nil- | otherwise -> t- Nil -> Nil---- | /O(min(n,W))/. Lookup and update.--- The function returns original value, if it is updated.--- This is different behavior than 'Data.Map.updateLookupWithKey'.--- Returns the original key value if the map entry is deleted.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:new a")])--- > updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a")])--- > updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) == (Just "b", singleton 5 "a")--updateLookupWithKey :: (Key -> a -> Maybe a) -> Key -> IntMap a -> (Maybe a,IntMap a)-updateLookupWithKey f k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> (Nothing, t)- | zero k m -> let (found,l') = updateLookupWithKey f k l in (found `strictPair` bin p m l' r)- | otherwise -> let (found,r') = updateLookupWithKey f k r in (found `strictPair` bin p m l r')- Tip ky y- | k==ky -> case f k y of- Just y' -> y' `seq` (Just y `strictPair` Tip ky y')- Nothing -> (Just y, Nil)- | otherwise -> (Nothing,t)- Nil -> (Nothing,Nil)------ | /O(log n)/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.--- 'alter' can be used to insert, delete, or update a value in an 'IntMap'.--- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.-alter :: (Maybe a -> Maybe a) -> Key -> IntMap a -> IntMap a-alter f k t = k `seq`- case t of- Bin p m l r- | nomatch k p m -> case f Nothing of- Nothing -> t- Just x -> x `seq` join k (Tip k x) p t- | zero k m -> bin p m (alter f k l) r- | otherwise -> bin p m l (alter f k r)- Tip ky y- | k==ky -> case f (Just y) of- Just x -> x `seq` Tip ky x- Nothing -> Nil- | otherwise -> case f Nothing of- Just x -> x `seq` join k (Tip k x) ky t- Nothing -> t- Nil -> case f Nothing of- Just x -> x `seq` Tip k x- Nothing -> Nil---{--------------------------------------------------------------------- Union---------------------------------------------------------------------}--- | The union of a list of maps, with a combining operation.------ > unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--unionsWith :: (a->a->a) -> [IntMap a] -> IntMap a-unionsWith f ts- = foldlStrict (unionWith f) empty ts---- | /O(n+m)/. The union with a combining function.------ > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]--unionWith :: (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a-unionWith f m1 m2- = unionWithKey (\_ x y -> f x y) m1 m2---- | /O(n+m)/. The union with a combining function.------ > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]--unionWithKey :: (Key -> a -> a -> a) -> IntMap a -> IntMap a -> IntMap a-unionWithKey f m1 m2- = mergeWithKey' Bin (\(Tip k1 x1) (Tip _k2 x2) -> Tip k1 $! f k1 x1 x2) id id m1 m2--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}---- | /O(n+m)/. Difference with a combining function.------ > let f al ar = if al == "b" then Just (al ++ ":" ++ ar) else Nothing--- > differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])--- > == singleton 3 "b:B"--differenceWith :: (a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a-differenceWith f m1 m2- = differenceWithKey (\_ x y -> f x y) m1 m2---- | /O(n+m)/. Difference with a combining function. When two equal keys are--- encountered, the combining function is applied to the key and both values.--- If it returns 'Nothing', the element is discarded (proper set difference).--- If it returns (@'Just' y@), the element is updated with a new value @y@.------ > let f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--- > differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])--- > == singleton 3 "3:b|B"--differenceWithKey :: (Key -> a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a-differenceWithKey f m1 m2- = mergeWithKey f id (const Nil) m1 m2--{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}---- | /O(n+m)/. The intersection with a combining function.------ > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"--intersectionWith :: (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c-intersectionWith f m1 m2- = intersectionWithKey (\_ x y -> f x y) m1 m2---- | /O(n+m)/. The intersection with a combining function.------ > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"--intersectionWithKey :: (Key -> a -> b -> c) -> IntMap a -> IntMap b -> IntMap c-intersectionWithKey f m1 m2- = mergeWithKey' bin (\(Tip k1 x1) (Tip _k2 x2) -> Tip k1 $! f k1 x1 x2) (const Nil) (const Nil) m1 m2--{--------------------------------------------------------------------- MergeWithKey---------------------------------------------------------------------}---- | /O(n+m)/. A high-performance universal combining function. Using--- 'mergeWithKey', all combining functions can be defined without any loss of--- efficiency (with exception of 'union', 'difference' and 'intersection',--- where sharing of some nodes is lost with 'mergeWithKey').------ Please make sure you know what is going on when using 'mergeWithKey',--- otherwise you can be surprised by unexpected code growth or even--- corruption of the data structure.------ When 'mergeWithKey' is given three arguments, it is inlined to the call--- site. You should therefore use 'mergeWithKey' only to define your custom--- combining functions. For example, you could define 'unionWithKey',--- 'differenceWithKey' and 'intersectionWithKey' as------ > myUnionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) id id m1 m2--- > myDifferenceWithKey f m1 m2 = mergeWithKey f id (const empty) m1 m2--- > myIntersectionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) (const empty) (const empty) m1 m2------ When calling @'mergeWithKey' combine only1 only2@, a function combining two--- 'IntMap's is created, such that------ * if a key is present in both maps, it is passed with both corresponding--- values to the @combine@ function. Depending on the result, the key is either--- present in the result with specified value, or is left out;------ * a nonempty subtree present only in the first map is passed to @only1@ and--- the output is added to the result;------ * a nonempty subtree present only in the second map is passed to @only2@ and--- the output is added to the result.------ The @only1@ and @only2@ methods /must return a map with a subset (possibly empty) of the keys of the given map/.--- The values can be modified arbitrarily. Most common variants of @only1@ and--- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@ or--- @'filterWithKey' f@ could be used for any @f@.--mergeWithKey :: (Key -> a -> b -> Maybe c) -> (IntMap a -> IntMap c) -> (IntMap b -> IntMap c)- -> IntMap a -> IntMap b -> IntMap c-mergeWithKey f g1 g2 = mergeWithKey' bin combine g1 g2- where -- We use the lambda form to avoid non-exhaustive pattern matches warning.- combine = \(Tip k1 x1) (Tip _k2 x2) -> case f k1 x1 x2 of Nothing -> Nil- Just x -> x `seq` Tip k1 x- {-# INLINE combine #-}-{-# INLINE mergeWithKey #-}--{--------------------------------------------------------------------- Min\/Max---------------------------------------------------------------------}---- | /O(log n)/. Update the value at the minimal key.------ > updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"3:b"), (5,"a")]--- > updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMinWithKey :: (Key -> a -> Maybe a) -> IntMap a -> IntMap a-updateMinWithKey f t =- case t of Bin p m l r | m < 0 -> bin p m l (go f r)- _ -> go f t- where- go f' (Bin p m l r) = bin p m (go f' l) r- go f' (Tip k y) = case f' k y of- Just y' -> y' `seq` Tip k y'- Nothing -> Nil- go _ Nil = error "updateMinWithKey Nil"---- | /O(log n)/. Update the value at the maximal key.------ > updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"b"), (5,"5:a")]--- > updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMaxWithKey :: (Key -> a -> Maybe a) -> IntMap a -> IntMap a-updateMaxWithKey f t =- case t of Bin p m l r | m < 0 -> bin p m (go f l) r- _ -> go f t- where- go f' (Bin p m l r) = bin p m l (go f' r)- go f' (Tip k y) = case f' k y of- Just y' -> y' `seq` Tip k y'- Nothing -> Nil- go _ Nil = error "updateMaxWithKey Nil"---- | /O(log n)/. Update the value at the maximal key.------ > updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "Xa")]--- > updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMax :: (a -> Maybe a) -> IntMap a -> IntMap a-updateMax f = updateMaxWithKey (const f)---- | /O(log n)/. Update the value at the minimal key.------ > updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "Xb"), (5, "a")]--- > updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMin :: (a -> Maybe a) -> IntMap a -> IntMap a-updateMin f = updateMinWithKey (const f)---{--------------------------------------------------------------------- Mapping---------------------------------------------------------------------}--- | /O(n)/. Map a function over all values in the map.------ > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]--map :: (a -> b) -> IntMap a -> IntMap b-map f t- = case t of- Bin p m l r -> Bin p m (map f l) (map f r)- Tip k x -> Tip k $! f x- Nil -> Nil---- | /O(n)/. Map a function over all values in the map.------ > let f key x = (show key) ++ ":" ++ x--- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]--mapWithKey :: (Key -> a -> b) -> IntMap a -> IntMap b-mapWithKey f t- = case t of- Bin p m l r -> Bin p m (mapWithKey f l) (mapWithKey f r)- Tip k x -> Tip k $! f k x- Nil -> Nil---- | /O(n)/. The function @'mapAccum'@ threads an accumulating--- argument through the map in ascending order of keys.------ > let f a b = (a ++ b, b ++ "X")--- > mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) == ("Everything: ba", fromList [(3, "bX"), (5, "aX")])--mapAccum :: (a -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccum f = mapAccumWithKey (\a' _ x -> f a' x)---- | /O(n)/. The function @'mapAccumWithKey'@ threads an accumulating--- argument through the map in ascending order of keys.------ > let f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--- > mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) == ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])--mapAccumWithKey :: (a -> Key -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccumWithKey f a t- = mapAccumL f a t---- | /O(n)/. The function @'mapAccumL'@ threads an accumulating--- argument through the map in ascending order of keys. Strict in--- the accumulating argument and the both elements of the--- result of the function.-mapAccumL :: (a -> Key -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccumL f a t- = case t of- Bin p m l r -> let (a1,l') = mapAccumL f a l- (a2,r') = mapAccumL f a1 r- in (a2 `strictPair` Bin p m l' r')- Tip k x -> let (a',x') = f a k x in x' `seq` (a' `strictPair` Tip k x')- Nil -> (a `strictPair` Nil)---- | /O(n)/. The function @'mapAccumR'@ threads an accumulating--- argument through the map in descending order of keys.-mapAccumRWithKey :: (a -> Key -> b -> (a,c)) -> a -> IntMap b -> (a,IntMap c)-mapAccumRWithKey f a t- = case t of- Bin p m l r -> let (a1,r') = mapAccumRWithKey f a r- (a2,l') = mapAccumRWithKey f a1 l- in (a2 `strictPair` Bin p m l' r')- Tip k x -> let (a',x') = f a k x in x' `seq` (a' `strictPair` Tip k x')- Nil -> (a `strictPair` Nil)---- | /O(n*log n)/.--- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the associated values will be--- combined using @c@.------ > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"--- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"--mapKeysWith :: (a -> a -> a) -> (Key->Key) -> IntMap a -> IntMap a-mapKeysWith c f = fromListWith c . foldrWithKey (\k x xs -> (f k, x) : xs) []--{--------------------------------------------------------------------- Filter---------------------------------------------------------------------}--- | /O(n)/. Map values and collect the 'Just' results.------ > let f x = if x == "a" then Just "new a" else Nothing--- > mapMaybe f (fromList [(5,"a"), (3,"b")]) == singleton 5 "new a"--mapMaybe :: (a -> Maybe b) -> IntMap a -> IntMap b-mapMaybe f = mapMaybeWithKey (\_ x -> f x)---- | /O(n)/. Map keys\/values and collect the 'Just' results.------ > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"--mapMaybeWithKey :: (Key -> a -> Maybe b) -> IntMap a -> IntMap b-mapMaybeWithKey f (Bin p m l r)- = bin p m (mapMaybeWithKey f l) (mapMaybeWithKey f r)-mapMaybeWithKey f (Tip k x) = case f k x of- Just y -> y `seq` Tip k y- Nothing -> Nil-mapMaybeWithKey _ Nil = Nil---- | /O(n)/. Map values and separate the 'Left' and 'Right' results.------ > let f a = if a < "c" then Left a else Right a--- > mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])--- >--- > mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--mapEither :: (a -> Either b c) -> IntMap a -> (IntMap b, IntMap c)-mapEither f m- = mapEitherWithKey (\_ x -> f x) m---- | /O(n)/. Map keys\/values and separate the 'Left' and 'Right' results.------ > let f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--- > mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])--- >--- > mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])--mapEitherWithKey :: (Key -> a -> Either b c) -> IntMap a -> (IntMap b, IntMap c)-mapEitherWithKey f (Bin p m l r)- = bin p m l1 r1 `strictPair` bin p m l2 r2- where- (l1,l2) = mapEitherWithKey f l- (r1,r2) = mapEitherWithKey f r-mapEitherWithKey f (Tip k x) = case f k x of- Left y -> y `seq` (Tip k y, Nil)- Right z -> z `seq` (Nil, Tip k z)-mapEitherWithKey _ Nil = (Nil, Nil)--{--------------------------------------------------------------------- Conversions---------------------------------------------------------------------}---- | /O(n)/. Build a map from a set of keys and a function which for each key--- computes its value.------ > fromSet (\k -> replicate k 'a') (Data.IntSet.fromList [3, 5]) == fromList [(5,"aaaaa"), (3,"aaa")]--- > fromSet undefined Data.IntSet.empty == empty--fromSet :: (Key -> a) -> IntSet.IntSet -> IntMap a-fromSet _ IntSet.Nil = Nil-fromSet f (IntSet.Bin p m l r) = Bin p m (fromSet f l) (fromSet f r)-fromSet f (IntSet.Tip kx bm) = buildTree f kx bm (IntSet.suffixBitMask + 1)- where -- This is slightly complicated, as we to convert the dense- -- representation of IntSet into tree representation of IntMap.- --- -- We are given a nonzero bit mask 'bmask' of 'bits' bits with prefix 'prefix'.- -- We split bmask into halves corresponding to left and right subtree.- -- If they are both nonempty, we create a Bin node, otherwise exactly- -- one of them is nonempty and we construct the IntMap from that half.- buildTree g prefix bmask bits = prefix `seq` bmask `seq` case bits of- 0 -> Tip prefix $! g prefix- _ -> case intFromNat ((natFromInt bits) `shiftRL` 1) of- bits2 | bmask .&. ((1 `shiftLL` bits2) - 1) == 0 ->- buildTree g (prefix + bits2) (bmask `shiftRL` bits2) bits2- | (bmask `shiftRL` bits2) .&. ((1 `shiftLL` bits2) - 1) == 0 ->- buildTree g prefix bmask bits2- | otherwise ->- Bin prefix bits2 (buildTree g prefix bmask bits2) (buildTree g (prefix + bits2) (bmask `shiftRL` bits2) bits2)--{--------------------------------------------------------------------- Lists---------------------------------------------------------------------}--- | /O(n*min(n,W))/. Create a map from a list of key\/value pairs.------ > fromList [] == empty--- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]--- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]--fromList :: [(Key,a)] -> IntMap a-fromList xs- = foldlStrict ins empty xs- where- ins t (k,x) = insert k x t---- | /O(n*min(n,W))/. Create a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "ab"), (5, "aba")]--- > fromListWith (++) [] == empty--fromListWith :: (a -> a -> a) -> [(Key,a)] -> IntMap a-fromListWith f xs- = fromListWithKey (\_ x y -> f x y) xs---- | /O(n*min(n,W))/. Build a map from a list of key\/value pairs with a combining function. See also fromAscListWithKey'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "ab"), (5, "aba")]--- > fromListWith (++) [] == empty--fromListWithKey :: (Key -> a -> a -> a) -> [(Key,a)] -> IntMap a-fromListWithKey f xs- = foldlStrict ins empty xs- where- ins t (k,x) = insertWithKey f k x t---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order.------ > fromAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]--fromAscList :: [(Key,a)] -> IntMap a-fromAscList xs- = fromAscListWithKey (\_ x _ -> x) xs---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order, with a combining function on equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--fromAscListWith :: (a -> a -> a) -> [(Key,a)] -> IntMap a-fromAscListWith f xs- = fromAscListWithKey (\_ x y -> f x y) xs---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order, with a combining function on equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--fromAscListWithKey :: (Key -> a -> a -> a) -> [(Key,a)] -> IntMap a-fromAscListWithKey _ [] = Nil-fromAscListWithKey f (x0 : xs0) = fromDistinctAscList (combineEq x0 xs0)- where- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]- combineEq z [] = [z]- combineEq z@(kz,zz) (x@(kx,xx):xs)- | kx==kz = let yy = f kx xx zz in yy `seq` combineEq (kx,yy) xs- | otherwise = z:combineEq x xs---- | /O(n)/. Build a map from a list of key\/value pairs where--- the keys are in ascending order and all distinct.--- /The precondition (input list is strictly ascending) is not checked./------ > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--fromDistinctAscList :: [(Key,a)] -> IntMap a-fromDistinctAscList [] = Nil-fromDistinctAscList (z0 : zs0) = work z0 zs0 Nada- where- work (kx,vx) [] stk = vx `seq` finish kx (Tip kx vx) stk- work (kx,vx) (z@(kz,_):zs) stk = vx `seq` reduce z zs (branchMask kx kz) kx (Tip kx vx) stk-- reduce :: (Key,a) -> [(Key,a)] -> Mask -> Prefix -> IntMap a -> Stack a -> IntMap a- reduce z zs _ px tx Nada = work z zs (Push px tx Nada)- reduce z zs m px tx stk@(Push py ty stk') =- let mxy = branchMask px py- pxy = mask px mxy- in if shorter m mxy- then reduce z zs m pxy (Bin pxy mxy ty tx) stk'- else work z zs (Push px tx stk)-- finish _ t Nada = t- finish px tx (Push py ty stk) = finish p (join py ty px tx) stk- where m = branchMask px py- p = mask px m--data Stack a = Push {-# UNPACK #-} !Prefix !(IntMap a) !(Stack a) | Nada
@@ -1,148 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Safe #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.IntSet--- Copyright : (c) Daan Leijen 2002--- (c) Joachim Breitner 2011--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of integer sets.------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.IntSet (IntSet)--- > import qualified Data.IntSet as IntSet------ The implementation is based on /big-endian patricia trees/. This data--- structure performs especially well on binary operations like 'union'--- and 'intersection'. However, my benchmarks show that it is also--- (much) faster on insertions and deletions when compared to a generic--- size-balanced set implementation (see "Data.Set").------ * Chris Okasaki and Andy Gill, \"/Fast Mergeable Integer Maps/\",--- Workshop on ML, September 1998, pages 77-86,--- <http://citeseer.ist.psu.edu/okasaki98fast.html>------ * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve--- Information Coded In Alphanumeric/\", Journal of the ACM, 15(4),--- October 1968, pages 514-534.------ Additionally, this implementation places bitmaps in the leaves of the tree.--- Their size is the natural size of a machine word (32 or 64 bits) and greatly--- reduce memory footprint and execution times for dense sets, e.g. sets where--- it is likely that many values lie close to each other. The asymptotics are--- not affected by this optimization.------ Many operations have a worst-case complexity of /O(min(n,W))/.--- This means that the operation can become linear in the number of--- elements with a maximum of /W/ -- the number of bits in an 'Int'--- (32 or 64).--------------------------------------------------------------------------------module Data.IntSet (- -- * Strictness properties- -- $strictness-- -- * Set type-#if !defined(TESTING)- IntSet -- instance Eq,Show-#else- IntSet(..) -- instance Eq,Show-#endif-- -- * Operators- , (\\)-- -- * Query- , IS.null- , size- , member- , notMember- , lookupLT- , lookupGT- , lookupLE- , lookupGE- , isSubsetOf- , isProperSubsetOf-- -- * Construction- , empty- , singleton- , insert- , delete-- -- * Combine- , union- , unions- , difference- , intersection-- -- * Filter- , IS.filter- , partition- , split- , splitMember-- -- * Map- , IS.map-- -- * Folds- , IS.foldr- , IS.foldl- -- ** Strict folds- , foldr'- , foldl'- -- ** Legacy folds- , fold-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , maxView- , minView-- -- * Conversion-- -- ** List- , elems- , toList- , fromList-- -- ** Ordered list- , toAscList- , toDescList- , fromAscList- , fromDistinctAscList-- -- * Debugging- , showTree- , showTreeWith--#if defined(TESTING)- -- * Internals- , match-#endif- ) where--import Data.IntSet.Base as IS---- $strictness------ This module satisfies the following strictness property:------ * Key arguments are evaluated to WHNF------ Here are some examples that illustrate the property:------ > delete undefined s == undefined
@@ -1,1485 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE MagicHash, BangPatterns, DeriveDataTypeable, StandaloneDeriving #-}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.IntSet.Base--- Copyright : (c) Daan Leijen 2002--- (c) Joachim Breitner 2011--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of integer sets.------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.IntSet (IntSet)--- > import qualified Data.IntSet as IntSet------ The implementation is based on /big-endian patricia trees/. This data--- structure performs especially well on binary operations like 'union'--- and 'intersection'. However, my benchmarks show that it is also--- (much) faster on insertions and deletions when compared to a generic--- size-balanced set implementation (see "Data.Set").------ * Chris Okasaki and Andy Gill, \"/Fast Mergeable Integer Maps/\",--- Workshop on ML, September 1998, pages 77-86,--- <http://citeseer.ist.psu.edu/okasaki98fast.html>------ * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve--- Information Coded In Alphanumeric/\", Journal of the ACM, 15(4),--- October 1968, pages 514-534.------ Additionally, this implementation places bitmaps in the leaves of the tree.--- Their size is the natural size of a machine word (32 or 64 bits) and greatly--- reduce memory footprint and execution times for dense sets, e.g. sets where--- it is likely that many values lie close to each other. The asymptotics are--- not affected by this optimization.------ Many operations have a worst-case complexity of /O(min(n,W))/.--- This means that the operation can become linear in the number of--- elements with a maximum of /W/ -- the number of bits in an 'Int'--- (32 or 64).---------------------------------------------------------------------------------- [Note: INLINE bit fiddling]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~--- It is essential that the bit fiddling functions like mask, zero, branchMask--- etc are inlined. If they do not, the memory allocation skyrockets. The GHC--- usually gets it right, but it is disastrous if it does not. Therefore we--- explicitly mark these functions INLINE.----- [Note: Local 'go' functions and capturing]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- Care must be taken when using 'go' function which captures an argument.--- Sometimes (for example when the argument is passed to a data constructor,--- as in insert), GHC heap-allocates more than necessary. Therefore C-- code--- must be checked for increased allocation when creating and modifying such--- functions.----- [Note: Order of constructors]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- The order of constructors of IntSet matters when considering performance.--- Currently in GHC 7.0, when type has 3 constructors, they are matched from--- the first to the last -- the best performance is achieved when the--- constructors are ordered by frequency.--- On GHC 7.0, reordering constructors from Nil | Tip | Bin to Bin | Tip | Nil--- improves the benchmark by circa 10%.--module Data.IntSet.Base (- -- * Set type- IntSet(..) -- instance Eq,Show-- -- * Operators- , (\\)-- -- * Query- , null- , size- , member- , notMember- , lookupLT- , lookupGT- , lookupLE- , lookupGE- , isSubsetOf- , isProperSubsetOf-- -- * Construction- , empty- , singleton- , insert- , delete-- -- * Combine- , union- , unions- , difference- , intersection-- -- * Filter- , filter- , partition- , split- , splitMember-- -- * Map- , map-- -- * Folds- , foldr- , foldl- -- ** Strict folds- , foldr'- , foldl'- -- ** Legacy folds- , fold-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , maxView- , minView-- -- * Conversion-- -- ** List- , elems- , toList- , fromList-- -- ** Ordered list- , toAscList- , toDescList- , fromAscList- , fromDistinctAscList-- -- * Debugging- , showTree- , showTreeWith-- -- * Internals- , match- , suffixBitMask- , prefixBitMask- , bitmapOf- ) where---import Prelude hiding (filter,foldr,foldl,null,map)-import Data.Bits--import qualified Data.List as List-import Data.Monoid (Monoid(..))-import Data.Maybe (fromMaybe)-import Data.Typeable-import Control.DeepSeq (NFData)--#if __GLASGOW_HASKELL__-import Text.Read-import Data.Data (Data(..), mkNoRepType)-#endif--#if __GLASGOW_HASKELL__-import GHC.Exts ( Word(..), Int(..), build )-import GHC.Prim ( uncheckedShiftL#, uncheckedShiftRL#, indexInt8OffAddr# )-#else-import Data.Word-#endif---- On GHC, include MachDeps.h to get WORD_SIZE_IN_BITS macro.-#if defined(__GLASGOW_HASKELL__)-#include "MachDeps.h"-#endif---- Use macros to define strictness of functions.--- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.--- We do not use BangPatterns, because they are not in any standard and we--- want the compilers to be compiled by as many compilers as possible.-#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined-#define STRICT_2_OF_2(fn) fn _ arg | arg `seq` False = undefined-#define STRICT_1_OF_3(fn) fn arg _ _ | arg `seq` False = undefined-#define STRICT_2_OF_3(fn) fn _ arg _ | arg `seq` False = undefined--infixl 9 \\{-This comment teaches CPP correct behaviour -}---- A "Nat" is a natural machine word (an unsigned Int)-type Nat = Word--natFromInt :: Int -> Nat-natFromInt i = fromIntegral i-{-# INLINE natFromInt #-}--intFromNat :: Nat -> Int-intFromNat w = fromIntegral w-{-# INLINE intFromNat #-}---- Right and left logical shifts.-shiftRL, shiftLL :: Nat -> Int -> Nat-#if __GLASGOW_HASKELL__-{--------------------------------------------------------------------- GHC: use unboxing to get @shiftRL@ and @shiftLL@ inlined.---------------------------------------------------------------------}-shiftRL (W# x) (I# i) = W# (uncheckedShiftRL# x i)-shiftLL (W# x) (I# i) = W# (uncheckedShiftL# x i)-#else-shiftRL x i = shiftR x i-shiftLL x i = shiftL x i-#endif-{-# INLINE shiftRL #-}-{-# INLINE shiftLL #-}--{--------------------------------------------------------------------- Operators---------------------------------------------------------------------}--- | /O(n+m)/. See 'difference'.-(\\) :: IntSet -> IntSet -> IntSet-m1 \\ m2 = difference m1 m2--{--------------------------------------------------------------------- Types---------------------------------------------------------------------}---- | A set of integers.---- See Note: Order of constructors-data IntSet = Bin {-# UNPACK #-} !Prefix {-# UNPACK #-} !Mask !IntSet !IntSet--- Invariant: Nil is never found as a child of Bin.--- Invariant: The Mask is a power of 2. It is the largest bit position at which--- two elements of the set differ.--- Invariant: Prefix is the common high-order bits that all elements share to--- the left of the Mask bit.--- Invariant: In Bin prefix mask left right, left consists of the elements that--- don't have the mask bit set; right is all the elements that do.- | Tip {-# UNPACK #-} !Prefix {-# UNPACK #-} !BitMap--- Invariant: The Prefix is zero for all but the last 5 (on 32 bit arches) or 6--- bits (on 64 bit arches). The values of the map represented by a tip--- are the prefix plus the indices of the set bits in the bit map.- | Nil---- A number stored in a set is stored as--- * Prefix (all but last 5-6 bits) and--- * BitMap (last 5-6 bits stored as a bitmask)--- Last 5-6 bits are called a Suffix.--type Prefix = Int-type Mask = Int-type BitMap = Word--instance Monoid IntSet where- mempty = empty- mappend = union- mconcat = unions--#if __GLASGOW_HASKELL__--{--------------------------------------------------------------------- A Data instance---------------------------------------------------------------------}---- This instance preserves data abstraction at the cost of inefficiency.--- We omit reflection services for the sake of data abstraction.--instance Data IntSet where- gfoldl f z is = z fromList `f` (toList is)- toConstr _ = error "toConstr"- gunfold _ _ = error "gunfold"- dataTypeOf _ = mkNoRepType "Data.IntSet.IntSet"--#endif--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}--- | /O(1)/. Is the set empty?-null :: IntSet -> Bool-null Nil = True-null _ = False-{-# INLINE null #-}---- | /O(n)/. Cardinality of the set.-size :: IntSet -> Int-size t- = case t of- Bin _ _ l r -> size l + size r- Tip _ bm -> bitcount 0 bm- Nil -> 0---- | /O(min(n,W))/. Is the value a member of the set?---- See Note: Local 'go' functions and capturing]-member :: Int -> IntSet -> Bool-member x = x `seq` go- where- go (Bin p m l r)- | nomatch x p m = False- | zero x m = go l- | otherwise = go r- go (Tip y bm) = prefixOf x == y && bitmapOf x .&. bm /= 0- go Nil = False---- | /O(min(n,W))/. Is the element not in the set?-notMember :: Int -> IntSet -> Bool-notMember k = not . member k---- | /O(log n)/. Find largest element smaller than the given one.------ > lookupLT 3 (fromList [3, 5]) == Nothing--- > lookupLT 5 (fromList [3, 5]) == Just 3---- See Note: Local 'go' functions and capturing.-lookupLT :: Int -> IntSet -> Maybe Int-lookupLT x t = x `seq` case t of- Bin _ m l r | m < 0 -> if x >= 0 then go r l else go Nil r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMax def else unsafeFindMax r- | zero x m = go def l- | otherwise = go l r- go def (Tip kx bm) | prefixOf x > kx = Just $ kx + highestBitSet bm- | prefixOf x == kx && maskLT /= 0 = Just $ kx + highestBitSet maskLT- | otherwise = unsafeFindMax def- where maskLT = (bitmapOf x - 1) .&. bm- go def Nil = unsafeFindMax def----- | /O(log n)/. Find smallest element greater than the given one.------ > lookupGT 4 (fromList [3, 5]) == Just 5--- > lookupGT 5 (fromList [3, 5]) == Nothing---- See Note: Local 'go' functions and capturing.-lookupGT :: Int -> IntSet -> Maybe Int-lookupGT x t = x `seq` case t of- Bin _ m l r | m < 0 -> if x >= 0 then go Nil l else go l r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMin l else unsafeFindMin def- | zero x m = go r l- | otherwise = go def r- go def (Tip kx bm) | prefixOf x < kx = Just $ kx + lowestBitSet bm- | prefixOf x == kx && maskGT /= 0 = Just $ kx + lowestBitSet maskGT- | otherwise = unsafeFindMin def- where maskGT = (- ((bitmapOf x) `shiftLL` 1)) .&. bm- go def Nil = unsafeFindMin def----- | /O(log n)/. Find largest element smaller or equal to the given one.------ > lookupLE 2 (fromList [3, 5]) == Nothing--- > lookupLE 4 (fromList [3, 5]) == Just 3--- > lookupLE 5 (fromList [3, 5]) == Just 5---- See Note: Local 'go' functions and capturing.-lookupLE :: Int -> IntSet -> Maybe Int-lookupLE x t = x `seq` case t of- Bin _ m l r | m < 0 -> if x >= 0 then go r l else go Nil r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMax def else unsafeFindMax r- | zero x m = go def l- | otherwise = go l r- go def (Tip kx bm) | prefixOf x > kx = Just $ kx + highestBitSet bm- | prefixOf x == kx && maskLE /= 0 = Just $ kx + highestBitSet maskLE- | otherwise = unsafeFindMax def- where maskLE = (((bitmapOf x) `shiftLL` 1) - 1) .&. bm- go def Nil = unsafeFindMax def----- | /O(log n)/. Find smallest element greater or equal to the given one.------ > lookupGE 3 (fromList [3, 5]) == Just 3--- > lookupGE 4 (fromList [3, 5]) == Just 5--- > lookupGE 6 (fromList [3, 5]) == Nothing---- See Note: Local 'go' functions and capturing.-lookupGE :: Int -> IntSet -> Maybe Int-lookupGE x t = x `seq` case t of- Bin _ m l r | m < 0 -> if x >= 0 then go Nil l else go l r- _ -> go Nil t- where- go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMin l else unsafeFindMin def- | zero x m = go r l- | otherwise = go def r- go def (Tip kx bm) | prefixOf x < kx = Just $ kx + lowestBitSet bm- | prefixOf x == kx && maskGE /= 0 = Just $ kx + lowestBitSet maskGE- | otherwise = unsafeFindMin def- where maskGE = (- (bitmapOf x)) .&. bm- go def Nil = unsafeFindMin def------ Helper function for lookupGE and lookupGT. It assumes that if a Bin node is--- given, it has m > 0.-unsafeFindMin :: IntSet -> Maybe Int-unsafeFindMin Nil = Nothing-unsafeFindMin (Tip kx bm) = Just $ kx + lowestBitSet bm-unsafeFindMin (Bin _ _ l _) = unsafeFindMin l---- Helper function for lookupLE and lookupLT. It assumes that if a Bin node is--- given, it has m > 0.-unsafeFindMax :: IntSet -> Maybe Int-unsafeFindMax Nil = Nothing-unsafeFindMax (Tip kx bm) = Just $ kx + highestBitSet bm-unsafeFindMax (Bin _ _ _ r) = unsafeFindMax r--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. The empty set.-empty :: IntSet-empty- = Nil-{-# INLINE empty #-}---- | /O(1)/. A set of one element.-singleton :: Int -> IntSet-singleton x- = Tip (prefixOf x) (bitmapOf x)-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insert---------------------------------------------------------------------}--- | /O(min(n,W))/. Add a value to the set. There is no left- or right bias for--- IntSets.-insert :: Int -> IntSet -> IntSet-insert x = x `seq` insertBM (prefixOf x) (bitmapOf x)---- Helper function for insert and union.-insertBM :: Prefix -> BitMap -> IntSet -> IntSet-insertBM kx bm t = kx `seq` bm `seq`- case t of- Bin p m l r- | nomatch kx p m -> join kx (Tip kx bm) p t- | zero kx m -> Bin p m (insertBM kx bm l) r- | otherwise -> Bin p m l (insertBM kx bm r)- Tip kx' bm'- | kx' == kx -> Tip kx' (bm .|. bm')- | otherwise -> join kx (Tip kx bm) kx' t- Nil -> Tip kx bm---- | /O(min(n,W))/. Delete a value in the set. Returns the--- original set when the value was not present.-delete :: Int -> IntSet -> IntSet-delete x = x `seq` deleteBM (prefixOf x) (bitmapOf x)---- Deletes all values mentioned in the BitMap from the set.--- Helper function for delete and difference.-deleteBM :: Prefix -> BitMap -> IntSet -> IntSet-deleteBM kx bm t = kx `seq` bm `seq`- case t of- Bin p m l r- | nomatch kx p m -> t- | zero kx m -> bin p m (deleteBM kx bm l) r- | otherwise -> bin p m l (deleteBM kx bm r)- Tip kx' bm'- | kx' == kx -> tip kx (bm' .&. complement bm)- | otherwise -> t- Nil -> Nil---{--------------------------------------------------------------------- Union---------------------------------------------------------------------}--- | The union of a list of sets.-unions :: [IntSet] -> IntSet-unions xs- = foldlStrict union empty xs----- | /O(n+m)/. The union of two sets.-union :: IntSet -> IntSet -> IntSet-union t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)- | shorter m1 m2 = union1- | shorter m2 m1 = union2- | p1 == p2 = Bin p1 m1 (union l1 l2) (union r1 r2)- | otherwise = join p1 t1 p2 t2- where- union1 | nomatch p2 p1 m1 = join p1 t1 p2 t2- | zero p2 m1 = Bin p1 m1 (union l1 t2) r1- | otherwise = Bin p1 m1 l1 (union r1 t2)-- union2 | nomatch p1 p2 m2 = join p1 t1 p2 t2- | zero p1 m2 = Bin p2 m2 (union t1 l2) r2- | otherwise = Bin p2 m2 l2 (union t1 r2)--union t@(Bin _ _ _ _) (Tip kx bm) = insertBM kx bm t-union t@(Bin _ _ _ _) Nil = t-union (Tip kx bm) t = insertBM kx bm t-union Nil t = t---{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}--- | /O(n+m)/. Difference between two sets.-difference :: IntSet -> IntSet -> IntSet-difference t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)- | shorter m1 m2 = difference1- | shorter m2 m1 = difference2- | p1 == p2 = bin p1 m1 (difference l1 l2) (difference r1 r2)- | otherwise = t1- where- difference1 | nomatch p2 p1 m1 = t1- | zero p2 m1 = bin p1 m1 (difference l1 t2) r1- | otherwise = bin p1 m1 l1 (difference r1 t2)-- difference2 | nomatch p1 p2 m2 = t1- | zero p1 m2 = difference t1 l2- | otherwise = difference t1 r2--difference t@(Bin _ _ _ _) (Tip kx bm) = deleteBM kx bm t-difference t@(Bin _ _ _ _) Nil = t--difference t1@(Tip kx bm) t2 = differenceTip t2- where differenceTip (Bin p2 m2 l2 r2) | nomatch kx p2 m2 = t1- | zero kx m2 = differenceTip l2- | otherwise = differenceTip r2- differenceTip (Tip kx2 bm2) | kx == kx2 = tip kx (bm .&. complement bm2)- | otherwise = t1- differenceTip Nil = t1--difference Nil _ = Nil----{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}--- | /O(n+m)/. The intersection of two sets.-intersection :: IntSet -> IntSet -> IntSet-intersection t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)- | shorter m1 m2 = intersection1- | shorter m2 m1 = intersection2- | p1 == p2 = bin p1 m1 (intersection l1 l2) (intersection r1 r2)- | otherwise = Nil- where- intersection1 | nomatch p2 p1 m1 = Nil- | zero p2 m1 = intersection l1 t2- | otherwise = intersection r1 t2-- intersection2 | nomatch p1 p2 m2 = Nil- | zero p1 m2 = intersection t1 l2- | otherwise = intersection t1 r2--intersection t1@(Bin _ _ _ _) (Tip kx2 bm2) = intersectBM t1- where intersectBM (Bin p1 m1 l1 r1) | nomatch kx2 p1 m1 = Nil- | zero kx2 m1 = intersectBM l1- | otherwise = intersectBM r1- intersectBM (Tip kx1 bm1) | kx1 == kx2 = tip kx1 (bm1 .&. bm2)- | otherwise = Nil- intersectBM Nil = Nil--intersection (Bin _ _ _ _) Nil = Nil--intersection (Tip kx1 bm1) t2 = intersectBM t2- where intersectBM (Bin p2 m2 l2 r2) | nomatch kx1 p2 m2 = Nil- | zero kx1 m2 = intersectBM l2- | otherwise = intersectBM r2- intersectBM (Tip kx2 bm2) | kx1 == kx2 = tip kx1 (bm1 .&. bm2)- | otherwise = Nil- intersectBM Nil = Nil--intersection Nil _ = Nil--{--------------------------------------------------------------------- Subset---------------------------------------------------------------------}--- | /O(n+m)/. Is this a proper subset? (ie. a subset but not equal).-isProperSubsetOf :: IntSet -> IntSet -> Bool-isProperSubsetOf t1 t2- = case subsetCmp t1 t2 of- LT -> True- _ -> False--subsetCmp :: IntSet -> IntSet -> Ordering-subsetCmp t1@(Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- | shorter m1 m2 = GT- | shorter m2 m1 = case subsetCmpLt of- GT -> GT- _ -> LT- | p1 == p2 = subsetCmpEq- | otherwise = GT -- disjoint- where- subsetCmpLt | nomatch p1 p2 m2 = GT- | zero p1 m2 = subsetCmp t1 l2- | otherwise = subsetCmp t1 r2- subsetCmpEq = case (subsetCmp l1 l2, subsetCmp r1 r2) of- (GT,_ ) -> GT- (_ ,GT) -> GT- (EQ,EQ) -> EQ- _ -> LT--subsetCmp (Bin _ _ _ _) _ = GT-subsetCmp (Tip kx1 bm1) (Tip kx2 bm2)- | kx1 /= kx2 = GT -- disjoint- | bm1 == bm2 = EQ- | bm1 .&. complement bm2 == 0 = LT- | otherwise = GT-subsetCmp t1@(Tip kx _) (Bin p m l r)- | nomatch kx p m = GT- | zero kx m = case subsetCmp t1 l of GT -> GT ; _ -> LT- | otherwise = case subsetCmp t1 r of GT -> GT ; _ -> LT-subsetCmp (Tip _ _) Nil = GT -- disjoint-subsetCmp Nil Nil = EQ-subsetCmp Nil _ = LT---- | /O(n+m)/. Is this a subset?--- @(s1 `isSubsetOf` s2)@ tells whether @s1@ is a subset of @s2@.--isSubsetOf :: IntSet -> IntSet -> Bool-isSubsetOf t1@(Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- | shorter m1 m2 = False- | shorter m2 m1 = match p1 p2 m2 && (if zero p1 m2 then isSubsetOf t1 l2- else isSubsetOf t1 r2)- | otherwise = (p1==p2) && isSubsetOf l1 l2 && isSubsetOf r1 r2-isSubsetOf (Bin _ _ _ _) _ = False-isSubsetOf (Tip kx1 bm1) (Tip kx2 bm2) = kx1 == kx2 && bm1 .&. complement bm2 == 0-isSubsetOf t1@(Tip kx _) (Bin p m l r)- | nomatch kx p m = False- | zero kx m = isSubsetOf t1 l- | otherwise = isSubsetOf t1 r-isSubsetOf (Tip _ _) Nil = False-isSubsetOf Nil _ = True---{--------------------------------------------------------------------- Filter---------------------------------------------------------------------}--- | /O(n)/. Filter all elements that satisfy some predicate.-filter :: (Int -> Bool) -> IntSet -> IntSet-filter predicate t- = case t of- Bin p m l r- -> bin p m (filter predicate l) (filter predicate r)- Tip kx bm- -> tip kx (foldl'Bits 0 (bitPred kx) 0 bm)- Nil -> Nil- where bitPred kx bm bi | predicate (kx + bi) = bm .|. bitmapOfSuffix bi- | otherwise = bm- {-# INLINE bitPred #-}---- | /O(n)/. partition the set according to some predicate.-partition :: (Int -> Bool) -> IntSet -> (IntSet,IntSet)-partition predicate t- = case t of- Bin p m l r- -> let (l1,l2) = partition predicate l- (r1,r2) = partition predicate r- in (bin p m l1 r1, bin p m l2 r2)- Tip kx bm- -> let bm1 = foldl'Bits 0 (bitPred kx) 0 bm- in (tip kx bm1, tip kx (bm `xor` bm1))- Nil -> (Nil,Nil)- where bitPred kx bm bi | predicate (kx + bi) = bm .|. bitmapOfSuffix bi- | otherwise = bm- {-# INLINE bitPred #-}----- | /O(min(n,W))/. The expression (@'split' x set@) is a pair @(set1,set2)@--- where @set1@ comprises the elements of @set@ less than @x@ and @set2@--- comprises the elements of @set@ greater than @x@.------ > split 3 (fromList [1..5]) == (fromList [1,2], fromList [4,5])-split :: Int -> IntSet -> (IntSet,IntSet)-split x t =- case t of Bin _ m l r | m < 0 -> if x >= 0 then case go x l of (lt, gt) -> (union lt r, gt)- else case go x r of (lt, gt) -> (lt, union gt l)- _ -> go x t- where- go x' t'@(Bin p m l r) | match x' p m = if zero x' m then case go x' l of (lt, gt) -> (lt, union gt r)- else case go x' r of (lt, gt) -> (union lt l, gt)- | otherwise = if x' < p then (Nil, t')- else (t', Nil)- go x' t'@(Tip kx' bm) | kx' > x' = (Nil, t')- -- equivalent to kx' > prefixOf x'- | kx' < prefixOf x' = (t', Nil)- | otherwise = (tip kx' (bm .&. lowerBitmap), tip kx' (bm .&. higherBitmap))- where lowerBitmap = bitmapOf x' - 1- higherBitmap = complement (lowerBitmap + bitmapOf x')- go _ Nil = (Nil, Nil)---- | /O(min(n,W))/. Performs a 'split' but also returns whether the pivot--- element was found in the original set.-splitMember :: Int -> IntSet -> (IntSet,Bool,IntSet)-splitMember x t =- case t of Bin _ m l r | m < 0 -> if x >= 0 then case go x l of (lt, fnd, gt) -> (union lt r, fnd, gt)- else case go x r of (lt, fnd, gt) -> (lt, fnd, union gt l)- _ -> go x t- where- go x' t'@(Bin p m l r) | match x' p m = if zero x' m then case go x' l of (lt, fnd, gt) -> (lt, fnd, union gt r)- else case go x' r of (lt, fnd, gt) -> (union lt l, fnd, gt)- | otherwise = if x' < p then (Nil, False, t')- else (t', False, Nil)- go x' t'@(Tip kx' bm) | kx' > x' = (Nil, False, t')- -- equivalent to kx' > prefixOf x'- | kx' < prefixOf x' = (t', False, Nil)- | otherwise = (tip kx' (bm .&. lowerBitmap), (bm .&. bitmapOfx') /= 0, tip kx' (bm .&. higherBitmap))- where bitmapOfx' = bitmapOf x'- lowerBitmap = bitmapOfx' - 1- higherBitmap = complement (lowerBitmap + bitmapOfx')- go _ Nil = (Nil, False, Nil)---{----------------------------------------------------------------------- Min/Max-----------------------------------------------------------------------}---- | /O(min(n,W))/. Retrieves the maximal key of the set, and the set--- stripped of that element, or 'Nothing' if passed an empty set.-maxView :: IntSet -> Maybe (Int, IntSet)-maxView t =- case t of Nil -> Nothing- Bin p m l r | m < 0 -> case go l of (result, l') -> Just (result, bin p m l' r)- _ -> Just (go t)- where- go (Bin p m l r) = case go r of (result, r') -> (result, bin p m l r')- go (Tip kx bm) = case highestBitSet bm of bi -> (kx + bi, tip kx (bm .&. complement (bitmapOfSuffix bi)))- go Nil = error "maxView Nil"---- | /O(min(n,W))/. Retrieves the minimal key of the set, and the set--- stripped of that element, or 'Nothing' if passed an empty set.-minView :: IntSet -> Maybe (Int, IntSet)-minView t =- case t of Nil -> Nothing- Bin p m l r | m < 0 -> case go r of (result, r') -> Just (result, bin p m l r')- _ -> Just (go t)- where- go (Bin p m l r) = case go l of (result, l') -> (result, bin p m l' r)- go (Tip kx bm) = case lowestBitSet bm of bi -> (kx + bi, tip kx (bm .&. complement (bitmapOfSuffix bi)))- go Nil = error "minView Nil"---- | /O(min(n,W))/. Delete and find the minimal element.------ > deleteFindMin set = (findMin set, deleteMin set)-deleteFindMin :: IntSet -> (Int, IntSet)-deleteFindMin = fromMaybe (error "deleteFindMin: empty set has no minimal element") . minView---- | /O(min(n,W))/. Delete and find the maximal element.------ > deleteFindMax set = (findMax set, deleteMax set)-deleteFindMax :: IntSet -> (Int, IntSet)-deleteFindMax = fromMaybe (error "deleteFindMax: empty set has no maximal element") . maxView----- | /O(min(n,W))/. The minimal element of the set.-findMin :: IntSet -> Int-findMin Nil = error "findMin: empty set has no minimal element"-findMin (Tip kx bm) = kx + lowestBitSet bm-findMin (Bin _ m l r)- | m < 0 = find r- | otherwise = find l- where find (Tip kx bm) = kx + lowestBitSet bm- find (Bin _ _ l' _) = find l'- find Nil = error "findMin Nil"---- | /O(min(n,W))/. The maximal element of a set.-findMax :: IntSet -> Int-findMax Nil = error "findMax: empty set has no maximal element"-findMax (Tip kx bm) = kx + highestBitSet bm-findMax (Bin _ m l r)- | m < 0 = find l- | otherwise = find r- where find (Tip kx bm) = kx + highestBitSet bm- find (Bin _ _ _ r') = find r'- find Nil = error "findMax Nil"----- | /O(min(n,W))/. Delete the minimal element.-deleteMin :: IntSet -> IntSet-deleteMin = maybe Nil snd . minView---- | /O(min(n,W))/. Delete the maximal element.-deleteMax :: IntSet -> IntSet-deleteMax = maybe Nil snd . maxView--{----------------------------------------------------------------------- Map-----------------------------------------------------------------------}---- | /O(n*min(n,W))/.--- @'map' f s@ is the set obtained by applying @f@ to each element of @s@.------ It's worth noting that the size of the result may be smaller if,--- for some @(x,y)@, @x \/= y && f x == f y@--map :: (Int->Int) -> IntSet -> IntSet-map f = fromList . List.map f . toList--{--------------------------------------------------------------------- Fold---------------------------------------------------------------------}--- | /O(n)/. Fold the elements in the set using the given right-associative--- binary operator. This function is an equivalent of 'foldr' and is present--- for compatibility only.------ /Please note that fold will be deprecated in the future and removed./-fold :: (Int -> b -> b) -> b -> IntSet -> b-fold = foldr-{-# INLINE fold #-}---- | /O(n)/. Fold the elements in the set using the given right-associative--- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'toAscList'@.------ For example,------ > toAscList set = foldr (:) [] set-foldr :: (Int -> b -> b) -> b -> IntSet -> b-foldr f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z l) r -- put negative numbers before- | otherwise -> go (go z r) l- _ -> go z t- where- go z' Nil = z'- go z' (Tip kx bm) = foldrBits kx f z' bm- go z' (Bin _ _ l r) = go (go z' r) l-{-# INLINE foldr #-}---- | /O(n)/. A strict version of 'foldr'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldr' :: (Int -> b -> b) -> b -> IntSet -> b-foldr' f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z l) r -- put negative numbers before- | otherwise -> go (go z r) l- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip kx bm) = foldr'Bits kx f z' bm- go z' (Bin _ _ l r) = go (go z' r) l-{-# INLINE foldr' #-}---- | /O(n)/. Fold the elements in the set using the given left-associative--- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'toAscList'@.------ For example,------ > toDescList set = foldl (flip (:)) [] set-foldl :: (a -> Int -> a) -> a -> IntSet -> a-foldl f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z r) l -- put negative numbers before- | otherwise -> go (go z l) r- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip kx bm) = foldlBits kx f z' bm- go z' (Bin _ _ l r) = go (go z' l) r-{-# INLINE foldl #-}---- | /O(n)/. A strict version of 'foldl'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldl' :: (a -> Int -> a) -> a -> IntSet -> a-foldl' f z = \t -> -- Use lambda t to be inlinable with two arguments only.- case t of Bin _ m l r | m < 0 -> go (go z r) l -- put negative numbers before- | otherwise -> go (go z l) r- _ -> go z t- where- STRICT_1_OF_2(go)- go z' Nil = z'- go z' (Tip kx bm) = foldl'Bits kx f z' bm- go z' (Bin _ _ l r) = go (go z' l) r-{-# INLINE foldl' #-}--{--------------------------------------------------------------------- List variations---------------------------------------------------------------------}--- | /O(n)/. An alias of 'toAscList'. The elements of a set in ascending order.--- Subject to list fusion.-elems :: IntSet -> [Int]-elems- = toAscList--{--------------------------------------------------------------------- Lists---------------------------------------------------------------------}--- | /O(n)/. Convert the set to a list of elements. Subject to list fusion.-toList :: IntSet -> [Int]-toList- = toAscList---- | /O(n)/. Convert the set to an ascending list of elements. Subject to list--- fusion.-toAscList :: IntSet -> [Int]-toAscList = foldr (:) []---- | /O(n)/. Convert the set to a descending list of elements. Subject to list--- fusion.-toDescList :: IntSet -> [Int]-toDescList = foldl (flip (:)) []---- List fusion for the list generating functions.-#if __GLASGOW_HASKELL__--- The foldrFB and foldlFB are foldr and foldl equivalents, used for list fusion.--- They are important to convert unfused to{Asc,Desc}List back, see mapFB in prelude.-foldrFB :: (Int -> b -> b) -> b -> IntSet -> b-foldrFB = foldr-{-# INLINE[0] foldrFB #-}-foldlFB :: (a -> Int -> a) -> a -> IntSet -> a-foldlFB = foldl-{-# INLINE[0] foldlFB #-}---- Inline elems and toList, so that we need to fuse only toAscList.-{-# INLINE elems #-}-{-# INLINE toList #-}---- The fusion is enabled up to phase 2 included. If it does not succeed,--- convert in phase 1 the expanded to{Asc,Desc}List calls back to--- to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were used in--- a list fusion, otherwise it would go away in phase 1), and let compiler do--- whatever it wants with to{Asc,Desc}List -- it was forbidden to inline it--- before phase 0, otherwise the fusion rules would not fire at all.-{-# NOINLINE[0] toAscList #-}-{-# NOINLINE[0] toDescList #-}-{-# RULES "IntSet.toAscList" [~1] forall s . toAscList s = build (\c n -> foldrFB c n s) #-}-{-# RULES "IntSet.toAscListBack" [1] foldrFB (:) [] = toAscList #-}-{-# RULES "IntSet.toDescList" [~1] forall s . toDescList s = build (\c n -> foldlFB (\xs x -> c x xs) n s) #-}-{-# RULES "IntSet.toDescListBack" [1] foldlFB (\xs x -> x : xs) [] = toDescList #-}-#endif----- | /O(n*min(n,W))/. Create a set from a list of integers.-fromList :: [Int] -> IntSet-fromList xs- = foldlStrict ins empty xs- where- ins t x = insert x t---- | /O(n)/. Build a set from an ascending list of elements.--- /The precondition (input list is ascending) is not checked./-fromAscList :: [Int] -> IntSet-fromAscList [] = Nil-fromAscList (x0 : xs0) = fromDistinctAscList (combineEq x0 xs0)- where- combineEq x' [] = [x']- combineEq x' (x:xs)- | x==x' = combineEq x' xs- | otherwise = x' : combineEq x xs---- | /O(n)/. Build a set from an ascending list of distinct elements.--- /The precondition (input list is strictly ascending) is not checked./-fromDistinctAscList :: [Int] -> IntSet-fromDistinctAscList [] = Nil-fromDistinctAscList (z0 : zs0) = work (prefixOf z0) (bitmapOf z0) zs0 Nada- where- -- 'work' accumulates all values that go into one tip, before passing this Tip- -- to 'reduce'- work kx bm [] stk = finish kx (Tip kx bm) stk- work kx bm (z:zs) stk | kx == prefixOf z = work kx (bm .|. bitmapOf z) zs stk- work kx bm (z:zs) stk = reduce z zs (branchMask z kx) kx (Tip kx bm) stk-- reduce z zs _ px tx Nada = work (prefixOf z) (bitmapOf z) zs (Push px tx Nada)- reduce z zs m px tx stk@(Push py ty stk') =- let mxy = branchMask px py- pxy = mask px mxy- in if shorter m mxy- then reduce z zs m pxy (Bin pxy mxy ty tx) stk'- else work (prefixOf z) (bitmapOf z) zs (Push px tx stk)-- finish _ t Nada = t- finish px tx (Push py ty stk) = finish p (join py ty px tx) stk- where m = branchMask px py- p = mask px m--data Stack = Push {-# UNPACK #-} !Prefix !IntSet !Stack | Nada---{--------------------------------------------------------------------- Eq---------------------------------------------------------------------}-instance Eq IntSet where- t1 == t2 = equal t1 t2- t1 /= t2 = nequal t1 t2--equal :: IntSet -> IntSet -> Bool-equal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- = (m1 == m2) && (p1 == p2) && (equal l1 l2) && (equal r1 r2)-equal (Tip kx1 bm1) (Tip kx2 bm2)- = kx1 == kx2 && bm1 == bm2-equal Nil Nil = True-equal _ _ = False--nequal :: IntSet -> IntSet -> Bool-nequal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)- = (m1 /= m2) || (p1 /= p2) || (nequal l1 l2) || (nequal r1 r2)-nequal (Tip kx1 bm1) (Tip kx2 bm2)- = kx1 /= kx2 || bm1 /= bm2-nequal Nil Nil = False-nequal _ _ = True--{--------------------------------------------------------------------- Ord---------------------------------------------------------------------}--instance Ord IntSet where- compare s1 s2 = compare (toAscList s1) (toAscList s2)- -- tentative implementation. See if more efficient exists.--{--------------------------------------------------------------------- Show---------------------------------------------------------------------}-instance Show IntSet where- showsPrec p xs = showParen (p > 10) $- showString "fromList " . shows (toList xs)--{--------------------------------------------------------------------- Read---------------------------------------------------------------------}-instance Read IntSet where-#ifdef __GLASGOW_HASKELL__- readPrec = parens $ prec 10 $ do- Ident "fromList" <- lexP- xs <- readPrec- return (fromList xs)-- readListPrec = readListPrecDefault-#else- readsPrec p = readParen (p > 10) $ \ r -> do- ("fromList",s) <- lex r- (xs,t) <- reads s- return (fromList xs,t)-#endif--{--------------------------------------------------------------------- Typeable---------------------------------------------------------------------}--#include "Typeable.h"-INSTANCE_TYPEABLE0(IntSet,intSetTc,"IntSet")--{--------------------------------------------------------------------- NFData---------------------------------------------------------------------}---- The IntSet constructors consist only of strict fields of Ints and--- IntSets, thus the default NFData instance which evaluates to whnf--- should suffice-instance NFData IntSet--{--------------------------------------------------------------------- Debugging---------------------------------------------------------------------}--- | /O(n)/. Show the tree that implements the set. The tree is shown--- in a compressed, hanging format.-showTree :: IntSet -> String-showTree s- = showTreeWith True False s---{- | /O(n)/. The expression (@'showTreeWith' hang wide map@) shows- the tree that implements the set. If @hang@ is- 'True', a /hanging/ tree is shown otherwise a rotated tree is shown. If- @wide@ is 'True', an extra wide version is shown.--}-showTreeWith :: Bool -> Bool -> IntSet -> String-showTreeWith hang wide t- | hang = (showsTreeHang wide [] t) ""- | otherwise = (showsTree wide [] [] t) ""--showsTree :: Bool -> [String] -> [String] -> IntSet -> ShowS-showsTree wide lbars rbars t- = case t of- Bin p m l r- -> showsTree wide (withBar rbars) (withEmpty rbars) r .- showWide wide rbars .- showsBars lbars . showString (showBin p m) . showString "\n" .- showWide wide lbars .- showsTree wide (withEmpty lbars) (withBar lbars) l- Tip kx bm- -> showsBars lbars . showString " " . shows kx . showString " + " .- showsBitMap bm . showString "\n"- Nil -> showsBars lbars . showString "|\n"--showsTreeHang :: Bool -> [String] -> IntSet -> ShowS-showsTreeHang wide bars t- = case t of- Bin p m l r- -> showsBars bars . showString (showBin p m) . showString "\n" .- showWide wide bars .- showsTreeHang wide (withBar bars) l .- showWide wide bars .- showsTreeHang wide (withEmpty bars) r- Tip kx bm- -> showsBars bars . showString " " . shows kx . showString " + " .- showsBitMap bm . showString "\n"- Nil -> showsBars bars . showString "|\n"--showBin :: Prefix -> Mask -> String-showBin _ _- = "*" -- ++ show (p,m)--showWide :: Bool -> [String] -> String -> String-showWide wide bars- | wide = showString (concat (reverse bars)) . showString "|\n"- | otherwise = id--showsBars :: [String] -> ShowS-showsBars bars- = case bars of- [] -> id- _ -> showString (concat (reverse (tail bars))) . showString node--showsBitMap :: Word -> ShowS-showsBitMap = showString . showBitMap--showBitMap :: Word -> String-showBitMap w = show $ foldrBits 0 (:) [] w--node :: String-node = "+--"--withBar, withEmpty :: [String] -> [String]-withBar bars = "| ":bars-withEmpty bars = " ":bars---{--------------------------------------------------------------------- Helpers---------------------------------------------------------------------}-{--------------------------------------------------------------------- Join---------------------------------------------------------------------}-join :: Prefix -> IntSet -> Prefix -> IntSet -> IntSet-join p1 t1 p2 t2- | zero p1 m = Bin p m t1 t2- | otherwise = Bin p m t2 t1- where- m = branchMask p1 p2- p = mask p1 m-{-# INLINE join #-}--{--------------------------------------------------------------------- @bin@ assures that we never have empty trees within a tree.---------------------------------------------------------------------}-bin :: Prefix -> Mask -> IntSet -> IntSet -> IntSet-bin _ _ l Nil = l-bin _ _ Nil r = r-bin p m l r = Bin p m l r-{-# INLINE bin #-}--{--------------------------------------------------------------------- @tip@ assures that we never have empty bitmaps within a tree.---------------------------------------------------------------------}-tip :: Prefix -> BitMap -> IntSet-tip _ 0 = Nil-tip kx bm = Tip kx bm-{-# INLINE tip #-}---{----------------------------------------------------------------------- Functions that generate Prefix and BitMap of a Key or a Suffix.-----------------------------------------------------------------------}--suffixBitMask :: Int-suffixBitMask = bitSize (undefined::Word) - 1-{-# INLINE suffixBitMask #-}--prefixBitMask :: Int-prefixBitMask = complement suffixBitMask-{-# INLINE prefixBitMask #-}--prefixOf :: Int -> Prefix-prefixOf x = x .&. prefixBitMask-{-# INLINE prefixOf #-}--suffixOf :: Int -> Int-suffixOf x = x .&. suffixBitMask-{-# INLINE suffixOf #-}--bitmapOfSuffix :: Int -> BitMap-bitmapOfSuffix s = 1 `shiftLL` s-{-# INLINE bitmapOfSuffix #-}--bitmapOf :: Int -> BitMap-bitmapOf x = bitmapOfSuffix (suffixOf x)-{-# INLINE bitmapOf #-}---{--------------------------------------------------------------------- Endian independent bit twiddling---------------------------------------------------------------------}-zero :: Int -> Mask -> Bool-zero i m- = (natFromInt i) .&. (natFromInt m) == 0-{-# INLINE zero #-}--nomatch,match :: Int -> Prefix -> Mask -> Bool-nomatch i p m- = (mask i m) /= p-{-# INLINE nomatch #-}--match i p m- = (mask i m) == p-{-# INLINE match #-}---- Suppose a is largest such that 2^a divides 2*m.--- Then mask i m is i with the low a bits zeroed out.-mask :: Int -> Mask -> Prefix-mask i m- = maskW (natFromInt i) (natFromInt m)-{-# INLINE mask #-}--{--------------------------------------------------------------------- Big endian operations---------------------------------------------------------------------}-maskW :: Nat -> Nat -> Prefix-maskW i m- = intFromNat (i .&. (complement (m-1) `xor` m))-{-# INLINE maskW #-}--shorter :: Mask -> Mask -> Bool-shorter m1 m2- = (natFromInt m1) > (natFromInt m2)-{-# INLINE shorter #-}--branchMask :: Prefix -> Prefix -> Mask-branchMask p1 p2- = intFromNat (highestBitMask (natFromInt p1 `xor` natFromInt p2))-{-# INLINE branchMask #-}--{----------------------------------------------------------------------- Finding the highest bit (mask) in a word [x] can be done efficiently in- three ways:- * convert to a floating point value and the mantissa tells us the- [log2(x)] that corresponds with the highest bit position. The mantissa- is retrieved either via the standard C function [frexp] or by some bit- twiddling on IEEE compatible numbers (float). Note that one needs to- use at least [double] precision for an accurate mantissa of 32 bit- numbers.- * use bit twiddling, a logarithmic sequence of bitwise or's and shifts (bit).- * use processor specific assembler instruction (asm).-- The most portable way would be [bit], but is it efficient enough?- I have measured the cycle counts of the different methods on an AMD- Athlon-XP 1800 (~ Pentium III 1.8Ghz) using the RDTSC instruction:-- highestBitMask: method cycles- --------------- frexp 200- float 33- bit 11- asm 12-- highestBit: method cycles- --------------- frexp 195- float 33- bit 11- asm 11-- Wow, the bit twiddling is on today's RISC like machines even faster- than a single CISC instruction (BSR)!-----------------------------------------------------------------------}--{----------------------------------------------------------------------- [highestBitMask] returns a word where only the highest bit is set.- It is found by first setting all bits in lower positions than the- highest bit and than taking an exclusive or with the original value.- Allthough the function may look expensive, GHC compiles this into- excellent C code that subsequently compiled into highly efficient- machine code. The algorithm is derived from Jorg Arndt's FXT library.-----------------------------------------------------------------------}-highestBitMask :: Nat -> Nat-highestBitMask x0- = case (x0 .|. shiftRL x0 1) of- x1 -> case (x1 .|. shiftRL x1 2) of- x2 -> case (x2 .|. shiftRL x2 4) of- x3 -> case (x3 .|. shiftRL x3 8) of- x4 -> case (x4 .|. shiftRL x4 16) of-#if !(defined(__GLASGOW_HASKELL__) && WORD_SIZE_IN_BITS==32)- x5 -> case (x5 .|. shiftRL x5 32) of -- for 64 bit platforms-#endif- x6 -> (x6 `xor` (shiftRL x6 1))-{-# INLINE highestBitMask #-}--{----------------------------------------------------------------------- To get best performance, we provide fast implementations of- lowestBitSet, highestBitSet and fold[lr][l]Bits for GHC.- If the intel bsf and bsr instructions ever become GHC primops,- this code should be reimplemented using these.-- Performance of this code is crucial for folds, toList, filter, partition.-- The signatures of methods in question are placed after this comment.-----------------------------------------------------------------------}--lowestBitSet :: Nat -> Int-highestBitSet :: Nat -> Int-foldlBits :: Int -> (a -> Int -> a) -> a -> Nat -> a-foldl'Bits :: Int -> (a -> Int -> a) -> a -> Nat -> a-foldrBits :: Int -> (Int -> a -> a) -> a -> Nat -> a-foldr'Bits :: Int -> (Int -> a -> a) -> a -> Nat -> a--{-# INLINE lowestBitSet #-}-{-# INLINE highestBitSet #-}-{-# INLINE foldlBits #-}-{-# INLINE foldl'Bits #-}-{-# INLINE foldrBits #-}-{-# INLINE foldr'Bits #-}--#if defined(__GLASGOW_HASKELL__) && (WORD_SIZE_IN_BITS==32 || WORD_SIZE_IN_BITS==64)-{----------------------------------------------------------------------- For lowestBitSet we use wordsize-dependant implementation based on- multiplication and DeBrujn indeces, which was proposed by Edward Kmett- <http://haskell.org/pipermail/libraries/2011-September/016749.html>-- The core of this implementation is fast indexOfTheOnlyBit,- which is given a Nat with exactly one bit set, and returns- its index.-- Lot of effort was put in these implementations, please benchmark carefully- before changing this code.-----------------------------------------------------------------------}--indexOfTheOnlyBit :: Nat -> Int-{-# INLINE indexOfTheOnlyBit #-}-indexOfTheOnlyBit bitmask =- I# (lsbArray `indexInt8OffAddr#` unboxInt (intFromNat ((bitmask * magic) `shiftRL` offset)))- where unboxInt (I# i) = i-#if WORD_SIZE_IN_BITS==32- magic = 0x077CB531- offset = 27- !lsbArray = "\0\1\28\2\29\14\24\3\30\22\20\15\25\17\4\8\31\27\13\23\21\19\16\7\26\12\18\6\11\5\10\9"#-#else- magic = 0x07EDD5E59A4E28C2- offset = 58- !lsbArray = "\63\0\58\1\59\47\53\2\60\39\48\27\54\33\42\3\61\51\37\40\49\18\28\20\55\30\34\11\43\14\22\4\62\57\46\52\38\26\32\41\50\36\17\19\29\10\13\21\56\45\25\31\35\16\9\12\44\24\15\8\23\7\6\5"#-#endif--- The lsbArray gets inlined to every call site of indexOfTheOnlyBit.--- That cannot be easily avoided, as GHC forbids top-level Addr# literal.--- One could go around that by supplying getLsbArray :: () -> Addr# marked--- as NOINLINE. But the code size of calling it and processing the result--- is 48B on 32-bit and 56B on 64-bit architectures -- so the 32B and 64B array--- is actually improvement on 32-bit and only a 8B size increase on 64-bit.--lowestBitMask :: Nat -> Nat-lowestBitMask x = x .&. negate x-{-# INLINE lowestBitMask #-}---- Reverse the order of bits in the Nat.-revNat :: Nat -> Nat-#if WORD_SIZE_IN_BITS==32-revNat x1 = case ((x1 `shiftRL` 1) .&. 0x55555555) .|. ((x1 .&. 0x55555555) `shiftLL` 1) of- x2 -> case ((x2 `shiftRL` 2) .&. 0x33333333) .|. ((x2 .&. 0x33333333) `shiftLL` 2) of- x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F) `shiftLL` 4) of- x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF) .|. ((x4 .&. 0x00FF00FF) `shiftLL` 8) of- x5 -> ( x5 `shiftRL` 16 ) .|. ( x5 `shiftLL` 16);-#else-revNat x1 = case ((x1 `shiftRL` 1) .&. 0x5555555555555555) .|. ((x1 .&. 0x5555555555555555) `shiftLL` 1) of- x2 -> case ((x2 `shiftRL` 2) .&. 0x3333333333333333) .|. ((x2 .&. 0x3333333333333333) `shiftLL` 2) of- x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F0F0F0F0F) `shiftLL` 4) of- x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF00FF00FF) .|. ((x4 .&. 0x00FF00FF00FF00FF) `shiftLL` 8) of- x5 -> case ((x5 `shiftRL` 16) .&. 0x0000FFFF0000FFFF) .|. ((x5 .&. 0x0000FFFF0000FFFF) `shiftLL` 16) of- x6 -> ( x6 `shiftRL` 32 ) .|. ( x6 `shiftLL` 32);-#endif--lowestBitSet x = indexOfTheOnlyBit (lowestBitMask x)--highestBitSet x = indexOfTheOnlyBit (highestBitMask x)--foldlBits prefix f z bitmap = go bitmap z- where go bm acc | bm == 0 = acc- | otherwise = case lowestBitMask bm of- bitmask -> bitmask `seq` case indexOfTheOnlyBit bitmask of- bi -> bi `seq` go (bm `xor` bitmask) ((f acc) $! (prefix+bi))--foldl'Bits prefix f z bitmap = go bitmap z- where STRICT_2_OF_2(go)- go bm acc | bm == 0 = acc- | otherwise = case lowestBitMask bm of- bitmask -> bitmask `seq` case indexOfTheOnlyBit bitmask of- bi -> bi `seq` go (bm `xor` bitmask) ((f acc) $! (prefix+bi))--foldrBits prefix f z bitmap = go (revNat bitmap) z- where go bm acc | bm == 0 = acc- | otherwise = case lowestBitMask bm of- bitmask -> bitmask `seq` case indexOfTheOnlyBit bitmask of- bi -> bi `seq` go (bm `xor` bitmask) ((f $! (prefix+(WORD_SIZE_IN_BITS-1)-bi)) acc)--foldr'Bits prefix f z bitmap = go (revNat bitmap) z- where STRICT_2_OF_2(go)- go bm acc | bm == 0 = acc- | otherwise = case lowestBitMask bm of- bitmask -> bitmask `seq` case indexOfTheOnlyBit bitmask of- bi -> bi `seq` go (bm `xor` bitmask) ((f $! (prefix+(WORD_SIZE_IN_BITS-1)-bi)) acc)--#else-{----------------------------------------------------------------------- In general case we use logarithmic implementation of- lowestBitSet and highestBitSet, which works up to bit sizes of 64.-- Folds are linear scans.-----------------------------------------------------------------------}--lowestBitSet n0 =- let (n1,b1) = if n0 .&. 0xFFFFFFFF /= 0 then (n0,0) else (n0 `shiftRL` 32, 32)- (n2,b2) = if n1 .&. 0xFFFF /= 0 then (n1,b1) else (n1 `shiftRL` 16, 16+b1)- (n3,b3) = if n2 .&. 0xFF /= 0 then (n2,b2) else (n2 `shiftRL` 8, 8+b2)- (n4,b4) = if n3 .&. 0xF /= 0 then (n3,b3) else (n3 `shiftRL` 4, 4+b3)- (n5,b5) = if n4 .&. 0x3 /= 0 then (n4,b4) else (n4 `shiftRL` 2, 2+b4)- b6 = if n5 .&. 0x1 /= 0 then b5 else 1+b5- in b6--highestBitSet n0 =- let (n1,b1) = if n0 .&. 0xFFFFFFFF00000000 /= 0 then (n0 `shiftRL` 32, 32) else (n0,0)- (n2,b2) = if n1 .&. 0xFFFF0000 /= 0 then (n1 `shiftRL` 16, 16+b1) else (n1,b1)- (n3,b3) = if n2 .&. 0xFF00 /= 0 then (n2 `shiftRL` 8, 8+b2) else (n2,b2)- (n4,b4) = if n3 .&. 0xF0 /= 0 then (n3 `shiftRL` 4, 4+b3) else (n3,b3)- (n5,b5) = if n4 .&. 0xC /= 0 then (n4 `shiftRL` 2, 2+b4) else (n4,b4)- b6 = if n5 .&. 0x2 /= 0 then 1+b5 else b5- in b6--foldlBits prefix f z bm = let lb = lowestBitSet bm- in go (prefix+lb) z (bm `shiftRL` lb)- where STRICT_1_OF_3(go)- go _ acc 0 = acc- go bi acc n | n `testBit` 0 = go (bi + 1) (f acc bi) (n `shiftRL` 1)- | otherwise = go (bi + 1) acc (n `shiftRL` 1)--foldl'Bits prefix f z bm = let lb = lowestBitSet bm- in go (prefix+lb) z (bm `shiftRL` lb)- where STRICT_1_OF_3(go)- STRICT_2_OF_3(go)- go _ acc 0 = acc- go bi acc n | n `testBit` 0 = go (bi + 1) (f acc bi) (n `shiftRL` 1)- | otherwise = go (bi + 1) acc (n `shiftRL` 1)--foldrBits prefix f z bm = let lb = lowestBitSet bm- in go (prefix+lb) (bm `shiftRL` lb)- where STRICT_1_OF_2(go)- go _ 0 = z- go bi n | n `testBit` 0 = f bi (go (bi + 1) (n `shiftRL` 1))- | otherwise = go (bi + 1) (n `shiftRL` 1)--foldr'Bits prefix f z bm = let lb = lowestBitSet bm- in go (prefix+lb) (bm `shiftRL` lb)- where STRICT_1_OF_2(go)- go _ 0 = z- go bi n | n `testBit` 0 = f bi $! go (bi + 1) (n `shiftRL` 1)- | otherwise = go (bi + 1) (n `shiftRL` 1)--#endif--{----------------------------------------------------------------------- [bitcount] as posted by David F. Place to haskell-cafe on April 11, 2006,- based on the code on- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan,- where the following source is given:- Published in 1988, the C Programming Language 2nd Ed. (by Brian W.- Kernighan and Dennis M. Ritchie) mentions this in exercise 2-9. On April- 19, 2006 Don Knuth pointed out to me that this method "was first published- by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by- Derrick Lehmer and published in 1964 in a book edited by Beckenbach.)"-----------------------------------------------------------------------}-bitcount :: Int -> Word -> Int-bitcount a0 x0 = go a0 x0- where go a 0 = a- go a x = go (a + 1) (x .&. (x-1))-{-# INLINE bitcount #-}---{--------------------------------------------------------------------- Utilities---------------------------------------------------------------------}-foldlStrict :: (a -> b -> a) -> a -> [b] -> a-foldlStrict f = go- where- go z [] = z- go z (x:xs) = let z' = f z x in z' `seq` go z' xs-{-# INLINE foldlStrict #-}
@@ -1,104 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Safe #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Map--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of ordered maps from keys to values--- (dictionaries).------ This module re-exports the value lazy 'Data.Map.Lazy' API, plus--- several value strict functions from 'Data.Map.Strict'.------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import qualified Data.Map as Map------ The implementation of 'Map' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'.------ Operation comments contain the operation time complexity in--- the Big-O notation (<http://en.wikipedia.org/wiki/Big_O_notation>).--------------------------------------------------------------------------------module Data.Map- ( module Data.Map.Lazy- , insertWith'- , insertWithKey'- , insertLookupWithKey'- , fold- , foldWithKey- ) where--import Data.Map.Lazy-import qualified Data.Map.Lazy as L-import qualified Data.Map.Strict as S---- | /Deprecated./ As of version 0.5, replaced by 'S.insertWith'.------ /O(log n)/. Same as 'insertWith', but the combining function is--- applied strictly. This is often the most desirable behavior.------ For example, to update a counter:------ > insertWith' (+) k 1 m----insertWith' :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWith' = S.insertWith-{-# INLINABLE insertWith' #-}---- | /Deprecated./ As of version 0.5, replaced by 'S.insertWithKey'.------ /O(log n)/. Same as 'insertWithKey', but the combining function is--- applied strictly.-insertWithKey' :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWithKey' = S.insertWithKey-{-# INLINABLE insertWithKey' #-}---- | /Deprecated./ As of version 0.5, replaced by--- 'S.insertLookupWithKey'.------ /O(log n)/. A strict version of 'insertLookupWithKey'.-insertLookupWithKey' :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a- -> (Maybe a, Map k a)-insertLookupWithKey' = S.insertLookupWithKey-{-# INLINABLE insertLookupWithKey' #-}---- | /Deprecated./ As of version 0.5, replaced by 'L.foldr'.------ /O(n)/. Fold the values in the map using the given right-associative--- binary operator. This function is an equivalent of 'foldr' and is present--- for compatibility only.-fold :: (a -> b -> b) -> b -> Map k a -> b-fold = L.foldr-{-# INLINE fold #-}---- | /Deprecated./ As of version 0.4, replaced by 'L.foldrWithKey'.------ /O(n)/. Fold the keys and values in the map using the given right-associative--- binary operator. This function is an equivalent of 'foldrWithKey' and is present--- for compatibility only.-foldWithKey :: (k -> a -> b -> b) -> b -> Map k a -> b-foldWithKey = foldrWithKey-{-# INLINE foldWithKey #-}
@@ -1,2992 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__--- LIQUID {- LANGUAGE DeriveDataTypeable, StandaloneDeriving -}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Map.Base--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from keys to values (dictionaries).------ Since many function names (but not the type name) clash with--- "Prelude" names, this module is usually imported @qualified@, e.g.------ > import Data.Map (Map)--- > import qualified Data.Map as Map------ The implementation of 'Map' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.---------------------------------------------------------------------------------- [Note: Using INLINABLE]--- ~~~~~~~~~~~~~~~~~~~~~~~--- It is crucial to the performance that the functions specialize on the Ord--- type when possible. GHC 7.0 and higher does this by itself when it sees th--- unfolding of a function -- that is why all public functions are marked--- INLINABLE (that exposes the unfolding).----- [Note: Using INLINE]--- ~~~~~~~~~~~~~~~~~~~~--- For other compilers and GHC pre 7.0, we mark some of the functions INLINE.--- We mark the functions that just navigate down the tree (lookup, insert,--- delete and similar). That navigation code gets inlined and thus specialized--- when possible. There is a price to pay -- code growth. The code INLINED is--- therefore only the tree navigation, all the real work (rebalancing) is not--- INLINED by using a NOINLINE.------ All methods marked INLINE have to be nonrecursive -- a 'go' function doing--- the real work is provided.----- [Note: Type of local 'go' function]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- If the local 'go' function uses an Ord class, it sometimes heap-allocates--- the Ord dictionary when the 'go' function does not have explicit type.--- In that case we give 'go' explicit type. But this slightly decrease--- performance, as the resulting 'go' function can float out to top level.----- [Note: Local 'go' functions and capturing]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- As opposed to IntMap, when 'go' function captures an argument, increased--- heap-allocation can occur: sometimes in a polymorphic function, the 'go'--- floats out of its enclosing function and then it heap-allocates the--- dictionary and the argument. Maybe it floats out too late and strictness--- analyzer cannot see that these could be passed on stack.------ For example, change 'member' so that its local 'go' function is not passing--- argument k and then look at the resulting code for hedgeInt.----- [Note: Order of constructors]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- The order of constructors of Map matters when considering performance.--- Currently in GHC 7.0, when type has 2 constructors, a forward conditional--- jump is made when successfully matching second constructor. Successful match--- of first constructor results in the forward jump not taken.--- On GHC 7.0, reordering constructors from Tip | Bin to Bin | Tip--- improves the benchmark by up to 10% on x86.--module Data.Map.Base (- -- * Map type- Map(..) -- instance Eq,Show,Read-- -- * Operators- , (!), (\\)-- -- * Query- , null- , size- , member- , notMember- , lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , map- , mapWithKey- -- LIQUID, traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , foldr- , foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- -- LIQUID, keysSet- -- LIQUID, fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Indexed- , lookupIndex- , findIndex- , elemAt- , updateAt- , deleteAt-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- , valid-- -- Used by the strict version- , bin- , balance- , balanced- , balanceL- , balanceR- , delta- , join- , merge- , glue- , trim- , trimLookupLo- , foldlStrict- , MaybeS(..)- , filterGt- , filterLt- ) where--import Prelude hiding (lookup,map,filter,foldr,foldl,null)--- LIQUID import qualified Data.Set.Base as Set--- LIQUID import Data.StrictPair-import Data.Monoid (Monoid(..))--- LIQUID import Control.Applicative (Applicative(..), (<$>))-import Data.Traversable (Traversable(traverse))-import qualified Data.Foldable as Foldable--- import Data.Typeable-import Control.DeepSeq (NFData(rnf))--#if __GLASGOW_HASKELL__-import GHC.Exts ( build )-import Text.Read-import Data.Data-#endif---- Use macros to define strictness of functions.--- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.--- We do not use BangPatterns, because they are not in any standard and we--- want the compilers to be compiled by as many compilers as possible.-#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined-#define STRICT_1_OF_3(fn) fn arg _ _ | arg `seq` False = undefined-#define STRICT_2_OF_3(fn) fn _ arg _ | arg `seq` False = undefined-#define STRICT_1_OF_4(fn) fn arg _ _ _ | arg `seq` False = undefined-#define STRICT_2_OF_4(fn) fn _ arg _ _ | arg `seq` False = undefined--{--------------------------------------------------------------------- Operators---------------------------------------------------------------------}-infixl 9 !,\\ ------ | /O(log n)/. Find the value at a key.--- Calls 'error' when the element can not be found.------ > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map--- > fromList [(5,'a'), (3,'b')] ! 5 == 'a'--(!) :: Ord k => Map k a -> k -> a-m ! k = find k m-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (!) #-}-#endif---- | Same as 'difference'.-(\\) :: Ord k => Map k a -> Map k b -> Map k a-m1 \\ m2 = difference m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (\\) #-}-#endif--{--------------------------------------------------------------------- Size balanced trees.---------------------------------------------------------------------}--- | A Map from keys @k@ to values @a@.---- See Note: Order of constructors-data Map k a = Bin Size k a (Map k a) (Map k a)- | Tip--type Size = Int--{-@ include <Base.hquals> @-}--{-@ - data Map k a <l :: root:k -> k -> Bool, r :: root:k -> k -> Bool>- = Bin (sz :: Size) - (key :: k) - (value :: a) - (left :: Map <l, r> (k <l key>) a) - (right :: Map <l, r> (k <r key>) a) - | Tip - @-}--{-@ type OMap k a = Map <{v:k | v < root}, {v:k | v > root}> k a @-}--{-@ measure isJustS :: forall a. MaybeS a -> Bool - isJustS (JustS x) = true- isJustS (NothingS) = false- @-}--{-@ measure fromJustS :: forall a. MaybeS a -> a - fromJustS (JustS x) = x - @-}--{-@ measure isBin :: Map k a -> Bool- isBin (Bin sz kx x l r) = true- isBin (Tip) = false- @-}--{-@ measure key :: Map k a -> k - key (Bin sz kx x l r) = kx - @-}----- LIQUID instance (Ord k) => Monoid (Map k v) where--- mempty = empty--- mappend = union--- mconcat = unions--#if __GLASGOW_HASKELL__--{--------------------------------------------------------------------- A Data instance---------------------------------------------------------------------}---- This instance preserves data abstraction at the cost of inefficiency.--- We omit reflection services for the sake of data abstraction.--- LIQUID instance (Data k, Data a, Ord k) => Data (Map k a) where--- LIQUID gfoldl f z m = z fromList `f` toList m--- LIQUID toConstr _ = error "toConstr"--- LIQUID gunfold _ _ = error "gunfold"--- LIQUID dataTypeOf _ = mkNoRepType "Data.Map.Map"--- LIQUID dataCast2 f = gcast2 f-#endif--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}--- | /O(1)/. Is the map empty?------ > Data.Map.null (empty) == True--- > Data.Map.null (singleton 1 'a') == False--null :: Map k a -> Bool-null Tip = True-null (Bin {}) = False-{-# INLINE null #-}---- | /O(1)/. The number of elements in the map.------ > size empty == 0--- > size (singleton 1 'a') == 1--- > size (fromList([(1,'a'), (2,'c'), (3,'b')])) == 3--size :: Map k a -> Int-size Tip = 0-size (Bin sz _ _ _ _) = sz-{-# INLINE size #-}----- | /O(log n)/. Lookup the value at a key in the map.------ The function will return the corresponding value as @('Just' value)@,--- or 'Nothing' if the key isn't in the map.------ An example of using @lookup@:------ > import Prelude hiding (lookup)--- > import Data.Map--- >--- > employeeDept = fromList([("John","Sales"), ("Bob","IT")])--- > deptCountry = fromList([("IT","USA"), ("Sales","France")])--- > countryCurrency = fromList([("USA", "Dollar"), ("France", "Euro")])--- >--- > employeeCurrency :: String -> Maybe String--- > employeeCurrency name = do--- > dept <- lookup name employeeDept--- > country <- lookup dept deptCountry--- > lookup country countryCurrency--- >--- > main = do--- > putStrLn $ "John's currency: " ++ (show (employeeCurrency "John"))--- > putStrLn $ "Pete's currency: " ++ (show (employeeCurrency "Pete"))------ The output of this program:------ > John's currency: Just "Euro"--- > Pete's currency: Nothing--{-@ assert lookup :: (Ord k) => k -> OMap k a -> Maybe a @-}-lookup :: Ord k => k -> Map k a -> Maybe a-lookup = go- where- STRICT_1_OF_2(go)- go _ Tip = Nothing- go k (Bin _ kx x l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> Just x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookup #-}-#else-{-# INLINE lookup #-}-#endif---- | /O(log n)/. Is the key a member of the map? See also 'notMember'.------ > member 5 (fromList [(5,'a'), (3,'b')]) == True--- > member 1 (fromList [(5,'a'), (3,'b')]) == False--{-@ assert member :: (Ord k) => k -> OMap k a -> Bool @-}-member :: Ord k => k -> Map k a -> Bool-member = go- where- STRICT_1_OF_2(go)- go _ Tip = False- go k (Bin _ kx _ l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> True-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE member #-}-#else-{-# INLINE member #-}-#endif---- | /O(log n)/. Is the key not a member of the map? See also 'member'.------ > notMember 5 (fromList [(5,'a'), (3,'b')]) == False--- > notMember 1 (fromList [(5,'a'), (3,'b')]) == True--{-@ assert notMember :: (Ord k) => k -> OMap k a -> Bool @-}-notMember :: Ord k => k -> Map k a -> Bool-notMember k m = not $ member k m-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE notMember #-}-#else-{-# INLINE notMember #-}-#endif---- | /O(log n)/. Find the value at a key.--- Calls 'error' when the element can not be found.--{-@ assert find :: (Ord k) => k -> OMap k a -> a @-}-find :: Ord k => k -> Map k a -> a-find = go- where- STRICT_1_OF_2(go)- go _ Tip = error "Map.!: given key is not an element in the map"- go k (Bin _ kx x l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE find #-}-#else-{-# INLINE find #-}-#endif---- | /O(log n)/. The expression @('findWithDefault' def k map)@ returns--- the value at key @k@ or returns default value @def@--- when the key is not in the map.------ > findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) == 'x'--- > findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) == 'a'--{-@ assert findWithDefault :: (Ord k) => a -> k -> OMap k a -> a @-}-findWithDefault :: Ord k => a -> k -> Map k a -> a-findWithDefault = go- where- STRICT_2_OF_3(go)- go def _ Tip = def- go def k (Bin _ kx x l r) = case compare k kx of- LT -> go def k l- GT -> go def k r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findWithDefault #-}-#else-{-# INLINE findWithDefault #-}-#endif---- | /O(log n)/. Find largest key smaller than the given one and return the--- corresponding (key, value) pair.------ > lookupLT 3 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLT 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')-{-@ assert lookupLT :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupLT :: Ord k => k -> Map k v -> Maybe (k, v)-lookupLT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) | k <= kx = goNothing k l- | otherwise = goJust k kx x r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) | k <= kx = goJust k kx' x' l- | otherwise = goJust k kx x r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLT #-}-#else-{-# INLINE lookupLT #-}-#endif---- | /O(log n)/. Find smallest key greater than the given one and return the--- corresponding (key, value) pair.------ > lookupGT 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGT 5 (fromList [(3,'a'), (5,'b')]) == Nothing-{-@ assert lookupGT :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupGT :: Ord k => k -> Map k v -> Maybe (k, v)-lookupGT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) | k < kx = goJust k kx x l- | otherwise = goNothing k r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) | k < kx = goJust k kx x l- | otherwise = goJust k kx' x' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGT #-}-#else-{-# INLINE lookupGT #-}-#endif---- | /O(log n)/. Find largest key smaller or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupLE 2 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLE 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupLE 5 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')-{-@ assert lookupLE :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupLE :: Ord k => k -> Map k v -> Maybe (k, v)-lookupLE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) = case compare k kx of LT -> goNothing k l- EQ -> Just (kx, x)- GT -> goJust k kx x r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx' x' l- EQ -> Just (kx, x)- GT -> goJust k kx x r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLE #-}-#else-{-# INLINE lookupLE #-}-#endif---- | /O(log n)/. Find smallest key greater or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupGE 3 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupGE 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGE 6 (fromList [(3,'a'), (5,'b')]) == Nothing-{-@ assert lookupLE :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupGE :: Ord k => k -> Map k v -> Maybe (k, v)-lookupGE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx x l- EQ -> Just (kx, x)- GT -> goNothing k r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx x l- EQ -> Just (kx, x)- GT -> goJust k kx' x' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGE #-}-#else-{-# INLINE lookupGE #-}-#endif--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. The empty map.------ > empty == fromList []--- > size empty == 0-{-@ assert empty :: OMap k a @-}-empty :: Map k a-empty = Tip-{-# INLINE empty #-}---- | /O(1)/. A map with a single element.------ > singleton 1 'a' == fromList [(1, 'a')]--- > size (singleton 1 'a') == 1--{-@ singleton :: k -> a -> OMap k a @-}-singleton :: k -> a -> Map k a-singleton k x = Bin 1 k x Tip Tip-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insertion---------------------------------------------------------------------}--- | /O(log n)/. Insert a new key and value in the map.--- If the key is already present in the map, the associated value is--- replaced with the supplied value. 'insert' is equivalent to--- @'insertWith' 'const'@.------ > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]--- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]--- > insert 5 'x' empty == singleton 5 'x'---- See Note: Type of local 'go' function-{-@ insert :: (Ord k) => k -> a -> OMap k a -> OMap k a @-}-insert :: Ord k => k -> a -> Map k a -> Map k a-insert = go- where- go :: Ord k => k -> a -> Map k a -> Map k a- STRICT_1_OF_3(go)- go kx x Tip = singleton kx x- go kx x (Bin sz ky y l r) =- case compare kx ky of- -- Bin ky y (go kx x l) r - LT -> balanceL ky y (go kx x l) r- GT -> balanceR ky y l (go kx x r)- EQ -> Bin sz kx x l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insert #-}-#else-{-# INLINE insert #-}-#endif---- Insert a new key and value in the map if it is not already present.--- Used by `union`.---- See Note: Type of local 'go' function-insertR :: Ord k => k -> a -> Map k a -> Map k a-insertR = go- where- go :: Ord k => k -> a -> Map k a -> Map k a- STRICT_1_OF_3(go)- go kx x Tip = singleton kx x- go kx x t@(Bin _ ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go kx x l) r- GT -> balanceR ky y l (go kx x r)- EQ -> t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertR #-}-#else-{-# INLINE insertR #-}-#endif---- | /O(log n)/. Insert with a function, combining new value and old value.--- @'insertWith' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key, f new_value old_value)@.------ > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]--- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"--{-@ assert insertWith :: (Ord k) => (a -> a -> a) -> k -> a -> OMap k a -> OMap k a @-}-insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWith f = insertWithKey (\_ x' y' -> f x' y')-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWith #-}-#else-{-# INLINE insertWith #-}-#endif---- | /O(log n)/. Insert with a function, combining key, new value and old value.--- @'insertWithKey' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key,f key new_value old_value)@.--- Note that the key passed to f is the same key passed to 'insertWithKey'.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]--- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"---- See Note: Type of local 'go' function--{-@ assert insertWithKey :: (Ord k) => (k -> a -> a -> a) -> k -> a -> OMap k a -> OMap k a @-}-insertWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWithKey = go- where- go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a- STRICT_2_OF_4(go)- go _ kx x Tip = singleton kx x- go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go f kx x l) r- GT -> balanceR ky y l (go f kx x r)- EQ -> Bin sy kx (f kx x y) l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWithKey #-}-#else-{-# INLINE insertWithKey #-}-#endif---- | /O(log n)/. Combines insert operation with old value retrieval.--- The expression (@'insertLookupWithKey' f k x map@)--- is a pair where the first element is equal to (@'lookup' k map@)--- and the second element equal to (@'insertWithKey' f k x map@).------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])--- > insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])--- > insertLookupWithKey f 5 "xxx" empty == (Nothing, singleton 5 "xxx")------ This is how to define @insertLookup@ using @insertLookupWithKey@:------ > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t--- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])--- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])---- See Note: Type of local 'go' function--{-@ assert insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> OMap k a -> (Maybe a, OMap k a) @-}-insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)-insertLookupWithKey = go- where- go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)- STRICT_2_OF_4(go)- go _ kx x Tip = (Nothing, singleton kx x)- go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> let (found, l') = go f kx x l- in (found, balanceL ky y l' r)- GT -> let (found, r') = go f kx x r- in (found, balanceR ky y l r')- EQ -> (Just y, Bin sy kx (f kx x y) l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertLookupWithKey #-}-#else-{-# INLINE insertLookupWithKey #-}-#endif--{--------------------------------------------------------------------- Deletion---------------------------------------------------------------------}--- | /O(log n)/. Delete a key and its value from the map. When the key is not--- a member of the map, the original map is returned.------ > delete 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > delete 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > delete 5 empty == empty---- See Note: Type of local 'go' function-{-@ assert delete :: (Ord k) => k -> OMap k a -> OMap k a @-}-delete :: Ord k => k -> Map k a -> Map k a-delete = go- where- go :: Ord k => k -> Map k a -> Map k a- STRICT_1_OF_2(go)- go _ Tip = Tip- go k (Bin _ kx x l r) =- case compare k kx of- LT -> balanceR kx x (go k l) r- GT -> balanceL kx x l (go k r)- EQ -> glue kx l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE delete #-}-#else-{-# INLINE delete #-}-#endif---- | /O(log n)/. Update a value at a specific key with the result of the provided function.--- When the key is not--- a member of the map, the original map is returned.------ > adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjust ("new " ++) 7 empty == empty--{-@ assert adjust :: (Ord k) => (a -> a) -> k -> OMap k a -> OMap k a @-}-adjust :: Ord k => (a -> a) -> k -> Map k a -> Map k a-adjust f = adjustWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjust #-}-#else-{-# INLINE adjust #-}-#endif---- | /O(log n)/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > let f key x = (show key) ++ ":new " ++ x--- > adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjustWithKey f 7 empty == empty--{-@ assert adjustWithKey :: (Ord k) => (k -> a -> a) -> k -> OMap k a -> OMap k a @-}-adjustWithKey :: Ord k => (k -> a -> a) -> k -> Map k a -> Map k a-adjustWithKey f = updateWithKey (\k' x' -> Just (f k' x'))-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjustWithKey #-}-#else-{-# INLINE adjustWithKey #-}-#endif---- | /O(log n)/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f x = if x == "a" then Just "new a" else Nothing--- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ update :: (Ord k) => (a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a-update f = updateWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE update #-}-#else-{-# INLINE update #-}-#endif---- | /O(log n)/. The expression (@'updateWithKey' f k map@) updates the--- value @x@ at @k@ (if it is in the map). If (@f k x@) is 'Nothing',--- the element is deleted. If it is (@'Just' y@), the key @k@ is bound--- to the new value @y@.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"---- See Note: Type of local 'go' function--{-@ updateWithKey :: (Ord k) => (k -> a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-updateWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a-updateWithKey = go- where- go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a- STRICT_2_OF_3(go)- go _ _ Tip = Tip- go f k(Bin sx kx x l r) =- case compare k kx of- LT -> balanceR kx x (go f k l) r- GT -> balanceL kx x l (go f k r)- EQ -> case f kx x of- Just x' -> Bin sx kx x' l r- Nothing -> glue kx l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateWithKey #-}-#else-{-# INLINE updateWithKey #-}-#endif---- | /O(log n)/. Lookup and update. See also 'updateWithKey'.--- The function returns changed value, if it is updated.--- Returns the original key value if the map entry is deleted.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) == (Just "5:new a", fromList [(3, "b"), (5, "5:new a")])--- > updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a")])--- > updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) == (Just "b", singleton 5 "a")---- See Note: Type of local 'go' function--{-@ updateLookupWithKey :: (Ord k) => (k -> a -> Maybe a) -> k -> OMap k a -> (Maybe a, OMap k a) @-}-updateLookupWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)-updateLookupWithKey = go- where- go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)- STRICT_2_OF_3(go)- go _ _ Tip = (Nothing,Tip)- go f k (Bin sx kx x l r) =- case compare k kx of- LT -> let (found,l') = go f k l in (found,balanceR kx x l' r)- GT -> let (found,r') = go f k r in (found,balanceL kx x l r')- EQ -> case f kx x of- Just x' -> (Just x',Bin sx kx x' l r)- Nothing -> (Just x,glue kx l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateLookupWithKey #-}-#else-{-# INLINE updateLookupWithKey #-}-#endif---- | /O(log n)/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.--- 'alter' can be used to insert, delete, or update a value in a 'Map'.--- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.------ > let f _ = Nothing--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- >--- > let f _ = Just "c"--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "c")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "c")]---- See Note: Type of local 'go' function--{-@ alter :: (Ord k) => (Maybe a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a-alter = go- where- go :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a- STRICT_2_OF_3(go)- go f k Tip = case f Nothing of- Nothing -> Tip- Just x -> singleton k x-- go f k (Bin sx kx x l r) = case compare k kx of- LT -> balance kx x (go f k l) r- GT -> balance kx x l (go f k r)- EQ -> case f (Just x) of- Just x' -> Bin sx kx x' l r- Nothing -> glue kx l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE alter #-}-#else-{-# INLINE alter #-}-#endif--{--------------------------------------------------------------------- Indexing---------------------------------------------------------------------}--- | /O(log n)/. Return the /index/ of a key. The index is a number from--- /0/ up to, but not including, the 'size' of the map. Calls 'error' when--- the key is not a 'member' of the map.------ > findIndex 2 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map--- > findIndex 3 (fromList [(5,"a"), (3,"b")]) == 0--- > findIndex 5 (fromList [(5,"a"), (3,"b")]) == 1--- > findIndex 6 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map---- See Note: Type of local 'go' function--{-@ findIndex :: (Ord k) => k -> OMap k a -> GHC.Types.Int @-}-findIndex :: Ord k => k -> Map k a -> Int-findIndex = go 0- where- go :: Ord k => Int -> k -> Map k a -> Int- STRICT_1_OF_3(go)- STRICT_2_OF_3(go)- go _ _ Tip = error "Map.findIndex: element is not in the map"- go idx k (Bin _ kx _ l r) = case compare k kx of- LT -> go idx k l- GT -> go (idx + size l + 1) k r- EQ -> idx + size l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findIndex #-}-#endif---- | /O(log n)/. Lookup the /index/ of a key. The index is a number from--- /0/ up to, but not including, the 'size' of the map.------ > isJust (lookupIndex 2 (fromList [(5,"a"), (3,"b")])) == False--- > fromJust (lookupIndex 3 (fromList [(5,"a"), (3,"b")])) == 0--- > fromJust (lookupIndex 5 (fromList [(5,"a"), (3,"b")])) == 1--- > isJust (lookupIndex 6 (fromList [(5,"a"), (3,"b")])) == False---- See Note: Type of local 'go' function-{-@ lookupIndex :: (Ord k) => k -> OMap k a -> Maybe GHC.Types.Int @-}-lookupIndex :: Ord k => k -> Map k a -> Maybe Int-lookupIndex = go 0- where- go :: Ord k => Int -> k -> Map k a -> Maybe Int- STRICT_1_OF_3(go)- STRICT_2_OF_3(go)- go _ _ Tip = Nothing- go idx k (Bin _ kx _ l r) = case compare k kx of- LT -> go idx k l- GT -> go (idx + size l + 1) k r- EQ -> Just $! idx + size l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupIndex #-}-#endif---- | /O(log n)/. Retrieve an element by /index/. Calls 'error' when an--- invalid index is used.------ > elemAt 0 (fromList [(5,"a"), (3,"b")]) == (3,"b")--- > elemAt 1 (fromList [(5,"a"), (3,"b")]) == (5, "a")--- > elemAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range---{-@ elemAt :: GHC.Types.Int -> OMap k a -> (k, a) @-}-elemAt :: Int -> Map k a -> (k,a)-STRICT_1_OF_2(elemAt)-elemAt _ Tip = error "Map.elemAt: index out of range"-elemAt i (Bin _ kx x l r)- = case compare i sizeL of- LT -> elemAt i l- GT -> elemAt (i-sizeL-1) r- EQ -> (kx,x)- where- sizeL = size l---- | /O(log n)/. Update the element at /index/. Calls 'error' when an--- invalid index is used.------ > updateAt (\ _ _ -> Just "x") 0 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "x"), (5, "a")]--- > updateAt (\ _ _ -> Just "x") 1 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "x")]--- > updateAt (\ _ _ -> Just "x") 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\ _ _ -> Just "x") (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > updateAt (\_ _ -> Nothing) 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--{-@ updateAt :: (k -> a -> Maybe a) -> GHC.Types.Int -> OMap k a -> OMap k a @-}-updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a-updateAt f i t = i `seq`- case t of- Tip -> error "Map.updateAt: index out of range"- Bin sx kx x l r -> case compare i sizeL of- LT -> balanceR kx x (updateAt f i l) r- GT -> balanceL kx x l (updateAt f (i-sizeL-1) r)- EQ -> case f kx x of- Just x' -> Bin sx kx x' l r- Nothing -> glue kx l r- where- sizeL = size l---- | /O(log n)/. Delete the element at /index/.--- Defined as (@'deleteAt' i map = 'updateAt' (\k x -> 'Nothing') i map@).------ > deleteAt 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > deleteAt 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > deleteAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > deleteAt (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--{-@ deleteAt :: GHC.Types.Int -> OMap k a -> OMap k a @-}-deleteAt :: Int -> Map k a -> Map k a-deleteAt i t = i `seq`- case t of- Tip -> error "Map.deleteAt: index out of range"- Bin _ kx x l r -> case compare i sizeL of- LT -> balanceR kx x (deleteAt i l) r- GT -> balanceL kx x l (deleteAt (i-sizeL-1) r)- EQ -> glue kx l r- where- sizeL = size l---{--------------------------------------------------------------------- Minimal, Maximal---------------------------------------------------------------------}--- | /O(log n)/. The minimal key of the map. Calls 'error' if the map is empty.------ > findMin (fromList [(5,"a"), (3,"b")]) == (3,"b")--- > findMin empty Error: empty map has no minimal element--{-@ findMin :: OMap k a -> (k, a) @-}-findMin :: Map k a -> (k,a)-findMin (Bin _ kx x Tip _) = (kx,x)-findMin (Bin _ _ _ l _) = findMin l-findMin Tip = error "Map.findMin: empty map has no minimal element"---- | /O(log n)/. The maximal key of the map. Calls 'error' if the map is empty.------ > findMax (fromList [(5,"a"), (3,"b")]) == (5,"a")--- > findMax empty Error: empty map has no maximal element--{-@ findMax :: OMap k a -> (k, a) @-}-findMax :: Map k a -> (k,a)-findMax (Bin _ kx x _ Tip) = (kx,x)-findMax (Bin _ _ _ _ r) = findMax r-findMax Tip = error "Map.findMax: empty map has no maximal element"---- | /O(log n)/. Delete the minimal key. Returns an empty map if the map is empty.------ > deleteMin (fromList [(5,"a"), (3,"b"), (7,"c")]) == fromList [(5,"a"), (7,"c")]--- > deleteMin empty == empty---{-@ deleteMin :: OMap k a -> OMap k a @-}-deleteMin :: Map k a -> Map k a-deleteMin (Bin _ _ _ Tip r) = r-deleteMin (Bin _ kx x l r) = balanceR kx x (deleteMin l) r-deleteMin Tip = Tip---- | /O(log n)/. Delete the maximal key. Returns an empty map if the map is empty.------ > deleteMax (fromList [(5,"a"), (3,"b"), (7,"c")]) == fromList [(3,"b"), (5,"a")]--- > deleteMax empty == empty--{-@ deleteMax :: OMap k a -> OMap k a @-}-deleteMax :: Map k a -> Map k a-deleteMax (Bin _ _ _ l Tip) = l-deleteMax (Bin _ kx x l r) = balanceL kx x l (deleteMax r)-deleteMax Tip = Tip---- | /O(log n)/. Update the value at the minimal key.------ > updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "Xb"), (5, "a")]--- > updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ updateMin :: (a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMin :: (a -> Maybe a) -> Map k a -> Map k a-updateMin f m- = updateMinWithKey (\_ x -> f x) m---- | /O(log n)/. Update the value at the maximal key.------ > updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "Xa")]--- > updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--{-@ updateMax :: (a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMax :: (a -> Maybe a) -> Map k a -> Map k a-updateMax f m- = updateMaxWithKey (\_ x -> f x) m----- | /O(log n)/. Update the value at the minimal key.------ > updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"3:b"), (5,"a")]--- > updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ updateMinWithKey :: (k -> a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMinWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMinWithKey _ Tip = Tip-updateMinWithKey f (Bin sx kx x Tip r) = case f kx x of- Nothing -> r- Just x' -> Bin sx kx x' Tip r-updateMinWithKey f (Bin _ kx x l r) = balanceR kx x (updateMinWithKey f l) r---- | /O(log n)/. Update the value at the maximal key.------ > updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"b"), (5,"5:a")]--- > updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--{-@ updateMaxWithKey :: (k -> a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMaxWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMaxWithKey _ Tip = Tip-updateMaxWithKey f (Bin sx kx x l Tip) = case f kx x of- Nothing -> l- Just x' -> Bin sx kx x' l Tip-updateMaxWithKey f (Bin _ kx x l r) = balanceL kx x l (updateMaxWithKey f r)---- | /O(log n)/. Retrieves the minimal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > minViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((3,"b"), singleton 5 "a")--- > minViewWithKey empty == Nothing--{-@ minViewWithKey :: OMap k a -> Maybe (k, a, OMap k a) @-}-minViewWithKey :: Map k a -> Maybe (k, a, Map k a)-minViewWithKey Tip = Nothing-minViewWithKey x = Just (deleteFindMin x)---- | /O(log n)/. Retrieves the maximal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > maxViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((5,"a"), singleton 3 "b")--- > maxViewWithKey empty == Nothing--{-@ maxViewWithKey :: OMap k a -> Maybe (k, a, OMap k a) @-}-maxViewWithKey :: Map k a -> Maybe (k, a, Map k a)-maxViewWithKey Tip = Nothing-maxViewWithKey x = Just (deleteFindMax x)---- | /O(log n)/. Retrieves the value associated with minimal key of the--- map, and the map stripped of that element, or 'Nothing' if passed an--- empty map.------ > minView (fromList [(5,"a"), (3,"b")]) == Just ("b", singleton 5 "a")--- > minView empty == Nothing--{-@ minView :: OMap k a -> Maybe (a, OMap k a) @-}-minView :: Map k a -> Maybe (a, Map k a)-minView Tip = Nothing-minView x = let (_, m, t) = deleteFindMin x in Just (m ,t) -- (first snd $ deleteFindMin x)---- | /O(log n)/. Retrieves the value associated with maximal key of the--- map, and the map stripped of that element, or 'Nothing' if passed an------ > maxView (fromList [(5,"a"), (3,"b")]) == Just ("a", singleton 3 "b")--- > maxView empty == Nothing--{-@ maxView :: OMap k a -> Maybe (a, OMap k a) @-}-maxView :: Map k a -> Maybe (a, Map k a)-maxView Tip = Nothing-maxView x = let (_, m, t) = deleteFindMax x in Just (m, t)---- Update the 1st component of a tuple (special case of Control.Arrow.first)-first :: (a -> b) -> (a, c) -> (b, c)-first f (x, y) = (f x, y)--{--------------------------------------------------------------------- Union.---------------------------------------------------------------------}--- | The union of a list of maps:--- (@'unions' == 'Prelude.foldl' 'union' 'empty'@).------ > unions [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "b"), (5, "a"), (7, "C")]--- > unions [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]--- > == fromList [(3, "B3"), (5, "A3"), (7, "C")]--{-@ unions :: (Ord k) => [OMap k a] -> OMap k a @-}-unions :: Ord k => [Map k a] -> Map k a-unions ts- = foldlStrict union empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unions #-}-#endif---- | The union of a list of maps, with a combining operation:--- (@'unionsWith' f == 'Prelude.foldl' ('unionWith' f) 'empty'@).------ > unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--{-@ unionsWith :: (Ord k) => (a->a->a) -> [OMap k a] -> OMap k a @-}-unionsWith :: Ord k => (a->a->a) -> [Map k a] -> Map k a-unionsWith f ts- = foldlStrict (unionWith f) empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionsWith #-}-#endif---- | /O(n+m)/.--- The expression (@'union' t1 t2@) takes the left-biased union of @t1@ and @t2@.--- It prefers @t1@ when duplicate keys are encountered,--- i.e. (@'union' == 'unionWith' 'const'@).--- The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > union (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "a"), (7, "C")]- -{-@ union :: (Ord k) => OMap k a -> OMap k a -> OMap k a @-}-union :: Ord k => Map k a -> Map k a -> Map k a-union Tip t2 = t2-union t1 Tip = t1-union t1 t2 = hedgeUnion NothingS NothingS NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE union #-}-#endif---- HACK UNTIL SELF-INVARIANT-{-@ hedgeUnion :: (Ord k) => lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } - -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } - | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a - -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a @-}-hedgeUnion :: Ord k => MaybeS k -> MaybeS k -> MaybeS k -> MaybeS k -> Map k b -> Map k b -> Map k b-hedgeUnion _ _ _ _ t1 Tip = t1-hedgeUnion blo0 blo bhi0 bhi Tip (Bin _ kx x l r) = join kx x (filterGt blo l) (filterLt bhi r)-hedgeUnion _ _ _ _ t1 (Bin _ kx x Tip Tip) = insertR kx x t1 -- According to benchmarks, this special case increases- -- performance up to 30%. It does not help in difference or intersection.-hedgeUnion blo0 blo bhi0 bhi (Bin _ kx x l r) t2 = join kx x (hedgeUnion blo blo bmi bmi l (trim blo bmi t2))- (hedgeUnion bmi bmi bhi0 bhi r (trim bmi bhi t2))- where bmi = JustS kx---- LIQUID -- left-biased hedge union--- LIQUID hedgeUnion :: Ord a => MaybeS a -> MaybeS a -> Map a b -> Map a b -> Map a b--- LIQUID hedgeUnion _ _ t1 Tip = t1--- LIQUID hedgeUnion blo bhi Tip (Bin _ kx x l r) = join kx x (filterGt blo l) (filterLt bhi r)--- LIQUID hedgeUnion _ _ t1 (Bin _ kx x Tip Tip) = insertR kx x t1 -- According to benchmarks, this special case increases--- LIQUID -- performance up to 30%. It does not help in difference or intersection.--- LIQUID hedgeUnion blo bhi (Bin _ kx x l r) t2 = join kx x (hedgeUnion blo bmi l (trim blo bmi t2))--- LIQUID (hedgeUnion bmi bhi r (trim bmi bhi t2))--- LIQUID where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeUnion #-}-#endif--{--------------------------------------------------------------------- Union with a combining function---------------------------------------------------------------------}--- | /O(n+m)/. Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.------ > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]--{-@ unionWith :: (Ord k) => (a -> a -> a) -> OMap k a -> OMap k a -> OMap k a @-}-unionWith :: Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWith f m1 m2- = unionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWith #-}-#endif---- | /O(n+m)/.--- Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]--{-@ unionWithKey :: (Ord k) => (k -> a -> a -> a) -> OMap k a -> OMap k a -> OMap k a @-}-unionWithKey :: Ord k => (k -> a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) (\ _ _ x -> x) (\ _ _ x -> x) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWithKey #-}-#endif--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}--- | /O(n+m)/. Difference of two maps.--- Return elements of the first map not existing in the second map.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 3 "b"--{-@ difference :: (Ord k) => OMap k a -> OMap k b -> OMap k a @-}-difference :: Ord k => Map k a -> Map k b -> Map k a-difference Tip _ = Tip-difference t1 Tip = t1-difference t1 t2 = hedgeDiff NothingS NothingS NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE difference #-}-#endif--{-@ hedgeDiff :: (Ord k) => lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } - -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } - | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } - -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } b - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a @-}--hedgeDiff :: Ord a => MaybeS a -> MaybeS a -> MaybeS a -> MaybeS a -> Map a b -> Map a c -> Map a b-hedgeDiff _ _ _ _ Tip _ = Tip-hedgeDiff blo0 blo bhi0 bhi (Bin _ kx x l r) Tip = join kx x (filterGt blo l) (filterLt bhi r)-hedgeDiff blo0 blo bhi0 bhi t (Bin _ kx _ l r) = merge kx (hedgeDiff blo0 blo bmi bmi (trim blo bmi t) l)- (hedgeDiff bmi bmi bhi0 bhi (trim bmi bhi t) r)- where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeDiff #-}-#endif---- | /O(n+m)/. Difference with a combining function.--- When two equal keys are--- encountered, the combining function is applied to the values of these keys.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f al ar = if al == "b" then Just (al ++ ":" ++ ar) else Nothing--- > differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])--- > == singleton 3 "b:B"--{-@ differenceWith :: (Ord k) => (a -> b -> Maybe a) -> OMap k a -> OMap k b -> OMap k a @-}-differenceWith :: Ord k => (a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWith f m1 m2- = differenceWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWith #-}-#endif---- | /O(n+m)/. Difference with a combining function. When two equal keys are--- encountered, the combining function is applied to the key and both values.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--- > differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])--- > == singleton 3 "3:b|B"--{-@ differenceWithKey :: (Ord k) => (k -> a -> b -> Maybe a) -> OMap k a -> OMap k b -> OMap k a @-}-differenceWithKey :: Ord k => (k -> a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWithKey f t1 t2 = mergeWithKey f (\_ _ x -> x) (\ _ _ _ -> Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWithKey #-}-#endif---{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}--- | /O(n+m)/. Intersection of two maps.--- Return data in the first map for the keys existing in both maps.--- (@'intersection' m1 m2 == 'intersectionWith' 'const' m1 m2@).------ > intersection (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "a"--{-@ intersection :: (Ord k) => OMap k a -> OMap k b -> OMap k a @-}-intersection :: Ord k => Map k a -> Map k b -> Map k a-intersection Tip _ = Tip-intersection _ Tip = Tip-intersection t1 t2 = hedgeInt NothingS NothingS NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersection #-}-#endif---- LIQUID hedgeInt :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k b -> Map k a--- LIQUID hedgeInt _ _ _ Tip = Tip--- LIQUID hedgeInt _ _ Tip _ = Tip--- LIQUID hedgeInt blo bhi (Bin _ kx x l r) t2 = let l' = hedgeInt blo bmi l (trim blo bmi t2)--- LIQUID r' = hedgeInt bmi bhi r (trim bmi bhi t2)--- LIQUID in if kx `member` t2 then join kx x l' r' else merge kx l' r'--- LIQUID where bmi = JustS kx--{-@ hedgeInt :: (Ord k) => lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } - -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } - | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a - -> {v: OMap k b | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a @-}-hedgeInt :: Ord k => MaybeS k -> MaybeS k -> MaybeS k -> MaybeS k -> Map k a -> Map k b -> Map k a-hedgeInt _ _ _ _ _ Tip = Tip-hedgeInt _ _ _ _ Tip _ = Tip-hedgeInt blo0 blo bhi0 bhi (Bin _ kx x l r) t2 = let l' = hedgeInt blo0 blo bmi bmi l (trim blo bmi t2)- r' = hedgeInt bmi bmi bhi0 bhi r (trim bmi bhi t2)- in if kx `member` t2 then join kx x l' r' else merge kx l' r'- where bmi = JustS kx-----#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeInt #-}-#endif---- | /O(n+m)/. Intersection with a combining function.------ > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"--{-@ intersectionWith :: (Ord k) => (a -> b -> c) -> OMap k a -> OMap k b -> OMap k c @-}-intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWith f m1 m2- = intersectionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWith #-}-#endif---- | /O(n+m)/. Intersection with a combining function.--- Intersection is more efficient on (bigset \``intersection`\` smallset).------ > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"---{-@ intersectionWithKey :: (Ord k) => (k -> a -> b -> c) -> OMap k a -> OMap k b -> OMap k c @-}-intersectionWithKey :: Ord k => (k -> a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) (\ _ _ _ -> Tip) (\ _ _ _ -> Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWithKey #-}-#endif---{--------------------------------------------------------------------- MergeWithKey---------------------------------------------------------------------}---- | /O(n+m)/. A high-performance universal combining function. This function--- is used to define 'unionWith', 'unionWithKey', 'differenceWith',--- 'differenceWithKey', 'intersectionWith', 'intersectionWithKey' and can be--- used to define other custom combine functions.------ Please make sure you know what is going on when using 'mergeWithKey',--- otherwise you can be surprised by unexpected code growth or even--- corruption of the data structure.------ When 'mergeWithKey' is given three arguments, it is inlined to the call--- site. You should therefore use 'mergeWithKey' only to define your custom--- combining functions. For example, you could define 'unionWithKey',--- 'differenceWithKey' and 'intersectionWithKey' as------ > myUnionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) id id m1 m2--- > myDifferenceWithKey f m1 m2 = mergeWithKey f id (const empty) m1 m2--- > myIntersectionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) (const empty) (const empty) m1 m2------ When calling @'mergeWithKey' combine only1 only2@, a function combining two--- 'IntMap's is created, such that------ * if a key is present in both maps, it is passed with both corresponding--- values to the @combine@ function. Depending on the result, the key is either--- present in the result with specified value, or is left out;------ * a nonempty subtree present only in the first map is passed to @only1@ and--- the output is added to the result;------ * a nonempty subtree present only in the second map is passed to @only2@ and--- the output is added to the result.------ The @only1@ and @only2@ methods /must return a map with a subset (possibly empty) of the keys of the given map/.--- The values can be modified arbitrarily. Most common variants of @only1@ and--- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@ or--- @'filterWithKey' f@ could be used for any @f@.---- LIQUID mergeWithKey :: Ord k => (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c)--- LIQUID -> Map k a -> Map k b -> Map k c--- LIQUID mergeWithKey f g1 g2 = go--- LIQUID where--- LIQUID go Tip t2 = g2 t2--- LIQUID go t1 Tip = g1 t1--- LIQUID go t1 t2 = hedgeMerge f g1 g2 NothingS NothingS NothingS NothingS t1 t2--- LIQUID --- LIQUID hedgeMerge f g1 g2 _ _ _ _ t1 Tip --- LIQUID = g1 t1--- LIQUID hedgeMerge f g1 g2 blo0 blo bhi0 bhi Tip (Bin _ kx x l r) --- LIQUID = g2 $ join kx x (filterGt blo l) (filterLt bhi r)--- LIQUID hedgeMerge f g1 g2 blo0 blo bhi0 bhi (Bin _ kx x l r) t2 --- LIQUID = let bmi = JustS kx --- LIQUID l' = hedgeMerge f g1 g2 blo0 blo bmi bmi l (trim blo bmi t2)--- LIQUID (found, trim_t2) = trimLookupLo kx bhi t2--- LIQUID r' = hedgeMerge f g1 g2 bmi bmi bhi0 bhi r trim_t2--- LIQUID in case found of--- LIQUID Nothing -> case g1 (singleton kx x) of--- LIQUID Tip -> merge kx l' r'--- LIQUID (Bin _ _ x' Tip Tip) -> join kx x' l' r'--- LIQUID _ -> error "mergeWithKey: Given function only1 does not fulfil required conditions (see documentation)"--- LIQUID Just x2 -> case f kx x x2 of--- LIQUID Nothing -> merge kx l' r'--- LIQUID Just x' -> join kx x' l' r'--- LIQUID -- where bmi = JustS kx--{-@ mergeWithKey :: (Ord k) => (k -> a -> b -> Maybe c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } b- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> OMap k a -> OMap k b -> OMap k c @-}-mergeWithKey :: Ord k => (k -> a -> b -> Maybe c) -> (MaybeS k -> MaybeS k -> Map k a -> Map k c) -> (MaybeS k -> MaybeS k -> Map k b -> Map k c)- -> Map k a -> Map k b -> Map k c-mergeWithKey f g1 g2 = go- where- go Tip t2 = g2 NothingS NothingS t2- go t1 Tip = g1 NothingS NothingS t1- go t1 t2 = hedgeMerge f g1 g2 NothingS NothingS NothingS NothingS t1 t2--{-@ hedgeMerge :: (Ord k) => (k -> a -> b -> Maybe c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } b- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } - -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } - | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a - -> {v: OMap k b | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c @-}--hedgeMerge :: Ord k => (k -> a -> b -> Maybe c) - -> (MaybeS k -> MaybeS k -> Map k a -> Map k c) - -> (MaybeS k -> MaybeS k -> Map k b -> Map k c)- -> MaybeS k -> MaybeS k -> MaybeS k -> MaybeS k - -> Map k a -> Map k b -> Map k c-hedgeMerge f g1 g2 _ blo _ bhi t1 Tip - = g1 blo bhi t1-hedgeMerge f g1 g2 blo0 blo bhi0 bhi Tip (Bin _ kx x l r) - = g2 blo bhi $ join kx x (filterGt blo l) (filterLt bhi r)-hedgeMerge f g1 g2 blo0 blo bhi0 bhi (Bin _ kx x l r) t2 - = let bmi = JustS kx - l' = hedgeMerge f g1 g2 blo0 blo bmi bmi l (trim blo bmi t2)- (found, trim_t2) = trimLookupLo kx bhi t2- r' = hedgeMerge f g1 g2 bmi bmi bhi0 bhi r trim_t2- in case found of- Nothing -> case g1 blo bhi (singleton kx x) of- Tip -> merge kx l' r'- (Bin _ _ x' Tip Tip) -> join kx x' l' r'- _ -> error "mergeWithKey: Given function only1 does not fulfil required conditions (see documentation)"- Just x2 -> case f kx x x2 of- Nothing -> merge kx l' r'- Just x' -> join kx x' l' r'-{-# INLINE mergeWithKey #-}--{--------------------------------------------------------------------- Submap---------------------------------------------------------------------}--- | /O(n+m)/.--- This function is defined as (@'isSubmapOf' = 'isSubmapOfBy' (==)@).----{-@ isSubmapOf :: (Ord k, Eq a) => OMap k a -> OMap k a -> Bool @-}-isSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool-isSubmapOf m1 m2 = isSubmapOfBy (==) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubmapOf #-}-#endif--{- | /O(n+m)/.- The expression (@'isSubmapOfBy' f t1 t2@) returns 'True' if- all keys in @t1@ are in tree @t2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isSubmapOfBy (==) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (<=) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1),('b',2)])-- But the following are all 'False':-- > isSubmapOfBy (==) (fromList [('a',2)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (<) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1)])----}--{-@ isSubmapOfBy :: (Ord k) => (a->b->Bool) -> OMap k a -> OMap k b -> Bool @-}-isSubmapOfBy :: Ord k => (a->b->Bool) -> Map k a -> Map k b -> Bool-isSubmapOfBy f t1 t2- = (size t1 <= size t2) && (submap' f t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubmapOfBy #-}-#endif--submap' :: Ord a => (b -> c -> Bool) -> Map a b -> Map a c -> Bool-submap' _ Tip _ = True-submap' _ _ Tip = False-submap' f (Bin _ kx x l r) t- = case found of- Nothing -> False- Just y -> f x y && submap' f l lt && submap' f r gt- where- (lt,found,gt) = splitLookup kx t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE submap' #-}-#endif---- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).--- Defined as (@'isProperSubmapOf' = 'isProperSubmapOfBy' (==)@).-isProperSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool-isProperSubmapOf m1 m2- = isProperSubmapOfBy (==) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubmapOf #-}-#endif--{- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).- The expression (@'isProperSubmapOfBy' f m1 m2@) returns 'True' when- @m1@ and @m2@ are not equal,- all keys in @m1@ are in @m2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isProperSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)])-- But the following are all 'False':-- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)])- > isProperSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)])----}-isProperSubmapOfBy :: Ord k => (a -> b -> Bool) -> Map k a -> Map k b -> Bool-isProperSubmapOfBy f t1 t2- = (size t1 < size t2) && (submap' f t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubmapOfBy #-}-#endif--{--------------------------------------------------------------------- Filter and partition---------------------------------------------------------------------}--- | /O(n)/. Filter all values that satisfy the predicate.------ > filter (> "a") (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > filter (> "x") (fromList [(5,"a"), (3,"b")]) == empty--- > filter (< "a") (fromList [(5,"a"), (3,"b")]) == empty--{-@ filter :: (a -> Bool) -> OMap k a -> OMap k a @-}-filter :: (a -> Bool) -> Map k a -> Map k a-filter p m- = filterWithKey (\_ x -> p x) m---- | /O(n)/. Filter all keys\/values that satisfy the predicate.------ > filterWithKey (\k _ -> k > 4) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ filterWithKey :: (k -> a -> Bool) -> OMap k a -> OMap k a @-}-filterWithKey :: (k -> a -> Bool) -> Map k a -> Map k a-filterWithKey _ Tip = Tip-filterWithKey p (Bin _ kx x l r)- | p kx x = join kx x (filterWithKey p l) (filterWithKey p r)- | otherwise = merge kx (filterWithKey p l) (filterWithKey p r)---- | /O(n)/. Partition the map according to a predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partition (> "a") (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > partition (< "x") (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partition (> "x") (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--{-@ partition :: (a -> Bool) -> OMap k a -> (OMap k a, OMap k a) @-}-partition :: (a -> Bool) -> Map k a -> (Map k a,Map k a)-partition p m- = partitionWithKey (\_ x -> p x) m---- | /O(n)/. Partition the map according to a predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partitionWithKey (\ k _ -> k > 3) (fromList [(5,"a"), (3,"b")]) == (singleton 5 "a", singleton 3 "b")--- > partitionWithKey (\ k _ -> k < 7) (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partitionWithKey (\ k _ -> k > 7) (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--{-@ partitionWithKey :: (k -> a -> Bool) -> OMap k a -> (OMap k a, OMap k a) @-}-partitionWithKey :: (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)-partitionWithKey _ Tip = (Tip,Tip)-partitionWithKey p (Bin _ kx x l r)- | p kx x = (join kx x l1 r1,merge kx l2 r2)- | otherwise = (merge kx l1 r1,join kx x l2 r2)- where- (l1,l2) = partitionWithKey p l- (r1,r2) = partitionWithKey p r---- | /O(n)/. Map values and collect the 'Just' results.------ > let f x = if x == "a" then Just "new a" else Nothing--- > mapMaybe f (fromList [(5,"a"), (3,"b")]) == singleton 5 "new a"--{-@ mapMaybe :: (a -> Maybe b) -> OMap k a -> OMap k b @-}-mapMaybe :: (a -> Maybe b) -> Map k a -> Map k b-mapMaybe f = mapMaybeWithKey (\_ x -> f x)---- | /O(n)/. Map keys\/values and collect the 'Just' results.------ > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"--{-@ mapMaybeWithKey :: (k -> a -> Maybe b) -> OMap k a -> OMap k b @-}-mapMaybeWithKey :: (k -> a -> Maybe b) -> Map k a -> Map k b-mapMaybeWithKey _ Tip = Tip-mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of- Just y -> join kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)- Nothing -> merge kx (mapMaybeWithKey f l) (mapMaybeWithKey f r)---- | /O(n)/. Map values and separate the 'Left' and 'Right' results.------ > let f a = if a < "c" then Left a else Right a--- > mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])--- >--- > mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--{-@ mapEither :: (a -> Either b c) -> OMap k a -> (OMap k b, OMap k c) @-}-mapEither :: (a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEither f m- = mapEitherWithKey (\_ x -> f x) m---- | /O(n)/. Map keys\/values and separate the 'Left' and 'Right' results.------ > let f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--- > mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])--- >--- > mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])--{-@ mapEitherWithKey :: (k -> a -> Either b c) -> OMap k a -> (OMap k b, OMap k c) @-}-mapEitherWithKey :: (k -> a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEitherWithKey _ Tip = (Tip, Tip)-mapEitherWithKey f (Bin _ kx x l r) = case f kx x of- Left y -> (join kx y l1 r1, merge kx l2 r2)- Right z -> (merge kx l1 r1, join kx z l2 r2)- where- (l1,l2) = mapEitherWithKey f l- (r1,r2) = mapEitherWithKey f r--{--------------------------------------------------------------------- Mapping---------------------------------------------------------------------}--- | /O(n)/. Map a function over all values in the map.------ > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]--{-@ map :: (a -> b) -> OMap k a -> OMap k b @-}-map :: (a -> b) -> Map k a -> Map k b-map _ Tip = Tip-map f (Bin sx kx x l r) = Bin sx kx (f x) (map f l) (map f r)---- | /O(n)/. Map a function over all values in the map.------ > let f key x = (show key) ++ ":" ++ x--- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]--{-@ mapWithKey :: (k -> a -> b) -> OMap k a -> OMap k b @-}-mapWithKey :: (k -> a -> b) -> Map k a -> Map k b-mapWithKey _ Tip = Tip-mapWithKey f (Bin sx kx x l r) = Bin sx kx (f kx x) (mapWithKey f l) (mapWithKey f r)---- | /O(n)/.--- @'traverseWithKey' f s == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@--- That is, behaves exactly like a regular 'traverse' except that the traversing--- function also has access to the key associated with a value.------ > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(1, 'a'), (5, 'e')]) == Just (fromList [(1, 'b'), (5, 'f')])--- > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(2, 'c')]) == Nothing---{-# INLINE traverseWithKey #-}---traverseWithKey :: Applicative t => (k -> a -> t b) -> Map k a -> t (Map k b)---traverseWithKey f = go--- where--- go Tip = pure Tip--- go (Bin s k v l r)--- = flip (Bin s k) <$> go l <*> f k v <*> go r---- | /O(n)/. The function 'mapAccum' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a b = (a ++ b, b ++ "X")--- > mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) == ("Everything: ba", fromList [(3, "bX"), (5, "aX")])--{-@ mapAccum :: (a -> b -> (a,c)) -> a -> OMap k b -> (a, OMap k c) @-}-mapAccum :: (a -> b -> (a,c)) -> a -> Map k b -> (a, Map k c)-mapAccum f a m- = mapAccumWithKey (\a' _ x' -> f a' x') a m---- | /O(n)/. The function 'mapAccumWithKey' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--- > mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) == ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])--{-@ mapAccumWithKey :: (a -> k -> b -> (a,c)) -> a -> OMap k b -> (a, OMap k c) @-}-mapAccumWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumWithKey f a t- = mapAccumL f a t---- | /O(n)/. The function 'mapAccumL' threads an accumulating--- argument through the map in ascending order of keys.-mapAccumL :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumL _ a Tip = (a,Tip)-mapAccumL f a (Bin sx kx x l r) =- let (a1,l') = mapAccumL f a l- (a2,x') = f a1 kx x- (a3,r') = mapAccumL f a2 r- in (a3,Bin sx kx x' l' r')---- | /O(n)/. The function 'mapAccumR' threads an accumulating--- argument through the map in descending order of keys.-{-@ mapAccumRWithKey :: (a -> k -> b -> (a,c)) -> a -> OMap k b -> (a, OMap k c) @-}-mapAccumRWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumRWithKey _ a Tip = (a,Tip)-mapAccumRWithKey f a (Bin sx kx x l r) =- let (a1,r') = mapAccumRWithKey f a r- (a2,x') = f a1 kx x- (a3,l') = mapAccumRWithKey f a2 l- in (a3,Bin sx kx x' l' r')---- | /O(n*log n)/.--- @'mapKeys' f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the value at the greatest of the--- original keys is retained.------ > mapKeys (+ 1) (fromList [(5,"a"), (3,"b")]) == fromList [(4, "b"), (6, "a")]--- > mapKeys (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "c"--- > mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "c"--{-@ mapKeys :: (Ord k2) => (k1 -> k2) -> OMap k1 a -> OMap k2 a @-}-mapKeys :: Ord k2 => (k1->k2) -> Map k1 a -> Map k2 a-mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeys #-}-#endif---- | /O(n*log n)/.--- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the associated values will be--- combined using @c@.------ > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"--- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"--{-@ mapKeysWith :: (Ord k2) => (a -> a -> a) -> (k1->k2) -> OMap k1 a -> OMap k2 a @-}-mapKeysWith :: Ord k2 => (a -> a -> a) -> (k1->k2) -> Map k1 a -> Map k2 a-mapKeysWith c f = fromListWith c . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeysWith #-}-#endif----- | /O(n)/.--- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@--- is strictly monotonic.--- That is, for any values @x@ and @y@, if @x@ < @y@ then @f x@ < @f y@.--- /The precondition is not checked./--- Semi-formally, we have:------ > and [x < y ==> f x < f y | x <- ls, y <- ls]--- > ==> mapKeysMonotonic f s == mapKeys f s--- > where ls = keys s------ This means that @f@ maps distinct original keys to distinct resulting keys.--- This function has better performance than 'mapKeys'.------ > mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) == fromList [(6, "b"), (10, "a")]--- > valid (mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")])) == True--- > valid (mapKeysMonotonic (\ _ -> 1) (fromList [(5,"a"), (3,"b")])) == False--- LIQUIDFAIL-mapKeysMonotonic :: (k1->k2) -> Map k1 a -> Map k2 a-mapKeysMonotonic _ Tip = Tip-mapKeysMonotonic f (Bin sz k x l r) =- Bin sz (f k) x (mapKeysMonotonic f l) (mapKeysMonotonic f r)--{--------------------------------------------------------------------- Folds---------------------------------------------------------------------}---- | /O(n)/. Fold the values in the map using the given right-associative--- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'elems'@.------ For example,------ > elems map = foldr (:) [] map------ > let f a len = len + (length a)--- > foldr f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldr :: (a -> b -> b) -> b -> Map k a -> b-foldr f z = go z- where- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr #-}---- | /O(n)/. A strict version of 'foldr'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldr' :: (a -> b -> b) -> b -> Map k a -> b-foldr' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr' #-}---- | /O(n)/. Fold the values in the map using the given left-associative--- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.------ For example,------ > elems = reverse . foldl (flip (:)) []------ > let f len a = len + (length a)--- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldl :: (a -> b -> a) -> a -> Map k b -> a-foldl f z = go z- where- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl #-}---- | /O(n)/. A strict version of 'foldl'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldl' :: (a -> b -> a) -> a -> Map k b -> a-foldl' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl' #-}---- | /O(n)/. Fold the keys and values in the map using the given right-associative--- binary operator, such that--- @'foldrWithKey' f z == 'Prelude.foldr' ('uncurry' f) z . 'toAscList'@.------ For example,------ > keys map = foldrWithKey (\k x ks -> k:ks) [] map------ > let f k a result = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldrWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (5:a)(3:b)"-foldrWithKey :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l-{-# INLINE foldrWithKey #-}---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldrWithKey' :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrWithKey' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l-{-# INLINE foldrWithKey' #-}---- | /O(n)/. Fold the keys and values in the map using the given left-associative--- binary operator, such that--- @'foldlWithKey' f z == 'Prelude.foldl' (\\z' (kx, x) -> f z' kx x) z . 'toAscList'@.------ For example,------ > keys = reverse . foldlWithKey (\ks k x -> k:ks) []------ > let f result k a = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldlWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (3:b)(5:a)"-foldlWithKey :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r-{-# INLINE foldlWithKey #-}---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldlWithKey' :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlWithKey' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r-{-# INLINE foldlWithKey' #-}--{--------------------------------------------------------------------- List variations---------------------------------------------------------------------}--- | /O(n)/.--- Return all elements of the map in the ascending order of their keys.--- Subject to list fusion.------ > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]--- > elems empty == []--elems :: Map k a -> [a]-elems = foldr (:) []---- | /O(n)/. Return all keys of the map in ascending order. Subject to list--- fusion.------ > keys (fromList [(5,"a"), (3,"b")]) == [3,5]--- > keys empty == []--{- LIQUID: SUMMARY-VALUES: keys :: OMap k a -> [k]<{v: k | v >= fld}> @-}-keys :: Map k a -> [k]-keys = foldrWithKey (\k _ ks -> k : ks) []---- | /O(n)/. An alias for 'toAscList'. Return all key\/value pairs in the map--- in ascending key order. Subject to list fusion.------ > assocs (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > assocs empty == []--{- LIQUID: SUMMARY-VALUES: assocs :: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) >= fst(fld) }> @-}-assocs :: Map k a -> [(k,a)]-assocs m- = toAscList m---- | /O(n)/. The set of all keys of the map.------ > keysSet (fromList [(5,"a"), (3,"b")]) == Data.Set.fromList [3,5]--- > keysSet empty == Data.Set.empty--- LIQUID keysSet :: Map k a -> Set.Set k--- LIQUID keysSet Tip = Set.Tip--- LIQUID keysSet (Bin sz kx _ l r) = Set.Bin sz kx (keysSet l) (keysSet r)---- | /O(n)/. Build a map from a set of keys and a function which for each key--- computes its value.------ > fromSet (\k -> replicate k 'a') (Data.Set.fromList [3, 5]) == fromList [(5,"aaaaa"), (3,"aaa")]--- > fromSet undefined Data.Set.empty == empty--- LIQUID fromSet :: (k -> a) -> Set.Set k -> Map k a--- LIQUID fromSet _ Set.Tip = Tip--- LIQUID fromSet f (Set.Bin sz x l r) = Bin sz x (f x) (fromSet f l) (fromSet f r)--{--------------------------------------------------------------------- Lists- use [foldlStrict] to reduce demand on the control-stack---------------------------------------------------------------------}--- | /O(n*log n)/. Build a map from a list of key\/value pairs. See also 'fromAscList'.--- If the list contains more than one value for the same key, the last value--- for the key is retained.------ > fromList [] == empty--- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]--- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]--{-@ fromList :: (Ord k) => [(k,a)] -> OMap k a @-}-fromList :: Ord k => [(k,a)] -> Map k a-fromList xs- = foldlStrict ins empty xs- where- ins t (k,x) = insert k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromList #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "ab"), (5, "aba")]--- > fromListWith (++) [] == empty--{-@ fromListWith :: (Ord k) => (a -> a -> a) -> [(k,a)] -> OMap k a @-}-fromListWith :: Ord k => (a -> a -> a) -> [(k,a)] -> Map k a-fromListWith f xs- = fromListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWith #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.------ > let f k a1 a2 = (show k) ++ a1 ++ a2--- > fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "3ab"), (5, "5a5ba")]--- > fromListWithKey f [] == empty--{-@ fromListWithKey :: (Ord k) => (k -> a -> a -> a) -> [(k,a)] -> OMap k a @-}-fromListWithKey :: Ord k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromListWithKey f xs- = foldlStrict ins empty xs- where- ins t (k,x) = insertWithKey f k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWithKey #-}-#endif---- | /O(n)/. Convert the map to a list of key\/value pairs. Subject to list fusion.------ > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > toList empty == []--{- LIQUIDTODO: toList:: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) > fst(fld) }> @-}-toList :: Map k a -> [(k,a)]-toList = toAscList---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys are--- in ascending order. Subject to list fusion.------ > toAscList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--{- LIQUIDTODO: toAscList :: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) > fst(fld) }> @-}-toAscList :: Map k a -> [(k,a)]-toAscList = foldrWithKey (\k x xs -> (k,x):xs) []---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys--- are in descending order. Subject to list fusion.------ > toDescList (fromList [(5,"a"), (3,"b")]) == [(5,"a"), (3,"b")]--{- LIQUIDTODO: toAscList :: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) < fst(fld) }> @-}-toDescList :: Map k a -> [(k,a)]-toDescList = foldlWithKey (\xs k x -> (k,x):xs) []---- List fusion for the list generating functions.-#if __GLASGOW_HASKELL__--- The foldrFB and foldlFB are fold{r,l}WithKey equivalents, used for list fusion.--- They are important to convert unfused methods back, see mapFB in prelude.-foldrFB :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrFB = foldrWithKey-{-# INLINE[0] foldrFB #-}-foldlFB :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlFB = foldlWithKey-{-# INLINE[0] foldlFB #-}---- Inline assocs and toList, so that we need to fuse only toAscList.-{-# INLINE assocs #-}-{-# INLINE toList #-}---- The fusion is enabled up to phase 2 included. If it does not succeed,--- convert in phase 1 the expanded elems,keys,to{Asc,Desc}List calls back to--- elems,keys,to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were--- used in a list fusion, otherwise it would go away in phase 1), and let compiler--- do whatever it wants with elems,keys,to{Asc,Desc}List -- it was forbidden to--- inline it before phase 0, otherwise the fusion rules would not fire at all.-{-# NOINLINE[0] elems #-}-{-# NOINLINE[0] keys #-}-{-# NOINLINE[0] toAscList #-}-{-# NOINLINE[0] toDescList #-}-{-# RULES "Map.elems" [~1] forall m . elems m = build (\c n -> foldrFB (\_ x xs -> c x xs) n m) #-}-{-# RULES "Map.elemsBack" [1] foldrFB (\_ x xs -> x : xs) [] = elems #-}-{-# RULES "Map.keys" [~1] forall m . keys m = build (\c n -> foldrFB (\k _ xs -> c k xs) n m) #-}-{-# RULES "Map.keysBack" [1] foldrFB (\k _ xs -> k : xs) [] = keys #-}-{-# RULES "Map.toAscList" [~1] forall m . toAscList m = build (\c n -> foldrFB (\k x xs -> c (k,x) xs) n m) #-}-{-# RULES "Map.toAscListBack" [1] foldrFB (\k x xs -> (k, x) : xs) [] = toAscList #-}-{-# RULES "Map.toDescList" [~1] forall m . toDescList m = build (\c n -> foldlFB (\xs k x -> c (k,x) xs) n m) #-}-{-# RULES "Map.toDescListBack" [1] foldlFB (\xs k x -> (k, x) : xs) [] = toDescList #-}-#endif--{--------------------------------------------------------------------- Building trees from ascending/descending lists can be done in linear time.-- Note that if [xs] is ascending that:- fromAscList xs == fromList xs- fromAscListWith f xs == fromListWith f xs---------------------------------------------------------------------}--- | /O(n)/. Build a map from an ascending list in linear time.--- /The precondition (input list is ascending) is not checked./------ > fromAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]--- > valid (fromAscList [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscList [(5,"a"), (3,"b"), (5,"b")]) == False--{- LIQUIDTODO fromAscList :: (Eq k) => [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-fromAscList :: Eq k => [(k,a)] -> Map k a-fromAscList xs- = fromAscListWithKey (\_ x _ -> x) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscList #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--- > valid (fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscListWith (++) [(5,"a"), (3,"b"), (5,"b")]) == False--{- LIQUIDTODO fromAscListWith :: (Eq k) => (a -> a -> a) -> [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-fromAscListWith :: Eq k => (a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWith f xs- = fromAscListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWith #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a--- combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > let f k a1 a2 = (show k) ++ ":" ++ a1 ++ a2--- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")] == fromList [(3, "b"), (5, "5:b5:ba")]--- > valid (fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")]) == True--- > valid (fromAscListWithKey f [(5,"a"), (3,"b"), (5,"b"), (5,"b")]) == False--{- LIQUIDTODO fromAscListWithKey :: (Eq k) => (k -> a -> a -> a) -> [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-fromAscListWithKey :: Eq k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWithKey f xs- = fromDistinctAscList (combineEq f xs)- where- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]- combineEq _ xs'- = case xs' of- [] -> []- [x] -> [x]- (x:xx) -> combineEq' x xx-- combineEq' z [] = [z]- combineEq' z@(kz,zz) (x@(kx,xx):xs')- | kx==kz = let yy = f kx xx zz in combineEq' (kx,yy) xs'- | otherwise = z:combineEq' x xs'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWithKey #-}-#endif----- | /O(n)/. Build a map from an ascending list of distinct elements in linear time.--- /The precondition is not checked./------ > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > valid (fromDistinctAscList [(3,"b"), (5,"a")]) == True--- > valid (fromDistinctAscList [(3,"b"), (5,"a"), (5,"b")]) == False--{- LIQUIDTODO fromDistinctAscList :: [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-fromDistinctAscList :: [(k,a)] -> Map k a-fromDistinctAscList xs- = create const (length xs) xs- where- -- 1) use continuations so that we use heap space instead of stack space.- -- 2) special case for n==5 to create bushier trees.- create c 0 xs' = c Tip xs'- create c 5 xs' = case xs' of- ((k1,x1):(k2,x2):(k3,x3):(k4,x4):(k5,x5):xx)- -> c (bin k4 x4 (bin k2 x2 (singleton k1 x1) (singleton k3 x3)) (singleton k5 x5)) xx- _ -> error "fromDistinctAscList create"- create c n xs' = seq nr $ create (createR nr c) nl xs'- where nl = n `div` 2- nr = n - nl - 1-- createR n c l ((k,x):ys) = create (createB l k x c) n ys- createR _ _ _ [] = error "fromDistinctAscList createR []"- createB l k x c r zs = c (bin k x l r) zs---{--------------------------------------------------------------------- Utility functions that return sub-ranges of the original- tree. Some functions take a `Maybe value` as an argument to- allow comparisons against infinite values. These are called `blow`- (Nothing is -\infty) and `bhigh` (here Nothing is +\infty).- We use MaybeS value, which is a Maybe strict in the Just case.-- [trim blow bhigh t] A tree that is either empty or where [x > blow]- and [x < bhigh] for the value [x] of the root.- [filterGt blow t] A tree where for all values [k]. [k > blow]- [filterLt bhigh t] A tree where for all values [k]. [k < bhigh]-- [split k t] Returns two trees [l] and [r] where all keys- in [l] are <[k] and all keys in [r] are >[k].- [splitLookup k t] Just like [split] but also returns whether [k]- was found in the tree.---------------------------------------------------------------------}--data MaybeS a = NothingS | JustS a -- LIQUID: !-annot-fix---{--------------------------------------------------------------------- [trim blo bhi t] trims away all subtrees that surely contain no- values between the range [blo] to [bhi]. The returned tree is either- empty or the key of the root is between @blo@ and @bhi@.---------------------------------------------------------------------}--- LIQUID: EXPANDED CASE-EXPRS for lesser, greater, middle to avoid DEFAULT hassle-{-@ trim :: (Ord k) => lo:MaybeS k - -> hi:MaybeS k - -> OMap k a - -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && - ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } @-}--trim :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k a-trim NothingS NothingS t = t-trim (JustS lk) NothingS t = greater lk t - where greater lo t@(Bin _ k _ _ r) | k <= lo = greater lo r- | otherwise = t- greater _ t'@Tip = t'-trim NothingS (JustS hk) t = lesser hk t - where lesser hi t'@(Bin _ k _ l _) | k >= hi = lesser hi l- | otherwise = t'- lesser _ t'@Tip = t'-trim (JustS lk) (JustS hk) t = middle lk hk t - where middle lo hi t'@(Bin _ k _ l r) | k <= lo = middle lo hi r- | k >= hi = middle lo hi l- | otherwise = t'- middle _ _ t'@Tip = t' -#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trim #-}-#endif---- Helper function for 'mergeWithKey'. The @'trimLookupLo' lk hk t@ performs both--- @'trim' (JustS lk) hk t@ and @'lookup' lk t@.---- See Note: Type of local 'go' function--- LIQUID trimLookupLo :: Ord k => k -> MaybeS k -> Map k a -> (Maybe a, Map k a)--- LIQUID trimLookupLo lk NothingS t = greater lk t--- LIQUID where greater :: Ord k => k -> Map k a -> (Maybe a, Map k a)--- LIQUID greater lo t'@(Bin _ kx x l r) = case compare lo kx of LT -> (lookup lo l, {-`strictPair`-} t')--- LIQUID EQ -> (Just x, r)--- LIQUID GT -> greater lo r--- LIQUID greater _ Tip = (Nothing, Tip)--- LIQUID trimLookupLo lk (JustS hk) t = middle lk hk t--- LIQUID where middle :: Ord k => k -> k -> Map k a -> (Maybe a, Map k a)--- LIQUID middle lo hi t'@(Bin _ kx x l r) = case compare lo kx of LT | kx < hi -> (lookup lo l, {- `strictPair` -} t')--- LIQUID | otherwise -> middle lo hi l--- LIQUID EQ -> (Just x, {-`strictPair`-} lesser hi r)--- LIQUID GT -> middle lo hi r--- LIQUID middle _ _ Tip = (Nothing, Tip)--- LIQUID --- LIQUID lesser :: Ord k => k -> Map k a -> Map k a--- LIQUID lesser hi (Bin _ k _ l _) | k >= hi = lesser hi l--- LIQUID lesser _ t' = t'--{-@ trimLookupLo :: (Ord k) - => lo:k - -> bhi:{v: MaybeS k | (isJustS(v) => (lo < fromJustS(v)))} - -> OMap k a - -> (Maybe a, {v: OMap k a | ((isBin(v) => (lo < key(v))) && ((isBin(v) && isJustS(bhi)) => (fromJustS(bhi) > key(v)))) }) @-}--trimLookupLo :: Ord k => k -> MaybeS k -> Map k a -> (Maybe a, Map k a)-trimLookupLo lk NothingS t = greater lk t- where greater :: Ord k => k -> Map k a -> (Maybe a, Map k a)- greater lo t'@(Bin _ kx x l r) = case compare lo kx of LT -> (lookup lo l, {-`strictPair`-} t')- EQ -> (Just x, (case r of {r'@(Bin _ _ _ _ _) -> r' ; r'@Tip -> r'}))- GT -> greater lo r- greater _ Tip = (Nothing, Tip)-trimLookupLo lk (JustS hk) t = middle lk hk t- where middle :: Ord k => k -> k -> Map k a -> (Maybe a, Map k a)- middle lo hi t'@(Bin _ kx x l r) = case compare lo kx of LT | kx < hi -> (lookup lo l, {- `strictPair` -} t')- | otherwise -> middle lo hi l- EQ -> (Just x, {-`strictPair`-} lesser lo hi (case r of {r'@(Bin _ _ _ _ _) -> r' ; r'@Tip -> r'}))- GT -> middle lo hi r- middle _ _ Tip = (Nothing, Tip)- - lesser :: Ord k => k -> k -> Map k a -> Map k a- lesser lo hi t'@(Bin _ k _ l _) | k >= hi = lesser lo hi l- | otherwise = t'- lesser _ _ t'@Tip = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trimLookupLo #-}-#endif---{--------------------------------------------------------------------- [filterGt b t] filter all keys >[b] from tree [t]- [filterLt b t] filter all keys <[b] from tree [t]---------------------------------------------------------------------}--{-@ filterGt :: (Ord k) -> x:MaybeS k -> OMap k v -> OMap {v:k | ((isJustS(x)) => (v > fromJustS(x))) } v @-}-filterGt :: Ord k => MaybeS k -> Map k v -> Map k v-filterGt NothingS t = t-filterGt (JustS b) t = filterGt' b t---- LIQUID TXREC-TOPLEVEL-ISSUE-filterGt' _ Tip = Tip-filterGt' b' (Bin _ kx x l r) =- case compare b' kx of LT -> join kx x (filterGt' b' l) r- EQ -> r- GT -> filterGt' b' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterGt #-}-#endif--{-@ filterLt :: (Ord k) -> x:MaybeS k -> OMap k v -> OMap {v:k | ((isJustS(x)) => (v < fromJustS(x))) } v @-}-filterLt :: Ord k => MaybeS k -> Map k v -> Map k v-filterLt NothingS t = t-filterLt (JustS b) t = filterLt' b t---- LIQUID TXREC-TOPLEVEL-ISSUE-filterLt' _ Tip = Tip-filterLt' b' (Bin _ kx x l r) =- case compare kx b' of LT -> join kx x l (filterLt' b' r)- EQ -> l- GT -> filterLt' b' l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterLt #-}-#endif--{--------------------------------------------------------------------- Split---------------------------------------------------------------------}--- | /O(log n)/. The expression (@'split' k map@) is a pair @(map1,map2)@ where--- the keys in @map1@ are smaller than @k@ and the keys in @map2@ larger than @k@.--- Any key equal to @k@ is found in neither @map1@ nor @map2@.------ > split 2 (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3,"b"), (5,"a")])--- > split 3 (fromList [(5,"a"), (3,"b")]) == (empty, singleton 5 "a")--- > split 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > split 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", empty)--- > split 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], empty)--{-@ split :: (Ord k) => x:k -> OMap k a -> (OMap {v: k | v < x} a, OMap {v:k | v > x} a) @-}-split :: Ord k => k -> Map k a -> (Map k a, Map k a)-split k t = k `seq`- case t of- Tip -> (Tip, Tip)- Bin _ kx x l r -> case compare k kx of- LT -> let (lt,gt) = split k l in (lt,join kx x gt r)- GT -> let (lt,gt) = split k r in (join kx x l lt,gt)- EQ -> (l,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE split #-}-#endif---- | /O(log n)/. The expression (@'splitLookup' k map@) splits a map just--- like 'split' but also returns @'lookup' k map@.------ > splitLookup 2 (fromList [(5,"a"), (3,"b")]) == (empty, Nothing, fromList [(3,"b"), (5,"a")])--- > splitLookup 3 (fromList [(5,"a"), (3,"b")]) == (empty, Just "b", singleton 5 "a")--- > splitLookup 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Nothing, singleton 5 "a")--- > splitLookup 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Just "a", empty)--- > splitLookup 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], Nothing, empty)--{-@ splitLookup :: (Ord k) => x:k -> OMap k a -> (OMap {v: k | v < x} a, Maybe a, OMap {v:k | v > x} a) @-}-splitLookup :: Ord k => k -> Map k a -> (Map k a,Maybe a,Map k a)-splitLookup k t = k `seq`- case t of- Tip -> (Tip,Nothing,Tip)- Bin _ kx x l r -> case compare k kx of- LT -> let (lt,z,gt) = splitLookup k l in (lt,z,join kx x gt r)- GT -> let (lt,z,gt) = splitLookup k r in (join kx x l lt,z,gt)- EQ -> (l,Just x,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE splitLookup #-}-#endif--{--------------------------------------------------------------------- Utility functions that maintain the balance properties of the tree.- All constructors assume that all values in [l] < [k] and all values- in [r] > [k], and that [l] and [r] are valid trees.-- In order of sophistication:- [Bin sz k x l r] The type constructor.- [bin k x l r] Maintains the correct size, assumes that both [l]- and [r] are balanced with respect to each other.- [balance k x l r] Restores the balance and size.- Assumes that the original tree was balanced and- that [l] or [r] has changed by at most one element.- [join k x l r] Restores balance and size.-- Furthermore, we can construct a new tree from two trees. Both operations- assume that all values in [l] < all values in [r] and that [l] and [r]- are valid:- [glue l r] Glues [l] and [r] together. Assumes that [l] and- [r] are already balanced with respect to each other.- [merge l r] Merges two trees and restores balance.-- Note: in contrast to Adam's paper, we use (<=) comparisons instead- of (<) comparisons in [join], [merge] and [balance].- Quickcheck (on [difference]) showed that this was necessary in order- to maintain the invariants. It is quite unsatisfactory that I haven't- been able to find out why this is actually the case! Fortunately, it- doesn't hurt to be a bit more conservative.---------------------------------------------------------------------}-{--------------------------------------------------------------------- Join---------------------------------------------------------------------}--{-@ join :: kcut:k -> a -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-join :: k -> a -> Map k a -> Map k a -> Map k a-join kx x Tip r = insertMin kx x r-join kx x l Tip = insertMax kx x l-join kx x l@(Bin sizeL ky y ly ry) r@(Bin sizeR kz z lz rz)- | delta*sizeL < sizeR = balanceL kz z (join kx x l lz) rz- | delta*sizeR < sizeL = balanceR ky y ly (join kx x ry r)- | otherwise = bin kx x l r---- insertMin and insertMax don't perform potentially expensive comparisons.-insertMax,insertMin :: k -> a -> Map k a -> Map k a-insertMax kx x t- = case t of- Tip -> singleton kx x- Bin _ ky y l r- -> balanceR ky y l (insertMax kx x r)--insertMin kx x t- = case t of- Tip -> singleton kx x- Bin _ ky y l r- -> balanceL ky y (insertMin kx x l) r--{--------------------------------------------------------------------- [merge l r]: merges two trees.---------------------------------------------------------------------}-{-@ merge :: kcut:k -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-merge :: k -> Map k a -> Map k a -> Map k a-merge _ Tip r = r-merge _ l Tip = l-merge kcut l@(Bin sizeL kx x lx rx) r@(Bin sizeR ky y ly ry)- | delta*sizeL < sizeR = balanceL ky y (merge kcut l ly) ry- | delta*sizeR < sizeL = balanceR kx x lx (merge kcut rx r)- | otherwise = glue kcut l r--{--------------------------------------------------------------------- [glue l r]: glues two trees together.- Assumes that [l] and [r] are already balanced with respect to each other.---------------------------------------------------------------------}-{-@ glue :: kcut:k -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-glue :: k -> Map k a -> Map k a -> Map k a-glue _ Tip r = r-glue _ l Tip = l-glue kcut l r- | size l > size r = let (km, m, l') = deleteFindMax l in balanceR km m l' r- | otherwise = let (km, m, r') = deleteFindMin r in balanceL km m l r'---- | /O(log n)/. Delete and find the minimal element.------ > deleteFindMin (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((3,"b"), fromList[(5,"a"), (10,"c")])--- > deleteFindMin Error: can not return the minimal element of an empty map--deleteFindMin :: Map k a -> (k, a, Map k a)-deleteFindMin t- = case t of- Bin _ k x Tip r -> (k, x, r)- Bin _ k x l r -> let (km, m, l') = deleteFindMin l in (km, m, balanceR k x l' r)- Tip -> error "Map.deleteFindMin: can not return the minimal element of an empty map"---- | /O(log n)/. Delete and find the maximal element.------ > deleteFindMax (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((10,"c"), fromList [(3,"b"), (5,"a")])--- > deleteFindMax empty Error: can not return the maximal element of an empty map--deleteFindMax :: Map k a -> (k, a, Map k a)-deleteFindMax t- = case t of- Bin _ k x l Tip -> (k, x, l)- Bin _ k x l r -> let (km, m, r') = deleteFindMax r in (km, m, balanceL k x l r')- Tip -> error "Map.deleteFindMax: can not return the maximal element of an empty map"---{--------------------------------------------------------------------- [balance l x r] balances two trees with value x.- The sizes of the trees should balance after decreasing the- size of one of them. (a rotation).-- [delta] is the maximal relative difference between the sizes of- two trees, it corresponds with the [w] in Adams' paper.- [ratio] is the ratio between an outer and inner sibling of the- heavier subtree in an unbalanced setting. It determines- whether a double or single rotation should be performed- to restore balance. It is corresponds with the inverse- of $\alpha$ in Adam's article.-- Note that according to the Adam's paper:- - [delta] should be larger than 4.646 with a [ratio] of 2.- - [delta] should be larger than 3.745 with a [ratio] of 1.534.-- But the Adam's paper is erroneous:- - It can be proved that for delta=2 and delta>=5 there does- not exist any ratio that would work.- - Delta=4.5 and ratio=2 does not work.-- That leaves two reasonable variants, delta=3 and delta=4,- both with ratio=2.-- - A lower [delta] leads to a more 'perfectly' balanced tree.- - A higher [delta] performs less rebalancing.-- In the benchmarks, delta=3 is faster on insert operations,- and delta=4 has slightly better deletes. As the insert speedup- is larger, we currently use delta=3.----------------------------------------------------------------------}-delta,ratio :: Int-delta = 3-ratio = 2---- The balance function is equivalent to the following:------ balance :: k -> a -> Map k a -> Map k a -> Map k a--- balance k x l r--- | sizeL + sizeR <= 1 = Bin sizeX k x l r--- | sizeR > delta*sizeL = rotateL k x l r--- | sizeL > delta*sizeR = rotateR k x l r--- | otherwise = Bin sizeX k x l r--- where--- sizeL = size l--- sizeR = size r--- sizeX = sizeL + sizeR + 1------ rotateL :: a -> b -> Map a b -> Map a b -> Map a b--- rotateL k x l r@(Bin _ _ _ ly ry) | size ly < ratio*size ry = singleL k x l r--- | otherwise = doubleL k x l r------ rotateR :: a -> b -> Map a b -> Map a b -> Map a b--- rotateR k x l@(Bin _ _ _ ly ry) r | size ry < ratio*size ly = singleR k x l r--- | otherwise = doubleR k x l r------ singleL, singleR :: a -> b -> Map a b -> Map a b -> Map a b--- singleL k1 x1 t1 (Bin _ k2 x2 t2 t3) = bin k2 x2 (bin k1 x1 t1 t2) t3--- singleR k1 x1 (Bin _ k2 x2 t1 t2) t3 = bin k2 x2 t1 (bin k1 x1 t2 t3)------ doubleL, doubleR :: a -> b -> Map a b -> Map a b -> Map a b--- doubleL k1 x1 t1 (Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4) = bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)--- doubleR k1 x1 (Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3)) t4 = bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)------ It is only written in such a way that every node is pattern-matched only once.--balance :: k -> a -> Map k a -> Map k a -> Map k a-balance k x l r = case l of- Tip -> case r of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r- (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr- (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)- (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr- | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)-- (Bin ls lk lx ll lr) -> case r of- Tip -> case (ll, lr) of- (Tip, Tip) -> Bin 2 k x l Tip- (Tip, (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)- ((Bin _ _ _ _ _), Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)- ((Bin lls _ _ _ _), (Bin lrs lrk lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)- | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)- (Bin rs rk rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr- | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)- (_, _) -> error "Failure in Data.Map.balance"- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)- | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)- (_, _) -> error "Failure in Data.Map.balance"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balance #-}---- Functions balanceL and balanceR are specialised versions of balance.--- balanceL only checks whether the left subtree is too big,--- balanceR only checks whether the right subtree is too big.---- balanceL is called when left subtree might have been inserted to or when--- right subtree might have been deleted from.-{-@ balanceL :: kcut:k -> a -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-balanceL :: k -> a -> Map k a -> Map k a -> Map k a-balanceL k x l r = case r of- Tip -> case l of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x l Tip- (Bin _ lk lx Tip (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)- (Bin _ lk lx ll@(Bin _ _ _ _ _) Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)- (Bin ls lk lx ll@(Bin lls _ _ _ _) lr@(Bin lrs lrk lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)- | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)-- (Bin rs _ _ _ _) -> case l of- Tip -> Bin (1+rs) k x Tip r-- (Bin ls lk lx ll lr)- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)- | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)- (_, _) -> error "Failure in Data.Map.balanceL"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balanceL #-}---- balanceR is called when right subtree might have been inserted to or when--- left subtree might have been deleted from.-{-@ balanceR :: kcut:k -> a -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-balanceR :: k -> a -> Map k a -> Map k a -> Map k a-balanceR k x l r = case l of- Tip -> case r of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r- (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr- (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)- (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr- | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)-- (Bin ls _ _ _ _) -> case r of- Tip -> Bin (1+ls) k x l Tip-- (Bin rs rk rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr- | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)- (_, _) -> error "Failure in Data.Map.balanceR"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balanceR #-}---{--------------------------------------------------------------------- The bin constructor maintains the size of the tree---------------------------------------------------------------------}-bin :: k -> a -> Map k a -> Map k a -> Map k a-bin k x l r- = Bin (size l + size r + 1) k x l r-{-# INLINE bin #-}--{--------------------------------------------------------------------- Eq converts the tree to a list. In a lazy setting, this- actually seems one of the faster methods to compare two trees- and it is certainly the simplest :-)---------------------------------------------------------------------}-instance (Eq k,Eq a) => Eq (Map k a) where- t1 == t2 = (size t1 == size t2) && (toAscList t1 == toAscList t2)--{--------------------------------------------------------------------- Ord---------------------------------------------------------------------}--instance (Ord k, Ord v) => Ord (Map k v) where- compare m1 m2 = compare (toAscList m1) (toAscList m2)--{--------------------------------------------------------------------- Functor---------------------------------------------------------------------}---- LIQUID instance Functor (Map k) where--- LIQUID fmap f m = map f m--- LIQUID --- LIQUID instance Traversable (Map k) where--- LIQUID traverse f = traverseWithKey (\_ -> f)--- LIQUID --- LIQUID instance Foldable.Foldable (Map k) where--- LIQUID fold Tip = mempty--- LIQUID fold (Bin _ _ v l r) = Foldable.fold l `mappend` v `mappend` Foldable.fold r--- LIQUID foldr = foldr--- LIQUID foldl = foldl--- LIQUID foldMap _ Tip = mempty--- LIQUID foldMap f (Bin _ _ v l r) = Foldable.foldMap f l `mappend` f v `mappend` Foldable.foldMap f r--- LIQUID --- LIQUID instance (NFData k, NFData a) => NFData (Map k a) where--- LIQUID rnf Tip = ()--- LIQUID rnf (Bin _ kx x l r) = rnf kx `seq` rnf x `seq` rnf l `seq` rnf r--{--------------------------------------------------------------------- Read---------------------------------------------------------------------}--- LIQUID instance (Ord k, Read k, Read e) => Read (Map k e) where--- LIQUID #ifdef __GLASGOW_HASKELL__--- LIQUID readPrec = parens $ prec 10 $ do--- LIQUID Ident "fromList" <- lexP--- LIQUID xs <- readPrec--- LIQUID return (fromList xs)--- LIQUID --- LIQUID readListPrec = readListPrecDefault--- LIQUID #else--- LIQUID readsPrec p = readParen (p > 10) $ \ r -> do--- LIQUID ("fromList",s) <- lex r--- LIQUID (xs,t) <- reads s--- LIQUID return (fromList xs,t)--- LIQUID #endif--{--------------------------------------------------------------------- Show---------------------------------------------------------------------}--- LIQUID instance (Show k, Show a) => Show (Map k a) where--- LIQUID showsPrec d m = showParen (d > 10) $--- LIQUID showString "fromList " . shows (toList m)---- | /O(n)/. Show the tree that implements the map. The tree is shown--- in a compressed, hanging format. See 'showTreeWith'.-showTree :: (Show k,Show a) => Map k a -> String-showTree m- = showTreeWith showElem True False m- where- showElem k x = show k ++ ":=" ++ show x---{- | /O(n)/. The expression (@'showTreeWith' showelem hang wide map@) shows- the tree that implements the map. Elements are shown using the @showElem@ function. If @hang@ is- 'True', a /hanging/ tree is shown otherwise a rotated tree is shown. If- @wide@ is 'True', an extra wide version is shown.--> Map> let t = fromDistinctAscList [(x,()) | x <- [1..5]]-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) True False t-> (4,())-> +--(2,())-> | +--(1,())-> | +--(3,())-> +--(5,())->-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) True True t-> (4,())-> |-> +--(2,())-> | |-> | +--(1,())-> | |-> | +--(3,())-> |-> +--(5,())->-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) False True t-> +--(5,())-> |-> (4,())-> |-> | +--(3,())-> | |-> +--(2,())-> |-> +--(1,())---}-showTreeWith :: (k -> a -> String) -> Bool -> Bool -> Map k a -> String-showTreeWith showelem hang wide t- | hang = (showsTreeHang showelem wide [] t) ""- | otherwise = (showsTree showelem wide [] [] t) ""--showsTree :: (k -> a -> String) -> Bool -> [String] -> [String] -> Map k a -> ShowS-showsTree showelem wide lbars rbars t- = case t of- Tip -> showsBars lbars . showString "|\n"- Bin _ kx x Tip Tip- -> showsBars lbars . showString (showelem kx x) . showString "\n"- Bin _ kx x l r- -> showsTree showelem wide (withBar rbars) (withEmpty rbars) r .- showWide wide rbars .- showsBars lbars . showString (showelem kx x) . showString "\n" .- showWide wide lbars .- showsTree showelem wide (withEmpty lbars) (withBar lbars) l--showsTreeHang :: (k -> a -> String) -> Bool -> [String] -> Map k a -> ShowS-showsTreeHang showelem wide bars t- = case t of- Tip -> showsBars bars . showString "|\n"- Bin _ kx x Tip Tip- -> showsBars bars . showString (showelem kx x) . showString "\n"- Bin _ kx x l r- -> showsBars bars . showString (showelem kx x) . showString "\n" .- showWide wide bars .- showsTreeHang showelem wide (withBar bars) l .- showWide wide bars .- showsTreeHang showelem wide (withEmpty bars) r--showWide :: Bool -> [String] -> String -> String-showWide wide bars- | wide = showString (concat (reverse bars)) . showString "|\n"- | otherwise = id--showsBars :: [String] -> ShowS-showsBars bars- = case bars of- [] -> id- _ -> showString (concat (reverse (tail bars))) . showString node--node :: String-node = "+--"--withBar, withEmpty :: [String] -> [String]-withBar bars = "| ":bars-withEmpty bars = " ":bars--{--------------------------------------------------------------------- Typeable---------------------------------------------------------------------}---- LIQUID #include "Typeable.h"--- LIQUID INSTANCE_TYPEABLE2(Map,mapTc,"Map")--{--------------------------------------------------------------------- Assertions---------------------------------------------------------------------}--- | /O(n)/. Test if the internal map structure is valid.------ > valid (fromAscList [(3,"b"), (5,"a")]) == True--- > valid (fromAscList [(5,"a"), (3,"b")]) == False--valid :: Ord k => Map k a -> Bool-valid t- = balanced t && ordered t && validsize t--ordered :: Ord a => Map a b -> Bool-ordered t- = bounded (const True) (const True) t- where- bounded lo hi t'- = case t' of- Tip -> True- Bin _ kx _ l r -> (lo kx) && (hi kx) && bounded lo (<kx) l && bounded (>kx) hi r---- | Exported only for "Debug.QuickCheck"-balanced :: Map k a -> Bool-balanced t- = case t of- Tip -> True- Bin _ _ _ l r -> (size l + size r <= 1 || (size l <= delta*size r && size r <= delta*size l)) &&- balanced l && balanced r--validsize :: Map a b -> Bool-validsize t- = (realsize t == Just (size t))- where- realsize t'- = case t' of- Tip -> Just 0- Bin sz _ _ l r -> case (realsize l,realsize r) of- (Just n,Just m) | n+m+1 == sz -> Just sz- _ -> Nothing--{--------------------------------------------------------------------- Utilities---------------------------------------------------------------------}-foldlStrict :: (a -> b -> a) -> a -> [b] -> a-foldlStrict f = go- where- go z [] = z- go z (x:xs) = let z' = f z x in z' `seq` go z' xs-{-# INLINE foldlStrict #-}
@@ -1,251 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-#if __GLASGOW_HASKELL__--- LIQUID {- LANGUAGE DeriveDataTypeable, StandaloneDeriving -}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--module Data.Map.Base where--import Language.Haskell.Liquid.Prelude--import Prelude hiding (lookup,map,filter,foldr,foldl,null)-import Data.Monoid (Monoid(..))-import Data.Traversable (Traversable(traverse))-import qualified Data.Foldable as Foldable-import Control.DeepSeq (NFData(rnf))--#if __GLASGOW_HASKELL__-import GHC.Exts ( build )-import Text.Read-import Data.Data-#endif--#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined-#define STRICT_1_OF_3(fn) fn arg _ _ | arg `seq` False = undefined-#define STRICT_2_OF_3(fn) fn _ arg _ | arg `seq` False = undefined-#define STRICT_1_OF_4(fn) fn arg _ _ _ | arg `seq` False = undefined-#define STRICT_2_OF_4(fn) fn _ arg _ _ | arg `seq` False = undefined--data Map k a = Bin Size k a (Map k a) (Map k a)- | Tip--type Size = Int--data MaybeS a = NothingS | JustS a--{-@ include <Base.hquals> @-}--{-@ - data Map k a <l :: root:k -> k -> Bool, r :: root:k -> k -> Bool>- = Bin (sz :: Size) - (key :: k) - (value :: a) - (left :: Map <l, r> (k <l key>) a) - (right :: Map <l, r> (k <r key>) a) - | Tip - @-}--{-@ measure isJustS :: forall a. MaybeS a -> Bool - isJustS (JustS x) = true- isJustS (NothingS) = false- @-}--{-@ measure fromJustS :: forall a. MaybeS a -> a- fromJustS (JustS x) = x - @-}--{-@ type OMap k a = Map <{v:k | v < root}, {v:k | v > root}> k a @-}--{-@ measure isBin :: Map k a -> Bool- isBin (Bin sz kx x l r) = true- isBin (Tip) = false- @-}--{-@ measure key :: Map k a -> k - key (Bin sz kx x l r) = kx - @-}-------------------------------------------------------------------------{-@ trim :: (Ord k) => lo:MaybeS k -> hi:MaybeS k -> OMap k a -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } @-}--trim :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k a-trim = error "GOO"---trim NothingS NothingS t = t---trim (JustS lk) NothingS t = greater lk t --- where greater lo t@(Bin _ k _ _ r) | k <= lo = greater lo r--- | otherwise = t--- greater _ t'@Tip = t'---trim NothingS (JustS hk) t = lesser hk t --- where lesser hi t'@(Bin _ k _ l _) | k >= hi = lesser hi l--- | otherwise = t'--- lesser _ t'@Tip = t'---trim (JustS lk) (JustS hk) t = middle lk hk t --- where middle lo hi t'@(Bin _ k _ l r) | k <= lo = middle lo hi r--- | k >= hi = middle lo hi l--- | otherwise = t'--- middle _ _ t'@Tip = t' --{-@ filterGt :: (Ord k) -> x:MaybeS k -> OMap k v -> OMap {v:k | ((isJustS(x)) => (v > fromJustS(x))) } v @-}-filterGt :: Ord k => MaybeS k -> Map k v -> Map k v-filterGt = error "GOO"--{-@ filterLt :: (Ord k) -> x:MaybeS k -> OMap k v -> OMap {v:k | ((isJustS(x)) => (v < fromJustS(x))) } v @-}-filterLt :: Ord k => MaybeS k -> Map k v -> Map k v-filterLt = error "GOO"--{-@ join :: kcut:k -> a -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-join :: k -> a -> Map k a -> Map k a -> Map k a-join kx x l r = Bin 1 kx x l r --{-@ merge :: kcut:k -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-merge :: k -> Map k a -> Map k a -> Map k a-merge = error "gOO"--{-@ member :: Ord k => k -> OMap k a -> Bool @-}-member :: Ord k => k -> Map k a -> Bool -member kx t = error "TODO"--{-@ insertR :: Ord k => k -> a -> OMap k a -> OMap k a @-}-insertR :: Ord k => k -> a -> Map k a -> Map k a-insertR kx x t = error "TODO"--{-@ singleton :: k -> a -> OMap k a @-}-singleton :: k -> a -> Map k a-singleton = error "GOO"--{-@ assert lookup :: (Ord k) => k -> OMap k a -> Maybe a @-}-lookup :: Ord k => k -> Map k a -> Maybe a-lookup = error "TDA"---{-@ hedgeDiff :: (Ord k) => lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } - -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } - | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } - - -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } b - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a @-}--hedgeDiff :: Ord a => MaybeS a -> MaybeS a -> MaybeS a -> MaybeS a -> Map a b -> Map a c -> Map a b-hedgeDiff _ _ _ _ Tip _ = Tip-hedgeDiff blo0 blo bhi0 bhi (Bin _ kx x l r) Tip = join kx x (filterGt blo l) (filterLt bhi r)-hedgeDiff blo0 blo bhi0 bhi t (Bin _ kx _ l r) = merge kx (hedgeDiff blo0 blo bmi bmi (trim blo bmi t) l)- (hedgeDiff bmi bmi bhi0 bhi (trim bmi bhi t) r)- where bmi = JustS kx---------------------------------------------------------------------------------- {- hedgeUnion :: (Ord k) => lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } --- -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } --- | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } --- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a --- -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } --- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a @-}--- --- hedgeUnion :: Ord k => MaybeS k -> MaybeS k -> MaybeS k -> MaybeS k -> Map k b -> Map k b -> Map k b--- hedgeUnion _ _ _ _ t1 Tip = t1--- hedgeUnion blo0 blo bhi0 bhi Tip (Bin _ kx x l r) = join kx x (filterGt blo l) (filterLt bhi r)--- hedgeUnion _ _ _ _ t1 (Bin _ kx x Tip Tip) = insertR kx x t1 -- According to benchmarks, this special case increases--- -- performance up to 30%. It does not help in difference or intersection.--- hedgeUnion blo0 blo bhi0 bhi (Bin _ kx x l r) t2 = join kx x (hedgeUnion blo blo bmi bmi l (trim blo bmi t2))--- (hedgeUnion bmi bmi bhi0 bhi r (trim bmi bhi t2))--- where bmi = JustS kx--- --- {- hedgeInt :: (Ord k) => lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } --- -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } --- | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } --- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a --- -> {v: OMap k b | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } --- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a @-}--- hedgeInt :: Ord k => MaybeS k -> MaybeS k -> MaybeS k -> MaybeS k -> Map k a -> Map k b -> Map k a--- hedgeInt _ _ _ _ _ Tip = Tip--- hedgeInt _ _ _ _ Tip _ = Tip--- hedgeInt blo0 blo bhi0 bhi (Bin _ kx x l r) t2 = let l' = hedgeInt blo0 blo bmi bmi l (trim blo bmi t2)--- r' = hedgeInt bmi bmi bhi0 bhi r (trim bmi bhi t2)--- in if kx `member` t2 then join kx x l' r' else merge kx l' r'--- where bmi = JustS kx-------------------------------------------------------------------------------------{- mergeWithKey :: (Ord k) => (k -> a -> b -> Maybe c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } b- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> OMap k a -> OMap k b -> OMap k c @-}---mergeWithKey :: Ord k => (k -> a -> b -> Maybe c) -> (MaybeS k -> MaybeS k -> Map k a -> Map k c) -> (MaybeS k -> MaybeS k -> Map k b -> Map k c)--- -> Map k a -> Map k b -> Map k c---mergeWithKey f g1 g2 = go--- where--- go Tip t2 = g2 NothingS NothingS t2--- go t1 Tip = g1 NothingS NothingS t1--- go t1 t2 = hedgeMerge f g1 g2 NothingS NothingS NothingS NothingS t1 t2--{-@ hedgeMerge :: (Ord k) => (k -> a -> b -> Maybe c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> (lo:MaybeS k -> hi: MaybeS k - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } b- -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c) - -> lo0:MaybeS k -> lo: {v: MaybeS {v: k | (isJustS(lo0) && (v = fromJustS(lo0))) } | v = lo0 } - -> hi0:MaybeS k -> hi:{v: MaybeS {v: k | ( isJustS(hi0) && (v = fromJustS(hi0))) } - | (((isJustS(lo) && isJustS(v)) => (fromJustS(v) >= fromJustS(lo))) && (v = hi0)) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } a - -> {v: OMap k b | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } - -> OMap {v: k | (((isJustS(lo)) => (v > fromJustS(lo))) && (((isJustS(hi)) => (v < fromJustS(hi))))) } c @-}--hedgeMerge :: Ord k => (k -> a -> b -> Maybe c) - -> (MaybeS k -> MaybeS k -> Map k a -> Map k c) - -> (MaybeS k -> MaybeS k -> Map k b -> Map k c)- -> MaybeS k -> MaybeS k -> MaybeS k -> MaybeS k - -> Map k a -> Map k b -> Map k c-hedgeMerge f g1 g2 _ blo _ bhi t1 Tip - = g1 blo bhi t1-hedgeMerge f g1 g2 blo0 blo bhi0 bhi Tip (Bin _ kx x l r) - = g2 blo bhi $ join kx x (filterGt blo l) (filterLt bhi r)-hedgeMerge f g1 g2 blo0 blo bhi0 bhi (Bin _ kx x l r) t2 - = let bmi = JustS kx - l' = hedgeMerge f g1 g2 blo0 blo bmi bmi l (trim blo bmi t2)- (found, trim_t2) = trimLookupLo kx bhi t2- r' = hedgeMerge f g1 g2 bmi bmi bhi0 bhi r trim_t2- in case found of- Nothing -> case g1 blo bhi (singleton kx x) of- Tip -> merge kx l' r'- (Bin _ _ x' Tip Tip) -> join kx x' l' r'- _ -> error "mergeWithKey: Given function only1 does not fulfil required conditions (see documentation)"- Just x2 -> case f kx x x2 of- Nothing -> merge kx l' r'- Just x' -> join kx x' l' r'--{-@ trimLookupLo :: (Ord k) - => lo:k - -> bhi:{v: MaybeS k | (isJustS(v) => (lo < fromJustS(v)))} - -> OMap k a - -> (Maybe a, {v: OMap k a | ((isBin(v) => (lo < key(v))) && ((isBin(v) && isJustS(bhi)) => (fromJustS(bhi) > key(v)))) }) @-}--trimLookupLo :: Ord k => k -> MaybeS k -> Map k a -> (Maybe a, Map k a)-trimLookupLo lk NothingS t = greater lk t- where greater :: Ord k => k -> Map k a -> (Maybe a, Map k a)- greater lo t'@(Bin _ kx x l r) = case compare lo kx of LT -> (lookup lo l, {-`strictPair`-} t')- EQ -> (Just x, (case r of {r'@(Bin _ _ _ _ _) -> r' ; r'@Tip -> r'}))- GT -> greater lo r- greater _ Tip = (Nothing, Tip)-trimLookupLo lk (JustS hk) t = middle lk hk t- where middle :: Ord k => k -> k -> Map k a -> (Maybe a, Map k a)- middle lo hi t'@(Bin _ kx x l r) = case compare lo kx of LT | kx < hi -> (lookup lo l, {- `strictPair` -} t')- | otherwise -> middle lo hi l- EQ -> (Just x, {-`strictPair`-} lesser lo hi (case r of {r'@(Bin _ _ _ _ _) -> r' ; r'@Tip -> r'}))- GT -> middle lo hi r- middle _ _ Tip = (Nothing, Tip)- - lesser :: Ord k => k -> k -> Map k a -> Map k a- lesser lo hi t'@(Bin _ k _ l _) | k >= hi = lesser lo hi l- | otherwise = t'- lesser _ _ t'@Tip = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trimLookupLo #-}-#endif
@@ -1,66 +0,0 @@-module Foo (- Map(..) -- instance Eq,Show,Read- , trim- ) where--data Map k a = Bin Size k a (Map k a) (Map k a)- | Tip--data MaybeS a = NothingS | JustS a -- LIQUID: !-annot-fix--type Size = Int--{-@ include <Base.hquals> @-}--{-@ - data Map k a <l :: root:k -> k -> Bool, r :: root:k -> k -> Bool>- = Bin (sz :: Size) - (key :: k) - (value :: a) - (left :: Map <l, r> (k <l key>) a) - (right :: Map <l, r> (k <r key>) a) - | Tip - @-}--{-@ type OMap k a = Map <{v:k | v < root}, {v:k | v > root}> k a @-}--{-@ measure isJustS :: forall a. MaybeS a -> Bool - isJustS (JustS x) = true- isJustS (NothingS) = false- @-}--{-@ measure fromJustS :: forall a. MaybeS a -> a - fromJustS (JustS x) = x - @-}--{-@ measure isBin :: Map k a -> Bool- isBin (Bin sz kx x l r) = true- isBin (Tip) = false- @-}--{-@ measure key :: Map k a -> k - key (Bin sz kx x l r) = kx - @-}--{-@ trim :: (Ord k) => lo:MaybeS k - -> hi:MaybeS k - -> OMap k a - -> {v: OMap k a | (((isBin(v) && isJustS(lo)) => (fromJustS(lo) < key(v))) && - ((isBin(v) && isJustS(hi)) => (fromJustS(hi) > key(v)))) } @-}--trim :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k a-trim NothingS NothingS t = t-trim (JustS lk) NothingS t = greater lk t - where greater lo t@(Bin _ k _ _ r) | k <= lo = greater lo r- | otherwise = t- greater _ t'@Tip = t'-trim NothingS (JustS hk) t = lesser hk t - where lesser hi t'@(Bin _ k _ l _) | k >= hi = lesser hi l- | otherwise = t'- lesser _ t'@Tip = t'-trim (JustS lk) (JustS hk) t = middle lk hk t - where middle lo hi t'@(Bin _ k _ l r) | k <= lo = middle lo hi r- | k >= hi = middle lo hi l- | otherwise = t'- middle _ _ t'@Tip = t'-
@@ -1,2718 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Map.Base--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from keys to values (dictionaries).------ Since many function names (but not the type name) clash with--- "Prelude" names, this module is usually imported @qualified@, e.g.------ > import Data.Map (Map)--- > import qualified Data.Map as Map------ The implementation of 'Map' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.---------------------------------------------------------------------------------- [Note: Using INLINABLE]--- ~~~~~~~~~~~~~~~~~~~~~~~--- It is crucial to the performance that the functions specialize on the Ord--- type when possible. GHC 7.0 and higher does this by itself when it sees th--- unfolding of a function -- that is why all public functions are marked--- INLINABLE (that exposes the unfolding).----- [Note: Using INLINE]--- ~~~~~~~~~~~~~~~~~~~~--- For other compilers and GHC pre 7.0, we mark some of the functions INLINE.--- We mark the functions that just navigate down the tree (lookup, insert,--- delete and similar). That navigation code gets inlined and thus specialized--- when possible. There is a price to pay -- code growth. The code INLINED is--- therefore only the tree navigation, all the real work (rebalancing) is not--- INLINED by using a NOINLINE.------ All methods marked INLINE have to be nonrecursive -- a 'go' function doing--- the real work is provided.----- [Note: Type of local 'go' function]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- If the local 'go' function uses an Ord class, it sometimes heap-allocates--- the Ord dictionary when the 'go' function does not have explicit type.--- In that case we give 'go' explicit type. But this slightly decrease--- performance, as the resulting 'go' function can float out to top level.----- [Note: Local 'go' functions and capturing]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- As opposed to IntMap, when 'go' function captures an argument, increased--- heap-allocation can occur: sometimes in a polymorphic function, the 'go'--- floats out of its enclosing function and then it heap-allocates the--- dictionary and the argument. Maybe it floats out too late and strictness--- analyzer cannot see that these could be passed on stack.------ For example, change 'member' so that its local 'go' function is not passing--- argument k and then look at the resulting code for hedgeInt.----- [Note: Order of constructors]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- The order of constructors of Map matters when considering performance.--- Currently in GHC 7.0, when type has 2 constructors, a forward conditional--- jump is made when successfully matching second constructor. Successful match--- of first constructor results in the forward jump not taken.--- On GHC 7.0, reordering constructors from Tip | Bin to Bin | Tip--- improves the benchmark by up to 10% on x86.--module Data.Map.Base (- -- * Map type- Map(..) -- instance Eq,Show,Read-- -- * Operators- , (!), (\\)-- -- * Query- , null- , size- , member- , notMember- , lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , map- , mapWithKey- , traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , foldr- , foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- , keysSet- , fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Indexed- , lookupIndex- , findIndex- , elemAt- , updateAt- , deleteAt-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- , valid-- -- Used by the strict version- , bin- , balance- , balanced- , balanceL- , balanceR- , delta- , join- , merge- , glue- , trim- , trimLookupLo- , foldlStrict- , MaybeS(..)- , filterGt- , filterLt- ) where--import Prelude hiding (lookup,map,filter,foldr,foldl,null)-import qualified Data.Set.Base as Set-import Data.StrictPair-import Data.Monoid (Monoid(..))-import Control.Applicative (Applicative(..), (<$>))-import Data.Traversable (Traversable(traverse))-import qualified Data.Foldable as Foldable--- import Data.Typeable-import Control.DeepSeq (NFData(rnf))--#if __GLASGOW_HASKELL__-import GHC.Exts ( build )-import Text.Read-import Data.Data-#endif---- Use macros to define strictness of functions.--- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.--- We do not use BangPatterns, because they are not in any standard and we--- want the compilers to be compiled by as many compilers as possible.-#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined-#define STRICT_1_OF_3(fn) fn arg _ _ | arg `seq` False = undefined-#define STRICT_2_OF_3(fn) fn _ arg _ | arg `seq` False = undefined-#define STRICT_1_OF_4(fn) fn arg _ _ _ | arg `seq` False = undefined-#define STRICT_2_OF_4(fn) fn _ arg _ _ | arg `seq` False = undefined--{--------------------------------------------------------------------- Operators---------------------------------------------------------------------}-infixl 9 !,\\ ------ | /O(log n)/. Find the value at a key.--- Calls 'error' when the element can not be found.------ > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map--- > fromList [(5,'a'), (3,'b')] ! 5 == 'a'--(!) :: Ord k => Map k a -> k -> a-m ! k = find k m-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (!) #-}-#endif---- | Same as 'difference'.-(\\) :: Ord k => Map k a -> Map k b -> Map k a-m1 \\ m2 = difference m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (\\) #-}-#endif--{--------------------------------------------------------------------- Size balanced trees.---------------------------------------------------------------------}--- | A Map from keys @k@ to values @a@.---- See Note: Order of constructors-data Map k a = Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)- | Tip--type Size = Int--instance (Ord k) => Monoid (Map k v) where- mempty = empty- mappend = union- mconcat = unions--#if __GLASGOW_HASKELL__--{--------------------------------------------------------------------- A Data instance---------------------------------------------------------------------}---- This instance preserves data abstraction at the cost of inefficiency.--- We omit reflection services for the sake of data abstraction.-instance (Data k, Data a, Ord k) => Data (Map k a) where- gfoldl f z m = z fromList `f` toList m- toConstr _ = error "toConstr"- gunfold _ _ = error "gunfold"- dataTypeOf _ = mkNoRepType "Data.Map.Map"- dataCast2 f = gcast2 f-#endif--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}--- | /O(1)/. Is the map empty?------ > Data.Map.null (empty) == True--- > Data.Map.null (singleton 1 'a') == False--null :: Map k a -> Bool-null Tip = True-null (Bin {}) = False-{-# INLINE null #-}---- | /O(1)/. The number of elements in the map.------ > size empty == 0--- > size (singleton 1 'a') == 1--- > size (fromList([(1,'a'), (2,'c'), (3,'b')])) == 3--size :: Map k a -> Int-size Tip = 0-size (Bin sz _ _ _ _) = sz-{-# INLINE size #-}----- | /O(log n)/. Lookup the value at a key in the map.------ The function will return the corresponding value as @('Just' value)@,--- or 'Nothing' if the key isn't in the map.------ An example of using @lookup@:------ > import Prelude hiding (lookup)--- > import Data.Map--- >--- > employeeDept = fromList([("John","Sales"), ("Bob","IT")])--- > deptCountry = fromList([("IT","USA"), ("Sales","France")])--- > countryCurrency = fromList([("USA", "Dollar"), ("France", "Euro")])--- >--- > employeeCurrency :: String -> Maybe String--- > employeeCurrency name = do--- > dept <- lookup name employeeDept--- > country <- lookup dept deptCountry--- > lookup country countryCurrency--- >--- > main = do--- > putStrLn $ "John's currency: " ++ (show (employeeCurrency "John"))--- > putStrLn $ "Pete's currency: " ++ (show (employeeCurrency "Pete"))------ The output of this program:------ > John's currency: Just "Euro"--- > Pete's currency: Nothing-lookup :: Ord k => k -> Map k a -> Maybe a-lookup = go- where- STRICT_1_OF_2(go)- go _ Tip = Nothing- go k (Bin _ kx x l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> Just x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookup #-}-#else-{-# INLINE lookup #-}-#endif---- | /O(log n)/. Is the key a member of the map? See also 'notMember'.------ > member 5 (fromList [(5,'a'), (3,'b')]) == True--- > member 1 (fromList [(5,'a'), (3,'b')]) == False-member :: Ord k => k -> Map k a -> Bool-member = go- where- STRICT_1_OF_2(go)- go _ Tip = False- go k (Bin _ kx _ l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> True-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE member #-}-#else-{-# INLINE member #-}-#endif---- | /O(log n)/. Is the key not a member of the map? See also 'member'.------ > notMember 5 (fromList [(5,'a'), (3,'b')]) == False--- > notMember 1 (fromList [(5,'a'), (3,'b')]) == True--notMember :: Ord k => k -> Map k a -> Bool-notMember k m = not $ member k m-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE notMember #-}-#else-{-# INLINE notMember #-}-#endif---- | /O(log n)/. Find the value at a key.--- Calls 'error' when the element can not be found.-find :: Ord k => k -> Map k a -> a-find = go- where- STRICT_1_OF_2(go)- go _ Tip = error "Map.!: given key is not an element in the map"- go k (Bin _ kx x l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE find #-}-#else-{-# INLINE find #-}-#endif---- | /O(log n)/. The expression @('findWithDefault' def k map)@ returns--- the value at key @k@ or returns default value @def@--- when the key is not in the map.------ > findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) == 'x'--- > findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) == 'a'-findWithDefault :: Ord k => a -> k -> Map k a -> a-findWithDefault = go- where- STRICT_2_OF_3(go)- go def _ Tip = def- go def k (Bin _ kx x l r) = case compare k kx of- LT -> go def k l- GT -> go def k r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findWithDefault #-}-#else-{-# INLINE findWithDefault #-}-#endif---- | /O(log n)/. Find largest key smaller than the given one and return the--- corresponding (key, value) pair.------ > lookupLT 3 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLT 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')-lookupLT :: Ord k => k -> Map k v -> Maybe (k, v)-lookupLT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) | k <= kx = goNothing k l- | otherwise = goJust k kx x r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) | k <= kx = goJust k kx' x' l- | otherwise = goJust k kx x r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLT #-}-#else-{-# INLINE lookupLT #-}-#endif---- | /O(log n)/. Find smallest key greater than the given one and return the--- corresponding (key, value) pair.------ > lookupGT 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGT 5 (fromList [(3,'a'), (5,'b')]) == Nothing-lookupGT :: Ord k => k -> Map k v -> Maybe (k, v)-lookupGT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) | k < kx = goJust k kx x l- | otherwise = goNothing k r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) | k < kx = goJust k kx x l- | otherwise = goJust k kx' x' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGT #-}-#else-{-# INLINE lookupGT #-}-#endif---- | /O(log n)/. Find largest key smaller or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupLE 2 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLE 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupLE 5 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')-lookupLE :: Ord k => k -> Map k v -> Maybe (k, v)-lookupLE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) = case compare k kx of LT -> goNothing k l- EQ -> Just (kx, x)- GT -> goJust k kx x r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx' x' l- EQ -> Just (kx, x)- GT -> goJust k kx x r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLE #-}-#else-{-# INLINE lookupLE #-}-#endif---- | /O(log n)/. Find smallest key greater or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupGE 3 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupGE 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGE 6 (fromList [(3,'a'), (5,'b')]) == Nothing-lookupGE :: Ord k => k -> Map k v -> Maybe (k, v)-lookupGE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx x l- EQ -> Just (kx, x)- GT -> goNothing k r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx x l- EQ -> Just (kx, x)- GT -> goJust k kx' x' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGE #-}-#else-{-# INLINE lookupGE #-}-#endif--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. The empty map.------ > empty == fromList []--- > size empty == 0--empty :: Map k a-empty = Tip-{-# INLINE empty #-}---- | /O(1)/. A map with a single element.------ > singleton 1 'a' == fromList [(1, 'a')]--- > size (singleton 1 'a') == 1--singleton :: k -> a -> Map k a-singleton k x = Bin 1 k x Tip Tip-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insertion---------------------------------------------------------------------}--- | /O(log n)/. Insert a new key and value in the map.--- If the key is already present in the map, the associated value is--- replaced with the supplied value. 'insert' is equivalent to--- @'insertWith' 'const'@.------ > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]--- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]--- > insert 5 'x' empty == singleton 5 'x'---- See Note: Type of local 'go' function-insert :: Ord k => k -> a -> Map k a -> Map k a-insert = go- where- go :: Ord k => k -> a -> Map k a -> Map k a- STRICT_1_OF_3(go)- go kx x Tip = singleton kx x- go kx x (Bin sz ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go kx x l) r- GT -> balanceR ky y l (go kx x r)- EQ -> Bin sz kx x l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insert #-}-#else-{-# INLINE insert #-}-#endif---- Insert a new key and value in the map if it is not already present.--- Used by `union`.---- See Note: Type of local 'go' function-insertR :: Ord k => k -> a -> Map k a -> Map k a-insertR = go- where- go :: Ord k => k -> a -> Map k a -> Map k a- STRICT_1_OF_3(go)- go kx x Tip = singleton kx x- go kx x t@(Bin _ ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go kx x l) r- GT -> balanceR ky y l (go kx x r)- EQ -> t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertR #-}-#else-{-# INLINE insertR #-}-#endif---- | /O(log n)/. Insert with a function, combining new value and old value.--- @'insertWith' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key, f new_value old_value)@.------ > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]--- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"--insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWith f = insertWithKey (\_ x' y' -> f x' y')-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWith #-}-#else-{-# INLINE insertWith #-}-#endif---- | /O(log n)/. Insert with a function, combining key, new value and old value.--- @'insertWithKey' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key,f key new_value old_value)@.--- Note that the key passed to f is the same key passed to 'insertWithKey'.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]--- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"---- See Note: Type of local 'go' function-insertWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWithKey = go- where- go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a- STRICT_2_OF_4(go)- go _ kx x Tip = singleton kx x- go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go f kx x l) r- GT -> balanceR ky y l (go f kx x r)- EQ -> Bin sy kx (f kx x y) l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWithKey #-}-#else-{-# INLINE insertWithKey #-}-#endif---- | /O(log n)/. Combines insert operation with old value retrieval.--- The expression (@'insertLookupWithKey' f k x map@)--- is a pair where the first element is equal to (@'lookup' k map@)--- and the second element equal to (@'insertWithKey' f k x map@).------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])--- > insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])--- > insertLookupWithKey f 5 "xxx" empty == (Nothing, singleton 5 "xxx")------ This is how to define @insertLookup@ using @insertLookupWithKey@:------ > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t--- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])--- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])---- See Note: Type of local 'go' function-insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a- -> (Maybe a, Map k a)-insertLookupWithKey = go- where- go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)- STRICT_2_OF_4(go)- go _ kx x Tip = (Nothing, singleton kx x)- go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> let (found, l') = go f kx x l- in (found, balanceL ky y l' r)- GT -> let (found, r') = go f kx x r- in (found, balanceR ky y l r')- EQ -> (Just y, Bin sy kx (f kx x y) l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertLookupWithKey #-}-#else-{-# INLINE insertLookupWithKey #-}-#endif--{--------------------------------------------------------------------- Deletion---------------------------------------------------------------------}--- | /O(log n)/. Delete a key and its value from the map. When the key is not--- a member of the map, the original map is returned.------ > delete 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > delete 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > delete 5 empty == empty---- See Note: Type of local 'go' function-delete :: Ord k => k -> Map k a -> Map k a-delete = go- where- go :: Ord k => k -> Map k a -> Map k a- STRICT_1_OF_2(go)- go _ Tip = Tip- go k (Bin _ kx x l r) =- case compare k kx of- LT -> balanceR kx x (go k l) r- GT -> balanceL kx x l (go k r)- EQ -> glue l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE delete #-}-#else-{-# INLINE delete #-}-#endif---- | /O(log n)/. Update a value at a specific key with the result of the provided function.--- When the key is not--- a member of the map, the original map is returned.------ > adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjust ("new " ++) 7 empty == empty--adjust :: Ord k => (a -> a) -> k -> Map k a -> Map k a-adjust f = adjustWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjust #-}-#else-{-# INLINE adjust #-}-#endif---- | /O(log n)/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > let f key x = (show key) ++ ":new " ++ x--- > adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjustWithKey f 7 empty == empty--adjustWithKey :: Ord k => (k -> a -> a) -> k -> Map k a -> Map k a-adjustWithKey f = updateWithKey (\k' x' -> Just (f k' x'))-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjustWithKey #-}-#else-{-# INLINE adjustWithKey #-}-#endif---- | /O(log n)/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f x = if x == "a" then Just "new a" else Nothing--- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a-update f = updateWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE update #-}-#else-{-# INLINE update #-}-#endif---- | /O(log n)/. The expression (@'updateWithKey' f k map@) updates the--- value @x@ at @k@ (if it is in the map). If (@f k x@) is 'Nothing',--- the element is deleted. If it is (@'Just' y@), the key @k@ is bound--- to the new value @y@.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"---- See Note: Type of local 'go' function-updateWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a-updateWithKey = go- where- go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a- STRICT_2_OF_3(go)- go _ _ Tip = Tip- go f k(Bin sx kx x l r) =- case compare k kx of- LT -> balanceR kx x (go f k l) r- GT -> balanceL kx x l (go f k r)- EQ -> case f kx x of- Just x' -> Bin sx kx x' l r- Nothing -> glue l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateWithKey #-}-#else-{-# INLINE updateWithKey #-}-#endif---- | /O(log n)/. Lookup and update. See also 'updateWithKey'.--- The function returns changed value, if it is updated.--- Returns the original key value if the map entry is deleted.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) == (Just "5:new a", fromList [(3, "b"), (5, "5:new a")])--- > updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a")])--- > updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) == (Just "b", singleton 5 "a")---- See Note: Type of local 'go' function-updateLookupWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)-updateLookupWithKey = go- where- go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)- STRICT_2_OF_3(go)- go _ _ Tip = (Nothing,Tip)- go f k (Bin sx kx x l r) =- case compare k kx of- LT -> let (found,l') = go f k l in (found,balanceR kx x l' r)- GT -> let (found,r') = go f k r in (found,balanceL kx x l r')- EQ -> case f kx x of- Just x' -> (Just x',Bin sx kx x' l r)- Nothing -> (Just x,glue l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateLookupWithKey #-}-#else-{-# INLINE updateLookupWithKey #-}-#endif---- | /O(log n)/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.--- 'alter' can be used to insert, delete, or update a value in a 'Map'.--- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.------ > let f _ = Nothing--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- >--- > let f _ = Just "c"--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "c")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "c")]---- See Note: Type of local 'go' function-alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a-alter = go- where- go :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a- STRICT_2_OF_3(go)- go f k Tip = case f Nothing of- Nothing -> Tip- Just x -> singleton k x-- go f k (Bin sx kx x l r) = case compare k kx of- LT -> balance kx x (go f k l) r- GT -> balance kx x l (go f k r)- EQ -> case f (Just x) of- Just x' -> Bin sx kx x' l r- Nothing -> glue l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE alter #-}-#else-{-# INLINE alter #-}-#endif--{--------------------------------------------------------------------- Indexing---------------------------------------------------------------------}--- | /O(log n)/. Return the /index/ of a key. The index is a number from--- /0/ up to, but not including, the 'size' of the map. Calls 'error' when--- the key is not a 'member' of the map.------ > findIndex 2 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map--- > findIndex 3 (fromList [(5,"a"), (3,"b")]) == 0--- > findIndex 5 (fromList [(5,"a"), (3,"b")]) == 1--- > findIndex 6 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map---- See Note: Type of local 'go' function-findIndex :: Ord k => k -> Map k a -> Int-findIndex = go 0- where- go :: Ord k => Int -> k -> Map k a -> Int- STRICT_1_OF_3(go)- STRICT_2_OF_3(go)- go _ _ Tip = error "Map.findIndex: element is not in the map"- go idx k (Bin _ kx _ l r) = case compare k kx of- LT -> go idx k l- GT -> go (idx + size l + 1) k r- EQ -> idx + size l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findIndex #-}-#endif---- | /O(log n)/. Lookup the /index/ of a key. The index is a number from--- /0/ up to, but not including, the 'size' of the map.------ > isJust (lookupIndex 2 (fromList [(5,"a"), (3,"b")])) == False--- > fromJust (lookupIndex 3 (fromList [(5,"a"), (3,"b")])) == 0--- > fromJust (lookupIndex 5 (fromList [(5,"a"), (3,"b")])) == 1--- > isJust (lookupIndex 6 (fromList [(5,"a"), (3,"b")])) == False---- See Note: Type of local 'go' function-lookupIndex :: Ord k => k -> Map k a -> Maybe Int-lookupIndex = go 0- where- go :: Ord k => Int -> k -> Map k a -> Maybe Int- STRICT_1_OF_3(go)- STRICT_2_OF_3(go)- go _ _ Tip = Nothing- go idx k (Bin _ kx _ l r) = case compare k kx of- LT -> go idx k l- GT -> go (idx + size l + 1) k r- EQ -> Just $! idx + size l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupIndex #-}-#endif---- | /O(log n)/. Retrieve an element by /index/. Calls 'error' when an--- invalid index is used.------ > elemAt 0 (fromList [(5,"a"), (3,"b")]) == (3,"b")--- > elemAt 1 (fromList [(5,"a"), (3,"b")]) == (5, "a")--- > elemAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--elemAt :: Int -> Map k a -> (k,a)-STRICT_1_OF_2(elemAt)-elemAt _ Tip = error "Map.elemAt: index out of range"-elemAt i (Bin _ kx x l r)- = case compare i sizeL of- LT -> elemAt i l- GT -> elemAt (i-sizeL-1) r- EQ -> (kx,x)- where- sizeL = size l---- | /O(log n)/. Update the element at /index/. Calls 'error' when an--- invalid index is used.------ > updateAt (\ _ _ -> Just "x") 0 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "x"), (5, "a")]--- > updateAt (\ _ _ -> Just "x") 1 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "x")]--- > updateAt (\ _ _ -> Just "x") 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\ _ _ -> Just "x") (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > updateAt (\_ _ -> Nothing) 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a-updateAt f i t = i `seq`- case t of- Tip -> error "Map.updateAt: index out of range"- Bin sx kx x l r -> case compare i sizeL of- LT -> balanceR kx x (updateAt f i l) r- GT -> balanceL kx x l (updateAt f (i-sizeL-1) r)- EQ -> case f kx x of- Just x' -> Bin sx kx x' l r- Nothing -> glue l r- where- sizeL = size l---- | /O(log n)/. Delete the element at /index/.--- Defined as (@'deleteAt' i map = 'updateAt' (\k x -> 'Nothing') i map@).------ > deleteAt 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > deleteAt 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > deleteAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > deleteAt (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--deleteAt :: Int -> Map k a -> Map k a-deleteAt i t = i `seq`- case t of- Tip -> error "Map.deleteAt: index out of range"- Bin _ kx x l r -> case compare i sizeL of- LT -> balanceR kx x (deleteAt i l) r- GT -> balanceL kx x l (deleteAt (i-sizeL-1) r)- EQ -> glue l r- where- sizeL = size l---{--------------------------------------------------------------------- Minimal, Maximal---------------------------------------------------------------------}--- | /O(log n)/. The minimal key of the map. Calls 'error' if the map is empty.------ > findMin (fromList [(5,"a"), (3,"b")]) == (3,"b")--- > findMin empty Error: empty map has no minimal element--findMin :: Map k a -> (k,a)-findMin (Bin _ kx x Tip _) = (kx,x)-findMin (Bin _ _ _ l _) = findMin l-findMin Tip = error "Map.findMin: empty map has no minimal element"---- | /O(log n)/. The maximal key of the map. Calls 'error' if the map is empty.------ > findMax (fromList [(5,"a"), (3,"b")]) == (5,"a")--- > findMax empty Error: empty map has no maximal element--findMax :: Map k a -> (k,a)-findMax (Bin _ kx x _ Tip) = (kx,x)-findMax (Bin _ _ _ _ r) = findMax r-findMax Tip = error "Map.findMax: empty map has no maximal element"---- | /O(log n)/. Delete the minimal key. Returns an empty map if the map is empty.------ > deleteMin (fromList [(5,"a"), (3,"b"), (7,"c")]) == fromList [(5,"a"), (7,"c")]--- > deleteMin empty == empty--deleteMin :: Map k a -> Map k a-deleteMin (Bin _ _ _ Tip r) = r-deleteMin (Bin _ kx x l r) = balanceR kx x (deleteMin l) r-deleteMin Tip = Tip---- | /O(log n)/. Delete the maximal key. Returns an empty map if the map is empty.------ > deleteMax (fromList [(5,"a"), (3,"b"), (7,"c")]) == fromList [(3,"b"), (5,"a")]--- > deleteMax empty == empty--deleteMax :: Map k a -> Map k a-deleteMax (Bin _ _ _ l Tip) = l-deleteMax (Bin _ kx x l r) = balanceL kx x l (deleteMax r)-deleteMax Tip = Tip---- | /O(log n)/. Update the value at the minimal key.------ > updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "Xb"), (5, "a")]--- > updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMin :: (a -> Maybe a) -> Map k a -> Map k a-updateMin f m- = updateMinWithKey (\_ x -> f x) m---- | /O(log n)/. Update the value at the maximal key.------ > updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "Xa")]--- > updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMax :: (a -> Maybe a) -> Map k a -> Map k a-updateMax f m- = updateMaxWithKey (\_ x -> f x) m----- | /O(log n)/. Update the value at the minimal key.------ > updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"3:b"), (5,"a")]--- > updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMinWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMinWithKey _ Tip = Tip-updateMinWithKey f (Bin sx kx x Tip r) = case f kx x of- Nothing -> r- Just x' -> Bin sx kx x' Tip r-updateMinWithKey f (Bin _ kx x l r) = balanceR kx x (updateMinWithKey f l) r---- | /O(log n)/. Update the value at the maximal key.------ > updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"b"), (5,"5:a")]--- > updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMaxWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMaxWithKey _ Tip = Tip-updateMaxWithKey f (Bin sx kx x l Tip) = case f kx x of- Nothing -> l- Just x' -> Bin sx kx x' l Tip-updateMaxWithKey f (Bin _ kx x l r) = balanceL kx x l (updateMaxWithKey f r)---- | /O(log n)/. Retrieves the minimal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > minViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((3,"b"), singleton 5 "a")--- > minViewWithKey empty == Nothing--minViewWithKey :: Map k a -> Maybe ((k,a), Map k a)-minViewWithKey Tip = Nothing-minViewWithKey x = Just (deleteFindMin x)---- | /O(log n)/. Retrieves the maximal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > maxViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((5,"a"), singleton 3 "b")--- > maxViewWithKey empty == Nothing--maxViewWithKey :: Map k a -> Maybe ((k,a), Map k a)-maxViewWithKey Tip = Nothing-maxViewWithKey x = Just (deleteFindMax x)---- | /O(log n)/. Retrieves the value associated with minimal key of the--- map, and the map stripped of that element, or 'Nothing' if passed an--- empty map.------ > minView (fromList [(5,"a"), (3,"b")]) == Just ("b", singleton 5 "a")--- > minView empty == Nothing--minView :: Map k a -> Maybe (a, Map k a)-minView Tip = Nothing-minView x = Just (first snd $ deleteFindMin x)---- | /O(log n)/. Retrieves the value associated with maximal key of the--- map, and the map stripped of that element, or 'Nothing' if passed an------ > maxView (fromList [(5,"a"), (3,"b")]) == Just ("a", singleton 3 "b")--- > maxView empty == Nothing--maxView :: Map k a -> Maybe (a, Map k a)-maxView Tip = Nothing-maxView x = Just (first snd $ deleteFindMax x)---- Update the 1st component of a tuple (special case of Control.Arrow.first)-first :: (a -> b) -> (a,c) -> (b,c)-first f (x,y) = (f x, y)--{--------------------------------------------------------------------- Union.---------------------------------------------------------------------}--- | The union of a list of maps:--- (@'unions' == 'Prelude.foldl' 'union' 'empty'@).------ > unions [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "b"), (5, "a"), (7, "C")]--- > unions [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]--- > == fromList [(3, "B3"), (5, "A3"), (7, "C")]--unions :: Ord k => [Map k a] -> Map k a-unions ts- = foldlStrict union empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unions #-}-#endif---- | The union of a list of maps, with a combining operation:--- (@'unionsWith' f == 'Prelude.foldl' ('unionWith' f) 'empty'@).------ > unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--unionsWith :: Ord k => (a->a->a) -> [Map k a] -> Map k a-unionsWith f ts- = foldlStrict (unionWith f) empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionsWith #-}-#endif---- | /O(n+m)/.--- The expression (@'union' t1 t2@) takes the left-biased union of @t1@ and @t2@.--- It prefers @t1@ when duplicate keys are encountered,--- i.e. (@'union' == 'unionWith' 'const'@).--- The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > union (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "a"), (7, "C")]--union :: Ord k => Map k a -> Map k a -> Map k a-union Tip t2 = t2-union t1 Tip = t1-union t1 t2 = hedgeUnion NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE union #-}-#endif---- left-biased hedge union-hedgeUnion :: Ord a => MaybeS a -> MaybeS a -> Map a b -> Map a b -> Map a b-hedgeUnion _ _ t1 Tip = t1-hedgeUnion blo bhi Tip (Bin _ kx x l r) = join kx x (filterGt blo l) (filterLt bhi r)-hedgeUnion _ _ t1 (Bin _ kx x Tip Tip) = insertR kx x t1 -- According to benchmarks, this special case increases- -- performance up to 30%. It does not help in difference or intersection.-hedgeUnion blo bhi (Bin _ kx x l r) t2 = join kx x (hedgeUnion blo bmi l (trim blo bmi t2))- (hedgeUnion bmi bhi r (trim bmi bhi t2))- where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeUnion #-}-#endif--{--------------------------------------------------------------------- Union with a combining function---------------------------------------------------------------------}--- | /O(n+m)/. Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.------ > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]--unionWith :: Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWith f m1 m2- = unionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWith #-}-#endif---- | /O(n+m)/.--- Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]--unionWithKey :: Ord k => (k -> a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) id id t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWithKey #-}-#endif--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}--- | /O(n+m)/. Difference of two maps.--- Return elements of the first map not existing in the second map.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 3 "b"--difference :: Ord k => Map k a -> Map k b -> Map k a-difference Tip _ = Tip-difference t1 Tip = t1-difference t1 t2 = hedgeDiff NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE difference #-}-#endif--hedgeDiff :: Ord a => MaybeS a -> MaybeS a -> Map a b -> Map a c -> Map a b-hedgeDiff _ _ Tip _ = Tip-hedgeDiff blo bhi (Bin _ kx x l r) Tip = join kx x (filterGt blo l) (filterLt bhi r)-hedgeDiff blo bhi t (Bin _ kx _ l r) = merge (hedgeDiff blo bmi (trim blo bmi t) l)- (hedgeDiff bmi bhi (trim bmi bhi t) r)- where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeDiff #-}-#endif---- | /O(n+m)/. Difference with a combining function.--- When two equal keys are--- encountered, the combining function is applied to the values of these keys.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f al ar = if al == "b" then Just (al ++ ":" ++ ar) else Nothing--- > differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])--- > == singleton 3 "b:B"--differenceWith :: Ord k => (a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWith f m1 m2- = differenceWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWith #-}-#endif---- | /O(n+m)/. Difference with a combining function. When two equal keys are--- encountered, the combining function is applied to the key and both values.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--- > differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])--- > == singleton 3 "3:b|B"--differenceWithKey :: Ord k => (k -> a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWithKey f t1 t2 = mergeWithKey f id (const Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWithKey #-}-#endif---{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}--- | /O(n+m)/. Intersection of two maps.--- Return data in the first map for the keys existing in both maps.--- (@'intersection' m1 m2 == 'intersectionWith' 'const' m1 m2@).------ > intersection (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "a"--intersection :: Ord k => Map k a -> Map k b -> Map k a-intersection Tip _ = Tip-intersection _ Tip = Tip-intersection t1 t2 = hedgeInt NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersection #-}-#endif--hedgeInt :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k b -> Map k a-hedgeInt _ _ _ Tip = Tip-hedgeInt _ _ Tip _ = Tip-hedgeInt blo bhi (Bin _ kx x l r) t2 = let l' = hedgeInt blo bmi l (trim blo bmi t2)- r' = hedgeInt bmi bhi r (trim bmi bhi t2)- in if kx `member` t2 then join kx x l' r' else merge l' r'- where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeInt #-}-#endif---- | /O(n+m)/. Intersection with a combining function.------ > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"--intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWith f m1 m2- = intersectionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWith #-}-#endif---- | /O(n+m)/. Intersection with a combining function.--- Intersection is more efficient on (bigset \``intersection`\` smallset).------ > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"---intersectionWithKey :: Ord k => (k -> a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) (const Tip) (const Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWithKey #-}-#endif---{--------------------------------------------------------------------- MergeWithKey---------------------------------------------------------------------}---- | /O(n+m)/. A high-performance universal combining function. This function--- is used to define 'unionWith', 'unionWithKey', 'differenceWith',--- 'differenceWithKey', 'intersectionWith', 'intersectionWithKey' and can be--- used to define other custom combine functions.------ Please make sure you know what is going on when using 'mergeWithKey',--- otherwise you can be surprised by unexpected code growth or even--- corruption of the data structure.------ When 'mergeWithKey' is given three arguments, it is inlined to the call--- site. You should therefore use 'mergeWithKey' only to define your custom--- combining functions. For example, you could define 'unionWithKey',--- 'differenceWithKey' and 'intersectionWithKey' as------ > myUnionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) id id m1 m2--- > myDifferenceWithKey f m1 m2 = mergeWithKey f id (const empty) m1 m2--- > myIntersectionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) (const empty) (const empty) m1 m2------ When calling @'mergeWithKey' combine only1 only2@, a function combining two--- 'IntMap's is created, such that------ * if a key is present in both maps, it is passed with both corresponding--- values to the @combine@ function. Depending on the result, the key is either--- present in the result with specified value, or is left out;------ * a nonempty subtree present only in the first map is passed to @only1@ and--- the output is added to the result;------ * a nonempty subtree present only in the second map is passed to @only2@ and--- the output is added to the result.------ The @only1@ and @only2@ methods /must return a map with a subset (possibly empty) of the keys of the given map/.--- The values can be modified arbitrarily. Most common variants of @only1@ and--- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@ or--- @'filterWithKey' f@ could be used for any @f@.--mergeWithKey :: Ord k => (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c)- -> Map k a -> Map k b -> Map k c-mergeWithKey f g1 g2 = go- where- go Tip t2 = g2 t2- go t1 Tip = g1 t1- go t1 t2 = hedgeMerge NothingS NothingS t1 t2-- hedgeMerge _ _ t1 Tip = g1 t1- hedgeMerge blo bhi Tip (Bin _ kx x l r) = g2 $ join kx x (filterGt blo l) (filterLt bhi r)- hedgeMerge blo bhi (Bin _ kx x l r) t2 = let l' = hedgeMerge blo bmi l (trim blo bmi t2)- (found, trim_t2) = trimLookupLo kx bhi t2- r' = hedgeMerge bmi bhi r trim_t2- in case found of- Nothing -> case g1 (singleton kx x) of- Tip -> merge l' r'- (Bin _ _ x' Tip Tip) -> join kx x' l' r'- _ -> error "mergeWithKey: Given function only1 does not fulfil required conditions (see documentation)"- Just x2 -> case f kx x x2 of- Nothing -> merge l' r'- Just x' -> join kx x' l' r'- where bmi = JustS kx-{-# INLINE mergeWithKey #-}--{--------------------------------------------------------------------- Submap---------------------------------------------------------------------}--- | /O(n+m)/.--- This function is defined as (@'isSubmapOf' = 'isSubmapOfBy' (==)@).----isSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool-isSubmapOf m1 m2 = isSubmapOfBy (==) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubmapOf #-}-#endif--{- | /O(n+m)/.- The expression (@'isSubmapOfBy' f t1 t2@) returns 'True' if- all keys in @t1@ are in tree @t2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isSubmapOfBy (==) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (<=) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1),('b',2)])-- But the following are all 'False':-- > isSubmapOfBy (==) (fromList [('a',2)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (<) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1)])----}-isSubmapOfBy :: Ord k => (a->b->Bool) -> Map k a -> Map k b -> Bool-isSubmapOfBy f t1 t2- = (size t1 <= size t2) && (submap' f t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubmapOfBy #-}-#endif--submap' :: Ord a => (b -> c -> Bool) -> Map a b -> Map a c -> Bool-submap' _ Tip _ = True-submap' _ _ Tip = False-submap' f (Bin _ kx x l r) t- = case found of- Nothing -> False- Just y -> f x y && submap' f l lt && submap' f r gt- where- (lt,found,gt) = splitLookup kx t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE submap' #-}-#endif---- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).--- Defined as (@'isProperSubmapOf' = 'isProperSubmapOfBy' (==)@).-isProperSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool-isProperSubmapOf m1 m2- = isProperSubmapOfBy (==) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubmapOf #-}-#endif--{- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).- The expression (@'isProperSubmapOfBy' f m1 m2@) returns 'True' when- @m1@ and @m2@ are not equal,- all keys in @m1@ are in @m2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isProperSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)])-- But the following are all 'False':-- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)])- > isProperSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)])----}-isProperSubmapOfBy :: Ord k => (a -> b -> Bool) -> Map k a -> Map k b -> Bool-isProperSubmapOfBy f t1 t2- = (size t1 < size t2) && (submap' f t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubmapOfBy #-}-#endif--{--------------------------------------------------------------------- Filter and partition---------------------------------------------------------------------}--- | /O(n)/. Filter all values that satisfy the predicate.------ > filter (> "a") (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > filter (> "x") (fromList [(5,"a"), (3,"b")]) == empty--- > filter (< "a") (fromList [(5,"a"), (3,"b")]) == empty--filter :: (a -> Bool) -> Map k a -> Map k a-filter p m- = filterWithKey (\_ x -> p x) m---- | /O(n)/. Filter all keys\/values that satisfy the predicate.------ > filterWithKey (\k _ -> k > 4) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--filterWithKey :: (k -> a -> Bool) -> Map k a -> Map k a-filterWithKey _ Tip = Tip-filterWithKey p (Bin _ kx x l r)- | p kx x = join kx x (filterWithKey p l) (filterWithKey p r)- | otherwise = merge (filterWithKey p l) (filterWithKey p r)---- | /O(n)/. Partition the map according to a predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partition (> "a") (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > partition (< "x") (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partition (> "x") (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--partition :: (a -> Bool) -> Map k a -> (Map k a,Map k a)-partition p m- = partitionWithKey (\_ x -> p x) m---- | /O(n)/. Partition the map according to a predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partitionWithKey (\ k _ -> k > 3) (fromList [(5,"a"), (3,"b")]) == (singleton 5 "a", singleton 3 "b")--- > partitionWithKey (\ k _ -> k < 7) (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partitionWithKey (\ k _ -> k > 7) (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--partitionWithKey :: (k -> a -> Bool) -> Map k a -> (Map k a,Map k a)-partitionWithKey _ Tip = (Tip,Tip)-partitionWithKey p (Bin _ kx x l r)- | p kx x = (join kx x l1 r1,merge l2 r2)- | otherwise = (merge l1 r1,join kx x l2 r2)- where- (l1,l2) = partitionWithKey p l- (r1,r2) = partitionWithKey p r---- | /O(n)/. Map values and collect the 'Just' results.------ > let f x = if x == "a" then Just "new a" else Nothing--- > mapMaybe f (fromList [(5,"a"), (3,"b")]) == singleton 5 "new a"--mapMaybe :: (a -> Maybe b) -> Map k a -> Map k b-mapMaybe f = mapMaybeWithKey (\_ x -> f x)---- | /O(n)/. Map keys\/values and collect the 'Just' results.------ > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"--mapMaybeWithKey :: (k -> a -> Maybe b) -> Map k a -> Map k b-mapMaybeWithKey _ Tip = Tip-mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of- Just y -> join kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)- Nothing -> merge (mapMaybeWithKey f l) (mapMaybeWithKey f r)---- | /O(n)/. Map values and separate the 'Left' and 'Right' results.------ > let f a = if a < "c" then Left a else Right a--- > mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])--- >--- > mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--mapEither :: (a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEither f m- = mapEitherWithKey (\_ x -> f x) m---- | /O(n)/. Map keys\/values and separate the 'Left' and 'Right' results.------ > let f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--- > mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])--- >--- > mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])--mapEitherWithKey :: (k -> a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEitherWithKey _ Tip = (Tip, Tip)-mapEitherWithKey f (Bin _ kx x l r) = case f kx x of- Left y -> (join kx y l1 r1, merge l2 r2)- Right z -> (merge l1 r1, join kx z l2 r2)- where- (l1,l2) = mapEitherWithKey f l- (r1,r2) = mapEitherWithKey f r--{--------------------------------------------------------------------- Mapping---------------------------------------------------------------------}--- | /O(n)/. Map a function over all values in the map.------ > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]--map :: (a -> b) -> Map k a -> Map k b-map _ Tip = Tip-map f (Bin sx kx x l r) = Bin sx kx (f x) (map f l) (map f r)---- | /O(n)/. Map a function over all values in the map.------ > let f key x = (show key) ++ ":" ++ x--- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]--mapWithKey :: (k -> a -> b) -> Map k a -> Map k b-mapWithKey _ Tip = Tip-mapWithKey f (Bin sx kx x l r) = Bin sx kx (f kx x) (mapWithKey f l) (mapWithKey f r)---- | /O(n)/.--- @'traverseWithKey' f s == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@--- That is, behaves exactly like a regular 'traverse' except that the traversing--- function also has access to the key associated with a value.------ > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(1, 'a'), (5, 'e')]) == Just (fromList [(1, 'b'), (5, 'f')])--- > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(2, 'c')]) == Nothing-{-# INLINE traverseWithKey #-}-traverseWithKey :: Applicative t => (k -> a -> t b) -> Map k a -> t (Map k b)-traverseWithKey f = go- where- go Tip = pure Tip- go (Bin s k v l r)- = flip (Bin s k) <$> go l <*> f k v <*> go r---- | /O(n)/. The function 'mapAccum' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a b = (a ++ b, b ++ "X")--- > mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) == ("Everything: ba", fromList [(3, "bX"), (5, "aX")])--mapAccum :: (a -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccum f a m- = mapAccumWithKey (\a' _ x' -> f a' x') a m---- | /O(n)/. The function 'mapAccumWithKey' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--- > mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) == ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])--mapAccumWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumWithKey f a t- = mapAccumL f a t---- | /O(n)/. The function 'mapAccumL' threads an accumulating--- argument through the map in ascending order of keys.-mapAccumL :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumL _ a Tip = (a,Tip)-mapAccumL f a (Bin sx kx x l r) =- let (a1,l') = mapAccumL f a l- (a2,x') = f a1 kx x- (a3,r') = mapAccumL f a2 r- in (a3,Bin sx kx x' l' r')---- | /O(n)/. The function 'mapAccumR' threads an accumulating--- argument through the map in descending order of keys.-mapAccumRWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumRWithKey _ a Tip = (a,Tip)-mapAccumRWithKey f a (Bin sx kx x l r) =- let (a1,r') = mapAccumRWithKey f a r- (a2,x') = f a1 kx x- (a3,l') = mapAccumRWithKey f a2 l- in (a3,Bin sx kx x' l' r')---- | /O(n*log n)/.--- @'mapKeys' f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the value at the greatest of the--- original keys is retained.------ > mapKeys (+ 1) (fromList [(5,"a"), (3,"b")]) == fromList [(4, "b"), (6, "a")]--- > mapKeys (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "c"--- > mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "c"--mapKeys :: Ord k2 => (k1->k2) -> Map k1 a -> Map k2 a-mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeys #-}-#endif---- | /O(n*log n)/.--- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the associated values will be--- combined using @c@.------ > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"--- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"--mapKeysWith :: Ord k2 => (a -> a -> a) -> (k1->k2) -> Map k1 a -> Map k2 a-mapKeysWith c f = fromListWith c . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeysWith #-}-#endif----- | /O(n)/.--- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@--- is strictly monotonic.--- That is, for any values @x@ and @y@, if @x@ < @y@ then @f x@ < @f y@.--- /The precondition is not checked./--- Semi-formally, we have:------ > and [x < y ==> f x < f y | x <- ls, y <- ls]--- > ==> mapKeysMonotonic f s == mapKeys f s--- > where ls = keys s------ This means that @f@ maps distinct original keys to distinct resulting keys.--- This function has better performance than 'mapKeys'.------ > mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) == fromList [(6, "b"), (10, "a")]--- > valid (mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")])) == True--- > valid (mapKeysMonotonic (\ _ -> 1) (fromList [(5,"a"), (3,"b")])) == False--mapKeysMonotonic :: (k1->k2) -> Map k1 a -> Map k2 a-mapKeysMonotonic _ Tip = Tip-mapKeysMonotonic f (Bin sz k x l r) =- Bin sz (f k) x (mapKeysMonotonic f l) (mapKeysMonotonic f r)--{--------------------------------------------------------------------- Folds---------------------------------------------------------------------}---- | /O(n)/. Fold the values in the map using the given right-associative--- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'elems'@.------ For example,------ > elems map = foldr (:) [] map------ > let f a len = len + (length a)--- > foldr f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldr :: (a -> b -> b) -> b -> Map k a -> b-foldr f z = go z- where- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr #-}---- | /O(n)/. A strict version of 'foldr'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldr' :: (a -> b -> b) -> b -> Map k a -> b-foldr' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr' #-}---- | /O(n)/. Fold the values in the map using the given left-associative--- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.------ For example,------ > elems = reverse . foldl (flip (:)) []------ > let f len a = len + (length a)--- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldl :: (a -> b -> a) -> a -> Map k b -> a-foldl f z = go z- where- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl #-}---- | /O(n)/. A strict version of 'foldl'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldl' :: (a -> b -> a) -> a -> Map k b -> a-foldl' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl' #-}---- | /O(n)/. Fold the keys and values in the map using the given right-associative--- binary operator, such that--- @'foldrWithKey' f z == 'Prelude.foldr' ('uncurry' f) z . 'toAscList'@.------ For example,------ > keys map = foldrWithKey (\k x ks -> k:ks) [] map------ > let f k a result = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldrWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (5:a)(3:b)"-foldrWithKey :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l-{-# INLINE foldrWithKey #-}---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldrWithKey' :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrWithKey' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l-{-# INLINE foldrWithKey' #-}---- | /O(n)/. Fold the keys and values in the map using the given left-associative--- binary operator, such that--- @'foldlWithKey' f z == 'Prelude.foldl' (\\z' (kx, x) -> f z' kx x) z . 'toAscList'@.------ For example,------ > keys = reverse . foldlWithKey (\ks k x -> k:ks) []------ > let f result k a = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldlWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (3:b)(5:a)"-foldlWithKey :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r-{-# INLINE foldlWithKey #-}---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldlWithKey' :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlWithKey' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r-{-# INLINE foldlWithKey' #-}--{--------------------------------------------------------------------- List variations---------------------------------------------------------------------}--- | /O(n)/.--- Return all elements of the map in the ascending order of their keys.--- Subject to list fusion.------ > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]--- > elems empty == []--elems :: Map k a -> [a]-elems = foldr (:) []---- | /O(n)/. Return all keys of the map in ascending order. Subject to list--- fusion.------ > keys (fromList [(5,"a"), (3,"b")]) == [3,5]--- > keys empty == []--keys :: Map k a -> [k]-keys = foldrWithKey (\k _ ks -> k : ks) []---- | /O(n)/. An alias for 'toAscList'. Return all key\/value pairs in the map--- in ascending key order. Subject to list fusion.------ > assocs (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > assocs empty == []--assocs :: Map k a -> [(k,a)]-assocs m- = toAscList m---- | /O(n)/. The set of all keys of the map.------ > keysSet (fromList [(5,"a"), (3,"b")]) == Data.Set.fromList [3,5]--- > keysSet empty == Data.Set.empty-keysSet :: Map k a -> Set.Set k-keysSet Tip = Set.Tip-keysSet (Bin sz kx _ l r) = Set.Bin sz kx (keysSet l) (keysSet r)---- | /O(n)/. Build a map from a set of keys and a function which for each key--- computes its value.------ > fromSet (\k -> replicate k 'a') (Data.Set.fromList [3, 5]) == fromList [(5,"aaaaa"), (3,"aaa")]--- > fromSet undefined Data.Set.empty == empty-fromSet :: (k -> a) -> Set.Set k -> Map k a-fromSet _ Set.Tip = Tip-fromSet f (Set.Bin sz x l r) = Bin sz x (f x) (fromSet f l) (fromSet f r)--{--------------------------------------------------------------------- Lists- use [foldlStrict] to reduce demand on the control-stack---------------------------------------------------------------------}--- | /O(n*log n)/. Build a map from a list of key\/value pairs. See also 'fromAscList'.--- If the list contains more than one value for the same key, the last value--- for the key is retained.------ > fromList [] == empty--- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]--- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]--fromList :: Ord k => [(k,a)] -> Map k a-fromList xs- = foldlStrict ins empty xs- where- ins t (k,x) = insert k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromList #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "ab"), (5, "aba")]--- > fromListWith (++) [] == empty--fromListWith :: Ord k => (a -> a -> a) -> [(k,a)] -> Map k a-fromListWith f xs- = fromListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWith #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.------ > let f k a1 a2 = (show k) ++ a1 ++ a2--- > fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "3ab"), (5, "5a5ba")]--- > fromListWithKey f [] == empty--fromListWithKey :: Ord k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromListWithKey f xs- = foldlStrict ins empty xs- where- ins t (k,x) = insertWithKey f k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWithKey #-}-#endif---- | /O(n)/. Convert the map to a list of key\/value pairs. Subject to list fusion.------ > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > toList empty == []--toList :: Map k a -> [(k,a)]-toList = toAscList---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys are--- in ascending order. Subject to list fusion.------ > toAscList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--toAscList :: Map k a -> [(k,a)]-toAscList = foldrWithKey (\k x xs -> (k,x):xs) []---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys--- are in descending order. Subject to list fusion.------ > toDescList (fromList [(5,"a"), (3,"b")]) == [(5,"a"), (3,"b")]--toDescList :: Map k a -> [(k,a)]-toDescList = foldlWithKey (\xs k x -> (k,x):xs) []---- List fusion for the list generating functions.-#if __GLASGOW_HASKELL__--- The foldrFB and foldlFB are fold{r,l}WithKey equivalents, used for list fusion.--- They are important to convert unfused methods back, see mapFB in prelude.-foldrFB :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrFB = foldrWithKey-{-# INLINE[0] foldrFB #-}-foldlFB :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlFB = foldlWithKey-{-# INLINE[0] foldlFB #-}---- Inline assocs and toList, so that we need to fuse only toAscList.-{-# INLINE assocs #-}-{-# INLINE toList #-}---- The fusion is enabled up to phase 2 included. If it does not succeed,--- convert in phase 1 the expanded elems,keys,to{Asc,Desc}List calls back to--- elems,keys,to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were--- used in a list fusion, otherwise it would go away in phase 1), and let compiler--- do whatever it wants with elems,keys,to{Asc,Desc}List -- it was forbidden to--- inline it before phase 0, otherwise the fusion rules would not fire at all.-{-# NOINLINE[0] elems #-}-{-# NOINLINE[0] keys #-}-{-# NOINLINE[0] toAscList #-}-{-# NOINLINE[0] toDescList #-}-{-# RULES "Map.elems" [~1] forall m . elems m = build (\c n -> foldrFB (\_ x xs -> c x xs) n m) #-}-{-# RULES "Map.elemsBack" [1] foldrFB (\_ x xs -> x : xs) [] = elems #-}-{-# RULES "Map.keys" [~1] forall m . keys m = build (\c n -> foldrFB (\k _ xs -> c k xs) n m) #-}-{-# RULES "Map.keysBack" [1] foldrFB (\k _ xs -> k : xs) [] = keys #-}-{-# RULES "Map.toAscList" [~1] forall m . toAscList m = build (\c n -> foldrFB (\k x xs -> c (k,x) xs) n m) #-}-{-# RULES "Map.toAscListBack" [1] foldrFB (\k x xs -> (k, x) : xs) [] = toAscList #-}-{-# RULES "Map.toDescList" [~1] forall m . toDescList m = build (\c n -> foldlFB (\xs k x -> c (k,x) xs) n m) #-}-{-# RULES "Map.toDescListBack" [1] foldlFB (\xs k x -> (k, x) : xs) [] = toDescList #-}-#endif--{--------------------------------------------------------------------- Building trees from ascending/descending lists can be done in linear time.-- Note that if [xs] is ascending that:- fromAscList xs == fromList xs- fromAscListWith f xs == fromListWith f xs---------------------------------------------------------------------}--- | /O(n)/. Build a map from an ascending list in linear time.--- /The precondition (input list is ascending) is not checked./------ > fromAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]--- > valid (fromAscList [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscList [(5,"a"), (3,"b"), (5,"b")]) == False--fromAscList :: Eq k => [(k,a)] -> Map k a-fromAscList xs- = fromAscListWithKey (\_ x _ -> x) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscList #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--- > valid (fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscListWith (++) [(5,"a"), (3,"b"), (5,"b")]) == False--fromAscListWith :: Eq k => (a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWith f xs- = fromAscListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWith #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a--- combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > let f k a1 a2 = (show k) ++ ":" ++ a1 ++ a2--- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")] == fromList [(3, "b"), (5, "5:b5:ba")]--- > valid (fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")]) == True--- > valid (fromAscListWithKey f [(5,"a"), (3,"b"), (5,"b"), (5,"b")]) == False--fromAscListWithKey :: Eq k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWithKey f xs- = fromDistinctAscList (combineEq f xs)- where- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]- combineEq _ xs'- = case xs' of- [] -> []- [x] -> [x]- (x:xx) -> combineEq' x xx-- combineEq' z [] = [z]- combineEq' z@(kz,zz) (x@(kx,xx):xs')- | kx==kz = let yy = f kx xx zz in combineEq' (kx,yy) xs'- | otherwise = z:combineEq' x xs'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWithKey #-}-#endif----- | /O(n)/. Build a map from an ascending list of distinct elements in linear time.--- /The precondition is not checked./------ > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > valid (fromDistinctAscList [(3,"b"), (5,"a")]) == True--- > valid (fromDistinctAscList [(3,"b"), (5,"a"), (5,"b")]) == False--fromDistinctAscList :: [(k,a)] -> Map k a-fromDistinctAscList xs- = create const (length xs) xs- where- -- 1) use continuations so that we use heap space instead of stack space.- -- 2) special case for n==5 to create bushier trees.- create c 0 xs' = c Tip xs'- create c 5 xs' = case xs' of- ((k1,x1):(k2,x2):(k3,x3):(k4,x4):(k5,x5):xx)- -> c (bin k4 x4 (bin k2 x2 (singleton k1 x1) (singleton k3 x3)) (singleton k5 x5)) xx- _ -> error "fromDistinctAscList create"- create c n xs' = seq nr $ create (createR nr c) nl xs'- where nl = n `div` 2- nr = n - nl - 1-- createR n c l ((k,x):ys) = create (createB l k x c) n ys- createR _ _ _ [] = error "fromDistinctAscList createR []"- createB l k x c r zs = c (bin k x l r) zs---{--------------------------------------------------------------------- Utility functions that return sub-ranges of the original- tree. Some functions take a `Maybe value` as an argument to- allow comparisons against infinite values. These are called `blow`- (Nothing is -\infty) and `bhigh` (here Nothing is +\infty).- We use MaybeS value, which is a Maybe strict in the Just case.-- [trim blow bhigh t] A tree that is either empty or where [x > blow]- and [x < bhigh] for the value [x] of the root.- [filterGt blow t] A tree where for all values [k]. [k > blow]- [filterLt bhigh t] A tree where for all values [k]. [k < bhigh]-- [split k t] Returns two trees [l] and [r] where all keys- in [l] are <[k] and all keys in [r] are >[k].- [splitLookup k t] Just like [split] but also returns whether [k]- was found in the tree.---------------------------------------------------------------------}--data MaybeS a = NothingS | JustS !a--{--------------------------------------------------------------------- [trim blo bhi t] trims away all subtrees that surely contain no- values between the range [blo] to [bhi]. The returned tree is either- empty or the key of the root is between @blo@ and @bhi@.---------------------------------------------------------------------}-trim :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k a-trim NothingS NothingS t = t-trim (JustS lk) NothingS t = greater lk t where greater lo (Bin _ k _ _ r) | k <= lo = greater lo r- greater _ t' = t'-trim NothingS (JustS hk) t = lesser hk t where lesser hi (Bin _ k _ l _) | k >= hi = lesser hi l- lesser _ t' = t'-trim (JustS lk) (JustS hk) t = middle lk hk t where middle lo hi (Bin _ k _ _ r) | k <= lo = middle lo hi r- middle lo hi (Bin _ k _ l _) | k >= hi = middle lo hi l- middle _ _ t' = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trim #-}-#endif---- Helper function for 'mergeWithKey'. The @'trimLookupLo' lk hk t@ performs both--- @'trim' (JustS lk) hk t@ and @'lookup' lk t@.---- See Note: Type of local 'go' function-trimLookupLo :: Ord k => k -> MaybeS k -> Map k a -> (Maybe a, Map k a)-trimLookupLo lk NothingS t = greater lk t- where greater :: Ord k => k -> Map k a -> (Maybe a, Map k a)- greater lo t'@(Bin _ kx x l r) = case compare lo kx of LT -> (lookup lo l, {-`strictPair`-} t')- EQ -> (Just x, r)- GT -> greater lo r- greater _ Tip = (Nothing, Tip)-trimLookupLo lk (JustS hk) t = middle lk hk t- where middle :: Ord k => k -> k -> Map k a -> (Maybe a, Map k a)- middle lo hi t'@(Bin _ kx x l r) = case compare lo kx of LT | kx < hi -> (lookup lo l, {- `strictPair` -} t')- | otherwise -> middle lo hi l- EQ -> (Just x, {-`strictPair`-} lesser hi r)- GT -> middle lo hi r- middle _ _ Tip = (Nothing, Tip)-- lesser :: Ord k => k -> Map k a -> Map k a- lesser hi (Bin _ k _ l _) | k >= hi = lesser hi l- lesser _ t' = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trimLookupLo #-}-#endif---{--------------------------------------------------------------------- [filterGt b t] filter all keys >[b] from tree [t]- [filterLt b t] filter all keys <[b] from tree [t]---------------------------------------------------------------------}-filterGt :: Ord k => MaybeS k -> Map k v -> Map k v-filterGt NothingS t = t-filterGt (JustS b) t = filter' b t- where filter' _ Tip = Tip- filter' b' (Bin _ kx x l r) =- case compare b' kx of LT -> join kx x (filter' b' l) r- EQ -> r- GT -> filter' b' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterGt #-}-#endif--filterLt :: Ord k => MaybeS k -> Map k v -> Map k v-filterLt NothingS t = t-filterLt (JustS b) t = filter' b t- where filter' _ Tip = Tip- filter' b' (Bin _ kx x l r) =- case compare kx b' of LT -> join kx x l (filter' b' r)- EQ -> l- GT -> filter' b' l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterLt #-}-#endif--{--------------------------------------------------------------------- Split---------------------------------------------------------------------}--- | /O(log n)/. The expression (@'split' k map@) is a pair @(map1,map2)@ where--- the keys in @map1@ are smaller than @k@ and the keys in @map2@ larger than @k@.--- Any key equal to @k@ is found in neither @map1@ nor @map2@.------ > split 2 (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3,"b"), (5,"a")])--- > split 3 (fromList [(5,"a"), (3,"b")]) == (empty, singleton 5 "a")--- > split 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > split 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", empty)--- > split 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], empty)--split :: Ord k => k -> Map k a -> (Map k a,Map k a)-split k t = k `seq`- case t of- Tip -> (Tip, Tip)- Bin _ kx x l r -> case compare k kx of- LT -> let (lt,gt) = split k l in (lt,join kx x gt r)- GT -> let (lt,gt) = split k r in (join kx x l lt,gt)- EQ -> (l,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE split #-}-#endif---- | /O(log n)/. The expression (@'splitLookup' k map@) splits a map just--- like 'split' but also returns @'lookup' k map@.------ > splitLookup 2 (fromList [(5,"a"), (3,"b")]) == (empty, Nothing, fromList [(3,"b"), (5,"a")])--- > splitLookup 3 (fromList [(5,"a"), (3,"b")]) == (empty, Just "b", singleton 5 "a")--- > splitLookup 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Nothing, singleton 5 "a")--- > splitLookup 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Just "a", empty)--- > splitLookup 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], Nothing, empty)--splitLookup :: Ord k => k -> Map k a -> (Map k a,Maybe a,Map k a)-splitLookup k t = k `seq`- case t of- Tip -> (Tip,Nothing,Tip)- Bin _ kx x l r -> case compare k kx of- LT -> let (lt,z,gt) = splitLookup k l in (lt,z,join kx x gt r)- GT -> let (lt,z,gt) = splitLookup k r in (join kx x l lt,z,gt)- EQ -> (l,Just x,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE splitLookup #-}-#endif--{--------------------------------------------------------------------- Utility functions that maintain the balance properties of the tree.- All constructors assume that all values in [l] < [k] and all values- in [r] > [k], and that [l] and [r] are valid trees.-- In order of sophistication:- [Bin sz k x l r] The type constructor.- [bin k x l r] Maintains the correct size, assumes that both [l]- and [r] are balanced with respect to each other.- [balance k x l r] Restores the balance and size.- Assumes that the original tree was balanced and- that [l] or [r] has changed by at most one element.- [join k x l r] Restores balance and size.-- Furthermore, we can construct a new tree from two trees. Both operations- assume that all values in [l] < all values in [r] and that [l] and [r]- are valid:- [glue l r] Glues [l] and [r] together. Assumes that [l] and- [r] are already balanced with respect to each other.- [merge l r] Merges two trees and restores balance.-- Note: in contrast to Adam's paper, we use (<=) comparisons instead- of (<) comparisons in [join], [merge] and [balance].- Quickcheck (on [difference]) showed that this was necessary in order- to maintain the invariants. It is quite unsatisfactory that I haven't- been able to find out why this is actually the case! Fortunately, it- doesn't hurt to be a bit more conservative.---------------------------------------------------------------------}--{--------------------------------------------------------------------- Join---------------------------------------------------------------------}-join :: k -> a -> Map k a -> Map k a -> Map k a-join kx x Tip r = insertMin kx x r-join kx x l Tip = insertMax kx x l-join kx x l@(Bin sizeL ky y ly ry) r@(Bin sizeR kz z lz rz)- | delta*sizeL < sizeR = balanceL kz z (join kx x l lz) rz- | delta*sizeR < sizeL = balanceR ky y ly (join kx x ry r)- | otherwise = bin kx x l r----- insertMin and insertMax don't perform potentially expensive comparisons.-insertMax,insertMin :: k -> a -> Map k a -> Map k a-insertMax kx x t- = case t of- Tip -> singleton kx x- Bin _ ky y l r- -> balanceR ky y l (insertMax kx x r)--insertMin kx x t- = case t of- Tip -> singleton kx x- Bin _ ky y l r- -> balanceL ky y (insertMin kx x l) r--{--------------------------------------------------------------------- [merge l r]: merges two trees.---------------------------------------------------------------------}-merge :: Map k a -> Map k a -> Map k a-merge Tip r = r-merge l Tip = l-merge l@(Bin sizeL kx x lx rx) r@(Bin sizeR ky y ly ry)- | delta*sizeL < sizeR = balanceL ky y (merge l ly) ry- | delta*sizeR < sizeL = balanceR kx x lx (merge rx r)- | otherwise = glue l r--{--------------------------------------------------------------------- [glue l r]: glues two trees together.- Assumes that [l] and [r] are already balanced with respect to each other.---------------------------------------------------------------------}-glue :: Map k a -> Map k a -> Map k a-glue Tip r = r-glue l Tip = l-glue l r- | size l > size r = let ((km,m),l') = deleteFindMax l in balanceR km m l' r- | otherwise = let ((km,m),r') = deleteFindMin r in balanceL km m l r'----- | /O(log n)/. Delete and find the minimal element.------ > deleteFindMin (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((3,"b"), fromList[(5,"a"), (10,"c")])--- > deleteFindMin Error: can not return the minimal element of an empty map--deleteFindMin :: Map k a -> ((k,a),Map k a)-deleteFindMin t- = case t of- Bin _ k x Tip r -> ((k,x),r)- Bin _ k x l r -> let (km,l') = deleteFindMin l in (km,balanceR k x l' r)- Tip -> (error "Map.deleteFindMin: can not return the minimal element of an empty map", Tip)---- | /O(log n)/. Delete and find the maximal element.------ > deleteFindMax (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((10,"c"), fromList [(3,"b"), (5,"a")])--- > deleteFindMax empty Error: can not return the maximal element of an empty map--deleteFindMax :: Map k a -> ((k,a),Map k a)-deleteFindMax t- = case t of- Bin _ k x l Tip -> ((k,x),l)- Bin _ k x l r -> let (km,r') = deleteFindMax r in (km,balanceL k x l r')- Tip -> (error "Map.deleteFindMax: can not return the maximal element of an empty map", Tip)---{--------------------------------------------------------------------- [balance l x r] balances two trees with value x.- The sizes of the trees should balance after decreasing the- size of one of them. (a rotation).-- [delta] is the maximal relative difference between the sizes of- two trees, it corresponds with the [w] in Adams' paper.- [ratio] is the ratio between an outer and inner sibling of the- heavier subtree in an unbalanced setting. It determines- whether a double or single rotation should be performed- to restore balance. It is corresponds with the inverse- of $\alpha$ in Adam's article.-- Note that according to the Adam's paper:- - [delta] should be larger than 4.646 with a [ratio] of 2.- - [delta] should be larger than 3.745 with a [ratio] of 1.534.-- But the Adam's paper is erroneous:- - It can be proved that for delta=2 and delta>=5 there does- not exist any ratio that would work.- - Delta=4.5 and ratio=2 does not work.-- That leaves two reasonable variants, delta=3 and delta=4,- both with ratio=2.-- - A lower [delta] leads to a more 'perfectly' balanced tree.- - A higher [delta] performs less rebalancing.-- In the benchmarks, delta=3 is faster on insert operations,- and delta=4 has slightly better deletes. As the insert speedup- is larger, we currently use delta=3.----------------------------------------------------------------------}-delta,ratio :: Int-delta = 3-ratio = 2---- The balance function is equivalent to the following:------ balance :: k -> a -> Map k a -> Map k a -> Map k a--- balance k x l r--- | sizeL + sizeR <= 1 = Bin sizeX k x l r--- | sizeR > delta*sizeL = rotateL k x l r--- | sizeL > delta*sizeR = rotateR k x l r--- | otherwise = Bin sizeX k x l r--- where--- sizeL = size l--- sizeR = size r--- sizeX = sizeL + sizeR + 1------ rotateL :: a -> b -> Map a b -> Map a b -> Map a b--- rotateL k x l r@(Bin _ _ _ ly ry) | size ly < ratio*size ry = singleL k x l r--- | otherwise = doubleL k x l r------ rotateR :: a -> b -> Map a b -> Map a b -> Map a b--- rotateR k x l@(Bin _ _ _ ly ry) r | size ry < ratio*size ly = singleR k x l r--- | otherwise = doubleR k x l r------ singleL, singleR :: a -> b -> Map a b -> Map a b -> Map a b--- singleL k1 x1 t1 (Bin _ k2 x2 t2 t3) = bin k2 x2 (bin k1 x1 t1 t2) t3--- singleR k1 x1 (Bin _ k2 x2 t1 t2) t3 = bin k2 x2 t1 (bin k1 x1 t2 t3)------ doubleL, doubleR :: a -> b -> Map a b -> Map a b -> Map a b--- doubleL k1 x1 t1 (Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4) = bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)--- doubleR k1 x1 (Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3)) t4 = bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)------ It is only written in such a way that every node is pattern-matched only once.--balance :: k -> a -> Map k a -> Map k a -> Map k a-balance k x l r = case l of- Tip -> case r of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r- (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr- (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)- (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr- | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)-- (Bin ls lk lx ll lr) -> case r of- Tip -> case (ll, lr) of- (Tip, Tip) -> Bin 2 k x l Tip- (Tip, (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)- ((Bin _ _ _ _ _), Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)- ((Bin lls _ _ _ _), (Bin lrs lrk lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)- | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)- (Bin rs rk rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr- | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)- (_, _) -> error "Failure in Data.Map.balance"- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)- | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)- (_, _) -> error "Failure in Data.Map.balance"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balance #-}---- Functions balanceL and balanceR are specialised versions of balance.--- balanceL only checks whether the left subtree is too big,--- balanceR only checks whether the right subtree is too big.---- balanceL is called when left subtree might have been inserted to or when--- right subtree might have been deleted from.-balanceL :: k -> a -> Map k a -> Map k a -> Map k a-balanceL k x l r = case r of- Tip -> case l of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x l Tip- (Bin _ lk lx Tip (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)- (Bin _ lk lx ll@(Bin _ _ _ _ _) Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)- (Bin ls lk lx ll@(Bin lls _ _ _ _) lr@(Bin lrs lrk lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)- | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)-- (Bin rs _ _ _ _) -> case l of- Tip -> Bin (1+rs) k x Tip r-- (Bin ls lk lx ll lr)- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)- | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)- (_, _) -> error "Failure in Data.Map.balanceL"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balanceL #-}---- balanceR is called when right subtree might have been inserted to or when--- left subtree might have been deleted from.-balanceR :: k -> a -> Map k a -> Map k a -> Map k a-balanceR k x l r = case l of- Tip -> case r of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r- (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr- (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)- (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr- | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)-- (Bin ls _ _ _ _) -> case r of- Tip -> Bin (1+ls) k x l Tip-- (Bin rs rk rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr- | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)- (_, _) -> error "Failure in Data.Map.balanceR"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balanceR #-}---{--------------------------------------------------------------------- The bin constructor maintains the size of the tree---------------------------------------------------------------------}-bin :: k -> a -> Map k a -> Map k a -> Map k a-bin k x l r- = Bin (size l + size r + 1) k x l r-{-# INLINE bin #-}---{--------------------------------------------------------------------- Eq converts the tree to a list. In a lazy setting, this- actually seems one of the faster methods to compare two trees- and it is certainly the simplest :-)---------------------------------------------------------------------}-instance (Eq k,Eq a) => Eq (Map k a) where- t1 == t2 = (size t1 == size t2) && (toAscList t1 == toAscList t2)--{--------------------------------------------------------------------- Ord---------------------------------------------------------------------}--instance (Ord k, Ord v) => Ord (Map k v) where- compare m1 m2 = compare (toAscList m1) (toAscList m2)--{--------------------------------------------------------------------- Functor---------------------------------------------------------------------}-instance Functor (Map k) where- fmap f m = map f m--instance Traversable (Map k) where- traverse f = traverseWithKey (\_ -> f)--instance Foldable.Foldable (Map k) where- fold Tip = mempty- fold (Bin _ _ v l r) = Foldable.fold l `mappend` v `mappend` Foldable.fold r- foldr = foldr- foldl = foldl- foldMap _ Tip = mempty- foldMap f (Bin _ _ v l r) = Foldable.foldMap f l `mappend` f v `mappend` Foldable.foldMap f r--instance (NFData k, NFData a) => NFData (Map k a) where- rnf Tip = ()- rnf (Bin _ kx x l r) = rnf kx `seq` rnf x `seq` rnf l `seq` rnf r--{--------------------------------------------------------------------- Read---------------------------------------------------------------------}-instance (Ord k, Read k, Read e) => Read (Map k e) where-#ifdef __GLASGOW_HASKELL__- readPrec = parens $ prec 10 $ do- Ident "fromList" <- lexP- xs <- readPrec- return (fromList xs)-- readListPrec = readListPrecDefault-#else- readsPrec p = readParen (p > 10) $ \ r -> do- ("fromList",s) <- lex r- (xs,t) <- reads s- return (fromList xs,t)-#endif--{--------------------------------------------------------------------- Show---------------------------------------------------------------------}-instance (Show k, Show a) => Show (Map k a) where- showsPrec d m = showParen (d > 10) $- showString "fromList " . shows (toList m)---- | /O(n)/. Show the tree that implements the map. The tree is shown--- in a compressed, hanging format. See 'showTreeWith'.-showTree :: (Show k,Show a) => Map k a -> String-showTree m- = showTreeWith showElem True False m- where- showElem k x = show k ++ ":=" ++ show x---{- | /O(n)/. The expression (@'showTreeWith' showelem hang wide map@) shows- the tree that implements the map. Elements are shown using the @showElem@ function. If @hang@ is- 'True', a /hanging/ tree is shown otherwise a rotated tree is shown. If- @wide@ is 'True', an extra wide version is shown.--> Map> let t = fromDistinctAscList [(x,()) | x <- [1..5]]-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) True False t-> (4,())-> +--(2,())-> | +--(1,())-> | +--(3,())-> +--(5,())->-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) True True t-> (4,())-> |-> +--(2,())-> | |-> | +--(1,())-> | |-> | +--(3,())-> |-> +--(5,())->-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) False True t-> +--(5,())-> |-> (4,())-> |-> | +--(3,())-> | |-> +--(2,())-> |-> +--(1,())---}-showTreeWith :: (k -> a -> String) -> Bool -> Bool -> Map k a -> String-showTreeWith showelem hang wide t- | hang = (showsTreeHang showelem wide [] t) ""- | otherwise = (showsTree showelem wide [] [] t) ""--showsTree :: (k -> a -> String) -> Bool -> [String] -> [String] -> Map k a -> ShowS-showsTree showelem wide lbars rbars t- = case t of- Tip -> showsBars lbars . showString "|\n"- Bin _ kx x Tip Tip- -> showsBars lbars . showString (showelem kx x) . showString "\n"- Bin _ kx x l r- -> showsTree showelem wide (withBar rbars) (withEmpty rbars) r .- showWide wide rbars .- showsBars lbars . showString (showelem kx x) . showString "\n" .- showWide wide lbars .- showsTree showelem wide (withEmpty lbars) (withBar lbars) l--showsTreeHang :: (k -> a -> String) -> Bool -> [String] -> Map k a -> ShowS-showsTreeHang showelem wide bars t- = case t of- Tip -> showsBars bars . showString "|\n"- Bin _ kx x Tip Tip- -> showsBars bars . showString (showelem kx x) . showString "\n"- Bin _ kx x l r- -> showsBars bars . showString (showelem kx x) . showString "\n" .- showWide wide bars .- showsTreeHang showelem wide (withBar bars) l .- showWide wide bars .- showsTreeHang showelem wide (withEmpty bars) r--showWide :: Bool -> [String] -> String -> String-showWide wide bars- | wide = showString (concat (reverse bars)) . showString "|\n"- | otherwise = id--showsBars :: [String] -> ShowS-showsBars bars- = case bars of- [] -> id- _ -> showString (concat (reverse (tail bars))) . showString node--node :: String-node = "+--"--withBar, withEmpty :: [String] -> [String]-withBar bars = "| ":bars-withEmpty bars = " ":bars--{--------------------------------------------------------------------- Typeable---------------------------------------------------------------------}--#include "Typeable.h"-INSTANCE_TYPEABLE2(Map,mapTc,"Map")--{--------------------------------------------------------------------- Assertions---------------------------------------------------------------------}--- | /O(n)/. Test if the internal map structure is valid.------ > valid (fromAscList [(3,"b"), (5,"a")]) == True--- > valid (fromAscList [(5,"a"), (3,"b")]) == False--valid :: Ord k => Map k a -> Bool-valid t- = balanced t && ordered t && validsize t--ordered :: Ord a => Map a b -> Bool-ordered t- = bounded (const True) (const True) t- where- bounded lo hi t'- = case t' of- Tip -> True- Bin _ kx _ l r -> (lo kx) && (hi kx) && bounded lo (<kx) l && bounded (>kx) hi r---- | Exported only for "Debug.QuickCheck"-balanced :: Map k a -> Bool-balanced t- = case t of- Tip -> True- Bin _ _ _ l r -> (size l + size r <= 1 || (size l <= delta*size r && size r <= delta*size l)) &&- balanced l && balanced r--validsize :: Map a b -> Bool-validsize t- = (realsize t == Just (size t))- where- realsize t'- = case t' of- Tip -> Just 0- Bin sz _ _ l r -> case (realsize l,realsize r) of- (Just n,Just m) | n+m+1 == sz -> Just sz- _ -> Nothing--{--------------------------------------------------------------------- Utilities---------------------------------------------------------------------}-foldlStrict :: (a -> b -> a) -> a -> [b] -> a-foldlStrict f = go- where- go z [] = z- go z (x:xs) = let z' = f z x in z' `seq` go z' xs-{-# INLINE foldlStrict #-}
@@ -1,227 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Safe #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Map.Lazy--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of ordered maps from keys to values--- (dictionaries).------ API of this module is strict in the keys, but lazy in the values.--- If you need value-strict maps, use 'Data.Map.Strict' instead.--- The 'Map' type itself is shared between the lazy and strict modules,--- meaning that the same 'Map' value can be passed to functions in--- both modules (although that is rarely needed).------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import qualified Data.Map.Lazy as Map------ The implementation of 'Map' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'.------ Operation comments contain the operation time complexity in--- the Big-O notation (<http://en.wikipedia.org/wiki/Big_O_notation>).--------------------------------------------------------------------------------module Data.Map.Lazy (- -- * Strictness properties- -- $strictness-- -- * Map type-#if !defined(TESTING)- Map -- instance Eq,Show,Read-#else- Map(..) -- instance Eq,Show,Read-#endif-- -- * Operators- , (!), (\\)-- -- * Query- , M.null- , size- , member- , notMember- , M.lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , M.map- , mapWithKey- , traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , M.foldr- , M.foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- , keysSet- , fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , M.filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Indexed- , lookupIndex- , findIndex- , elemAt- , updateAt- , deleteAt-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- , valid--#if defined(TESTING)- -- * Internals- , bin- , balanced- , join- , merge-#endif-- ) where--import Data.Map.Base as M---- $strictness------ This module satisfies the following strictness property:------ * Key arguments are evaluated to WHNF------ Here are some examples that illustrate the property:------ > insertWith (\ new old -> old) undefined v m == undefined--- > insertWith (\ new old -> old) k undefined m == OK--- > delete undefined m == undefined
@@ -1,1139 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Safe #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Map.Strict--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of ordered maps from keys to values--- (dictionaries).------ API of this module is strict in both the keys and the values.--- If you need value-lazy maps, use 'Data.Map.Lazy' instead.--- The 'Map' type is shared between the lazy and strict modules,--- meaning that the same 'Map' value can be passed to functions in--- both modules (although that is rarely needed).------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import qualified Data.Map.Strict as Map------ The implementation of 'Map' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'.------ Operation comments contain the operation time complexity in--- the Big-O notation (<http://en.wikipedia.org/wiki/Big_O_notation>).------ Be aware that the 'Functor', 'Traversable' and 'Data' instances--- are the same as for the 'Data.Map.Lazy' module, so if they are used--- on strict maps, the resulting maps will be lazy.---------------------------------------------------------------------------------- See the notes at the beginning of Data.Map.Base.--module Data.Map.Strict- (- -- * Strictness properties- -- $strictness-- -- * Map type-#if !defined(TESTING)- Map -- instance Eq,Show,Read-#else- Map(..) -- instance Eq,Show,Read-#endif-- -- * Operators- , (!), (\\)-- -- * Query- , null- , size- , member- , notMember- , lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , map- , mapWithKey- , traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , foldr- , foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- , keysSet- , fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Indexed- , lookupIndex- , findIndex- , elemAt- , updateAt- , deleteAt-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- , valid--#if defined(TESTING)- -- * Internals- , bin- , balanced- , join- , merge-#endif- ) where--import Prelude hiding (lookup,map,filter,foldr,foldl,null)--import Data.Map.Base hiding- ( findWithDefault- , singleton- , insert- , insertWith- , insertWithKey- , insertLookupWithKey- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter- , unionWith- , unionWithKey- , unionsWith- , differenceWith- , differenceWithKey- , intersectionWith- , intersectionWithKey- , mergeWithKey- , map- , mapWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeysWith- , fromSet- , fromList- , fromListWith- , fromListWithKey- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey- , updateAt- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- )-import qualified Data.Set.Base as Set-import Data.StrictPair---- Use macros to define strictness of functions. STRICT_x_OF_y--- denotes an y-ary function strict in the x-th parameter. Similarly--- STRICT_x_y_OF_z denotes an z-ary function strict in the x-th and--- y-th parameter. We do not use BangPatterns, because they are not--- in any standard and we want the compilers to be compiled by as many--- compilers as possible.-#define STRICT_2_OF_3(fn) fn _ arg _ | arg `seq` False = undefined-#define STRICT_1_2_OF_3(fn) fn arg1 arg2 _ | arg1 `seq` arg2 `seq` False = undefined-#define STRICT_2_3_OF_4(fn) fn _ arg1 arg2 _ | arg1 `seq` arg2 `seq` False = undefined---- $strictness------ This module satisfies the following strictness properties:------ 1. Key and value arguments are evaluated to WHNF;------ 2. Keys and values are evaluated to WHNF before they are stored in--- the map.------ Here are some examples that illustrate the first property:------ > insertWith (\ new old -> old) k undefined m == undefined--- > delete undefined m == undefined------ Here are some examples that illustrate the second property:------ > map (\ v -> undefined) m == undefined -- m is not empty--- > mapKeys (\ k -> undefined) m == undefined -- m is not empty--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}---- | /O(log n)/. The expression @('findWithDefault' def k map)@ returns--- the value at key @k@ or returns default value @def@--- when the key is not in the map.------ > findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) == 'x'--- > findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) == 'a'---- See Map.Base.Note: Local 'go' functions and capturing-findWithDefault :: Ord k => a -> k -> Map k a -> a-findWithDefault def k = def `seq` k `seq` go- where- go Tip = def- go (Bin _ kx x l r) = case compare k kx of- LT -> go l- GT -> go r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findWithDefault #-}-#else-{-# INLINE findWithDefault #-}-#endif--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}---- | /O(1)/. A map with a single element.------ > singleton 1 'a' == fromList [(1, 'a')]--- > size (singleton 1 'a') == 1--singleton :: k -> a -> Map k a-singleton k x = x `seq` Bin 1 k x Tip Tip-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insertion---------------------------------------------------------------------}--- | /O(log n)/. Insert a new key and value in the map.--- If the key is already present in the map, the associated value is--- replaced with the supplied value. 'insert' is equivalent to--- @'insertWith' 'const'@.------ > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]--- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]--- > insert 5 'x' empty == singleton 5 'x'---- See Map.Base.Note: Type of local 'go' function-insert :: Ord k => k -> a -> Map k a -> Map k a-insert = go- where- go :: Ord k => k -> a -> Map k a -> Map k a- STRICT_1_2_OF_3(go)- go kx x Tip = singleton kx x- go kx x (Bin sz ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go kx x l) r- GT -> balanceR ky y l (go kx x r)- EQ -> Bin sz kx x l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insert #-}-#else-{-# INLINE insert #-}-#endif---- | /O(log n)/. Insert with a function, combining new value and old value.--- @'insertWith' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key, f new_value old_value)@.------ > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]--- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"--insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWith f = insertWithKey (\_ x' y' -> f x' y')-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWith #-}-#else-{-# INLINE insertWith #-}-#endif---- | /O(log n)/. Insert with a function, combining key, new value and old value.--- @'insertWithKey' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key,f key new_value old_value)@.--- Note that the key passed to f is the same key passed to 'insertWithKey'.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]--- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"---- See Map.Base.Note: Type of local 'go' function-insertWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWithKey = go- where- go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a- STRICT_2_3_OF_4(go)- go _ kx x Tip = singleton kx x- go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> balanceL ky y (go f kx x l) r- GT -> balanceR ky y l (go f kx x r)- EQ -> let x' = f kx x y- in x' `seq` Bin sy kx x' l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWithKey #-}-#else-{-# INLINE insertWithKey #-}-#endif---- | /O(log n)/. Combines insert operation with old value retrieval.--- The expression (@'insertLookupWithKey' f k x map@)--- is a pair where the first element is equal to (@'lookup' k map@)--- and the second element equal to (@'insertWithKey' f k x map@).------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])--- > insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])--- > insertLookupWithKey f 5 "xxx" empty == (Nothing, singleton 5 "xxx")------ This is how to define @insertLookup@ using @insertLookupWithKey@:------ > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t--- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])--- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])---- See Map.Base.Note: Type of local 'go' function-insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a- -> (Maybe a, Map k a)-insertLookupWithKey = go- where- go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)- STRICT_2_3_OF_4(go)- go _ kx x Tip = Nothing `strictPair` singleton kx x- go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> let (found, l') = go f kx x l- in found `strictPair` balanceL ky y l' r- GT -> let (found, r') = go f kx x r- in found `strictPair` balanceR ky y l r'- EQ -> let x' = f kx x y- in x' `seq` (Just y `strictPair` Bin sy kx x' l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertLookupWithKey #-}-#else-{-# INLINE insertLookupWithKey #-}-#endif--{--------------------------------------------------------------------- Deletion---------------------------------------------------------------------}---- | /O(log n)/. Update a value at a specific key with the result of the provided function.--- When the key is not--- a member of the map, the original map is returned.------ > adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjust ("new " ++) 7 empty == empty--adjust :: Ord k => (a -> a) -> k -> Map k a -> Map k a-adjust f = adjustWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjust #-}-#else-{-# INLINE adjust #-}-#endif---- | /O(log n)/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > let f key x = (show key) ++ ":new " ++ x--- > adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjustWithKey f 7 empty == empty--adjustWithKey :: Ord k => (k -> a -> a) -> k -> Map k a -> Map k a-adjustWithKey f = updateWithKey (\k' x' -> Just (f k' x'))-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjustWithKey #-}-#else-{-# INLINE adjustWithKey #-}-#endif---- | /O(log n)/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f x = if x == "a" then Just "new a" else Nothing--- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a-update f = updateWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE update #-}-#else-{-# INLINE update #-}-#endif---- | /O(log n)/. The expression (@'updateWithKey' f k map@) updates the--- value @x@ at @k@ (if it is in the map). If (@f k x@) is 'Nothing',--- the element is deleted. If it is (@'Just' y@), the key @k@ is bound--- to the new value @y@.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"---- See Map.Base.Note: Type of local 'go' function-updateWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a-updateWithKey = go- where- go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a- STRICT_2_OF_3(go)- go _ _ Tip = Tip- go f k(Bin sx kx x l r) =- case compare k kx of- LT -> balanceR kx x (go f k l) r- GT -> balanceL kx x l (go f k r)- EQ -> case f kx x of- Just x' -> x' `seq` Bin sx kx x' l r- Nothing -> glue l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateWithKey #-}-#else-{-# INLINE updateWithKey #-}-#endif---- | /O(log n)/. Lookup and update. See also 'updateWithKey'.--- The function returns changed value, if it is updated.--- Returns the original key value if the map entry is deleted.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) == (Just "5:new a", fromList [(3, "b"), (5, "5:new a")])--- > updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a")])--- > updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) == (Just "b", singleton 5 "a")---- See Map.Base.Note: Type of local 'go' function-updateLookupWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)-updateLookupWithKey = go- where- go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)- STRICT_2_OF_3(go)- go _ _ Tip = (Nothing,Tip)- go f k (Bin sx kx x l r) =- case compare k kx of- LT -> let (found,l') = go f k l- in found `strictPair` balanceR kx x l' r- GT -> let (found,r') = go f k r- in found `strictPair` balanceL kx x l r'- EQ -> case f kx x of- Just x' -> x' `seq` (Just x' `strictPair` Bin sx kx x' l r)- Nothing -> (Just x,glue l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateLookupWithKey #-}-#else-{-# INLINE updateLookupWithKey #-}-#endif---- | /O(log n)/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.--- 'alter' can be used to insert, delete, or update a value in a 'Map'.--- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.------ > let f _ = Nothing--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- >--- > let f _ = Just "c"--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "c")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "c")]---- See Map.Base.Note: Type of local 'go' function-alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a-alter = go- where- go :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a- STRICT_2_OF_3(go)- go f k Tip = case f Nothing of- Nothing -> Tip- Just x -> singleton k x-- go f k (Bin sx kx x l r) = case compare k kx of- LT -> balance kx x (go f k l) r- GT -> balance kx x l (go f k r)- EQ -> case f (Just x) of- Just x' -> x' `seq` Bin sx kx x' l r- Nothing -> glue l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE alter #-}-#else-{-# INLINE alter #-}-#endif--{--------------------------------------------------------------------- Indexing---------------------------------------------------------------------}---- | /O(log n)/. Update the element at /index/. Calls 'error' when an--- invalid index is used.------ > updateAt (\ _ _ -> Just "x") 0 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "x"), (5, "a")]--- > updateAt (\ _ _ -> Just "x") 1 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "x")]--- > updateAt (\ _ _ -> Just "x") 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\ _ _ -> Just "x") (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > updateAt (\_ _ -> Nothing) 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a-updateAt f i t = i `seq`- case t of- Tip -> error "Map.updateAt: index out of range"- Bin sx kx x l r -> case compare i sizeL of- LT -> balanceR kx x (updateAt f i l) r- GT -> balanceL kx x l (updateAt f (i-sizeL-1) r)- EQ -> case f kx x of- Just x' -> x' `seq` Bin sx kx x' l r- Nothing -> glue l r- where- sizeL = size l--{--------------------------------------------------------------------- Minimal, Maximal---------------------------------------------------------------------}---- | /O(log n)/. Update the value at the minimal key.------ > updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "Xb"), (5, "a")]--- > updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMin :: (a -> Maybe a) -> Map k a -> Map k a-updateMin f m- = updateMinWithKey (\_ x -> f x) m---- | /O(log n)/. Update the value at the maximal key.------ > updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "Xa")]--- > updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMax :: (a -> Maybe a) -> Map k a -> Map k a-updateMax f m- = updateMaxWithKey (\_ x -> f x) m----- | /O(log n)/. Update the value at the minimal key.------ > updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"3:b"), (5,"a")]--- > updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--updateMinWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMinWithKey _ Tip = Tip-updateMinWithKey f (Bin sx kx x Tip r) = case f kx x of- Nothing -> r- Just x' -> x' `seq` Bin sx kx x' Tip r-updateMinWithKey f (Bin _ kx x l r) = balanceR kx x (updateMinWithKey f l) r---- | /O(log n)/. Update the value at the maximal key.------ > updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"b"), (5,"5:a")]--- > updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--updateMaxWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMaxWithKey _ Tip = Tip-updateMaxWithKey f (Bin sx kx x l Tip) = case f kx x of- Nothing -> l- Just x' -> x' `seq` Bin sx kx x' l Tip-updateMaxWithKey f (Bin _ kx x l r) = balanceL kx x l (updateMaxWithKey f r)--{--------------------------------------------------------------------- Union.---------------------------------------------------------------------}---- | The union of a list of maps, with a combining operation:--- (@'unionsWith' f == 'Prelude.foldl' ('unionWith' f) 'empty'@).------ > unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--unionsWith :: Ord k => (a->a->a) -> [Map k a] -> Map k a-unionsWith f ts- = foldlStrict (unionWith f) empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionsWith #-}-#endif--{--------------------------------------------------------------------- Union with a combining function---------------------------------------------------------------------}--- | /O(n+m)/. Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.------ > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]--unionWith :: Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWith f m1 m2- = unionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWith #-}-#endif---- | /O(n+m)/.--- Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]--unionWithKey :: Ord k => (k -> a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) id id t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWithKey #-}-#endif--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}---- | /O(n+m)/. Difference with a combining function.--- When two equal keys are--- encountered, the combining function is applied to the values of these keys.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f al ar = if al == "b" then Just (al ++ ":" ++ ar) else Nothing--- > differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])--- > == singleton 3 "b:B"--differenceWith :: Ord k => (a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWith f m1 m2- = differenceWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWith #-}-#endif---- | /O(n+m)/. Difference with a combining function. When two equal keys are--- encountered, the combining function is applied to the key and both values.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--- > differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])--- > == singleton 3 "3:b|B"--differenceWithKey :: Ord k => (k -> a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWithKey f t1 t2 = mergeWithKey f id (const Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWithKey #-}-#endif---{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}---- | /O(n+m)/. Intersection with a combining function.------ > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"--intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWith f m1 m2- = intersectionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWith #-}-#endif---- | /O(n+m)/. Intersection with a combining function.--- Intersection is more efficient on (bigset \``intersection`\` smallset).------ > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"---intersectionWithKey :: Ord k => (k -> a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) (const Tip) (const Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWithKey #-}-#endif---{--------------------------------------------------------------------- MergeWithKey---------------------------------------------------------------------}---- | /O(n+m)/. A high-performance universal combining function. This function--- is used to define 'unionWith', 'unionWithKey', 'differenceWith',--- 'differenceWithKey', 'intersectionWith', 'intersectionWithKey' and can be--- used to define other custom combine functions.------ Please make sure you know what is going on when using 'mergeWithKey',--- otherwise you can be surprised by unexpected code growth or even--- corruption of the data structure.------ When 'mergeWithKey' is given three arguments, it is inlined to the call--- site. You should therefore use 'mergeWithKey' only to define your custom--- combining functions. For example, you could define 'unionWithKey',--- 'differenceWithKey' and 'intersectionWithKey' as------ > myUnionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) id id m1 m2--- > myDifferenceWithKey f m1 m2 = mergeWithKey f id (const empty) m1 m2--- > myIntersectionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) (const empty) (const empty) m1 m2------ When calling @'mergeWithKey' combine only1 only2@, a function combining two--- 'IntMap's is created, such that------ * if a key is present in both maps, it is passed with both corresponding--- values to the @combine@ function. Depending on the result, the key is either--- present in the result with specified value, or is left out;------ * a nonempty subtree present only in the first map is passed to @only1@ and--- the output is added to the result;------ * a nonempty subtree present only in the second map is passed to @only2@ and--- the output is added to the result.------ The @only1@ and @only2@ methods /must return a map with a subset (possibly empty) of the keys of the given map/.--- The values can be modified arbitrarily. Most common variants of @only1@ and--- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@ or--- @'filterWithKey' f@ could be used for any @f@.--mergeWithKey :: Ord k => (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c)- -> Map k a -> Map k b -> Map k c-mergeWithKey f g1 g2 = go- where- go Tip t2 = g2 t2- go t1 Tip = g1 t1- go t1 t2 = hedgeMerge NothingS NothingS t1 t2-- hedgeMerge _ _ t1 Tip = g1 t1- hedgeMerge blo bhi Tip (Bin _ kx x l r) = g2 $ join kx x (filterGt blo l) (filterLt bhi r)- hedgeMerge blo bhi (Bin _ kx x l r) t2 = let l' = hedgeMerge blo bmi l (trim blo bmi t2)- (found, trim_t2) = trimLookupLo kx bhi t2- r' = hedgeMerge bmi bhi r trim_t2- in case found of- Nothing -> case g1 (singleton kx x) of- Tip -> merge l' r'- (Bin _ _ x' Tip Tip) -> join kx x' l' r'- _ -> error "mergeWithKey: Given function only1 does not fulfil required conditions (see documentation)"- Just x2 -> case f kx x x2 of- Nothing -> merge l' r'- Just x' -> x' `seq` join kx x' l' r'- where bmi = JustS kx-{-# INLINE mergeWithKey #-}--{--------------------------------------------------------------------- Filter and partition---------------------------------------------------------------------}---- | /O(n)/. Map values and collect the 'Just' results.------ > let f x = if x == "a" then Just "new a" else Nothing--- > mapMaybe f (fromList [(5,"a"), (3,"b")]) == singleton 5 "new a"--mapMaybe :: (a -> Maybe b) -> Map k a -> Map k b-mapMaybe f = mapMaybeWithKey (\_ x -> f x)---- | /O(n)/. Map keys\/values and collect the 'Just' results.------ > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"--mapMaybeWithKey :: (k -> a -> Maybe b) -> Map k a -> Map k b-mapMaybeWithKey _ Tip = Tip-mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of- Just y -> y `seq` join kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)- Nothing -> merge (mapMaybeWithKey f l) (mapMaybeWithKey f r)---- | /O(n)/. Map values and separate the 'Left' and 'Right' results.------ > let f a = if a < "c" then Left a else Right a--- > mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])--- >--- > mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--mapEither :: (a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEither f m- = mapEitherWithKey (\_ x -> f x) m---- | /O(n)/. Map keys\/values and separate the 'Left' and 'Right' results.------ > let f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--- > mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])--- >--- > mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])--mapEitherWithKey :: (k -> a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEitherWithKey _ Tip = (Tip, Tip)-mapEitherWithKey f (Bin _ kx x l r) = case f kx x of- Left y -> y `seq` (join kx y l1 r1 `strictPair` merge l2 r2)- Right z -> z `seq` (merge l1 r1 `strictPair` join kx z l2 r2)- where- (l1,l2) = mapEitherWithKey f l- (r1,r2) = mapEitherWithKey f r--{--------------------------------------------------------------------- Mapping---------------------------------------------------------------------}--- | /O(n)/. Map a function over all values in the map.------ > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]--map :: (a -> b) -> Map k a -> Map k b-map _ Tip = Tip-map f (Bin sx kx x l r) = let x' = f x in x' `seq` Bin sx kx x' (map f l) (map f r)---- | /O(n)/. Map a function over all values in the map.------ > let f key x = (show key) ++ ":" ++ x--- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]--mapWithKey :: (k -> a -> b) -> Map k a -> Map k b-mapWithKey _ Tip = Tip-mapWithKey f (Bin sx kx x l r) = let x' = f kx x- in x' `seq` Bin sx kx x' (mapWithKey f l) (mapWithKey f r)---- | /O(n)/. The function 'mapAccum' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a b = (a ++ b, b ++ "X")--- > mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) == ("Everything: ba", fromList [(3, "bX"), (5, "aX")])--mapAccum :: (a -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccum f a m- = mapAccumWithKey (\a' _ x' -> f a' x') a m---- | /O(n)/. The function 'mapAccumWithKey' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--- > mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) == ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])--mapAccumWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumWithKey f a t- = mapAccumL f a t---- | /O(n)/. The function 'mapAccumL' threads an accumulating--- argument through the map in ascending order of keys.-mapAccumL :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumL _ a Tip = (a,Tip)-mapAccumL f a (Bin sx kx x l r) =- let (a1,l') = mapAccumL f a l- (a2,x') = f a1 kx x- (a3,r') = mapAccumL f a2 r- in x' `seq` (a3,Bin sx kx x' l' r')---- | /O(n)/. The function 'mapAccumR' threads an accumulating--- argument through the map in descending order of keys.-mapAccumRWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumRWithKey _ a Tip = (a,Tip)-mapAccumRWithKey f a (Bin sx kx x l r) =- let (a1,r') = mapAccumRWithKey f a r- (a2,x') = f a1 kx x- (a3,l') = mapAccumRWithKey f a2 l- in x' `seq` (a3,Bin sx kx x' l' r')---- | /O(n*log n)/.--- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the associated values will be--- combined using @c@.------ > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"--- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"--mapKeysWith :: Ord k2 => (a -> a -> a) -> (k1->k2) -> Map k1 a -> Map k2 a-mapKeysWith c f = fromListWith c . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeysWith #-}-#endif--{--------------------------------------------------------------------- Conversions---------------------------------------------------------------------}---- | /O(n)/. Build a map from a set of keys and a function which for each key--- computes its value.------ > fromSet (\k -> replicate k 'a') (Data.Set.fromList [3, 5]) == fromList [(5,"aaaaa"), (3,"aaa")]--- > fromSet undefined Data.Set.empty == empty--fromSet :: (k -> a) -> Set.Set k -> Map k a-fromSet _ Set.Tip = Tip-fromSet f (Set.Bin sz x l r) = case f x of v -> v `seq` Bin sz x v (fromSet f l) (fromSet f r)--{--------------------------------------------------------------------- Lists- use [foldlStrict] to reduce demand on the control-stack---------------------------------------------------------------------}--- | /O(n*log n)/. Build a map from a list of key\/value pairs. See also 'fromAscList'.--- If the list contains more than one value for the same key, the last value--- for the key is retained.------ > fromList [] == empty--- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]--- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]--fromList :: Ord k => [(k,a)] -> Map k a-fromList xs- = foldlStrict ins empty xs- where- ins t (k,x) = insert k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromList #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "ab"), (5, "aba")]--- > fromListWith (++) [] == empty--fromListWith :: Ord k => (a -> a -> a) -> [(k,a)] -> Map k a-fromListWith f xs- = fromListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWith #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.------ > let f k a1 a2 = (show k) ++ a1 ++ a2--- > fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "3ab"), (5, "5a5ba")]--- > fromListWithKey f [] == empty--fromListWithKey :: Ord k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromListWithKey f xs- = foldlStrict ins empty xs- where- ins t (k,x) = insertWithKey f k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWithKey #-}-#endif--{--------------------------------------------------------------------- Building trees from ascending/descending lists can be done in linear time.-- Note that if [xs] is ascending that:- fromAscList xs == fromList xs- fromAscListWith f xs == fromListWith f xs---------------------------------------------------------------------}--- | /O(n)/. Build a map from an ascending list in linear time.--- /The precondition (input list is ascending) is not checked./------ > fromAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]--- > valid (fromAscList [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscList [(5,"a"), (3,"b"), (5,"b")]) == False--fromAscList :: Eq k => [(k,a)] -> Map k a-fromAscList xs- = fromAscListWithKey (\_ x _ -> x) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscList #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--- > valid (fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscListWith (++) [(5,"a"), (3,"b"), (5,"b")]) == False--fromAscListWith :: Eq k => (a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWith f xs- = fromAscListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWith #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a--- combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > let f k a1 a2 = (show k) ++ ":" ++ a1 ++ a2--- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")] == fromList [(3, "b"), (5, "5:b5:ba")]--- > valid (fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")]) == True--- > valid (fromAscListWithKey f [(5,"a"), (3,"b"), (5,"b"), (5,"b")]) == False--fromAscListWithKey :: Eq k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWithKey f xs- = fromDistinctAscList (combineEq f xs)- where- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]- combineEq _ xs'- = case xs' of- [] -> []- [x] -> [x]- (x:xx) -> combineEq' x xx-- combineEq' z [] = [z]- combineEq' z@(kz,zz) (x@(kx,xx):xs')- | kx==kz = let yy = f kx xx zz in yy `seq` combineEq' (kx,yy) xs'- | otherwise = z:combineEq' x xs'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWithKey #-}-#endif---- | /O(n)/. Build a map from an ascending list of distinct elements in linear time.--- /The precondition is not checked./------ > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > valid (fromDistinctAscList [(3,"b"), (5,"a")]) == True--- > valid (fromDistinctAscList [(3,"b"), (5,"a"), (5,"b")]) == False--fromDistinctAscList :: [(k,a)] -> Map k a-fromDistinctAscList xs- = create const (length xs) xs- where- -- 1) use continuations so that we use heap space instead of stack space.- -- 2) special case for n==5 to create bushier trees.- create c 0 xs' = c Tip xs'- create c 5 xs' = case xs' of- ((k1,x1):(k2,x2):(k3,x3):(k4,x4):(k5,x5):xx)- -> x1 `seq` x2 `seq` x3 `seq` x4 `seq` x5 `seq`- c (bin k4 x4 (bin k2 x2 (singleton k1 x1) (singleton k3 x3))- (singleton k5 x5)) xx- _ -> error "fromDistinctAscList create"- create c n xs' = seq nr $ create (createR nr c) nl xs'- where nl = n `div` 2- nr = n - nl - 1-- createR n c l ((k,x):ys) = x `seq` create (createB l k x c) n ys- createR _ _ _ [] = error "fromDistinctAscList createR []"- createB l k x c r zs = x `seq` c (bin k x l r) zs
@@ -1,1793 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif-#if __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Sequence--- Copyright : (c) Ross Paterson 2005--- (c) Louis Wasserman 2009--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ General purpose finite sequences.--- Apart from being finite and having strict operations, sequences--- also differ from lists in supporting a wider variety of operations--- efficiently.------ An amortized running time is given for each operation, with /n/ referring--- to the length of the sequence and /i/ being the integral index used by--- some operations. These bounds hold even in a persistent (shared) setting.------ The implementation uses 2-3 finger trees annotated with sizes,--- as described in section 4.2 of------ * Ralf Hinze and Ross Paterson,--- \"Finger trees: a simple general-purpose data structure\",--- /Journal of Functional Programming/ 16:2 (2006) pp 197-217.--- <http://www.soi.city.ac.uk/~ross/papers/FingerTree.html>------ /Note/: Many of these operations have the same names as similar--- operations on lists in the "Prelude". The ambiguity may be resolved--- using either qualification or the @hiding@ clause.-----------------------------------------------------------------------------------module Data.Sequence (-#if !defined(TESTING)- Seq,-#else- Seq(..), Elem(..), FingerTree(..), Node(..), Digit(..),-#endif- -- * Construction- empty, -- :: Seq a- singleton, -- :: a -> Seq a- (<|), -- :: a -> Seq a -> Seq a- (|>), -- :: Seq a -> a -> Seq a- (><), -- :: Seq a -> Seq a -> Seq a- fromList, -- :: [a] -> Seq a- -- ** Repetition- replicate, -- :: Int -> a -> Seq a- replicateA, -- :: Applicative f => Int -> f a -> f (Seq a)- replicateM, -- :: Monad m => Int -> m a -> m (Seq a)- -- ** Iterative construction- iterateN, -- :: Int -> (a -> a) -> a -> Seq a- unfoldr, -- :: (b -> Maybe (a, b)) -> b -> Seq a- unfoldl, -- :: (b -> Maybe (b, a)) -> b -> Seq a- -- * Deconstruction- -- | Additional functions for deconstructing sequences are available- -- via the 'Foldable' instance of 'Seq'.-- -- ** Queries- null, -- :: Seq a -> Bool- length, -- :: Seq a -> Int- -- ** Views- ViewL(..),- viewl, -- :: Seq a -> ViewL a- ViewR(..),- viewr, -- :: Seq a -> ViewR a- -- * Scans- scanl, -- :: (a -> b -> a) -> a -> Seq b -> Seq a- scanl1, -- :: (a -> a -> a) -> Seq a -> Seq a- scanr, -- :: (a -> b -> b) -> b -> Seq a -> Seq b- scanr1, -- :: (a -> a -> a) -> Seq a -> Seq a- -- * Sublists- tails, -- :: Seq a -> Seq (Seq a)- inits, -- :: Seq a -> Seq (Seq a)- -- ** Sequential searches- takeWhileL, -- :: (a -> Bool) -> Seq a -> Seq a- takeWhileR, -- :: (a -> Bool) -> Seq a -> Seq a- dropWhileL, -- :: (a -> Bool) -> Seq a -> Seq a- dropWhileR, -- :: (a -> Bool) -> Seq a -> Seq a- spanl, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a)- spanr, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a)- breakl, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a)- breakr, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a)- partition, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a)- filter, -- :: (a -> Bool) -> Seq a -> Seq a- -- * Sorting- sort, -- :: Ord a => Seq a -> Seq a- sortBy, -- :: (a -> a -> Ordering) -> Seq a -> Seq a- unstableSort, -- :: Ord a => Seq a -> Seq a- unstableSortBy, -- :: (a -> a -> Ordering) -> Seq a -> Seq a- -- * Indexing- index, -- :: Seq a -> Int -> a- adjust, -- :: (a -> a) -> Int -> Seq a -> Seq a- update, -- :: Int -> a -> Seq a -> Seq a- take, -- :: Int -> Seq a -> Seq a- drop, -- :: Int -> Seq a -> Seq a- splitAt, -- :: Int -> Seq a -> (Seq a, Seq a)- -- ** Indexing with predicates- -- | These functions perform sequential searches from the left- -- or right ends of the sequence, returning indices of matching- -- elements.- elemIndexL, -- :: Eq a => a -> Seq a -> Maybe Int- elemIndicesL, -- :: Eq a => a -> Seq a -> [Int]- elemIndexR, -- :: Eq a => a -> Seq a -> Maybe Int- elemIndicesR, -- :: Eq a => a -> Seq a -> [Int]- findIndexL, -- :: (a -> Bool) -> Seq a -> Maybe Int- findIndicesL, -- :: (a -> Bool) -> Seq a -> [Int]- findIndexR, -- :: (a -> Bool) -> Seq a -> Maybe Int- findIndicesR, -- :: (a -> Bool) -> Seq a -> [Int]- -- * Folds- -- | General folds are available via the 'Foldable' instance of 'Seq'.- foldlWithIndex, -- :: (b -> Int -> a -> b) -> b -> Seq a -> b- foldrWithIndex, -- :: (Int -> a -> b -> b) -> b -> Seq a -> b- -- * Transformations- mapWithIndex, -- :: (Int -> a -> b) -> Seq a -> Seq b- reverse, -- :: Seq a -> Seq a- -- ** Zips- zip, -- :: Seq a -> Seq b -> Seq (a, b)- zipWith, -- :: (a -> b -> c) -> Seq a -> Seq b -> Seq c- zip3, -- :: Seq a -> Seq b -> Seq c -> Seq (a, b, c)- zipWith3, -- :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d- zip4, -- :: Seq a -> Seq b -> Seq c -> Seq d -> Seq (a, b, c, d)- zipWith4, -- :: (a -> b -> c -> d -> e) -> Seq a -> Seq b -> Seq c -> Seq d -> Seq e-#if TESTING- Sized(..),- deep,- node2,- node3,-#endif- ) where--import Prelude hiding (- Functor(..),- null, length, take, drop, splitAt, foldl, foldl1, foldr, foldr1,- scanl, scanl1, scanr, scanr1, replicate, zip, zipWith, zip3, zipWith3,- takeWhile, dropWhile, iterate, reverse, filter, mapM, sum, all)-import qualified Data.List-import Control.Applicative (Applicative(..), (<$>), WrappedMonad(..), liftA, liftA2, liftA3)-import Control.DeepSeq (NFData(rnf))-import Control.Monad (MonadPlus(..), ap)-import Data.Monoid (Monoid(..))-import Data.Functor (Functor(..))-import Data.Foldable-import Data.Traversable-import Data.Typeable--#ifdef __GLASGOW_HASKELL__-import GHC.Exts (build)-import Text.Read (Lexeme(Ident), lexP, parens, prec,- readPrec, readListPrec, readListPrecDefault)-import Data.Data-#endif--infixr 5 `consTree`-infixl 5 `snocTree`--infixr 5 ><-infixr 5 <|, :<-infixl 5 |>, :>--class Sized a where- size :: a -> Int---- | General-purpose finite sequences.-newtype Seq a = Seq (FingerTree (Elem a))--instance Functor Seq where- fmap f (Seq xs) = Seq (fmap (fmap f) xs)-#ifdef __GLASGOW_HASKELL__- x <$ s = replicate (length s) x-#endif--instance Foldable Seq where- foldr f z (Seq xs) = foldr (flip (foldr f)) z xs- foldl f z (Seq xs) = foldl (foldl f) z xs-- foldr1 f (Seq xs) = getElem (foldr1 f' xs)- where f' (Elem x) (Elem y) = Elem (f x y)-- foldl1 f (Seq xs) = getElem (foldl1 f' xs)- where f' (Elem x) (Elem y) = Elem (f x y)--instance Traversable Seq where- traverse f (Seq xs) = Seq <$> traverse (traverse f) xs--instance NFData a => NFData (Seq a) where- rnf (Seq xs) = rnf xs--instance Monad Seq where- return = singleton- xs >>= f = foldl' add empty xs- where add ys x = ys >< f x--instance MonadPlus Seq where- mzero = empty- mplus = (><)--instance Eq a => Eq (Seq a) where- xs == ys = length xs == length ys && toList xs == toList ys--instance Ord a => Ord (Seq a) where- compare xs ys = compare (toList xs) (toList ys)--#if TESTING-instance Show a => Show (Seq a) where- showsPrec p (Seq x) = showsPrec p x-#else-instance Show a => Show (Seq a) where- showsPrec p xs = showParen (p > 10) $- showString "fromList " . shows (toList xs)-#endif--instance Read a => Read (Seq a) where-#ifdef __GLASGOW_HASKELL__- readPrec = parens $ prec 10 $ do- Ident "fromList" <- lexP- xs <- readPrec- return (fromList xs)-- readListPrec = readListPrecDefault-#else- readsPrec p = readParen (p > 10) $ \ r -> do- ("fromList",s) <- lex r- (xs,t) <- reads s- return (fromList xs,t)-#endif--instance Monoid (Seq a) where- mempty = empty- mappend = (><)--#include "Typeable.h"-INSTANCE_TYPEABLE1(Seq,seqTc,"Seq")--#if __GLASGOW_HASKELL__-instance Data a => Data (Seq a) where- gfoldl f z s = case viewl s of- EmptyL -> z empty- x :< xs -> z (<|) `f` x `f` xs-- gunfold k z c = case constrIndex c of- 1 -> z empty- 2 -> k (k (z (<|)))- _ -> error "gunfold"-- toConstr xs- | null xs = emptyConstr- | otherwise = consConstr-- dataTypeOf _ = seqDataType-- dataCast1 f = gcast1 f--emptyConstr, consConstr :: Constr-emptyConstr = mkConstr seqDataType "empty" [] Prefix-consConstr = mkConstr seqDataType "<|" [] Infix--seqDataType :: DataType-seqDataType = mkDataType "Data.Sequence.Seq" [emptyConstr, consConstr]-#endif---- Finger trees--data FingerTree a- = Empty- | Single a- | Deep {-# UNPACK #-} !Int !(Digit a) (FingerTree (Node a)) !(Digit a)-#if TESTING- deriving Show-#endif--instance Sized a => Sized (FingerTree a) where- {-# SPECIALIZE instance Sized (FingerTree (Elem a)) #-}- {-# SPECIALIZE instance Sized (FingerTree (Node a)) #-}- size Empty = 0- size (Single x) = size x- size (Deep v _ _ _) = v--instance Foldable FingerTree where- foldr _ z Empty = z- foldr f z (Single x) = x `f` z- foldr f z (Deep _ pr m sf) =- foldr f (foldr (flip (foldr f)) (foldr f z sf) m) pr-- foldl _ z Empty = z- foldl f z (Single x) = z `f` x- foldl f z (Deep _ pr m sf) =- foldl f (foldl (foldl f) (foldl f z pr) m) sf-- foldr1 _ Empty = error "foldr1: empty sequence"- foldr1 _ (Single x) = x- foldr1 f (Deep _ pr m sf) =- foldr f (foldr (flip (foldr f)) (foldr1 f sf) m) pr-- foldl1 _ Empty = error "foldl1: empty sequence"- foldl1 _ (Single x) = x- foldl1 f (Deep _ pr m sf) =- foldl f (foldl (foldl f) (foldl1 f pr) m) sf--instance Functor FingerTree where- fmap _ Empty = Empty- fmap f (Single x) = Single (f x)- fmap f (Deep v pr m sf) =- Deep v (fmap f pr) (fmap (fmap f) m) (fmap f sf)--instance Traversable FingerTree where- traverse _ Empty = pure Empty- traverse f (Single x) = Single <$> f x- traverse f (Deep v pr m sf) =- Deep v <$> traverse f pr <*> traverse (traverse f) m <*>- traverse f sf--instance NFData a => NFData (FingerTree a) where- rnf (Empty) = ()- rnf (Single x) = rnf x- rnf (Deep _ pr m sf) = rnf pr `seq` rnf m `seq` rnf sf--{-# INLINE deep #-}-deep :: Sized a => Digit a -> FingerTree (Node a) -> Digit a -> FingerTree a-deep pr m sf = Deep (size pr + size m + size sf) pr m sf--{-# INLINE pullL #-}-pullL :: Sized a => Int -> FingerTree (Node a) -> Digit a -> FingerTree a-pullL s m sf = case viewLTree m of- Nothing2 -> digitToTree' s sf- Just2 pr m' -> Deep s (nodeToDigit pr) m' sf--{-# INLINE pullR #-}-pullR :: Sized a => Int -> Digit a -> FingerTree (Node a) -> FingerTree a-pullR s pr m = case viewRTree m of- Nothing2 -> digitToTree' s pr- Just2 m' sf -> Deep s pr m' (nodeToDigit sf)--{-# SPECIALIZE deepL :: Maybe (Digit (Elem a)) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-}-{-# SPECIALIZE deepL :: Maybe (Digit (Node a)) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-}-deepL :: Sized a => Maybe (Digit a) -> FingerTree (Node a) -> Digit a -> FingerTree a-deepL Nothing m sf = pullL (size m + size sf) m sf-deepL (Just pr) m sf = deep pr m sf--{-# SPECIALIZE deepR :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Maybe (Digit (Elem a)) -> FingerTree (Elem a) #-}-{-# SPECIALIZE deepR :: Digit (Node a) -> FingerTree (Node (Node a)) -> Maybe (Digit (Node a)) -> FingerTree (Node a) #-}-deepR :: Sized a => Digit a -> FingerTree (Node a) -> Maybe (Digit a) -> FingerTree a-deepR pr m Nothing = pullR (size m + size pr) pr m-deepR pr m (Just sf) = deep pr m sf---- Digits--data Digit a- = One a- | Two a a- | Three a a a- | Four a a a a-#if TESTING- deriving Show-#endif--instance Foldable Digit where- foldr f z (One a) = a `f` z- foldr f z (Two a b) = a `f` (b `f` z)- foldr f z (Three a b c) = a `f` (b `f` (c `f` z))- foldr f z (Four a b c d) = a `f` (b `f` (c `f` (d `f` z)))-- foldl f z (One a) = z `f` a- foldl f z (Two a b) = (z `f` a) `f` b- foldl f z (Three a b c) = ((z `f` a) `f` b) `f` c- foldl f z (Four a b c d) = (((z `f` a) `f` b) `f` c) `f` d-- foldr1 _ (One a) = a- foldr1 f (Two a b) = a `f` b- foldr1 f (Three a b c) = a `f` (b `f` c)- foldr1 f (Four a b c d) = a `f` (b `f` (c `f` d))-- foldl1 _ (One a) = a- foldl1 f (Two a b) = a `f` b- foldl1 f (Three a b c) = (a `f` b) `f` c- foldl1 f (Four a b c d) = ((a `f` b) `f` c) `f` d--instance Functor Digit where- {-# INLINE fmap #-}- fmap f (One a) = One (f a)- fmap f (Two a b) = Two (f a) (f b)- fmap f (Three a b c) = Three (f a) (f b) (f c)- fmap f (Four a b c d) = Four (f a) (f b) (f c) (f d)--instance Traversable Digit where- {-# INLINE traverse #-}- traverse f (One a) = One <$> f a- traverse f (Two a b) = Two <$> f a <*> f b- traverse f (Three a b c) = Three <$> f a <*> f b <*> f c- traverse f (Four a b c d) = Four <$> f a <*> f b <*> f c <*> f d--instance NFData a => NFData (Digit a) where- rnf (One a) = rnf a- rnf (Two a b) = rnf a `seq` rnf b- rnf (Three a b c) = rnf a `seq` rnf b `seq` rnf c- rnf (Four a b c d) = rnf a `seq` rnf b `seq` rnf c `seq` rnf d--instance Sized a => Sized (Digit a) where- {-# INLINE size #-}- size = foldl1 (+) . fmap size--{-# SPECIALIZE digitToTree :: Digit (Elem a) -> FingerTree (Elem a) #-}-{-# SPECIALIZE digitToTree :: Digit (Node a) -> FingerTree (Node a) #-}-digitToTree :: Sized a => Digit a -> FingerTree a-digitToTree (One a) = Single a-digitToTree (Two a b) = deep (One a) Empty (One b)-digitToTree (Three a b c) = deep (Two a b) Empty (One c)-digitToTree (Four a b c d) = deep (Two a b) Empty (Two c d)---- | Given the size of a digit and the digit itself, efficiently converts--- it to a FingerTree.-digitToTree' :: Int -> Digit a -> FingerTree a-digitToTree' n (Four a b c d) = Deep n (Two a b) Empty (Two c d)-digitToTree' n (Three a b c) = Deep n (Two a b) Empty (One c)-digitToTree' n (Two a b) = Deep n (One a) Empty (One b)-digitToTree' n (One a) = n `seq` Single a---- Nodes--data Node a- = Node2 {-# UNPACK #-} !Int a a- | Node3 {-# UNPACK #-} !Int a a a-#if TESTING- deriving Show-#endif--instance Foldable Node where- foldr f z (Node2 _ a b) = a `f` (b `f` z)- foldr f z (Node3 _ a b c) = a `f` (b `f` (c `f` z))-- foldl f z (Node2 _ a b) = (z `f` a) `f` b- foldl f z (Node3 _ a b c) = ((z `f` a) `f` b) `f` c--instance Functor Node where- {-# INLINE fmap #-}- fmap f (Node2 v a b) = Node2 v (f a) (f b)- fmap f (Node3 v a b c) = Node3 v (f a) (f b) (f c)--instance Traversable Node where- {-# INLINE traverse #-}- traverse f (Node2 v a b) = Node2 v <$> f a <*> f b- traverse f (Node3 v a b c) = Node3 v <$> f a <*> f b <*> f c--instance NFData a => NFData (Node a) where- rnf (Node2 _ a b) = rnf a `seq` rnf b- rnf (Node3 _ a b c) = rnf a `seq` rnf b `seq` rnf c--instance Sized (Node a) where- size (Node2 v _ _) = v- size (Node3 v _ _ _) = v--{-# INLINE node2 #-}-node2 :: Sized a => a -> a -> Node a-node2 a b = Node2 (size a + size b) a b--{-# INLINE node3 #-}-node3 :: Sized a => a -> a -> a -> Node a-node3 a b c = Node3 (size a + size b + size c) a b c--nodeToDigit :: Node a -> Digit a-nodeToDigit (Node2 _ a b) = Two a b-nodeToDigit (Node3 _ a b c) = Three a b c---- Elements--newtype Elem a = Elem { getElem :: a }-#if TESTING- deriving Show-#endif--instance Sized (Elem a) where- size _ = 1--instance Functor Elem where- fmap f (Elem x) = Elem (f x)--instance Foldable Elem where- foldr f z (Elem x) = f x z- foldl f z (Elem x) = f z x--instance Traversable Elem where- traverse f (Elem x) = Elem <$> f x--instance NFData a => NFData (Elem a) where- rnf (Elem x) = rnf x------------------------------------------------------------ Applicative construction----------------------------------------------------------newtype Id a = Id {runId :: a}--instance Functor Id where- fmap f (Id x) = Id (f x)--instance Monad Id where- return = Id- m >>= k = k (runId m)--instance Applicative Id where- pure = return- (<*>) = ap---- | This is essentially a clone of Control.Monad.State.Strict.-newtype State s a = State {runState :: s -> (s, a)}--instance Functor (State s) where- fmap = liftA--instance Monad (State s) where- {-# INLINE return #-}- {-# INLINE (>>=) #-}- return x = State $ \ s -> (s, x)- m >>= k = State $ \ s -> case runState m s of- (s', x) -> runState (k x) s'--instance Applicative (State s) where- pure = return- (<*>) = ap--execState :: State s a -> s -> a-execState m x = snd (runState m x)---- | A helper method: a strict version of mapAccumL.-mapAccumL' :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)-mapAccumL' f s t = runState (traverse (State . flip f) t) s---- | 'applicativeTree' takes an Applicative-wrapped construction of a--- piece of a FingerTree, assumed to always have the same size (which--- is put in the second argument), and replicates it as many times as--- specified. This is a generalization of 'replicateA', which itself--- is a generalization of many Data.Sequence methods.-{-# SPECIALIZE applicativeTree :: Int -> Int -> State s a -> State s (FingerTree a) #-}-{-# SPECIALIZE applicativeTree :: Int -> Int -> Id a -> Id (FingerTree a) #-}--- Special note: the Id specialization automatically does node sharing,--- reducing memory usage of the resulting tree to /O(log n)/.-applicativeTree :: Applicative f => Int -> Int -> f a -> f (FingerTree a)-applicativeTree n mSize m = mSize `seq` case n of- 0 -> pure Empty- 1 -> liftA Single m- 2 -> deepA one emptyTree one- 3 -> deepA two emptyTree one- 4 -> deepA two emptyTree two- 5 -> deepA three emptyTree two- 6 -> deepA three emptyTree three- 7 -> deepA four emptyTree three- 8 -> deepA four emptyTree four- _ -> let (q, r) = n `quotRem` 3 in q `seq` case r of- 0 -> deepA three (applicativeTree (q - 2) mSize' n3) three- 1 -> deepA four (applicativeTree (q - 2) mSize' n3) three- _ -> deepA four (applicativeTree (q - 2) mSize' n3) four- where- one = liftA One m- two = liftA2 Two m m- three = liftA3 Three m m m- four = liftA3 Four m m m <*> m- deepA = liftA3 (Deep (n * mSize))- mSize' = 3 * mSize- n3 = liftA3 (Node3 mSize') m m m- emptyTree = pure Empty----------------------------------------------------------------------------- Construction----------------------------------------------------------------------------- | /O(1)/. The empty sequence.-empty :: Seq a-empty = Seq Empty---- | /O(1)/. A singleton sequence.-singleton :: a -> Seq a-singleton x = Seq (Single (Elem x))---- | /O(log n)/. @replicate n x@ is a sequence consisting of @n@ copies of @x@.-replicate :: Int -> a -> Seq a-replicate n x- | n >= 0 = runId (replicateA n (Id x))- | otherwise = error "replicate takes a nonnegative integer argument"---- | 'replicateA' is an 'Applicative' version of 'replicate', and makes--- /O(log n)/ calls to '<*>' and 'pure'.------ > replicateA n x = sequenceA (replicate n x)-replicateA :: Applicative f => Int -> f a -> f (Seq a)-replicateA n x- | n >= 0 = Seq <$> applicativeTree n 1 (Elem <$> x)- | otherwise = error "replicateA takes a nonnegative integer argument"---- | 'replicateM' is a sequence counterpart of 'Control.Monad.replicateM'.------ > replicateM n x = sequence (replicate n x)-replicateM :: Monad m => Int -> m a -> m (Seq a)-replicateM n x- | n >= 0 = unwrapMonad (replicateA n (WrapMonad x))- | otherwise = error "replicateM takes a nonnegative integer argument"---- | /O(1)/. Add an element to the left end of a sequence.--- Mnemonic: a triangle with the single element at the pointy end.-(<|) :: a -> Seq a -> Seq a-x <| Seq xs = Seq (Elem x `consTree` xs)--{-# SPECIALIZE consTree :: Elem a -> FingerTree (Elem a) -> FingerTree (Elem a) #-}-{-# SPECIALIZE consTree :: Node a -> FingerTree (Node a) -> FingerTree (Node a) #-}-consTree :: Sized a => a -> FingerTree a -> FingerTree a-consTree a Empty = Single a-consTree a (Single b) = deep (One a) Empty (One b)-consTree a (Deep s (Four b c d e) m sf) = m `seq`- Deep (size a + s) (Two a b) (node3 c d e `consTree` m) sf-consTree a (Deep s (Three b c d) m sf) =- Deep (size a + s) (Four a b c d) m sf-consTree a (Deep s (Two b c) m sf) =- Deep (size a + s) (Three a b c) m sf-consTree a (Deep s (One b) m sf) =- Deep (size a + s) (Two a b) m sf---- | /O(1)/. Add an element to the right end of a sequence.--- Mnemonic: a triangle with the single element at the pointy end.-(|>) :: Seq a -> a -> Seq a-Seq xs |> x = Seq (xs `snocTree` Elem x)--{-# SPECIALIZE snocTree :: FingerTree (Elem a) -> Elem a -> FingerTree (Elem a) #-}-{-# SPECIALIZE snocTree :: FingerTree (Node a) -> Node a -> FingerTree (Node a) #-}-snocTree :: Sized a => FingerTree a -> a -> FingerTree a-snocTree Empty a = Single a-snocTree (Single a) b = deep (One a) Empty (One b)-snocTree (Deep s pr m (Four a b c d)) e = m `seq`- Deep (s + size e) pr (m `snocTree` node3 a b c) (Two d e)-snocTree (Deep s pr m (Three a b c)) d =- Deep (s + size d) pr m (Four a b c d)-snocTree (Deep s pr m (Two a b)) c =- Deep (s + size c) pr m (Three a b c)-snocTree (Deep s pr m (One a)) b =- Deep (s + size b) pr m (Two a b)---- | /O(log(min(n1,n2)))/. Concatenate two sequences.-(><) :: Seq a -> Seq a -> Seq a-Seq xs >< Seq ys = Seq (appendTree0 xs ys)---- The appendTree/addDigits gunk below is machine generated--appendTree0 :: FingerTree (Elem a) -> FingerTree (Elem a) -> FingerTree (Elem a)-appendTree0 Empty xs =- xs-appendTree0 xs Empty =- xs-appendTree0 (Single x) xs =- x `consTree` xs-appendTree0 xs (Single x) =- xs `snocTree` x-appendTree0 (Deep s1 pr1 m1 sf1) (Deep s2 pr2 m2 sf2) =- Deep (s1 + s2) pr1 (addDigits0 m1 sf1 pr2 m2) sf2--addDigits0 :: FingerTree (Node (Elem a)) -> Digit (Elem a) -> Digit (Elem a) -> FingerTree (Node (Elem a)) -> FingerTree (Node (Elem a))-addDigits0 m1 (One a) (One b) m2 =- appendTree1 m1 (node2 a b) m2-addDigits0 m1 (One a) (Two b c) m2 =- appendTree1 m1 (node3 a b c) m2-addDigits0 m1 (One a) (Three b c d) m2 =- appendTree2 m1 (node2 a b) (node2 c d) m2-addDigits0 m1 (One a) (Four b c d e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits0 m1 (Two a b) (One c) m2 =- appendTree1 m1 (node3 a b c) m2-addDigits0 m1 (Two a b) (Two c d) m2 =- appendTree2 m1 (node2 a b) (node2 c d) m2-addDigits0 m1 (Two a b) (Three c d e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits0 m1 (Two a b) (Four c d e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits0 m1 (Three a b c) (One d) m2 =- appendTree2 m1 (node2 a b) (node2 c d) m2-addDigits0 m1 (Three a b c) (Two d e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits0 m1 (Three a b c) (Three d e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits0 m1 (Three a b c) (Four d e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits0 m1 (Four a b c d) (One e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits0 m1 (Four a b c d) (Two e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits0 m1 (Four a b c d) (Three e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits0 m1 (Four a b c d) (Four e f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2--appendTree1 :: FingerTree (Node a) -> Node a -> FingerTree (Node a) -> FingerTree (Node a)-appendTree1 Empty a xs =- a `consTree` xs-appendTree1 xs a Empty =- xs `snocTree` a-appendTree1 (Single x) a xs =- x `consTree` a `consTree` xs-appendTree1 xs a (Single x) =- xs `snocTree` a `snocTree` x-appendTree1 (Deep s1 pr1 m1 sf1) a (Deep s2 pr2 m2 sf2) =- Deep (s1 + size a + s2) pr1 (addDigits1 m1 sf1 a pr2 m2) sf2--addDigits1 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a))-addDigits1 m1 (One a) b (One c) m2 =- appendTree1 m1 (node3 a b c) m2-addDigits1 m1 (One a) b (Two c d) m2 =- appendTree2 m1 (node2 a b) (node2 c d) m2-addDigits1 m1 (One a) b (Three c d e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits1 m1 (One a) b (Four c d e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits1 m1 (Two a b) c (One d) m2 =- appendTree2 m1 (node2 a b) (node2 c d) m2-addDigits1 m1 (Two a b) c (Two d e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits1 m1 (Two a b) c (Three d e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits1 m1 (Two a b) c (Four d e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits1 m1 (Three a b c) d (One e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits1 m1 (Three a b c) d (Two e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits1 m1 (Three a b c) d (Three e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits1 m1 (Three a b c) d (Four e f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits1 m1 (Four a b c d) e (One f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits1 m1 (Four a b c d) e (Two f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits1 m1 (Four a b c d) e (Three f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits1 m1 (Four a b c d) e (Four f g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2--appendTree2 :: FingerTree (Node a) -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a)-appendTree2 Empty a b xs =- a `consTree` b `consTree` xs-appendTree2 xs a b Empty =- xs `snocTree` a `snocTree` b-appendTree2 (Single x) a b xs =- x `consTree` a `consTree` b `consTree` xs-appendTree2 xs a b (Single x) =- xs `snocTree` a `snocTree` b `snocTree` x-appendTree2 (Deep s1 pr1 m1 sf1) a b (Deep s2 pr2 m2 sf2) =- Deep (s1 + size a + size b + s2) pr1 (addDigits2 m1 sf1 a b pr2 m2) sf2--addDigits2 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a))-addDigits2 m1 (One a) b c (One d) m2 =- appendTree2 m1 (node2 a b) (node2 c d) m2-addDigits2 m1 (One a) b c (Two d e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits2 m1 (One a) b c (Three d e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits2 m1 (One a) b c (Four d e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits2 m1 (Two a b) c d (One e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits2 m1 (Two a b) c d (Two e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits2 m1 (Two a b) c d (Three e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits2 m1 (Two a b) c d (Four e f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits2 m1 (Three a b c) d e (One f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits2 m1 (Three a b c) d e (Two f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits2 m1 (Three a b c) d e (Three f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits2 m1 (Three a b c) d e (Four f g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits2 m1 (Four a b c d) e f (One g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits2 m1 (Four a b c d) e f (Two g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits2 m1 (Four a b c d) e f (Three g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits2 m1 (Four a b c d) e f (Four g h i j) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2--appendTree3 :: FingerTree (Node a) -> Node a -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a)-appendTree3 Empty a b c xs =- a `consTree` b `consTree` c `consTree` xs-appendTree3 xs a b c Empty =- xs `snocTree` a `snocTree` b `snocTree` c-appendTree3 (Single x) a b c xs =- x `consTree` a `consTree` b `consTree` c `consTree` xs-appendTree3 xs a b c (Single x) =- xs `snocTree` a `snocTree` b `snocTree` c `snocTree` x-appendTree3 (Deep s1 pr1 m1 sf1) a b c (Deep s2 pr2 m2 sf2) =- Deep (s1 + size a + size b + size c + s2) pr1 (addDigits3 m1 sf1 a b c pr2 m2) sf2--addDigits3 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Node a -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a))-addDigits3 m1 (One a) b c d (One e) m2 =- appendTree2 m1 (node3 a b c) (node2 d e) m2-addDigits3 m1 (One a) b c d (Two e f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits3 m1 (One a) b c d (Three e f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits3 m1 (One a) b c d (Four e f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits3 m1 (Two a b) c d e (One f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits3 m1 (Two a b) c d e (Two f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits3 m1 (Two a b) c d e (Three f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits3 m1 (Two a b) c d e (Four f g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits3 m1 (Three a b c) d e f (One g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits3 m1 (Three a b c) d e f (Two g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits3 m1 (Three a b c) d e f (Three g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits3 m1 (Three a b c) d e f (Four g h i j) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2-addDigits3 m1 (Four a b c d) e f g (One h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits3 m1 (Four a b c d) e f g (Two h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits3 m1 (Four a b c d) e f g (Three h i j) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2-addDigits3 m1 (Four a b c d) e f g (Four h i j k) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2--appendTree4 :: FingerTree (Node a) -> Node a -> Node a -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a)-appendTree4 Empty a b c d xs =- a `consTree` b `consTree` c `consTree` d `consTree` xs-appendTree4 xs a b c d Empty =- xs `snocTree` a `snocTree` b `snocTree` c `snocTree` d-appendTree4 (Single x) a b c d xs =- x `consTree` a `consTree` b `consTree` c `consTree` d `consTree` xs-appendTree4 xs a b c d (Single x) =- xs `snocTree` a `snocTree` b `snocTree` c `snocTree` d `snocTree` x-appendTree4 (Deep s1 pr1 m1 sf1) a b c d (Deep s2 pr2 m2 sf2) =- Deep (s1 + size a + size b + size c + size d + s2) pr1 (addDigits4 m1 sf1 a b c d pr2 m2) sf2--addDigits4 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Node a -> Node a -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a))-addDigits4 m1 (One a) b c d e (One f) m2 =- appendTree2 m1 (node3 a b c) (node3 d e f) m2-addDigits4 m1 (One a) b c d e (Two f g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits4 m1 (One a) b c d e (Three f g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits4 m1 (One a) b c d e (Four f g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits4 m1 (Two a b) c d e f (One g) m2 =- appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2-addDigits4 m1 (Two a b) c d e f (Two g h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits4 m1 (Two a b) c d e f (Three g h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits4 m1 (Two a b) c d e f (Four g h i j) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2-addDigits4 m1 (Three a b c) d e f g (One h) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2-addDigits4 m1 (Three a b c) d e f g (Two h i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits4 m1 (Three a b c) d e f g (Three h i j) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2-addDigits4 m1 (Three a b c) d e f g (Four h i j k) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2-addDigits4 m1 (Four a b c d) e f g h (One i) m2 =- appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2-addDigits4 m1 (Four a b c d) e f g h (Two i j) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2-addDigits4 m1 (Four a b c d) e f g h (Three i j k) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2-addDigits4 m1 (Four a b c d) e f g h (Four i j k l) m2 =- appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node3 j k l) m2---- | Builds a sequence from a seed value. Takes time linear in the--- number of generated elements. /WARNING:/ If the number of generated--- elements is infinite, this method will not terminate.-unfoldr :: (b -> Maybe (a, b)) -> b -> Seq a-unfoldr f = unfoldr' empty- -- uses tail recursion rather than, for instance, the List implementation.- where unfoldr' as b = maybe as (\ (a, b') -> unfoldr' (as |> a) b') (f b)---- | @'unfoldl' f x@ is equivalent to @'reverse' ('unfoldr' ('fmap' swap . f) x)@.-unfoldl :: (b -> Maybe (b, a)) -> b -> Seq a-unfoldl f = unfoldl' empty- where unfoldl' as b = maybe as (\ (b', a) -> unfoldl' (a <| as) b') (f b)---- | /O(n)/. Constructs a sequence by repeated application of a function--- to a seed value.------ > iterateN n f x = fromList (Prelude.take n (Prelude.iterate f x))-iterateN :: Int -> (a -> a) -> a -> Seq a-iterateN n f x- | n >= 0 = replicateA n (State (\ y -> (f y, y))) `execState` x- | otherwise = error "iterateN takes a nonnegative integer argument"----------------------------------------------------------------------------- Deconstruction----------------------------------------------------------------------------- | /O(1)/. Is this the empty sequence?-null :: Seq a -> Bool-null (Seq Empty) = True-null _ = False---- | /O(1)/. The number of elements in the sequence.-length :: Seq a -> Int-length (Seq xs) = size xs---- Views--data Maybe2 a b = Nothing2 | Just2 a b---- | View of the left end of a sequence.-data ViewL a- = EmptyL -- ^ empty sequence- | a :< Seq a -- ^ leftmost element and the rest of the sequence-#if __GLASGOW_HASKELL__- deriving (Eq, Ord, Show, Read, Data)-#else- deriving (Eq, Ord, Show, Read)-#endif--INSTANCE_TYPEABLE1(ViewL,viewLTc,"ViewL")--instance Functor ViewL where- {-# INLINE fmap #-}- fmap _ EmptyL = EmptyL- fmap f (x :< xs) = f x :< fmap f xs--instance Foldable ViewL where- foldr _ z EmptyL = z- foldr f z (x :< xs) = f x (foldr f z xs)-- foldl _ z EmptyL = z- foldl f z (x :< xs) = foldl f (f z x) xs-- foldl1 _ EmptyL = error "foldl1: empty view"- foldl1 f (x :< xs) = foldl f x xs--instance Traversable ViewL where- traverse _ EmptyL = pure EmptyL- traverse f (x :< xs) = (:<) <$> f x <*> traverse f xs---- | /O(1)/. Analyse the left end of a sequence.-viewl :: Seq a -> ViewL a-viewl (Seq xs) = case viewLTree xs of- Nothing2 -> EmptyL- Just2 (Elem x) xs' -> x :< Seq xs'--{-# SPECIALIZE viewLTree :: FingerTree (Elem a) -> Maybe2 (Elem a) (FingerTree (Elem a)) #-}-{-# SPECIALIZE viewLTree :: FingerTree (Node a) -> Maybe2 (Node a) (FingerTree (Node a)) #-}-viewLTree :: Sized a => FingerTree a -> Maybe2 a (FingerTree a)-viewLTree Empty = Nothing2-viewLTree (Single a) = Just2 a Empty-viewLTree (Deep s (One a) m sf) = Just2 a (pullL (s - size a) m sf)-viewLTree (Deep s (Two a b) m sf) =- Just2 a (Deep (s - size a) (One b) m sf)-viewLTree (Deep s (Three a b c) m sf) =- Just2 a (Deep (s - size a) (Two b c) m sf)-viewLTree (Deep s (Four a b c d) m sf) =- Just2 a (Deep (s - size a) (Three b c d) m sf)---- | View of the right end of a sequence.-data ViewR a- = EmptyR -- ^ empty sequence- | Seq a :> a -- ^ the sequence minus the rightmost element,- -- and the rightmost element-#if __GLASGOW_HASKELL__- deriving (Eq, Ord, Show, Read, Data)-#else- deriving (Eq, Ord, Show, Read)-#endif--INSTANCE_TYPEABLE1(ViewR,viewRTc,"ViewR")--instance Functor ViewR where- {-# INLINE fmap #-}- fmap _ EmptyR = EmptyR- fmap f (xs :> x) = fmap f xs :> f x--instance Foldable ViewR where- foldr _ z EmptyR = z- foldr f z (xs :> x) = foldr f (f x z) xs-- foldl _ z EmptyR = z- foldl f z (xs :> x) = foldl f z xs `f` x-- foldr1 _ EmptyR = error "foldr1: empty view"- foldr1 f (xs :> x) = foldr f x xs--instance Traversable ViewR where- traverse _ EmptyR = pure EmptyR- traverse f (xs :> x) = (:>) <$> traverse f xs <*> f x---- | /O(1)/. Analyse the right end of a sequence.-viewr :: Seq a -> ViewR a-viewr (Seq xs) = case viewRTree xs of- Nothing2 -> EmptyR- Just2 xs' (Elem x) -> Seq xs' :> x--{-# SPECIALIZE viewRTree :: FingerTree (Elem a) -> Maybe2 (FingerTree (Elem a)) (Elem a) #-}-{-# SPECIALIZE viewRTree :: FingerTree (Node a) -> Maybe2 (FingerTree (Node a)) (Node a) #-}-viewRTree :: Sized a => FingerTree a -> Maybe2 (FingerTree a) a-viewRTree Empty = Nothing2-viewRTree (Single z) = Just2 Empty z-viewRTree (Deep s pr m (One z)) = Just2 (pullR (s - size z) pr m) z-viewRTree (Deep s pr m (Two y z)) =- Just2 (Deep (s - size z) pr m (One y)) z-viewRTree (Deep s pr m (Three x y z)) =- Just2 (Deep (s - size z) pr m (Two x y)) z-viewRTree (Deep s pr m (Four w x y z)) =- Just2 (Deep (s - size z) pr m (Three w x y)) z----------------------------------------------------------------------------- Scans------ These are not particularly complex applications of the Traversable--- functor, though making the correspondence with Data.List exact--- requires the use of (<|) and (|>).------ Note that save for the single (<|) or (|>), we maintain the original--- structure of the Seq, not having to do any restructuring of our own.------ wasserman.louis@gmail.com, 5/23/09----------------------------------------------------------------------------- | 'scanl' is similar to 'foldl', but returns a sequence of reduced--- values from the left:------ > scanl f z (fromList [x1, x2, ...]) = fromList [z, z `f` x1, (z `f` x1) `f` x2, ...]-scanl :: (a -> b -> a) -> a -> Seq b -> Seq a-scanl f z0 xs = z0 <| snd (mapAccumL (\ x z -> let x' = f x z in (x', x')) z0 xs)---- | 'scanl1' is a variant of 'scanl' that has no starting value argument:------ > scanl1 f (fromList [x1, x2, ...]) = fromList [x1, x1 `f` x2, ...]-scanl1 :: (a -> a -> a) -> Seq a -> Seq a-scanl1 f xs = case viewl xs of- EmptyL -> error "scanl1 takes a nonempty sequence as an argument"- x :< xs' -> scanl f x xs'---- | 'scanr' is the right-to-left dual of 'scanl'.-scanr :: (a -> b -> b) -> b -> Seq a -> Seq b-scanr f z0 xs = snd (mapAccumR (\ z x -> let z' = f x z in (z', z')) z0 xs) |> z0---- | 'scanr1' is a variant of 'scanr' that has no starting value argument.-scanr1 :: (a -> a -> a) -> Seq a -> Seq a-scanr1 f xs = case viewr xs of- EmptyR -> error "scanr1 takes a nonempty sequence as an argument"- xs' :> x -> scanr f x xs'---- Indexing---- | /O(log(min(i,n-i)))/. The element at the specified position,--- counting from 0. The argument should thus be a non-negative--- integer less than the size of the sequence.--- If the position is out of range, 'index' fails with an error.-index :: Seq a -> Int -> a-index (Seq xs) i- | 0 <= i && i < size xs = case lookupTree i xs of- Place _ (Elem x) -> x- | otherwise = error "index out of bounds"--data Place a = Place {-# UNPACK #-} !Int a-#if TESTING- deriving Show-#endif--{-# SPECIALIZE lookupTree :: Int -> FingerTree (Elem a) -> Place (Elem a) #-}-{-# SPECIALIZE lookupTree :: Int -> FingerTree (Node a) -> Place (Node a) #-}-lookupTree :: Sized a => Int -> FingerTree a -> Place a-lookupTree _ Empty = error "lookupTree of empty tree"-lookupTree i (Single x) = Place i x-lookupTree i (Deep _ pr m sf)- | i < spr = lookupDigit i pr- | i < spm = case lookupTree (i - spr) m of- Place i' xs -> lookupNode i' xs- | otherwise = lookupDigit (i - spm) sf- where- spr = size pr- spm = spr + size m--{-# SPECIALIZE lookupNode :: Int -> Node (Elem a) -> Place (Elem a) #-}-{-# SPECIALIZE lookupNode :: Int -> Node (Node a) -> Place (Node a) #-}-lookupNode :: Sized a => Int -> Node a -> Place a-lookupNode i (Node2 _ a b)- | i < sa = Place i a- | otherwise = Place (i - sa) b- where- sa = size a-lookupNode i (Node3 _ a b c)- | i < sa = Place i a- | i < sab = Place (i - sa) b- | otherwise = Place (i - sab) c- where- sa = size a- sab = sa + size b--{-# SPECIALIZE lookupDigit :: Int -> Digit (Elem a) -> Place (Elem a) #-}-{-# SPECIALIZE lookupDigit :: Int -> Digit (Node a) -> Place (Node a) #-}-lookupDigit :: Sized a => Int -> Digit a -> Place a-lookupDigit i (One a) = Place i a-lookupDigit i (Two a b)- | i < sa = Place i a- | otherwise = Place (i - sa) b- where- sa = size a-lookupDigit i (Three a b c)- | i < sa = Place i a- | i < sab = Place (i - sa) b- | otherwise = Place (i - sab) c- where- sa = size a- sab = sa + size b-lookupDigit i (Four a b c d)- | i < sa = Place i a- | i < sab = Place (i - sa) b- | i < sabc = Place (i - sab) c- | otherwise = Place (i - sabc) d- where- sa = size a- sab = sa + size b- sabc = sab + size c---- | /O(log(min(i,n-i)))/. Replace the element at the specified position.--- If the position is out of range, the original sequence is returned.-update :: Int -> a -> Seq a -> Seq a-update i x = adjust (const x) i---- | /O(log(min(i,n-i)))/. Update the element at the specified position.--- If the position is out of range, the original sequence is returned.-adjust :: (a -> a) -> Int -> Seq a -> Seq a-adjust f i (Seq xs)- | 0 <= i && i < size xs = Seq (adjustTree (const (fmap f)) i xs)- | otherwise = Seq xs--{-# SPECIALIZE adjustTree :: (Int -> Elem a -> Elem a) -> Int -> FingerTree (Elem a) -> FingerTree (Elem a) #-}-{-# SPECIALIZE adjustTree :: (Int -> Node a -> Node a) -> Int -> FingerTree (Node a) -> FingerTree (Node a) #-}-adjustTree :: Sized a => (Int -> a -> a) ->- Int -> FingerTree a -> FingerTree a-adjustTree _ _ Empty = error "adjustTree of empty tree"-adjustTree f i (Single x) = Single (f i x)-adjustTree f i (Deep s pr m sf)- | i < spr = Deep s (adjustDigit f i pr) m sf- | i < spm = Deep s pr (adjustTree (adjustNode f) (i - spr) m) sf- | otherwise = Deep s pr m (adjustDigit f (i - spm) sf)- where- spr = size pr- spm = spr + size m--{-# SPECIALIZE adjustNode :: (Int -> Elem a -> Elem a) -> Int -> Node (Elem a) -> Node (Elem a) #-}-{-# SPECIALIZE adjustNode :: (Int -> Node a -> Node a) -> Int -> Node (Node a) -> Node (Node a) #-}-adjustNode :: Sized a => (Int -> a -> a) -> Int -> Node a -> Node a-adjustNode f i (Node2 s a b)- | i < sa = Node2 s (f i a) b- | otherwise = Node2 s a (f (i - sa) b)- where- sa = size a-adjustNode f i (Node3 s a b c)- | i < sa = Node3 s (f i a) b c- | i < sab = Node3 s a (f (i - sa) b) c- | otherwise = Node3 s a b (f (i - sab) c)- where- sa = size a- sab = sa + size b--{-# SPECIALIZE adjustDigit :: (Int -> Elem a -> Elem a) -> Int -> Digit (Elem a) -> Digit (Elem a) #-}-{-# SPECIALIZE adjustDigit :: (Int -> Node a -> Node a) -> Int -> Digit (Node a) -> Digit (Node a) #-}-adjustDigit :: Sized a => (Int -> a -> a) -> Int -> Digit a -> Digit a-adjustDigit f i (One a) = One (f i a)-adjustDigit f i (Two a b)- | i < sa = Two (f i a) b- | otherwise = Two a (f (i - sa) b)- where- sa = size a-adjustDigit f i (Three a b c)- | i < sa = Three (f i a) b c- | i < sab = Three a (f (i - sa) b) c- | otherwise = Three a b (f (i - sab) c)- where- sa = size a- sab = sa + size b-adjustDigit f i (Four a b c d)- | i < sa = Four (f i a) b c d- | i < sab = Four a (f (i - sa) b) c d- | i < sabc = Four a b (f (i - sab) c) d- | otherwise = Four a b c (f (i- sabc) d)- where- sa = size a- sab = sa + size b- sabc = sab + size c---- | A generalization of 'fmap', 'mapWithIndex' takes a mapping function--- that also depends on the element's index, and applies it to every--- element in the sequence.-mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b-mapWithIndex f xs = snd (mapAccumL' (\ i x -> (i + 1, f i x)) 0 xs)---- Splitting---- | /O(log(min(i,n-i)))/. The first @i@ elements of a sequence.--- If @i@ is negative, @'take' i s@ yields the empty sequence.--- If the sequence contains fewer than @i@ elements, the whole sequence--- is returned.-take :: Int -> Seq a -> Seq a-take i = fst . splitAt i---- | /O(log(min(i,n-i)))/. Elements of a sequence after the first @i@.--- If @i@ is negative, @'drop' i s@ yields the whole sequence.--- If the sequence contains fewer than @i@ elements, the empty sequence--- is returned.-drop :: Int -> Seq a -> Seq a-drop i = snd . splitAt i---- | /O(log(min(i,n-i)))/. Split a sequence at a given position.--- @'splitAt' i s = ('take' i s, 'drop' i s)@.-splitAt :: Int -> Seq a -> (Seq a, Seq a)-splitAt i (Seq xs) = (Seq l, Seq r)- where (l, r) = split i xs--split :: Int -> FingerTree (Elem a) ->- (FingerTree (Elem a), FingerTree (Elem a))-split i Empty = i `seq` (Empty, Empty)-split i xs- | size xs > i = (l, consTree x r)- | otherwise = (xs, Empty)- where Split l x r = splitTree i xs--data Split t a = Split t a t-#if TESTING- deriving Show-#endif--{-# SPECIALIZE splitTree :: Int -> FingerTree (Elem a) -> Split (FingerTree (Elem a)) (Elem a) #-}-{-# SPECIALIZE splitTree :: Int -> FingerTree (Node a) -> Split (FingerTree (Node a)) (Node a) #-}-splitTree :: Sized a => Int -> FingerTree a -> Split (FingerTree a) a-splitTree _ Empty = error "splitTree of empty tree"-splitTree i (Single x) = i `seq` Split Empty x Empty-splitTree i (Deep _ pr m sf)- | i < spr = case splitDigit i pr of- Split l x r -> Split (maybe Empty digitToTree l) x (deepL r m sf)- | i < spm = case splitTree im m of- Split ml xs mr -> case splitNode (im - size ml) xs of- Split l x r -> Split (deepR pr ml l) x (deepL r mr sf)- | otherwise = case splitDigit (i - spm) sf of- Split l x r -> Split (deepR pr m l) x (maybe Empty digitToTree r)- where- spr = size pr- spm = spr + size m- im = i - spr--{-# SPECIALIZE splitNode :: Int -> Node (Elem a) -> Split (Maybe (Digit (Elem a))) (Elem a) #-}-{-# SPECIALIZE splitNode :: Int -> Node (Node a) -> Split (Maybe (Digit (Node a))) (Node a) #-}-splitNode :: Sized a => Int -> Node a -> Split (Maybe (Digit a)) a-splitNode i (Node2 _ a b)- | i < sa = Split Nothing a (Just (One b))- | otherwise = Split (Just (One a)) b Nothing- where- sa = size a-splitNode i (Node3 _ a b c)- | i < sa = Split Nothing a (Just (Two b c))- | i < sab = Split (Just (One a)) b (Just (One c))- | otherwise = Split (Just (Two a b)) c Nothing- where- sa = size a- sab = sa + size b--{-# SPECIALIZE splitDigit :: Int -> Digit (Elem a) -> Split (Maybe (Digit (Elem a))) (Elem a) #-}-{-# SPECIALIZE splitDigit :: Int -> Digit (Node a) -> Split (Maybe (Digit (Node a))) (Node a) #-}-splitDigit :: Sized a => Int -> Digit a -> Split (Maybe (Digit a)) a-splitDigit i (One a) = i `seq` Split Nothing a Nothing-splitDigit i (Two a b)- | i < sa = Split Nothing a (Just (One b))- | otherwise = Split (Just (One a)) b Nothing- where- sa = size a-splitDigit i (Three a b c)- | i < sa = Split Nothing a (Just (Two b c))- | i < sab = Split (Just (One a)) b (Just (One c))- | otherwise = Split (Just (Two a b)) c Nothing- where- sa = size a- sab = sa + size b-splitDigit i (Four a b c d)- | i < sa = Split Nothing a (Just (Three b c d))- | i < sab = Split (Just (One a)) b (Just (Two c d))- | i < sabc = Split (Just (Two a b)) c (Just (One d))- | otherwise = Split (Just (Three a b c)) d Nothing- where- sa = size a- sab = sa + size b- sabc = sab + size c---- | /O(n)/. Returns a sequence of all suffixes of this sequence,--- longest first. For example,------ > tails (fromList "abc") = fromList [fromList "abc", fromList "bc", fromList "c", fromList ""]------ Evaluating the /i/th suffix takes /O(log(min(i, n-i)))/, but evaluating--- every suffix in the sequence takes /O(n)/ due to sharing.-tails :: Seq a -> Seq (Seq a)-tails (Seq xs) = Seq (tailsTree (Elem . Seq) xs) |> empty---- | /O(n)/. Returns a sequence of all prefixes of this sequence,--- shortest first. For example,------ > inits (fromList "abc") = fromList [fromList "", fromList "a", fromList "ab", fromList "abc"]------ Evaluating the /i/th prefix takes /O(log(min(i, n-i)))/, but evaluating--- every prefix in the sequence takes /O(n)/ due to sharing.-inits :: Seq a -> Seq (Seq a)-inits (Seq xs) = empty <| Seq (initsTree (Elem . Seq) xs)---- This implementation of tails (and, analogously, inits) has the--- following algorithmic advantages:--- Evaluating each tail in the sequence takes linear total time,--- which is better than we could say for--- @fromList [drop n xs | n <- [0..length xs]]@.--- Evaluating any individual tail takes logarithmic time, which is--- better than we can say for either--- @scanr (<|) empty xs@ or @iterateN (length xs + 1) (\ xs -> let _ :< xs' = viewl xs in xs') xs@.------ Moreover, if we actually look at every tail in the sequence, the--- following benchmarks demonstrate that this implementation is modestly--- faster than any of the above:------ Times (ms)--- min mean +/-sd median max--- Seq.tails: 21.986 24.961 10.169 22.417 86.485--- scanr: 85.392 87.942 2.488 87.425 100.217--- iterateN: 29.952 31.245 1.574 30.412 37.268------ The algorithm for tails (and, analogously, inits) is as follows:------ A Node in the FingerTree of tails is constructed by evaluating the--- corresponding tail of the FingerTree of Nodes, considering the first--- Node in this tail, and constructing a Node in which each tail of this--- Node is made to be the prefix of the remaining tree. This ends up--- working quite elegantly, as the remainder of the tail of the FingerTree--- of Nodes becomes the middle of a new tail, the suffix of the Node is--- the prefix, and the suffix of the original tree is retained.------ In particular, evaluating the /i/th tail involves making as--- many partial evaluations as the Node depth of the /i/th element.--- In addition, when we evaluate the /i/th tail, and we also evaluate--- the /j/th tail, and /m/ Nodes are on the path to both /i/ and /j/,--- each of those /m/ evaluations are shared between the computation of--- the /i/th and /j/th tails.------ wasserman.louis@gmail.com, 7/16/09--tailsDigit :: Digit a -> Digit (Digit a)-tailsDigit (One a) = One (One a)-tailsDigit (Two a b) = Two (Two a b) (One b)-tailsDigit (Three a b c) = Three (Three a b c) (Two b c) (One c)-tailsDigit (Four a b c d) = Four (Four a b c d) (Three b c d) (Two c d) (One d)--initsDigit :: Digit a -> Digit (Digit a)-initsDigit (One a) = One (One a)-initsDigit (Two a b) = Two (One a) (Two a b)-initsDigit (Three a b c) = Three (One a) (Two a b) (Three a b c)-initsDigit (Four a b c d) = Four (One a) (Two a b) (Three a b c) (Four a b c d)--tailsNode :: Node a -> Node (Digit a)-tailsNode (Node2 s a b) = Node2 s (Two a b) (One b)-tailsNode (Node3 s a b c) = Node3 s (Three a b c) (Two b c) (One c)--initsNode :: Node a -> Node (Digit a)-initsNode (Node2 s a b) = Node2 s (One a) (Two a b)-initsNode (Node3 s a b c) = Node3 s (One a) (Two a b) (Three a b c)--{-# SPECIALIZE tailsTree :: (FingerTree (Elem a) -> Elem b) -> FingerTree (Elem a) -> FingerTree (Elem b) #-}-{-# SPECIALIZE tailsTree :: (FingerTree (Node a) -> Node b) -> FingerTree (Node a) -> FingerTree (Node b) #-}--- | Given a function to apply to tails of a tree, applies that function--- to every tail of the specified tree.-tailsTree :: (Sized a, Sized b) => (FingerTree a -> b) -> FingerTree a -> FingerTree b-tailsTree _ Empty = Empty-tailsTree f (Single x) = Single (f (Single x))-tailsTree f (Deep n pr m sf) =- Deep n (fmap (\ pr' -> f (deep pr' m sf)) (tailsDigit pr))- (tailsTree f' m)- (fmap (f . digitToTree) (tailsDigit sf))- where- f' ms = let Just2 node m' = viewLTree ms in- fmap (\ pr' -> f (deep pr' m' sf)) (tailsNode node)--{-# SPECIALIZE initsTree :: (FingerTree (Elem a) -> Elem b) -> FingerTree (Elem a) -> FingerTree (Elem b) #-}-{-# SPECIALIZE initsTree :: (FingerTree (Node a) -> Node b) -> FingerTree (Node a) -> FingerTree (Node b) #-}--- | Given a function to apply to inits of a tree, applies that function--- to every init of the specified tree.-initsTree :: (Sized a, Sized b) => (FingerTree a -> b) -> FingerTree a -> FingerTree b-initsTree _ Empty = Empty-initsTree f (Single x) = Single (f (Single x))-initsTree f (Deep n pr m sf) =- Deep n (fmap (f . digitToTree) (initsDigit pr))- (initsTree f' m)- (fmap (f . deep pr m) (initsDigit sf))- where- f' ms = let Just2 m' node = viewRTree ms in- fmap (\ sf' -> f (deep pr m' sf')) (initsNode node)--{-# INLINE foldlWithIndex #-}--- | 'foldlWithIndex' is a version of 'foldl' that also provides access--- to the index of each element.-foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b-foldlWithIndex f z xs = foldl (\ g x i -> i `seq` f (g (i - 1)) i x) (const z) xs (length xs - 1)--{-# INLINE foldrWithIndex #-}--- | 'foldrWithIndex' is a version of 'foldr' that also provides access--- to the index of each element.-foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b-foldrWithIndex f z xs = foldr (\ x g i -> i `seq` f i x (g (i+1))) (const z) xs 0--{-# INLINE listToMaybe' #-}--- 'listToMaybe\'' is a good consumer version of 'listToMaybe'.-listToMaybe' :: [a] -> Maybe a-listToMaybe' = foldr (\ x _ -> Just x) Nothing---- | /O(i)/ where /i/ is the prefix length. 'takeWhileL', applied--- to a predicate @p@ and a sequence @xs@, returns the longest prefix--- (possibly empty) of @xs@ of elements that satisfy @p@.-takeWhileL :: (a -> Bool) -> Seq a -> Seq a-takeWhileL p = fst . spanl p---- | /O(i)/ where /i/ is the suffix length. 'takeWhileR', applied--- to a predicate @p@ and a sequence @xs@, returns the longest suffix--- (possibly empty) of @xs@ of elements that satisfy @p@.------ @'takeWhileR' p xs@ is equivalent to @'reverse' ('takeWhileL' p ('reverse' xs))@.-takeWhileR :: (a -> Bool) -> Seq a -> Seq a-takeWhileR p = fst . spanr p---- | /O(i)/ where /i/ is the prefix length. @'dropWhileL' p xs@ returns--- the suffix remaining after @'takeWhileL' p xs@.-dropWhileL :: (a -> Bool) -> Seq a -> Seq a-dropWhileL p = snd . spanl p---- | /O(i)/ where /i/ is the suffix length. @'dropWhileR' p xs@ returns--- the prefix remaining after @'takeWhileR' p xs@.------ @'dropWhileR' p xs@ is equivalent to @'reverse' ('dropWhileL' p ('reverse' xs))@.-dropWhileR :: (a -> Bool) -> Seq a -> Seq a-dropWhileR p = snd . spanr p---- | /O(i)/ where /i/ is the prefix length. 'spanl', applied to--- a predicate @p@ and a sequence @xs@, returns a pair whose first--- element is the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@ and the second element is the remainder of the sequence.-spanl :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-spanl p = breakl (not . p)---- | /O(i)/ where /i/ is the suffix length. 'spanr', applied to a--- predicate @p@ and a sequence @xs@, returns a pair whose /first/ element--- is the longest /suffix/ (possibly empty) of @xs@ of elements that--- satisfy @p@ and the second element is the remainder of the sequence.-spanr :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-spanr p = breakr (not . p)--{-# INLINE breakl #-}--- | /O(i)/ where /i/ is the breakpoint index. 'breakl', applied to a--- predicate @p@ and a sequence @xs@, returns a pair whose first element--- is the longest prefix (possibly empty) of @xs@ of elements that--- /do not satisfy/ @p@ and the second element is the remainder of--- the sequence.------ @'breakl' p@ is equivalent to @'spanl' (not . p)@.-breakl :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-breakl p xs = foldr (\ i _ -> splitAt i xs) (xs, empty) (findIndicesL p xs)--{-# INLINE breakr #-}--- | @'breakr' p@ is equivalent to @'spanr' (not . p)@.-breakr :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-breakr p xs = foldr (\ i _ -> flipPair (splitAt (i + 1) xs)) (xs, empty) (findIndicesR p xs)- where flipPair (x, y) = (y, x)---- | /O(n)/. The 'partition' function takes a predicate @p@ and a--- sequence @xs@ and returns sequences of those elements which do and--- do not satisfy the predicate.-partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-partition p = foldl part (empty, empty)- where- part (xs, ys) x- | p x = (xs |> x, ys)- | otherwise = (xs, ys |> x)---- | /O(n)/. The 'filter' function takes a predicate @p@ and a sequence--- @xs@ and returns a sequence of those elements which satisfy the--- predicate.-filter :: (a -> Bool) -> Seq a -> Seq a-filter p = foldl (\ xs x -> if p x then xs |> x else xs) empty---- Indexing sequences---- | 'elemIndexL' finds the leftmost index of the specified element,--- if it is present, and otherwise 'Nothing'.-elemIndexL :: Eq a => a -> Seq a -> Maybe Int-elemIndexL x = findIndexL (x ==)---- | 'elemIndexR' finds the rightmost index of the specified element,--- if it is present, and otherwise 'Nothing'.-elemIndexR :: Eq a => a -> Seq a -> Maybe Int-elemIndexR x = findIndexR (x ==)---- | 'elemIndicesL' finds the indices of the specified element, from--- left to right (i.e. in ascending order).-elemIndicesL :: Eq a => a -> Seq a -> [Int]-elemIndicesL x = findIndicesL (x ==)---- | 'elemIndicesR' finds the indices of the specified element, from--- right to left (i.e. in descending order).-elemIndicesR :: Eq a => a -> Seq a -> [Int]-elemIndicesR x = findIndicesR (x ==)---- | @'findIndexL' p xs@ finds the index of the leftmost element that--- satisfies @p@, if any exist.-findIndexL :: (a -> Bool) -> Seq a -> Maybe Int-findIndexL p = listToMaybe' . findIndicesL p---- | @'findIndexR' p xs@ finds the index of the rightmost element that--- satisfies @p@, if any exist.-findIndexR :: (a -> Bool) -> Seq a -> Maybe Int-findIndexR p = listToMaybe' . findIndicesR p--{-# INLINE findIndicesL #-}--- | @'findIndicesL' p@ finds all indices of elements that satisfy @p@,--- in ascending order.-findIndicesL :: (a -> Bool) -> Seq a -> [Int]-#if __GLASGOW_HASKELL__-findIndicesL p xs = build (\ c n -> let g i x z = if p x then c i z else z in- foldrWithIndex g n xs)-#else-findIndicesL p xs = foldrWithIndex g [] xs- where g i x is = if p x then i:is else is-#endif--{-# INLINE findIndicesR #-}--- | @'findIndicesR' p@ finds all indices of elements that satisfy @p@,--- in descending order.-findIndicesR :: (a -> Bool) -> Seq a -> [Int]-#if __GLASGOW_HASKELL__-findIndicesR p xs = build (\ c n ->- let g z i x = if p x then c i z else z in foldlWithIndex g n xs)-#else-findIndicesR p xs = foldlWithIndex g [] xs- where g is i x = if p x then i:is else is-#endif----------------------------------------------------------------------------- Lists----------------------------------------------------------------------------- | /O(n)/. Create a sequence from a finite list of elements.--- There is a function 'toList' in the opposite direction for all--- instances of the 'Foldable' class, including 'Seq'.-fromList :: [a] -> Seq a-fromList = Data.List.foldl' (|>) empty----------------------------------------------------------------------------- Reverse----------------------------------------------------------------------------- | /O(n)/. The reverse of a sequence.-reverse :: Seq a -> Seq a-reverse (Seq xs) = Seq (reverseTree id xs)--reverseTree :: (a -> a) -> FingerTree a -> FingerTree a-reverseTree _ Empty = Empty-reverseTree f (Single x) = Single (f x)-reverseTree f (Deep s pr m sf) =- Deep s (reverseDigit f sf)- (reverseTree (reverseNode f) m)- (reverseDigit f pr)--{-# INLINE reverseDigit #-}-reverseDigit :: (a -> a) -> Digit a -> Digit a-reverseDigit f (One a) = One (f a)-reverseDigit f (Two a b) = Two (f b) (f a)-reverseDigit f (Three a b c) = Three (f c) (f b) (f a)-reverseDigit f (Four a b c d) = Four (f d) (f c) (f b) (f a)--reverseNode :: (a -> a) -> Node a -> Node a-reverseNode f (Node2 s a b) = Node2 s (f b) (f a)-reverseNode f (Node3 s a b c) = Node3 s (f c) (f b) (f a)----------------------------------------------------------------------------- Zipping----------------------------------------------------------------------------- | /O(min(n1,n2))/. 'zip' takes two sequences and returns a sequence--- of corresponding pairs. If one input is short, excess elements are--- discarded from the right end of the longer sequence.-zip :: Seq a -> Seq b -> Seq (a, b)-zip = zipWith (,)---- | /O(min(n1,n2))/. 'zipWith' generalizes 'zip' by zipping with the--- function given as the first argument, instead of a tupling function.--- For example, @zipWith (+)@ is applied to two sequences to take the--- sequence of corresponding sums.-zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c-zipWith f xs ys- | length xs <= length ys = zipWith' f xs ys- | otherwise = zipWith' (flip f) ys xs---- like 'zipWith', but assumes length xs <= length ys-zipWith' :: (a -> b -> c) -> Seq a -> Seq b -> Seq c-zipWith' f xs ys = snd (mapAccumL k ys xs)- where- k kys x = case viewl kys of- (z :< zs) -> (zs, f x z)- EmptyL -> error "zipWith': unexpected EmptyL"---- | /O(min(n1,n2,n3))/. 'zip3' takes three sequences and returns a--- sequence of triples, analogous to 'zip'.-zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)-zip3 = zipWith3 (,,)---- | /O(min(n1,n2,n3))/. 'zipWith3' takes a function which combines--- three elements, as well as three sequences and returns a sequence of--- their point-wise combinations, analogous to 'zipWith'.-zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d-zipWith3 f s1 s2 s3 = zipWith ($) (zipWith f s1 s2) s3---- | /O(min(n1,n2,n3,n4))/. 'zip4' takes four sequences and returns a--- sequence of quadruples, analogous to 'zip'.-zip4 :: Seq a -> Seq b -> Seq c -> Seq d -> Seq (a,b,c,d)-zip4 = zipWith4 (,,,)---- | /O(min(n1,n2,n3,n4))/. 'zipWith4' takes a function which combines--- four elements, as well as four sequences and returns a sequence of--- their point-wise combinations, analogous to 'zipWith'.-zipWith4 :: (a -> b -> c -> d -> e) -> Seq a -> Seq b -> Seq c -> Seq d -> Seq e-zipWith4 f s1 s2 s3 s4 = zipWith ($) (zipWith ($) (zipWith f s1 s2) s3) s4----------------------------------------------------------------------------- Sorting------ sort and sortBy are implemented by simple deforestations of--- \ xs -> fromList2 (length xs) . Data.List.sortBy cmp . toList--- which does not get deforested automatically, it would appear.------ Unstable sorting is performed by a heap sort implementation based on--- pairing heaps. Because the internal structure of sequences is quite--- varied, it is difficult to get blocks of elements of roughly the same--- length, which would improve merge sort performance. Pairing heaps,--- on the other hand, are relatively resistant to the effects of merging--- heaps of wildly different sizes, as guaranteed by its amortized--- constant-time merge operation. Moreover, extensive use of SpecConstr--- transformations can be done on pairing heaps, especially when we're--- only constructing them to immediately be unrolled.------ On purely random sequences of length 50000, with no RTS options,--- I get the following statistics, in which heapsort is about 42.5%--- faster: (all comparisons done with -O2)------ Times (ms) min mean +/-sd median max--- to/from list: 103.802 108.572 7.487 106.436 143.339--- unstable heapsort: 60.686 62.968 4.275 61.187 79.151------ Heapsort, it would seem, is less of a memory hog than Data.List.sortBy.--- The gap is narrowed when more memory is available, but heapsort still--- wins, 15% faster, with +RTS -H128m:------ Times (ms) min mean +/-sd median max--- to/from list: 42.692 45.074 2.596 44.600 56.601--- unstable heapsort: 37.100 38.344 3.043 37.715 55.526------ In addition, on strictly increasing sequences the gap is even wider--- than normal; heapsort is 68.5% faster with no RTS options:--- Times (ms) min mean +/-sd median max--- to/from list: 52.236 53.574 1.987 53.034 62.098--- unstable heapsort: 16.433 16.919 0.931 16.681 21.622------ This may be attributed to the elegant nature of the pairing heap.------ wasserman.louis@gmail.com, 7/20/09----------------------------------------------------------------------------- | /O(n log n)/. 'sort' sorts the specified 'Seq' by the natural--- ordering of its elements. The sort is stable.--- If stability is not required, 'unstableSort' can be considerably--- faster, and in particular uses less memory.-sort :: Ord a => Seq a -> Seq a-sort = sortBy compare---- | /O(n log n)/. 'sortBy' sorts the specified 'Seq' according to the--- specified comparator. The sort is stable.--- If stability is not required, 'unstableSortBy' can be considerably--- faster, and in particular uses less memory.-sortBy :: (a -> a -> Ordering) -> Seq a -> Seq a-sortBy cmp xs = fromList2 (length xs) (Data.List.sortBy cmp (toList xs))---- | /O(n log n)/. 'unstableSort' sorts the specified 'Seq' by--- the natural ordering of its elements, but the sort is not stable.--- This algorithm is frequently faster and uses less memory than 'sort',--- and performs extremely well -- frequently twice as fast as 'sort' ----- when the sequence is already nearly sorted.-unstableSort :: Ord a => Seq a -> Seq a-unstableSort = unstableSortBy compare---- | /O(n log n)/. A generalization of 'unstableSort', 'unstableSortBy'--- takes an arbitrary comparator and sorts the specified sequence.--- The sort is not stable. This algorithm is frequently faster and--- uses less memory than 'sortBy', and performs extremely well ----- frequently twice as fast as 'sortBy' -- when the sequence is already--- nearly sorted.-unstableSortBy :: (a -> a -> Ordering) -> Seq a -> Seq a-unstableSortBy cmp (Seq xs) =- fromList2 (size xs) $ maybe [] (unrollPQ cmp) $- toPQ cmp (\ (Elem x) -> PQueue x Nil) xs---- | fromList2, given a list and its length, constructs a completely--- balanced Seq whose elements are that list using the applicativeTree--- generalization.-fromList2 :: Int -> [a] -> Seq a-fromList2 n = execState (replicateA n (State ht))- where- ht (x:xs) = (xs, x)- ht [] = error "fromList2: short list"---- | A 'PQueue' is a simple pairing heap.-data PQueue e = PQueue e (PQL e)-data PQL e = Nil | {-# UNPACK #-} !(PQueue e) :& PQL e--infixr 8 :&--#if TESTING--instance Functor PQueue where- fmap f (PQueue x ts) = PQueue (f x) (fmap f ts)--instance Functor PQL where- fmap f (q :& qs) = fmap f q :& fmap f qs- fmap _ Nil = Nil--instance Show e => Show (PQueue e) where- show = unlines . draw . fmap show---- borrowed wholesale from Data.Tree, as Data.Tree actually depends--- on Data.Sequence-draw :: PQueue String -> [String]-draw (PQueue x ts0) = x : drawSubTrees ts0- where- drawSubTrees Nil = []- drawSubTrees (t :& Nil) =- "|" : shift "`- " " " (draw t)- drawSubTrees (t :& ts) =- "|" : shift "+- " "| " (draw t) ++ drawSubTrees ts-- shift first other = Data.List.zipWith (++) (first : repeat other)-#endif---- | 'unrollPQ', given a comparator function, unrolls a 'PQueue' into--- a sorted list.-unrollPQ :: (e -> e -> Ordering) -> PQueue e -> [e]-unrollPQ cmp = unrollPQ'- where- {-# INLINE unrollPQ' #-}- unrollPQ' (PQueue x ts) = x:mergePQs0 ts- (<>) = mergePQ cmp- mergePQs0 Nil = []- mergePQs0 (t :& Nil) = unrollPQ' t- mergePQs0 (t1 :& t2 :& ts) = mergePQs (t1 <> t2) ts- mergePQs t ts = t `seq` case ts of- Nil -> unrollPQ' t- t1 :& Nil -> unrollPQ' (t <> t1)- t1 :& t2 :& ts' -> mergePQs (t <> (t1 <> t2)) ts'---- | 'toPQ', given an ordering function and a mechanism for queueifying--- elements, converts a 'FingerTree' to a 'PQueue'.-toPQ :: (e -> e -> Ordering) -> (a -> PQueue e) -> FingerTree a -> Maybe (PQueue e)-toPQ _ _ Empty = Nothing-toPQ _ f (Single x) = Just (f x)-toPQ cmp f (Deep _ pr m sf) = Just (maybe (pr' <> sf') ((pr' <> sf') <>) (toPQ cmp fNode m))- where- fDigit digit = case fmap f digit of- One a -> a- Two a b -> a <> b- Three a b c -> a <> b <> c- Four a b c d -> (a <> b) <> (c <> d)- (<>) = mergePQ cmp- fNode = fDigit . nodeToDigit- pr' = fDigit pr- sf' = fDigit sf---- | 'mergePQ' merges two 'PQueue's.-mergePQ :: (a -> a -> Ordering) -> PQueue a -> PQueue a -> PQueue a-mergePQ cmp q1@(PQueue x1 ts1) q2@(PQueue x2 ts2)- | cmp x1 x2 == GT = PQueue x2 (q1 :& ts2)- | otherwise = PQueue x1 (q2 :& ts1)
@@ -1,144 +0,0 @@-{-# LANGUAGE CPP #-}-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Safe #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Set--- Copyright : (c) Daan Leijen 2002--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of sets.------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.Set (Set)--- > import qualified Data.Set as Set------ The implementation of 'Set' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'. Of course, left-biasing can only be observed--- when equality is an equivalence relation instead of structural--- equality.--------------------------------------------------------------------------------module Data.Set (- -- * Strictness properties- -- $strictness-- -- * Set type-#if !defined(TESTING)- Set -- instance Eq,Ord,Show,Read,Data,Typeable-#else- Set(..)-#endif-- -- * Operators- , (\\)-- -- * Query- , S.null- , size- , member- , notMember- , lookupLT- , lookupGT- , lookupLE- , lookupGE- , isSubsetOf- , isProperSubsetOf-- -- * Construction- , empty- , singleton- , insert- , delete-- -- * Combine- , union- , unions- , difference- , intersection-- -- * Filter- , S.filter- , partition- , split- , splitMember-- -- * Map- , S.map- , mapMonotonic-- -- * Folds- , S.foldr- , S.foldl- -- ** Strict folds- , foldr'- , foldl'- -- ** Legacy folds- , fold-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , maxView- , minView-- -- * Conversion-- -- ** List- , elems- , toList- , fromList-- -- ** Ordered list- , toAscList- , toDescList- , fromAscList- , fromDistinctAscList-- -- * Debugging- , showTree- , showTreeWith- , valid--#if defined(TESTING)- -- Internals (for testing)- , bin- , balanced- , join- , merge-#endif- ) where--import Data.Set.Base as S---- $strictness------ This module satisfies the following strictness property:------ * Key arguments are evaluated to WHNF------ Here are some examples that illustrate the property:------ > delete undefined s == undefined
@@ -1,1364 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Set.Base--- Copyright : (c) Daan Leijen 2002--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of sets.------ These modules are intended to be imported qualified, to avoid name--- clashes with Prelude functions, e.g.------ > import Data.Set (Set)--- > import qualified Data.Set as Set------ The implementation of 'Set' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'. Of course, left-biasing can only be observed--- when equality is an equivalence relation instead of structural--- equality.---------------------------------------------------------------------------------- [Note: Using INLINABLE]--- ~~~~~~~~~~~~~~~~~~~~~~~--- It is crucial to the performance that the functions specialize on the Ord--- type when possible. GHC 7.0 and higher does this by itself when it sees th--- unfolding of a function -- that is why all public functions are marked--- INLINABLE (that exposes the unfolding).----- [Note: Using INLINE]--- ~~~~~~~~~~~~~~~~~~~~--- For other compilers and GHC pre 7.0, we mark some of the functions INLINE.--- We mark the functions that just navigate down the tree (lookup, insert,--- delete and similar). That navigation code gets inlined and thus specialized--- when possible. There is a price to pay -- code growth. The code INLINED is--- therefore only the tree navigation, all the real work (rebalancing) is not--- INLINED by using a NOINLINE.------ All methods marked INLINE have to be nonrecursive -- a 'go' function doing--- the real work is provided.----- [Note: Type of local 'go' function]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- If the local 'go' function uses an Ord class, it sometimes heap-allocates--- the Ord dictionary when the 'go' function does not have explicit type.--- In that case we give 'go' explicit type. But this slightly decrease--- performance, as the resulting 'go' function can float out to top level.----- [Note: Local 'go' functions and capturing]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- As opposed to IntSet, when 'go' function captures an argument, increased--- heap-allocation can occur: sometimes in a polymorphic function, the 'go'--- floats out of its enclosing function and then it heap-allocates the--- dictionary and the argument. Maybe it floats out too late and strictness--- analyzer cannot see that these could be passed on stack.------ For example, change 'member' so that its local 'go' function is not passing--- argument x and then look at the resulting code for hedgeInt.----- [Note: Order of constructors]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- The order of constructors of Set matters when considering performance.--- Currently in GHC 7.0, when type has 2 constructors, a forward conditional--- jump is made when successfully matching second constructor. Successful match--- of first constructor results in the forward jump not taken.--- On GHC 7.0, reordering constructors from Tip | Bin to Bin | Tip--- improves the benchmark by up to 10% on x86.--module Data.Set.Base (- -- * Set type- Set(..) -- instance Eq,Ord,Show,Read,Data,Typeable-- -- * Operators- , (\\)-- -- * Query- , null- , size- , member- , notMember- , lookupLT- , lookupGT- , lookupLE- , lookupGE- , isSubsetOf- , isProperSubsetOf-- -- * Construction- , empty- , singleton- , insert- , delete-- -- * Combine- , union- , unions- , difference- , intersection-- -- * Filter- , filter- , partition- , split- , splitMember-- -- * Map- , map- , mapMonotonic-- -- * Folds- , foldr- , foldl- -- ** Strict folds- , foldr'- , foldl'- -- ** Legacy folds- , fold-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , maxView- , minView-- -- * Conversion-- -- ** List- , elems- , toList- , fromList-- -- ** Ordered list- , toAscList- , toDescList- , fromAscList- , fromDistinctAscList-- -- * Debugging- , showTree- , showTreeWith- , valid-- -- Internals (for testing)- , bin- , balanced- , join- , merge- ) where--import Prelude hiding (filter,foldl,foldr,null,map)-import qualified Data.List as List-import Data.Monoid (Monoid(..))-import qualified Data.Foldable as Foldable-import Data.Typeable-import Control.DeepSeq (NFData(rnf))--#if __GLASGOW_HASKELL__-import GHC.Exts ( build )-import Text.Read-import Data.Data-#endif---- Use macros to define strictness of functions.--- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.--- We do not use BangPatterns, because they are not in any standard and we--- want the compilers to be compiled by as many compilers as possible.-#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined-#define STRICT_1_OF_3(fn) fn arg _ _ | arg `seq` False = undefined--{--------------------------------------------------------------------- Operators---------------------------------------------------------------------}-infixl 9 \\ ------ | /O(n+m)/. See 'difference'.-(\\) :: Ord a => Set a -> Set a -> Set a-m1 \\ m2 = difference m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (\\) #-}-#endif--{--------------------------------------------------------------------- Sets are size balanced trees---------------------------------------------------------------------}--- | A set of values @a@.---- See Note: Order of constructors-data Set a = Bin {-# UNPACK #-} !Size !a !(Set a) !(Set a)- | Tip--type Size = Int--instance Ord a => Monoid (Set a) where- mempty = empty- mappend = union- mconcat = unions--instance Foldable.Foldable Set where- fold Tip = mempty- fold (Bin _ k l r) = Foldable.fold l `mappend` k `mappend` Foldable.fold r- foldr = foldr- foldl = foldl- foldMap _ Tip = mempty- foldMap f (Bin _ k l r) = Foldable.foldMap f l `mappend` f k `mappend` Foldable.foldMap f r--#if __GLASGOW_HASKELL__--{--------------------------------------------------------------------- A Data instance---------------------------------------------------------------------}---- This instance preserves data abstraction at the cost of inefficiency.--- We omit reflection services for the sake of data abstraction.--instance (Data a, Ord a) => Data (Set a) where- gfoldl f z set = z fromList `f` (toList set)- toConstr _ = error "toConstr"- gunfold _ _ = error "gunfold"- dataTypeOf _ = mkNoRepType "Data.Set.Set"- dataCast1 f = gcast1 f--#endif--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}--- | /O(1)/. Is this the empty set?-null :: Set a -> Bool-null Tip = True-null (Bin {}) = False-{-# INLINE null #-}---- | /O(1)/. The number of elements in the set.-size :: Set a -> Int-size Tip = 0-size (Bin sz _ _ _) = sz-{-# INLINE size #-}---- | /O(log n)/. Is the element in the set?-member :: Ord a => a -> Set a -> Bool-member = go- where- STRICT_1_OF_2(go)- go _ Tip = False- go x (Bin _ y l r) = case compare x y of- LT -> go x l- GT -> go x r- EQ -> True-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE member #-}-#else-{-# INLINE member #-}-#endif---- | /O(log n)/. Is the element not in the set?-notMember :: Ord a => a -> Set a -> Bool-notMember a t = not $ member a t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE notMember #-}-#else-{-# INLINE notMember #-}-#endif---- | /O(log n)/. Find largest element smaller than the given one.------ > lookupLT 3 (fromList [3, 5]) == Nothing--- > lookupLT 5 (fromList [3, 5]) == Just 3-lookupLT :: Ord a => a -> Set a -> Maybe a-lookupLT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing x (Bin _ y l r) | x <= y = goNothing x l- | otherwise = goJust x y r-- STRICT_1_OF_3(goJust)- goJust _ best Tip = Just best- goJust x best (Bin _ y l r) | x <= y = goJust x best l- | otherwise = goJust x y r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLT #-}-#else-{-# INLINE lookupLT #-}-#endif---- | /O(log n)/. Find smallest element greater than the given one.------ > lookupGT 4 (fromList [3, 5]) == Just 5--- > lookupGT 5 (fromList [3, 5]) == Nothing-lookupGT :: Ord a => a -> Set a -> Maybe a-lookupGT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing x (Bin _ y l r) | x < y = goJust x y l- | otherwise = goNothing x r-- STRICT_1_OF_3(goJust)- goJust _ best Tip = Just best- goJust x best (Bin _ y l r) | x < y = goJust x y l- | otherwise = goJust x best r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGT #-}-#else-{-# INLINE lookupGT #-}-#endif---- | /O(log n)/. Find largest element smaller or equal to the given one.------ > lookupLE 2 (fromList [3, 5]) == Nothing--- > lookupLE 4 (fromList [3, 5]) == Just 3--- > lookupLE 5 (fromList [3, 5]) == Just 5-lookupLE :: Ord a => a -> Set a -> Maybe a-lookupLE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing x (Bin _ y l r) = case compare x y of LT -> goNothing x l- EQ -> Just y- GT -> goJust x y r-- STRICT_1_OF_3(goJust)- goJust _ best Tip = Just best- goJust x best (Bin _ y l r) = case compare x y of LT -> goJust x best l- EQ -> Just y- GT -> goJust x y r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLE #-}-#else-{-# INLINE lookupLE #-}-#endif---- | /O(log n)/. Find smallest element greater or equal to the given one.------ > lookupGE 3 (fromList [3, 5]) == Just 3--- > lookupGE 4 (fromList [3, 5]) == Just 5--- > lookupGE 6 (fromList [3, 5]) == Nothing-lookupGE :: Ord a => a -> Set a -> Maybe a-lookupGE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing x (Bin _ y l r) = case compare x y of LT -> goJust x y l- EQ -> Just y- GT -> goNothing x r-- STRICT_1_OF_3(goJust)- goJust _ best Tip = Just best- goJust x best (Bin _ y l r) = case compare x y of LT -> goJust x y l- EQ -> Just y- GT -> goJust x best r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGE #-}-#else-{-# INLINE lookupGE #-}-#endif--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. The empty set.-empty :: Set a-empty = Tip-{-# INLINE empty #-}---- | /O(1)/. Create a singleton set.-singleton :: a -> Set a-singleton x = Bin 1 x Tip Tip-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insertion, Deletion---------------------------------------------------------------------}--- | /O(log n)/. Insert an element in a set.--- If the set already contains an element equal to the given value,--- it is replaced with the new value.---- See Note: Type of local 'go' function-insert :: Ord a => a -> Set a -> Set a-insert = go- where- go :: Ord a => a -> Set a -> Set a- STRICT_1_OF_2(go)- go x Tip = singleton x- go x (Bin sz y l r) = case compare x y of- LT -> balanceL y (go x l) r- GT -> balanceR y l (go x r)- EQ -> Bin sz x l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insert #-}-#else-{-# INLINE insert #-}-#endif---- Insert an element to the set only if it is not in the set.--- Used by `union`.---- See Note: Type of local 'go' function-insertR :: Ord a => a -> Set a -> Set a-insertR = go- where- go :: Ord a => a -> Set a -> Set a- STRICT_1_OF_2(go)- go x Tip = singleton x- go x t@(Bin _ y l r) = case compare x y of- LT -> balanceL y (go x l) r- GT -> balanceR y l (go x r)- EQ -> t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertR #-}-#else-{-# INLINE insertR #-}-#endif---- | /O(log n)/. Delete an element from a set.---- See Note: Type of local 'go' function-delete :: Ord a => a -> Set a -> Set a-delete = go- where- go :: Ord a => a -> Set a -> Set a- STRICT_1_OF_2(go)- go _ Tip = Tip- go x (Bin _ y l r) = case compare x y of- LT -> balanceR y (go x l) r- GT -> balanceL y l (go x r)- EQ -> glue l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE delete #-}-#else-{-# INLINE delete #-}-#endif--{--------------------------------------------------------------------- Subset---------------------------------------------------------------------}--- | /O(n+m)/. Is this a proper subset? (ie. a subset but not equal).-isProperSubsetOf :: Ord a => Set a -> Set a -> Bool-isProperSubsetOf s1 s2- = (size s1 < size s2) && (isSubsetOf s1 s2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubsetOf #-}-#endif----- | /O(n+m)/. Is this a subset?--- @(s1 `isSubsetOf` s2)@ tells whether @s1@ is a subset of @s2@.-isSubsetOf :: Ord a => Set a -> Set a -> Bool-isSubsetOf t1 t2- = (size t1 <= size t2) && (isSubsetOfX t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubsetOf #-}-#endif--isSubsetOfX :: Ord a => Set a -> Set a -> Bool-isSubsetOfX Tip _ = True-isSubsetOfX _ Tip = False-isSubsetOfX (Bin _ x l r) t- = found && isSubsetOfX l lt && isSubsetOfX r gt- where- (lt,found,gt) = splitMember x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubsetOfX #-}-#endif---{--------------------------------------------------------------------- Minimal, Maximal---------------------------------------------------------------------}--- | /O(log n)/. The minimal element of a set.-findMin :: Set a -> a-findMin (Bin _ x Tip _) = x-findMin (Bin _ _ l _) = findMin l-findMin Tip = error "Set.findMin: empty set has no minimal element"---- | /O(log n)/. The maximal element of a set.-findMax :: Set a -> a-findMax (Bin _ x _ Tip) = x-findMax (Bin _ _ _ r) = findMax r-findMax Tip = error "Set.findMax: empty set has no maximal element"---- | /O(log n)/. Delete the minimal element.-deleteMin :: Set a -> Set a-deleteMin (Bin _ _ Tip r) = r-deleteMin (Bin _ x l r) = balanceR x (deleteMin l) r-deleteMin Tip = Tip---- | /O(log n)/. Delete the maximal element.-deleteMax :: Set a -> Set a-deleteMax (Bin _ _ l Tip) = l-deleteMax (Bin _ x l r) = balanceL x l (deleteMax r)-deleteMax Tip = Tip--{--------------------------------------------------------------------- Union.---------------------------------------------------------------------}--- | The union of a list of sets: (@'unions' == 'foldl' 'union' 'empty'@).-unions :: Ord a => [Set a] -> Set a-unions = foldlStrict union empty-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unions #-}-#endif---- | /O(n+m)/. The union of two sets, preferring the first set when--- equal elements are encountered.--- The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset `union` smallset).-union :: Ord a => Set a -> Set a -> Set a-union Tip t2 = t2-union t1 Tip = t1-union t1 t2 = hedgeUnion NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE union #-}-#endif--hedgeUnion :: Ord a => MaybeS a -> MaybeS a -> Set a -> Set a -> Set a-hedgeUnion _ _ t1 Tip = t1-hedgeUnion blo bhi Tip (Bin _ x l r) = join x (filterGt blo l) (filterLt bhi r)-hedgeUnion _ _ t1 (Bin _ x Tip Tip) = insertR x t1 -- According to benchmarks, this special case increases- -- performance up to 30%. It does not help in difference or intersection.-hedgeUnion blo bhi (Bin _ x l r) t2 = join x (hedgeUnion blo bmi l (trim blo bmi t2))- (hedgeUnion bmi bhi r (trim bmi bhi t2))- where bmi = JustS x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeUnion #-}-#endif--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}--- | /O(n+m)/. Difference of two sets.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.-difference :: Ord a => Set a -> Set a -> Set a-difference Tip _ = Tip-difference t1 Tip = t1-difference t1 t2 = hedgeDiff NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE difference #-}-#endif--hedgeDiff :: Ord a => MaybeS a -> MaybeS a -> Set a -> Set a -> Set a-hedgeDiff _ _ Tip _ = Tip-hedgeDiff blo bhi (Bin _ x l r) Tip = join x (filterGt blo l) (filterLt bhi r)-hedgeDiff blo bhi t (Bin _ x l r) = merge (hedgeDiff blo bmi (trim blo bmi t) l)- (hedgeDiff bmi bhi (trim bmi bhi t) r)- where bmi = JustS x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeDiff #-}-#endif--{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}--- | /O(n+m)/. The intersection of two sets.--- Elements of the result come from the first set, so for example------ > import qualified Data.Set as S--- > data AB = A | B deriving Show--- > instance Ord AB where compare _ _ = EQ--- > instance Eq AB where _ == _ = True--- > main = print (S.singleton A `S.intersection` S.singleton B,--- > S.singleton B `S.intersection` S.singleton A)------ prints @(fromList [A],fromList [B])@.-intersection :: Ord a => Set a -> Set a -> Set a-intersection Tip _ = Tip-intersection _ Tip = Tip-intersection t1 t2 = hedgeInt NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersection #-}-#endif--hedgeInt :: Ord a => MaybeS a -> MaybeS a -> Set a -> Set a -> Set a-hedgeInt _ _ _ Tip = Tip-hedgeInt _ _ Tip _ = Tip-hedgeInt blo bhi (Bin _ x l r) t2 = let l' = hedgeInt blo bmi l (trim blo bmi t2)- r' = hedgeInt bmi bhi r (trim bmi bhi t2)- in if x `member` t2 then join x l' r' else merge l' r'- where bmi = JustS x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeInt #-}-#endif--{--------------------------------------------------------------------- Filter and partition---------------------------------------------------------------------}--- | /O(n)/. Filter all elements that satisfy the predicate.-filter :: (a -> Bool) -> Set a -> Set a-filter _ Tip = Tip-filter p (Bin _ x l r)- | p x = join x (filter p l) (filter p r)- | otherwise = merge (filter p l) (filter p r)---- | /O(n)/. Partition the set into two sets, one with all elements that satisfy--- the predicate and one with all elements that don't satisfy the predicate.--- See also 'split'.-partition :: (a -> Bool) -> Set a -> (Set a,Set a)-partition _ Tip = (Tip, Tip)-partition p (Bin _ x l r) = case (partition p l, partition p r) of- ((l1, l2), (r1, r2))- | p x -> (join x l1 r1, merge l2 r2)- | otherwise -> (merge l1 r1, join x l2 r2)--{----------------------------------------------------------------------- Map-----------------------------------------------------------------------}---- | /O(n*log n)/.--- @'map' f s@ is the set obtained by applying @f@ to each element of @s@.------ It's worth noting that the size of the result may be smaller if,--- for some @(x,y)@, @x \/= y && f x == f y@--map :: (Ord a, Ord b) => (a->b) -> Set a -> Set b-map f = fromList . List.map f . toList-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE map #-}-#endif---- | /O(n)/. The------ @'mapMonotonic' f s == 'map' f s@, but works only when @f@ is monotonic.--- /The precondition is not checked./--- Semi-formally, we have:------ > and [x < y ==> f x < f y | x <- ls, y <- ls]--- > ==> mapMonotonic f s == map f s--- > where ls = toList s--mapMonotonic :: (a->b) -> Set a -> Set b-mapMonotonic _ Tip = Tip-mapMonotonic f (Bin sz x l r) = Bin sz (f x) (mapMonotonic f l) (mapMonotonic f r)--{--------------------------------------------------------------------- Fold---------------------------------------------------------------------}--- | /O(n)/. Fold the elements in the set using the given right-associative--- binary operator. This function is an equivalent of 'foldr' and is present--- for compatibility only.------ /Please note that fold will be deprecated in the future and removed./-fold :: (a -> b -> b) -> b -> Set a -> b-fold = foldr-{-# INLINE fold #-}---- | /O(n)/. Fold the elements in the set using the given right-associative--- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'toAscList'@.------ For example,------ > toAscList set = foldr (:) [] set-foldr :: (a -> b -> b) -> b -> Set a -> b-foldr f z = go z- where- go z' Tip = z'- go z' (Bin _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr #-}---- | /O(n)/. A strict version of 'foldr'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldr' :: (a -> b -> b) -> b -> Set a -> b-foldr' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr' #-}---- | /O(n)/. Fold the elements in the set using the given left-associative--- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'toAscList'@.------ For example,------ > toDescList set = foldl (flip (:)) [] set-foldl :: (a -> b -> a) -> a -> Set b -> a-foldl f z = go z- where- go z' Tip = z'- go z' (Bin _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl #-}---- | /O(n)/. A strict version of 'foldl'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldl' :: (a -> b -> a) -> a -> Set b -> a-foldl' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl' #-}--{--------------------------------------------------------------------- List variations---------------------------------------------------------------------}--- | /O(n)/. An alias of 'toAscList'. The elements of a set in ascending order.--- Subject to list fusion.-elems :: Set a -> [a]-elems = toAscList--{--------------------------------------------------------------------- Lists---------------------------------------------------------------------}--- | /O(n)/. Convert the set to a list of elements. Subject to list fusion.-toList :: Set a -> [a]-toList = toAscList---- | /O(n)/. Convert the set to an ascending list of elements. Subject to list fusion.-toAscList :: Set a -> [a]-toAscList = foldr (:) []---- | /O(n)/. Convert the set to a descending list of elements. Subject to list--- fusion.-toDescList :: Set a -> [a]-toDescList = foldl (flip (:)) []---- List fusion for the list generating functions.-#if __GLASGOW_HASKELL__--- The foldrFB and foldlFB are foldr and foldl equivalents, used for list fusion.--- They are important to convert unfused to{Asc,Desc}List back, see mapFB in prelude.-foldrFB :: (a -> b -> b) -> b -> Set a -> b-foldrFB = foldr-{-# INLINE[0] foldrFB #-}-foldlFB :: (a -> b -> a) -> a -> Set b -> a-foldlFB = foldl-{-# INLINE[0] foldlFB #-}---- Inline elems and toList, so that we need to fuse only toAscList.-{-# INLINE elems #-}-{-# INLINE toList #-}---- The fusion is enabled up to phase 2 included. If it does not succeed,--- convert in phase 1 the expanded to{Asc,Desc}List calls back to--- to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were used in--- a list fusion, otherwise it would go away in phase 1), and let compiler do--- whatever it wants with to{Asc,Desc}List -- it was forbidden to inline it--- before phase 0, otherwise the fusion rules would not fire at all.-{-# NOINLINE[0] toAscList #-}-{-# NOINLINE[0] toDescList #-}-{-# RULES "Set.toAscList" [~1] forall s . toAscList s = build (\c n -> foldrFB c n s) #-}-{-# RULES "Set.toAscListBack" [1] foldrFB (:) [] = toAscList #-}-{-# RULES "Set.toDescList" [~1] forall s . toDescList s = build (\c n -> foldlFB (\xs x -> c x xs) n s) #-}-{-# RULES "Set.toDescListBack" [1] foldlFB (\xs x -> x : xs) [] = toDescList #-}-#endif---- | /O(n*log n)/. Create a set from a list of elements.-fromList :: Ord a => [a] -> Set a-fromList = foldlStrict ins empty- where- ins t x = insert x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromList #-}-#endif--{--------------------------------------------------------------------- Building trees from ascending/descending lists can be done in linear time.-- Note that if [xs] is ascending that:- fromAscList xs == fromList xs---------------------------------------------------------------------}--- | /O(n)/. Build a set from an ascending list in linear time.--- /The precondition (input list is ascending) is not checked./-fromAscList :: Eq a => [a] -> Set a-fromAscList xs- = fromDistinctAscList (combineEq xs)- where- -- [combineEq xs] combines equal elements with [const] in an ordered list [xs]- combineEq xs'- = case xs' of- [] -> []- [x] -> [x]- (x:xx) -> combineEq' x xx-- combineEq' z [] = [z]- combineEq' z (x:xs')- | z==x = combineEq' z xs'- | otherwise = z:combineEq' x xs'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscList #-}-#endif----- | /O(n)/. Build a set from an ascending list of distinct elements in linear time.--- /The precondition (input list is strictly ascending) is not checked./-fromDistinctAscList :: [a] -> Set a-fromDistinctAscList xs- = create const (length xs) xs- where- -- 1) use continutations so that we use heap space instead of stack space.- -- 2) special case for n==5 to create bushier trees.- create c 0 xs' = c Tip xs'- create c 5 xs' = case xs' of- (x1:x2:x3:x4:x5:xx)- -> c (bin x4 (bin x2 (singleton x1) (singleton x3)) (singleton x5)) xx- _ -> error "fromDistinctAscList create 5"- create c n xs' = seq nr $ create (createR nr c) nl xs'- where nl = n `div` 2- nr = n - nl - 1-- createR n c l (x:ys) = create (createB l x c) n ys- createR _ _ _ [] = error "fromDistinctAscList createR []"- createB l x c r zs = c (bin x l r) zs--{--------------------------------------------------------------------- Eq converts the set to a list. In a lazy setting, this- actually seems one of the faster methods to compare two trees- and it is certainly the simplest :-)---------------------------------------------------------------------}-instance Eq a => Eq (Set a) where- t1 == t2 = (size t1 == size t2) && (toAscList t1 == toAscList t2)--{--------------------------------------------------------------------- Ord---------------------------------------------------------------------}--instance Ord a => Ord (Set a) where- compare s1 s2 = compare (toAscList s1) (toAscList s2)--{--------------------------------------------------------------------- Show---------------------------------------------------------------------}-instance Show a => Show (Set a) where- showsPrec p xs = showParen (p > 10) $- showString "fromList " . shows (toList xs)--{--------------------------------------------------------------------- Read---------------------------------------------------------------------}-instance (Read a, Ord a) => Read (Set a) where-#ifdef __GLASGOW_HASKELL__- readPrec = parens $ prec 10 $ do- Ident "fromList" <- lexP- xs <- readPrec- return (fromList xs)-- readListPrec = readListPrecDefault-#else- readsPrec p = readParen (p > 10) $ \ r -> do- ("fromList",s) <- lex r- (xs,t) <- reads s- return (fromList xs,t)-#endif--{--------------------------------------------------------------------- Typeable/Data---------------------------------------------------------------------}--#include "Typeable.h"-INSTANCE_TYPEABLE1(Set,setTc,"Set")--{--------------------------------------------------------------------- NFData---------------------------------------------------------------------}--instance NFData a => NFData (Set a) where- rnf Tip = ()- rnf (Bin _ y l r) = rnf y `seq` rnf l `seq` rnf r--{--------------------------------------------------------------------- Utility functions that return sub-ranges of the original- tree. Some functions take a `Maybe value` as an argument to- allow comparisons against infinite values. These are called `blow`- (Nothing is -\infty) and `bhigh` (here Nothing is +\infty).- We use MaybeS value, which is a Maybe strict in the Just case.-- [trim blow bhigh t] A tree that is either empty or where [x > blow]- and [x < bhigh] for the value [x] of the root.- [filterGt blow t] A tree where for all values [k]. [k > blow]- [filterLt bhigh t] A tree where for all values [k]. [k < bhigh]-- [split k t] Returns two trees [l] and [r] where all values- in [l] are <[k] and all keys in [r] are >[k].- [splitMember k t] Just like [split] but also returns whether [k]- was found in the tree.---------------------------------------------------------------------}--data MaybeS a = NothingS | JustS !a--{--------------------------------------------------------------------- [trim blo bhi t] trims away all subtrees that surely contain no- values between the range [blo] to [bhi]. The returned tree is either- empty or the key of the root is between @blo@ and @bhi@.---------------------------------------------------------------------}-trim :: Ord a => MaybeS a -> MaybeS a -> Set a -> Set a-trim NothingS NothingS t = t-trim (JustS lx) NothingS t = greater lx t where greater lo (Bin _ x _ r) | x <= lo = greater lo r- greater _ t' = t'-trim NothingS (JustS hx) t = lesser hx t where lesser hi (Bin _ x l _) | x >= hi = lesser hi l- lesser _ t' = t'-trim (JustS lx) (JustS hx) t = middle lx hx t where middle lo hi (Bin _ x _ r) | x <= lo = middle lo hi r- middle lo hi (Bin _ x l _) | x >= hi = middle lo hi l- middle _ _ t' = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trim #-}-#endif--{--------------------------------------------------------------------- [filterGt b t] filter all values >[b] from tree [t]- [filterLt b t] filter all values <[b] from tree [t]---------------------------------------------------------------------}-filterGt :: Ord a => MaybeS a -> Set a -> Set a-filterGt NothingS t = t-filterGt (JustS b) t = filter' b t- where filter' _ Tip = Tip- filter' b' (Bin _ x l r) =- case compare b' x of LT -> join x (filter' b' l) r- EQ -> r- GT -> filter' b' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterGt #-}-#endif--filterLt :: Ord a => MaybeS a -> Set a -> Set a-filterLt NothingS t = t-filterLt (JustS b) t = filter' b t- where filter' _ Tip = Tip- filter' b' (Bin _ x l r) =- case compare x b' of LT -> join x l (filter' b' r)- EQ -> l- GT -> filter' b' l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterLt #-}-#endif--{--------------------------------------------------------------------- Split---------------------------------------------------------------------}--- | /O(log n)/. The expression (@'split' x set@) is a pair @(set1,set2)@--- where @set1@ comprises the elements of @set@ less than @x@ and @set2@--- comprises the elements of @set@ greater than @x@.-split :: Ord a => a -> Set a -> (Set a,Set a)-split _ Tip = (Tip,Tip)-split x (Bin _ y l r)- = case compare x y of- LT -> let (lt,gt) = split x l in (lt,join y gt r)- GT -> let (lt,gt) = split x r in (join y l lt,gt)- EQ -> (l,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE split #-}-#endif---- | /O(log n)/. Performs a 'split' but also returns whether the pivot--- element was found in the original set.-splitMember :: Ord a => a -> Set a -> (Set a,Bool,Set a)-splitMember _ Tip = (Tip, False, Tip)-splitMember x (Bin _ y l r)- = case compare x y of- LT -> let (lt, found, gt) = splitMember x l in (lt, found, join y gt r)- GT -> let (lt, found, gt) = splitMember x r in (join y l lt, found, gt)- EQ -> (l, True, r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE splitMember #-}-#endif--{--------------------------------------------------------------------- Utility functions that maintain the balance properties of the tree.- All constructors assume that all values in [l] < [x] and all values- in [r] > [x], and that [l] and [r] are valid trees.-- In order of sophistication:- [Bin sz x l r] The type constructor.- [bin x l r] Maintains the correct size, assumes that both [l]- and [r] are balanced with respect to each other.- [balance x l r] Restores the balance and size.- Assumes that the original tree was balanced and- that [l] or [r] has changed by at most one element.- [join x l r] Restores balance and size.-- Furthermore, we can construct a new tree from two trees. Both operations- assume that all values in [l] < all values in [r] and that [l] and [r]- are valid:- [glue l r] Glues [l] and [r] together. Assumes that [l] and- [r] are already balanced with respect to each other.- [merge l r] Merges two trees and restores balance.-- Note: in contrast to Adam's paper, we use (<=) comparisons instead- of (<) comparisons in [join], [merge] and [balance].- Quickcheck (on [difference]) showed that this was necessary in order- to maintain the invariants. It is quite unsatisfactory that I haven't- been able to find out why this is actually the case! Fortunately, it- doesn't hurt to be a bit more conservative.---------------------------------------------------------------------}--{--------------------------------------------------------------------- Join---------------------------------------------------------------------}-join :: a -> Set a -> Set a -> Set a-join x Tip r = insertMin x r-join x l Tip = insertMax x l-join x l@(Bin sizeL y ly ry) r@(Bin sizeR z lz rz)- | delta*sizeL < sizeR = balanceL z (join x l lz) rz- | delta*sizeR < sizeL = balanceR y ly (join x ry r)- | otherwise = bin x l r----- insertMin and insertMax don't perform potentially expensive comparisons.-insertMax,insertMin :: a -> Set a -> Set a-insertMax x t- = case t of- Tip -> singleton x- Bin _ y l r- -> balanceR y l (insertMax x r)--insertMin x t- = case t of- Tip -> singleton x- Bin _ y l r- -> balanceL y (insertMin x l) r--{--------------------------------------------------------------------- [merge l r]: merges two trees.---------------------------------------------------------------------}-merge :: Set a -> Set a -> Set a-merge Tip r = r-merge l Tip = l-merge l@(Bin sizeL x lx rx) r@(Bin sizeR y ly ry)- | delta*sizeL < sizeR = balanceL y (merge l ly) ry- | delta*sizeR < sizeL = balanceR x lx (merge rx r)- | otherwise = glue l r--{--------------------------------------------------------------------- [glue l r]: glues two trees together.- Assumes that [l] and [r] are already balanced with respect to each other.---------------------------------------------------------------------}-glue :: Set a -> Set a -> Set a-glue Tip r = r-glue l Tip = l-glue l r- | size l > size r = let (m,l') = deleteFindMax l in balanceR m l' r- | otherwise = let (m,r') = deleteFindMin r in balanceL m l r'---- | /O(log n)/. Delete and find the minimal element.------ > deleteFindMin set = (findMin set, deleteMin set)--deleteFindMin :: Set a -> (a,Set a)-deleteFindMin t- = case t of- Bin _ x Tip r -> (x,r)- Bin _ x l r -> let (xm,l') = deleteFindMin l in (xm,balanceR x l' r)- Tip -> (error "Set.deleteFindMin: can not return the minimal element of an empty set", Tip)---- | /O(log n)/. Delete and find the maximal element.------ > deleteFindMax set = (findMax set, deleteMax set)-deleteFindMax :: Set a -> (a,Set a)-deleteFindMax t- = case t of- Bin _ x l Tip -> (x,l)- Bin _ x l r -> let (xm,r') = deleteFindMax r in (xm,balanceL x l r')- Tip -> (error "Set.deleteFindMax: can not return the maximal element of an empty set", Tip)---- | /O(log n)/. Retrieves the minimal key of the set, and the set--- stripped of that element, or 'Nothing' if passed an empty set.-minView :: Set a -> Maybe (a, Set a)-minView Tip = Nothing-minView x = Just (deleteFindMin x)---- | /O(log n)/. Retrieves the maximal key of the set, and the set--- stripped of that element, or 'Nothing' if passed an empty set.-maxView :: Set a -> Maybe (a, Set a)-maxView Tip = Nothing-maxView x = Just (deleteFindMax x)--{--------------------------------------------------------------------- [balance x l r] balances two trees with value x.- The sizes of the trees should balance after decreasing the- size of one of them. (a rotation).-- [delta] is the maximal relative difference between the sizes of- two trees, it corresponds with the [w] in Adams' paper.- [ratio] is the ratio between an outer and inner sibling of the- heavier subtree in an unbalanced setting. It determines- whether a double or single rotation should be performed- to restore balance. It is correspondes with the inverse- of $\alpha$ in Adam's article.-- Note that according to the Adam's paper:- - [delta] should be larger than 4.646 with a [ratio] of 2.- - [delta] should be larger than 3.745 with a [ratio] of 1.534.-- But the Adam's paper is errorneous:- - it can be proved that for delta=2 and delta>=5 there does- not exist any ratio that would work- - delta=4.5 and ratio=2 does not work-- That leaves two reasonable variants, delta=3 and delta=4,- both with ratio=2.-- - A lower [delta] leads to a more 'perfectly' balanced tree.- - A higher [delta] performs less rebalancing.-- In the benchmarks, delta=3 is faster on insert operations,- and delta=4 has slightly better deletes. As the insert speedup- is larger, we currently use delta=3.----------------------------------------------------------------------}-delta,ratio :: Int-delta = 3-ratio = 2---- The balance function is equivalent to the following:------ balance :: a -> Set a -> Set a -> Set a--- balance x l r--- | sizeL + sizeR <= 1 = Bin sizeX x l r--- | sizeR > delta*sizeL = rotateL x l r--- | sizeL > delta*sizeR = rotateR x l r--- | otherwise = Bin sizeX x l r--- where--- sizeL = size l--- sizeR = size r--- sizeX = sizeL + sizeR + 1------ rotateL :: a -> Set a -> Set a -> Set a--- rotateL x l r@(Bin _ _ ly ry) | size ly < ratio*size ry = singleL x l r--- | otherwise = doubleL x l r--- rotateR :: a -> Set a -> Set a -> Set a--- rotateR x l@(Bin _ _ ly ry) r | size ry < ratio*size ly = singleR x l r--- | otherwise = doubleR x l r------ singleL, singleR :: a -> Set a -> Set a -> Set a--- singleL x1 t1 (Bin _ x2 t2 t3) = bin x2 (bin x1 t1 t2) t3--- singleR x1 (Bin _ x2 t1 t2) t3 = bin x2 t1 (bin x1 t2 t3)------ doubleL, doubleR :: a -> Set a -> Set a -> Set a--- doubleL x1 t1 (Bin _ x2 (Bin _ x3 t2 t3) t4) = bin x3 (bin x1 t1 t2) (bin x2 t3 t4)--- doubleR x1 (Bin _ x2 t1 (Bin _ x3 t2 t3)) t4 = bin x3 (bin x2 t1 t2) (bin x1 t3 t4)------ It is only written in such a way that every node is pattern-matched only once.------ Only balanceL and balanceR are needed at the moment, so balance is not here anymore.--- In case it is needed, it can be found in Data.Map.---- Functions balanceL and balanceR are specialised versions of balance.--- balanceL only checks whether the left subtree is too big,--- balanceR only checks whether the right subtree is too big.---- balanceL is called when left subtree might have been inserted to or when--- right subtree might have been deleted from.-balanceL :: a -> Set a -> Set a -> Set a-balanceL x l r = case r of- Tip -> case l of- Tip -> Bin 1 x Tip Tip- (Bin _ _ Tip Tip) -> Bin 2 x l Tip- (Bin _ lx Tip (Bin _ lrx _ _)) -> Bin 3 lrx (Bin 1 lx Tip Tip) (Bin 1 x Tip Tip)- (Bin _ lx ll@(Bin _ _ _ _) Tip) -> Bin 3 lx ll (Bin 1 x Tip Tip)- (Bin ls lx ll@(Bin lls _ _ _) lr@(Bin lrs lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lx ll (Bin (1+lrs) x lr Tip)- | otherwise -> Bin (1+ls) lrx (Bin (1+lls+size lrl) lx ll lrl) (Bin (1+size lrr) x lrr Tip)-- (Bin rs _ _ _) -> case l of- Tip -> Bin (1+rs) x Tip r-- (Bin ls lx ll lr)- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _, Bin lrs lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lx ll (Bin (1+rs+lrs) x lr r)- | otherwise -> Bin (1+ls+rs) lrx (Bin (1+lls+size lrl) lx ll lrl) (Bin (1+rs+size lrr) x lrr r)- (_, _) -> error "Failure in Data.Map.balanceL"- | otherwise -> Bin (1+ls+rs) x l r-{-# NOINLINE balanceL #-}---- balanceR is called when right subtree might have been inserted to or when--- left subtree might have been deleted from.-balanceR :: a -> Set a -> Set a -> Set a-balanceR x l r = case l of- Tip -> case r of- Tip -> Bin 1 x Tip Tip- (Bin _ _ Tip Tip) -> Bin 2 x Tip r- (Bin _ rx Tip rr@(Bin _ _ _ _)) -> Bin 3 rx (Bin 1 x Tip Tip) rr- (Bin _ rx (Bin _ rlx _ _) Tip) -> Bin 3 rlx (Bin 1 x Tip Tip) (Bin 1 rx Tip Tip)- (Bin rs rx rl@(Bin rls rlx rll rlr) rr@(Bin rrs _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rx (Bin (1+rls) x Tip rl) rr- | otherwise -> Bin (1+rs) rlx (Bin (1+size rll) x Tip rll) (Bin (1+rrs+size rlr) rx rlr rr)-- (Bin ls _ _ _) -> case r of- Tip -> Bin (1+ls) x l Tip-- (Bin rs rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlx rll rlr, Bin rrs _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rx (Bin (1+ls+rls) x l rl) rr- | otherwise -> Bin (1+ls+rs) rlx (Bin (1+ls+size rll) x l rll) (Bin (1+rrs+size rlr) rx rlr rr)- (_, _) -> error "Failure in Data.Map.balanceR"- | otherwise -> Bin (1+ls+rs) x l r-{-# NOINLINE balanceR #-}--{--------------------------------------------------------------------- The bin constructor maintains the size of the tree---------------------------------------------------------------------}-bin :: a -> Set a -> Set a -> Set a-bin x l r- = Bin (size l + size r + 1) x l r-{-# INLINE bin #-}---{--------------------------------------------------------------------- Utilities---------------------------------------------------------------------}-foldlStrict :: (a -> b -> a) -> a -> [b] -> a-foldlStrict f = go- where- go z [] = z- go z (x:xs) = let z' = f z x in z' `seq` go z' xs-{-# INLINE foldlStrict #-}--{--------------------------------------------------------------------- Debugging---------------------------------------------------------------------}--- | /O(n)/. Show the tree that implements the set. The tree is shown--- in a compressed, hanging format.-showTree :: Show a => Set a -> String-showTree s- = showTreeWith True False s---{- | /O(n)/. The expression (@showTreeWith hang wide map@) shows- the tree that implements the set. If @hang@ is- @True@, a /hanging/ tree is shown otherwise a rotated tree is shown. If- @wide@ is 'True', an extra wide version is shown.--> Set> putStrLn $ showTreeWith True False $ fromDistinctAscList [1..5]-> 4-> +--2-> | +--1-> | +--3-> +--5->-> Set> putStrLn $ showTreeWith True True $ fromDistinctAscList [1..5]-> 4-> |-> +--2-> | |-> | +--1-> | |-> | +--3-> |-> +--5->-> Set> putStrLn $ showTreeWith False True $ fromDistinctAscList [1..5]-> +--5-> |-> 4-> |-> | +--3-> | |-> +--2-> |-> +--1---}-showTreeWith :: Show a => Bool -> Bool -> Set a -> String-showTreeWith hang wide t- | hang = (showsTreeHang wide [] t) ""- | otherwise = (showsTree wide [] [] t) ""--showsTree :: Show a => Bool -> [String] -> [String] -> Set a -> ShowS-showsTree wide lbars rbars t- = case t of- Tip -> showsBars lbars . showString "|\n"- Bin _ x Tip Tip- -> showsBars lbars . shows x . showString "\n"- Bin _ x l r- -> showsTree wide (withBar rbars) (withEmpty rbars) r .- showWide wide rbars .- showsBars lbars . shows x . showString "\n" .- showWide wide lbars .- showsTree wide (withEmpty lbars) (withBar lbars) l--showsTreeHang :: Show a => Bool -> [String] -> Set a -> ShowS-showsTreeHang wide bars t- = case t of- Tip -> showsBars bars . showString "|\n"- Bin _ x Tip Tip- -> showsBars bars . shows x . showString "\n"- Bin _ x l r- -> showsBars bars . shows x . showString "\n" .- showWide wide bars .- showsTreeHang wide (withBar bars) l .- showWide wide bars .- showsTreeHang wide (withEmpty bars) r--showWide :: Bool -> [String] -> String -> String-showWide wide bars- | wide = showString (concat (reverse bars)) . showString "|\n"- | otherwise = id--showsBars :: [String] -> ShowS-showsBars bars- = case bars of- [] -> id- _ -> showString (concat (reverse (tail bars))) . showString node--node :: String-node = "+--"--withBar, withEmpty :: [String] -> [String]-withBar bars = "| ":bars-withEmpty bars = " ":bars--{--------------------------------------------------------------------- Assertions---------------------------------------------------------------------}--- | /O(n)/. Test if the internal set structure is valid.-valid :: Ord a => Set a -> Bool-valid t- = balanced t && ordered t && validsize t--ordered :: Ord a => Set a -> Bool-ordered t- = bounded (const True) (const True) t- where- bounded lo hi t'- = case t' of- Tip -> True- Bin _ x l r -> (lo x) && (hi x) && bounded lo (<x) l && bounded (>x) hi r--balanced :: Set a -> Bool-balanced t- = case t of- Tip -> True- Bin _ _ l r -> (size l + size r <= 1 || (size l <= delta*size r && size r <= delta*size l)) &&- balanced l && balanced r--validsize :: Set a -> Bool-validsize t- = (realsize t == Just (size t))- where- realsize t'- = case t' of- Tip -> Just 0- Bin sz _ l r -> case (realsize l,realsize r) of- (Just n,Just m) | n+m+1 == sz -> Just sz- _ -> Nothing
@@ -1,6 +0,0 @@-module Data.StrictPair (strictPair) where---- | Evaluate both argument to WHNF and create a pair of the result.-strictPair :: a -> b -> (a, b)-strictPair x y = x `seq` y `seq` (x, y)-{-# INLINE strictPair #-}
@@ -1,170 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__-{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}-#endif-#if __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Safe #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Tree--- Copyright : (c) The University of Glasgow 2002--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ Multi-way trees (/aka/ rose trees) and forests.-----------------------------------------------------------------------------------module Data.Tree(- Tree(..), Forest,- -- * Two-dimensional drawing- drawTree, drawForest,- -- * Extraction- flatten, levels,- -- * Building trees- unfoldTree, unfoldForest,- unfoldTreeM, unfoldForestM,- unfoldTreeM_BF, unfoldForestM_BF,- ) where--import Control.Applicative (Applicative(..), (<$>))-import Control.Monad-import Data.Monoid (Monoid(..))-import Data.Sequence (Seq, empty, singleton, (<|), (|>), fromList,- ViewL(..), ViewR(..), viewl, viewr)-import Data.Foldable (Foldable(foldMap), toList)-import Data.Traversable (Traversable(traverse))-import Data.Typeable-import Control.DeepSeq (NFData(rnf))--#ifdef __GLASGOW_HASKELL__-import Data.Data (Data)-#endif---- | Multi-way trees, also known as /rose trees/.-data Tree a = Node {- rootLabel :: a, -- ^ label value- subForest :: Forest a -- ^ zero or more child trees- }-#ifdef __GLASGOW_HASKELL__- deriving (Eq, Read, Show, Data)-#else- deriving (Eq, Read, Show)-#endif-type Forest a = [Tree a]--#include "Typeable.h"-INSTANCE_TYPEABLE1(Tree,treeTc,"Tree")--instance Functor Tree where- fmap f (Node x ts) = Node (f x) (map (fmap f) ts)--instance Applicative Tree where- pure x = Node x []- Node f tfs <*> tx@(Node x txs) =- Node (f x) (map (f <$>) txs ++ map (<*> tx) tfs)--instance Monad Tree where- return x = Node x []- Node x ts >>= f = Node x' (ts' ++ map (>>= f) ts)- where Node x' ts' = f x--instance Traversable Tree where- traverse f (Node x ts) = Node <$> f x <*> traverse (traverse f) ts--instance Foldable Tree where- foldMap f (Node x ts) = f x `mappend` foldMap (foldMap f) ts--instance NFData a => NFData (Tree a) where- rnf (Node x ts) = rnf x `seq` rnf ts---- | Neat 2-dimensional drawing of a tree.-drawTree :: Tree String -> String-drawTree = unlines . draw---- | Neat 2-dimensional drawing of a forest.-drawForest :: Forest String -> String-drawForest = unlines . map drawTree--draw :: Tree String -> [String]-draw (Node x ts0) = x : drawSubTrees ts0- where- drawSubTrees [] = []- drawSubTrees [t] =- "|" : shift "`- " " " (draw t)- drawSubTrees (t:ts) =- "|" : shift "+- " "| " (draw t) ++ drawSubTrees ts-- shift first other = zipWith (++) (first : repeat other)---- | The elements of a tree in pre-order.-flatten :: Tree a -> [a]-flatten t = squish t []- where squish (Node x ts) xs = x:Prelude.foldr squish xs ts---- | Lists of nodes at each level of the tree.-levels :: Tree a -> [[a]]-levels t =- map (map rootLabel) $- takeWhile (not . null) $- iterate (concatMap subForest) [t]---- | Build a tree from a seed value-unfoldTree :: (b -> (a, [b])) -> b -> Tree a-unfoldTree f b = let (a, bs) = f b in Node a (unfoldForest f bs)---- | Build a forest from a list of seed values-unfoldForest :: (b -> (a, [b])) -> [b] -> Forest a-unfoldForest f = map (unfoldTree f)---- | Monadic tree builder, in depth-first order-unfoldTreeM :: Monad m => (b -> m (a, [b])) -> b -> m (Tree a)-unfoldTreeM f b = do- (a, bs) <- f b- ts <- unfoldForestM f bs- return (Node a ts)---- | Monadic forest builder, in depth-first order-#ifndef __NHC__-unfoldForestM :: Monad m => (b -> m (a, [b])) -> [b] -> m (Forest a)-#endif-unfoldForestM f = Prelude.mapM (unfoldTreeM f)---- | Monadic tree builder, in breadth-first order,--- using an algorithm adapted from--- /Breadth-First Numbering: Lessons from a Small Exercise in Algorithm Design/,--- by Chris Okasaki, /ICFP'00/.-unfoldTreeM_BF :: Monad m => (b -> m (a, [b])) -> b -> m (Tree a)-unfoldTreeM_BF f b = liftM getElement $ unfoldForestQ f (singleton b)- where- getElement xs = case viewl xs of- x :< _ -> x- EmptyL -> error "unfoldTreeM_BF"---- | Monadic forest builder, in breadth-first order,--- using an algorithm adapted from--- /Breadth-First Numbering: Lessons from a Small Exercise in Algorithm Design/,--- by Chris Okasaki, /ICFP'00/.-unfoldForestM_BF :: Monad m => (b -> m (a, [b])) -> [b] -> m (Forest a)-unfoldForestM_BF f = liftM toList . unfoldForestQ f . fromList---- takes a sequence (queue) of seeds--- produces a sequence (reversed queue) of trees of the same length-unfoldForestQ :: Monad m => (b -> m (a, [b])) -> Seq b -> m (Seq (Tree a))-unfoldForestQ f aQ = case viewl aQ of- EmptyL -> return empty- a :< aQ' -> do- (b, as) <- f a- tQ <- unfoldForestQ f (Prelude.foldl (|>) aQ' as)- let (tQ', ts) = splitOnto [] as tQ- return (Node b ts <| tQ')- where- splitOnto :: [a'] -> [b'] -> Seq a' -> (Seq a', [a'])- splitOnto as [] q = (q, as)- splitOnto as (_:bs) q = case viewr q of- q' :> a -> splitOnto (a:as) bs q'- EmptyR -> error "unfoldForestQ"
@@ -1,83 +0,0 @@-This library (libraries/containers) is derived from code from several-sources:-- * Code from the GHC project which is largely (c) The University of- Glasgow, and distributable under a BSD-style license (see below),-- * Code from the Haskell 98 Report which is (c) Simon Peyton Jones- and freely redistributable (but see the full license for- restrictions).-- * Code from the Haskell Foreign Function Interface specification,- which is (c) Manuel M. T. Chakravarty and freely redistributable- (but see the full license for restrictions).--The full text of these licenses is reproduced below. All of the-licenses are BSD-style or compatible.---------------------------------------------------------------------------------The Glasgow Haskell Compiler License--Copyright 2004, The University Court of the University of Glasgow.-All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:--- Redistributions of source code must retain the above copyright notice,-this list of conditions and the following disclaimer.--- Redistributions in binary form must reproduce the above copyright notice,-this list of conditions and the following disclaimer in the documentation-and/or other materials provided with the distribution.--- Neither name of the University nor the names of its contributors may be-used to endorse or promote products derived from this software without-specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF-GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE-UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH-DAMAGE.---------------------------------------------------------------------------------Code derived from the document "Report on the Programming Language-Haskell 98", is distributed under the following license:-- Copyright (c) 2002 Simon Peyton Jones-- The authors intend this Report to belong to the entire Haskell- community, and so we grant permission to copy and distribute it for- any purpose, provided that it is reproduced in its entirety,- including this Notice. Modified versions of this Report may also be- copied and distributed for any purpose, provided that the modified- version is clearly presented as such, and that it does not claim to- be a definition of the Haskell 98 Language.---------------------------------------------------------------------------------Code derived from the document "The Haskell 98 Foreign Function-Interface, An Addendum to the Haskell 98 Report" is distributed under-the following license:-- Copyright (c) 2002 Manuel M. T. Chakravarty-- The authors intend this Report to belong to the entire Haskell- community, and so we grant permission to copy and distribute it for- any purpose, provided that it is reproduced in its entirety,- including this Notice. Modified versions of this Report may also be- copied and distributed for any purpose, provided that the modified- version is clearly presented as such, and that it does not claim to- be a definition of the Haskell 98 Foreign Function Interface.-------------------------------------------------------------------------------
@@ -1,6 +0,0 @@-module Main (main) where--import Distribution.Simple--main :: IO ()-main = defaultMain
@@ -1,94 +0,0 @@-{-# LANGUAGE BangPatterns #-}-module Main where--import Control.DeepSeq-import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO)-import Criterion.Config-import Criterion.Main-import Data.List (foldl')-import qualified Data.IntMap as M-import Data.Maybe (fromMaybe)-import Prelude hiding (lookup)--main = do- let m = M.fromAscList elems :: M.IntMap Int- defaultMainWith- defaultConfig- (liftIO . evaluate $ rnf [m])- [ bench "lookup" $ whnf (lookup keys) m- , bench "insert" $ whnf (ins elems) M.empty- , bench "insertWith empty" $ whnf (insWith elems) M.empty- , bench "insertWith update" $ whnf (insWith elems) m- , bench "insertWith' empty" $ whnf (insWith' elems) M.empty- , bench "insertWith' update" $ whnf (insWith' elems) m- , bench "insertWithKey empty" $ whnf (insWithKey elems) M.empty- , bench "insertWithKey update" $ whnf (insWithKey elems) m- , bench "insertWithKey' empty" $ whnf (insWithKey' elems) M.empty- , bench "insertWithKey' update" $ whnf (insWithKey' elems) m- , bench "insertLookupWithKey empty" $ whnf (insLookupWithKey elems) M.empty- , bench "insertLookupWithKey update" $ whnf (insLookupWithKey elems) m- , bench "map" $ whnf (M.map (+ 1)) m- , bench "mapWithKey" $ whnf (M.mapWithKey (+)) m- , bench "foldlWithKey" $ whnf (ins elems) m- , bench "foldlWithKey'" $ whnf (M.foldlWithKey' sum 0) m- , bench "foldrWithKey" $ whnf (M.foldrWithKey consPair []) m- , bench "delete" $ whnf (del keys) m- , bench "update" $ whnf (upd keys) m- , bench "updateLookupWithKey" $ whnf (upd' keys) m- , bench "alter" $ whnf (alt keys) m- , bench "mapMaybe" $ whnf (M.mapMaybe maybeDel) m- , bench "mapMaybeWithKey" $ whnf (M.mapMaybeWithKey (const maybeDel)) m- ]- where- elems = zip keys values- keys = [1..2^12]- values = [1..2^12]- sum k v1 v2 = k + v1 + v2- consPair k v xs = (k, v) : xs--add3 :: Int -> Int -> Int -> Int-add3 x y z = x + y + z-{-# INLINE add3 #-}--lookup :: [Int] -> M.IntMap Int -> Int-lookup xs m = foldl' (\n k -> fromMaybe n (M.lookup k m)) 0 xs--ins :: [(Int, Int)] -> M.IntMap Int -> M.IntMap Int-ins xs m = foldl' (\m (k, v) -> M.insert k v m) m xs--insWith :: [(Int, Int)] -> M.IntMap Int -> M.IntMap Int-insWith xs m = foldl' (\m (k, v) -> M.insertWith (+) k v m) m xs--insWithKey :: [(Int, Int)] -> M.IntMap Int -> M.IntMap Int-insWithKey xs m = foldl' (\m (k, v) -> M.insertWithKey add3 k v m) m xs--insWith' :: [(Int, Int)] -> M.IntMap Int -> M.IntMap Int-insWith' xs m = foldl' (\m (k, v) -> M.insertWith' (+) k v m) m xs--insWithKey' :: [(Int, Int)] -> M.IntMap Int -> M.IntMap Int-insWithKey' xs m = foldl' (\m (k, v) -> M.insertWithKey' add3 k v m) m xs--data PairS a b = PS !a !b--insLookupWithKey :: [(Int, Int)] -> M.IntMap Int -> (Int, M.IntMap Int)-insLookupWithKey xs m = let !(PS a b) = foldl' f (PS 0 m) xs in (a, b)- where- f (PS n m) (k, v) = let !(n', m') = M.insertLookupWithKey add3 k v m- in PS (fromMaybe 0 n' + n) m'--del :: [Int] -> M.IntMap Int -> M.IntMap Int-del xs m = foldl' (\m k -> M.delete k m) m xs--upd :: [Int] -> M.IntMap Int -> M.IntMap Int-upd xs m = foldl' (\m k -> M.update Just k m) m xs--upd' :: [Int] -> M.IntMap Int -> M.IntMap Int-upd' xs m = foldl' (\m k -> snd $ M.updateLookupWithKey (\_ a -> Just a) k m) m xs--alt :: [Int] -> M.IntMap Int -> M.IntMap Int-alt xs m = foldl' (\m k -> M.alter id k m) m xs--maybeDel :: Int -> Maybe Int-maybeDel n | n `mod` 3 == 0 = Nothing- | otherwise = Just n
@@ -1,48 +0,0 @@-{-# LANGUAGE BangPatterns #-}--module Main where--import Control.DeepSeq-import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO)-import Criterion.Config-import Criterion.Main-import Data.List (foldl')-import qualified Data.IntSet as S--main = do- let s = S.fromAscList elems :: S.IntSet- s_even = S.fromAscList elems_even :: S.IntSet- s_odd = S.fromAscList elems_odd :: S.IntSet- defaultMainWith- defaultConfig- (liftIO . evaluate $ rnf [s, s_even, s_odd])- [ bench "member" $ whnf (member elems) s- , bench "insert" $ whnf (ins elems) S.empty- , bench "map" $ whnf (S.map (+ 1)) s- , bench "filter" $ whnf (S.filter ((== 0) . (`mod` 2))) s- , bench "partition" $ whnf (S.partition ((== 0) . (`mod` 2))) s- , bench "fold" $ whnf (S.fold (:) []) s- , bench "delete" $ whnf (del elems) s- , bench "findMin" $ whnf S.findMin s- , bench "findMax" $ whnf S.findMax s- , bench "deleteMin" $ whnf S.deleteMin s- , bench "deleteMax" $ whnf S.deleteMax s- , bench "unions" $ whnf S.unions [s_even, s_odd]- , bench "union" $ whnf (S.union s_even) s_odd- , bench "difference" $ whnf (S.difference s) s_even- , bench "intersection" $ whnf (S.intersection s) s_even- ]- where- elems = [1..2^10]- elems_even = [2,4..2^10]- elems_odd = [1,3..2^10]--member :: [Int] -> S.IntSet -> Int-member xs s = foldl' (\n x -> if S.member x s then n + 1 else n) 0 xs--ins :: [Int] -> S.IntSet -> S.IntSet-ins xs s0 = foldl' (\s a -> S.insert a s) s0 xs--del :: [Int] -> S.IntSet -> S.IntSet-del xs s0 = foldl' (\s k -> S.delete k s) s0 xs
@@ -1,51 +0,0 @@-{-# LANGUAGE BangPatterns #-}-module Main where--import Control.DeepSeq-import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO)-import Criterion.Config-import Criterion.Main-import Data.List (foldl')-import qualified Data.IntMap as M-import qualified LookupGE_IntMap as M-import Data.Maybe (fromMaybe)-import Prelude hiding (lookup)--main :: IO ()-main = do- defaultMainWith- defaultConfig- (liftIO . evaluate $ rnf [m_even, m_odd, m_large])- [b f | b <- benches, f <- funs1]- where- m_even = M.fromAscList elems_even :: M.IntMap Int- m_odd = M.fromAscList elems_odd :: M.IntMap Int- m_large = M.fromAscList elems_large :: M.IntMap Int- bound = 2^12- elems_even = zip evens evens- elems_odd = zip odds odds- elems_large = zip large large- evens = [2,4..bound]- odds = [1,3..bound]- large = [1,100..50*bound]- benches =- [ \(n,fun) -> bench (n++" present") $ nf (fge fun evens) m_even- , \(n,fun) -> bench (n++" absent") $ nf (fge fun evens) m_odd- , \(n,fun) -> bench (n++" far") $ nf (fge fun odds) m_large- , \(n,fun) -> bench (n++" !present") $ nf (fge2 fun evens) m_even- , \(n,fun) -> bench (n++" !absent") $ nf (fge2 fun evens) m_odd- , \(n,fun) -> bench (n++" !far") $ nf (fge2 fun odds) m_large- ]- funs1 = [ ("GE split", M.lookupGE1)- , ("GE Craig", M.lookupGE2)- , ("GE Twan", M.lookupGE3)- , ("GE Milan", M.lookupGE4) ]--fge :: (Int -> M.IntMap Int -> Maybe (Int,Int)) -> [Int] -> M.IntMap Int -> (Int,Int)-fge fun xs m = foldl' (\n k -> fromMaybe n (fun k m)) (0,0) xs---- forcing values inside tuples!-fge2 :: (Int -> M.IntMap Int -> Maybe (Int,Int)) -> [Int] -> M.IntMap Int -> (Int,Int)-fge2 fun xs m = foldl' (\n@(!_, !_) k -> fromMaybe n (fun k m)) (0,0) xs-
@@ -1,97 +0,0 @@-{-# LANGUAGE CPP #-}-module LookupGE_IntMap where--import Prelude hiding (null)-import Data.IntMap.Base-#ifdef TESTING-import Test.QuickCheck-#endif--lookupGE1 :: Key -> IntMap a -> Maybe (Key,a)-lookupGE1 k m =- case splitLookup k m of- (_,Just v,_) -> Just (k,v)- (_,Nothing,r) -> findMinMaybe r--lookupGE2 :: Key -> IntMap a -> Maybe (Key,a)-lookupGE2 k t = case t of- Bin _ m l r | m < 0 -> if k >= 0- then go l- else case go r of- Nothing -> Just $ findMin l- justx -> justx- _ -> go t- where- go (Bin p m l r)- | nomatch k p m = if k < p- then Just $ findMin l- else Nothing- | zero k m = case go l of- Nothing -> Just $ findMin r- justx -> justx- | otherwise = go r- go (Tip ky y)- | k > ky = Nothing- | otherwise = Just (ky, y)- go Nil = Nothing--lookupGE3 :: Key -> IntMap a -> Maybe (Key,a)-lookupGE3 k t = k `seq` case t of- Bin _ m l r | m < 0 -> if k >= 0- then go Nothing l- else go (Just (findMin l)) r- _ -> go Nothing t- where- go def (Bin p m l r)- | nomatch k p m = if k < p then Just $ findMin l else def- | zero k m = go (Just $ findMin r) l- | otherwise = go def r- go def (Tip ky y)- | k > ky = def- | otherwise = Just (ky, y)- go def Nil = def--lookupGE4 :: Key -> IntMap a -> Maybe (Key,a)-lookupGE4 k t = k `seq` case t of- Bin _ m l r | m < 0 -> if k >= 0 then go Nil l- else go l r- _ -> go Nil t- where- go def (Bin p m l r)- | nomatch k p m = if k < p then fMin l else fMin def- | zero k m = go r l- | otherwise = go def r- go def (Tip ky y)- | k > ky = fMin def- | otherwise = Just (ky, y)- go def Nil = fMin def-- fMin :: IntMap a -> Maybe (Key, a)- fMin Nil = Nothing- fMin (Tip ky y) = Just (ky, y)- fMin (Bin _ _ l _) = fMin l------------------------------------------------------------------------------------ Utilities------------------------------------------------------------------------------------ | /O(log n)/. The minimal key of the map.-findMinMaybe :: IntMap a -> Maybe (Key, a)-findMinMaybe m- | null m = Nothing- | otherwise = Just (findMin m)--#ifdef TESTING----------------------------------------------------------------------------------- Properties:----------------------------------------------------------------------------------prop_lookupGE12 :: Int -> [Int] -> Bool-prop_lookupGE12 x xs = case fromList $ zip xs xs of m -> lookupGE1 x m == lookupGE2 x m--prop_lookupGE13 :: Int -> [Int] -> Bool-prop_lookupGE13 x xs = case fromList $ zip xs xs of m -> lookupGE1 x m == lookupGE3 x m--prop_lookupGE14 :: Int -> [Int] -> Bool-prop_lookupGE14 x xs = case fromList $ zip xs xs of m -> lookupGE1 x m == lookupGE4 x m-#endif
@@ -1,78 +0,0 @@-{-# LANGUAGE BangPatterns, CPP #-}-module LookupGE_Map where--import Data.Map.Base-#ifdef TESTING-import Test.QuickCheck-#endif--lookupGE1 :: Ord k => k -> Map k a -> Maybe (k,a)-lookupGE1 k m =- case splitLookup k m of- (_,Just v,_) -> Just (k,v)- (_,Nothing,r) -> findMinMaybe r-{-# INLINABLE lookupGE1 #-}--lookupGE2 :: Ord k => k -> Map k a -> Maybe (k,a)-lookupGE2 = go- where- go !_ Tip = Nothing- go !k (Bin _ kx x l r) =- case compare k kx of- LT -> case go k l of- Nothing -> Just (kx,x)- ret -> ret- GT -> go k r- EQ -> Just (kx,x)-{-# INLINABLE lookupGE2 #-}--lookupGE3 :: Ord k => k -> Map k a -> Maybe (k,a)-lookupGE3 = go Nothing- where- go def !_ Tip = def- go def !k (Bin _ kx x l r) =- case compare k kx of- LT -> go (Just (kx,x)) k l- GT -> go def k r- EQ -> Just (kx,x)-{-# INLINABLE lookupGE3 #-}--lookupGE4 :: Ord k => k -> Map k a -> Maybe (k,a)-lookupGE4 k = k `seq` goNothing- where- goNothing Tip = Nothing- goNothing (Bin _ kx x l r) = case compare k kx of- LT -> goJust kx x l- EQ -> Just (kx, x)- GT -> goNothing r-- goJust ky y Tip = Just (ky, y)- goJust ky y (Bin _ kx x l r) = case compare k kx of- LT -> goJust kx x l- EQ -> Just (kx, x)- GT -> goJust ky y r-{-# INLINABLE lookupGE4 #-}------------------------------------------------------------------------------------ Utilities----------------------------------------------------------------------------------findMinMaybe :: Map k a -> Maybe (k,a)-findMinMaybe (Bin _ kx x Tip _) = Just (kx,x)-findMinMaybe (Bin _ _ _ l _) = findMinMaybe l-findMinMaybe Tip = Nothing--#ifdef TESTING----------------------------------------------------------------------------------- Properties:----------------------------------------------------------------------------------prop_lookupGE12 :: Int -> [Int] -> Bool-prop_lookupGE12 x xs = case fromList $ zip xs xs of m -> lookupGE1 x m == lookupGE2 x m--prop_lookupGE13 :: Int -> [Int] -> Bool-prop_lookupGE13 x xs = case fromList $ zip xs xs of m -> lookupGE1 x m == lookupGE3 x m--prop_lookupGE14 :: Int -> [Int] -> Bool-prop_lookupGE14 x xs = case fromList $ zip xs xs of m -> lookupGE1 x m == lookupGE4 x m-#endif
@@ -1,3 +0,0 @@-TOP = ..--include ../Makefile
@@ -1,50 +0,0 @@-{-# LANGUAGE BangPatterns #-}-module Main where--import Control.DeepSeq-import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO)-import Criterion.Config-import Criterion.Main-import Data.List (foldl')-import qualified Data.Map as M-import qualified LookupGE_Map as M-import Data.Maybe (fromMaybe)-import Prelude hiding (lookup)--main :: IO ()-main = do- defaultMainWith- defaultConfig- (liftIO . evaluate $ rnf [m_even, m_odd, m_large])- [b f | b <- benches, f <- funs1]- where- m_even = M.fromAscList elems_even :: M.Map Int Int- m_odd = M.fromAscList elems_odd :: M.Map Int Int- m_large = M.fromAscList elems_large :: M.Map Int Int- bound = 2^10- elems_even = zip evens evens- elems_odd = zip odds odds- elems_large = zip large large- evens = [2,4..bound]- odds = [1,3..bound]- large = [1,100..50*bound]- benches =- [ \(n,fun) -> bench (n++" present") $ nf (fge fun evens) m_even- , \(n,fun) -> bench (n++" absent") $ nf (fge fun evens) m_odd- , \(n,fun) -> bench (n++" far") $ nf (fge fun odds) m_large- , \(n,fun) -> bench (n++" !present") $ nf (fge2 fun evens) m_even- , \(n,fun) -> bench (n++" !absent") $ nf (fge2 fun evens) m_odd- , \(n,fun) -> bench (n++" !far") $ nf (fge2 fun odds) m_large- ]- funs1 = [ ("GE split", M.lookupGE1)- , ("GE caseof", M.lookupGE2)- , ("GE Twan", M.lookupGE3)- , ("GE Milan", M.lookupGE4) ]--fge :: (Int -> M.Map Int Int -> Maybe (Int,Int)) -> [Int] -> M.Map Int Int -> (Int,Int)-fge fun xs m = foldl' (\n k -> fromMaybe n (fun k m)) (0,0) xs---- forcing values inside tuples!-fge2 :: (Int -> M.Map Int Int -> Maybe (Int,Int)) -> [Int] -> M.Map Int Int -> (Int,Int)-fge2 fun xs m = foldl' (\n@(!_, !_) k -> fromMaybe n (fun k m)) (0,0) xs
@@ -1,16 +0,0 @@-all:--bench-%: %.hs force- ghc -O2 -DTESTING $< -i../$(TOP) -o $@ -outputdir tmp -rtsopts--bench-%.csv: bench-%- ./bench-$* -v -u bench-$*.csv--.PHONY: force clean veryclean-force:--clean:- rm -rf tmp $(patsubst %.hs, bench-%, $(wildcard *.hs))--veryclean: clean- rm -rf *.csv
@@ -1,126 +0,0 @@-{-# LANGUAGE BangPatterns #-}-module Main where--import Control.DeepSeq-import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO)-import Criterion.Config-import Criterion.Main-import Data.List (foldl')-import qualified Data.Map as M-import Data.Maybe (fromMaybe)-import Prelude hiding (lookup)--main = do- let m = M.fromAscList elems :: M.Map Int Int- m_even = M.fromAscList elems_even :: M.Map Int Int- m_odd = M.fromAscList elems_odd :: M.Map Int Int- defaultMainWith- defaultConfig- (liftIO . evaluate $ rnf [m, m_even, m_odd])- [ bench "lookup absent" $ whnf (lookup evens) m_odd- , bench "lookup present" $ whnf (lookup evens) m_even- , bench "insert absent" $ whnf (ins elems_even) m_odd- , bench "insert present" $ whnf (ins elems_even) m_even- , bench "insertWith absent" $ whnf (insWith elems_even) m_odd- , bench "insertWith present" $ whnf (insWith elems_even) m_even- , bench "insertWith' absent" $ whnf (insWith' elems_even) m_odd- , bench "insertWith' present" $ whnf (insWith' elems_even) m_even- , bench "insertWithKey absent" $ whnf (insWithKey elems_even) m_odd- , bench "insertWithKey present" $ whnf (insWithKey elems_even) m_even- , bench "insertWithKey' absent" $ whnf (insWithKey' elems_even) m_odd- , bench "insertWithKey' present" $ whnf (insWithKey' elems_even) m_even- , bench "insertLookupWithKey absent" $ whnf (insLookupWithKey elems_even) m_odd- , bench "insertLookupWithKey present" $ whnf (insLookupWithKey elems_even) m_even- , bench "insertLookupWithKey' absent" $ whnf (insLookupWithKey' elems_even) m_odd- , bench "insertLookupWithKey' present" $ whnf (insLookupWithKey' elems_even) m_even- , bench "map" $ whnf (M.map (+ 1)) m- , bench "mapWithKey" $ whnf (M.mapWithKey (+)) m- , bench "foldlWithKey" $ whnf (ins elems) m--- , bench "foldlWithKey'" $ whnf (M.foldlWithKey' sum 0) m- , bench "foldrWithKey" $ whnf (M.foldrWithKey consPair []) m- , bench "delete absent" $ whnf (del evens) m_odd- , bench "delete present" $ whnf (del evens) m- , bench "update absent" $ whnf (upd Just evens) m_odd- , bench "update present" $ whnf (upd Just evens) m_even- , bench "update delete" $ whnf (upd (const Nothing) evens) m- , bench "updateLookupWithKey absent" $ whnf (upd' Just evens) m_odd- , bench "updateLookupWithKey present" $ whnf (upd' Just evens) m_even- , bench "updateLookupWithKey delete" $ whnf (upd' (const Nothing) evens) m- , bench "alter absent" $ whnf (alt id evens) m_odd- , bench "alter insert" $ whnf (alt (const (Just 1)) evens) m_odd- , bench "alter update" $ whnf (alt id evens) m_even- , bench "alter delete" $ whnf (alt (const Nothing) evens) m- , bench "mapMaybe" $ whnf (M.mapMaybe maybeDel) m- , bench "mapMaybeWithKey" $ whnf (M.mapMaybeWithKey (const maybeDel)) m- , bench "lookupIndex" $ whnf (lookupIndex keys) m- , bench "union" $ whnf (M.union m_even) m_odd- , bench "difference" $ whnf (M.difference m) m_even- , bench "intersection" $ whnf (M.intersection m) m_even- ]- where- bound = 2^10- elems = zip keys values- elems_even = zip evens evens- elems_odd = zip odds odds- keys = [1..bound]- evens = [2,4..bound]- odds = [1,3..bound]- values = [1..bound]- sum k v1 v2 = k + v1 + v2- consPair k v xs = (k, v) : xs--add3 :: Int -> Int -> Int -> Int-add3 x y z = x + y + z-{-# INLINE add3 #-}--lookup :: [Int] -> M.Map Int Int -> Int-lookup xs m = foldl' (\n k -> fromMaybe n (M.lookup k m)) 0 xs--lookupIndex :: [Int] -> M.Map Int Int -> Int-lookupIndex xs m = foldl' (\n k -> fromMaybe n (M.lookupIndex k m)) 0 xs--ins :: [(Int, Int)] -> M.Map Int Int -> M.Map Int Int-ins xs m = foldl' (\m (k, v) -> M.insert k v m) m xs--insWith :: [(Int, Int)] -> M.Map Int Int -> M.Map Int Int-insWith xs m = foldl' (\m (k, v) -> M.insertWith (+) k v m) m xs--insWithKey :: [(Int, Int)] -> M.Map Int Int -> M.Map Int Int-insWithKey xs m = foldl' (\m (k, v) -> M.insertWithKey add3 k v m) m xs--insWith' :: [(Int, Int)] -> M.Map Int Int -> M.Map Int Int-insWith' xs m = foldl' (\m (k, v) -> M.insertWith' (+) k v m) m xs--insWithKey' :: [(Int, Int)] -> M.Map Int Int -> M.Map Int Int-insWithKey' xs m = foldl' (\m (k, v) -> M.insertWithKey' add3 k v m) m xs--data PairS a b = PS !a !b--insLookupWithKey :: [(Int, Int)] -> M.Map Int Int -> (Int, M.Map Int Int)-insLookupWithKey xs m = let !(PS a b) = foldl' f (PS 0 m) xs in (a, b)- where- f (PS n m) (k, v) = let !(n', m') = M.insertLookupWithKey add3 k v m- in PS (fromMaybe 0 n' + n) m'--insLookupWithKey' :: [(Int, Int)] -> M.Map Int Int -> (Int, M.Map Int Int)-insLookupWithKey' xs m = let !(PS a b) = foldl' f (PS 0 m) xs in (a, b)- where- f (PS n m) (k, v) = let !(n', m') = M.insertLookupWithKey' add3 k v m- in PS (fromMaybe 0 n' + n) m'--del :: [Int] -> M.Map Int Int -> M.Map Int Int-del xs m = foldl' (\m k -> M.delete k m) m xs--upd :: (Int -> Maybe Int) -> [Int] -> M.Map Int Int -> M.Map Int Int-upd f xs m = foldl' (\m k -> M.update f k m) m xs--upd' :: (Int -> Maybe Int) -> [Int] -> M.Map Int Int -> M.Map Int Int-upd' f xs m = foldl' (\m k -> snd $ M.updateLookupWithKey (\_ a -> f a) k m) m xs--alt :: (Maybe Int -> Maybe Int) -> [Int] -> M.Map Int Int -> M.Map Int Int-alt f xs m = foldl' (\m k -> M.alter f k m) m xs--maybeDel :: Int -> Maybe Int-maybeDel n | n `mod` 3 == 0 = Nothing- | otherwise = Just n
@@ -1,34 +0,0 @@--- > ghc -DTESTING --make -O2 -fforce-recomp -i.. Sequence.hs-module Main where--import Control.DeepSeq-import Criterion.Main-import Data.List (foldl')-import qualified Data.Sequence as S-import qualified Data.Foldable-import System.Random--main = do- let s10 = S.fromList [1..10] :: S.Seq Int- s100 = S.fromList [1..100] :: S.Seq Int- s1000 = S.fromList [1..1000] :: S.Seq Int- rnf [s10, s100, s1000] `seq` return ()- let g = mkStdGen 1- let rlist n = map (`mod` (n+1)) (take 10000 (randoms g)) :: [Int]- r10 = rlist 10- r100 = rlist 100- r1000 = rlist 1000- rnf [r10, r100, r1000] `seq` return ()- defaultMain- [ bench "splitAt/append 10" $ nf (shuffle r10) s10- , bench "splitAt/append 100" $ nf (shuffle r100) s100- , bench "splitAt/append 1000" $ nf (shuffle r1000) s1000- ]---- splitAt+append: repeatedly cut the sequence at a random point--- and rejoin the pieces in the opposite order.--- Finally getting the middle element forces the whole spine.-shuffle :: [Int] -> S.Seq Int -> Int-shuffle ps s = case S.viewl (S.drop (S.length s `div` 2) (foldl' cut s ps)) of- x S.:< _ -> x- where cut xs p = let (front, back) = S.splitAt p xs in back S.>< front
@@ -1,49 +0,0 @@-{-# LANGUAGE BangPatterns #-}---- > ghc -DTESTING --make -O2 -fforce-recomp -i.. Set.hs-module Main where--import Control.DeepSeq-import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO)-import Criterion.Config-import Criterion.Main-import Data.List (foldl')-import qualified Data.Set as S--main = do- let s = S.fromAscList elems :: S.Set Int- s_even = S.fromAscList elems_even :: S.Set Int- s_odd = S.fromAscList elems_odd :: S.Set Int- defaultMainWith- defaultConfig- (liftIO . evaluate $ rnf [s, s_even, s_odd])- [ bench "member" $ whnf (member elems) s- , bench "insert" $ whnf (ins elems) S.empty- , bench "map" $ whnf (S.map (+ 1)) s- , bench "filter" $ whnf (S.filter ((== 0) . (`mod` 2))) s- , bench "partition" $ whnf (S.partition ((== 0) . (`mod` 2))) s- , bench "fold" $ whnf (S.fold (:) []) s- , bench "delete" $ whnf (del elems) s- , bench "findMin" $ whnf S.findMin s- , bench "findMax" $ whnf S.findMax s- , bench "deleteMin" $ whnf S.deleteMin s- , bench "deleteMax" $ whnf S.deleteMax s- , bench "unions" $ whnf S.unions [s_even, s_odd]- , bench "union" $ whnf (S.union s_even) s_odd- , bench "difference" $ whnf (S.difference s) s_even- , bench "intersection" $ whnf (S.intersection s) s_even- ]- where- elems = [1..2^10]- elems_even = [2,4..2^10]- elems_odd = [1,3..2^10]--member :: [Int] -> S.Set Int -> Int-member xs s = foldl' (\n x -> if S.member x s then n + 1 else n) 0 xs--ins :: [Int] -> S.Set Int -> S.Set Int-ins xs s0 = foldl' (\s a -> S.insert a s) s0 xs--del :: [Int] -> S.Set Int -> S.Set Int-del xs s0 = foldl' (\s k -> S.delete k s) s0 xs
@@ -1,3 +0,0 @@-TOP = ..--include ../Makefile
@@ -1,6 +0,0 @@-module Main where--import Data.IntMap as C-import SetOperations--main = benchmark (\xs -> fromList [(x, x) | x <- xs]) True [("union", C.union), ("difference", C.difference), ("intersection", C.intersection)]
@@ -1,6 +0,0 @@-module Main where--import Data.IntSet as C-import SetOperations--main = benchmark fromList True [("union", C.union), ("difference", C.difference), ("intersection", C.intersection)]
@@ -1,6 +0,0 @@-module Main where--import Data.Map as C-import SetOperations--main = benchmark (\xs -> fromList [(x, x) | x <- xs]) True [("union", C.union), ("difference", C.difference), ("intersection", C.intersection)]
@@ -1,6 +0,0 @@-module Main where--import Data.Set as C-import SetOperations--main = benchmark fromList True [("union", C.union), ("difference", C.difference), ("intersection", C.intersection)]
@@ -1,45 +0,0 @@-{-# LANGUAGE BangPatterns #-}--module SetOperations (benchmark) where--import Criterion.Main-import Data.List (partition)--benchmark :: ([Int] -> container) -> Bool -> [(String, container -> container -> container)] -> IO ()-benchmark fromList swap methods = do- defaultMain $ [ bench (method_str++"-"++input_str) $ whnf (method input1) input2 | (method_str, method) <- methods, (input_str, input1, input2) <- inputs ]-- where- n, s, t :: Int- n = 100000- s {-small-} = n `div` 10- t {-tiny-} = round $ sqrt $ fromIntegral n-- inputs = [ (mode_str, left, right)- | (mode_str, (left, right)) <- [ ("disj_nn", disj_nn), ("disj_ns", disj_ns), ("disj_nt", disj_nt)- , ("common_nn", common_nn), ("common_ns", common_ns), ("common_nt", common_nt)- , ("mix_nn", mix_nn), ("mix_ns", mix_ns), ("mix_nt", mix_nt)- , ("block_nn", block_nn), ("block_sn", block_ns)- ]-- , (mode_str, left, right) <- replicate 2 (mode_str, left, right) ++- replicate (if swap && take 4 mode_str /= "diff" && last mode_str /= last (init mode_str) then 2 else 0)- (init (init mode_str) ++ [last mode_str] ++ [last (init mode_str)], right, left)- ]-- all_n = fromList [1..n]-- !disj_nn = seqPair $ (all_n, fromList [n+1..n+n])- !disj_ns = seqPair $ (all_n, fromList [n+1..n+s])- !disj_nt = seqPair $ (all_n, fromList [n+1..n+t])- !common_nn = seqPair $ (all_n, fromList [2,4..n])- !common_ns = seqPair $ (all_n, fromList [0,1+n`div`s..n])- !common_nt = seqPair $ (all_n, fromList [0,1+n`div`t..n])- !mix_nn = seqPair $ fromLists $ partition ((== 0) . (`mod` 2)) [1..n+n]- !mix_ns = seqPair $ fromLists $ partition ((== 0) . (`mod` (1 + n`div`s))) [1..s+n]- !mix_nt = seqPair $ fromLists $ partition ((== 0) . (`mod` (1 + n`div`t))) [1..t+n]- !block_nn = seqPair $ fromLists $ partition ((< t) . (`mod` (t * 2))) [1..n+n]- !block_ns = seqPair $ fromLists $ partition ((< t) . (`mod` (t * (1 + n`div`s)))) [1..s+n]-- fromLists (xs, ys) = (fromList xs, fromList ys)- seqPair pair@(xs, ys) = xs `seq` ys `seq` pair
@@ -1,24 +0,0 @@-#!/usr/bin/perl-use warnings;-use strict;--@ARGV >= 2 or die "Usage: bench-cmp.pl csv_file_1 csv_file_2";-open (my $f1, "<", $ARGV[0]) or die "Cannot open file $ARGV[0]";-open (my $f2, "<", $ARGV[1]) or die "Cannot open file $ARGV[1]";--my $l1 = <$f1>;-my $l2 = <$f2>;-$l1 eq $l2 or die "CSV files do not correspond -- $l1 and $l2";--while (defined($l1 = <$f1>)) {- $l2 = <$f2>;-- my @parts1 = split /,/, $l1;- my @parts2 = split /,/, $l2;-- $parts1[0] eq $parts2[0] or die "CSV files do not correspond -- $parts1[0] and $parts2[0]";- printf "%s;%+7.2f%%;%.2e\n", $parts1[0], 100 * $parts2[1] / $parts1[1] - 100, $parts1[1];-}--close $f2;-close $f1;
@@ -1,3 +0,0 @@-#!/bin/sh--./bench-cmp.pl "$@" | column -nts\; | less -SR
@@ -1,193 +0,0 @@-name: containers-version: 0.5.0.0-license: BSD3-license-file: LICENSE-maintainer: fox@ucw.cz-bug-reports: https://github.com/haskell/containers/issues-synopsis: Assorted concrete container types-category: Data Structures-description:- This package contains efficient general-purpose implementations- of various basic immutable container types. The declared cost of- each operation is either worst-case or amortized, but remains- valid even if structures are shared.-build-type: Simple-cabal-version: >=1.8-extra-source-files:- include/Typeable.h- tests/Makefile- tests/*.hs- benchmarks/Makefile- benchmarks/bench-cmp.pl- benchmarks/bench-cmp.sh- benchmarks/*.hs- benchmarks/SetOperations/Makefile- benchmarks/SetOperations/*.hs- benchmarks/LookupGE/Makefile- benchmarks/LookupGE/*.hs--source-repository head- type: git- location: http://github.com/haskell/containers.git--Library- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4- if impl(ghc>=6.10)- build-depends: ghc-prim-- ghc-options: -O2 -Wall-- exposed-modules:- Data.IntMap- Data.IntMap.Lazy- Data.IntMap.Strict- Data.IntSet- Data.Map- Data.Map.Lazy- Data.Map.Strict- Data.Set- if !impl(nhc98)- exposed-modules:- Data.Graph- Data.Sequence- Data.Tree- other-modules:- Data.IntMap.Base- Data.IntSet.Base- Data.Map.Base- Data.Set.Base- Data.StrictPair-- include-dirs: include-- if impl(ghc<7.0)- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types------------------------ T E S T I N G -------------------------- Every test-suite contains the build-depends and options of the library,--- plus the testing stuff.---- Because the test-suites cannot contain conditionals in GHC 7.0, the extensions--- are switched on for every compiler to allow GHC < 7.0 to compile the tests--- (because GHC < 7.0 cannot handle conditional LANGUAGE pragmas).--- When testing with GHC < 7.0 is not needed, the extensions should be removed.--Test-suite map-lazy-properties- hs-source-dirs: tests, .- main-is: map-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- HUnit,- QuickCheck,- test-framework,- test-framework-hunit,- test-framework-quickcheck2--Test-suite map-strict-properties- hs-source-dirs: tests, .- main-is: map-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING -DSTRICT-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- HUnit,- QuickCheck,- test-framework,- test-framework-hunit,- test-framework-quickcheck2--Test-suite set-properties- hs-source-dirs: tests, .- main-is: set-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- HUnit,- QuickCheck,- test-framework,- test-framework-hunit,- test-framework-quickcheck2--Test-suite intmap-lazy-properties- hs-source-dirs: tests, .- main-is: intmap-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- HUnit,- QuickCheck,- test-framework,- test-framework-hunit,- test-framework-quickcheck2--Test-suite intmap-strict-properties- hs-source-dirs: tests, .- main-is: intmap-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING -DSTRICT-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- HUnit,- QuickCheck,- test-framework,- test-framework-hunit,- test-framework-quickcheck2--Test-suite intset-properties- hs-source-dirs: tests, .- main-is: intset-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- HUnit,- QuickCheck,- test-framework,- test-framework-hunit,- test-framework-quickcheck2--Test-suite seq-properties- hs-source-dirs: tests, .- main-is: seq-properties.hs- type: exitcode-stdio-1.0- cpp-options: -DTESTING-- build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim- ghc-options: -O2- extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types-- build-depends:- QuickCheck,- test-framework,- test-framework-quickcheck2
@@ -1,59 +0,0 @@-{- ---------------------------------------------------------------------------// Macros to help make Typeable instances.-//-// INSTANCE_TYPEABLEn(tc,tcname,"tc") defines-//-// instance Typeable/n/ tc-// instance Typeable a => Typeable/n-1/ (tc a)-// instance (Typeable a, Typeable b) => Typeable/n-2/ (tc a b)-// ...-// instance (Typeable a1, ..., Typeable an) => Typeable (tc a1 ... an)-// ----------------------------------------------------------------------------}--#ifndef TYPEABLE_H-#define TYPEABLE_H--#ifdef __GLASGOW_HASKELL__---- // For GHC, we can use DeriveDataTypeable + StandaloneDeriving to--- // generate the instances.--#define INSTANCE_TYPEABLE0(tycon,tcname,str) deriving instance Typeable tycon-#define INSTANCE_TYPEABLE1(tycon,tcname,str) deriving instance Typeable1 tycon-#define INSTANCE_TYPEABLE2(tycon,tcname,str) deriving instance Typeable2 tycon-#define INSTANCE_TYPEABLE3(tycon,tcname,str) deriving instance Typeable3 tycon--#else /* !__GLASGOW_HASKELL__ */--#define INSTANCE_TYPEABLE0(tycon,tcname,str) \-tcname :: TyCon; \-tcname = mkTyCon str; \-instance Typeable tycon where { typeOf _ = mkTyConApp tcname [] }--#define INSTANCE_TYPEABLE1(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable1 tycon where { typeOf1 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable (tycon a) where { typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE2(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable2 tycon where { typeOf2 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable1 (tycon a) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b) => Typeable (tycon a b) where { \- typeOf = typeOfDefault }--#define INSTANCE_TYPEABLE3(tycon,tcname,str) \-tcname = mkTyCon str; \-instance Typeable3 tycon where { typeOf3 _ = mkTyConApp tcname [] }; \-instance Typeable a => Typeable2 (tycon a) where { \- typeOf2 = typeOf2Default }; \-instance (Typeable a, Typeable b) => Typeable1 (tycon a b) where { \- typeOf1 = typeOf1Default }; \-instance (Typeable a, Typeable b, Typeable c) => Typeable (tycon a b c) where { \- typeOf = typeOfDefault }--#endif /* !__GLASGOW_HASKELL__ */--#endif
@@ -1,20 +0,0 @@-# The tests should be compiled and run using cabal:-# > cabal configure --enable-tests-# > cabal build-# > cabal test-#-# This Makefile is used by developers to compile the tests manually.--all:--%-properties: %-properties.hs force- ghc -O2 -DTESTING $< -i.. -o $@ -outputdir tmp--%-strict-properties: %-properties.hs force- ghc -O2 -DTESTING -DSTRICT $< -o $@ -i.. -outputdir tmp--.PHONY: force clean-force:--clean:- rm -rf tmp $(patsubst %.hs, %, $(wildcard *-properties.hs)) $(patsubst %-properties.hs, %-strict-properties, $(wildcard *-properties.hs))
@@ -1,1041 +0,0 @@-{-# LANGUAGE CPP #-}--#ifdef STRICT-import Data.IntMap.Strict as Data.IntMap-#else-import Data.IntMap.Lazy as Data.IntMap-#endif--import Data.Monoid-import Data.Maybe hiding (mapMaybe)-import qualified Data.Maybe as Maybe (mapMaybe)-import Data.Ord-import Data.Function-import Prelude hiding (lookup, null, map, filter, foldr, foldl)-import qualified Prelude (map)--import Data.List (nub,sort)-import qualified Data.List as List-import qualified Data.IntSet-import Test.Framework-import Test.Framework.Providers.HUnit-import Test.Framework.Providers.QuickCheck2-import Test.HUnit hiding (Test, Testable)-import Test.QuickCheck-import Text.Show.Functions ()--default (Int)--main :: IO ()-main = defaultMainWithOpts- [- testCase "index" test_index- , testCase "size" test_size- , testCase "size2" test_size2- , testCase "member" test_member- , testCase "notMember" test_notMember- , testCase "lookup" test_lookup- , testCase "findWithDefault" test_findWithDefault- , testCase "lookupLT" test_lookupLT- , testCase "lookupGT" test_lookupGT- , testCase "lookupLE" test_lookupLE- , testCase "lookupGE" test_lookupGE- , testCase "empty" test_empty- , testCase "mempty" test_mempty- , testCase "singleton" test_singleton- , testCase "insert" test_insert- , testCase "insertWith" test_insertWith- , testCase "insertWithKey" test_insertWithKey- , testCase "insertLookupWithKey" test_insertLookupWithKey- , testCase "delete" test_delete- , testCase "adjust" test_adjust- , testCase "adjustWithKey" test_adjustWithKey- , testCase "update" test_update- , testCase "updateWithKey" test_updateWithKey- , testCase "updateLookupWithKey" test_updateLookupWithKey- , testCase "alter" test_alter- , testCase "union" test_union- , testCase "mappend" test_mappend- , testCase "unionWith" test_unionWith- , testCase "unionWithKey" test_unionWithKey- , testCase "unions" test_unions- , testCase "mconcat" test_mconcat- , testCase "unionsWith" test_unionsWith- , testCase "difference" test_difference- , testCase "differenceWith" test_differenceWith- , testCase "differenceWithKey" test_differenceWithKey- , testCase "intersection" test_intersection- , testCase "intersectionWith" test_intersectionWith- , testCase "intersectionWithKey" test_intersectionWithKey- , testCase "map" test_map- , testCase "mapWithKey" test_mapWithKey- , testCase "mapAccum" test_mapAccum- , testCase "mapAccumWithKey" test_mapAccumWithKey- , testCase "mapAccumRWithKey" test_mapAccumRWithKey- , testCase "mapKeys" test_mapKeys- , testCase "mapKeysWith" test_mapKeysWith- , testCase "mapKeysMonotonic" test_mapKeysMonotonic- , testCase "elems" test_elems- , testCase "keys" test_keys- , testCase "assocs" test_assocs- , testCase "keysSet" test_keysSet- , testCase "keysSet" test_fromSet- , testCase "toList" test_toList- , testCase "fromList" test_fromList- , testCase "fromListWith" test_fromListWith- , testCase "fromListWithKey" test_fromListWithKey- , testCase "toAscList" test_toAscList- , testCase "toDescList" test_toDescList- , testCase "showTree" test_showTree- , testCase "fromAscList" test_fromAscList- , testCase "fromAscListWith" test_fromAscListWith- , testCase "fromAscListWithKey" test_fromAscListWithKey- , testCase "fromDistinctAscList" test_fromDistinctAscList- , testCase "filter" test_filter- , testCase "filterWithKey" test_filteWithKey- , testCase "partition" test_partition- , testCase "partitionWithKey" test_partitionWithKey- , testCase "mapMaybe" test_mapMaybe- , testCase "mapMaybeWithKey" test_mapMaybeWithKey- , testCase "mapEither" test_mapEither- , testCase "mapEitherWithKey" test_mapEitherWithKey- , testCase "split" test_split- , testCase "splitLookup" test_splitLookup- , testCase "isSubmapOfBy" test_isSubmapOfBy- , testCase "isSubmapOf" test_isSubmapOf- , testCase "isProperSubmapOfBy" test_isProperSubmapOfBy- , testCase "isProperSubmapOf" test_isProperSubmapOf- , testCase "findMin" test_findMin- , testCase "findMax" test_findMax- , testCase "deleteMin" test_deleteMin- , testCase "deleteMax" test_deleteMax- , testCase "deleteFindMin" test_deleteFindMin- , testCase "deleteFindMax" test_deleteFindMax- , testCase "updateMin" test_updateMin- , testCase "updateMax" test_updateMax- , testCase "updateMinWithKey" test_updateMinWithKey- , testCase "updateMaxWithKey" test_updateMaxWithKey- , testCase "minView" test_minView- , testCase "maxView" test_maxView- , testCase "minViewWithKey" test_minViewWithKey- , testCase "maxViewWithKey" test_maxViewWithKey- , testProperty "insert to singleton" prop_singleton- , testProperty "insert then lookup" prop_insertLookup- , testProperty "insert then delete" prop_insertDelete- , testProperty "delete non member" prop_deleteNonMember- , testProperty "union model" prop_unionModel- , testProperty "union singleton" prop_unionSingleton- , testProperty "union associative" prop_unionAssoc- , testProperty "union+unionWith" prop_unionWith- , testProperty "union sum" prop_unionSum- , testProperty "difference model" prop_differenceModel- , testProperty "intersection model" prop_intersectionModel- , testProperty "intersectionWith model" prop_intersectionWithModel- , testProperty "intersectionWithKey model" prop_intersectionWithKeyModel- , testProperty "mergeWithKey model" prop_mergeWithKeyModel- , testProperty "fromAscList" prop_ordered- , testProperty "fromList then toList" prop_list- , testProperty "toDescList" prop_descList- , testProperty "toAscList+toDescList" prop_ascDescList- , testProperty "alter" prop_alter- , testProperty "index" prop_index- , testProperty "null" prop_null- , testProperty "member" prop_member- , testProperty "notmember" prop_notmember- , testProperty "lookup" prop_lookup- , testProperty "find" prop_find- , testProperty "findWithDefault" prop_findWithDefault- , testProperty "lookupLT" prop_lookupLT- , testProperty "lookupGT" prop_lookupGT- , testProperty "lookupLE" prop_lookupLE- , testProperty "lookupGE" prop_lookupGE- , testProperty "findMin" prop_findMin- , testProperty "findMax" prop_findMax- , testProperty "deleteMin" prop_deleteMinModel- , testProperty "deleteMax" prop_deleteMaxModel- , testProperty "filter" prop_filter- , testProperty "partition" prop_partition- , testProperty "map" prop_map- , testProperty "fmap" prop_fmap- , testProperty "mapkeys" prop_mapkeys- , testProperty "split" prop_splitModel- , testProperty "foldr" prop_foldr- , testProperty "foldr'" prop_foldr'- , testProperty "foldl" prop_foldl- , testProperty "foldl'" prop_foldl'- , testProperty "keysSet" prop_keysSet- , testProperty "fromSet" prop_fromSet- ] opts-- where- opts = mempty { ropt_test_options = Just $ mempty { topt_maximum_generated_tests = Just 500- , topt_maximum_unsuitable_generated_tests = Just 500- }- }--{--------------------------------------------------------------------- Arbitrary, reasonably balanced trees---------------------------------------------------------------------}--instance Arbitrary a => Arbitrary (IntMap a) where- arbitrary = do{ ks <- arbitrary- ; xs <- arbitrary- ; return (fromList (zip xs ks))- }-----------------------------------------------------------------------------type UMap = IntMap ()-type IMap = IntMap Int-type SMap = IntMap String--------------------------------------------------------------------tests :: [Test]-tests = [ testGroup "Test Case" [- ]- , testGroup "Property Test" [- ]- ]---------------------------------------------------------------------- Unit tests-------------------------------------------------------------------------------------------------------------------------------------- Operators--test_index :: Assertion-test_index = fromList [(5,'a'), (3,'b')] ! 5 @?= 'a'--------------------------------------------------------------------- Query--test_size :: Assertion-test_size = do- null (empty) @?= True- null (singleton 1 'a') @?= False--test_size2 :: Assertion-test_size2 = do- size empty @?= 0- size (singleton 1 'a') @?= 1- size (fromList([(1,'a'), (2,'c'), (3,'b')])) @?= 3--test_member :: Assertion-test_member = do- member 5 (fromList [(5,'a'), (3,'b')]) @?= True- member 1 (fromList [(5,'a'), (3,'b')]) @?= False--test_notMember :: Assertion-test_notMember = do- notMember 5 (fromList [(5,'a'), (3,'b')]) @?= False- notMember 1 (fromList [(5,'a'), (3,'b')]) @?= True--test_lookup :: Assertion-test_lookup = do- employeeCurrency 1 @?= Just 1- employeeCurrency 2 @?= Nothing- where- employeeDept = fromList([(1,2), (3,1)])- deptCountry = fromList([(1,1), (2,2)])- countryCurrency = fromList([(1, 2), (2, 1)])- employeeCurrency :: Int -> Maybe Int- employeeCurrency name = do- dept <- lookup name employeeDept- country <- lookup dept deptCountry- lookup country countryCurrency--test_findWithDefault :: Assertion-test_findWithDefault = do- findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) @?= 'x'- findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) @?= 'a'--test_lookupLT :: Assertion-test_lookupLT = do- lookupLT 3 (fromList [(3,'a'), (5,'b')]) @?= Nothing- lookupLT 4 (fromList [(3,'a'), (5,'b')]) @?= Just (3, 'a')--test_lookupGT :: Assertion-test_lookupGT = do- lookupGT 4 (fromList [(3,'a'), (5,'b')]) @?= Just (5, 'b')- lookupGT 5 (fromList [(3,'a'), (5,'b')]) @?= Nothing--test_lookupLE :: Assertion-test_lookupLE = do- lookupLE 2 (fromList [(3,'a'), (5,'b')]) @?= Nothing- lookupLE 4 (fromList [(3,'a'), (5,'b')]) @?= Just (3, 'a')- lookupLE 5 (fromList [(3,'a'), (5,'b')]) @?= Just (5, 'b')--test_lookupGE :: Assertion-test_lookupGE = do- lookupGE 3 (fromList [(3,'a'), (5,'b')]) @?= Just (3, 'a')- lookupGE 4 (fromList [(3,'a'), (5,'b')]) @?= Just (5, 'b')- lookupGE 6 (fromList [(3,'a'), (5,'b')]) @?= Nothing--------------------------------------------------------------------- Construction--test_empty :: Assertion-test_empty = do- (empty :: UMap) @?= fromList []- size empty @?= 0--test_mempty :: Assertion-test_mempty = do- (mempty :: UMap) @?= fromList []- size (mempty :: UMap) @?= 0--test_singleton :: Assertion-test_singleton = do- singleton 1 'a' @?= fromList [(1, 'a')]- size (singleton 1 'a') @?= 1--test_insert :: Assertion-test_insert = do- insert 5 'x' (fromList [(5,'a'), (3,'b')]) @?= fromList [(3, 'b'), (5, 'x')]- insert 7 'x' (fromList [(5,'a'), (3,'b')]) @?= fromList [(3, 'b'), (5, 'a'), (7, 'x')]- insert 5 'x' empty @?= singleton 5 'x'--test_insertWith :: Assertion-test_insertWith = do- insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "xxxa")]- insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a"), (7, "xxx")]- insertWith (++) 5 "xxx" empty @?= singleton 5 "xxx"--test_insertWithKey :: Assertion-test_insertWithKey = do- insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "5:xxx|a")]- insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a"), (7, "xxx")]- insertWithKey f 5 "xxx" empty @?= singleton 5 "xxx"- where- f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--test_insertLookupWithKey :: Assertion-test_insertLookupWithKey = do- insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) @?= (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])- insertLookupWithKey f 2 "xxx" (fromList [(5,"a"), (3,"b")]) @?= (Nothing,fromList [(2,"xxx"),(3,"b"),(5,"a")])- insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) @?= (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])- insertLookupWithKey f 5 "xxx" empty @?= (Nothing, singleton 5 "xxx")- where- f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--------------------------------------------------------------------- Delete/Update--test_delete :: Assertion-test_delete = do- delete 5 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"- delete 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- delete 5 empty @?= (empty :: IMap)--test_adjust :: Assertion-test_adjust = do- adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "new a")]- adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- adjust ("new " ++) 7 empty @?= empty--test_adjustWithKey :: Assertion-test_adjustWithKey = do- adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "5:new a")]- adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- adjustWithKey f 7 empty @?= empty- where- f key x = (show key) ++ ":new " ++ x--test_update :: Assertion-test_update = do- update f 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "new a")]- update f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- update f 3 (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"- where- f x = if x == "a" then Just "new a" else Nothing--test_updateWithKey :: Assertion-test_updateWithKey = do- updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "5:new a")]- updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"- where- f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--test_updateLookupWithKey :: Assertion-test_updateLookupWithKey = do- updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) @?= (Just "a", fromList [(3, "b"), (5, "5:new a")])- updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) @?= (Nothing, fromList [(3, "b"), (5, "a")])- updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) @?= (Just "b", singleton 5 "a")- where- f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--test_alter :: Assertion-test_alter = do- alter f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- alter f 5 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"- alter g 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a"), (7, "c")]- alter g 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "c")]- where- f _ = Nothing- g _ = Just "c"--------------------------------------------------------------------- Combine--test_union :: Assertion-test_union = union (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "a"), (7, "C")]--test_mappend :: Assertion-test_mappend = mappend (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "a"), (7, "C")]--test_unionWith :: Assertion-test_unionWith = unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "aA"), (7, "C")]--test_unionWithKey :: Assertion-test_unionWithKey = unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "5:a|A"), (7, "C")]- where- f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--test_unions :: Assertion-test_unions = do- unions [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]- @?= fromList [(3, "b"), (5, "a"), (7, "C")]- unions [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]- @?= fromList [(3, "B3"), (5, "A3"), (7, "C")]--test_mconcat :: Assertion-test_mconcat = do- mconcat [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]- @?= fromList [(3, "b"), (5, "a"), (7, "C")]- mconcat [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]- @?= fromList [(3, "B3"), (5, "A3"), (7, "C")]--test_unionsWith :: Assertion-test_unionsWith = unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]- @?= fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--test_difference :: Assertion-test_difference = difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 3 "b"--test_differenceWith :: Assertion-test_differenceWith = differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])- @?= singleton 3 "b:B"- where- f al ar = if al== "b" then Just (al ++ ":" ++ ar) else Nothing--test_differenceWithKey :: Assertion-test_differenceWithKey = differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])- @?= singleton 3 "3:b|B"- where- f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--test_intersection :: Assertion-test_intersection = intersection (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 5 "a"---test_intersectionWith :: Assertion-test_intersectionWith = intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 5 "aA"--test_intersectionWithKey :: Assertion-test_intersectionWithKey = intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 5 "5:a|A"- where- f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--------------------------------------------------------------------- Traversal--test_map :: Assertion-test_map = map (++ "x") (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "bx"), (5, "ax")]--test_mapWithKey :: Assertion-test_mapWithKey = mapWithKey f (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "3:b"), (5, "5:a")]- where- f key x = (show key) ++ ":" ++ x--test_mapAccum :: Assertion-test_mapAccum = mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) @?= ("Everything: ba", fromList [(3, "bX"), (5, "aX")])- where- f a b = (a ++ b, b ++ "X")--test_mapAccumWithKey :: Assertion-test_mapAccumWithKey = mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) @?= ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])- where- f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--test_mapAccumRWithKey :: Assertion-test_mapAccumRWithKey = mapAccumRWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) @?= ("Everything: 5-a 3-b", fromList [(3, "bX"), (5, "aX")])- where- f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--test_mapKeys :: Assertion-test_mapKeys = do- mapKeys (+ 1) (fromList [(5,"a"), (3,"b")]) @?= fromList [(4, "b"), (6, "a")]- mapKeys (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 1 "c"- mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 3 "c"--test_mapKeysWith :: Assertion-test_mapKeysWith = do- mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 1 "cdab"- mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 3 "cdab"--test_mapKeysMonotonic :: Assertion-test_mapKeysMonotonic = do- mapKeysMonotonic (+ 1) (fromList [(5,"a"), (3,"b")]) @?= fromList [(4, "b"), (6, "a")]- mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) @?= fromList [(6, "b"), (10, "a")]--------------------------------------------------------------------- Conversion--test_elems :: Assertion-test_elems = do- elems (fromList [(5,"a"), (3,"b")]) @?= ["b","a"]- elems (empty :: UMap) @?= []--test_keys :: Assertion-test_keys = do- keys (fromList [(5,"a"), (3,"b")]) @?= [3,5]- keys (empty :: UMap) @?= []--test_assocs :: Assertion-test_assocs = do- assocs (fromList [(5,"a"), (3,"b")]) @?= [(3,"b"), (5,"a")]- assocs (empty :: UMap) @?= []--test_keysSet :: Assertion-test_keysSet = do- keysSet (fromList [(5,"a"), (3,"b")]) @?= Data.IntSet.fromList [3,5]- keysSet (empty :: UMap) @?= Data.IntSet.empty--test_fromSet :: Assertion-test_fromSet = do- fromSet (\k -> replicate k 'a') (Data.IntSet.fromList [3, 5]) @?= fromList [(5,"aaaaa"), (3,"aaa")]- fromSet undefined Data.IntSet.empty @?= (empty :: IMap)--------------------------------------------------------------------- Lists--test_toList :: Assertion-test_toList = do- toList (fromList [(5,"a"), (3,"b")]) @?= [(3,"b"), (5,"a")]- toList (empty :: SMap) @?= []--test_fromList :: Assertion-test_fromList = do- fromList [] @?= (empty :: SMap)- fromList [(5,"a"), (3,"b"), (5, "c")] @?= fromList [(5,"c"), (3,"b")]- fromList [(5,"c"), (3,"b"), (5, "a")] @?= fromList [(5,"a"), (3,"b")]--test_fromListWith :: Assertion-test_fromListWith = do- fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] @?= fromList [(3, "ab"), (5, "aba")]- fromListWith (++) [] @?= (empty :: SMap)--test_fromListWithKey :: Assertion-test_fromListWithKey = do- fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] @?= fromList [(3, "3ab"), (5, "5a5ba")]- fromListWithKey f [] @?= (empty :: SMap)- where- f k a1 a2 = (show k) ++ a1 ++ a2--------------------------------------------------------------------- Ordered lists--test_toAscList :: Assertion-test_toAscList = toAscList (fromList [(5,"a"), (3,"b")]) @?= [(3,"b"), (5,"a")]--test_toDescList :: Assertion-test_toDescList = toDescList (fromList [(5,"a"), (3,"b")]) @?= [(5,"a"), (3,"b")]--test_showTree :: Assertion-test_showTree =- (let t = fromDistinctAscList [(x,()) | x <- [1..5]]- in showTree t) @?= "*\n+--*\n| +-- 1:=()\n| +--*\n| +-- 2:=()\n| +-- 3:=()\n+--*\n +-- 4:=()\n +-- 5:=()\n"--test_fromAscList :: Assertion-test_fromAscList = do- fromAscList [(3,"b"), (5,"a")] @?= fromList [(3, "b"), (5, "a")]- fromAscList [(3,"b"), (5,"a"), (5,"b")] @?= fromList [(3, "b"), (5, "b")]---test_fromAscListWith :: Assertion-test_fromAscListWith = do- fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] @?= fromList [(3, "b"), (5, "ba")]--test_fromAscListWithKey :: Assertion-test_fromAscListWithKey = do- fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")] @?= fromList [(3, "b"), (5, "5:b5:ba")]- where- f k a1 a2 = (show k) ++ ":" ++ a1 ++ a2--test_fromDistinctAscList :: Assertion-test_fromDistinctAscList = do- fromDistinctAscList [(3,"b"), (5,"a")] @?= fromList [(3, "b"), (5, "a")]--------------------------------------------------------------------- Filter--test_filter :: Assertion-test_filter = do- filter (> "a") (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"- filter (> "x") (fromList [(5,"a"), (3,"b")]) @?= empty- filter (< "a") (fromList [(5,"a"), (3,"b")]) @?= empty--test_filteWithKey :: Assertion-test_filteWithKey = filterWithKey (\k _ -> k > 4) (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"--test_partition :: Assertion-test_partition = do- partition (> "a") (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", singleton 5 "a")- partition (< "x") (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3, "b"), (5, "a")], empty)- partition (> "x") (fromList [(5,"a"), (3,"b")]) @?= (empty, fromList [(3, "b"), (5, "a")])--test_partitionWithKey :: Assertion-test_partitionWithKey = do- partitionWithKey (\ k _ -> k > 3) (fromList [(5,"a"), (3,"b")]) @?= (singleton 5 "a", singleton 3 "b")- partitionWithKey (\ k _ -> k < 7) (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3, "b"), (5, "a")], empty)- partitionWithKey (\ k _ -> k > 7) (fromList [(5,"a"), (3,"b")]) @?= (empty, fromList [(3, "b"), (5, "a")])--test_mapMaybe :: Assertion-test_mapMaybe = mapMaybe f (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "new a"- where- f x = if x == "a" then Just "new a" else Nothing--test_mapMaybeWithKey :: Assertion-test_mapMaybeWithKey = mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "key : 3"- where- f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--test_mapEither :: Assertion-test_mapEither = do- mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])- mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= ((empty :: SMap), fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- where- f a = if a < "c" then Left a else Right a--test_mapEitherWithKey :: Assertion-test_mapEitherWithKey = do- mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])- mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= ((empty :: SMap), fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])- where- f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--test_split :: Assertion-test_split = do- split 2 (fromList [(5,"a"), (3,"b")]) @?= (empty, fromList [(3,"b"), (5,"a")])- split 3 (fromList [(5,"a"), (3,"b")]) @?= (empty, singleton 5 "a")- split 4 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", singleton 5 "a")- split 5 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", empty)- split 6 (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3,"b"), (5,"a")], empty)--test_splitLookup :: Assertion-test_splitLookup = do- splitLookup 2 (fromList [(5,"a"), (3,"b")]) @?= (empty, Nothing, fromList [(3,"b"), (5,"a")])- splitLookup 3 (fromList [(5,"a"), (3,"b")]) @?= (empty, Just "b", singleton 5 "a")- splitLookup 4 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", Nothing, singleton 5 "a")- splitLookup 5 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", Just "a", empty)- splitLookup 6 (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3,"b"), (5,"a")], Nothing, empty)--------------------------------------------------------------------- Submap--test_isSubmapOfBy :: Assertion-test_isSubmapOfBy = do- isSubmapOfBy (==) (fromList [(fromEnum 'a',1)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= True- isSubmapOfBy (<=) (fromList [(fromEnum 'a',1)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= True- isSubmapOfBy (==) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= True- isSubmapOfBy (==) (fromList [(fromEnum 'a',2)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= False- isSubmapOfBy (<) (fromList [(fromEnum 'a',1)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= False- isSubmapOfBy (==) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) (fromList [(fromEnum 'a',1)]) @?= False--test_isSubmapOf :: Assertion-test_isSubmapOf = do- isSubmapOf (fromList [(fromEnum 'a',1)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= True- isSubmapOf (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= True- isSubmapOf (fromList [(fromEnum 'a',2)]) (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) @?= False- isSubmapOf (fromList [(fromEnum 'a',1),(fromEnum 'b',2)]) (fromList [(fromEnum 'a',1)]) @?= False--test_isProperSubmapOfBy :: Assertion-test_isProperSubmapOfBy = do- isProperSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= True- isProperSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= True- isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)]) @?= False- isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)]) @?= False- isProperSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= False--test_isProperSubmapOf :: Assertion-test_isProperSubmapOf = do- isProperSubmapOf (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= True- isProperSubmapOf (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)]) @?= False- isProperSubmapOf (fromList [(1,1),(2,2)]) (fromList [(1,1)]) @?= False--------------------------------------------------------------------- Min/Max--test_findMin :: Assertion-test_findMin = findMin (fromList [(5,"a"), (3,"b")]) @?= (3,"b")--test_findMax :: Assertion-test_findMax = findMax (fromList [(5,"a"), (3,"b")]) @?= (5,"a")--test_deleteMin :: Assertion-test_deleteMin = do- deleteMin (fromList [(5,"a"), (3,"b"), (7,"c")]) @?= fromList [(5,"a"), (7,"c")]- deleteMin (empty :: SMap) @?= empty--test_deleteMax :: Assertion-test_deleteMax = do- deleteMax (fromList [(5,"a"), (3,"b"), (7,"c")]) @?= fromList [(3,"b"), (5,"a")]- deleteMax (empty :: SMap) @?= empty--test_deleteFindMin :: Assertion-test_deleteFindMin = deleteFindMin (fromList [(5,"a"), (3,"b"), (10,"c")]) @?= ((3,"b"), fromList[(5,"a"), (10,"c")])--test_deleteFindMax :: Assertion-test_deleteFindMax = deleteFindMax (fromList [(5,"a"), (3,"b"), (10,"c")]) @?= ((10,"c"), fromList [(3,"b"), (5,"a")])--test_updateMin :: Assertion-test_updateMin = do- updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "Xb"), (5, "a")]- updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"--test_updateMax :: Assertion-test_updateMax = do- updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "Xa")]- updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--test_updateMinWithKey :: Assertion-test_updateMinWithKey = do- updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3,"3:b"), (5,"a")]- updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"--test_updateMaxWithKey :: Assertion-test_updateMaxWithKey = do- updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3,"b"), (5,"5:a")]- updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--test_minView :: Assertion-test_minView = do- minView (fromList [(5,"a"), (3,"b")]) @?= Just ("b", singleton 5 "a")- minView (empty :: SMap) @?= Nothing--test_maxView :: Assertion-test_maxView = do- maxView (fromList [(5,"a"), (3,"b")]) @?= Just ("a", singleton 3 "b")- maxView (empty :: SMap) @?= Nothing--test_minViewWithKey :: Assertion-test_minViewWithKey = do- minViewWithKey (fromList [(5,"a"), (3,"b")]) @?= Just ((3,"b"), singleton 5 "a")- minViewWithKey (empty :: SMap) @?= Nothing--test_maxViewWithKey :: Assertion-test_maxViewWithKey = do- maxViewWithKey (fromList [(5,"a"), (3,"b")]) @?= Just ((5,"a"), singleton 3 "b")- maxViewWithKey (empty :: SMap) @?= Nothing--------------------------------------------------------------------- QuickCheck-------------------------------------------------------------------prop_singleton :: Int -> Int -> Bool-prop_singleton k x = insert k x empty == singleton k x--prop_insertLookup :: Int -> UMap -> Bool-prop_insertLookup k t = lookup k (insert k () t) /= Nothing--prop_insertDelete :: Int -> UMap -> Property-prop_insertDelete k t = (lookup k t == Nothing) ==> (delete k (insert k () t) == t)--prop_deleteNonMember :: Int -> UMap -> Property-prop_deleteNonMember k t = (lookup k t == Nothing) ==> (delete k t == t)--------------------------------------------------------------------prop_unionModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_unionModel xs ys- = sort (keys (union (fromList xs) (fromList ys)))- == sort (nub (Prelude.map fst xs ++ Prelude.map fst ys))--prop_unionSingleton :: IMap -> Int -> Int -> Bool-prop_unionSingleton t k x = union (singleton k x) t == insert k x t--prop_unionAssoc :: IMap -> IMap -> IMap -> Bool-prop_unionAssoc t1 t2 t3 = union t1 (union t2 t3) == union (union t1 t2) t3--prop_unionWith :: IMap -> IMap -> Bool-prop_unionWith t1 t2 = (union t1 t2 == unionWith (\_ y -> y) t2 t1)--prop_unionSum :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_unionSum xs ys- = sum (elems (unionWith (+) (fromListWith (+) xs) (fromListWith (+) ys)))- == (sum (Prelude.map snd xs) + sum (Prelude.map snd ys))--prop_differenceModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_differenceModel xs ys- = sort (keys (difference (fromListWith (+) xs) (fromListWith (+) ys)))- == sort ((List.\\) (nub (Prelude.map fst xs)) (nub (Prelude.map fst ys)))--prop_intersectionModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_intersectionModel xs ys- = sort (keys (intersection (fromListWith (+) xs) (fromListWith (+) ys)))- == sort (nub ((List.intersect) (Prelude.map fst xs) (Prelude.map fst ys)))--prop_intersectionWithModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_intersectionWithModel xs ys- = toList (intersectionWith f (fromList xs') (fromList ys'))- == [(kx, f vx vy ) | (kx, vx) <- List.sort xs', (ky, vy) <- ys', kx == ky]- where xs' = List.nubBy ((==) `on` fst) xs- ys' = List.nubBy ((==) `on` fst) ys- f l r = l + 2 * r--prop_intersectionWithKeyModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_intersectionWithKeyModel xs ys- = toList (intersectionWithKey f (fromList xs') (fromList ys'))- == [(kx, f kx vx vy) | (kx, vx) <- List.sort xs', (ky, vy) <- ys', kx == ky]- where xs' = List.nubBy ((==) `on` fst) xs- ys' = List.nubBy ((==) `on` fst) ys- f k l r = k + 2 * l + 3 * r--prop_mergeWithKeyModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_mergeWithKeyModel xs ys- = and [ testMergeWithKey f keep_x keep_y- | f <- [ \_k x1 _x2 -> Just x1- , \_k _x1 x2 -> Just x2- , \_k _x1 _x2 -> Nothing- , \k x1 x2 -> if k `mod` 2 == 0 then Nothing else Just (2 * x1 + 3 * x2)- ]- , keep_x <- [ True, False ]- , keep_y <- [ True, False ]- ]-- where xs' = List.nubBy ((==) `on` fst) xs- ys' = List.nubBy ((==) `on` fst) ys-- xm = fromList xs'- ym = fromList ys'-- testMergeWithKey f keep_x keep_y- = toList (mergeWithKey f (keep keep_x) (keep keep_y) xm ym) == emulateMergeWithKey f keep_x keep_y- where keep False _ = empty- keep True m = m-- emulateMergeWithKey f keep_x keep_y- = Maybe.mapMaybe combine (sort $ List.union (List.map fst xs') (List.map fst ys'))- where combine k = case (List.lookup k xs', List.lookup k ys') of- (Nothing, Just y) -> if keep_y then Just (k, y) else Nothing- (Just x, Nothing) -> if keep_x then Just (k, x) else Nothing- (Just x, Just y) -> (\v -> (k, v)) `fmap` f k x y-- -- We prevent inlining testMergeWithKey to disable the SpecConstr- -- optimalization. There are too many call patterns here so several- -- warnings are issued if testMergeWithKey gets inlined.- {-# NOINLINE testMergeWithKey #-}--------------------------------------------------------------------prop_ordered :: Property-prop_ordered- = forAll (choose (5,100)) $ \n ->- let xs = [(x,()) | x <- [0..n::Int]]- in fromAscList xs == fromList xs--prop_list :: [Int] -> Bool-prop_list xs = (sort (nub xs) == [x | (x,()) <- toList (fromList [(x,()) | x <- xs])])--prop_descList :: [Int] -> Bool-prop_descList xs = (reverse (sort (nub xs)) == [x | (x,()) <- toDescList (fromList [(x,()) | x <- xs])])--prop_ascDescList :: [Int] -> Bool-prop_ascDescList xs = toAscList m == reverse (toDescList m)- where m = fromList $ zip xs $ repeat ()--------------------------------------------------------------------prop_alter :: UMap -> Int -> Bool-prop_alter t k = case lookup k t of- Just _ -> (size t - 1) == size t' && lookup k t' == Nothing- Nothing -> (size t + 1) == size t' && lookup k t' /= Nothing- where- t' = alter f k t- f Nothing = Just ()- f (Just ()) = Nothing----------------------------------------------------------------------------- Compare against the list model (after nub on keys)--prop_index :: [Int] -> Property-prop_index xs = length xs > 0 ==>- let m = fromList (zip xs xs)- in xs == [ m ! i | i <- xs ]--prop_null :: IMap -> Bool-prop_null m = null m == (size m == 0)--prop_member :: [Int] -> Int -> Bool-prop_member xs n =- let m = fromList (zip xs xs)- in all (\k -> k `member` m == (k `elem` xs)) (n : xs)--prop_notmember :: [Int] -> Int -> Bool-prop_notmember xs n =- let m = fromList (zip xs xs)- in all (\k -> k `notMember` m == (k `notElem` xs)) (n : xs)--prop_lookup :: [(Int, Int)] -> Int -> Bool-prop_lookup xs n =- let xs' = List.nubBy ((==) `on` fst) xs- m = fromList xs'- in all (\k -> lookup k m == List.lookup k xs') (n : List.map fst xs')--prop_find :: [(Int, Int)] -> Bool-prop_find xs =- let xs' = List.nubBy ((==) `on` fst) xs- m = fromList xs'- in all (\(k, v) -> m ! k == v) xs'--prop_findWithDefault :: [(Int, Int)] -> Int -> Int -> Bool-prop_findWithDefault xs n x =- let xs' = List.nubBy ((==) `on` fst) xs- m = fromList xs'- in all (\k -> findWithDefault x k m == maybe x id (List.lookup k xs')) (n : List.map fst xs')--test_lookupSomething :: (Int -> IntMap Int -> Maybe (Int, Int)) -> (Int -> Int -> Bool) -> [(Int, Int)] -> Bool-test_lookupSomething lookup' cmp xs =- let odd_sorted_xs = filter_odd $ sort $ List.nubBy ((==) `on` fst) xs- t = fromList odd_sorted_xs- test k = case List.filter ((`cmp` k) . fst) odd_sorted_xs of- [] -> lookup' k t == Nothing- cs | 0 `cmp` 1 -> lookup' k t == Just (last cs) -- we want largest such element- | otherwise -> lookup' k t == Just (head cs) -- we want smallest such element- in all test (List.map fst xs)-- where filter_odd [] = []- filter_odd [_] = []- filter_odd (_ : o : xs) = o : filter_odd xs--prop_lookupLT :: [(Int, Int)] -> Bool-prop_lookupLT = test_lookupSomething lookupLT (<)--prop_lookupGT :: [(Int, Int)] -> Bool-prop_lookupGT = test_lookupSomething lookupGT (>)--prop_lookupLE :: [(Int, Int)] -> Bool-prop_lookupLE = test_lookupSomething lookupLE (<=)--prop_lookupGE :: [(Int, Int)] -> Bool-prop_lookupGE = test_lookupSomething lookupGE (>=)--prop_findMin :: [(Int, Int)] -> Property-prop_findMin ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in findMin m == List.minimumBy (comparing fst) xs--prop_findMax :: [(Int, Int)] -> Property-prop_findMax ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in findMax m == List.maximumBy (comparing fst) xs--prop_deleteMinModel :: [(Int, Int)] -> Property-prop_deleteMinModel ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in toAscList (deleteMin m) == tail (sort xs)--prop_deleteMaxModel :: [(Int, Int)] -> Property-prop_deleteMaxModel ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in toAscList (deleteMax m) == init (sort xs)--prop_filter :: (Int -> Bool) -> [(Int, Int)] -> Property-prop_filter p ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in filter p m == fromList (List.filter (p . snd) xs)--prop_partition :: (Int -> Bool) -> [(Int, Int)] -> Property-prop_partition p ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in partition p m == let (a,b) = (List.partition (p . snd) xs) in (fromList a, fromList b)--prop_map :: (Int -> Int) -> [(Int, Int)] -> Property-prop_map f ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in map f m == fromList [ (a, f b) | (a,b) <- xs ]--prop_fmap :: (Int -> Int) -> [(Int, Int)] -> Property-prop_fmap f ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in fmap f m == fromList [ (a, f b) | (a,b) <- xs ]--prop_mapkeys :: (Int -> Int) -> [(Int, Int)] -> Property-prop_mapkeys f ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in mapKeys f m == (fromList $ List.nubBy ((==) `on` fst) $ reverse [ (f a, b) | (a,b) <- sort xs])--prop_splitModel :: Int -> [(Int, Int)] -> Property-prop_splitModel n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- (l, r) = split n $ fromList xs- in toAscList l == sort [(k, v) | (k,v) <- xs, k < n] &&- toAscList r == sort [(k, v) | (k,v) <- xs, k > n]--prop_foldr :: Int -> [(Int, Int)] -> Property-prop_foldr n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldr (+) n m == List.foldr (+) n (List.map snd xs) &&- foldr (:) [] m == List.map snd (List.sort xs) &&- foldrWithKey (\_ a b -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldrWithKey (\k _ b -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldrWithKey (\k x xs -> (k,x):xs) [] m == List.sort xs---prop_foldr' :: Int -> [(Int, Int)] -> Property-prop_foldr' n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldr' (+) n m == List.foldr (+) n (List.map snd xs) &&- foldr' (:) [] m == List.map snd (List.sort xs) &&- foldrWithKey' (\_ a b -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldrWithKey' (\k _ b -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldrWithKey' (\k x xs -> (k,x):xs) [] m == List.sort xs--prop_foldl :: Int -> [(Int, Int)] -> Property-prop_foldl n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldl (+) n m == List.foldr (+) n (List.map snd xs) &&- foldl (flip (:)) [] m == reverse (List.map snd (List.sort xs)) &&- foldlWithKey (\b _ a -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldlWithKey (\b k _ -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldlWithKey (\xs k x -> (k,x):xs) [] m == reverse (List.sort xs)--prop_foldl' :: Int -> [(Int, Int)] -> Property-prop_foldl' n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldl' (+) n m == List.foldr (+) n (List.map snd xs) &&- foldl' (flip (:)) [] m == reverse (List.map snd (List.sort xs)) &&- foldlWithKey' (\b _ a -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldlWithKey' (\b k _ -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldlWithKey' (\xs k x -> (k,x):xs) [] m == reverse (List.sort xs)--prop_keysSet :: [(Int, Int)] -> Bool-prop_keysSet xs =- keysSet (fromList xs) == Data.IntSet.fromList (List.map fst xs)--prop_fromSet :: [(Int, Int)] -> Bool-prop_fromSet ys =- let xs = List.nubBy ((==) `on` fst) ys- in fromSet (\k -> fromJust $ List.lookup k xs) (Data.IntSet.fromList $ List.map fst xs) == fromList xs
@@ -1,312 +0,0 @@-import Data.Bits ((.&.))-import Data.IntSet-import Data.List (nub,sort)-import qualified Data.List as List-import Data.Monoid (mempty)-import qualified Data.Set as Set-import Prelude hiding (lookup, null, map, filter, foldr, foldl)-import Test.Framework-import Test.Framework.Providers.HUnit-import Test.Framework.Providers.QuickCheck2-import Test.HUnit hiding (Test, Testable)-import Test.QuickCheck hiding ((.&.))--main :: IO ()-main = defaultMainWithOpts [ testCase "lookupLT" test_lookupLT- , testCase "lookupGT" test_lookupGT- , testCase "lookupLE" test_lookupLE- , testCase "lookupGE" test_lookupGE- , testCase "split" test_split- , testProperty "prop_Single" prop_Single- , testProperty "prop_Member" prop_Member- , testProperty "prop_NotMember" prop_NotMember- , testProperty "prop_LookupLT" prop_LookupLT- , testProperty "prop_LookupGT" prop_LookupGT- , testProperty "prop_LookupLE" prop_LookupLE- , testProperty "prop_LookupGE" prop_LookupGE- , testProperty "prop_InsertDelete" prop_InsertDelete- , testProperty "prop_MemberFromList" prop_MemberFromList- , testProperty "prop_UnionInsert" prop_UnionInsert- , testProperty "prop_UnionAssoc" prop_UnionAssoc- , testProperty "prop_UnionComm" prop_UnionComm- , testProperty "prop_Diff" prop_Diff- , testProperty "prop_Int" prop_Int- , testProperty "prop_Ordered" prop_Ordered- , testProperty "prop_List" prop_List- , testProperty "prop_DescList" prop_DescList- , testProperty "prop_AscDescList" prop_AscDescList- , testProperty "prop_fromList" prop_fromList- , testProperty "prop_MaskPow2" prop_MaskPow2- , testProperty "prop_Prefix" prop_Prefix- , testProperty "prop_LeftRight" prop_LeftRight- , testProperty "prop_isProperSubsetOf" prop_isProperSubsetOf- , testProperty "prop_isProperSubsetOf2" prop_isProperSubsetOf2- , testProperty "prop_isSubsetOf" prop_isSubsetOf- , testProperty "prop_isSubsetOf2" prop_isSubsetOf2- , testProperty "prop_size" prop_size- , testProperty "prop_findMax" prop_findMax- , testProperty "prop_findMin" prop_findMin- , testProperty "prop_ord" prop_ord- , testProperty "prop_readShow" prop_readShow- , testProperty "prop_foldR" prop_foldR- , testProperty "prop_foldR'" prop_foldR'- , testProperty "prop_foldL" prop_foldL- , testProperty "prop_foldL'" prop_foldL'- , testProperty "prop_map" prop_map- , testProperty "prop_maxView" prop_maxView- , testProperty "prop_minView" prop_minView- , testProperty "prop_split" prop_split- , testProperty "prop_splitMember" prop_splitMember- , testProperty "prop_partition" prop_partition- , testProperty "prop_filter" prop_filter- ] opts- where- opts = mempty { ropt_test_options = Just $ mempty { topt_maximum_generated_tests = Just 500- , topt_maximum_unsuitable_generated_tests = Just 500- }- }--------------------------------------------------------------------- Unit tests-------------------------------------------------------------------test_lookupLT :: Assertion-test_lookupLT = do- lookupLT 3 (fromList [3, 5]) @?= Nothing- lookupLT 5 (fromList [3, 5]) @?= Just 3--test_lookupGT :: Assertion-test_lookupGT = do- lookupGT 4 (fromList [3, 5]) @?= Just 5- lookupGT 5 (fromList [3, 5]) @?= Nothing--test_lookupLE :: Assertion-test_lookupLE = do- lookupLE 2 (fromList [3, 5]) @?= Nothing- lookupLE 4 (fromList [3, 5]) @?= Just 3- lookupLE 5 (fromList [3, 5]) @?= Just 5--test_lookupGE :: Assertion-test_lookupGE = do- lookupGE 3 (fromList [3, 5]) @?= Just 3- lookupGE 4 (fromList [3, 5]) @?= Just 5- lookupGE 6 (fromList [3, 5]) @?= Nothing--test_split :: Assertion-test_split = do- split 3 (fromList [1..5]) @?= (fromList [1,2], fromList [4,5])--{--------------------------------------------------------------------- Arbitrary, reasonably balanced trees---------------------------------------------------------------------}-instance Arbitrary IntSet where- arbitrary = do{ xs <- arbitrary- ; return (fromList xs)- }---{--------------------------------------------------------------------- Single, Member, Insert, Delete, Member, FromList---------------------------------------------------------------------}-prop_Single :: Int -> Bool-prop_Single x- = (insert x empty == singleton x)--prop_Member :: [Int] -> Int -> Bool-prop_Member xs n =- let m = fromList xs- in all (\k -> k `member` m == (k `elem` xs)) (n : xs)--prop_NotMember :: [Int] -> Int -> Bool-prop_NotMember xs n =- let m = fromList xs- in all (\k -> k `notMember` m == (k `notElem` xs)) (n : xs)--test_LookupSomething :: (Int -> IntSet -> Maybe Int) -> (Int -> Int -> Bool) -> [Int] -> Bool-test_LookupSomething lookup' cmp xs =- let odd_sorted_xs = filter_odd $ nub $ sort xs- t = fromList odd_sorted_xs- test x = case List.filter (`cmp` x) odd_sorted_xs of- [] -> lookup' x t == Nothing- cs | 0 `cmp` 1 -> lookup' x t == Just (last cs) -- we want largest such element- | otherwise -> lookup' x t == Just (head cs) -- we want smallest such element- in all test xs-- where filter_odd [] = []- filter_odd [_] = []- filter_odd (_ : o : xs) = o : filter_odd xs--prop_LookupLT :: [Int] -> Bool-prop_LookupLT = test_LookupSomething lookupLT (<)--prop_LookupGT :: [Int] -> Bool-prop_LookupGT = test_LookupSomething lookupGT (>)--prop_LookupLE :: [Int] -> Bool-prop_LookupLE = test_LookupSomething lookupLE (<=)--prop_LookupGE :: [Int] -> Bool-prop_LookupGE = test_LookupSomething lookupGE (>=)--prop_InsertDelete :: Int -> IntSet -> Property-prop_InsertDelete k t- = not (member k t) ==> delete k (insert k t) == t--prop_MemberFromList :: [Int] -> Bool-prop_MemberFromList xs- = all (`member` t) abs_xs && all ((`notMember` t) . negate) abs_xs- where abs_xs = [abs x | x <- xs, x /= 0]- t = fromList abs_xs--{--------------------------------------------------------------------- Union---------------------------------------------------------------------}-prop_UnionInsert :: Int -> IntSet -> Bool-prop_UnionInsert x t- = union t (singleton x) == insert x t--prop_UnionAssoc :: IntSet -> IntSet -> IntSet -> Bool-prop_UnionAssoc t1 t2 t3- = union t1 (union t2 t3) == union (union t1 t2) t3--prop_UnionComm :: IntSet -> IntSet -> Bool-prop_UnionComm t1 t2- = (union t1 t2 == union t2 t1)--prop_Diff :: [Int] -> [Int] -> Bool-prop_Diff xs ys- = toAscList (difference (fromList xs) (fromList ys))- == List.sort ((List.\\) (nub xs) (nub ys))--prop_Int :: [Int] -> [Int] -> Bool-prop_Int xs ys- = toAscList (intersection (fromList xs) (fromList ys))- == List.sort (nub ((List.intersect) (xs) (ys)))--{--------------------------------------------------------------------- Lists---------------------------------------------------------------------}-prop_Ordered- = forAll (choose (5,100)) $ \n ->- let xs = concat [[i-n,i-n]|i<-[0..2*n :: Int]]- in fromAscList xs == fromList xs--prop_List :: [Int] -> Bool-prop_List xs- = (sort (nub xs) == toAscList (fromList xs))--prop_DescList :: [Int] -> Bool-prop_DescList xs = (reverse (sort (nub xs)) == toDescList (fromList xs))--prop_AscDescList :: [Int] -> Bool-prop_AscDescList xs = toAscList s == reverse (toDescList s)- where s = fromList xs--prop_fromList :: [Int] -> Bool-prop_fromList xs- = case fromList xs of- t -> t == fromAscList sort_xs &&- t == fromDistinctAscList nub_sort_xs &&- t == List.foldr insert empty xs- where sort_xs = sort xs- nub_sort_xs = List.map List.head $ List.group sort_xs--{--------------------------------------------------------------------- Bin invariants---------------------------------------------------------------------}-powersOf2 :: IntSet-powersOf2 = fromList [2^i | i <- [0..63]]---- Check the invariant that the mask is a power of 2.-prop_MaskPow2 :: IntSet -> Bool-prop_MaskPow2 (Bin _ msk left right) = member msk powersOf2 && prop_MaskPow2 left && prop_MaskPow2 right-prop_MaskPow2 _ = True---- Check that the prefix satisfies its invariant.-prop_Prefix :: IntSet -> Bool-prop_Prefix s@(Bin prefix msk left right) = all (\elem -> match elem prefix msk) (toList s) && prop_Prefix left && prop_Prefix right-prop_Prefix _ = True---- Check that the left elements don't have the mask bit set, and the right--- ones do.-prop_LeftRight :: IntSet -> Bool-prop_LeftRight (Bin _ msk left right) = and [x .&. msk == 0 | x <- toList left] && and [x .&. msk == msk | x <- toList right]-prop_LeftRight _ = True--{--------------------------------------------------------------------- IntSet operations are like Set operations---------------------------------------------------------------------}-toSet :: IntSet -> Set.Set Int-toSet = Set.fromList . toList---- Check that IntSet.isProperSubsetOf is the same as Set.isProperSubsetOf.-prop_isProperSubsetOf :: IntSet -> IntSet -> Bool-prop_isProperSubsetOf a b = isProperSubsetOf a b == Set.isProperSubsetOf (toSet a) (toSet b)---- In the above test, isProperSubsetOf almost always returns False (since a--- random set is almost never a subset of another random set). So this second--- test checks the True case.-prop_isProperSubsetOf2 :: IntSet -> IntSet -> Bool-prop_isProperSubsetOf2 a b = isProperSubsetOf a c == (a /= c) where- c = union a b--prop_isSubsetOf :: IntSet -> IntSet -> Bool-prop_isSubsetOf a b = isSubsetOf a b == Set.isSubsetOf (toSet a) (toSet b)--prop_isSubsetOf2 :: IntSet -> IntSet -> Bool-prop_isSubsetOf2 a b = isSubsetOf a (union a b)--prop_size :: IntSet -> Bool-prop_size s = size s == List.length (toList s)--prop_findMax :: IntSet -> Property-prop_findMax s = not (null s) ==> findMax s == maximum (toList s)--prop_findMin :: IntSet -> Property-prop_findMin s = not (null s) ==> findMin s == minimum (toList s)--prop_ord :: IntSet -> IntSet -> Bool-prop_ord s1 s2 = s1 `compare` s2 == toList s1 `compare` toList s2--prop_readShow :: IntSet -> Bool-prop_readShow s = s == read (show s)--prop_foldR :: IntSet -> Bool-prop_foldR s = foldr (:) [] s == toList s--prop_foldR' :: IntSet -> Bool-prop_foldR' s = foldr' (:) [] s == toList s--prop_foldL :: IntSet -> Bool-prop_foldL s = foldl (flip (:)) [] s == List.foldl (flip (:)) [] (toList s)--prop_foldL' :: IntSet -> Bool-prop_foldL' s = foldl' (flip (:)) [] s == List.foldl' (flip (:)) [] (toList s)--prop_map :: IntSet -> Bool-prop_map s = map id s == s--prop_maxView :: IntSet -> Bool-prop_maxView s = case maxView s of- Nothing -> null s- Just (m,s') -> m == maximum (toList s) && s == insert m s' && m `notMember` s'--prop_minView :: IntSet -> Bool-prop_minView s = case minView s of- Nothing -> null s- Just (m,s') -> m == minimum (toList s) && s == insert m s' && m `notMember` s'--prop_split :: IntSet -> Int -> Bool-prop_split s i = case split i s of- (s1,s2) -> all (<i) (toList s1) && all (>i) (toList s2) && i `delete` s == union s1 s2--prop_splitMember :: IntSet -> Int -> Bool-prop_splitMember s i = case splitMember i s of- (s1,t,s2) -> all (<i) (toList s1) && all (>i) (toList s2) && t == i `member` s && i `delete` s == union s1 s2--prop_partition :: IntSet -> Int -> Bool-prop_partition s i = case partition odd s of- (s1,s2) -> all odd (toList s1) && all even (toList s2) && s == s1 `union` s2--prop_filter :: IntSet -> Int -> Bool-prop_filter s i = partition odd s == (filter odd s, filter even s)
@@ -1,1188 +0,0 @@-{-# LANGUAGE CPP #-}--#ifdef STRICT-import Data.Map.Strict as Data.Map-#else-import Data.Map.Lazy as Data.Map-#endif--import Data.Monoid-import Data.Maybe hiding (mapMaybe)-import qualified Data.Maybe as Maybe (mapMaybe)-import Data.Ord-import Data.Function-import Prelude hiding (lookup, null, map, filter, foldr, foldl)-import qualified Prelude (map)--import Data.List (nub,sort)-import qualified Data.List as List-import qualified Data.Set-import Test.Framework-import Test.Framework.Providers.HUnit-import Test.Framework.Providers.QuickCheck2-import Test.HUnit hiding (Test, Testable)-import Test.QuickCheck-import Text.Show.Functions ()--default (Int)--main :: IO ()-main = defaultMainWithOpts- [ testCase "ticket4242" test_ticket4242- , testCase "index" test_index- , testCase "size" test_size- , testCase "size2" test_size2- , testCase "member" test_member- , testCase "notMember" test_notMember- , testCase "lookup" test_lookup- , testCase "findWithDefault" test_findWithDefault- , testCase "lookupLT" test_lookupLT- , testCase "lookupGT" test_lookupGT- , testCase "lookupLE" test_lookupLE- , testCase "lookupGE" test_lookupGE- , testCase "empty" test_empty- , testCase "mempty" test_mempty- , testCase "singleton" test_singleton- , testCase "insert" test_insert- , testCase "insertWith" test_insertWith- , testCase "insertWithKey" test_insertWithKey- , testCase "insertLookupWithKey" test_insertLookupWithKey- , testCase "delete" test_delete- , testCase "adjust" test_adjust- , testCase "adjustWithKey" test_adjustWithKey- , testCase "update" test_update- , testCase "updateWithKey" test_updateWithKey- , testCase "updateLookupWithKey" test_updateLookupWithKey- , testCase "alter" test_alter- , testCase "union" test_union- , testCase "mappend" test_mappend- , testCase "unionWith" test_unionWith- , testCase "unionWithKey" test_unionWithKey- , testCase "unions" test_unions- , testCase "mconcat" test_mconcat- , testCase "unionsWith" test_unionsWith- , testCase "difference" test_difference- , testCase "differenceWith" test_differenceWith- , testCase "differenceWithKey" test_differenceWithKey- , testCase "intersection" test_intersection- , testCase "intersectionWith" test_intersectionWith- , testCase "intersectionWithKey" test_intersectionWithKey- , testCase "map" test_map- , testCase "mapWithKey" test_mapWithKey- , testCase "mapAccum" test_mapAccum- , testCase "mapAccumWithKey" test_mapAccumWithKey- , testCase "mapAccumRWithKey" test_mapAccumRWithKey- , testCase "mapKeys" test_mapKeys- , testCase "mapKeysWith" test_mapKeysWith- , testCase "mapKeysMonotonic" test_mapKeysMonotonic- , testCase "elems" test_elems- , testCase "keys" test_keys- , testCase "assocs" test_assocs- , testCase "keysSet" test_keysSet- , testCase "fromSet" test_fromSet- , testCase "toList" test_toList- , testCase "fromList" test_fromList- , testCase "fromListWith" test_fromListWith- , testCase "fromListWithKey" test_fromListWithKey- , testCase "toAscList" test_toAscList- , testCase "toDescList" test_toDescList- , testCase "showTree" test_showTree- , testCase "showTree'" test_showTree'- , testCase "fromAscList" test_fromAscList- , testCase "fromAscListWith" test_fromAscListWith- , testCase "fromAscListWithKey" test_fromAscListWithKey- , testCase "fromDistinctAscList" test_fromDistinctAscList- , testCase "filter" test_filter- , testCase "filterWithKey" test_filteWithKey- , testCase "partition" test_partition- , testCase "partitionWithKey" test_partitionWithKey- , testCase "mapMaybe" test_mapMaybe- , testCase "mapMaybeWithKey" test_mapMaybeWithKey- , testCase "mapEither" test_mapEither- , testCase "mapEitherWithKey" test_mapEitherWithKey- , testCase "split" test_split- , testCase "splitLookup" test_splitLookup- , testCase "isSubmapOfBy" test_isSubmapOfBy- , testCase "isSubmapOf" test_isSubmapOf- , testCase "isProperSubmapOfBy" test_isProperSubmapOfBy- , testCase "isProperSubmapOf" test_isProperSubmapOf- , testCase "lookupIndex" test_lookupIndex- , testCase "findIndex" test_findIndex- , testCase "elemAt" test_elemAt- , testCase "updateAt" test_updateAt- , testCase "deleteAt" test_deleteAt- , testCase "findMin" test_findMin- , testCase "findMax" test_findMax- , testCase "deleteMin" test_deleteMin- , testCase "deleteMax" test_deleteMax- , testCase "deleteFindMin" test_deleteFindMin- , testCase "deleteFindMax" test_deleteFindMax- , testCase "updateMin" test_updateMin- , testCase "updateMax" test_updateMax- , testCase "updateMinWithKey" test_updateMinWithKey- , testCase "updateMaxWithKey" test_updateMaxWithKey- , testCase "minView" test_minView- , testCase "maxView" test_maxView- , testCase "minViewWithKey" test_minViewWithKey- , testCase "maxViewWithKey" test_maxViewWithKey- , testCase "valid" test_valid- , testProperty "fromList" prop_fromList- , testProperty "insert to singleton" prop_singleton- , testProperty "insert" prop_insert- , testProperty "insert then lookup" prop_insertLookup- , testProperty "insert then delete" prop_insertDelete- , testProperty "insert then delete2" prop_insertDelete2- , testProperty "delete non member" prop_deleteNonMember- , testProperty "deleteMin" prop_deleteMin- , testProperty "deleteMax" prop_deleteMax- , testProperty "split" prop_split- , testProperty "split then join" prop_join- , testProperty "split then merge" prop_merge- , testProperty "union" prop_union- , testProperty "union model" prop_unionModel- , testProperty "union singleton" prop_unionSingleton- , testProperty "union associative" prop_unionAssoc- , testProperty "union+unionWith" prop_unionWith- , testProperty "unionWith" prop_unionWith2- , testProperty "union sum" prop_unionSum- , testProperty "difference" prop_difference- , testProperty "difference model" prop_differenceModel- , testProperty "intersection" prop_intersection- , testProperty "intersection model" prop_intersectionModel- , testProperty "intersectionWith" prop_intersectionWith- , testProperty "intersectionWithModel" prop_intersectionWithModel- , testProperty "intersectionWithKey" prop_intersectionWithKey- , testProperty "intersectionWithKeyModel" prop_intersectionWithKeyModel- , testProperty "mergeWithKey model" prop_mergeWithKeyModel- , testProperty "fromAscList" prop_ordered- , testProperty "fromList then toList" prop_list- , testProperty "toDescList" prop_descList- , testProperty "toAscList+toDescList" prop_ascDescList- , testProperty "alter" prop_alter- , testProperty "index" prop_index- , testProperty "null" prop_null- , testProperty "member" prop_member- , testProperty "notmember" prop_notmember- , testProperty "lookup" prop_lookup- , testProperty "find" prop_find- , testProperty "findWithDefault" prop_findWithDefault- , testProperty "lookupLT" prop_lookupLT- , testProperty "lookupGT" prop_lookupGT- , testProperty "lookupLE" prop_lookupLE- , testProperty "lookupGE" prop_lookupGE- , testProperty "findIndex" prop_findIndex- , testProperty "lookupIndex" prop_lookupIndex- , testProperty "findMin" prop_findMin- , testProperty "findMax" prop_findMax- , testProperty "deleteMin" prop_deleteMinModel- , testProperty "deleteMax" prop_deleteMaxModel- , testProperty "filter" prop_filter- , testProperty "partition" prop_partition- , testProperty "map" prop_map- , testProperty "fmap" prop_fmap- , testProperty "mapkeys" prop_mapkeys- , testProperty "split" prop_splitModel- , testProperty "foldr" prop_foldr- , testProperty "foldr'" prop_foldr'- , testProperty "foldl" prop_foldl- , testProperty "foldl'" prop_foldl'- , testProperty "keysSet" prop_keysSet- , testProperty "fromSet" prop_fromSet- ] opts-- where- opts = mempty { ropt_test_options = Just $ mempty { topt_maximum_generated_tests = Just 500- , topt_maximum_unsuitable_generated_tests = Just 500- }- }--{--------------------------------------------------------------------- Arbitrary, reasonably balanced trees---------------------------------------------------------------------}-instance (Enum k,Arbitrary a) => Arbitrary (Map k a) where- arbitrary = sized (arbtree 0 maxkey)- where maxkey = 10^5-- arbtree :: (Enum k, Arbitrary a) => Int -> Int -> Int -> Gen (Map k a)- arbtree lo hi n = do t <- gentree lo hi n- if balanced t then return t else arbtree lo hi n- where gentree lo hi n- | n <= 0 = return Tip- | lo >= hi = return Tip- | otherwise = do{ x <- arbitrary- ; i <- choose (lo,hi)- ; m <- choose (1,70)- ; let (ml,mr) | m==(1::Int)= (1,2)- | m==2 = (2,1)- | m==3 = (1,1)- | otherwise = (2,2)- ; l <- gentree lo (i-1) (n `div` ml)- ; r <- gentree (i+1) hi (n `div` mr)- ; return (bin (toEnum i) x l r)- }----------------------------------------------------------------------------type UMap = Map Int ()-type IMap = Map Int Int-type SMap = Map Int String--------------------------------------------------------------------- Unit tests-------------------------------------------------------------------test_ticket4242 :: Assertion-test_ticket4242 = (valid $ deleteMin $ deleteMin $ fromList [ (i, ()) | i <- [0,2,5,1,6,4,8,9,7,11,10,3] :: [Int] ]) @?= True--------------------------------------------------------------------- Operators--test_index :: Assertion-test_index = fromList [(5,'a'), (3,'b')] ! 5 @?= 'a'--------------------------------------------------------------------- Query--test_size :: Assertion-test_size = do- null (empty) @?= True- null (singleton 1 'a') @?= False--test_size2 :: Assertion-test_size2 = do- size empty @?= 0- size (singleton 1 'a') @?= 1- size (fromList([(1,'a'), (2,'c'), (3,'b')])) @?= 3--test_member :: Assertion-test_member = do- member 5 (fromList [(5,'a'), (3,'b')]) @?= True- member 1 (fromList [(5,'a'), (3,'b')]) @?= False--test_notMember :: Assertion-test_notMember = do- notMember 5 (fromList [(5,'a'), (3,'b')]) @?= False- notMember 1 (fromList [(5,'a'), (3,'b')]) @?= True--test_lookup :: Assertion-test_lookup = do- employeeCurrency "John" @?= Just "Euro"- employeeCurrency "Pete" @?= Nothing- where- employeeDept = fromList([("John","Sales"), ("Bob","IT")])- deptCountry = fromList([("IT","USA"), ("Sales","France")])- countryCurrency = fromList([("USA", "Dollar"), ("France", "Euro")])- employeeCurrency :: String -> Maybe String- employeeCurrency name = do- dept <- lookup name employeeDept- country <- lookup dept deptCountry- lookup country countryCurrency--test_findWithDefault :: Assertion-test_findWithDefault = do- findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) @?= 'x'- findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) @?= 'a'--test_lookupLT :: Assertion-test_lookupLT = do- lookupLT 3 (fromList [(3,'a'), (5,'b')]) @?= Nothing- lookupLT 4 (fromList [(3,'a'), (5,'b')]) @?= Just (3, 'a')--test_lookupGT :: Assertion-test_lookupGT = do- lookupGT 4 (fromList [(3,'a'), (5,'b')]) @?= Just (5, 'b')- lookupGT 5 (fromList [(3,'a'), (5,'b')]) @?= Nothing--test_lookupLE :: Assertion-test_lookupLE = do- lookupLE 2 (fromList [(3,'a'), (5,'b')]) @?= Nothing- lookupLE 4 (fromList [(3,'a'), (5,'b')]) @?= Just (3, 'a')- lookupLE 5 (fromList [(3,'a'), (5,'b')]) @?= Just (5, 'b')--test_lookupGE :: Assertion-test_lookupGE = do- lookupGE 3 (fromList [(3,'a'), (5,'b')]) @?= Just (3, 'a')- lookupGE 4 (fromList [(3,'a'), (5,'b')]) @?= Just (5, 'b')- lookupGE 6 (fromList [(3,'a'), (5,'b')]) @?= Nothing--------------------------------------------------------------------- Construction--test_empty :: Assertion-test_empty = do- (empty :: UMap) @?= fromList []- size empty @?= 0--test_mempty :: Assertion-test_mempty = do- (mempty :: UMap) @?= fromList []- size (mempty :: UMap) @?= 0--test_singleton :: Assertion-test_singleton = do- singleton 1 'a' @?= fromList [(1, 'a')]- size (singleton 1 'a') @?= 1--test_insert :: Assertion-test_insert = do- insert 5 'x' (fromList [(5,'a'), (3,'b')]) @?= fromList [(3, 'b'), (5, 'x')]- insert 7 'x' (fromList [(5,'a'), (3,'b')]) @?= fromList [(3, 'b'), (5, 'a'), (7, 'x')]- insert 5 'x' empty @?= singleton 5 'x'--test_insertWith :: Assertion-test_insertWith = do- insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "xxxa")]- insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a"), (7, "xxx")]- insertWith (++) 5 "xxx" empty @?= singleton 5 "xxx"--test_insertWithKey :: Assertion-test_insertWithKey = do- insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "5:xxx|a")]- insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a"), (7, "xxx")]- insertWithKey f 5 "xxx" empty @?= singleton 5 "xxx"- where- f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--test_insertLookupWithKey :: Assertion-test_insertLookupWithKey = do- insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) @?= (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])- insertLookupWithKey f 2 "xxx" (fromList [(5,"a"), (3,"b")]) @?= (Nothing,fromList [(2,"xxx"),(3,"b"),(5,"a")])- insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) @?= (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])- insertLookupWithKey f 5 "xxx" empty @?= (Nothing, singleton 5 "xxx")- where- f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--------------------------------------------------------------------- Delete/Update--test_delete :: Assertion-test_delete = do- delete 5 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"- delete 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- delete 5 empty @?= (empty :: IMap)--test_adjust :: Assertion-test_adjust = do- adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "new a")]- adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- adjust ("new " ++) 7 empty @?= empty--test_adjustWithKey :: Assertion-test_adjustWithKey = do- adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "5:new a")]- adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- adjustWithKey f 7 empty @?= empty- where- f key x = (show key) ++ ":new " ++ x--test_update :: Assertion-test_update = do- update f 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "new a")]- update f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- update f 3 (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"- where- f x = if x == "a" then Just "new a" else Nothing--test_updateWithKey :: Assertion-test_updateWithKey = do- updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "5:new a")]- updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"- where- f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--test_updateLookupWithKey :: Assertion-test_updateLookupWithKey = do- updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) @?= (Just "5:new a", fromList [(3, "b"), (5, "5:new a")])- updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) @?= (Nothing, fromList [(3, "b"), (5, "a")])- updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) @?= (Just "b", singleton 5 "a")- where- f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--test_alter :: Assertion-test_alter = do- alter f 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a")]- alter f 5 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"- alter g 7 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "a"), (7, "c")]- alter g 5 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "c")]- where- f _ = Nothing- g _ = Just "c"--------------------------------------------------------------------- Combine--test_union :: Assertion-test_union = union (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "a"), (7, "C")]--test_mappend :: Assertion-test_mappend = mappend (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "a"), (7, "C")]--test_unionWith :: Assertion-test_unionWith = unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "aA"), (7, "C")]--test_unionWithKey :: Assertion-test_unionWithKey = unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= fromList [(3, "b"), (5, "5:a|A"), (7, "C")]- where- f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--test_unions :: Assertion-test_unions = do- unions [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]- @?= fromList [(3, "b"), (5, "a"), (7, "C")]- unions [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]- @?= fromList [(3, "B3"), (5, "A3"), (7, "C")]--test_mconcat :: Assertion-test_mconcat = do- mconcat [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]- @?= fromList [(3, "b"), (5, "a"), (7, "C")]- mconcat [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]- @?= fromList [(3, "B3"), (5, "A3"), (7, "C")]--test_unionsWith :: Assertion-test_unionsWith = unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]- @?= fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--test_difference :: Assertion-test_difference = difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 3 "b"--test_differenceWith :: Assertion-test_differenceWith = differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])- @?= singleton 3 "b:B"- where- f al ar = if al== "b" then Just (al ++ ":" ++ ar) else Nothing--test_differenceWithKey :: Assertion-test_differenceWithKey = differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])- @?= singleton 3 "3:b|B"- where- f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--test_intersection :: Assertion-test_intersection = intersection (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 5 "a"---test_intersectionWith :: Assertion-test_intersectionWith = intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 5 "aA"--test_intersectionWithKey :: Assertion-test_intersectionWithKey = intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) @?= singleton 5 "5:a|A"- where- f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--------------------------------------------------------------------- Traversal--test_map :: Assertion-test_map = map (++ "x") (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "bx"), (5, "ax")]--test_mapWithKey :: Assertion-test_mapWithKey = mapWithKey f (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "3:b"), (5, "5:a")]- where- f key x = (show key) ++ ":" ++ x--test_mapAccum :: Assertion-test_mapAccum = mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) @?= ("Everything: ba", fromList [(3, "bX"), (5, "aX")])- where- f a b = (a ++ b, b ++ "X")--test_mapAccumWithKey :: Assertion-test_mapAccumWithKey = mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) @?= ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])- where- f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--test_mapAccumRWithKey :: Assertion-test_mapAccumRWithKey = mapAccumRWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) @?= ("Everything: 5-a 3-b", fromList [(3, "bX"), (5, "aX")])- where- f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--test_mapKeys :: Assertion-test_mapKeys = do- mapKeys (+ 1) (fromList [(5,"a"), (3,"b")]) @?= fromList [(4, "b"), (6, "a")]- mapKeys (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 1 "c"- mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 3 "c"--test_mapKeysWith :: Assertion-test_mapKeysWith = do- mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 1 "cdab"- mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) @?= singleton 3 "cdab"--test_mapKeysMonotonic :: Assertion-test_mapKeysMonotonic = do- mapKeysMonotonic (+ 1) (fromList [(5,"a"), (3,"b")]) @?= fromList [(4, "b"), (6, "a")]- mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) @?= fromList [(6, "b"), (10, "a")]- valid (mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")])) @?= True- valid (mapKeysMonotonic (\ _ -> 1) (fromList [(5,"a"), (3,"b")])) @?= False--------------------------------------------------------------------- Conversion--test_elems :: Assertion-test_elems = do- elems (fromList [(5,"a"), (3,"b")]) @?= ["b","a"]- elems (empty :: UMap) @?= []--test_keys :: Assertion-test_keys = do- keys (fromList [(5,"a"), (3,"b")]) @?= [3,5]- keys (empty :: UMap) @?= []--test_assocs :: Assertion-test_assocs = do- assocs (fromList [(5,"a"), (3,"b")]) @?= [(3,"b"), (5,"a")]- assocs (empty :: UMap) @?= []--test_keysSet :: Assertion-test_keysSet = do- keysSet (fromList [(5,"a"), (3,"b")]) @?= Data.Set.fromList [3,5]- keysSet (empty :: UMap) @?= Data.Set.empty--test_fromSet :: Assertion-test_fromSet = do- fromSet (\k -> replicate k 'a') (Data.Set.fromList [3, 5]) @?= fromList [(5,"aaaaa"), (3,"aaa")]- fromSet undefined Data.Set.empty @?= (empty :: IMap)--------------------------------------------------------------------- Lists--test_toList :: Assertion-test_toList = do- toList (fromList [(5,"a"), (3,"b")]) @?= [(3,"b"), (5,"a")]- toList (empty :: SMap) @?= []--test_fromList :: Assertion-test_fromList = do- fromList [] @?= (empty :: SMap)- fromList [(5,"a"), (3,"b"), (5, "c")] @?= fromList [(5,"c"), (3,"b")]- fromList [(5,"c"), (3,"b"), (5, "a")] @?= fromList [(5,"a"), (3,"b")]--test_fromListWith :: Assertion-test_fromListWith = do- fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] @?= fromList [(3, "ab"), (5, "aba")]- fromListWith (++) [] @?= (empty :: SMap)--test_fromListWithKey :: Assertion-test_fromListWithKey = do- fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] @?= fromList [(3, "3ab"), (5, "5a5ba")]- fromListWithKey f [] @?= (empty :: SMap)- where- f k a1 a2 = (show k) ++ a1 ++ a2--------------------------------------------------------------------- Ordered lists--test_toAscList :: Assertion-test_toAscList = toAscList (fromList [(5,"a"), (3,"b")]) @?= [(3,"b"), (5,"a")]--test_toDescList :: Assertion-test_toDescList = toDescList (fromList [(5,"a"), (3,"b")]) @?= [(5,"a"), (3,"b")]--test_showTree :: Assertion-test_showTree =- (let t = fromDistinctAscList [(x,()) | x <- [1..5]]- in showTree t) @?= "4:=()\n+--2:=()\n| +--1:=()\n| +--3:=()\n+--5:=()\n"--test_showTree' :: Assertion-test_showTree' =- (let t = fromDistinctAscList [(x,()) | x <- [1..5]]- in s t ) @?= "+--5:=()\n|\n4:=()\n|\n| +--3:=()\n| |\n+--2:=()\n |\n +--1:=()\n"- where- showElem k x = show k ++ ":=" ++ show x-- s = showTreeWith showElem False True---test_fromAscList :: Assertion-test_fromAscList = do- fromAscList [(3,"b"), (5,"a")] @?= fromList [(3, "b"), (5, "a")]- fromAscList [(3,"b"), (5,"a"), (5,"b")] @?= fromList [(3, "b"), (5, "b")]- valid (fromAscList [(3,"b"), (5,"a"), (5,"b")]) @?= True- valid (fromAscList [(5,"a"), (3,"b"), (5,"b")]) @?= False--test_fromAscListWith :: Assertion-test_fromAscListWith = do- fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] @?= fromList [(3, "b"), (5, "ba")]- valid (fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")]) @?= True- valid (fromAscListWith (++) [(5,"a"), (3,"b"), (5,"b")]) @?= False--test_fromAscListWithKey :: Assertion-test_fromAscListWithKey = do- fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")] @?= fromList [(3, "b"), (5, "5:b5:ba")]- valid (fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")]) @?= True- valid (fromAscListWithKey f [(5,"a"), (3,"b"), (5,"b"), (5,"b")]) @?= False- where- f k a1 a2 = (show k) ++ ":" ++ a1 ++ a2--test_fromDistinctAscList :: Assertion-test_fromDistinctAscList = do- fromDistinctAscList [(3,"b"), (5,"a")] @?= fromList [(3, "b"), (5, "a")]- valid (fromDistinctAscList [(3,"b"), (5,"a")]) @?= True- valid (fromDistinctAscList [(3,"b"), (5,"a"), (5,"b")]) @?= False--------------------------------------------------------------------- Filter--test_filter :: Assertion-test_filter = do- filter (> "a") (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"- filter (> "x") (fromList [(5,"a"), (3,"b")]) @?= empty- filter (< "a") (fromList [(5,"a"), (3,"b")]) @?= empty--test_filteWithKey :: Assertion-test_filteWithKey = filterWithKey (\k _ -> k > 4) (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"--test_partition :: Assertion-test_partition = do- partition (> "a") (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", singleton 5 "a")- partition (< "x") (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3, "b"), (5, "a")], empty)- partition (> "x") (fromList [(5,"a"), (3,"b")]) @?= (empty, fromList [(3, "b"), (5, "a")])--test_partitionWithKey :: Assertion-test_partitionWithKey = do- partitionWithKey (\ k _ -> k > 3) (fromList [(5,"a"), (3,"b")]) @?= (singleton 5 "a", singleton 3 "b")- partitionWithKey (\ k _ -> k < 7) (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3, "b"), (5, "a")], empty)- partitionWithKey (\ k _ -> k > 7) (fromList [(5,"a"), (3,"b")]) @?= (empty, fromList [(3, "b"), (5, "a")])--test_mapMaybe :: Assertion-test_mapMaybe = mapMaybe f (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "new a"- where- f x = if x == "a" then Just "new a" else Nothing--test_mapMaybeWithKey :: Assertion-test_mapMaybeWithKey = mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "key : 3"- where- f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--test_mapEither :: Assertion-test_mapEither = do- mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])- mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= ((empty :: SMap), fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- where- f a = if a < "c" then Left a else Right a--test_mapEitherWithKey :: Assertion-test_mapEitherWithKey = do- mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])- mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])- @?= ((empty :: SMap), fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])- where- f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--test_split :: Assertion-test_split = do- split 2 (fromList [(5,"a"), (3,"b")]) @?= (empty, fromList [(3,"b"), (5,"a")])- split 3 (fromList [(5,"a"), (3,"b")]) @?= (empty, singleton 5 "a")- split 4 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", singleton 5 "a")- split 5 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", empty)- split 6 (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3,"b"), (5,"a")], empty)--test_splitLookup :: Assertion-test_splitLookup = do- splitLookup 2 (fromList [(5,"a"), (3,"b")]) @?= (empty, Nothing, fromList [(3,"b"), (5,"a")])- splitLookup 3 (fromList [(5,"a"), (3,"b")]) @?= (empty, Just "b", singleton 5 "a")- splitLookup 4 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", Nothing, singleton 5 "a")- splitLookup 5 (fromList [(5,"a"), (3,"b")]) @?= (singleton 3 "b", Just "a", empty)- splitLookup 6 (fromList [(5,"a"), (3,"b")]) @?= (fromList [(3,"b"), (5,"a")], Nothing, empty)--------------------------------------------------------------------- Submap--test_isSubmapOfBy :: Assertion-test_isSubmapOfBy = do- isSubmapOfBy (==) (fromList [('a',1)]) (fromList [('a',1),('b',2)]) @?= True- isSubmapOfBy (<=) (fromList [('a',1)]) (fromList [('a',1),('b',2)]) @?= True- isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1),('b',2)]) @?= True- isSubmapOfBy (==) (fromList [('a',2)]) (fromList [('a',1),('b',2)]) @?= False- isSubmapOfBy (<) (fromList [('a',1)]) (fromList [('a',1),('b',2)]) @?= False- isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1)]) @?= False--test_isSubmapOf :: Assertion-test_isSubmapOf = do- isSubmapOf (fromList [('a',1)]) (fromList [('a',1),('b',2)]) @?= True- isSubmapOf (fromList [('a',1),('b',2)]) (fromList [('a',1),('b',2)]) @?= True- isSubmapOf (fromList [('a',2)]) (fromList [('a',1),('b',2)]) @?= False- isSubmapOf (fromList [('a',1),('b',2)]) (fromList [('a',1)]) @?= False--test_isProperSubmapOfBy :: Assertion-test_isProperSubmapOfBy = do- isProperSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= True- isProperSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= True- isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)]) @?= False- isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)]) @?= False- isProperSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= False--test_isProperSubmapOf :: Assertion-test_isProperSubmapOf = do- isProperSubmapOf (fromList [(1,1)]) (fromList [(1,1),(2,2)]) @?= True- isProperSubmapOf (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)]) @?= False- isProperSubmapOf (fromList [(1,1),(2,2)]) (fromList [(1,1)]) @?= False--------------------------------------------------------------------- Indexed--test_lookupIndex :: Assertion-test_lookupIndex = do- isJust (lookupIndex 2 (fromList [(5,"a"), (3,"b")])) @?= False- fromJust (lookupIndex 3 (fromList [(5,"a"), (3,"b")])) @?= 0- fromJust (lookupIndex 5 (fromList [(5,"a"), (3,"b")])) @?= 1- isJust (lookupIndex 6 (fromList [(5,"a"), (3,"b")])) @?= False--test_findIndex :: Assertion-test_findIndex = do- findIndex 3 (fromList [(5,"a"), (3,"b")]) @?= 0- findIndex 5 (fromList [(5,"a"), (3,"b")]) @?= 1--test_elemAt :: Assertion-test_elemAt = do- elemAt 0 (fromList [(5,"a"), (3,"b")]) @?= (3,"b")- elemAt 1 (fromList [(5,"a"), (3,"b")]) @?= (5, "a")--test_updateAt :: Assertion-test_updateAt = do- updateAt (\ _ _ -> Just "x") 0 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "x"), (5, "a")]- updateAt (\ _ _ -> Just "x") 1 (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "x")]- updateAt (\_ _ -> Nothing) 0 (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"- updateAt (\_ _ -> Nothing) 1 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--- updateAt (\_ _ -> Nothing) 7 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--test_deleteAt :: Assertion-test_deleteAt = do- deleteAt 0 (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"- deleteAt 1 (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--------------------------------------------------------------------- Min/Max--test_findMin :: Assertion-test_findMin = findMin (fromList [(5,"a"), (3,"b")]) @?= (3,"b")--test_findMax :: Assertion-test_findMax = findMax (fromList [(5,"a"), (3,"b")]) @?= (5,"a")--test_deleteMin :: Assertion-test_deleteMin = do- deleteMin (fromList [(5,"a"), (3,"b"), (7,"c")]) @?= fromList [(5,"a"), (7,"c")]- deleteMin (empty :: SMap) @?= empty--test_deleteMax :: Assertion-test_deleteMax = do- deleteMax (fromList [(5,"a"), (3,"b"), (7,"c")]) @?= fromList [(3,"b"), (5,"a")]- deleteMax (empty :: SMap) @?= empty--test_deleteFindMin :: Assertion-test_deleteFindMin = deleteFindMin (fromList [(5,"a"), (3,"b"), (10,"c")]) @?= ((3,"b"), fromList[(5,"a"), (10,"c")])--test_deleteFindMax :: Assertion-test_deleteFindMax = deleteFindMax (fromList [(5,"a"), (3,"b"), (10,"c")]) @?= ((10,"c"), fromList [(3,"b"), (5,"a")])--test_updateMin :: Assertion-test_updateMin = do- updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "Xb"), (5, "a")]- updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"--test_updateMax :: Assertion-test_updateMax = do- updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3, "b"), (5, "Xa")]- updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--test_updateMinWithKey :: Assertion-test_updateMinWithKey = do- updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3,"3:b"), (5,"a")]- updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 5 "a"--test_updateMaxWithKey :: Assertion-test_updateMaxWithKey = do- updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) @?= fromList [(3,"b"), (5,"5:a")]- updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) @?= singleton 3 "b"--test_minView :: Assertion-test_minView = do- minView (fromList [(5,"a"), (3,"b")]) @?= Just ("b", singleton 5 "a")- minView (empty :: SMap) @?= Nothing--test_maxView :: Assertion-test_maxView = do- maxView (fromList [(5,"a"), (3,"b")]) @?= Just ("a", singleton 3 "b")- maxView (empty :: SMap) @?= Nothing--test_minViewWithKey :: Assertion-test_minViewWithKey = do- minViewWithKey (fromList [(5,"a"), (3,"b")]) @?= Just ((3,"b"), singleton 5 "a")- minViewWithKey (empty :: SMap) @?= Nothing--test_maxViewWithKey :: Assertion-test_maxViewWithKey = do- maxViewWithKey (fromList [(5,"a"), (3,"b")]) @?= Just ((5,"a"), singleton 3 "b")- maxViewWithKey (empty :: SMap) @?= Nothing--------------------------------------------------------------------- Debug--test_valid :: Assertion-test_valid = do- valid (fromAscList [(3,"b"), (5,"a")]) @?= True- valid (fromAscList [(5,"a"), (3,"b")]) @?= False--------------------------------------------------------------------- QuickCheck-------------------------------------------------------------------prop_fromList :: UMap -> Bool-prop_fromList t = valid t--prop_singleton :: Int -> Int -> Bool-prop_singleton k x = insert k x empty == singleton k x--prop_insert :: Int -> UMap -> Bool-prop_insert k t = valid $ insert k () t--prop_insertLookup :: Int -> UMap -> Bool-prop_insertLookup k t = lookup k (insert k () t) /= Nothing--prop_insertDelete :: Int -> UMap -> Bool-prop_insertDelete k t = valid $ delete k (insert k () t)--prop_insertDelete2 :: Int -> UMap -> Property-prop_insertDelete2 k t = (lookup k t == Nothing) ==> (delete k (insert k () t) == t)--prop_deleteNonMember :: Int -> UMap -> Property-prop_deleteNonMember k t = (lookup k t == Nothing) ==> (delete k t == t)--prop_deleteMin :: UMap -> Bool-prop_deleteMin t = valid $ deleteMin $ deleteMin t--prop_deleteMax :: UMap -> Bool-prop_deleteMax t = valid $ deleteMax $ deleteMax t--------------------------------------------------------------------prop_split :: Int -> UMap -> Bool-prop_split k t = let (r,l) = split k t- in (valid r, valid l) == (True, True)--prop_join :: Int -> UMap -> Bool-prop_join k t = let (l,r) = split k t- in valid (join k () l r)--prop_merge :: Int -> UMap -> Bool-prop_merge k t = let (l,r) = split k t- in valid (merge l r)--------------------------------------------------------------------prop_union :: UMap -> UMap -> Bool-prop_union t1 t2 = valid (union t1 t2)--prop_unionModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_unionModel xs ys- = sort (keys (union (fromList xs) (fromList ys)))- == sort (nub (Prelude.map fst xs ++ Prelude.map fst ys))--prop_unionSingleton :: IMap -> Int -> Int -> Bool-prop_unionSingleton t k x = union (singleton k x) t == insert k x t--prop_unionAssoc :: IMap -> IMap -> IMap -> Bool-prop_unionAssoc t1 t2 t3 = union t1 (union t2 t3) == union (union t1 t2) t3--prop_unionWith :: IMap -> IMap -> Bool-prop_unionWith t1 t2 = (union t1 t2 == unionWith (\_ y -> y) t2 t1)--prop_unionWith2 :: IMap -> IMap -> Bool-prop_unionWith2 t1 t2 = valid (unionWithKey (\_ x y -> x+y) t1 t2)--prop_unionSum :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_unionSum xs ys- = sum (elems (unionWith (+) (fromListWith (+) xs) (fromListWith (+) ys)))- == (sum (Prelude.map snd xs) + sum (Prelude.map snd ys))--prop_difference :: IMap -> IMap -> Bool-prop_difference t1 t2 = valid (difference t1 t2)--prop_differenceModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_differenceModel xs ys- = sort (keys (difference (fromListWith (+) xs) (fromListWith (+) ys)))- == sort ((List.\\) (nub (Prelude.map fst xs)) (nub (Prelude.map fst ys)))--prop_intersection :: IMap -> IMap -> Bool-prop_intersection t1 t2 = valid (intersection t1 t2)--prop_intersectionModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_intersectionModel xs ys- = sort (keys (intersection (fromListWith (+) xs) (fromListWith (+) ys)))- == sort (nub ((List.intersect) (Prelude.map fst xs) (Prelude.map fst ys)))--prop_intersectionWith :: (Int -> Int -> Maybe Int) -> IMap -> IMap -> Bool-prop_intersectionWith f t1 t2 = valid (intersectionWith f t1 t2)--prop_intersectionWithModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_intersectionWithModel xs ys- = toList (intersectionWith f (fromList xs') (fromList ys'))- == [(kx, f vx vy) | (kx, vx) <- List.sort xs', (ky, vy) <- ys', kx == ky]- where xs' = List.nubBy ((==) `on` fst) xs- ys' = List.nubBy ((==) `on` fst) ys- f l r = l + 2 * r--prop_intersectionWithKey :: (Int -> Int -> Int -> Maybe Int) -> IMap -> IMap -> Bool-prop_intersectionWithKey f t1 t2 = valid (intersectionWithKey f t1 t2)--prop_intersectionWithKeyModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_intersectionWithKeyModel xs ys- = toList (intersectionWithKey f (fromList xs') (fromList ys'))- == [(kx, f kx vx vy) | (kx, vx) <- List.sort xs', (ky, vy) <- ys', kx == ky]- where xs' = List.nubBy ((==) `on` fst) xs- ys' = List.nubBy ((==) `on` fst) ys- f k l r = k + 2 * l + 3 * r--prop_mergeWithKeyModel :: [(Int,Int)] -> [(Int,Int)] -> Bool-prop_mergeWithKeyModel xs ys- = and [ testMergeWithKey f keep_x keep_y- | f <- [ \_k x1 _x2 -> Just x1- , \_k _x1 x2 -> Just x2- , \_k _x1 _x2 -> Nothing- , \k x1 x2 -> if k `mod` 2 == 0 then Nothing else Just (2 * x1 + 3 * x2)- ]- , keep_x <- [ True, False ]- , keep_y <- [ True, False ]- ]-- where xs' = List.nubBy ((==) `on` fst) xs- ys' = List.nubBy ((==) `on` fst) ys-- xm = fromList xs'- ym = fromList ys'-- testMergeWithKey f keep_x keep_y- = toList (mergeWithKey f (keep keep_x) (keep keep_y) xm ym) == emulateMergeWithKey f keep_x keep_y- where keep False _ = empty- keep True m = m-- emulateMergeWithKey f keep_x keep_y- = Maybe.mapMaybe combine (sort $ List.union (List.map fst xs') (List.map fst ys'))- where combine k = case (List.lookup k xs', List.lookup k ys') of- (Nothing, Just y) -> if keep_y then Just (k, y) else Nothing- (Just x, Nothing) -> if keep_x then Just (k, x) else Nothing- (Just x, Just y) -> (\v -> (k, v)) `fmap` f k x y-- -- We prevent inlining testMergeWithKey to disable the SpecConstr- -- optimalization. There are too many call patterns here so several- -- warnings are issued if testMergeWithKey gets inlined.- {-# NOINLINE testMergeWithKey #-}--------------------------------------------------------------------prop_ordered :: Property-prop_ordered- = forAll (choose (5,100)) $ \n ->- let xs = [(x,()) | x <- [0..n::Int]]- in fromAscList xs == fromList xs--prop_list :: [Int] -> Bool-prop_list xs = (sort (nub xs) == [x | (x,()) <- toList (fromList [(x,()) | x <- xs])])--prop_descList :: [Int] -> Bool-prop_descList xs = (reverse (sort (nub xs)) == [x | (x,()) <- toDescList (fromList [(x,()) | x <- xs])])--prop_ascDescList :: [Int] -> Bool-prop_ascDescList xs = toAscList m == reverse (toDescList m)- where m = fromList $ zip xs $ repeat ()--------------------------------------------------------------------prop_alter :: UMap -> Int -> Bool-prop_alter t k = balanced t' && case lookup k t of- Just _ -> (size t - 1) == size t' && lookup k t' == Nothing- Nothing -> (size t + 1) == size t' && lookup k t' /= Nothing- where- t' = alter f k t- f Nothing = Just ()- f (Just ()) = Nothing----------------------------------------------------------------------------- Compare against the list model (after nub on keys)--prop_index :: [Int] -> Property-prop_index xs = length xs > 0 ==>- let m = fromList (zip xs xs)- in xs == [ m ! i | i <- xs ]--prop_null :: IMap -> Bool-prop_null m = null m == (size m == 0)--prop_member :: [Int] -> Int -> Bool-prop_member xs n =- let m = fromList (zip xs xs)- in all (\k -> k `member` m == (k `elem` xs)) (n : xs)--prop_notmember :: [Int] -> Int -> Bool-prop_notmember xs n =- let m = fromList (zip xs xs)- in all (\k -> k `notMember` m == (k `notElem` xs)) (n : xs)--prop_lookup :: [(Int, Int)] -> Int -> Bool-prop_lookup xs n =- let xs' = List.nubBy ((==) `on` fst) xs- m = fromList xs'- in all (\k -> lookup k m == List.lookup k xs') (n : List.map fst xs')--prop_find :: [(Int, Int)] -> Bool-prop_find xs =- let xs' = List.nubBy ((==) `on` fst) xs- m = fromList xs'- in all (\(k, v) -> m ! k == v) xs'--prop_findWithDefault :: [(Int, Int)] -> Int -> Int -> Bool-prop_findWithDefault xs n x =- let xs' = List.nubBy ((==) `on` fst) xs- m = fromList xs'- in all (\k -> findWithDefault x k m == maybe x id (List.lookup k xs')) (n : List.map fst xs')--test_lookupSomething :: (Int -> Map Int Int -> Maybe (Int, Int)) -> (Int -> Int -> Bool) -> [(Int, Int)] -> Bool-test_lookupSomething lookup' cmp xs =- let odd_sorted_xs = filter_odd $ sort $ List.nubBy ((==) `on` fst) xs- t = fromList odd_sorted_xs- test k = case List.filter ((`cmp` k) . fst) odd_sorted_xs of- [] -> lookup' k t == Nothing- cs | 0 `cmp` 1 -> lookup' k t == Just (last cs) -- we want largest such element- | otherwise -> lookup' k t == Just (head cs) -- we want smallest such element- in all test (List.map fst xs)-- where filter_odd [] = []- filter_odd [_] = []- filter_odd (_ : o : xs) = o : filter_odd xs--prop_lookupLT :: [(Int, Int)] -> Bool-prop_lookupLT = test_lookupSomething lookupLT (<)--prop_lookupGT :: [(Int, Int)] -> Bool-prop_lookupGT = test_lookupSomething lookupGT (>)--prop_lookupLE :: [(Int, Int)] -> Bool-prop_lookupLE = test_lookupSomething lookupLE (<=)--prop_lookupGE :: [(Int, Int)] -> Bool-prop_lookupGE = test_lookupSomething lookupGE (>=)--prop_findIndex :: [(Int, Int)] -> Property-prop_findIndex ys = length ys > 0 ==>- let m = fromList ys- in findIndex (fst (head ys)) m `seq` True--prop_lookupIndex :: [(Int, Int)] -> Property-prop_lookupIndex ys = length ys > 0 ==>- let m = fromList ys- in isJust (lookupIndex (fst (head ys)) m)--prop_findMin :: [(Int, Int)] -> Property-prop_findMin ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in findMin m == List.minimumBy (comparing fst) xs--prop_findMax :: [(Int, Int)] -> Property-prop_findMax ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in findMax m == List.maximumBy (comparing fst) xs--prop_deleteMinModel :: [(Int, Int)] -> Property-prop_deleteMinModel ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in toAscList (deleteMin m) == tail (sort xs)--prop_deleteMaxModel :: [(Int, Int)] -> Property-prop_deleteMaxModel ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in toAscList (deleteMax m) == init (sort xs)--prop_filter :: (Int -> Bool) -> [(Int, Int)] -> Property-prop_filter p ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in filter p m == fromList (List.filter (p . snd) xs)--prop_partition :: (Int -> Bool) -> [(Int, Int)] -> Property-prop_partition p ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in partition p m == let (a,b) = (List.partition (p . snd) xs) in (fromList a, fromList b)--prop_map :: (Int -> Int) -> [(Int, Int)] -> Property-prop_map f ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in map f m == fromList [ (a, f b) | (a,b) <- xs ]--prop_fmap :: (Int -> Int) -> [(Int, Int)] -> Property-prop_fmap f ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in fmap f m == fromList [ (a, f b) | (a,b) <- xs ]--prop_mapkeys :: (Int -> Int) -> [(Int, Int)] -> Property-prop_mapkeys f ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in mapKeys f m == (fromList $ List.nubBy ((==) `on` fst) $ reverse [ (f a, b) | (a,b) <- sort xs])--prop_splitModel :: Int -> [(Int, Int)] -> Property-prop_splitModel n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- (l, r) = split n $ fromList xs- in toAscList l == sort [(k, v) | (k,v) <- xs, k < n] &&- toAscList r == sort [(k, v) | (k,v) <- xs, k > n]--prop_foldr :: Int -> [(Int, Int)] -> Property-prop_foldr n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldr (+) n m == List.foldr (+) n (List.map snd xs) &&- foldr (:) [] m == List.map snd (List.sort xs) &&- foldrWithKey (\_ a b -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldrWithKey (\k _ b -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldrWithKey (\k x xs -> (k,x):xs) [] m == List.sort xs---prop_foldr' :: Int -> [(Int, Int)] -> Property-prop_foldr' n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldr' (+) n m == List.foldr (+) n (List.map snd xs) &&- foldr' (:) [] m == List.map snd (List.sort xs) &&- foldrWithKey' (\_ a b -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldrWithKey' (\k _ b -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldrWithKey' (\k x xs -> (k,x):xs) [] m == List.sort xs--prop_foldl :: Int -> [(Int, Int)] -> Property-prop_foldl n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldl (+) n m == List.foldr (+) n (List.map snd xs) &&- foldl (flip (:)) [] m == reverse (List.map snd (List.sort xs)) &&- foldlWithKey (\b _ a -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldlWithKey (\b k _ -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldlWithKey (\xs k x -> (k,x):xs) [] m == reverse (List.sort xs)--prop_foldl' :: Int -> [(Int, Int)] -> Property-prop_foldl' n ys = length ys > 0 ==>- let xs = List.nubBy ((==) `on` fst) ys- m = fromList xs- in foldl' (+) n m == List.foldr (+) n (List.map snd xs) &&- foldl' (flip (:)) [] m == reverse (List.map snd (List.sort xs)) &&- foldlWithKey' (\b _ a -> a + b) n m == List.foldr (+) n (List.map snd xs) &&- foldlWithKey' (\b k _ -> k + b) n m == List.foldr (+) n (List.map fst xs) &&- foldlWithKey' (\xs k x -> (k,x):xs) [] m == reverse (List.sort xs)--prop_keysSet :: [(Int, Int)] -> Bool-prop_keysSet xs =- keysSet (fromList xs) == Data.Set.fromList (List.map fst xs)--prop_fromSet :: [(Int, Int)] -> Bool-prop_fromSet ys =- let xs = List.nubBy ((==) `on` fst) ys- in fromSet (\k -> fromJust $ List.lookup k xs) (Data.Set.fromList $ List.map fst xs) == fromList xs
@@ -1,598 +0,0 @@-import Data.Sequence -- needs to be compiled with -DTESTING for use here--import Control.Applicative (Applicative(..))-import Control.Arrow ((***))-import Data.Foldable (Foldable(..), toList, all, sum)-import Data.Functor ((<$>), (<$))-import Data.Maybe-import Data.Monoid (Monoid(..))-import Data.Traversable (Traversable(traverse), sequenceA)-import Prelude hiding (- null, length, take, drop, splitAt,- foldl, foldl1, foldr, foldr1, scanl, scanl1, scanr, scanr1,- filter, reverse, replicate, zip, zipWith, zip3, zipWith3,- all, sum)-import qualified Prelude-import qualified Data.List-import Test.QuickCheck hiding ((><))-import Test.QuickCheck.Poly-import Test.Framework-import Test.Framework.Providers.QuickCheck2---main :: IO ()-main = defaultMainWithOpts- [ testProperty "fmap" prop_fmap- , testProperty "(<$)" prop_constmap- , testProperty "foldr" prop_foldr- , testProperty "foldr1" prop_foldr1- , testProperty "foldl" prop_foldl- , testProperty "foldl1" prop_foldl1- , testProperty "(==)" prop_equals- , testProperty "compare" prop_compare- , testProperty "mappend" prop_mappend- , testProperty "singleton" prop_singleton- , testProperty "(<|)" prop_cons- , testProperty "(|>)" prop_snoc- , testProperty "(><)" prop_append- , testProperty "fromList" prop_fromList- , testProperty "replicate" prop_replicate- , testProperty "replicateA" prop_replicateA- , testProperty "replicateM" prop_replicateM- , testProperty "iterateN" prop_iterateN- , testProperty "unfoldr" prop_unfoldr- , testProperty "unfoldl" prop_unfoldl- , testProperty "null" prop_null- , testProperty "length" prop_length- , testProperty "viewl" prop_viewl- , testProperty "viewr" prop_viewr- , testProperty "scanl" prop_scanl- , testProperty "scanl1" prop_scanl1- , testProperty "scanr" prop_scanr- , testProperty "scanr1" prop_scanr1- , testProperty "tails" prop_tails- , testProperty "inits" prop_inits- , testProperty "takeWhileL" prop_takeWhileL- , testProperty "takeWhileR" prop_takeWhileR- , testProperty "dropWhileL" prop_dropWhileL- , testProperty "dropWhileR" prop_dropWhileR- , testProperty "spanl" prop_spanl- , testProperty "spanr" prop_spanr- , testProperty "breakl" prop_breakl- , testProperty "breakr" prop_breakr- , testProperty "partition" prop_partition- , testProperty "filter" prop_filter- , testProperty "sort" prop_sort- , testProperty "sortBy" prop_sortBy- , testProperty "unstableSort" prop_unstableSort- , testProperty "unstableSortBy" prop_unstableSortBy- , testProperty "index" prop_index- , testProperty "adjust" prop_adjust- , testProperty "update" prop_update- , testProperty "take" prop_take- , testProperty "drop" prop_drop- , testProperty "splitAt" prop_splitAt- , testProperty "elemIndexL" prop_elemIndexL- , testProperty "elemIndicesL" prop_elemIndicesL- , testProperty "elemIndexR" prop_elemIndexR- , testProperty "elemIndicesR" prop_elemIndicesR- , testProperty "findIndexL" prop_findIndexL- , testProperty "findIndicesL" prop_findIndicesL- , testProperty "findIndexR" prop_findIndexR- , testProperty "findIndicesR" prop_findIndicesR- , testProperty "foldlWithIndex" prop_foldlWithIndex- , testProperty "foldrWithIndex" prop_foldrWithIndex- , testProperty "mapWithIndex" prop_mapWithIndex- , testProperty "reverse" prop_reverse- , testProperty "zip" prop_zip- , testProperty "zipWith" prop_zipWith- , testProperty "zip3" prop_zip3- , testProperty "zipWith3" prop_zipWith3- , testProperty "zip4" prop_zip4- , testProperty "zipWith4" prop_zipWith4- ] opts-- where- opts = mempty { ropt_test_options = Just $ mempty { topt_maximum_generated_tests = Just 500- , topt_maximum_unsuitable_generated_tests = Just 500- }- }----------------------------------------------------------------------------- Arbitrary---------------------------------------------------------------------------instance Arbitrary a => Arbitrary (Seq a) where- arbitrary = Seq <$> arbitrary- shrink (Seq x) = map Seq (shrink x)--instance Arbitrary a => Arbitrary (Elem a) where- arbitrary = Elem <$> arbitrary--instance (Arbitrary a, Sized a) => Arbitrary (FingerTree a) where- arbitrary = sized arb- where- arb :: (Arbitrary a, Sized a) => Int -> Gen (FingerTree a)- arb 0 = return Empty- arb 1 = Single <$> arbitrary- arb n = deep <$> arbitrary <*> arb (n `div` 2) <*> arbitrary-- shrink (Deep _ (One a) Empty (One b)) = [Single a, Single b]- shrink (Deep _ pr m sf) =- [deep pr' m sf | pr' <- shrink pr] ++- [deep pr m' sf | m' <- shrink m] ++- [deep pr m sf' | sf' <- shrink sf]- shrink (Single x) = map Single (shrink x)- shrink Empty = []--instance (Arbitrary a, Sized a) => Arbitrary (Node a) where- arbitrary = oneof [- node2 <$> arbitrary <*> arbitrary,- node3 <$> arbitrary <*> arbitrary <*> arbitrary]-- shrink (Node2 _ a b) =- [node2 a' b | a' <- shrink a] ++- [node2 a b' | b' <- shrink b]- shrink (Node3 _ a b c) =- [node2 a b, node2 a c, node2 b c] ++- [node3 a' b c | a' <- shrink a] ++- [node3 a b' c | b' <- shrink b] ++- [node3 a b c' | c' <- shrink c]--instance Arbitrary a => Arbitrary (Digit a) where- arbitrary = oneof [- One <$> arbitrary,- Two <$> arbitrary <*> arbitrary,- Three <$> arbitrary <*> arbitrary <*> arbitrary,- Four <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary]-- shrink (One a) = map One (shrink a)- shrink (Two a b) = [One a, One b]- shrink (Three a b c) = [Two a b, Two a c, Two b c]- shrink (Four a b c d) = [Three a b c, Three a b d, Three a c d, Three b c d]----------------------------------------------------------------------------- Valid trees---------------------------------------------------------------------------class Valid a where- valid :: a -> Bool--instance Valid (Elem a) where- valid _ = True--instance Valid (Seq a) where- valid (Seq xs) = valid xs--instance (Sized a, Valid a) => Valid (FingerTree a) where- valid Empty = True- valid (Single x) = valid x- valid (Deep s pr m sf) =- s == size pr + size m + size sf && valid pr && valid m && valid sf--instance (Sized a, Valid a) => Valid (Node a) where- valid node = size node == sum (fmap size node) && all valid node--instance Valid a => Valid (Digit a) where- valid = all valid--{--------------------------------------------------------------------- The general plan is to compare each function with a list equivalent.- Each operation should produce a valid tree representing the same- sequence as produced by its list counterpart on corresponding inputs.- (The list versions are often lazier, but these properties ignore- strictness.)---------------------------------------------------------------------}---- utilities for partial conversions--infix 4 ~=--(~=) :: Eq a => Maybe a -> a -> Bool-(~=) = maybe (const False) (==)---- Partial conversion of an output sequence to a list.-toList' :: Seq a -> Maybe [a]-toList' xs- | valid xs = Just (toList xs)- | otherwise = Nothing--toListList' :: Seq (Seq a) -> Maybe [[a]]-toListList' xss = toList' xss >>= mapM toList'--toListPair' :: (Seq a, Seq b) -> Maybe ([a], [b])-toListPair' (xs, ys) = (,) <$> toList' xs <*> toList' ys---- instances--prop_fmap :: Seq Int -> Bool-prop_fmap xs =- toList' (fmap f xs) ~= map f (toList xs)- where f = (+100)--prop_constmap :: A -> Seq A -> Bool-prop_constmap x xs =- toList' (x <$ xs) ~= map (const x) (toList xs)--prop_foldr :: Seq A -> Bool-prop_foldr xs =- foldr f z xs == Prelude.foldr f z (toList xs)- where- f = (:)- z = []--prop_foldr1 :: Seq Int -> Property-prop_foldr1 xs =- not (null xs) ==> foldr1 f xs == Data.List.foldr1 f (toList xs)- where f = (-)--prop_foldl :: Seq A -> Bool-prop_foldl xs =- foldl f z xs == Prelude.foldl f z (toList xs)- where- f = flip (:)- z = []--prop_foldl1 :: Seq Int -> Property-prop_foldl1 xs =- not (null xs) ==> foldl1 f xs == Data.List.foldl1 f (toList xs)- where f = (-)--prop_equals :: Seq OrdA -> Seq OrdA -> Bool-prop_equals xs ys =- (xs == ys) == (toList xs == toList ys)--prop_compare :: Seq OrdA -> Seq OrdA -> Bool-prop_compare xs ys =- compare xs ys == compare (toList xs) (toList ys)--prop_mappend :: Seq A -> Seq A -> Bool-prop_mappend xs ys =- toList' (mappend xs ys) ~= toList xs ++ toList ys---- * Construction--{-- toList' empty ~= []--}--prop_singleton :: A -> Bool-prop_singleton x =- toList' (singleton x) ~= [x]--prop_cons :: A -> Seq A -> Bool-prop_cons x xs =- toList' (x <| xs) ~= x : toList xs--prop_snoc :: Seq A -> A -> Bool-prop_snoc xs x =- toList' (xs |> x) ~= toList xs ++ [x]--prop_append :: Seq A -> Seq A -> Bool-prop_append xs ys =- toList' (xs >< ys) ~= toList xs ++ toList ys--prop_fromList :: [A] -> Bool-prop_fromList xs =- toList' (fromList xs) ~= xs---- ** Repetition--prop_replicate :: NonNegative Int -> A -> Bool-prop_replicate (NonNegative m) x =- toList' (replicate n x) ~= Prelude.replicate n x- where n = m `mod` 10000--prop_replicateA :: NonNegative Int -> Bool-prop_replicateA (NonNegative m) =- traverse toList' (replicateA n a) ~= sequenceA (Prelude.replicate n a)- where- n = m `mod` 10000- a = Action 1 0 :: M Int--prop_replicateM :: NonNegative Int -> Bool-prop_replicateM (NonNegative m) =- traverse toList' (replicateM n a) ~= sequence (Prelude.replicate n a)- where- n = m `mod` 10000- a = Action 1 0 :: M Int---- ** Iterative construction--prop_iterateN :: NonNegative Int -> Int -> Bool-prop_iterateN (NonNegative m) x =- toList' (iterateN n f x) ~= Prelude.take n (Prelude.iterate f x)- where- n = m `mod` 10000- f = (+1)--prop_unfoldr :: [A] -> Bool-prop_unfoldr z =- toList' (unfoldr f z) ~= Data.List.unfoldr f z- where- f [] = Nothing- f (x:xs) = Just (x, xs)--prop_unfoldl :: [A] -> Bool-prop_unfoldl z =- toList' (unfoldl f z) ~= Data.List.reverse (Data.List.unfoldr (fmap swap . f) z)- where- f [] = Nothing- f (x:xs) = Just (xs, x)- swap (x,y) = (y,x)---- * Deconstruction---- ** Queries--prop_null :: Seq A -> Bool-prop_null xs =- null xs == Prelude.null (toList xs)--prop_length :: Seq A -> Bool-prop_length xs =- length xs == Prelude.length (toList xs)---- ** Views--prop_viewl :: Seq A -> Bool-prop_viewl xs =- case viewl xs of- EmptyL -> Prelude.null (toList xs)- x :< xs' -> valid xs' && toList xs == x : toList xs'--prop_viewr :: Seq A -> Bool-prop_viewr xs =- case viewr xs of- EmptyR -> Prelude.null (toList xs)- xs' :> x -> valid xs' && toList xs == toList xs' ++ [x]---- * Scans--prop_scanl :: [A] -> Seq A -> Bool-prop_scanl z xs =- toList' (scanl f z xs) ~= Data.List.scanl f z (toList xs)- where f = flip (:)--prop_scanl1 :: Seq Int -> Property-prop_scanl1 xs =- not (null xs) ==> toList' (scanl1 f xs) ~= Data.List.scanl1 f (toList xs)- where f = (-)--prop_scanr :: [A] -> Seq A -> Bool-prop_scanr z xs =- toList' (scanr f z xs) ~= Data.List.scanr f z (toList xs)- where f = (:)--prop_scanr1 :: Seq Int -> Property-prop_scanr1 xs =- not (null xs) ==> toList' (scanr1 f xs) ~= Data.List.scanr1 f (toList xs)- where f = (-)---- * Sublists--prop_tails :: Seq A -> Bool-prop_tails xs =- toListList' (tails xs) ~= Data.List.tails (toList xs)--prop_inits :: Seq A -> Bool-prop_inits xs =- toListList' (inits xs) ~= Data.List.inits (toList xs)---- ** Sequential searches--- We use predicates with varying density.--prop_takeWhileL :: Positive Int -> Seq Int -> Bool-prop_takeWhileL (Positive n) xs =- toList' (takeWhileL p xs) ~= Prelude.takeWhile p (toList xs)- where p x = x `mod` n == 0--prop_takeWhileR :: Positive Int -> Seq Int -> Bool-prop_takeWhileR (Positive n) xs =- toList' (takeWhileR p xs) ~= Prelude.reverse (Prelude.takeWhile p (Prelude.reverse (toList xs)))- where p x = x `mod` n == 0--prop_dropWhileL :: Positive Int -> Seq Int -> Bool-prop_dropWhileL (Positive n) xs =- toList' (dropWhileL p xs) ~= Prelude.dropWhile p (toList xs)- where p x = x `mod` n == 0--prop_dropWhileR :: Positive Int -> Seq Int -> Bool-prop_dropWhileR (Positive n) xs =- toList' (dropWhileR p xs) ~= Prelude.reverse (Prelude.dropWhile p (Prelude.reverse (toList xs)))- where p x = x `mod` n == 0--prop_spanl :: Positive Int -> Seq Int -> Bool-prop_spanl (Positive n) xs =- toListPair' (spanl p xs) ~= Data.List.span p (toList xs)- where p x = x `mod` n == 0--prop_spanr :: Positive Int -> Seq Int -> Bool-prop_spanr (Positive n) xs =- toListPair' (spanr p xs) ~= (Prelude.reverse *** Prelude.reverse) (Data.List.span p (Prelude.reverse (toList xs)))- where p x = x `mod` n == 0--prop_breakl :: Positive Int -> Seq Int -> Bool-prop_breakl (Positive n) xs =- toListPair' (breakl p xs) ~= Data.List.break p (toList xs)- where p x = x `mod` n == 0--prop_breakr :: Positive Int -> Seq Int -> Bool-prop_breakr (Positive n) xs =- toListPair' (breakr p xs) ~= (Prelude.reverse *** Prelude.reverse) (Data.List.break p (Prelude.reverse (toList xs)))- where p x = x `mod` n == 0--prop_partition :: Positive Int -> Seq Int -> Bool-prop_partition (Positive n) xs =- toListPair' (partition p xs) ~= Data.List.partition p (toList xs)- where p x = x `mod` n == 0--prop_filter :: Positive Int -> Seq Int -> Bool-prop_filter (Positive n) xs =- toList' (filter p xs) ~= Prelude.filter p (toList xs)- where p x = x `mod` n == 0---- * Sorting--prop_sort :: Seq OrdA -> Bool-prop_sort xs =- toList' (sort xs) ~= Data.List.sort (toList xs)--prop_sortBy :: Seq (OrdA, B) -> Bool-prop_sortBy xs =- toList' (sortBy f xs) ~= Data.List.sortBy f (toList xs)- where f (x1, _) (x2, _) = compare x1 x2--prop_unstableSort :: Seq OrdA -> Bool-prop_unstableSort xs =- toList' (unstableSort xs) ~= Data.List.sort (toList xs)--prop_unstableSortBy :: Seq OrdA -> Bool-prop_unstableSortBy xs =- toList' (unstableSortBy compare xs) ~= Data.List.sort (toList xs)---- * Indexing--prop_index :: Seq A -> Property-prop_index xs =- not (null xs) ==> forAll (choose (0, length xs-1)) $ \ i ->- index xs i == toList xs !! i--prop_adjust :: Int -> Int -> Seq Int -> Bool-prop_adjust n i xs =- toList' (adjust f i xs) ~= adjustList f i (toList xs)- where f = (+n)--prop_update :: Int -> A -> Seq A -> Bool-prop_update i x xs =- toList' (update i x xs) ~= adjustList (const x) i (toList xs)--prop_take :: Int -> Seq A -> Bool-prop_take n xs =- toList' (take n xs) ~= Prelude.take n (toList xs)--prop_drop :: Int -> Seq A -> Bool-prop_drop n xs =- toList' (drop n xs) ~= Prelude.drop n (toList xs)--prop_splitAt :: Int -> Seq A -> Bool-prop_splitAt n xs =- toListPair' (splitAt n xs) ~= Prelude.splitAt n (toList xs)--adjustList :: (a -> a) -> Int -> [a] -> [a]-adjustList f i xs =- [if j == i then f x else x | (j, x) <- Prelude.zip [0..] xs]---- ** Indexing with predicates--- The elem* tests have poor coverage, but for find* we use predicates--- of varying density.--prop_elemIndexL :: A -> Seq A -> Bool-prop_elemIndexL x xs =- elemIndexL x xs == Data.List.elemIndex x (toList xs)--prop_elemIndicesL :: A -> Seq A -> Bool-prop_elemIndicesL x xs =- elemIndicesL x xs == Data.List.elemIndices x (toList xs)--prop_elemIndexR :: A -> Seq A -> Bool-prop_elemIndexR x xs =- elemIndexR x xs == listToMaybe (Prelude.reverse (Data.List.elemIndices x (toList xs)))--prop_elemIndicesR :: A -> Seq A -> Bool-prop_elemIndicesR x xs =- elemIndicesR x xs == Prelude.reverse (Data.List.elemIndices x (toList xs))--prop_findIndexL :: Positive Int -> Seq Int -> Bool-prop_findIndexL (Positive n) xs =- findIndexL p xs == Data.List.findIndex p (toList xs)- where p x = x `mod` n == 0--prop_findIndicesL :: Positive Int -> Seq Int -> Bool-prop_findIndicesL (Positive n) xs =- findIndicesL p xs == Data.List.findIndices p (toList xs)- where p x = x `mod` n == 0--prop_findIndexR :: Positive Int -> Seq Int -> Bool-prop_findIndexR (Positive n) xs =- findIndexR p xs == listToMaybe (Prelude.reverse (Data.List.findIndices p (toList xs)))- where p x = x `mod` n == 0--prop_findIndicesR :: Positive Int -> Seq Int -> Bool-prop_findIndicesR (Positive n) xs =- findIndicesR p xs == Prelude.reverse (Data.List.findIndices p (toList xs))- where p x = x `mod` n == 0---- * Folds--prop_foldlWithIndex :: [(Int, A)] -> Seq A -> Bool-prop_foldlWithIndex z xs =- foldlWithIndex f z xs == Data.List.foldl (uncurry . f) z (Data.List.zip [0..] (toList xs))- where f ys n y = (n,y):ys--prop_foldrWithIndex :: [(Int, A)] -> Seq A -> Bool-prop_foldrWithIndex z xs =- foldrWithIndex f z xs == Data.List.foldr (uncurry f) z (Data.List.zip [0..] (toList xs))- where f n y ys = (n,y):ys---- * Transformations--prop_mapWithIndex :: Seq A -> Bool-prop_mapWithIndex xs =- toList' (mapWithIndex f xs) ~= map (uncurry f) (Data.List.zip [0..] (toList xs))- where f = (,)--prop_reverse :: Seq A -> Bool-prop_reverse xs =- toList' (reverse xs) ~= Prelude.reverse (toList xs)---- ** Zips--prop_zip :: Seq A -> Seq B -> Bool-prop_zip xs ys =- toList' (zip xs ys) ~= Prelude.zip (toList xs) (toList ys)--prop_zipWith :: Seq A -> Seq B -> Bool-prop_zipWith xs ys =- toList' (zipWith f xs ys) ~= Prelude.zipWith f (toList xs) (toList ys)- where f = (,)--prop_zip3 :: Seq A -> Seq B -> Seq C -> Bool-prop_zip3 xs ys zs =- toList' (zip3 xs ys zs) ~= Prelude.zip3 (toList xs) (toList ys) (toList zs)--prop_zipWith3 :: Seq A -> Seq B -> Seq C -> Bool-prop_zipWith3 xs ys zs =- toList' (zipWith3 f xs ys zs) ~= Prelude.zipWith3 f (toList xs) (toList ys) (toList zs)- where f = (,,)--prop_zip4 :: Seq A -> Seq B -> Seq C -> Seq Int -> Bool-prop_zip4 xs ys zs ts =- toList' (zip4 xs ys zs ts) ~= Data.List.zip4 (toList xs) (toList ys) (toList zs) (toList ts)--prop_zipWith4 :: Seq A -> Seq B -> Seq C -> Seq Int -> Bool-prop_zipWith4 xs ys zs ts =- toList' (zipWith4 f xs ys zs ts) ~= Data.List.zipWith4 f (toList xs) (toList ys) (toList zs) (toList ts)- where f = (,,,)---- Simple test monad--data M a = Action Int a- deriving (Eq, Show)--instance Functor M where- fmap f (Action n x) = Action n (f x)--instance Applicative M where- pure x = Action 0 x- Action m f <*> Action n x = Action (m+n) (f x)--instance Monad M where- return x = Action 0 x- Action m x >>= f = let Action n y = f x in Action (m+n) y--instance Foldable M where- foldMap f (Action _ x) = f x--instance Traversable M where- traverse f (Action n x) = Action n <$> f x
@@ -1,341 +0,0 @@-import qualified Data.IntSet as IntSet-import Data.List (nub,sort)-import qualified Data.List as List-import Data.Monoid (mempty)-import Data.Set-import Prelude hiding (lookup, null, map, filter, foldr, foldl)-import Test.Framework-import Test.Framework.Providers.HUnit-import Test.Framework.Providers.QuickCheck2-import Test.HUnit hiding (Test, Testable)-import Test.QuickCheck--main :: IO ()-main = defaultMainWithOpts [ testCase "lookupLT" test_lookupLT- , testCase "lookupGT" test_lookupGT- , testCase "lookupLE" test_lookupLE- , testCase "lookupGE" test_lookupGE- , testProperty "prop_Valid" prop_Valid- , testProperty "prop_Single" prop_Single- , testProperty "prop_Member" prop_Member- , testProperty "prop_NotMember" prop_NotMember- , testProperty "prop_LookupLT" prop_LookupLT- , testProperty "prop_LookupGT" prop_LookupGT- , testProperty "prop_LookupLE" prop_LookupLE- , testProperty "prop_LookupGE" prop_LookupGE- , testProperty "prop_InsertValid" prop_InsertValid- , testProperty "prop_InsertDelete" prop_InsertDelete- , testProperty "prop_DeleteValid" prop_DeleteValid- , testProperty "prop_Join" prop_Join- , testProperty "prop_Merge" prop_Merge- , testProperty "prop_UnionValid" prop_UnionValid- , testProperty "prop_UnionInsert" prop_UnionInsert- , testProperty "prop_UnionAssoc" prop_UnionAssoc- , testProperty "prop_UnionComm" prop_UnionComm- , testProperty "prop_DiffValid" prop_DiffValid- , testProperty "prop_Diff" prop_Diff- , testProperty "prop_IntValid" prop_IntValid- , testProperty "prop_Int" prop_Int- , testProperty "prop_Ordered" prop_Ordered- , testProperty "prop_List" prop_List- , testProperty "prop_DescList" prop_DescList- , testProperty "prop_AscDescList" prop_AscDescList- , testProperty "prop_fromList" prop_fromList- , testProperty "prop_isProperSubsetOf" prop_isProperSubsetOf- , testProperty "prop_isProperSubsetOf2" prop_isProperSubsetOf2- , testProperty "prop_isSubsetOf" prop_isSubsetOf- , testProperty "prop_isSubsetOf2" prop_isSubsetOf2- , testProperty "prop_size" prop_size- , testProperty "prop_findMax" prop_findMax- , testProperty "prop_findMin" prop_findMin- , testProperty "prop_ord" prop_ord- , testProperty "prop_readShow" prop_readShow- , testProperty "prop_foldR" prop_foldR- , testProperty "prop_foldR'" prop_foldR'- , testProperty "prop_foldL" prop_foldL- , testProperty "prop_foldL'" prop_foldL'- , testProperty "prop_map" prop_map- , testProperty "prop_maxView" prop_maxView- , testProperty "prop_minView" prop_minView- , testProperty "prop_split" prop_split- , testProperty "prop_splitMember" prop_splitMember- , testProperty "prop_partition" prop_partition- , testProperty "prop_filter" prop_filter- ] opts- where- opts = mempty { ropt_test_options = Just $ mempty { topt_maximum_generated_tests = Just 500- , topt_maximum_unsuitable_generated_tests = Just 500- }- }--------------------------------------------------------------------- Unit tests-------------------------------------------------------------------test_lookupLT :: Assertion-test_lookupLT = do- lookupLT 3 (fromList [3, 5]) @?= Nothing- lookupLT 5 (fromList [3, 5]) @?= Just 3--test_lookupGT :: Assertion-test_lookupGT = do- lookupGT 4 (fromList [3, 5]) @?= Just 5- lookupGT 5 (fromList [3, 5]) @?= Nothing--test_lookupLE :: Assertion-test_lookupLE = do- lookupLE 2 (fromList [3, 5]) @?= Nothing- lookupLE 4 (fromList [3, 5]) @?= Just 3- lookupLE 5 (fromList [3, 5]) @?= Just 5--test_lookupGE :: Assertion-test_lookupGE = do- lookupGE 3 (fromList [3, 5]) @?= Just 3- lookupGE 4 (fromList [3, 5]) @?= Just 5- lookupGE 6 (fromList [3, 5]) @?= Nothing--{--------------------------------------------------------------------- Arbitrary, reasonably balanced trees---------------------------------------------------------------------}-instance (Enum a) => Arbitrary (Set a) where- arbitrary = sized (arbtree 0 maxkey)- where maxkey = 10000-- arbtree :: (Enum a) => Int -> Int -> Int -> Gen (Set a)- arbtree lo hi n = do t <- gentree lo hi n- if balanced t then return t else arbtree lo hi n- where gentree lo hi n- | n <= 0 = return Tip- | lo >= hi = return Tip- | otherwise = do i <- choose (lo,hi)- m <- choose (1,70)- let (ml,mr) | m==(1::Int) = (1,2)- | m==2 = (2,1)- | m==3 = (1,1)- | otherwise = (2,2)- l <- gentree lo (i-1) (n `div` ml)- r <- gentree (i+1) hi (n `div` mr)- return (bin (toEnum i) l r)--{--------------------------------------------------------------------- Valid tree's---------------------------------------------------------------------}-forValid :: (Enum a,Show a,Testable b) => (Set a -> b) -> Property-forValid f = forAll arbitrary $ \t ->--- classify (balanced t) "balanced" $- classify (size t == 0) "empty" $- classify (size t > 0 && size t <= 10) "small" $- classify (size t > 10 && size t <= 64) "medium" $- classify (size t > 64) "large" $- balanced t ==> f t--forValidUnitTree :: Testable a => (Set Int -> a) -> Property-forValidUnitTree f = forValid f--prop_Valid :: Property-prop_Valid = forValidUnitTree $ \t -> valid t--{--------------------------------------------------------------------- Single, Member, Insert, Delete---------------------------------------------------------------------}-prop_Single :: Int -> Bool-prop_Single x = (insert x empty == singleton x)--prop_Member :: [Int] -> Int -> Bool-prop_Member xs n =- let m = fromList xs- in all (\k -> k `member` m == (k `elem` xs)) (n : xs)--prop_NotMember :: [Int] -> Int -> Bool-prop_NotMember xs n =- let m = fromList xs- in all (\k -> k `notMember` m == (k `notElem` xs)) (n : xs)--test_LookupSomething :: (Int -> Set Int -> Maybe Int) -> (Int -> Int -> Bool) -> [Int] -> Bool-test_LookupSomething lookup' cmp xs =- let odd_sorted_xs = filter_odd $ nub $ sort xs- t = fromList odd_sorted_xs- test x = case List.filter (`cmp` x) odd_sorted_xs of- [] -> lookup' x t == Nothing- cs | 0 `cmp` 1 -> lookup' x t == Just (last cs) -- we want largest such element- | otherwise -> lookup' x t == Just (head cs) -- we want smallest such element- in all test xs-- where filter_odd [] = []- filter_odd [_] = []- filter_odd (_ : o : xs) = o : filter_odd xs--prop_LookupLT :: [Int] -> Bool-prop_LookupLT = test_LookupSomething lookupLT (<)--prop_LookupGT :: [Int] -> Bool-prop_LookupGT = test_LookupSomething lookupGT (>)--prop_LookupLE :: [Int] -> Bool-prop_LookupLE = test_LookupSomething lookupLE (<=)--prop_LookupGE :: [Int] -> Bool-prop_LookupGE = test_LookupSomething lookupGE (>=)--prop_InsertValid :: Int -> Property-prop_InsertValid k = forValidUnitTree $ \t -> valid (insert k t)--prop_InsertDelete :: Int -> Set Int -> Property-prop_InsertDelete k t = not (member k t) ==> delete k (insert k t) == t--prop_DeleteValid :: Int -> Property-prop_DeleteValid k = forValidUnitTree $ \t -> valid (delete k (insert k t))--{--------------------------------------------------------------------- Balance---------------------------------------------------------------------}-prop_Join :: Int -> Property-prop_Join x = forValidUnitTree $ \t ->- let (l,r) = split x t- in valid (join x l r)--prop_Merge :: Int -> Property-prop_Merge x = forValidUnitTree $ \t ->- let (l,r) = split x t- in valid (merge l r)--{--------------------------------------------------------------------- Union---------------------------------------------------------------------}-prop_UnionValid :: Property-prop_UnionValid- = forValidUnitTree $ \t1 ->- forValidUnitTree $ \t2 ->- valid (union t1 t2)--prop_UnionInsert :: Int -> Set Int -> Bool-prop_UnionInsert x t = union t (singleton x) == insert x t--prop_UnionAssoc :: Set Int -> Set Int -> Set Int -> Bool-prop_UnionAssoc t1 t2 t3 = union t1 (union t2 t3) == union (union t1 t2) t3--prop_UnionComm :: Set Int -> Set Int -> Bool-prop_UnionComm t1 t2 = (union t1 t2 == union t2 t1)--prop_DiffValid :: Property-prop_DiffValid = forValidUnitTree $ \t1 ->- forValidUnitTree $ \t2 ->- valid (difference t1 t2)--prop_Diff :: [Int] -> [Int] -> Bool-prop_Diff xs ys = toAscList (difference (fromList xs) (fromList ys))- == List.sort ((List.\\) (nub xs) (nub ys))--prop_IntValid :: Property-prop_IntValid = forValidUnitTree $ \t1 ->- forValidUnitTree $ \t2 ->- valid (intersection t1 t2)--prop_Int :: [Int] -> [Int] -> Bool-prop_Int xs ys = toAscList (intersection (fromList xs) (fromList ys))- == List.sort (nub ((List.intersect) (xs) (ys)))--{--------------------------------------------------------------------- Lists---------------------------------------------------------------------}-prop_Ordered :: Property-prop_Ordered = forAll (choose (5,100)) $ \n ->- let xs = [0..n::Int]- in fromAscList xs == fromList xs--prop_List :: [Int] -> Bool-prop_List xs = (sort (nub xs) == toList (fromList xs))--prop_DescList :: [Int] -> Bool-prop_DescList xs = (reverse (sort (nub xs)) == toDescList (fromList xs))--prop_AscDescList :: [Int] -> Bool-prop_AscDescList xs = toAscList s == reverse (toDescList s)- where s = fromList xs--prop_fromList :: [Int] -> Bool-prop_fromList xs- = case fromList xs of- t -> t == fromAscList sort_xs &&- t == fromDistinctAscList nub_sort_xs &&- t == List.foldr insert empty xs- where sort_xs = sort xs- nub_sort_xs = List.map List.head $ List.group sort_xs--{--------------------------------------------------------------------- Set operations are like IntSet operations---------------------------------------------------------------------}-toIntSet :: Set Int -> IntSet.IntSet-toIntSet = IntSet.fromList . toList---- Check that Set Int.isProperSubsetOf is the same as Set.isProperSubsetOf.-prop_isProperSubsetOf :: Set Int -> Set Int -> Bool-prop_isProperSubsetOf a b = isProperSubsetOf a b == IntSet.isProperSubsetOf (toIntSet a) (toIntSet b)---- In the above test, isProperSubsetOf almost always returns False (since a--- random set is almost never a subset of another random set). So this second--- test checks the True case.-prop_isProperSubsetOf2 :: Set Int -> Set Int -> Bool-prop_isProperSubsetOf2 a b = isProperSubsetOf a c == (a /= c) where- c = union a b--prop_isSubsetOf :: Set Int -> Set Int -> Bool-prop_isSubsetOf a b = isSubsetOf a b == IntSet.isSubsetOf (toIntSet a) (toIntSet b)--prop_isSubsetOf2 :: Set Int -> Set Int -> Bool-prop_isSubsetOf2 a b = isSubsetOf a (union a b)--prop_size :: Set Int -> Bool-prop_size s = size s == List.length (toList s)--prop_findMax :: Set Int -> Property-prop_findMax s = not (null s) ==> findMax s == maximum (toList s)--prop_findMin :: Set Int -> Property-prop_findMin s = not (null s) ==> findMin s == minimum (toList s)--prop_ord :: Set Int -> Set Int -> Bool-prop_ord s1 s2 = s1 `compare` s2 == toList s1 `compare` toList s2--prop_readShow :: Set Int -> Bool-prop_readShow s = s == read (show s)--prop_foldR :: Set Int -> Bool-prop_foldR s = foldr (:) [] s == toList s--prop_foldR' :: Set Int -> Bool-prop_foldR' s = foldr' (:) [] s == toList s--prop_foldL :: Set Int -> Bool-prop_foldL s = foldl (flip (:)) [] s == List.foldl (flip (:)) [] (toList s)--prop_foldL' :: Set Int -> Bool-prop_foldL' s = foldl' (flip (:)) [] s == List.foldl' (flip (:)) [] (toList s)--prop_map :: Set Int -> Bool-prop_map s = map id s == s--prop_maxView :: Set Int -> Bool-prop_maxView s = case maxView s of- Nothing -> null s- Just (m,s') -> m == maximum (toList s) && s == insert m s' && m `notMember` s'--prop_minView :: Set Int -> Bool-prop_minView s = case minView s of- Nothing -> null s- Just (m,s') -> m == minimum (toList s) && s == insert m s' && m `notMember` s'--prop_split :: Set Int -> Int -> Bool-prop_split s i = case split i s of- (s1,s2) -> all (<i) (toList s1) && all (>i) (toList s2) && i `delete` s == union s1 s2--prop_splitMember :: Set Int -> Int -> Bool-prop_splitMember s i = case splitMember i s of- (s1,t,s2) -> all (<i) (toList s1) && all (>i) (toList s2) && t == i `member` s && i `delete` s == union s1 s2--prop_partition :: Set Int -> Int -> Bool-prop_partition s i = case partition odd s of- (s1,s2) -> all odd (toList s1) && all even (toList s2) && s == s1 `union` s2--prop_filter :: Set Int -> Int -> Bool-prop_filter s i = partition odd s == (filter odd s, filter even s)
@@ -1,21 +0,0 @@-The MIT License (MIT)--Copyright (c) 2014 Dr. Kat--Permission is hereby granted, free of charge, to any person obtaining a copy-of this software and associated documentation files (the "Software"), to deal-in the Software without restriction, including without limitation the rights-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-copies of the Software, and to permit persons to whom the Software is-furnished to do so, subject to the following conditions:--The above copyright notice and this permission notice shall be included in all-copies or substantial portions of the Software.--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-SOFTWARE.
@@ -1,1 +0,0 @@-Retrieved from: https://github.com/ucsd-progsys/230-wi19-web/
@@ -1,364 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--diff" @-}-{- LIQUID "--short-names" @-}-{-@ infixr ++ @-} -- TODO: Silly to have to rewrite this annotation!-{-@ infixr <~ @-} -- TODO: Silly to have to rewrite this annotation!------------------------------------------------------------------------------------- | Inspired by --- http://flint.cs.yale.edu/cs428/coq/sf/Hoare.html--- http://flint.cs.yale.edu/cs428/coq/sf/Hoare2.html-----------------------------------------------------------------------------------{-# LANGUAGE GADTs #-}--module Axiomatic where--import Prelude hiding ((++)) -import ProofCombinators-import qualified State as S-import Expressions -import Imp -import BigStep hiding (And)-----------------------------------------------------------------------------------{- | A Floyd-Hoare triple is of the form -- { P } c { Q }-- where - - - `P` and `Q` are assertions (think `BExp`) and - - `c` is a command (think `Com`) - - A Floyd-Hoare triple states that -- IF -- * The program `c` is starts at a state where the *precondition* `P` is True, and - * The program finishes execution-- THEN -- * At the final state, the *postcondition* `Q` will also evaluate to True.-- -}--{- | Lets paraphrase the following Hoare triples in English.-- 1) {True} c {X = 5}-- 2) {X = m} c {X = m + 5}-- 3) {X <= Y} c {Y <= X}-- 4) {True} c {False}---}-------------------------------------------------------------------------------------- | The type `Assertion` formalizes the type for the --- assertions (i.e. pre- and post-conditions) `P`, `Q`--- appearing in the triples {P} c {Q}--type Assertion = BExp ---------------------------------------------------------------------------------------------------------------------------------------------------------------------{- | Legitimate Triples -----------------------------------------------------------------------------------Which of the following triples are "legit" i.e., the claimed relation between -`pre`condition` `P`, `com`mand `C`, and `post`condition `Q` is true?-- 1) {True} - X <~ 5 - {X = 5}-- 2) {X = 2} - X <~ X + 1 - {X = 3}-- 3) {True} - X <~ 5; - Y <~ 0 - {X = 5}-- 4) {True} - X <~ 5; - Y <~ X - {Y = 5}-- 5) {X = 2 && X = 3} - X <~ 5 - {X = 0}-- 6) {True} - SKIP - {False}-- 7) {False} - SKIP - {True}-- 8) {True} - WHILE True DO - SKIP - {False}-- 9) {X = 0}- WHILE X <= 0 DO - X <~ X + 1 - {X = 1}-- 10) {X = 1}- WHILE not (X <= 0) DO - X <~ X + 1 - {X = 100}- -}------------------------------------------------------------------------------------- | `Legit` formalizes the notion of when a Floyd-Hoare triple is legitimate ----------------------------------------------------------------------------------{-@ type Legit P C Q = s:{State | bval P s} - -> s':_ -> Prop (BStep C s s') - -> {bval Q s'} - @-}-type Legit = State -> State -> BStep -> Proof ---- | {True} X <~ 5 {X = 5} -----------------------------------------------------{-@ leg1 :: Legit tt (Assign {"x"} (N 5)) (Equal (V {"x"}) (N 5)) @-}-leg1 :: Legit -leg1 s s' (BAssign {}) - = S.lemma_get_set "x" 5 s ----- | {True} X <~ 5; y <- X {X = 5} ---------------------------------------------{-@ leg3 :: Legit tt (Seq (Assign {"x"} (N 5)) (Assign {"y"} (V {"x"}))) (Equal (V {"y"}) (N 5)) @-}-leg3 :: Legit -leg3 s s' (BSeq _ _ _ smid _ (BAssign {}) (BAssign {})) - = S.lemma_get_set "x" 5 s &&& S.lemma_get_set "y" 5 smid ----- | {False} X <~ 5 {X = 0} ----------------------------------------------------{-@ leg5 :: Legit ff (Assign {"x"} (N 5)) (Equal (V {"x"}) (N 22)) @-}-leg5 :: Legit -leg5 s s' _ = () -------------------------------------------------------------------------------------- | Two simple facts about Floyd-Hoare Triples -------------------------------------------------------------------------------------------------------------------{-@ lem_post_true :: p:_ -> c:_ -> Legit p c tt @-}-lem_post_true :: Assertion -> Com -> Legit-lem_post_true p c = \s s' c_s_s' -> () --{-@ lem_pre_false :: c:_ -> q:_ -> Legit ff c q @-}-lem_pre_false :: Com -> Assertion -> Legit -lem_pre_false c q = \s s' c_s_s' -> () ----- | Assignment ---- { Y = 1 } X <~ Y { X = 1 }---- { X + Y = 1 } X <~ X + Y { X = 1 }---- { a = 1 } X <~ a { X = 1 }---{- | Lets fill in the blanks-- { ??? } - x <~ 3 - { x == 3 }-- { ??? } - x <~ x + 1 - { x <= 5 }-- { ??? }- x <~ y + 1 - { 0 <= x && x <= 5 }-- -} ---{- | To conclude that an arbitrary postcondition `Q` holds after - `x <~ a`, we need to assume that Q holds before `x <~ a` - but with all occurrences of `x` replaced by `a` in `Q` -- Lets revisit the example above:-- { ??? } - x <~ 3 - { x == 3 }-- { ??? } - x <~ x + 1 - { x <= 5 }-- { ??? }- x <~ y + 1 - { 0 <= x && x <= 5 }-- -} ------------------------------------------------------------------------------------- | `Valid`ity of an assertion-------------------------------------------------------------------------------------- forall s. bval P s == True -{-@ type Valid P = s:State -> { v: Proof | bval P s } @-}-type Valid = State -> Proof ---- x >= 0 || x < 0--{-@ checkValid :: p:_ -> Valid p -> () @-}-checkValid :: Assertion -> Valid -> ()-checkValid p v = () ---- x <= 0 -ex0 = checkValid (e0 `bImp` e1) (\_ -> ())- where - e0 = (V "x") `Leq` (N 0)- e1 = ((V "x") `Minus` (N 1)) `Leq` (N 0)---- x <= 0 => x - 1 <= 0--- e1 = e0 `bImp` ((V "x" `Minus` N 1) `Leq` (N 0))------------------------------------------------------------------------------------- | When does an assertion `Imply` another-----------------------------------------------------------------------------------{-@ type Imply P Q = Valid (bImp P Q) @-}---- 10 <= x => 5 <= x-{-@ v1 :: _ -> Imply (Leq (N 10) (V {"x"})) (Leq (N 5) (V {"x"})) @-} -v1 :: a -> Valid -v1 _ = \_ -> ()---- (0 < x && 0 < y) ===> (0 < x + y)-{-@ v2 :: _ -> Imply (bAnd (Leq (N 0) (V {"x"})) (Leq (N 0) (V {"y"}))) - (Leq (N 0) (Plus (V {"x"}) (V {"y"})))- @-} -v2 :: a -> Valid -v2 _ = \_ -> ()------------------------------------------------------------------------------------- | The Floyd-Hoare proof system-----------------------------------------------------------------------------------data FHP where - FH :: Assertion -> Com -> Assertion -> FHP--data FH where - FHSkip :: Assertion -> FH - FHAssign :: Assertion -> Vname -> AExp -> FH - FHSeq :: Assertion -> Com -> Assertion -> Com -> Assertion -> FH -> FH -> FH - FHIf :: Assertion -> Assertion -> BExp -> Com -> Com -> FH -> FH -> FH- FHWhile :: Assertion -> BExp -> Com -> FH -> FH - FHConPre :: Assertion -> Assertion -> Assertion -> Com -> Valid -> FH -> FH - FHConPost :: Assertion -> Assertion -> Assertion -> Com -> FH -> Valid -> FH --{-@ data FH where - FHSkip :: p:_- -> Prop (FH p Skip p) - FHAssign :: q:_ -> x:_ -> a:_- -> Prop (FH (bsubst x a q) (Assign x a) q) - FHSeq :: p:_ -> c1:_ -> q:_ -> c2:_ -> r:_ - -> Prop (FH p c1 q) - -> Prop (FH q c2 r) - -> Prop (FH p (Seq c1 c2) r) - FHIf :: p:_ -> q:_ -> b:_ -> c1:_ -> c2:_- -> Prop (FH (bAnd p b) c1 q) - -> Prop (FH (bAnd p (Not b)) c2 q)- -> Prop (FH p (If b c1 c2) q)- FHWhile :: inv:_ -> b:_ -> c:_- -> Prop (FH (bAnd inv b) c inv) - -> Prop (FH inv (While b c) (bAnd inv (Not b)))- FHConPre :: p':_ -> p:_ -> q:_ -> c:_ - -> Imply p' p- -> Prop (FH p c q) - -> Prop (FH p' c q)- FHConPost :: p:_ -> q:_ -> q':_ -> c:_ - -> Prop (FH p c q) - -> Imply q q'- -> Prop (FH p c q')- @-}------------------------------------------------------------------------------------- | THEOREM: Soundness of Floyd-Hoare Logic ------------------------------------------------------------------------------------ thm_fh_legit :: p:_ -> c:_ -> q:_ -> Prop (FH p c q) -> Legit p c q---- thm_legit_fh :: p:_ -> c:_ -> q:_ -> Legit p c q -> Prop (FH p c q) -------------------------------------------------------------------------------------- | Making FH Algorithmic: Verification Conditions ----------------------------------------------------------------------------------data ICom - = ISkip -- skip - | IAssign Vname AExp -- x := a- | ISeq ICom ICom -- c1; c2- | IIf BExp ICom ICom -- if b then c1 else c2- | IWhile Assertion BExp ICom -- while {I} b c - deriving (Show)--{-@ reflect pre @-}-pre :: ICom -> Assertion -> Assertion -pre ISkip q = q-pre (IAssign x a) q = bsubst x a q -pre (ISeq c1 c2) q = pre c1 (pre c2 q)-pre (IIf b c1 c2) q = bIte b (pre c1 q) (pre c2 q) -pre (IWhile i _ _) _ = i -----{-@ reflect vc @-}-vc :: ICom -> Assertion -> Assertion-vc ISkip _ = tt -vc (IAssign {}) _ = tt -vc (ISeq c1 c2) q = (vc c1 (pre c2 q)) `bAnd` (vc c2 q)-vc (IIf _ c1 c2) q = (vc c1 q) `bAnd` (vc c2 q)-vc (IWhile i b c) q = ((bAnd i b) `bImp` (pre c i)) `bAnd` -- { i && b} c { i }- ((bAnd i (Not b)) `bImp` q ) `bAnd` -- { i & ~b} => Q - vc c i--{-@ reflect erase @-}-erase :: ICom -> Com -erase ISkip = Skip -erase (IAssign x a) = Assign x a -erase (ISeq c1 c2) = Seq (erase c1) (erase c2)-erase (IIf b c1 c2) = If b (erase c1) (erase c2)-erase (IWhile _ b c) = While b (erase c)---------------------------------------------------------------------------------------- | THEOREM: Soundness of VC--------------------------------------------------------------------------------------- thm_vc :: c:_ -> q:_ -> Valid (vc c q) -> Legit (pre c q) (erase c) q---------------------------------------------------------------------------------------- | Extending the above to triples [HW] --------------------------------------------------------------------------------------{-@ reflect vc' @-}-vc' :: Assertion -> ICom -> Assertion -> Assertion -vc' p c q = bAnd (bImp p (pre c q)) (vc c q) ---------------------------------------------------------------------------------------- | THEOREM: Soundness of VC'--------------------------------------------------------------------------------------- thm_vc' :: p:_ -> c:_ -> q:_ -> Valid (vc' p c q) -> Legit p (erase c) q--
@@ -1,160 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--diff" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--short-names" @-}--{-@ infixr ++ @-} -- TODO: Silly to have to rewrite this annotation!--{-# LANGUAGE GADTs #-}--module BigStep where--import Prelude hiding ((++)) -import ProofCombinators-import qualified State as S-import Expressions hiding (And)-import Imp --{- - BStep c s1 s2 -- ------------------[BSkip]- BStep Skip s s--- s' = set x (aval a s) s- ----------------------------------[BAssign]- BStep (x := a) s s'--- BStep c1 s smid BStep c2 smid s'- ----------------------------------------[BSeq]- BStep (c1; c2) s s' --- bval b s1 = TRUE BStep c1 s s'- ----------------------------------------- BStep (If b c1 c2) s s' -- bval b s = FALSE BStep c2 s s'- -------------------------------- BStep (If b c1 c2) s s' -- WHILE - -}------------------------------------------------------------------------------------- | Big-step Semantics -----------------------------------------------------------------------------------data BStepP where- BStep :: Com -> State -> State -> BStepP --data BStep where - BSkip :: State -> BStep - BAssign :: Vname -> AExp -> State -> BStep - BSeq :: Com -> Com -> State -> State -> State -> BStep -> BStep -> BStep - BIfT :: BExp -> Com -> Com -> State -> State -> BStep -> BStep - BIfF :: BExp -> Com -> Com -> State -> State -> BStep -> BStep- BWhileF :: BExp -> Com -> State -> BStep - BWhileT :: BExp -> Com -> State -> State -> State -> BStep -> BStep -> BStep --{-@ data BStep where - BSkip :: s:State - -> Prop (BStep Skip s s)- BAssign :: x:Vname -> a:AExp -> s:State - -> Prop (BStep (Assign x a) s (asgn x a s)) - BSeq :: c1:Com -> c2:Com -> s1:State -> s2:State -> s3:State - -> Prop (BStep c1 s1 s2) -> Prop (BStep c2 s2 s3) - -> Prop (BStep (Seq c1 c2) s1 s3)- BIfT :: b:BExp -> c1:Com -> c2:Com -> s:{State | bval b s} -> s1:State- -> Prop (BStep c1 s s1) -> Prop (BStep (If b c1 c2) s s1)- BIfF :: b:BExp -> c1:Com -> c2:Com -> s:{State | not (bval b s)} -> s2:State- -> Prop (BStep c2 s s2) -> Prop (BStep (If b c1 c2) s s2)- BWhileF :: b:BExp -> c:Com -> s:{State | not (bval b s)} - -> Prop (BStep (While b c) s s)- BWhileT :: b:BExp -> c:Com -> s1:{State | bval b s1} -> s1':State -> s2:State- -> Prop (BStep c s1 s1') -> Prop (BStep (While b c) s1' s2)- -> Prop (BStep (While b c) s1 s2)- @-} ---{-@ reflect cmd_1 @-}-cmd_1 = "x" <~ N 5--{-@ reflect cmd_2 @-}-cmd_2 = "y" <~ (V "x")--{-@ reflect cmd_1_2 @-}-cmd_1_2 = cmd_1 @@ cmd_2--{-@ reflect prop_set @-}-prop_set cmd x v s = BStep cmd s (S.set s x v)--{-@ step_1 :: s:State -> Prop (prop_set cmd_1 {"x"} 5 s) @-}-step_1 s = BAssign "x" (N 5) s--{-@ step_2 :: s:{State | S.get s "x" == 5} -> Prop (prop_set cmd_2 {"y"} 5 s) @-}-step_2 s = BAssign "y" (V "x") s--{-@ step_1_2 :: s:State -> Prop (BStep cmd_1_2 s (S.set (S.set s {"x"} 5) {"y"} 5)) @-}-step_1_2 s = BSeq cmd_1 cmd_2 s s1 s2 (step_1 s) (step_2 s1)- where- s1 = S.set s "x" 5- s2 = S.set s1 "y" 5-------------------------------------------------------------------------------------- | We say `Sim c1 c2` or `c1` is simulated by `c2` if --- the transitions of `c1` are contained within those of `c2`----------------------------------------------------------------------------------{-@ type Sim C1 C2 = s:State -> t:State -> Prop (BStep C1 s t) -> Prop (BStep C2 s t) @-}-type SimT = State -> State -> BStep -> BStep --------------------------------------------------------------------------------------- | IMP is Deterministic------------------------------------------------------------------------------------{- -{-@ thm_bigstep_det - :: s:_ -> t1:_ -> t2:_ -> c:_- -> Prop (BStep c s t1) - -> Prop (BStep c s t2) - -> { t1 == t2 }- @-}-thm_bigstep_det :: State -> State -> State -> Com -> BStep -> BStep -> Proof-----{- -}-thm_bigstep_det s t t' Skip (BSkip {}) (BSkip {})- = ()- -thm_bigstep_det s t t' (Assign x a) (BAssign {}) (BAssign {})- = ()- -thm_bigstep_det s t t' (Seq c1 c2) (BSeq _ _ _ s1 s2 s_s1 s1_s2) (BSeq _ _ _ s1' s2' s_s1' s1_s2')- = thm_bigstep_det s1_eq_s1' s2 s2' c2 s1_s2 s1_s2' - where s1_eq_s1' = s1 ? thm_bigstep_det s s1 s1' c1 s_s1 s_s1'- -thm_bigstep_det s t t' (If b c1 c2) (BIfT _ _ _ _ _t c1_s_t) (BIfT _ _ _ _ _t' c1_s_t')- = thm_bigstep_det s t t' c1 c1_s_t c1_s_t'- -thm_bigstep_det s t t' (If b c1 c2) (BIfF _ _ _ _ _t c2_s_t) (BIfF _ _ _ _ _t' c2_s_t')- = thm_bigstep_det s t t' c2 c2_s_t c2_s_t'- -thm_bigstep_det s t t' (While b c) (BWhileF {}) (BWhileF {})- = ()- -thm_bigstep_det s t t' (While b c) (BWhileT _ _ _ s1 _ s_s1 s1_t) (BWhileT _ _ _ s1' _ s_s1' s1_t')- = thm_bigstep_det s1_eq_s1' t t' (While b c) s1_t s1_t' - where s1_eq_s1' = s1 ? thm_bigstep_det s s1 s1' c s_s1 s_s1'--thm_bigstep_det _ _ _ _ _ _ - = impossible "no really" - --}
@@ -1,144 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--diff" @-}--{-# LANGUAGE PartialTypeSignatures #-}--module Expressions where--import qualified State as S -import ProofCombinators ------------------------------------------------------------------------------------- | Arithmetic Expressions ----------------------------------------------------------------------------------type Vname = String--data AExp - = N Val - | V Vname - | Plus AExp AExp - | Minus AExp AExp - | Times AExp AExp - deriving (Show)--type Val = Int -type State = S.GState Vname Val --{-@ reflect aval @-}-aval :: AExp -> State -> Val -aval (N n) _ = n -aval (V x) s = S.get s x -aval (Plus e1 e2) s = aval e1 s + aval e2 s-aval (Minus e1 e2) s = aval e1 s - aval e2 s-aval (Times e1 e2) s = aval e1 s * aval e2 s--{-@ reflect asgn @-}-asgn :: Vname -> AExp -> State -> State-asgn x a s = S.set s x (aval a s)--{-@ reflect subst @-}-subst :: Vname -> AExp -> AExp -> AExp-subst x e (Plus a1 a2) = Plus (subst x e a1) (subst x e a2)-subst x e (Minus a1 a2) = Minus (subst x e a1) (subst x e a2)-subst x e (Times a1 a2) = Times (subst x e a1) (subst x e a2)-subst x e (V y) | x == y = e-subst _ _ a = a--{-@ lem_subst :: x:_ -> a:_ -> e:_ -> s:_ -> - { aval (subst x a e) s = aval e (asgn x a s) } - @-}-lem_subst :: Vname -> AExp -> AExp -> State -> Proof-lem_subst x a (V y) s- | x == y = ()- | otherwise = S.lemma_get_not_set y x (aval a s) s-lem_subst x a (N i) s = ()-lem_subst x a (Plus e1 e2) s = lem_subst x a e1 s &&& lem_subst x a e2 s-lem_subst x a (Minus e1 e2) s = lem_subst x a e1 s &&& lem_subst x a e2 s-lem_subst x a (Times e1 e2) s = lem_subst x a e1 s &&& lem_subst x a e2 s--------------------------------------------------------------------------------------- | Boolean Expressions -----------------------------------------------------------------------------------data BExp - = Bc Bool -- true, false - | Not BExp -- not b - | And BExp BExp -- b1 && b2- | Leq AExp AExp -- a1 <= a2 - | Equal AExp AExp -- a1 == a2 - deriving (Show)--{-@ reflect .&&. @-}-(.&&.) :: BExp -> BExp -> BExp -b1 .&&. b2 = And b1 b2 --{-@ reflect .=>. @-}-(.=>.) :: BExp -> BExp -> BExp -b1 .=>. b2 = bImp b1 b2 --{-@ reflect bAnd @-}-bAnd :: BExp -> BExp -> BExp -bAnd b1 b2 = And b1 b2 --{-@ reflect bIte @-}-bIte :: BExp -> BExp -> BExp -> BExp -bIte p b1 b2 = And (bImp p b1) (bImp (Not p) b2)--{-@ reflect .==. @-}-(.==.) :: AExp -> AExp -> BExp -b1 .==. b2 = Equal b1 b2 --{-@ reflect .<=. @-}-(.<=.) :: AExp -> AExp -> BExp -b1 .<=. b2 = Leq b1 b2 --{-@ reflect bOr @-}-bOr :: BExp -> BExp -> BExp -bOr b1 b2 = Not ((Not b1) `And` (Not b2))- -{-@ reflect bImp @-}-bImp :: BExp -> BExp -> BExp -bImp b1 b2 = bOr (Not b1) b2--{-@ reflect bLess @-}-bLess :: AExp -> AExp -> BExp -bLess a1 a2 = And (Leq a1 a2) (Not (Equal a1 a2))--{-@ reflect tt @-}-tt :: BExp -tt = Bc True --{-@ reflect ff @-}-ff :: BExp -ff = Bc False --{-@ reflect bval @-}-bval :: BExp -> State -> Bool-bval (Bc b) _ = b -bval (Not b) s = not (bval b s) -bval (And b1 b2) s = bval b1 s && bval b2 s -bval (Leq a1 a2) s = aval a1 s <= aval a2 s -bval (Equal a1 a2) s = aval a1 s == aval a2 s ---{-@ reflect bsubst @-}-bsubst :: Vname -> AExp -> BExp -> BExp-bsubst x a (Bc b) = Bc b-bsubst x a (Not b) = Not (bsubst x a b)-bsubst x a (And b1 b2) = And (bsubst x a b1) (bsubst x a b2)-bsubst x a (Leq a1 a2) = Leq (subst x a a1) (subst x a a2)-bsubst x a (Equal a1 a2) = Equal (subst x a a1) (subst x a a2)--{-@ lem_bsubst :: x:_ -> a:_ -> b:_ -> s:_ -> - { bval (bsubst x a b) s = bval b (asgn x a s) } - @-}-lem_bsubst :: Vname -> AExp -> BExp -> State -> Proof -lem_bsubst x a (Bc _) _ = () -lem_bsubst x a (Not b) s = lem_bsubst x a b s -lem_bsubst x a (And b1 b2) s = lem_bsubst x a b1 s &&& lem_bsubst x a b2 s -lem_bsubst x a (Leq a1 a2) s = lem_subst x a a1 s &&& lem_subst x a a2 s -lem_bsubst x a (Equal a1 a2) s = lem_subst x a a1 s &&& lem_subst x a a2 s -
@@ -1,36 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--diff" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--short-names" @-}--{-@ infixr ++ @-} -- TODO: Silly to have to rewrite this annotation!-{-@ infixr <~ @-} -- TODO: Silly to have to rewrite this annotation!--{-# LANGUAGE GADTs #-}--module Imp where--import Prelude hiding ((++)) -import ProofCombinators-import qualified State as S-import Expressions -- hiding (And)------------------------------------------------------------------------------------- | IMP Commands----------------------------------------------------------------------------------data Com - = Skip -- skip - | Assign Vname AExp -- x := a- | Seq Com Com -- c1; c2- | If BExp Com Com -- if b then c1 else c2- | While BExp Com -- while b c - deriving (Show)--{-@ reflect <~ @-}-(<~) :: Vname -> AExp -> Com -x <~ a = Assign x a --{-@ reflect @@ @-}-(@@) :: Com -> Com -> Com -s1 @@ s2 = Seq s1 s2-
@@ -1,427 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--diff" @-}-{- LIQUID "--short-names" @-}-{-@ infixr ++ @-} -- TODO: Silly to have to rewrite this annotation!-{-@ infixr <~ @-} -- TODO: Silly to have to rewrite this annotation!------------------------------------------------------------------------------------- | Inspired by --- http://flint.cs.yale.edu/cs428/coq/sf/Hoare.html--- http://flint.cs.yale.edu/cs428/coq/sf/Hoare2.html-----------------------------------------------------------------------------------{-# LANGUAGE GADTs #-}--module Axiomatic where--import Prelude hiding ((++)) -import ProofCombinators-import qualified State as S-import Expressions -import Imp -import BigStep hiding (And)-----------------------------------------------------------------------------------{- | A Floyd-Hoare triple is of the form -- { P } c { Q }-- where - - - `P` and `Q` are assertions (think `BExp`) and - - `c` is a command (think `Com`) - - A Floyd-Hoare triple states that -- IF -- * The program `c` is starts at a state where the *precondition* `P` is True, and - * The program finishes execution-- THEN -- * At the final state, the *postcondition* `Q` will also evaluate to True.-- -}--{- | Lets paraphrase the following Hoare triples in English.-- 1) {True} c {X = 5}-- 2) {X = m} c {X = m + 5}-- 3) {X <= Y} c {Y <= X}-- 4) {True} c {False}---}-------------------------------------------------------------------------------------- | The type `Assertion` formalizes the type for the --- assertions (i.e. pre- and post-conditions) `P`, `Q`--- appearing in the triples {P} c {Q}--type Assertion = BExp ---------------------------------------------------------------------------------------------------------------------------------------------------------------------{- | Legitimate Triples -----------------------------------------------------------------------------------Which of the following triples are "legit" i.e., the claimed relation between -`pre`condition` `P`, `com`mand `C`, and `post`condition `Q` is true?-- 1) {True} - X <~ 5 - {X = 5}-- 2) {X = 2} - X <~ X + 1 - {X = 3}-- 3) {True} - X <~ 5; - Y <~ 0 - {X = 5}-- 4) {True} - X <~ 5; - Y <~ X - {Y = 5}-- 5) {X = 2 && X = 3} - X <~ 5 - {X = 0}-- 6) {True} - SKIP - {False}-- 7) {False} - SKIP - {True}-- 8) {True} - WHILE True DO - SKIP - {False}-- 9) {X = 0}- WHILE X <= 0 DO - X <~ X + 1 - {X = 1}-- 10) {X = 1}- WHILE not (X <= 0) DO - X <~ X + 1 - {X = 100}- -}------------------------------------------------------------------------------------- | `Legit` formalizes the notion of when a Floyd-Hoare triple is legitimate ----------------------------------------------------------------------------------{-@ type Legit P C Q = s:{State | bval P s} - -> s':_ -> Prop (BStep C s s') - -> {bval Q s'} - @-}-type Legit = State -> State -> BStep -> Proof ---- | {True} X <~ 5 {X = 5} -----------------------------------------------------{-@ leg1 :: Legit tt (Assign {"x"} (N 5)) (Equal (V {"x"}) (N 5)) @-}-leg1 :: Legit -leg1 s s' (BAssign {}) - = S.lemma_get_set "x" 5 s ----- | {True} X <~ 5; y <- X {X = 5} ---------------------------------------------{-@ leg3 :: Legit tt (Seq (Assign {"x"} (N 5)) (Assign {"y"} (V {"x"}))) (Equal (V {"y"}) (N 5)) @-}-leg3 :: Legit -leg3 s s' (BSeq _ _ _ smid _ (BAssign {}) (BAssign {})) - = S.lemma_get_set "x" 5 s &&& S.lemma_get_set "y" 5 smid ----- | {False} X <~ 5 {X = 0} ----------------------------------------------------{-@ leg5 :: Legit ff (Assign {"x"} (N 5)) (Equal (V {"x"}) (N 22)) @-}-leg5 :: Legit -leg5 s s' _ = () -------------------------------------------------------------------------------------- | 1. Simple facts about Floyd-Hoare Triples -------------------------------------------------------------------------------------------------------------------{-@ lem_post_true :: p:_ -> c:_ -> Legit p c tt @-}-lem_post_true :: Assertion -> Com -> Legit-lem_post_true p c = \s s' c_s_s' -> () --{-@ lem_pre_false :: c:_ -> q:_ -> Legit ff c q @-}-lem_pre_false :: Com -> Assertion -> Legit -lem_pre_false c q = \s s' c_s_s' -> () ------------------------------------------------------------------------------------- | 2. Validity and Implication-----------------------------------------------------------------------------------{-@ type Valid P = s:State -> { v: Proof | bval P s } @-}-type Valid = State -> Proof --{-@ type Imply P Q = Valid (bImp P Q) @-}---- 10 <= x => 5 <= x -{-@ v1 :: _ -> Imply (Leq (N 10) (V {"x"})) (Leq (N 5) (V {"x"})) @-} -v1 :: a -> Valid -v1 _ = \_ -> ()---- (0 < x && 0 < y) ===> (0 < x + y)--{-@ v2 :: _ -> Imply (bAnd (Leq (N 0) (V {"x"})) (Leq (N 0) (V {"y"}))) - (Leq (N 0) (Plus (V {"x"}) (V {"y"})))- @-} -v2 :: a -> Valid -v2 _ = \_ -> ()------------------------------------------------------------------------------------- | 3. Consequence----------------------------------------------------------------------------------{-@ lem_conseq_pre :: p':_ -> p:_ -> q:_ -> c:_ - -> Imply p' p -> Legit p c q - -> Legit p' c q- @-}-lem_conseq_pre :: Assertion -> Assertion -> Assertion -> Com -> Valid -> Legit -> Legit -lem_conseq_pre p' p q c impl pcq = \s s' c_s_s' -> pcq (s ? (impl s)) s' c_s_s'--{-@ lem_conseq_post :: p:_ -> q:_ -> q':_ -> c:_ - -> Legit p c q -> Imply q q' - -> Legit p c q'- @-}-lem_conseq_post :: Assertion -> Assertion -> Assertion -> Com -> Legit -> Valid -> Legit -lem_conseq_post p q q' c pcq impl = \s s' c_s_s' -> pcq s s' c_s_s' ? (impl s') ------------------------------------------------------------------------------------- | 4. Skip ------------------------------------------------------------------------------------ {P} Skip {P}--{-@ lem_skip :: p:_ -> (Legit p Skip p) @-}-lem_skip :: Assertion -> Legit -lem_skip p = \s s' (BSkip {}) -> () ---{- | Exercise suppose you have -- {P} Skip {Q} -- Prove that -- P => Q -- -}------------------------------------------------------------------------------------- | 5. Assignment ------------------------------------------------------------------------------------- { Y = 1 } X <~ Y { X = 1 }---- { X + Y = 1 } X <~ X + Y { X = 1 }---- { a = 1 } X <~ a { X = 1 }---{- | Lets fill in the blanks-- { ??? } - x <~ 3 - { x == 3 }-- { ??? } - x <~ x + 1 - { x <= 5 }-- { ??? }- x <~ y + 1 - { 0 <= x && x <= 5 }-- -} ---{- | To conclude that an arbitrary postcondition `Q` holds after - `x <~ a`, we need to assume that Q holds before `x <~ a` - but with all occurrences of `x` replaced by `a` in `Q` -- Lets revisit the example above:-- { ??? } - x <~ 3 - { x == 3 }-- { ??? } - x <~ x + 1 - { x <= 5 }-- { ??? }- x <~ y + 1 - { 0 <= x && x <= 5 }-- -} --{-@ lem_asgn :: x:_ -> a:_ -> q:_ -> - Legit (bsubst x a q) (Assign x a) q - @-}-lem_asgn :: Vname -> AExp -> Assertion -> Legit -lem_asgn x a q = \s s' (BAssign {}) -> lem_bsubst x a q s-------------------------------------------------------------------------------------- | 6. Sequencing ----------------------------------------------------------------------------------{-@ lem_seq :: c1:_ -> c2:_ -> p:_ -> q:_ -> r:_ - -> Legit p c1 q -> Legit q c2 r - -> Legit p (Seq c1 c2) r - @-}-lem_seq :: Com -> Com -> Assertion -> Assertion -> Assertion -> Legit -> Legit -> Legit -lem_seq c1 c2 p q r l1 l2 = \s s' (BSeq _ _ _ smid _ t1 t2) -> - l1 s smid t1 &&& l2 smid s' t2 -------------------------------------------------------------------------------------- | 7. Branches ----------------------------------------------------------------------------------{-@ lem_if :: b:_ -> c1:_ -> c2:_ -> p:_ -> q:_ - -> Legit (bAnd p b) c1 q - -> Legit (bAnd p (Not b)) c2 q - -> Legit p (If b c1 c2) q- @-}-lem_if :: BExp -> Com -> Com -> Assertion -> Assertion -> Legit -> Legit -> Legit-lem_if b c1 c2 p q l1 l2 = \s s' bs -> case bs of - BIfF _ _ _ _ _ c2_s_s' -> l2 s s' c2_s_s'- BIfT _ _ _ _ _ c1_s_s' -> l1 s s' c1_s_s'------------------------------------------------------------------------------------- | 8. Loops ----------------------------------------------------------------------------------{-@ lem_while :: b:_ -> c:_ -> p:_ - -> Legit (bAnd p b) c p - -> Legit p (While b c) (bAnd p (Not b)) - @-}-lem_while :: BExp -> Com -> Assertion -> Legit -> Legit -lem_while b c p lbody s s' (BWhileF {}) - = ()-lem_while b c p lbody s s' (BWhileT _ _ _ smid _ c_s_smid w_smid_s') - = lem_while b c p lbody (smid ? lbody s smid c_s_smid) s' w_smid_s' ------------------------------------------------------------------------------------- | The Floyd-Hoare proof system-----------------------------------------------------------------------------------data FHP where - FH :: Assertion -> Com -> Assertion -> FHP--data FH where - FHSkip :: Assertion -> FH - FHAssign :: Assertion -> Vname -> AExp -> FH - FHSeq :: Assertion -> Com -> Assertion -> Com -> Assertion -> FH -> FH -> FH - FHIf :: Assertion -> Assertion -> BExp -> Com -> Com -> FH -> FH -> FH- FHWhile :: Assertion -> BExp -> Com -> FH -> FH - FHConPre :: Assertion -> Assertion -> Assertion -> Com -> Valid -> FH -> FH - FHConPost :: Assertion -> Assertion -> Assertion -> Com -> FH -> Valid -> FH --{-@ data FH where - FHSkip :: p:_- -> Prop (FH p Skip p) - FHAssign :: q:_ -> x:_ -> a:_- -> Prop (FH (bsubst x a q) (Assign x a) q) - FHSeq :: p:_ -> c1:_ -> q:_ -> c2:_ -> r:_ - -> Prop (FH p c1 q) - -> Prop (FH q c2 r) - -> Prop (FH p (Seq c1 c2) r) - FHIf :: p:_ -> q:_ -> b:_ -> c1:_ -> c2:_- -> Prop (FH (bAnd p b) c1 q) - -> Prop (FH (bAnd p (Not b)) c2 q)- -> Prop (FH p (If b c1 c2) q)- FHWhile :: p:_ -> b:_ -> c:_- -> Prop (FH (bAnd p b) c p) - -> Prop (FH p (While b c) (bAnd p (Not b)))- FHConPre :: p':_ -> p:_ -> q:_ -> c:_ - -> Imply p' p- -> Prop (FH p c q) - -> Prop (FH p' c q)- FHConPost :: p:_ -> q:_ -> q':_ -> c:_ - -> Prop (FH p c q) - -> Imply q q'- -> Prop (FH p c q')- @-}------------------------------------------------------------------------------------- | THEOREM: Soundness of Floyd-Hoare Logic ------------------------------------------------------------------------------------ thm_fh_legit :: p:_ -> c:_ -> q:_ -> Prop (FH p c q) -> Legit p c q--------------------------------------------------------------------------------------------- | Making FH Algorithmic: Verification Conditions ----------------------------------------------------------------------------------data ICom - = ISkip -- skip - | IAssign Vname AExp -- x := a- | ISeq ICom ICom -- c1; c2- | IIf BExp ICom ICom -- if b then c1 else c2- | IWhile BExp BExp ICom -- while {I} b c - deriving (Show)--{-@ reflect pre @-}-pre :: ICom -> Assertion -> Assertion -pre ISkip q = q-pre (IAssign x a) q = bsubst x a q -pre (ISeq c1 c2) q = pre c1 (pre c2 q)-pre (IIf b c1 c2) q = bIte b (pre c1 q) (pre c2 q) -pre (IWhile i _ _) _ = i --{-@ reflect vc @-}-vc :: ICom -> Assertion -> Assertion-vc ISkip _ = tt -vc (IAssign {}) _ = tt -vc (ISeq c1 c2) q = (vc c1 (pre c2 q)) `bAnd` (vc c2 q)-vc (IIf _ c1 c2) q = (vc c1 q) `bAnd` (vc c2 q)-vc (IWhile i b c) q = ((bAnd i b) `bImp` (pre c i)) `bAnd` - ((bAnd i (Not b)) `bImp` q ) `bAnd`- vc c i--{-@ reflect strip @-}-strip :: ICom -> Com -strip ISkip = Skip -strip (IAssign x a) = Assign x a -strip (ISeq c1 c2) = Seq (strip c1) (strip c2)-strip (IIf b c1 c2) = If b (strip c1) (strip c2)-strip (IWhile _ b c) = While b (strip c)---------------------------------------------------------------------------------------- | THEOREM: Soundness of VC--------------------------------------------------------------------------------------- thm_vc :: c:_ -> q:_ -> Valid (vc c q) -> Legit (pre c q) (strip c) q---------------------------------------------------------------------------------------- | Extending the above to triples [HW] --------------------------------------------------------------------------------------{-@ reflect vc' @-}-vc' :: Assertion -> ICom -> Assertion -> Assertion -vc' p c q = bAnd (bImp p (pre c q)) (vc c q) ---------------------------------------------------------------------------------------- | THEOREM: Soundness of VC'--------------------------------------------------------------------------------------- thm_vc' :: p:_ -> c:_ -> q:_ -> Valid (vc' p c q) -> Legit p (strip c) q
@@ -1,170 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--diff" @-}--module Lec_3_15 () where --import ProofCombinators-import qualified State as S-import Expressions -import Imp -import BigStep hiding (And)-import Axiomatic --imports = (FH undefined undefined undefined)--------------------------------------------------------------------- TODO: Move into FloydHoare.hs -------------------------------------------------------------------------------------------------------------------------------------- | Lets build a 'verify'-er-------------------------------------------------------------------{-@ verify :: p:_ -> c:_ -> q:_ -> Valid (vc' p c q) -> () @-}-verify :: Assertion -> ICom -> Assertion -> Valid -> () -verify _ _ _ _ = () -{-------------------------------------------------------------------ex1 :: () -> ()-ex1 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IAssign "x" (N 5) -- x := 50- q = Equal (V "x") (N 5) -- { x == 5 }-- -- p => pre c q /\ vc c q- -- VC = (True => 5 = 5) /\ True - -- pre = 50 == 5 -------------------------------------------------------------------}--ex2 :: () -> () -ex2 _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 2) -- { x = 2 } - c = IAssign "x" (Plus (V "x") (N 1)) -- x := x + 1- q = Equal (V "x") (N 3) -- { x = 3 }-- -- p => pre c q /\ vc c q- -- VC = (x=2 => x+1=3) /\ True - -- pre = x+1 = 3 -------------------------------------------------------------------{--ex2a :: () -> () -ex2a _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 2) -- { x = 2 } - c = c1 `ISeq` c1 -- x := x + 1 - c1 = IAssign "x" (Plus (V "x") (N 1)) -- x := x + 1- q = Equal (V "x") (N 4) -- { x = 4 }--------------------------------------------------------------------ex4 :: () -> () -ex4 _ = verify p (c1 `ISeq` c2) q (\_ -> ()) - where - p = tt -- { True } - c1 = IAssign "x" (N 5) -- x := 5 - c2 = IAssign "y" (V "x") -- y := x - q = Equal (V "y") (N 5) -- { y = 5 }-------------------------------------------------------------------ex5 :: () -> () -ex5 _ = verify p c q (\_ -> ()) - where - p = ((V "x") `Equal` (N 2)) `bAnd` - ((V "x") `Equal` (N 3)) -- { x = 2 && x = 3} - c = IAssign "x" (N 5) -- x := 5- q = V "x" `Equal` N 0 -- { x = 0}--------------------------------------------------------------------}-ex8 :: () -> () -ex8 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IWhile i tt ISkip -- WHILE_i true SKIP - q = ff -- { false }- i = tt-------------------------------------------------------------------ex9 :: () -> () -ex9 _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 0) -- { x = 0 } - c = IWhile i (Leq (V "x") (N 0)) -- WHILE_i (x <= 0) DO- (IAssign "x" (Plus (V "x") (N 1))) -- x := x + 1- q = Equal (V "x") (N 1) -- { x = 1 } - i = bOr p (Equal (V "x") (N 1))-- -- x=0 => (x=0 || x=1)- -- {(x=0 || x=1) /\ x <= 0 } x := x+1 {x=0 || x=1}- -- (x=0|| x=1) /\ x > 0 => x = 1------------------------------------------------------------------ex10 :: () -> () -ex10 _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 1) -- { x = 1 } - c = IWhile i (Not (Leq (V "x") (N 0))) -- WHILE (x > 0) DO- (IAssign "x" (Plus (V "x") (N 1))) -- x := x + 1- q = Equal (V "x") (N 100) -- { x = 100 } - i = undefined -- TODO: In class-- -- P => I - -- {I && b} c { I }- -- I && !b => Q - -- x>0 &&& not ( x > 0 ) => Q- -- I := x > 0 -{------------------------------------------------------------------------------------ | Example 1: branching----------------------------------------------------------------------------------bx1 :: () -> () -bx1 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IIf (Equal (V "x") (N 0)) -- IF x == 0 - (IAssign "y" (N 2)) -- THEN y := 2- (IAssign "y" (Plus (V "x") (N 1))) -- ELSE y := x + 1- q = Leq (V "x") (V "y") -- { x <= y } ------------------------------------------------------------------------------------ | Example 2: Swapping Using Addition and Subtraction ----------------------------------------------------------------------------------} --bx2 :: () -> () -bx2 _ = verify p c q (\_ -> ()) - where - p = (V "x" `Equal` V "a") - `bAnd` (V "y" `Equal` V "b") -- { x = a && y = b } - c = IAssign "x" (Plus (V "x") (V "y")) -- x := x + y- `ISeq` IAssign "y" (Minus (V "x") (V "y")) -- y := x - y- `ISeq` IAssign "x" (Minus (V "x") (V "y")) -- x := x - y- q = (V "x" `Equal` V "b") -- { x = b && y = a } - `bAnd` (V "y" `Equal` V "a") -- -- vc' = x=a & y=b => (x+y-(x+y-y) =b && (x+y)-y=a) && true & True & true- -- pre = (x+y-(x+y-y) =b && (x+y)-y=a)- -- vc = true & true & true -{------------------------------------------------------------------------------------ | Example 4: Reduce to Zero ----------------------------------------------------------------------------------bx4 :: () -> () -bx4 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IWhile i (Not (Equal (V "x") (N 0))) -- WHILE not (x == 0) DO: - (IAssign "x" (Minus (V "x") (N 1))) -- x := x - 1- q = (V "x" `Equal` N 0) -- { x = 0 } - i = tt ------}
@@ -1,183 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE IncoherentInstances #-}--module ProofCombinators (-- -- ATTENTION! `Admit` and `(==!)` are UNSAFE: they should not belong the final proof term-- -- * Proof is just a () alias- Proof- , toProof -- -- * Proof constructors- , trivial, unreachable, (***), QED(..)-- -- * "Because" combinator - , (?)-- -- * These two operators check all intermediate equalities- , (===) -- proof of equality is implicit eg. x === y- , (=<=) -- proof of equality is implicit eg. x <= y- , (=>=) -- proof of equality is implicit eg. x =>= y -- -- * This operator does not check intermediate equalities- , (==.) -- -- Uncheck operator used only for proof debugging- , (==!) -- x ==! y always succeds-- -- * Combining Proofs- , (&&&)- , withProof - , impossible ---) where------------------------------------------------------------------------------------ | Proof is just a () alias -----------------------------------------------------------------------------------------------------------------------------------type Proof = ()--toProof :: a -> Proof-toProof _ = ()------------------------------------------------------------------------------------ | Proof Construction ------------------------------------------------------------------------------------------------------------------------------------------- | trivial is proof by SMT--trivial :: Proof-trivial = ()---- {-@ unreachable :: {v : Proof | False } @-}-unreachable :: Proof-unreachable = ()---- All proof terms are deleted at runtime.-{- RULE "proofs are irrelevant" forall (p :: Proof). p = () #-}---- | proof casting--- | `x *** QED`: x is a proof certificate* strong enough for SMT to prove your theorem--- | `x *** Admit`: x is an unfinished proof--infixl 3 ***-{-@ assume (***) :: a -> p:QED -> { if (isAdmit p) then false else true } @-}-(***) :: a -> QED -> Proof-_ *** _ = ()--data QED = Admit | QED--{-@ measure isAdmit :: QED -> Bool @-}-{-@ Admit :: {v:QED | isAdmit v } @-}------------------------------------------------------------------------------------- | * Checked Proof Certificates --------------------------------------------------------------------------------------------------------------------------------- Any (refined) carries proof certificates.--- For example 42 :: {v:Int | v == 42} is a certificate that--- the value 42 is equal to 42.--- But, this certificate will not really be used to proof any fancy theorems.---- Below we provide a number of equational operations--- that constuct proof certificates.---- | Implicit equality---- x === y returns the proof certificate that--- result value is equal to both x and y--- when y == x (as assumed by the operator's precondition)--infixl 3 ===-{-@ (===) :: x:a -> y:{a | y == x} -> {v:a | v == x && v == y} @-}-(===) :: a -> a -> a-_ === y = y--infixl 3 =<=-{-@ (=<=) :: x:a -> y:{a | x <= y} -> {v:a | x <= y && v == y} @-}-(=<=) :: a -> a -> a-_ =<= y = y--infixl 3 =>=-{-@ (=>=) :: x:a -> y:{a | x >= y} -> {v:a | x >= y && v == y} @-}-(=>=) :: a -> a -> a-_ =>= y = y------------------------------------------------------------------------------------ | `?` is basically Haskell's $ and is used for the right precedence--- | `?` lets you "add" some fact into a proof term----------------------------------------------------------------------------------infixl 3 ?--{-@ (?) :: forall a b <pa :: a -> Bool, pb :: b -> Bool>. a<pa> -> b<pb> -> a<pa> @-}-(?) :: a -> b -> a -x ? _ = x -{-# INLINE (?) #-} ------------------------------------------------------------------------------------ | Assumed equality--- `x ==! y `--- returns the admitted proof certificate that result value is equals x and y----------------------------------------------------------------------------------infixl 3 ==!-{-@ assume (==!) :: x:a -> y:a -> {v:a | v == x && v == y} @-}-(==!) :: a -> a -> a-(==!) _ y = y----- | To summarize:------ - (==!) is *only* for proof debugging--- - (===) does not require explicit proof term--- - (?) lets you insert "lemmas" as other `Proof` values------------------------------------------------------------------------------------ | * Unchecked Proof Certificates ------------------------------------------------------------------------------------------------------------------------------- | The above operators check each intermediate proof step.--- The operator `==.` below accepts an optional proof term--- argument, but does not check intermediate steps.--- TODO: What is it USEFUL FOR?--infixl 3 ==.--{-# DEPRECATED (==.) "Use (===) instead" #-}--{-# INLINE (==.) #-} -(==.) :: a -> a -> a -_ ==. x = x ------------------------------------------------------------------------------------ | * Combining Proof Certificates -----------------------------------------------------------------------------------------------------------------------------(&&&) :: Proof -> Proof -> Proof-x &&& _ = x---{-@ withProof :: x:a -> b -> {v:a | v = x} @-}-withProof :: a -> b -> a-withProof x _ = x--{-@ impossible :: {v:a | false} -> b @-}-impossible :: a -> b-impossible _ = undefined------------------------------------------------------------------------------------ | Convenient Syntax for Inductive Propositions ----------------------------------------------------------------------------------{-@ measure prop :: a -> b @-}-{-@ type Prop E = {v:_ | prop v = E} @-}---
@@ -1,473 +0,0 @@--The Simply Typed Lambda Calculus -================================ - -A formalization of the Simply Typed Lambda Calculus (STLC) in the style -of [Jeremy Siek](http://siek.blogspot.com/2013/05/type-safety-in-three-easy-lemmas.html)--\begin{code}-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--no-termination" @-}--{-# LANGUAGE GADTs #-}--module STLC where --import ProofCombinators-\end{code}---Variables ------------\begin{code} -type Var = String -\end{code} --Types and Environments-------------------------\begin{code}-data Type - = TInt -- ^ `TInt` is `Int` - | TBool -- ^ `TBool` is `Bool`- | TFun Type Type -- ^ `TFun t1 t2` is `t1 -> t2`- deriving (Eq, Show) --data TEnv - = TBind Var Type TEnv -- ^ x:t, G- | TEmp -- ^ Empty environment- deriving (Eq, Show) -\end{code}--Terms --------\begin{code}-data Op - = Add -- ^ `Add` is `+` - | Leq -- ^ `Leq` is `<=`- | And -- ^ `And` is `&&`- deriving (Eq, Show) --data Expr - = EBool Bool -- ^ 'EBool b' is 'b'- | EInt Int -- ^ 'EInt i' is 'i'- | EBin Op Expr Expr -- ^ 'EBin op e1 e2' is 'e1 `op` e2'- | EVar Var -- ^ 'EVar x' is 'x'- | EFun Var Var Type Expr -- ^ 'EFun f x t e' is 'fun f(x:t) e'- | EApp Expr Expr -- ^ 'EApp e1 e2' is 'e1 e2' - deriving (Eq, Show) -\end{code}---Values and Stores --------------------\begin{code}-data Val - = VBool Bool - | VInt Int- | VClos Var Var Expr Store- deriving (Eq, Show) --data Store - = VBind Var Val Store - | VEmp - deriving (Eq, Show) -\end{code}---Evaluation Result --------------------\begin{code}-data Result - = Result Val - | Stuck - | Timeout- deriving (Eq, Show) -\end{code}---Dynamic Semantics (Evaluator)------------------------------ --Big-Step? Small-Step?--\begin{code}-{-@ reflect eval @-}-eval :: Store -> Expr -> Result -eval _ (EBool b) = Result (VBool b)-eval _ (EInt n) = Result (VInt n)-eval s (EBin o e1 e2) = seq2 (evalOp o) (eval s e1) (eval s e2) -eval s (EVar x) = case lookupStore x s of - Nothing -> Stuck - Just v -> Result v -eval s (EFun f x t e) = Result (VClos f x e s) -eval s (EApp e1 e2) = seq2 evalApp (eval s e1) (eval s e2)--{-@ reflect evalApp @-}-evalApp :: Val -> Val -> Result -evalApp v1@(VClos f x e s) v2 = eval (VBind x v2 (VBind f v1 s)) e -evalApp _ _ = Stuck --{-@ reflect evalOp @-}-evalOp :: Op -> Val -> Val -> Result -evalOp Add (VInt n1) (VInt n2) = Result (VInt (n1 + n2))-evalOp Leq (VInt n1) (VInt n2) = Result (VBool (n1 <= n2))-evalOp And (VBool b1) (VBool b2) = Result (VBool (b1 && b2)) -evalOp _ _ _ = Stuck --{-@ reflect lookupStore @-}-lookupStore :: Var -> Store -> Maybe Val -lookupStore x VEmp = Nothing -lookupStore x (VBind y v env) = if x == y then Just v else lookupStore x env-\end{code}--Helper to *sequence* sub-computations.--\begin{code}-{-@ reflect seq2 @-}-seq2 :: (Val -> Val -> Result) -> Result -> Result -> Result-seq2 f r1 r2 = case r1 of - Stuck -> Stuck - Timeout -> Timeout - Result v1 -> case r2 of - Stuck -> Stuck - Timeout -> Timeout - Result v2 -> f v1 v2-\end{code}--Tests before proofs ----------------------\begin{code}-tests :: [Expr]-tests = [ e1 -- 15- , EBin Leq e1 e1 -- True- , EBin And e1 e1 -- Stuck!- ]- where - e1 = EBin Add (EInt 5) (EInt 10)-\end{code}--Static Semantics (aka Static Typing Rules) ----------------------------------------------**Typing Results** --[ . |- r : T ]--- |- v : T - -------------------- [R_Res]- |- Result v : T -- -------------------- [R_Time]- |- Timeout : T --\begin{code}-{-@ data ResTy where- R_Res :: x:Val -> t:Type -> Prop (ValTy x t) -> Prop (ResTy (Result x) t) - R_Time :: t:Type -> Prop (ResTy Timeout t) - @-}--data ResTyP where - ResTy :: Result -> Type -> ResTyP --data ResTy where - R_Res :: Val -> Type -> ValTy -> ResTy - R_Time :: Type -> ResTy -\end{code}--**Typing Values**--[ |- v : T ] -- ----------------------- [V_Bool]- |- VBool b : TBool-- ----------------------- [V_Int]- |- VInt i : TInt - - G |- s (x,t1), (f,t1->t2),G |- e : t2 - --------------------------------------- [V_Clos]- |- VClos f x e s : t1 -> t2 --\begin{code}-{-@ data ValTy where- V_Bool :: b:Bool -> Prop (ValTy (VBool b) TBool) - V_Int :: i:Int -> Prop (ValTy (VInt i) TInt) - V_Clos :: g:TEnv -> s:Store -> f:Var -> x:Var -> t1:Type -> t2:Type -> e:Expr - -> Prop (StoTy g s) - -> Prop (ExprTy (TBind x t1 (TBind f (TFun t1 t2) g)) e t2)- -> Prop (ValTy (VClos f x e s) (TFun t1 t2)) - @-}--data ValTyP where - ValTy :: Val -> Type -> ValTyP --data ValTy where - V_Bool :: Bool -> ValTy - V_Int :: Int -> ValTy - V_Clos :: TEnv -> Store -> Var -> Var -> Type -> Type -> Expr -> StoTy -> ExprTy -> ValTy -\end{code}--**Typing Stores**--[ G |- S ] -- ------------------------[S_Emp]- TEmp |- VEmp -- |- v : t g |- s - ------------------------[S_Bind]- (x, t), g |- (x, v), s --\begin{code}-{-@ data StoTy where- S_Emp :: Prop (StoTy TEmp VEmp) - S_Bind :: x:Var -> t:Type -> val:Val -> g:TEnv -> s:Store- -> Prop (ValTy val t) - -> Prop (StoTy g s) - -> Prop (StoTy (TBind x t g) (VBind x val s)) - @-}--data StoTyP where - StoTy :: TEnv -> Store -> StoTyP --data StoTy where - S_Emp :: StoTy - S_Bind :: Var -> Type -> Val -> TEnv -> Store -> ValTy -> StoTy -> StoTy -\end{code}--**Typing Expressions**-- --------------------------------------[E-Bool]- G |- EBool b : TBool-- --------------------------------------[E-Int]- G |- EInt n : TInt -- lookupTEnv x G = Just t- --------------------------------------[E-Var]- G |- Var x : t -- G |- e1 : opIn o G |- e2 : opIn o - --------------------------------------[E-Bin]- G |- EBin o e1 e2 : opOut o--- (x,t1), (f, t1->t2), G |- e : t2 - --------------------------------------[E-Fun]- G |- EFun f x t1 e : t1 -> t2 -- G |- e1 : t1 -> t2 G |- e2 : t1 - --------------------------------------[E-App]- G |- EApp e1 e2 : t2 --\begin{code}-{-@ reflect opIn @-}-opIn :: Op -> Type -opIn Add = TInt -opIn Leq = TInt -opIn And = TBool--{-@ reflect opOut @-}-opOut :: Op -> Type -opOut Add = TInt -opOut Leq = TBool -opOut And = TBool--{-@ reflect lookupTEnv @-}-lookupTEnv :: Var -> TEnv -> Maybe Type -lookupTEnv x TEmp = Nothing -lookupTEnv x (TBind y v env) = if x == y then Just v else lookupTEnv x env---{-@ data ExprTy where - E_Bool :: g:TEnv -> b:Bool - -> Prop (ExprTy g (EBool b) TBool)- E_Int :: g:TEnv -> i:Int - -> Prop (ExprTy g (EInt i) TInt)- E_Bin :: g:TEnv -> o:Op -> e1:Expr -> e2:Expr - -> Prop (ExprTy g e1 (opIn o)) - -> Prop (ExprTy g e2 (opIn o))- -> Prop (ExprTy g (EBin o e1 e2) (opOut o))- E_Var :: g:TEnv -> x:Var -> t:{Type| lookupTEnv x g == Just t} - -> Prop (ExprTy g (EVar x) t)- E_Fun :: g:TEnv -> f:Var -> x:Var -> t1:Type -> e:Expr -> t2:Type- -> Prop (ExprTy (TBind x t1 (TBind f (TFun t1 t2) g)) e t2)- -> Prop (ExprTy g (EFun f x t1 e) (TFun t1 t2)) - E_App :: g:TEnv -> e1:Expr -> e2:Expr -> t1:Type -> t2:Type - -> Prop (ExprTy g e1 (TFun t1 t2))- -> Prop (ExprTy g e2 t1)- -> Prop (ExprTy g (EApp e1 e2) t2)- @-}-data ExprTyP where - ExprTy :: TEnv -> Expr -> Type -> ExprTyP --data ExprTy where - E_Bool :: TEnv -> Bool -> ExprTy - E_Int :: TEnv -> Int -> ExprTy - E_Var :: TEnv -> Var -> Type -> ExprTy - E_Bin :: TEnv -> Op -> Expr -> Expr -> ExprTy -> ExprTy -> ExprTy - E_Fun :: TEnv -> Var -> Var -> Type -> Expr -> Type -> ExprTy -> ExprTy - E_App :: TEnv -> Expr -> Expr -> Type -> Type -> ExprTy -> ExprTy -> ExprTy -\end{code}--Lemma 1: "evalOp_safe" --------------------------\begin{code}-{-@ reflect isValTy @-}-isValTy :: Val -> Type -> Bool -isValTy (VInt _) TInt = True -isValTy (VBool _) TBool = True -isValTy _ _ = False --{-@ propValTy :: o:Op -> w:Val -> Prop (ValTy w (opIn o)) -> { w' : Val | w = w' && isValTy w' (opIn o) } @-}-propValTy :: Op -> Val -> ValTy -> Val -propValTy Add w (V_Int _) = w -propValTy Leq w (V_Int _) = w -propValTy And w (V_Bool _) = w --{-@ evalOp_safe - :: o:Op -> v1:{Val | isValTy v1 (opIn o) } -> v2:{Val | isValTy v2 (opIn o) } - -> (v :: Val, ( {y:() | evalOp o v1 v2 == Result v} , {z:ValTy | prop z = ValTy v (opOut o)}))- @-}-evalOp_safe :: Op -> Val -> Val -> (Val, ((), ValTy))-evalOp_safe Add (VInt n1) (VInt n2) = (VInt n, ((), V_Int n)) where n = n1 + n2 -evalOp_safe Leq (VInt n1) (VInt n2) = (VBool b, ((), V_Bool b)) where b = n1 <= n2 -evalOp_safe And (VBool b1) (VBool b2) = (VBool b, ((), V_Bool b)) where b = b1 && b2 --{-@ evalOp_res_safe - :: o:Op -> r1:Result -> r2:Result- -> Prop (ResTy r1 (opIn o))- -> Prop (ResTy r2 (opIn o))- -> Prop (ResTy (seq2 (evalOp o) r1 r2) (opOut o)) - @-}-evalOp_res_safe :: Op -> Result -> Result -> ResTy -> ResTy -> ResTy-evalOp_res_safe o (Result v1) (Result v2) (R_Res _ t1 vt1) (R_Res _ t2 vt2) - = case evalOp_safe o (propValTy o v1 vt1) (propValTy o v2 vt2) of - (v, (_, vt)) -> R_Res v (opOut o) vt -evalOp_res_safe o _ _ (R_Time t1) _ - = R_Time (opOut o)-evalOp_res_safe o _ _ _ (R_Time t2) - = R_Time (opOut o)-\end{code}--Lemma 2: "lookup_safe"-------------------------\begin{code}-{-@ lookup_safe :: g:TEnv -> s:Store -> x:Var -> t:{Type | lookupTEnv x g == Just t} - -> Prop (StoTy g s) - -> (w :: Val, ({z:() | lookupStore x s == Just w} , {z:ValTy | prop z = ValTy w t} ))- @-}-lookup_safe :: TEnv -> Store -> Var -> Type -> StoTy -> (Val, ((), ValTy)) -lookup_safe _ _ _ _ S_Emp - = impossible () -lookup_safe g s x t (S_Bind y yt yv g' s' yvt gs') - | x == y - = (yv, ((), yvt)) - | otherwise - = lookup_safe g' s' x t gs' -\end{code}--Lemma 3: "app_safe" ----------------------\begin{code}-{-@ evalApp_safe - :: v1:Val -> v2:Val -> t1:Type -> t2:Type- -> Prop (ValTy v1 (TFun t1 t2)) - -> Prop (ValTy v2 t1)- -> Prop (ResTy (evalApp v1 v2) t2) - @-}-evalApp_safe :: Val -> Val -> Type -> Type -> ValTy -> ValTy -> ResTy -evalApp_safe v1@(VClos f x e s) v2 t1 t2 v1_t1_t2@(V_Clos g _ _ _ _ _ _ g_s gxf_e_t2) v2_t1 - = eval_safe gxf sxf e t2 gxf_e_t2 gxf_sxf - where - gf = TBind f (TFun t1 t2) g- sf = VBind f v1 s- gxf = TBind x t1 gf - sxf = VBind x v2 sf - gf_sf = S_Bind f (TFun t1 t2) v1 g s v1_t1_t2 g_s - gxf_sxf = S_Bind x t1 v2 gf sf v2_t1 gf_sf - -evalApp_safe (VInt {}) _ _ _ (V_Clos {}) _ - = impossible () --evalApp_safe (VBool {}) _ _ _ (V_Clos {}) _ - = impossible () -----{-@ evalApp_res_safe - :: r1:Result -> r2:Result -> t1:Type -> t2:Type- -> Prop (ResTy r1 (TFun t1 t2)) - -> Prop (ResTy r2 t1)- -> Prop (ResTy (seq2 evalApp r1 r2) t2)- @-}-evalApp_res_safe :: Result -> Result -> Type -> Type -> ResTy -> ResTy -> ResTy -evalApp_res_safe (Result v1) (Result v2) t1 t2 (R_Res _ _ v1_t1_t2) (R_Res _ _ v2_t1)- = evalApp_safe v1 v2 t1 t2 v1_t1_t2 v2_t1 -evalApp_res_safe _ _ _ t2 (R_Time {}) _ - = R_Time t2 -evalApp_res_safe _ _ _ t2 _ (R_Time {}) - = R_Time t2 -\end{code}--THEOREM: "eval_safe" -----------------------\begin{code}-{-@ eval_safe :: g:TEnv -> s:Store -> e:Expr -> t:Type - -> Prop (ExprTy g e t) - -> Prop (StoTy g s) - -> Prop (ResTy (eval s e) t) - @-}-eval_safe :: TEnv -> Store -> Expr -> Type -> ExprTy -> StoTy -> ResTy --eval_safe _ _ (EBool b) _ (E_Bool {}) _ - = R_Res (VBool b) TBool (V_Bool b) - -eval_safe _ _ (EInt n) _ (E_Int {}) _ - = R_Res (VInt n) TInt (V_Int n) --eval_safe g s (EBin o e1 e2) t (E_Bin _ _ _ _ et1 et2) gs- = evalOp_res_safe o (eval s e1) (eval s e2) rt1 rt2 - where - rt1 = eval_safe g s e1 (opIn o) et1 gs- rt2 = eval_safe g s e2 (opIn o) et2 gs--eval_safe g s (EVar x) t (E_Var {}) gs - = R_Res w t wt - where - (w, (_, wt)) = lookup_safe g s x t gs --eval_safe g s (EFun f x t1 e) t (E_Fun _ _ _ _ _ t2 et2) gs - = R_Res (VClos f x e s) t (V_Clos g s f x t1 t2 e gs et2)- -eval_safe g s (EApp e1 e2) t2 (E_App _ _ _ t1 _ e1_t1_t2 e2_t1) gs - = evalApp_res_safe (eval s e1) (eval s e2) t1 t2 r1_t1_t2 r2_t1 - where - r1_t1_t2 = eval_safe g s e1 (TFun t1 t2) e1_t1_t2 gs - r2_t1 = eval_safe g s e2 t1 e2_t1 gs-\end{code} --Boilerplate --------------{-@ measure prop :: a -> b @-}-{-@ type Prop E = {v:_ | prop v = E} @-}--{-@ impossible :: {v:a | false} -> b @-}-impossible :: a -> b-impossible x = impossible x
@@ -1,32 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}--module State where--import Prelude hiding ((++), const, max)-import ProofCombinators--data GState k v = Init v | Bind k v (GState k v)--{-@ reflect init @-}-init :: v -> GState k v-init v = Init v--{-@ reflect set @-}-set :: GState k v -> k -> v -> GState k v-set s k v = Bind k v s--{-@ reflect get @-}-get :: (Eq k) => GState k v -> k -> v-get (Init v) _ = v-get (Bind k v s) key = if key == k then v else get s key--{-@ lemma_get_set :: k:_ -> v:_ -> s:_ -> { get (set s k v) k == v } @-}-lemma_get_set :: k -> v -> GState k v -> Proof -lemma_get_set _ _ _ = () --{-@ lemma_get_not_set :: k0:_ -> k:{k /= k0} -> val:_ -> s:_ - -> { get (set s k val) k0 = get s k0 } @-}-lemma_get_not_set :: k -> k -> v -> GState k v -> Proof -lemma_get_not_set _ _ _ (Bind {}) = ()-lemma_get_not_set _ _ _ (Init {}) = ()
@@ -1,149 +0,0 @@-{-@ LIQUID "--reflection" @-}-{-@ LIQUID "--ple" @-}-{-@ LIQUID "--diff" @-}--module Verifier () where --import ProofCombinators-import qualified State as S-import Expressions -import Imp -import BigStep hiding (And)-import Axiomatic --imports = (FH undefined undefined undefined)--------------------------------------------------------------------- TODO: Move into FloydHoare.hs -------------------------------------------------------------------------------------------------------------------------------------- | Lets build a 'verify'-er-------------------------------------------------------------------{-@ verify :: p:_ -> c:_ -> q:_ -> Valid (vc' p c q) -> () @-}-verify :: Assertion -> ICom -> Assertion -> Valid -> () -verify _ _ _ _ = () -------------------------------------------------------------------ex1 :: () -> ()-ex1 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IAssign "x" (N 5) -- x := 5- q = Equal (V "x") (N 5) -- { x == 5 }--------------------------------------------------------------------ex2 :: () -> () -ex2 _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 2) -- { x = 2 } - c = IAssign "x" (Plus (V "x") (N 1)) -- x := x + 1- q = Equal (V "x") (N 3) -- { x = 3 }--------------------------------------------------------------------ex2a :: () -> () -ex2a _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 2) -- { x = 2 } - c = c1 `ISeq` c1 -- x := x + 1 - c1 = IAssign "x" (Plus (V "x") (N 1)) -- x := x + 1- q = Equal (V "x") (N 4) -- { x = 4 }--------------------------------------------------------------------ex4 :: () -> () -ex4 _ = verify p (c1 `ISeq` c2) q (\_ -> ()) - where - p = tt -- { True } - c1 = IAssign "x" (N 5) -- x := 5 - c2 = IAssign "y" (V "x") -- y := x - q = Equal (V "y") (N 5) -- { y = 5 }-------------------------------------------------------------------ex5 :: () -> () -ex5 _ = verify p c q (\_ -> ()) - where - p = ((V "x") `Equal` (N 2)) `bAnd` - ((V "x") `Equal` (N 3)) -- { x = 2 && x = 3} - c = IAssign "x" (N 5) -- x := 5- q = V "x" `Equal` N 0 -- { x = 0}--------------------------------------------------------------------ex8 :: () -> () -ex8 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IWhile i tt ISkip -- WHILE_i true SKIP - q = ff -- { false }- i = tt -- undefined -- TODO: In class--------------------------------------------------------------------ex9 :: () -> () -ex9 _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 0) -- { x = 0 } - c = IWhile i (Leq (V "x") (N 0)) -- WHILE_i (x <= 0) DO- (IAssign "x" (Plus (V "x") (N 1))) -- x := x + 1- q = Equal (V "x") (N 1) -- { x = 1 } - i = undefined -- TODO: In class-------------------------------------------------------------------ex10 :: () -> () -ex10 _ = verify p c q (\_ -> ()) - where - p = Equal (V "x") (N 1) -- { x = 1 } - c = IWhile i (Not (Leq (V "x") (N 0))) -- WHILE_i not (x <= 0) DO- (IAssign "x" (Plus (V "x") (N 1))) -- x := x + 1- q = Equal (V "x") (N 100) -- { x = 100 } - i = undefined -- TODO: In class------------------------------------------------------------------------------------ | Example 1: branching----------------------------------------------------------------------------------bx1 :: () -> () -bx1 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IIf (Equal (V "x") (N 0)) -- IF x == 0 - (IAssign "y" (N 2)) -- THEN y := 2- (IAssign "y" (Plus (V "x") (N 1))) -- ELSE y := x + 1- q = Leq (V "x") (V "y") -- { x <= y } ------------------------------------------------------------------------------------ | Example 2: Swapping Using Addition and Subtraction ----------------------------------------------------------------------------------bx2 :: () -> () -bx2 _ = verify p c q (\_ -> ()) - where - p = (V "x" `Equal` V "a") - `bAnd` (V "y" `Equal` V "b") -- { x = a && y = b } - c = IAssign "x" (Plus (V "x") (V "y")) -- x := x + y- `ISeq` IAssign "y" (Minus (V "x") (V "y")) -- y := x - y- `ISeq` IAssign "x" (Minus (V "x") (V "y")) -- x := x - y- q = (V "x" `Equal` V "b") -- { x = a && y = b } - `bAnd` (V "y" `Equal` V "a") ------------------------------------------------------------------------------------- | Example 4: Reduce to Zero ----------------------------------------------------------------------------------bx4 :: () -> () -bx4 _ = verify p c q (\_ -> ()) - where - p = tt -- { true } - c = IWhile i (Not (Equal (V "x") (N 0))) -- WHILE not (x == 0) DO: - (IAssign "x" (Minus (V "x") (N 1))) -- x := x - 1- q = (V "x" `Equal` N 0) -- { x = 0 } - i = tt ----
@@ -1,175 +0,0 @@-{-@ LIQUID "--no-termination" @-}--module LiquidArray where--import Language.Haskell.Liquid.Prelude (liquidAssume)--data Vec a = V (Int -> a)-{-@-data Vec a <dom :: Int -> Bool, rng :: Int -> a -> Bool>- = V {a :: i:Int<dom> -> a <rng i>}- @-}---{-@ empty :: forall <p :: Int -> a -> Bool>. Vec <{\v -> 0=1}, p> a @-}-empty :: Vec a-empty = V $ \_ -> (error "Empty array!")---{-@ create :: x:a -> Vec <{\v -> 0=0}, {\i v-> v=x}> a @-}-create :: a -> Vec a-create x = V $ \_ -> x--{-@ get :: forall a <r :: x0: Int -> x1: a -> Bool, d :: x0: Int -> Bool>.- i: Int<d> ->- a: Vec<d, r> a ->- a<r i> @-}-get :: Int -> Vec a -> a-get i (V f) = f i--{-@ set :: forall a <r :: x0: Int -> x1: a -> Bool, d :: x0: Int -> Bool>.- i: Int<d> ->- x: a<r i> ->- a: Vec <{v:Int<d> | v != i}, r> a -> - Vec <d, r> a @-}-set :: Int -> a -> Vec a -> Vec a-set i v (V f) = V $ \k -> if k == i then v else f k--------------------------------------------------------------------------------------------------------------- init array ------------------------------------------------------------------------------------------------------------------------{-@ zero ::- i: {v: Int | v >= 0} ->- n: Int ->- a: Vec <{\v -> (0 <= v && v < i)}, {\d v -> v = 0}> Int ->- Vec <{\v -> (0 <= v && v < n)}, {\d v -> v = 0}> Int @-}-zero :: Int -> Int -> Vec Int -> Vec Int-zero i n a = if i >= n then a- else zero (i + 1) n (set i 0 a)-{-@ tenZeroes :: Vec <{\v -> (0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}-tenZeroes = zero z ten empty- where z = 0- ten = 10 --{-@ zeroBackwards ::- i: Int ->- n: {v: Int | v > i} ->- a: Vec <{\v -> (i < v && v < n)}, {\d v -> v = 0}> Int ->- Vec <{\v -> (0 <= v && v < n)}, {\d v -> v = 0}> Int @-}-zeroBackwards :: Int -> Int -> Vec Int -> Vec Int-zeroBackwards i n a = if i < 0 then a- else zeroBackwards (i - 1) n (set i 0 a)---{-@ tenZeroes' :: Vec <{\v -> (0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}-tenZeroes' :: Vec Int-tenZeroes' = zeroBackwards nine ten empty- where nine = 9- ten = 10--{-@ zeroEveryOther ::- i: {v: Int | (v >= 0 && v mod 2 = 0)} ->- n: Int ->- a: Vec <{\v -> (0 <= v && v < i && v mod 2 = 0)}, {\d v -> v = 0}> Int ->- Vec <{\v -> (0 <= v && v < n && v mod 2 = 0)}, {\d v -> v = 0}> Int @-}-zeroEveryOther :: Int -> Int -> Vec Int -> Vec Int-zeroEveryOther i n a = if i >= n then a- else zeroEveryOther (i + 2) n (set i 0 a)--{-@ stridedZeroes ::- Vec <{\v -> (v mod 2 = 0 && 0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}-stridedZeroes :: Vec Int-stridedZeroes = zeroEveryOther z ten empty- where z = 0- ten = 10--{-@ initArray :: forall a <p :: x0: Int -> x1: a -> Bool>.- f: Vec <{\v -> 0=0}, p> a ->- i: {v: Int | v >= 0} ->- n: Int ->- a: Vec <{\v -> (0 <= v && v < i)}, p> a ->- Vec <{\v -> (0 <= v && v < n)}, p> a @-}-initArray :: Vec a -> Int -> Int -> Vec a -> Vec a-initArray (V f) i n a = if i >= n then a- else initArray (V f) (i + 1) n (set i (f i) a)--{-@ zeroInitArray ::- i: {v: Int | v >= 0} ->- n: Int ->- a: Vec <{\v -> (0 <= v && v < i)}, {\d v -> v = 0}> Int ->- Vec <{\v -> (0 <= v && v < n)}, {\d v -> v = 0}> Int @-}-zeroInitArray :: Int -> Int -> Vec Int -> Vec Int-zeroInitArray = initArray (V (\_ -> 0))--{-@ tenZeroes'' :: Vec <{\v -> (0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}-tenZeroes'' :: Vec Int-tenZeroes'' = zeroInitArray z ten empty- where z = 0- ten = 10 --{-@ initid ::- i: {v: Int | v >= 0} ->- n: Int ->- a: Vec <{\v -> (0 <= v && v < i)}, {\j v -> v = j}> Int ->- Vec <{\v -> (0 <= v && v < n)}, {\k v -> v = k}> Int @-}-initid :: Int -> Int -> Vec Int -> Vec Int-initid = initArray (V id)-------------------------------------------------------------------------------------------------------------- null terms ------------------------------------------------------------------------------------------------------------------------{-@ upperCaseString' ::- n: {v: Int | v > 0} ->- i: {v: Nat | v < n} ->- s: Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int ->- Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int-@-}-upperCaseString' :: Int -> Int -> Vec Int -> Vec Int-upperCaseString' n i s =- let c = get i s in- if c == 0 then s- else upperCaseString' n (i + 1) (set i (c + 32) s)--{-@ upperCaseString ::- n: {v: Int | v > 0} ->- s: Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int ->- Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int-@-}-upperCaseString :: Int -> Vec Int -> Vec Int-upperCaseString n s = upperCaseString' n 0 s---------------------------------------------------------------------------------------------------------------- memoization -----------------------------------------------------------------------------------------------------------------------{-@ measure fib :: Int -> Int @-}-{-@ type FibV = Vec <{\v -> 0=0}, {\j v -> ((v != 0) => (v = fib(j)))}> Int @-}---{-@ assume axiom_fib :: i:Int -> {v: Bool | v <=> (fib i = (if i <= 1 then 1 else (fib (i-1) + fib (i-2)))) } @-}-axiom_fib :: Int -> Bool-axiom_fib i = undefined--{-@ fastFib :: x:Int -> {v:Int | v = fib(x)} @-}-fastFib :: Int -> Int-fastFib n = snd $ fibMemo (V (\_ -> 0)) n---{-@ fibMemo :: FibV -> i:Int -> (FibV, {v: Int | v = fib(i)}) @-}-fibMemo :: Vec Int -> Int -> (Vec Int, Int)-fibMemo t i - | i <= 1 - = (t, liquidAssume (axiom_fib i) (1 :: Int))- - | otherwise - = case get i t of - 0 -> let (t1, n1) = fibMemo t (i-1)- (t2, n2) = fibMemo t1 (i-2)- n = liquidAssume (axiom_fib i) (n1 + n2)- in (set i n t2, n)- n -> (t, n)-
@@ -1,3 +0,0 @@-qualif Bound1(v: Data.Map.Base.Map k a , x : k): ((isBin v) => (x < (key v)))-qualif Bound2(v: Data.Map.Base.Map k a , x : k): ((isBin v) => (x > (key v)))-
@@ -1,3167 +0,0 @@-{-@ LIQUID "--prune-unsorted" @-}-{-@ LIQUID "--bscope" @-}--{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__--- LIQUID {- LANGUAGE DeriveDataTypeable, StandaloneDeriving -}-#endif-#if !defined(TESTING) && __GLASGOW_HASKELL__ >= 703-{-# LANGUAGE Trustworthy #-}-#endif--------------------------------------------------------------------------------- |--- Module : Data.Map.Base--- Copyright : (c) Daan Leijen 2002--- (c) Andriy Palamarchuk 2008--- License : BSD-style--- Maintainer : libraries@haskell.org--- Stability : provisional--- Portability : portable------ An efficient implementation of maps from keys to values (dictionaries).------ Since many function names (but not the type name) clash with--- "Prelude" names, this module is usually imported @qualified@, e.g.------ > import Data.Map (Map)--- > import qualified Data.Map as Map------ The implementation of 'Map' is based on /size balanced/ binary trees (or--- trees of /bounded balance/) as described by:------ * Stephen Adams, \"/Efficient sets: a balancing act/\",--- Journal of Functional Programming 3(4):553-562, October 1993,--- <http://www.swiss.ai.mit.edu/~adams/BB/>.------ * J. Nievergelt and E.M. Reingold,--- \"/Binary search trees of bounded balance/\",--- SIAM journal of computing 2(1), March 1973.------ Note that the implementation is /left-biased/ -- the elements of a--- first argument are always preferred to the second, for example in--- 'union' or 'insert'.------ Operation comments contain the operation time complexity in--- the Big-O notation <http://en.wikipedia.org/wiki/Big_O_notation>.---------------------------------------------------------------------------------- [Note: Using INLINABLE]--- ~~~~~~~~~~~~~~~~~~~~~~~--- It is crucial to the performance that the functions specialize on the Ord--- type when possible. GHC 7.0 and higher does this by itself when it sees th--- unfolding of a function -- that is why all public functions are marked--- INLINABLE (that exposes the unfolding).----- [Note: Using INLINE]--- ~~~~~~~~~~~~~~~~~~~~--- For other compilers and GHC pre 7.0, we mark some of the functions INLINE.--- We mark the functions that just navigate down the tree (lookup, insert,--- delete and similar). That navigation code gets inlined and thus specialized--- when possible. There is a price to pay -- code growth. The code INLINED is--- therefore only the tree navigation, all the real work (rebalancing) is not--- INLINED by using a NOINLINE.------ All methods marked INLINE have to be nonrecursive -- a 'go' function doing--- the real work is provided.----- [Note: Type of local 'go' function]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- If the local 'go' function uses an Ord class, it sometimes heap-allocates--- the Ord dictionary when the 'go' function does not have explicit type.--- In that case we give 'go' explicit type. But this slightly decrease--- performance, as the resulting 'go' function can float out to top level.----- [Note: Local 'go' functions and capturing]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- As opposed to IntMap, when 'go' function captures an argument, increased--- heap-allocation can occur: sometimes in a polymorphic function, the 'go'--- floats out of its enclosing function and then it heap-allocates the--- dictionary and the argument. Maybe it floats out too late and strictness--- analyzer cannot see that these could be passed on stack.------ For example, change 'member' so that its local 'go' function is not passing--- argument k and then look at the resulting code for hedgeInt.----- [Note: Order of constructors]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- The order of constructors of Map matters when considering performance.--- Currently in GHC 7.0, when type has 2 constructors, a forward conditional--- jump is made when successfully matching second constructor. Successful match--- of first constructor results in the forward jump not taken.--- On GHC 7.0, reordering constructors from Tip | Bin to Bin | Tip--- improves the benchmark by up to 10% on x86.--module Data.Map.Base (-- -- * Map type- Map(..) -- instance Eq,Show,Read-- , mlen-- -- * Operators- , (!), (\\)-- -- * Query- , null- , size- , member- , notMember- , lookup- , findWithDefault- , lookupLT- , lookupGT- , lookupLE- , lookupGE-- -- * Construction- , empty- , singleton-- -- ** Insertion- , insert- , insertWith- , insertWithKey- , insertLookupWithKey-- -- ** Delete\/Update- , delete- , adjust- , adjustWithKey- , update- , updateWithKey- , updateLookupWithKey- , alter-- -- * Combine-- -- ** Union- , union- , unionWith- , unionWithKey- , unions- , unionsWith-- -- ** Difference- , difference- , differenceWith- , differenceWithKey-- -- ** Intersection- , intersection- , intersectionWith- , intersectionWithKey-- -- ** Universal combining function- , mergeWithKey-- -- * Traversal- -- ** Map- , map- , mapWithKey- -- LIQUID, traverseWithKey- , mapAccum- , mapAccumWithKey- , mapAccumRWithKey- , mapKeys- , mapKeysWith- , mapKeysMonotonic-- -- * Folds- , foldr- , foldl- , foldrWithKey- , foldlWithKey- -- ** Strict folds- , foldr'- , foldl'- , foldrWithKey'- , foldlWithKey'-- -- * Conversion- , elems- , keys- , assocs- -- LIQUID, keysSet- -- LIQUID, fromSet-- -- ** Lists- , toList- , fromList- , fromListWith- , fromListWithKey-- -- ** Ordered lists- , toAscList- , toDescList- , fromAscList- , fromAscListWith- , fromAscListWithKey- , fromDistinctAscList-- -- * Filter- , filter- , filterWithKey- , partition- , partitionWithKey-- , mapMaybe- , mapMaybeWithKey- , mapEither- , mapEitherWithKey-- , split- , splitLookup-- -- * Submap- , isSubmapOf, isSubmapOfBy- , isProperSubmapOf, isProperSubmapOfBy-- -- * Indexed- , lookupIndex- , findIndex- , elemAt- , updateAt- , deleteAt-- -- * Min\/Max- , findMin- , findMax- , deleteMin- , deleteMax- , deleteFindMin- , deleteFindMax- , updateMin- , updateMax- , updateMinWithKey- , updateMaxWithKey- , minView- , maxView- , minViewWithKey- , maxViewWithKey-- -- * Debugging- , showTree- , showTreeWith- , valid-- -- Used by the strict version- , bin- , balance- , balanced- , balanceL- , balanceR- , delta- , join- , merge- , glue- , trim, zoo1, zoo2- , trimLookupLo- , foldlStrict- , MaybeS(..)- , filterGt- , filterLt- ) where--import Prelude hiding (error,lookup,map,filter,foldr,foldl,null)--- LIQUID import qualified Data.Set.Base as Set--- LIQUID import Data.StrictPair-import Data.Monoid (Monoid(..))--- LIQUID import Control.Applicative (Applicative(..), (<$>))-import Data.Traversable (Traversable(traverse))-import qualified Data.Foldable as Foldable--- import Data.Typeable-import Control.DeepSeq (NFData(rnf))--#if __GLASGOW_HASKELL__-import GHC.Exts ( build )-import Text.Read-import Data.Data-#endif---- Use macros to define strictness of functions.--- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.--- We do not use BangPatterns, because they are not in any standard and we--- want the compilers to be compiled by as many compilers as possible.-#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined-#define STRICT_1_OF_3(fn) fn arg _ _ | arg `seq` False = undefined-#define STRICT_2_OF_3(fn) fn _ arg _ | arg `seq` False = undefined-#define STRICT_1_OF_4(fn) fn arg _ _ _ | arg `seq` False = undefined-#define STRICT_2_OF_4(fn) fn _ arg _ _ | arg `seq` False = undefined--{-@ lazy error @-}-{-@ error :: a -> b @-}-error :: a -> b-error x = error x--{--------------------------------------------------------------------- Operators---------------------------------------------------------------------}-infixl 9 !,\\ ------ | /O(log n)/. Find the value at a key.--- Calls 'error' when the element can not be found.------ > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map--- > fromList [(5,'a'), (3,'b')] ! 5 == 'a'--{-@ Data.Map.Base.! :: (Ord k) => OMap k a -> k -> a @-}-(!) :: Ord k => Map k a -> k -> a-m ! k = find k m-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (!) #-}-#endif---- | Same as 'difference'.-{-@ Data.Map.Base.\\ :: Ord k => OMap k a -> OMap k b -> OMap k a @-}-(\\) :: Ord k => Map k a -> Map k b -> Map k a-m1 \\ m2 = difference m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE (\\) #-}-#endif--{--------------------------------------------------------------------- Size balanced trees.---------------------------------------------------------------------}--- | A Map from keys @k@ to values @a@.---- See Note: Order of constructors-data Map k a = Bin { mSize :: Size- , key :: k - , value :: a- , left :: (Map k a) - , right :: (Map k a)- }- | Tip--type Size = Int--{- include <Base.hquals> @-}--{-@ qualif_bound1 :: x:k -> {v:Map k a | ((isBin v) => (x < (key v))) } @-}-{-@ qualif_bound2 :: x:k -> {v:Map k a | ((isBin v) => (x > (key v))) } @-}-qualif_bound1, qualif_bound2 :: k -> Map k a-qualif_bound1 = undefined -qualif_bound2 = undefined --- --{-@ data Map [mlen] k a <l :: root:k -> k -> Bool, r :: root:k -> k -> Bool>- = Bin (mSize :: Size)- (key :: k)- (value :: a)- (left :: Map <l, r> (k <l key>) a)- (right :: Map <l, r> (k <r key>) a)- | Tip- @-}--{-@ type SumMLen A B = {v:Nat | v = (mlen A) + (mlen B)} @-}--{-@ invariant {v:Map k a | (mlen v) >= 0} @-}--{- mlen :: m:Map k a -> {v:Nat | v = (mlen m)} -}--{- measure mlen :: (Map k a) -> Int- mlen(Tip) = 0- mlen(Bin s k v l r) = 1 + (mlen l) + (mlen r)- -}--{-@ measure mlen @-}-mlen :: Map k a -> Int-mlen Tip = 0-mlen (Bin s k v l r) = 1 + mlen l + mlen r--{-@ type OMap k a = Map <{\root v -> v < root}, {\root v -> v > root}> k a @-}--{-@ measure isJustS :: forall a. MaybeS a -> Bool- isJustS (JustS x) = true- isJustS NothingS = false-@-}--{-@ measure fromJustS :: forall a. MaybeS a -> a- fromJustS (JustS x) = x- @-}--{-@ measure isBin :: Map k a -> Bool- isBin (Bin sz kx x l r) = true- isBin Tip = false- @-}--{-@ invariant {v0: MaybeS {v: a | ((isJustS v0) && (v = (fromJustS v0)))} | true} @-}--{-@ predicate IfDefLe X Y = ((isJustS X) => ((fromJustS X) < Y)) @-}-{-@ predicate IfDefLt X Y = ((isJustS X) => ((fromJustS X) < Y)) @-}-{-@ predicate IfDefGt X Y = ((isJustS X) => (Y < (fromJustS X))) @-}-{-@ predicate RootLt Lo V = ((isBin V) => (IfDefLt Lo (key V))) @-}-{-@ predicate RootGt Hi V = ((isBin V) => (IfDefGt Hi (key V))) @-}-{-@ predicate RootBetween Lo Hi V = ((RootLt Lo V) && (RootGt Hi V)) @-}-{-@ predicate KeyBetween Lo Hi V = ((IfDefLt Lo V) && (IfDefGt Hi V)) @-}----- LIQUID instance (Ord k) => Monoid (Map k v) where--- mempty = empty--- mappend = union--- mconcat = unions--#if __GLASGOW_HASKELL__--{--------------------------------------------------------------------- A Data instance---------------------------------------------------------------------}---- This instance preserves data abstraction at the cost of inefficiency.--- We omit reflection services for the sake of data abstraction.--- LIQUID instance (Data k, Data a, Ord k) => Data (Map k a) where--- LIQUID gfoldl f z m = z fromList `f` toList m--- LIQUID toConstr _ = error "toConstr"--- LIQUID gunfold _ _ = error "gunfold"--- LIQUID dataTypeOf _ = mkNoRepType "Data.Map.Map"--- LIQUID dataCast2 f = gcast2 f-#endif--{--------------------------------------------------------------------- Query---------------------------------------------------------------------}--- | /O(1)/. Is the map empty?------ > Data.Map.null (empty) == True--- > Data.Map.null (singleton 1 'a') == False--null :: Map k a -> Bool-null Tip = True-null (Bin {}) = False-{-# INLINE null #-}---- | /O(1)/. The number of elements in the map.------ > size empty == 0--- > size (singleton 1 'a') == 1--- > size (fromList([(1,'a'), (2,'c'), (3,'b')])) == 3--size :: Map k a -> Int-size Tip = 0-size (Bin sz _ _ _ _) = sz-{-# INLINE size #-}----- | /O(log n)/. Lookup the value at a key in the map.------ The function will return the corresponding value as @('Just' value)@,--- or 'Nothing' if the key isn't in the map.------ An example of using @lookup@:------ > import Prelude hiding (lookup)--- > import Data.Map--- >--- > employeeDept = fromList([("John","Sales"), ("Bob","IT")])--- > deptCountry = fromList([("IT","USA"), ("Sales","France")])--- > countryCurrency = fromList([("USA", "Dollar"), ("France", "Euro")])--- >--- > employeeCurrency :: String -> Maybe String--- > employeeCurrency name = do--- > dept <- lookup name employeeDept--- > country <- lookup dept deptCountry--- > lookup country countryCurrency--- >--- > main = do--- > putStrLn $ "John's currency: " ++ (show (employeeCurrency "John"))--- > putStrLn $ "Pete's currency: " ++ (show (employeeCurrency "Pete"))------ The output of this program:------ > John's currency: Just "Euro"--- > Pete's currency: Nothing--{-@ lookup :: (Ord k) => k -> OMap k a -> Maybe a @-}-lookup :: Ord k => k -> Map k a -> Maybe a-lookup = go- where- STRICT_1_OF_2(go)- go _ Tip = Nothing- go k (Bin _ kx x l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> Just x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookup #-}-#else-{-# INLINE lookup #-}-#endif---- | /O(log n)/. Is the key a member of the map? See also 'notMember'.------ > member 5 (fromList [(5,'a'), (3,'b')]) == True--- > member 1 (fromList [(5,'a'), (3,'b')]) == False--{-@ member :: (Ord k) => k -> OMap k a -> Bool @-}-member :: Ord k => k -> Map k a -> Bool-member = go- where- STRICT_1_OF_2(go)- go _ Tip = False- go k (Bin _ kx _ l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> True-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE member #-}-#else-{-# INLINE member #-}-#endif---- | /O(log n)/. Is the key not a member of the map? See also 'member'.------ > notMember 5 (fromList [(5,'a'), (3,'b')]) == False--- > notMember 1 (fromList [(5,'a'), (3,'b')]) == True--{-@ notMember :: (Ord k) => k -> OMap k a -> Bool @-}-notMember :: Ord k => k -> Map k a -> Bool-notMember k m = not $ member k m-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE notMember #-}-#else-{-# INLINE notMember #-}-#endif---- | /O(log n)/. Find the value at a key.--- Calls 'error' when the element can not be found.--{-@ find :: (Ord k) => k -> OMap k a -> a @-}-find :: Ord k => k -> Map k a -> a-find = go- where- STRICT_1_OF_2(go)- go _ Tip = error "Map.!: given key is not an element in the map"- go k (Bin _ kx x l r) = case compare k kx of- LT -> go k l- GT -> go k r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE find #-}-#else-{-# INLINE find #-}-#endif---- | /O(log n)/. The expression @('findWithDefault' def k map)@ returns--- the value at key @k@ or returns default value @def@--- when the key is not in the map.------ > findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) == 'x'--- > findWithDefault 'x' 5 (fromList [(5,'a'), (3,'b')]) == 'a'--{-@ findWithDefault :: (Ord k) => a -> k -> OMap k a -> a @-}-findWithDefault :: Ord k => a -> k -> Map k a -> a-findWithDefault = go- where- STRICT_2_OF_3(go)- go def _ Tip = def- go def k (Bin _ kx x l r) = case compare k kx of- LT -> go def k l- GT -> go def k r- EQ -> x-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findWithDefault #-}-#else-{-# INLINE findWithDefault #-}-#endif---- | /O(log n)/. Find largest key smaller than the given one and return the--- corresponding (key, value) pair.------ > lookupLT 3 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLT 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')-{-@ lookupLT :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupLT :: Ord k => k -> Map k v -> Maybe (k, v)-lookupLT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) | k <= kx = goNothing k l- | otherwise = goJust k kx x r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) | k <= kx = goJust k kx' x' l- | otherwise = goJust k kx x r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLT #-}-#else-{-# INLINE lookupLT #-}-#endif---- | /O(log n)/. Find smallest key greater than the given one and return the--- corresponding (key, value) pair.------ > lookupGT 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGT 5 (fromList [(3,'a'), (5,'b')]) == Nothing-{-@ lookupGT :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupGT :: Ord k => k -> Map k v -> Maybe (k, v)-lookupGT = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) | k < kx = goJust k kx x l- | otherwise = goNothing k r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) | k < kx = goJust k kx x l- | otherwise = goJust k kx' x' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGT #-}-#else-{-# INLINE lookupGT #-}-#endif---- | /O(log n)/. Find largest key smaller or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupLE 2 (fromList [(3,'a'), (5,'b')]) == Nothing--- > lookupLE 4 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupLE 5 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')-{-@ lookupLE :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupLE :: Ord k => k -> Map k v -> Maybe (k, v)-lookupLE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) = case compare k kx of LT -> goNothing k l- EQ -> Just (kx, x)- GT -> goJust k kx x r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx' x' l- EQ -> Just (kx, x)- GT -> goJust k kx x r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupLE #-}-#else-{-# INLINE lookupLE #-}-#endif---- | /O(log n)/. Find smallest key greater or equal to the given one and return--- the corresponding (key, value) pair.------ > lookupGE 3 (fromList [(3,'a'), (5,'b')]) == Just (3, 'a')--- > lookupGE 4 (fromList [(3,'a'), (5,'b')]) == Just (5, 'b')--- > lookupGE 6 (fromList [(3,'a'), (5,'b')]) == Nothing-{-@ lookupGE :: (Ord k) => k -> OMap k v -> Maybe (k, v) @-}-lookupGE :: Ord k => k -> Map k v -> Maybe (k, v)-lookupGE = goNothing- where- STRICT_1_OF_2(goNothing)- goNothing _ Tip = Nothing- goNothing k (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx x l- EQ -> Just (kx, x)- GT -> goNothing k r-- STRICT_1_OF_4(goJust)- goJust _ kx' x' Tip = Just (kx', x')- goJust k kx' x' (Bin _ kx x l r) = case compare k kx of LT -> goJust k kx x l- EQ -> Just (kx, x)- GT -> goJust k kx' x' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupGE #-}-#else-{-# INLINE lookupGE #-}-#endif--{--------------------------------------------------------------------- Construction---------------------------------------------------------------------}--- | /O(1)/. The empty map.------ > empty == fromList []--- > size empty == 0-{-@ empty :: OMap k a @-}-empty :: Map k a-empty = Tip-{-# INLINE empty #-}---- | /O(1)/. A map with a single element.------ > singleton 1 'a' == fromList [(1, 'a')]--- > size (singleton 1 'a') == 1--{-@ singleton :: k -> a -> OMap k a @-}-singleton :: k -> a -> Map k a-singleton k x = Bin 1 k x Tip Tip-{-# INLINE singleton #-}--{--------------------------------------------------------------------- Insertion---------------------------------------------------------------------}--- | /O(log n)/. Insert a new key and value in the map.--- If the key is already present in the map, the associated value is--- replaced with the supplied value. 'insert' is equivalent to--- @'insertWith' 'const'@.------ > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]--- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]--- > insert 5 'x' empty == singleton 5 'x'---- See Note: Type of local 'go' function-{-@ insert :: (Ord k) => k -> a -> OMap k a -> OMap k a @-}-insert :: Ord k => k -> a -> Map k a -> Map k a-insert = insert_go---LIQUID insert = go---LIQUID where---LIQUID go :: Ord k => k -> a -> Map k a -> Map k a---LIQUID STRICT_1_OF_3(go)---LIQUID go kx x Tip = singleton kx x---LIQUID go kx x (Bin sz ky y l r) =---LIQUID case compare kx ky of---LIQUID -- Bin ky y (go kx x l) r---LIQUID LT -> balanceL ky y (go kx x l) r---LIQUID GT -> balanceR ky y l (go kx x r)---LIQUID EQ -> Bin sz kx x l r--{-@ insert_go :: (Ord k) => k -> a -> OMap k a -> OMap k a @-}-insert_go :: Ord k => k -> a -> Map k a -> Map k a-STRICT_1_OF_3(insert_go)-insert_go kx x Tip = singleton kx x-insert_go kx x (Bin sz ky y l r) =- case compare kx ky of- -- Bin ky y (insert_go kx x l) r- LT -> balanceL ky y (insert_go kx x l) r- GT -> balanceR ky y l (insert_go kx x r)- EQ -> Bin sz kx x l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insert #-}-#else-{-# INLINE insert #-}-#endif---- Insert a new key and value in the map if it is not already present.--- Used by `union`.---- See Note: Type of local 'go' function-insertR :: Ord k => k -> a -> Map k a -> Map k a-insertR = insertR_go---LIQUID insertR = go---LIQUID where---LIQUID go :: Ord k => k -> a -> Map k a -> Map k a---LIQUID STRICT_1_OF_3(go)---LIQUID go kx x Tip = singleton kx x---LIQUID go kx x t@(Bin _ ky y l r) =---LIQUID case compare kx ky of---LIQUID LT -> balanceL ky y (go kx x l) r---LIQUID GT -> balanceR ky y l (go kx x r)---LIQUID EQ -> t--insertR_go :: Ord k => k -> a -> Map k a -> Map k a-STRICT_1_OF_3(insertR_go)-insertR_go kx x Tip = singleton kx x-insertR_go kx x t@(Bin _ ky y l r) =- case compare kx ky of- LT -> balanceL ky y (insertR_go kx x l) r- GT -> balanceR ky y l (insertR_go kx x r)- EQ -> t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertR #-}-#else-{-# INLINE insertR #-}-#endif---- | /O(log n)/. Insert with a function, combining new value and old value.--- @'insertWith' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key, f new_value old_value)@.------ > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]--- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"--{-@ insertWith :: (Ord k) => (a -> a -> a) -> k -> a -> OMap k a -> OMap k a @-}-insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWith f = insertWithKey (\_ x' y' -> f x' y')-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWith #-}-#else-{-# INLINE insertWith #-}-#endif---- | /O(log n)/. Insert with a function, combining key, new value and old value.--- @'insertWithKey' f key value mp@--- will insert the pair (key, value) into @mp@ if key does--- not exist in the map. If the key does exist, the function will--- insert the pair @(key,f key new_value old_value)@.--- Note that the key passed to f is the same key passed to 'insertWithKey'.------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]--- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]--- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"---- See Note: Type of local 'go' function--{-@ insertWithKey :: (Ord k) => (k -> a -> a -> a) -> k -> a -> OMap k a -> OMap k a @-}-insertWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a-insertWithKey = insertWithKey_go---LIQUID insertWithKey = go---LIQUID where---LIQUID go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a---LIQUID STRICT_2_OF_4(go)---LIQUID go _ kx x Tip = singleton kx x---LIQUID go f kx x (Bin sy ky y l r) =---LIQUID case compare kx ky of---LIQUID LT -> balanceL ky y (go f kx x l) r---LIQUID GT -> balanceR ky y l (go f kx x r)---LIQUID EQ -> Bin sy kx (f kx x y) l r--{-@ insertWithKey_go :: (Ord k) => (k -> a -> a -> a) -> k -> a -> OMap k a -> OMap k a @-}-insertWithKey_go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a-STRICT_2_OF_4(insertWithKey_go)-insertWithKey_go _ kx x Tip = singleton kx x-insertWithKey_go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> balanceL ky y (insertWithKey_go f kx x l) r- GT -> balanceR ky y l (insertWithKey_go f kx x r)- EQ -> Bin sy kx (f kx x y) l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertWithKey #-}-#else-{-# INLINE insertWithKey #-}-#endif---- | /O(log n)/. Combines insert operation with old value retrieval.--- The expression (@'insertLookupWithKey' f k x map@)--- is a pair where the first element is equal to (@'lookup' k map@)--- and the second element equal to (@'insertWithKey' f k x map@).------ > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value--- > insertLookupWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "5:xxx|a")])--- > insertLookupWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "xxx")])--- > insertLookupWithKey f 5 "xxx" empty == (Nothing, singleton 5 "xxx")------ This is how to define @insertLookup@ using @insertLookupWithKey@:------ > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t--- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])--- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])---- See Note: Type of local 'go' function--{-@ insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> OMap k a -> (Maybe a, OMap k a) @-}-insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)-insertLookupWithKey = insertLookupWithKey_go---LIQUID insertLookupWithKey = go---LIQUID where---LIQUID go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)---LIQUID STRICT_2_OF_4(go)---LIQUID go _ kx x Tip = (Nothing, singleton kx x)---LIQUID go f kx x (Bin sy ky y l r) =---LIQUID case compare kx ky of---LIQUID LT -> let (found, l') = go f kx x l---LIQUID in (found, balanceL ky y l' r)---LIQUID GT -> let (found, r') = go f kx x r---LIQUID in (found, balanceR ky y l r')---LIQUID EQ -> (Just y, Bin sy kx (f kx x y) l r)--{-@ insertLookupWithKey_go :: Ord k => (k -> a -> a -> a) -> k -> a -> OMap k a -> (Maybe a, OMap k a) @-}-insertLookupWithKey_go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)-STRICT_2_OF_4(insertLookupWithKey_go)-insertLookupWithKey_go _ kx x Tip = (Nothing, singleton kx x)-insertLookupWithKey_go f kx x (Bin sy ky y l r) =- case compare kx ky of- LT -> let (found, l') = insertLookupWithKey_go f kx x l- in (found, balanceL ky y l' r)- GT -> let (found, r') = insertLookupWithKey_go f kx x r- in (found, balanceR ky y l r')- EQ -> (Just y, Bin sy kx (f kx x y) l r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE insertLookupWithKey #-}-#else-{-# INLINE insertLookupWithKey #-}-#endif--{--------------------------------------------------------------------- Deletion---------------------------------------------------------------------}--- | /O(log n)/. Delete a key and its value from the map. When the key is not--- a member of the map, the original map is returned.------ > delete 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > delete 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > delete 5 empty == empty---- See Note: Type of local 'go' function-{-@ delete :: (Ord k) => k -> OMap k a -> OMap k a @-}-delete :: Ord k => k -> Map k a -> Map k a-delete = delete_go---LIQUID delete = go---LIQUID where---LIQUID go :: Ord k => k -> Map k a -> Map k a---LIQUID STRICT_1_OF_2(go)---LIQUID go _ Tip = Tip---LIQUID go k (Bin _ kx x l r) =---LIQUID case compare k kx of---LIQUID LT -> balanceR kx x (go k l) r---LIQUID GT -> balanceL kx x l (go k r)---LIQUID EQ -> glue kx l r--{-@ delete_go :: (Ord k) => k -> OMap k a -> OMap k a @-}-delete_go :: Ord k => k -> Map k a -> Map k a-STRICT_1_OF_2(delete_go)-delete_go _ Tip = Tip-delete_go k (Bin _ kx x l r) =- case compare k kx of- LT -> balanceR kx x (delete_go k l) r- GT -> balanceL kx x l (delete_go k r)- EQ -> glue kx l r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE delete #-}-#else-{-# INLINE delete #-}-#endif---- | /O(log n)/. Update a value at a specific key with the result of the provided function.--- When the key is not--- a member of the map, the original map is returned.------ > adjust ("new " ++) 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > adjust ("new " ++) 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjust ("new " ++) 7 empty == empty--{-@ adjust :: (Ord k) => (a -> a) -> k -> OMap k a -> OMap k a @-}-adjust :: Ord k => (a -> a) -> k -> Map k a -> Map k a-adjust f = adjustWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjust #-}-#else-{-# INLINE adjust #-}-#endif---- | /O(log n)/. Adjust a value at a specific key. When the key is not--- a member of the map, the original map is returned.------ > let f key x = (show key) ++ ":new " ++ x--- > adjustWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > adjustWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > adjustWithKey f 7 empty == empty--{-@ adjustWithKey :: (Ord k) => (k -> a -> a) -> k -> OMap k a -> OMap k a @-}-adjustWithKey :: Ord k => (k -> a -> a) -> k -> Map k a -> Map k a-adjustWithKey f = updateWithKey (\k' x' -> Just (f k' x'))-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE adjustWithKey #-}-#else-{-# INLINE adjustWithKey #-}-#endif---- | /O(log n)/. The expression (@'update' f k map@) updates the value @x@--- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is--- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.------ > let f x = if x == "a" then Just "new a" else Nothing--- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")]--- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ update :: (Ord k) => (a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a-update f = updateWithKey (\_ x -> f x)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE update #-}-#else-{-# INLINE update #-}-#endif---- | /O(log n)/. The expression (@'updateWithKey' f k map@) updates the--- value @x@ at @k@ (if it is in the map). If (@f k x@) is 'Nothing',--- the element is deleted. If it is (@'Just' y@), the key @k@ is bound--- to the new value @y@.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")]--- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"---- See Note: Type of local 'go' function--{-@ updateWithKey :: (Ord k) => (k -> a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-updateWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a-updateWithKey = updateWithKey_go---LIQUID updateWithKey = go---LIQUID where---LIQUID go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a---LIQUID STRICT_2_OF_3(go)---LIQUID go _ _ Tip = Tip---LIQUID go f k(Bin sx kx x l r) =---LIQUID case compare k kx of---LIQUID LT -> balanceR kx x (go f k l) r---LIQUID GT -> balanceL kx x l (go f k r)---LIQUID EQ -> case f kx x of---LIQUID Just x' -> Bin sx kx x' l r---LIQUID Nothing -> glue kx l r-{-@ updateWithKey_go :: (Ord k) => (k -> a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-updateWithKey_go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> Map k a-STRICT_2_OF_3(updateWithKey_go)-updateWithKey_go _ _ Tip = Tip-updateWithKey_go f k(Bin sx kx x l r) =- case compare k kx of- LT -> balanceR kx x (updateWithKey_go f k l) r- GT -> balanceL kx x l (updateWithKey_go f k r)- EQ -> case f kx x of- Just x' -> Bin sx kx x' l r- Nothing -> glue kx l r--#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateWithKey #-}-#else-{-# INLINE updateWithKey #-}-#endif---- | /O(log n)/. Lookup and update. See also 'updateWithKey'.--- The function returns changed value, if it is updated.--- Returns the original key value if the map entry is deleted.------ > let f k x = if x == "a" then Just ((show k) ++ ":new a") else Nothing--- > updateLookupWithKey f 5 (fromList [(5,"a"), (3,"b")]) == (Just "5:new a", fromList [(3, "b"), (5, "5:new a")])--- > updateLookupWithKey f 7 (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a")])--- > updateLookupWithKey f 3 (fromList [(5,"a"), (3,"b")]) == (Just "b", singleton 5 "a")---- See Note: Type of local 'go' function--{-@ updateLookupWithKey :: (Ord k) => (k -> a -> Maybe a) -> k -> OMap k a -> (Maybe a, OMap k a) @-}-updateLookupWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)-updateLookupWithKey = updateLookupWithKey_go---LIQUID updateLookupWithKey = go---LIQUID where---LIQUID go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)---LIQUID STRICT_2_OF_3(go)---LIQUID go _ _ Tip = (Nothing,Tip)---LIQUID go f k (Bin sx kx x l r) =---LIQUID case compare k kx of---LIQUID LT -> let (found,l') = go f k l in (found,balanceR kx x l' r)---LIQUID GT -> let (found,r') = go f k r in (found,balanceL kx x l r')---LIQUID EQ -> case f kx x of---LIQUID Just x' -> (Just x',Bin sx kx x' l r)---LIQUID Nothing -> (Just x,glue kx l r)--{-@ updateLookupWithKey_go :: (Ord k) => (k -> a -> Maybe a) -> k -> OMap k a -> (Maybe a, OMap k a) @-}-updateLookupWithKey_go :: Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a,Map k a)-STRICT_2_OF_3(updateLookupWithKey_go)-updateLookupWithKey_go _ _ Tip = (Nothing,Tip)-updateLookupWithKey_go f k (Bin sx kx x l r) =- case compare k kx of- LT -> let (found,l') = updateLookupWithKey_go f k l in (found,balanceR kx x l' r)- GT -> let (found,r') = updateLookupWithKey_go f k r in (found,balanceL kx x l r')- EQ -> case f kx x of- Just x' -> (Just x',Bin sx kx x' l r)- Nothing -> (Just x,glue kx l r)--#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE updateLookupWithKey #-}-#else-{-# INLINE updateLookupWithKey #-}-#endif---- | /O(log n)/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.--- 'alter' can be used to insert, delete, or update a value in a 'Map'.--- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.------ > let f _ = Nothing--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- >--- > let f _ = Just "c"--- > alter f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "c")]--- > alter f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "c")]---- See Note: Type of local 'go' function--{-@ alter :: (Ord k) => (Maybe a -> Maybe a) -> k -> OMap k a -> OMap k a @-}-alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a-alter = alter_go---LIQUID alter = go---LIQUID where---LIQUID go :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a---LIQUID STRICT_2_OF_3(go)---LIQUID go f k Tip = case f Nothing of---LIQUID Nothing -> Tip---LIQUID Just x -> singleton k x---LIQUID---LIQUID go f k (Bin sx kx x l r) = case compare k kx of---LIQUID LT -> balance kx x (go f k l) r---LIQUID GT -> balance kx x l (go f k r)---LIQUID EQ -> case f (Just x) of---LIQUID Just x' -> Bin sx kx x' l r---LIQUID Nothing -> glue kx l r--alter_go :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a-STRICT_2_OF_3(alter_go)-alter_go f k Tip = case f Nothing of- Nothing -> Tip- Just x -> singleton k x--alter_go f k (Bin sx kx x l r) = case compare k kx of- LT -> balance kx x (alter_go f k l) r- GT -> balance kx x l (alter_go f k r)- EQ -> case f (Just x) of- Just x' -> Bin sx kx x' l r- Nothing -> glue kx l r--#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE alter #-}-#else-{-# INLINE alter #-}-#endif--{--------------------------------------------------------------------- Indexing---------------------------------------------------------------------}--- | /O(log n)/. Return the /index/ of a key. The index is a number from--- /0/ up to, but not including, the 'size' of the map. Calls 'error' when--- the key is not a 'member' of the map.------ > findIndex 2 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map--- > findIndex 3 (fromList [(5,"a"), (3,"b")]) == 0--- > findIndex 5 (fromList [(5,"a"), (3,"b")]) == 1--- > findIndex 6 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map---- See Note: Type of local 'go' function--{-@ findIndex :: (Ord k) => k -> OMap k a -> GHC.Types.Int @-}-findIndex :: Ord k => k -> Map k a -> Int-findIndex = findIndex_go 0---LIQUID findIndex = go 0---LIQUID where---LIQUID go :: Ord k => Int -> k -> Map k a -> Int---LIQUID STRICT_1_OF_3(go)---LIQUID STRICT_2_OF_3(go)---LIQUID go _ _ Tip = error "Map.findIndex: element is not in the map"---LIQUID go idx k (Bin _ kx _ l r) = case compare k kx of---LIQUID LT -> go idx k l---LIQUID GT -> go (idx + size l + 1) k r---LIQUID EQ -> idx + size l--{-@ findIndex_go :: (Ord k) => Int -> k -> OMap k a -> GHC.Types.Int @-}-{-@ decrease findIndex_go 4 @-}-findIndex_go :: Ord k => Int -> k -> Map k a -> Int-STRICT_1_OF_3(findIndex_go)-STRICT_2_OF_3(findIndex_go)-findIndex_go _ _ Tip = error "Map.findIndex: element is not in the map"-findIndex_go idx k (Bin _ kx _ l r) = case compare k kx of- LT -> findIndex_go idx k l- GT -> findIndex_go (idx + size l + 1) k r- EQ -> idx + size l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE findIndex #-}-#endif---- | /O(log n)/. Lookup the /index/ of a key. The index is a number from--- /0/ up to, but not including, the 'size' of the map.------ > isJust (lookupIndex 2 (fromList [(5,"a"), (3,"b")])) == False--- > fromJust (lookupIndex 3 (fromList [(5,"a"), (3,"b")])) == 0--- > fromJust (lookupIndex 5 (fromList [(5,"a"), (3,"b")])) == 1--- > isJust (lookupIndex 6 (fromList [(5,"a"), (3,"b")])) == False---- See Note: Type of local 'go' function-{-@ lookupIndex :: (Ord k) => k -> OMap k a -> Maybe GHC.Types.Int @-}-lookupIndex :: Ord k => k -> Map k a -> Maybe Int-lookupIndex = lookupIndex_go 0---LIQUID lookupIndex = go 0---LIQUID where---LIQUID go :: Ord k => Int -> k -> Map k a -> Maybe Int---LIQUID STRICT_1_OF_3(go)---LIQUID STRICT_2_OF_3(go)---LIQUID go _ _ Tip = Nothing---LIQUID go idx k (Bin _ kx _ l r) = case compare k kx of---LIQUID LT -> go idx k l---LIQUID GT -> go (idx + size l + 1) k r---LIQUID EQ -> Just $! idx + size l--{-@ lookupIndex_go :: (Ord k) => Int -> k -> OMap k a -> Maybe GHC.Types.Int @-}-{-@ decrease lookupIndex_go 4 @-}-lookupIndex_go :: Ord k => Int -> k -> Map k a -> Maybe Int-STRICT_1_OF_3(lookupIndex_go)-STRICT_2_OF_3(lookupIndex_go)-lookupIndex_go _ _ Tip = Nothing-lookupIndex_go idx k (Bin _ kx _ l r) = case compare k kx of- LT -> lookupIndex_go idx k l- GT -> lookupIndex_go (idx + size l + 1) k r- EQ -> Just $! idx + size l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE lookupIndex #-}-#endif---- | /O(log n)/. Retrieve an element by /index/. Calls 'error' when an--- invalid index is used.------ > elemAt 0 (fromList [(5,"a"), (3,"b")]) == (3,"b")--- > elemAt 1 (fromList [(5,"a"), (3,"b")]) == (5, "a")--- > elemAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range---{-@ elemAt :: GHC.Types.Int -> OMap k a -> (k, a) @-}-{-@ decrease elemAt 2 @-}-elemAt :: Int -> Map k a -> (k,a)-STRICT_1_OF_2(elemAt)-elemAt _ Tip = error "Map.elemAt: index out of range"-elemAt i (Bin _ kx x l r)- = case compare i sizeL of- LT -> elemAt i l- GT -> elemAt (i-sizeL-1) r- EQ -> (kx,x)- where- sizeL = size l---- | /O(log n)/. Update the element at /index/. Calls 'error' when an--- invalid index is used.------ > updateAt (\ _ _ -> Just "x") 0 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "x"), (5, "a")]--- > updateAt (\ _ _ -> Just "x") 1 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "x")]--- > updateAt (\ _ _ -> Just "x") 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\ _ _ -> Just "x") (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > updateAt (\_ _ -> Nothing) 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--{-@ updateAt :: (k -> a -> Maybe a) -> GHC.Types.Int -> OMap k a -> OMap k a @-}-{-@ decrease updateAt 3 @-}-updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a-updateAt f i t = i `seq`- case t of- Tip -> error "Map.updateAt: index out of range"- Bin sx kx x l r -> case compare i sizeL of- LT -> balanceR kx x (updateAt f i l) r- GT -> balanceL kx x l (updateAt f (i-sizeL-1) r)- EQ -> case f kx x of- Just x' -> Bin sx kx x' l r- Nothing -> glue kx l r- where- sizeL = size l---- | /O(log n)/. Delete the element at /index/.--- Defined as (@'deleteAt' i map = 'updateAt' (\k x -> 'Nothing') i map@).------ > deleteAt 0 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--- > deleteAt 1 (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > deleteAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range--- > deleteAt (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range--{-@ deleteAt :: GHC.Types.Int -> OMap k a -> OMap k a @-}-{-@ decrease deleteAt 2 @-}-deleteAt :: Int -> Map k a -> Map k a-deleteAt i t = i `seq`- case t of- Tip -> error "Map.deleteAt: index out of range"- Bin _ kx x l r -> case compare i sizeL of- LT -> balanceR kx x (deleteAt i l) r- GT -> balanceL kx x l (deleteAt (i-sizeL-1) r)- EQ -> glue kx l r- where- sizeL = size l---{--------------------------------------------------------------------- Minimal, Maximal---------------------------------------------------------------------}--- | /O(log n)/. The minimal key of the map. Calls 'error' if the map is empty.------ > findMin (fromList [(5,"a"), (3,"b")]) == (3,"b")--- > findMin empty Error: empty map has no minimal element--{-@ findMin :: OMap k a -> (k, a) @-}-findMin :: Map k a -> (k,a)-findMin (Bin _ kx x Tip _) = (kx,x)-findMin (Bin _ _ _ l _) = findMin l-findMin Tip = error "Map.findMin: empty map has no minimal element"---- | /O(log n)/. The maximal key of the map. Calls 'error' if the map is empty.------ > findMax (fromList [(5,"a"), (3,"b")]) == (5,"a")--- > findMax empty Error: empty map has no maximal element--{-@ findMax :: OMap k a -> (k, a) @-}-findMax :: Map k a -> (k,a)-findMax (Bin _ kx x _ Tip) = (kx,x)-findMax (Bin _ _ _ _ r) = findMax r-findMax Tip = error "Map.findMax: empty map has no maximal element"---- | /O(log n)/. Delete the minimal key. Returns an empty map if the map is empty.------ > deleteMin (fromList [(5,"a"), (3,"b"), (7,"c")]) == fromList [(5,"a"), (7,"c")]--- > deleteMin empty == empty---{-@ deleteMin :: OMap k a -> OMap k a @-}-deleteMin :: Map k a -> Map k a-deleteMin (Bin _ _ _ Tip r) = r-deleteMin (Bin _ kx x l r) = balanceR kx x (deleteMin l) r-deleteMin Tip = Tip---- | /O(log n)/. Delete the maximal key. Returns an empty map if the map is empty.------ > deleteMax (fromList [(5,"a"), (3,"b"), (7,"c")]) == fromList [(3,"b"), (5,"a")]--- > deleteMax empty == empty--{-@ deleteMax :: OMap k a -> OMap k a @-}-deleteMax :: Map k a -> Map k a-deleteMax (Bin _ _ _ l Tip) = l-deleteMax (Bin _ kx x l r) = balanceL kx x l (deleteMax r)-deleteMax Tip = Tip---- | /O(log n)/. Update the value at the minimal key.------ > updateMin (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "Xb"), (5, "a")]--- > updateMin (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ updateMin :: (a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMin :: (a -> Maybe a) -> Map k a -> Map k a-updateMin f m- = updateMinWithKey (\_ x -> f x) m---- | /O(log n)/. Update the value at the maximal key.------ > updateMax (\ a -> Just ("X" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "Xa")]--- > updateMax (\ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--{-@ updateMax :: (a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMax :: (a -> Maybe a) -> Map k a -> Map k a-updateMax f m- = updateMaxWithKey (\_ x -> f x) m----- | /O(log n)/. Update the value at the minimal key.------ > updateMinWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"3:b"), (5,"a")]--- > updateMinWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ updateMinWithKey :: (k -> a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMinWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMinWithKey _ Tip = Tip-updateMinWithKey f (Bin sx kx x Tip r) = case f kx x of- Nothing -> r- Just x' -> Bin sx kx x' Tip r-updateMinWithKey f (Bin _ kx x l r) = balanceR kx x (updateMinWithKey f l) r---- | /O(log n)/. Update the value at the maximal key.------ > updateMaxWithKey (\ k a -> Just ((show k) ++ ":" ++ a)) (fromList [(5,"a"), (3,"b")]) == fromList [(3,"b"), (5,"5:a")]--- > updateMaxWithKey (\ _ _ -> Nothing) (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--{-@ updateMaxWithKey :: (k -> a -> Maybe a) -> OMap k a -> OMap k a @-}-updateMaxWithKey :: (k -> a -> Maybe a) -> Map k a -> Map k a-updateMaxWithKey _ Tip = Tip-updateMaxWithKey f (Bin sx kx x l Tip) = case f kx x of- Nothing -> l- Just x' -> Bin sx kx x' l Tip-updateMaxWithKey f (Bin _ kx x l r) = balanceL kx x l (updateMaxWithKey f r)---- | /O(log n)/. Retrieves the minimal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > minViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((3,"b"), singleton 5 "a")--- > minViewWithKey empty == Nothing--{-@ minViewWithKey :: OMap k a -> Maybe (k, a, OMap k a) @-}-minViewWithKey :: Map k a -> Maybe (k, a, Map k a)-minViewWithKey Tip = Nothing-minViewWithKey x = Just (deleteFindMin x)---- | /O(log n)/. Retrieves the maximal (key,value) pair of the map, and--- the map stripped of that element, or 'Nothing' if passed an empty map.------ > maxViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((5,"a"), singleton 3 "b")--- > maxViewWithKey empty == Nothing--{-@ maxViewWithKey :: OMap k a -> Maybe (k, a, OMap k a) @-}-maxViewWithKey :: Map k a -> Maybe (k, a, Map k a)-maxViewWithKey Tip = Nothing-maxViewWithKey x = Just (deleteFindMax x)---- | /O(log n)/. Retrieves the value associated with minimal key of the--- map, and the map stripped of that element, or 'Nothing' if passed an--- empty map.------ > minView (fromList [(5,"a"), (3,"b")]) == Just ("b", singleton 5 "a")--- > minView empty == Nothing--{-@ minView :: OMap k a -> Maybe (a, OMap k a) @-}-minView :: Map k a -> Maybe (a, Map k a)-minView Tip = Nothing-minView x = let (_, m, t) = deleteFindMin x in Just (m ,t) -- (first snd $ deleteFindMin x)---- | /O(log n)/. Retrieves the value associated with maximal key of the--- map, and the map stripped of that element, or 'Nothing' if passed an------ > maxView (fromList [(5,"a"), (3,"b")]) == Just ("a", singleton 3 "b")--- > maxView empty == Nothing--{-@ maxView :: OMap k a -> Maybe (a, OMap k a) @-}-maxView :: Map k a -> Maybe (a, Map k a)-maxView Tip = Nothing-maxView x = let (_, m, t) = deleteFindMax x in Just (m, t)---- Update the 1st component of a tuple (special case of Control.Arrow.first)-first :: (a -> b) -> (a, c) -> (b, c)-first f (x, y) = (f x, y)--{--------------------------------------------------------------------- Union.---------------------------------------------------------------------}--- | The union of a list of maps:--- (@'unions' == 'Prelude.foldl' 'union' 'empty'@).------ > unions [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "b"), (5, "a"), (7, "C")]--- > unions [(fromList [(5, "A3"), (3, "B3")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "a"), (3, "b")])]--- > == fromList [(3, "B3"), (5, "A3"), (7, "C")]--{-@ unions :: (Ord k) => [OMap k a] -> OMap k a @-}-unions :: Ord k => [Map k a] -> Map k a-unions ts- = foldlStrict union empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unions #-}-#endif---- | The union of a list of maps, with a combining operation:--- (@'unionsWith' f == 'Prelude.foldl' ('unionWith' f) 'empty'@).------ > unionsWith (++) [(fromList [(5, "a"), (3, "b")]), (fromList [(5, "A"), (7, "C")]), (fromList [(5, "A3"), (3, "B3")])]--- > == fromList [(3, "bB3"), (5, "aAA3"), (7, "C")]--{-@ unionsWith :: (Ord k) => (a->a->a) -> [OMap k a] -> OMap k a @-}-unionsWith :: Ord k => (a->a->a) -> [Map k a] -> Map k a-unionsWith f ts- = foldlStrict (unionWith f) empty ts-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionsWith #-}-#endif---- | /O(n+m)/.--- The expression (@'union' t1 t2@) takes the left-biased union of @t1@ and @t2@.--- It prefers @t1@ when duplicate keys are encountered,--- i.e. (@'union' == 'unionWith' 'const'@).--- The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > union (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "a"), (7, "C")]--{-@ union :: (Ord k) => OMap k a -> OMap k a -> OMap k a @-}-union :: Ord k => Map k a -> Map k a -> Map k a-union Tip t2 = t2-union t1 Tip = t1-union t1 t2 = hedgeUnion NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE union #-}-#endif---- left-biased hedge union-{-@ hedgeUnion :: (Ord k) => lo: MaybeS k- -> hi: MaybeS {v: k | (IfDefLt lo v) }- -> OMap {v: k | (KeyBetween lo hi v) } a- -> {v: OMap k a | (RootBetween lo hi v) }- -> OMap {v: k | (KeyBetween lo hi v)} a @-}-hedgeUnion :: Ord a => MaybeS a -> MaybeS a -> Map a b -> Map a b -> Map a b-hedgeUnion _ _ t1 Tip = t1-hedgeUnion blo bhi Tip (Bin _ kx x l r) = join kx x (filterGt blo l) (filterLt bhi r)-hedgeUnion _ _ t1 (Bin _ kx x Tip Tip) = insertR kx x t1 -- According to benchmarks, this special case increases- -- performance up to 30%. It does not help in difference or intersection.-hedgeUnion blo bhi (Bin _ kx x l r) t2 = join kx x (hedgeUnion blo bmi l (trim blo bmi t2))- (hedgeUnion bmi bhi r (trim bmi bhi t2))- where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeUnion #-}-#endif--{--------------------------------------------------------------------- Union with a combining function---------------------------------------------------------------------}--- | /O(n+m)/. Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.------ > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]--{-@ unionWith :: (Ord k) => (a -> a -> a) -> OMap k a -> OMap k a -> OMap k a @-}-unionWith :: Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWith f m1 m2- = unionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWith #-}-#endif---- | /O(n+m)/.--- Union with a combining function. The implementation uses the efficient /hedge-union/ algorithm.--- Hedge-union is more efficient on (bigset \``union`\` smallset).------ > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value--- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]--{-@ unionWithKey :: (Ord k) => (k -> a -> a -> a) -> OMap k a -> OMap k a -> OMap k a @-}-unionWithKey :: Ord k => (k -> a -> a -> a) -> Map k a -> Map k a -> Map k a-unionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) (\ _ _ x -> x) (\ _ _ x -> x) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE unionWithKey #-}-#endif--{--------------------------------------------------------------------- Difference---------------------------------------------------------------------}--- | /O(n+m)/. Difference of two maps.--- Return elements of the first map not existing in the second map.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 3 "b"--{-@ difference :: (Ord k) => OMap k a -> OMap k b -> OMap k a @-}-difference :: Ord k => Map k a -> Map k b -> Map k a-difference Tip _ = Tip-difference t1 Tip = t1-difference t1 t2 = hedgeDiff NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE difference #-}-#endif--{-@ hedgeDiff :: (Ord k) => lo: MaybeS k- -> hi: MaybeS {v: k | (IfDefLt lo v) }- -> {v: OMap k a | (RootBetween lo hi v) }- -> OMap {v: k | (KeyBetween lo hi v) } b- -> OMap {v: k | (KeyBetween lo hi v) } a @-}-{-@ decrease hedgeDiff 5 @-}-hedgeDiff :: Ord a => MaybeS a -> MaybeS a -> Map a b -> Map a c -> Map a b-hedgeDiff _ _ Tip _ = Tip-hedgeDiff blo bhi (Bin _ kx x l r) Tip = join kx x (filterGt blo l) (filterLt bhi r)-hedgeDiff blo bhi t (Bin _ kx _ l r) = merge kx (hedgeDiff blo bmi (trim blo bmi t) l)- (hedgeDiff bmi bhi (trim bmi bhi t) r)- where bmi = JustS kx-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeDiff #-}-#endif---- | /O(n+m)/. Difference with a combining function.--- When two equal keys are--- encountered, the combining function is applied to the values of these keys.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f al ar = if al == "b" then Just (al ++ ":" ++ ar) else Nothing--- > differenceWith f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (7, "C")])--- > == singleton 3 "b:B"--{-@ differenceWith :: (Ord k) => (a -> b -> Maybe a) -> OMap k a -> OMap k b -> OMap k a @-}-differenceWith :: Ord k => (a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWith f m1 m2- = differenceWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWith #-}-#endif---- | /O(n+m)/. Difference with a combining function. When two equal keys are--- encountered, the combining function is applied to the key and both values.--- If it returns 'Nothing', the element is discarded (proper set difference). If--- it returns (@'Just' y@), the element is updated with a new value @y@.--- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.------ > let f k al ar = if al == "b" then Just ((show k) ++ ":" ++ al ++ "|" ++ ar) else Nothing--- > differenceWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (3, "B"), (10, "C")])--- > == singleton 3 "3:b|B"--{-@ differenceWithKey :: (Ord k) => (k -> a -> b -> Maybe a) -> OMap k a -> OMap k b -> OMap k a @-}-differenceWithKey :: Ord k => (k -> a -> b -> Maybe a) -> Map k a -> Map k b -> Map k a-differenceWithKey f t1 t2 = mergeWithKey f (\_ _ x -> x) (\ _ _ _ -> Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE differenceWithKey #-}-#endif---{--------------------------------------------------------------------- Intersection---------------------------------------------------------------------}--- | /O(n+m)/. Intersection of two maps.--- Return data in the first map for the keys existing in both maps.--- (@'intersection' m1 m2 == 'intersectionWith' 'const' m1 m2@).------ > intersection (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "a"--{-@ intersection :: (Ord k) => OMap k a -> OMap k b -> OMap k a @-}-intersection :: Ord k => Map k a -> Map k b -> Map k a-intersection Tip _ = Tip-intersection _ Tip = Tip-intersection t1 t2 = hedgeInt NothingS NothingS t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersection #-}-#endif--{-@ hedgeInt :: (Ord k) => lo: MaybeS k- -> hi: MaybeS {v: k | (IfDefLt lo v) }- -> OMap {v: k | (KeyBetween lo hi v) } a- -> {v: OMap k b | (RootBetween lo hi v) }- -> OMap {v: k | (KeyBetween lo hi v)} a @-}--hedgeInt :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k b -> Map k a-hedgeInt _ _ _ Tip = Tip-hedgeInt _ _ Tip _ = Tip-hedgeInt blo bhi (Bin _ kx x l r) t2 = let l' = hedgeInt blo bmi l (trim blo bmi t2)- r' = hedgeInt bmi bhi r (trim bmi bhi t2)- in if kx `member` t2 then join kx x l' r' else merge kx l' r'- where bmi = JustS kx--#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE hedgeInt #-}-#endif---- | /O(n+m)/. Intersection with a combining function.------ > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"--{-@ intersectionWith :: (Ord k) => (a -> b -> c) -> OMap k a -> OMap k b -> OMap k c @-}-intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWith f m1 m2- = intersectionWithKey (\_ x y -> f x y) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWith #-}-#endif---- | /O(n+m)/. Intersection with a combining function.--- Intersection is more efficient on (bigset \``intersection`\` smallset).------ > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar--- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"---{-@ intersectionWithKey :: (Ord k) => (k -> a -> b -> c) -> OMap k a -> OMap k b -> OMap k c @-}-intersectionWithKey :: Ord k => (k -> a -> b -> c) -> Map k a -> Map k b -> Map k c-intersectionWithKey f t1 t2 = mergeWithKey (\k x1 x2 -> Just $ f k x1 x2) (\ _ _ _ -> Tip) (\ _ _ _ -> Tip) t1 t2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE intersectionWithKey #-}-#endif---{--------------------------------------------------------------------- MergeWithKey---------------------------------------------------------------------}---- | /O(n+m)/. A high-performance universal combining function. This function--- is used to define 'unionWith', 'unionWithKey', 'differenceWith',--- 'differenceWithKey', 'intersectionWith', 'intersectionWithKey' and can be--- used to define other custom combine functions.------ Please make sure you know what is going on when using 'mergeWithKey',--- otherwise you can be surprised by unexpected code growth or even--- corruption of the data structure.------ When 'mergeWithKey' is given three arguments, it is inlined to the call--- site. You should therefore use 'mergeWithKey' only to define your custom--- combining functions. For example, you could define 'unionWithKey',--- 'differenceWithKey' and 'intersectionWithKey' as------ > myUnionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) id id m1 m2--- > myDifferenceWithKey f m1 m2 = mergeWithKey f id (const empty) m1 m2--- > myIntersectionWithKey f m1 m2 = mergeWithKey (\k x1 x2 -> Just (f k x1 x2)) (const empty) (const empty) m1 m2------ When calling @'mergeWithKey' combine only1 only2@, a function combining two--- 'IntMap's is created, such that------ * if a key is present in both maps, it is passed with both corresponding--- values to the @combine@ function. Depending on the result, the key is either--- present in the result with specified value, or is left out;------ * a nonempty subtree present only in the first map is passed to @only1@ and--- the output is added to the result;------ * a nonempty subtree present only in the second map is passed to @only2@ and--- the output is added to the result.------ The @only1@ and @only2@ methods /must return a map with a subset (possibly empty) of the keys of the given map/.--- The values can be modified arbitrarily. Most common variants of @only1@ and--- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@ or--- @'filterWithKey' f@ could be used for any @f@.--{-@ mergeWithKey :: (Ord k) => (k -> a -> b -> Maybe c)- -> (lo:MaybeS k -> hi: MaybeS k -> OMap {v: k | (KeyBetween lo hi v) } a -> OMap {v: k | (KeyBetween lo hi v) } c)- -> (lo:MaybeS k -> hi: MaybeS k -> OMap {v: k | (KeyBetween lo hi v) } b -> OMap {v: k | (KeyBetween lo hi v) } c)- -> OMap k a -> OMap k b -> OMap k c @-}-mergeWithKey :: Ord k => (k -> a -> b -> Maybe c) -> (MaybeS k -> MaybeS k -> Map k a -> Map k c) -> (MaybeS k -> MaybeS k -> Map k b -> Map k c)- -> Map k a -> Map k b -> Map k c-mergeWithKey f g1 g2 = go- where- go Tip t2 = g2 NothingS NothingS t2- go t1 Tip = g1 NothingS NothingS t1- go t1 t2 = hedgeMerge f g1 g2 NothingS NothingS t1 t2--{-@ hedgeMerge :: (Ord k) => (k -> a -> b -> Maybe c)- -> (lo:MaybeS k -> hi: MaybeS k -> OMap {v: k | (KeyBetween lo hi v) } a -> OMap {v: k | (KeyBetween lo hi v) } c)- -> (lo:MaybeS k -> hi: MaybeS k -> OMap {v: k | (KeyBetween lo hi v) } b -> OMap {v: k | (KeyBetween lo hi v) } c)- -> lo: MaybeS k- -> hi: MaybeS {v: k | (IfDefLt lo v) }- -> OMap {v: k | (KeyBetween lo hi v) } a- -> {v: OMap k b | (RootBetween lo hi v) }- -> OMap {v: k | (KeyBetween lo hi v)} c @-}--hedgeMerge :: Ord k => (k -> a -> b -> Maybe c)- -> (MaybeS k -> MaybeS k -> Map k a -> Map k c)- -> (MaybeS k -> MaybeS k -> Map k b -> Map k c)- -> MaybeS k -> MaybeS k- -> Map k a -> Map k b -> Map k c-hedgeMerge f g1 g2 blo bhi t1 Tip- = g1 blo bhi t1-hedgeMerge f g1 g2 blo bhi Tip (Bin _ kx x l r)- = g2 blo bhi $ join kx x (filterGt blo l) (filterLt bhi r)-hedgeMerge f g1 g2 blo bhi (Bin _ kx x l r) t2- = let bmi = JustS kx- l' = hedgeMerge f g1 g2 blo bmi l (trim blo bmi t2)- (found, trim_t2) = trimLookupLo kx bhi t2- r' = hedgeMerge f g1 g2 bmi bhi r trim_t2- in case found of- Nothing -> case g1 blo bhi (singleton kx x) of- Tip -> merge kx l' r'- (Bin _ _ x' Tip Tip) -> join kx x' l' r'- _ -> error "mergeWithKey: Given function only1 does not fulfil required conditions (see documentation)"- Just x2 -> case f kx x x2 of- Nothing -> merge kx l' r'- Just x' -> join kx x' l' r'-{-# INLINE mergeWithKey #-}--{--------------------------------------------------------------------- Submap---------------------------------------------------------------------}--- | /O(n+m)/.--- This function is defined as (@'isSubmapOf' = 'isSubmapOfBy' (==)@).----{-@ isSubmapOf :: (Ord k, Eq a) => OMap k a -> OMap k a -> Bool @-}-isSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool-isSubmapOf m1 m2 = isSubmapOfBy (==) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubmapOf #-}-#endif--{- | /O(n+m)/.- The expression (@'isSubmapOfBy' f t1 t2@) returns 'True' if- all keys in @t1@ are in tree @t2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isSubmapOfBy (==) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (<=) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1),('b',2)])-- But the following are all 'False':-- > isSubmapOfBy (==) (fromList [('a',2)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (<) (fromList [('a',1)]) (fromList [('a',1),('b',2)])- > isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1)])----}--{-@ isSubmapOfBy :: (Ord k) => (a->b->Bool) -> OMap k a -> OMap k b -> Bool @-}-isSubmapOfBy :: Ord k => (a->b->Bool) -> Map k a -> Map k b -> Bool-isSubmapOfBy f t1 t2- = (size t1 <= size t2) && (submap' f t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isSubmapOfBy #-}-#endif--submap' :: Ord a => (b -> c -> Bool) -> Map a b -> Map a c -> Bool-submap' _ Tip _ = True-submap' _ _ Tip = False-submap' f (Bin _ kx x l r) t- = case found of- Nothing -> False- Just y -> f x y && submap' f l lt && submap' f r gt- where- (lt,found,gt) = splitLookup kx t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE submap' #-}-#endif---- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).--- Defined as (@'isProperSubmapOf' = 'isProperSubmapOfBy' (==)@).--{-@ isProperSubmapOf :: (Ord k,Eq a) => OMap k a -> OMap k a -> Bool @-}-isProperSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool-isProperSubmapOf m1 m2- = isProperSubmapOfBy (==) m1 m2-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubmapOf #-}-#endif--{- | /O(n+m)/. Is this a proper submap? (ie. a submap but not equal).- The expression (@'isProperSubmapOfBy' f m1 m2@) returns 'True' when- @m1@ and @m2@ are not equal,- all keys in @m1@ are in @m2@, and when @f@ returns 'True' when- applied to their respective values. For example, the following- expressions are all 'True':-- > isProperSubmapOfBy (==) (fromList [(1,1)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (<=) (fromList [(1,1)]) (fromList [(1,1),(2,2)])-- But the following are all 'False':-- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1),(2,2)])- > isProperSubmapOfBy (==) (fromList [(1,1),(2,2)]) (fromList [(1,1)])- > isProperSubmapOfBy (<) (fromList [(1,1)]) (fromList [(1,1),(2,2)])----}-{-@ isProperSubmapOfBy :: Ord k => (a -> b -> Bool) -> OMap k a -> OMap k b -> Bool @-}-isProperSubmapOfBy :: Ord k => (a -> b -> Bool) -> Map k a -> Map k b -> Bool-isProperSubmapOfBy f t1 t2- = (size t1 < size t2) && (submap' f t1 t2)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE isProperSubmapOfBy #-}-#endif--{--------------------------------------------------------------------- Filter and partition---------------------------------------------------------------------}--- | /O(n)/. Filter all values that satisfy the predicate.------ > filter (> "a") (fromList [(5,"a"), (3,"b")]) == singleton 3 "b"--- > filter (> "x") (fromList [(5,"a"), (3,"b")]) == empty--- > filter (< "a") (fromList [(5,"a"), (3,"b")]) == empty--{-@ filter :: (a -> Bool) -> OMap k a -> OMap k a @-}-filter :: (a -> Bool) -> Map k a -> Map k a-filter p m- = filterWithKey (\_ x -> p x) m---- | /O(n)/. Filter all keys\/values that satisfy the predicate.------ > filterWithKey (\k _ -> k > 4) (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"--{-@ filterWithKey :: (k -> a -> Bool) -> OMap k a -> OMap k a @-}-filterWithKey :: (k -> a -> Bool) -> Map k a -> Map k a-filterWithKey _ Tip = Tip-filterWithKey p (Bin _ kx x l r)- | p kx x = join kx x (filterWithKey p l) (filterWithKey p r)- | otherwise = merge kx (filterWithKey p l) (filterWithKey p r)---- | /O(n)/. Partition the map according to a predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partition (> "a") (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > partition (< "x") (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partition (> "x") (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--{-@ partition :: (a -> Bool) -> OMap k a -> (OMap k a, OMap k a) @-}-partition :: (a -> Bool) -> Map k a -> (Map k a,Map k a)-partition p m- = partitionWithKey (\_ x -> p x) m---- | /O(n)/. Partition the map according to a predicate. The first--- map contains all elements that satisfy the predicate, the second all--- elements that fail the predicate. See also 'split'.------ > partitionWithKey (\ k _ -> k > 3) (fromList [(5,"a"), (3,"b")]) == (singleton 5 "a", singleton 3 "b")--- > partitionWithKey (\ k _ -> k < 7) (fromList [(5,"a"), (3,"b")]) == (fromList [(3, "b"), (5, "a")], empty)--- > partitionWithKey (\ k _ -> k > 7) (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])--{-@ partitionWithKey :: (k -> a -> Bool) -> OMap k a -> (OMap k a, OMap k a) @-}-partitionWithKey :: (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)-partitionWithKey _ Tip = (Tip,Tip)-partitionWithKey p (Bin _ kx x l r)- | p kx x = (join kx x l1 r1,merge kx l2 r2)- | otherwise = (merge kx l1 r1,join kx x l2 r2)- where- (l1,l2) = partitionWithKey p l- (r1,r2) = partitionWithKey p r---- | /O(n)/. Map values and collect the 'Just' results.------ > let f x = if x == "a" then Just "new a" else Nothing--- > mapMaybe f (fromList [(5,"a"), (3,"b")]) == singleton 5 "new a"--{-@ mapMaybe :: (a -> Maybe b) -> OMap k a -> OMap k b @-}-mapMaybe :: (a -> Maybe b) -> Map k a -> Map k b-mapMaybe f = mapMaybeWithKey (\_ x -> f x)---- | /O(n)/. Map keys\/values and collect the 'Just' results.------ > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing--- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"--{-@ mapMaybeWithKey :: (k -> a -> Maybe b) -> OMap k a -> OMap k b @-}-mapMaybeWithKey :: (k -> a -> Maybe b) -> Map k a -> Map k b-mapMaybeWithKey _ Tip = Tip-mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of- Just y -> join kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)- Nothing -> merge kx (mapMaybeWithKey f l) (mapMaybeWithKey f r)---- | /O(n)/. Map values and separate the 'Left' and 'Right' results.------ > let f a = if a < "c" then Left a else Right a--- > mapEither f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(3,"b"), (5,"a")], fromList [(1,"x"), (7,"z")])--- >--- > mapEither (\ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--{-@ mapEither :: (a -> Either b c) -> OMap k a -> (OMap k b, OMap k c) @-}-mapEither :: (a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEither f m- = mapEitherWithKey (\_ x -> f x) m---- | /O(n)/. Map keys\/values and separate the 'Left' and 'Right' results.------ > let f k a = if k < 5 then Left (k * 2) else Right (a ++ a)--- > mapEitherWithKey f (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (fromList [(1,2), (3,6)], fromList [(5,"aa"), (7,"zz")])--- >--- > mapEitherWithKey (\_ a -> Right a) (fromList [(5,"a"), (3,"b"), (1,"x"), (7,"z")])--- > == (empty, fromList [(1,"x"), (3,"b"), (5,"a"), (7,"z")])--{-@ mapEitherWithKey :: (k -> a -> Either b c) -> OMap k a -> (OMap k b, OMap k c) @-}-mapEitherWithKey :: (k -> a -> Either b c) -> Map k a -> (Map k b, Map k c)-mapEitherWithKey _ Tip = (Tip, Tip)-mapEitherWithKey f (Bin _ kx x l r) = case f kx x of- Left y -> (join kx y l1 r1, merge kx l2 r2)- Right z -> (merge kx l1 r1, join kx z l2 r2)- where- (l1,l2) = mapEitherWithKey f l- (r1,r2) = mapEitherWithKey f r--{--------------------------------------------------------------------- Mapping---------------------------------------------------------------------}--- | /O(n)/. Map a function over all values in the map.------ > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]--{-@ map :: (a -> b) -> OMap k a -> OMap k b @-}-map :: (a -> b) -> Map k a -> Map k b-map _ Tip = Tip-map f (Bin sx kx x l r) = Bin sx kx (f x) (map f l) (map f r)---- | /O(n)/. Map a function over all values in the map.------ > let f key x = (show key) ++ ":" ++ x--- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]--{-@ mapWithKey :: (k -> a -> b) -> OMap k a -> OMap k b @-}-mapWithKey :: (k -> a -> b) -> Map k a -> Map k b-mapWithKey _ Tip = Tip-mapWithKey f (Bin sx kx x l r) = Bin sx kx (f kx x) (mapWithKey f l) (mapWithKey f r)---- | /O(n)/.--- @'traverseWithKey' f s == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@--- That is, behaves exactly like a regular 'traverse' except that the traversing--- function also has access to the key associated with a value.------ > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(1, 'a'), (5, 'e')]) == Just (fromList [(1, 'b'), (5, 'f')])--- > traverseWithKey (\k v -> if odd k then Just (succ v) else Nothing) (fromList [(2, 'c')]) == Nothing---{-# INLINE traverseWithKey #-}---traverseWithKey :: Applicative t => (k -> a -> t b) -> Map k a -> t (Map k b)---traverseWithKey f = go--- where--- go Tip = pure Tip--- go (Bin s k v l r)--- = flip (Bin s k) <$> go l <*> f k v <*> go r---- | /O(n)/. The function 'mapAccum' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a b = (a ++ b, b ++ "X")--- > mapAccum f "Everything: " (fromList [(5,"a"), (3,"b")]) == ("Everything: ba", fromList [(3, "bX"), (5, "aX")])--{-@ mapAccum :: (a -> b -> (a,c)) -> a -> OMap k b -> (a, OMap k c) @-}-mapAccum :: (a -> b -> (a,c)) -> a -> Map k b -> (a, Map k c)-mapAccum f a m- = mapAccumWithKey (\a' _ x' -> f a' x') a m---- | /O(n)/. The function 'mapAccumWithKey' threads an accumulating--- argument through the map in ascending order of keys.------ > let f a k b = (a ++ " " ++ (show k) ++ "-" ++ b, b ++ "X")--- > mapAccumWithKey f "Everything:" (fromList [(5,"a"), (3,"b")]) == ("Everything: 3-b 5-a", fromList [(3, "bX"), (5, "aX")])--{-@ mapAccumWithKey :: (a -> k -> b -> (a,c)) -> a -> OMap k b -> (a, OMap k c) @-}-mapAccumWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumWithKey f a t- = mapAccumL f a t---- | /O(n)/. The function 'mapAccumL' threads an accumulating--- argument through the map in ascending order of keys.-mapAccumL :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumL _ a Tip = (a,Tip)-mapAccumL f a (Bin sx kx x l r) =- let (a1,l') = mapAccumL f a l- (a2,x') = f a1 kx x- (a3,r') = mapAccumL f a2 r- in (a3,Bin sx kx x' l' r')---- | /O(n)/. The function 'mapAccumR' threads an accumulating--- argument through the map in descending order of keys.-{-@ mapAccumRWithKey :: (a -> k -> b -> (a,c)) -> a -> OMap k b -> (a, OMap k c) @-}-mapAccumRWithKey :: (a -> k -> b -> (a,c)) -> a -> Map k b -> (a,Map k c)-mapAccumRWithKey _ a Tip = (a,Tip)-mapAccumRWithKey f a (Bin sx kx x l r) =- let (a1,r') = mapAccumRWithKey f a r- (a2,x') = f a1 kx x- (a3,l') = mapAccumRWithKey f a2 l- in (a3,Bin sx kx x' l' r')---- | /O(n*log n)/.--- @'mapKeys' f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the value at the greatest of the--- original keys is retained.------ > mapKeys (+ 1) (fromList [(5,"a"), (3,"b")]) == fromList [(4, "b"), (6, "a")]--- > mapKeys (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "c"--- > mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "c"--{-@ mapKeys :: (Ord k2) => (k1 -> k2) -> OMap k1 a -> OMap k2 a @-}-mapKeys :: Ord k2 => (k1->k2) -> Map k1 a -> Map k2 a-mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeys #-}-#endif---- | /O(n*log n)/.--- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.------ The size of the result may be smaller if @f@ maps two or more distinct--- keys to the same new key. In this case the associated values will be--- combined using @c@.------ > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"--- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"--{-@ mapKeysWith :: (Ord k2) => (a -> a -> a) -> (k1->k2) -> OMap k1 a -> OMap k2 a @-}-mapKeysWith :: Ord k2 => (a -> a -> a) -> (k1->k2) -> Map k1 a -> Map k2 a-mapKeysWith c f = fromListWith c . foldrWithKey (\k x xs -> (f k, x) : xs) []-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE mapKeysWith #-}-#endif----- | /O(n)/.--- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@--- is strictly monotonic.--- That is, for any values @x@ and @y@, if @x@ < @y@ then @f x@ < @f y@.--- /The precondition is not checked./--- Semi-formally, we have:------ > and [x < y ==> f x < f y | x <- ls, y <- ls]--- > ==> mapKeysMonotonic f s == mapKeys f s--- > where ls = keys s------ This means that @f@ maps distinct original keys to distinct resulting keys.--- This function has better performance than 'mapKeys'.------ > mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) == fromList [(6, "b"), (10, "a")]--- > valid (mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")])) == True--- > valid (mapKeysMonotonic (\ _ -> 1) (fromList [(5,"a"), (3,"b")])) == False--- LIQUIDFAIL-mapKeysMonotonic :: (k1->k2) -> Map k1 a -> Map k2 a-mapKeysMonotonic _ Tip = Tip-mapKeysMonotonic f (Bin sz k x l r) =- Bin sz (f k) x (mapKeysMonotonic f l) (mapKeysMonotonic f r)--{--------------------------------------------------------------------- Folds---------------------------------------------------------------------}---- | /O(n)/. Fold the values in the map using the given right-associative--- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'elems'@.------ For example,------ > elems map = foldr (:) [] map------ > let f a len = len + (length a)--- > foldr f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldr :: (a -> b -> b) -> b -> Map k a -> b-foldr f z = go z- where- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr #-}---- | /O(n)/. A strict version of 'foldr'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldr' :: (a -> b -> b) -> b -> Map k a -> b-foldr' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f x (go z' r)) l-{-# INLINE foldr' #-}---- | /O(n)/. Fold the values in the map using the given left-associative--- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.------ For example,------ > elems = reverse . foldl (flip (:)) []------ > let f len a = len + (length a)--- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4-foldl :: (a -> b -> a) -> a -> Map k b -> a-foldl f z = go z- where- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl #-}---- | /O(n)/. A strict version of 'foldl'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldl' :: (a -> b -> a) -> a -> Map k b -> a-foldl' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ _ x l r) = go (f (go z' l) x) r-{-# INLINE foldl' #-}---- | /O(n)/. Fold the keys and values in the map using the given right-associative--- binary operator, such that--- @'foldrWithKey' f z == 'Prelude.foldr' ('uncurry' f) z . 'toAscList'@.------ For example,------ > keys map = foldrWithKey (\k x ks -> k:ks) [] map------ > let f k a result = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldrWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (5:a)(3:b)"-foldrWithKey :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l-{-# INLINE foldrWithKey #-}---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldrWithKey' :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrWithKey' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l-{-# INLINE foldrWithKey' #-}---- | /O(n)/. Fold the keys and values in the map using the given left-associative--- binary operator, such that--- @'foldlWithKey' f z == 'Prelude.foldl' (\\z' (kx, x) -> f z' kx x) z . 'toAscList'@.------ For example,------ > keys = reverse . foldlWithKey (\ks k x -> k:ks) []------ > let f result k a = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"--- > foldlWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (3:b)(5:a)"-foldlWithKey :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r-{-# INLINE foldlWithKey #-}---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the operator is--- evaluated before using the result in the next application. This--- function is strict in the starting value.-foldlWithKey' :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlWithKey' f z = go z- where- STRICT_1_OF_2(go)- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r-{-# INLINE foldlWithKey' #-}--{--------------------------------------------------------------------- List variations---------------------------------------------------------------------}--- | /O(n)/.--- Return all elements of the map in the ascending order of their keys.--- Subject to list fusion.------ > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]--- > elems empty == []--{-@ elems :: m:Map k a -> [a] / [mlen m] @-}-elems :: Map k a -> [a]-elems = foldr (:) []---- | /O(n)/. Return all keys of the map in ascending order. Subject to list--- fusion.------ > keys (fromList [(5,"a"), (3,"b")]) == [3,5]--- > keys empty == []--{- LIQUID: SUMMARY-VALUES: keys :: OMap k a -> [k]<{v: k | v >= fld}> @-}-{-@ keys :: m:Map k a -> [k] / [mlen m] @-}-keys :: Map k a -> [k]-keys = foldrWithKey (\k _ ks -> k : ks) []---- | /O(n)/. An alias for 'toAscList'. Return all key\/value pairs in the map--- in ascending key order. Subject to list fusion.------ > assocs (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > assocs empty == []--{- LIQUID: SUMMARY-VALUES: assocs :: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) >= fst(fld) }> @-}-assocs :: Map k a -> [(k,a)]-assocs m- = toAscList m---- | /O(n)/. The set of all keys of the map.------ > keysSet (fromList [(5,"a"), (3,"b")]) == Data.Set.fromList [3,5]--- > keysSet empty == Data.Set.empty--- LIQUID keysSet :: Map k a -> Set.Set k--- LIQUID keysSet Tip = Set.Tip--- LIQUID keysSet (Bin sz kx _ l r) = Set.Bin sz kx (keysSet l) (keysSet r)---- | /O(n)/. Build a map from a set of keys and a function which for each key--- computes its value.------ > fromSet (\k -> replicate k 'a') (Data.Set.fromList [3, 5]) == fromList [(5,"aaaaa"), (3,"aaa")]--- > fromSet undefined Data.Set.empty == empty--- LIQUID fromSet :: (k -> a) -> Set.Set k -> Map k a--- LIQUID fromSet _ Set.Tip = Tip--- LIQUID fromSet f (Set.Bin sz x l r) = Bin sz x (f x) (fromSet f l) (fromSet f r)--{--------------------------------------------------------------------- Lists- use [foldlStrict] to reduce demand on the control-stack---------------------------------------------------------------------}--- | /O(n*log n)/. Build a map from a list of key\/value pairs. See also 'fromAscList'.--- If the list contains more than one value for the same key, the last value--- for the key is retained.------ > fromList [] == empty--- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]--- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]--{-@ fromList :: (Ord k) => [(k,a)] -> OMap k a @-}-fromList :: Ord k => [(k,a)] -> Map k a-fromList xs- = foldlStrict ins empty xs- where- ins t (k,x) = insert k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromList #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.------ > fromListWith (++) [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "ab"), (5, "aba")]--- > fromListWith (++) [] == empty--{-@ fromListWith :: (Ord k) => (a -> a -> a) -> [(k,a)] -> OMap k a @-}-fromListWith :: Ord k => (a -> a -> a) -> [(k,a)] -> Map k a-fromListWith f xs- = fromListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWith #-}-#endif---- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.------ > let f k a1 a2 = (show k) ++ a1 ++ a2--- > fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"a")] == fromList [(3, "3ab"), (5, "5a5ba")]--- > fromListWithKey f [] == empty--{-@ fromListWithKey :: (Ord k) => (k -> a -> a -> a) -> [(k,a)] -> OMap k a @-}-fromListWithKey :: Ord k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromListWithKey f xs- = foldlStrict ins empty xs- where- ins t (k,x) = insertWithKey f k x t-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromListWithKey #-}-#endif---- | /O(n)/. Convert the map to a list of key\/value pairs. Subject to list fusion.------ > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--- > toList empty == []--{- LIQUIDTODO: toList:: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) > fst(fld) }> @-}-toList :: Map k a -> [(k,a)]-toList = toAscList---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys are--- in ascending order. Subject to list fusion.------ > toAscList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]--{- LIQUIDTODO: toAscList :: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) > fst(fld) }> @-}-{-@ toAscList :: m:Map k a -> [(k,a)] / [mlen m] @-}-toAscList :: Map k a -> [(k,a)]-toAscList = foldrWithKey (\k x xs -> (k,x):xs) []---- | /O(n)/. Convert the map to a list of key\/value pairs where the keys--- are in descending order. Subject to list fusion.------ > toDescList (fromList [(5,"a"), (3,"b")]) == [(5,"a"), (3,"b")]--{- LIQUIDTODO: toAscList :: OMap k a -> [(k, a)]<{v: (k, a) | fst(v) < fst(fld) }> @-}-{-@ toDescList :: m:Map k a -> [(k,a)] / [mlen m] @-}-toDescList :: Map k a -> [(k,a)]-toDescList = foldlWithKey (\xs k x -> (k,x):xs) []---- List fusion for the list generating functions.-#if __GLASGOW_HASKELL__--- The foldrFB and foldlFB are fold{r,l}WithKey equivalents, used for list fusion.--- They are important to convert unfused methods back, see mapFB in prelude.-{-@ foldrFB :: (k -> a -> b -> b) -> b -> m:Map k a -> b / [mlen m] @-}-foldrFB :: (k -> a -> b -> b) -> b -> Map k a -> b-foldrFB = foldrWithKey-{-# INLINE[0] foldrFB #-}-{-@ foldlFB :: (a -> k -> b -> a) -> a -> m:Map k b -> a / [mlen m] @-}-foldlFB :: (a -> k -> b -> a) -> a -> Map k b -> a-foldlFB = foldlWithKey-{-# INLINE[0] foldlFB #-}---- Inline assocs and toList, so that we need to fuse only toAscList.-{-# INLINE assocs #-}-{-# INLINE toList #-}---- The fusion is enabled up to phase 2 included. If it does not succeed,--- convert in phase 1 the expanded elems,keys,to{Asc,Desc}List calls back to--- elems,keys,to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were--- used in a list fusion, otherwise it would go away in phase 1), and let compiler--- do whatever it wants with elems,keys,to{Asc,Desc}List -- it was forbidden to--- inline it before phase 0, otherwise the fusion rules would not fire at all.-{-# NOINLINE[0] elems #-}-{-# NOINLINE[0] keys #-}-{-# NOINLINE[0] toAscList #-}-{-# NOINLINE[0] toDescList #-}-{-# RULES "Map.elems" [~1] forall m . elems m = build (\c n -> foldrFB (\_ x xs -> c x xs) n m) #-}-{-# RULES "Map.elemsBack" [1] foldrFB (\_ x xs -> x : xs) [] = elems #-}-{-# RULES "Map.keys" [~1] forall m . keys m = build (\c n -> foldrFB (\k _ xs -> c k xs) n m) #-}-{-# RULES "Map.keysBack" [1] foldrFB (\k _ xs -> k : xs) [] = keys #-}-{-# RULES "Map.toAscList" [~1] forall m . toAscList m = build (\c n -> foldrFB (\k x xs -> c (k,x) xs) n m) #-}-{-# RULES "Map.toAscListBack" [1] foldrFB (\k x xs -> (k, x) : xs) [] = toAscList #-}-{-# RULES "Map.toDescList" [~1] forall m . toDescList m = build (\c n -> foldlFB (\xs k x -> c (k,x) xs) n m) #-}-{-# RULES "Map.toDescListBack" [1] foldlFB (\xs k x -> (k, x) : xs) [] = toDescList #-}-#endif--{--------------------------------------------------------------------- Building trees from ascending/descending lists can be done in linear time.-- Note that if [xs] is ascending that:- fromAscList xs == fromList xs- fromAscListWith f xs == fromListWith f xs---------------------------------------------------------------------}--- | /O(n)/. Build a map from an ascending list in linear time.--- /The precondition (input list is ascending) is not checked./------ > fromAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]--- > valid (fromAscList [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscList [(5,"a"), (3,"b"), (5,"b")]) == False--{- LIQUIDTODO fromAscList :: (Eq k) => [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-{-@ fromAscList :: (Eq k) => {v: [(k,a)] | false} -> OMap k a @-}-fromAscList :: Eq k => [(k,a)] -> Map k a-fromAscList xs- = fromAscListWithKey (\_ x _ -> x) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscList #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]--- > valid (fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")]) == True--- > valid (fromAscListWith (++) [(5,"a"), (3,"b"), (5,"b")]) == False--{- LIQUIDTODO fromAscListWith :: (Eq k) => (a -> a -> a) -> [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-{-@ fromAscListWith :: Eq k => (a -> a -> a) -> {v:[(k,a)] | false} -> OMap k a @-}-fromAscListWith :: Eq k => (a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWith f xs- = fromAscListWithKey (\_ x y -> f x y) xs-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWith #-}-#endif---- | /O(n)/. Build a map from an ascending list in linear time with a--- combining function for equal keys.--- /The precondition (input list is ascending) is not checked./------ > let f k a1 a2 = (show k) ++ ":" ++ a1 ++ a2--- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")] == fromList [(3, "b"), (5, "5:b5:ba")]--- > valid (fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b"), (5,"b")]) == True--- > valid (fromAscListWithKey f [(5,"a"), (3,"b"), (5,"b"), (5,"b")]) == False--{- LIQUIDTODO fromAscListWithKey :: (Eq k) => (k -> a -> a -> a) -> [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-{-@ fromAscListWithKey :: (Eq k) => (k -> a -> a -> a) -> {v: [(k,a)] | false} -> OMap k a @-}-fromAscListWithKey :: Eq k => (k -> a -> a -> a) -> [(k,a)] -> Map k a-fromAscListWithKey f xs- = fromDistinctAscList (combineEq f xs)- where- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]- combineEq _ xs'- = case xs' of- [] -> []- [x] -> [x]- (x:xx) -> combineEq' x xx-- combineEq' z [] = [z]- combineEq' z@(kz,zz) (x@(kx,xx):xs')- | kx==kz = let yy = f kx xx zz in combineEq' (kx,yy) xs'- | otherwise = z:combineEq' x xs'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromAscListWithKey #-}-#endif----- | /O(n)/. Build a map from an ascending list of distinct elements in linear time.--- /The precondition is not checked./------ > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]--- > valid (fromDistinctAscList [(3,"b"), (5,"a")]) == True--- > valid (fromDistinctAscList [(3,"b"), (5,"a"), (5,"b")]) == False--{- LIQUIDTODO fromDistinctAscList :: [(k,a)]<{v: (k, a) | fst(v) > fst(fld)}> -> OMap k a -}-{-@ lazy fromDistinctAscList @-}-{-@ fromDistinctAscList :: {v: [(k, a)] | false} -> OMap k a @-}-fromDistinctAscList :: [(k,a)] -> Map k a-fromDistinctAscList xs- = create const (length xs) xs- where- -- 1) use continuations so that we use heap space instead of stack space.- -- 2) special case for n==5 to create bushier trees.- create c 0 xs' = c Tip xs'- create c 5 xs' = case xs' of- ((k1,x1):(k2,x2):(k3,x3):(k4,x4):(k5,x5):xx)- -> c (bin k4 x4 (bin k2 x2 (singleton k1 x1) (singleton k3 x3)) (singleton k5 x5)) xx- _ -> error "fromDistinctAscList create"- create c n xs' = seq nr $ create (createR nr c) nl xs'- where nl = n `div` 2- nr = n - nl - 1-- createR n c l ((k,x):ys) = create (createB l k x c) n ys- createR _ _ _ [] = error "fromDistinctAscList createR []"- createB l k x c r zs = c (bin k x l r) zs---{--------------------------------------------------------------------- Utility functions that return sub-ranges of the original- tree. Some functions take a `Maybe value` as an argument to- allow comparisons against infinite values. These are called `blow`- (Nothing is -\infty) and `bhigh` (here Nothing is +\infty).- We use MaybeS value, which is a Maybe strict in the Just case.-- [trim blow bhigh t] A tree that is either empty or where [x > blow]- and [x < bhigh] for the value [x] of the root.- [filterGt blow t] A tree where for all values [k]. [k > blow]- [filterLt bhigh t] A tree where for all values [k]. [k < bhigh]-- [split k t] Returns two trees [l] and [r] where all keys- in [l] are <[k] and all keys in [r] are >[k].- [splitLookup k t] Just like [split] but also returns whether [k]- was found in the tree.---------------------------------------------------------------------}--data MaybeS a = NothingS | JustS a -- LIQUID: !-annot-fix---{--------------------------------------------------------------------- [trim blo bhi t] trims away all subtrees that surely contain no- values between the range [blo] to [bhi]. The returned tree is either- empty or the key of the root is between @blo@ and @bhi@.---------------------------------------------------------------------}--- LIQUID: EXPANDED CASE-EXPRS for lesser, greater, middle to avoid DEFAULT hassle-{-@ trim :: (Ord k) => lo:MaybeS k- -> hi:MaybeS k- -> OMap k a- -> {v: OMap k a | (RootBetween lo hi v) }- @-}---trim :: Ord k => MaybeS k -> MaybeS k -> Map k a -> Map k a---trim NothingS NothingS t = t-trim (JustS lk) NothingS t = greater lk t-- where greater lo t@(Bin _ k _ _ r) | k <= lo = greater lo r- | otherwise = t- greater _ t'@Tip = t'--trim NothingS (JustS hk) t = lesser hk t-- where lesser hi t'@(Bin _ k _ l _) | k >= hi = lesser hi l- | otherwise = t'- lesser _ t'@Tip = t'-trim (JustS lk) (JustS hk) t = middle lk hk t- where middle lo hi t'@(Bin _ k _ l r) | k <= lo = middle lo hi r- | k >= hi = middle lo hi l- | otherwise = t'- middle _ _ t'@Tip = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trim #-}-#endif---- LIQUID QUALIFIER DEBUG SILLINESS-{-@ zoo1 :: (Ord k) => lo:k -> OMap k a -> {v: OMap k a | ((isBin(v)) => (lo < key(v)))} @-}-zoo1 :: Ord k => k -> Map k a -> Map k a-zoo1 = error "TODO"--{-@ zoo2 :: (Ord k) => lo:k -> OMap k a -> {v: OMap k a | ((isBin(v)) => (lo > key(v)))} @-}-zoo2 :: Ord k => k -> Map k a -> Map k a-zoo2 = error "TODO"----- Helper function for 'mergeWithKey'. The @'trimLookupLo' lk hk t@ performs both--- @'trim' (JustS lk) hk t@ and @'lookup' lk t@.---- See Note: Type of local 'go' function--- LIQUID trimLookupLo :: Ord k => k -> MaybeS k -> Map k a -> (Maybe a, Map k a)--- LIQUID trimLookupLo lk NothingS t = greater lk t--- LIQUID where greater :: Ord k => k -> Map k a -> (Maybe a, Map k a)--- LIQUID greater lo t'@(Bin _ kx x l r) = case compare lo kx of LT -> (lookup lo l, {-`strictPair`-} t')--- LIQUID EQ -> (Just x, r)--- LIQUID GT -> greater lo r--- LIQUID greater _ Tip = (Nothing, Tip)--- LIQUID trimLookupLo lk (JustS hk) t = middle lk hk t--- LIQUID where middle :: Ord k => k -> k -> Map k a -> (Maybe a, Map k a)--- LIQUID middle lo hi t'@(Bin _ kx x l r) = case compare lo kx of LT | kx < hi -> (lookup lo l, {- `strictPair` -} t')--- LIQUID | otherwise -> middle lo hi l--- LIQUID EQ -> (Just x, {-`strictPair`-} lesser hi r)--- LIQUID GT -> middle lo hi r--- LIQUID middle _ _ Tip = (Nothing, Tip)--- LIQUID--- LIQUID lesser :: Ord k => k -> Map k a -> Map k a--- LIQUID lesser hi (Bin _ k _ l _) | k >= hi = lesser hi l--- LIQUID lesser _ t' = t'--{-@ trimLookupLo :: (Ord k)- => lo:k- -> bhi:{v: MaybeS k | (isJustS(v) => (lo < fromJustS(v)))}- -> OMap k a- -> (Maybe a, {v: OMap k a | ((isBin(v) => (lo < key(v))) && ((isBin(v) && isJustS(bhi)) => (fromJustS(bhi) > key(v)))) }) @-}--trimLookupLo :: Ord k => k -> MaybeS k -> Map k a -> (Maybe a, Map k a)-trimLookupLo lk NothingS t = greater lk t- where greater :: Ord k => k -> Map k a -> (Maybe a, Map k a)- greater lo t'@(Bin _ kx x l r) = case compare lo kx of LT -> (lookup lo l, {-`strictPair`-} t')- EQ -> (Just x, (case r of {r'@(Bin _ _ _ _ _) -> r' ; r'@Tip -> r'}))- GT -> greater lo r- greater _ Tip = (Nothing, Tip)-trimLookupLo lk (JustS hk) t = middle lk hk t- where middle :: Ord k => k -> k -> Map k a -> (Maybe a, Map k a)- middle lo hi t'@(Bin _ kx x l r) = case compare lo kx of LT | kx < hi -> (lookup lo l, {- `strictPair` -} t')- | otherwise -> middle lo hi l- EQ -> (Just x, {-`strictPair`-} lesser lo hi (case r of {r'@(Bin _ _ _ _ _) -> r' ; r'@Tip -> r'}))- GT -> middle lo hi r- middle _ _ Tip = (Nothing, Tip)-- lesser :: Ord k => k -> k -> Map k a -> Map k a- lesser lo hi t'@(Bin _ k _ l _) | k >= hi = lesser lo hi l- | otherwise = t'- lesser _ _ t'@Tip = t'-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE trimLookupLo #-}-#endif---{--------------------------------------------------------------------- [filterGt b t] filter all keys >[b] from tree [t]- [filterLt b t] filter all keys <[b] from tree [t]---------------------------------------------------------------------}--{-@ filterGt :: (Ord k) => x:MaybeS k -> OMap k v -> OMap {v:k | ((isJustS(x)) => (v > fromJustS(x))) } v @-}-filterGt :: Ord k => MaybeS k -> Map k v -> Map k v-filterGt NothingS t = t-filterGt (JustS b) t = filterGt' b t---- LIQUID TXREC-TOPLEVEL-ISSUE-filterGt' _ Tip = Tip-filterGt' b' (Bin _ kx x l r) =- case compare b' kx of LT -> join kx x (filterGt' b' l) r- EQ -> r- GT -> filterGt' b' r-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterGt #-}-#endif--{-@ filterLt :: (Ord k) => x:MaybeS k -> OMap k v -> OMap {v:k | ((isJustS(x)) => (v < fromJustS(x))) } v @-}-filterLt :: Ord k => MaybeS k -> Map k v -> Map k v-filterLt NothingS t = t-filterLt (JustS b) t = filterLt' b t---- LIQUID TXREC-TOPLEVEL-ISSUE-filterLt' _ Tip = Tip-filterLt' b' (Bin _ kx x l r) =- case compare kx b' of LT -> join kx x l (filterLt' b' r)- EQ -> l- GT -> filterLt' b' l-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE filterLt #-}-#endif--{--------------------------------------------------------------------- Split---------------------------------------------------------------------}--- | /O(log n)/. The expression (@'split' k map@) is a pair @(map1,map2)@ where--- the keys in @map1@ are smaller than @k@ and the keys in @map2@ larger than @k@.--- Any key equal to @k@ is found in neither @map1@ nor @map2@.------ > split 2 (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3,"b"), (5,"a")])--- > split 3 (fromList [(5,"a"), (3,"b")]) == (empty, singleton 5 "a")--- > split 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a")--- > split 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", empty)--- > split 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], empty)--{-@ split :: (Ord k) => x:k -> OMap k a -> (OMap {v: k | v < x} a, OMap {v:k | v > x} a) @-}-split :: Ord k => k -> Map k a -> (Map k a, Map k a)-split k t = k `seq`- case t of- Tip -> (Tip, Tip)- Bin _ kx x l r -> case compare k kx of- LT -> let (lt,gt) = split k l in (lt,join kx x gt r)- GT -> let (lt,gt) = split k r in (join kx x l lt,gt)- EQ -> (l,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE split #-}-#endif---- | /O(log n)/. The expression (@'splitLookup' k map@) splits a map just--- like 'split' but also returns @'lookup' k map@.------ > splitLookup 2 (fromList [(5,"a"), (3,"b")]) == (empty, Nothing, fromList [(3,"b"), (5,"a")])--- > splitLookup 3 (fromList [(5,"a"), (3,"b")]) == (empty, Just "b", singleton 5 "a")--- > splitLookup 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Nothing, singleton 5 "a")--- > splitLookup 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", Just "a", empty)--- > splitLookup 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], Nothing, empty)--{-@ splitLookup :: (Ord k) => x:k -> OMap k a -> (OMap {v: k | v < x} a, Maybe a, OMap {v:k | v > x} a) @-}-splitLookup :: Ord k => k -> Map k a -> (Map k a,Maybe a,Map k a)-splitLookup k t = k `seq`- case t of- Tip -> (Tip,Nothing,Tip)- Bin _ kx x l r -> case compare k kx of- LT -> let (lt,z,gt) = splitLookup k l in (lt,z,join kx x gt r)- GT -> let (lt,z,gt) = splitLookup k r in (join kx x l lt,z,gt)- EQ -> (l,Just x,r)-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE splitLookup #-}-#endif--{--------------------------------------------------------------------- Utility functions that maintain the balance properties of the tree.- All constructors assume that all values in [l] < [k] and all values- in [r] > [k], and that [l] and [r] are valid trees.-- In order of sophistication:- [Bin sz k x l r] The type constructor.- [bin k x l r] Maintains the correct size, assumes that both [l]- and [r] are balanced with respect to each other.- [balance k x l r] Restores the balance and size.- Assumes that the original tree was balanced and- that [l] or [r] has changed by at most one element.- [join k x l r] Restores balance and size.-- Furthermore, we can construct a new tree from two trees. Both operations- assume that all values in [l] < all values in [r] and that [l] and [r]- are valid:- [glue l r] Glues [l] and [r] together. Assumes that [l] and- [r] are already balanced with respect to each other.- [merge l r] Merges two trees and restores balance.-- Note: in contrast to Adam's paper, we use (<=) comparisons instead- of (<) comparisons in [join], [merge] and [balance].- Quickcheck (on [difference]) showed that this was necessary in order- to maintain the invariants. It is quite unsatisfactory that I haven't- been able to find out why this is actually the case! Fortunately, it- doesn't hurt to be a bit more conservative.---------------------------------------------------------------------}-{--------------------------------------------------------------------- Join---------------------------------------------------------------------}--{-@ join :: k:k -> a -> OMap {v:k | v < k} a -> OMap {v:k| v > k} a -> OMap k a @-}-join :: k -> a -> Map k a -> Map k a -> Map k a-join k x m1 m2 = joinT k x m1 m2 (mlen m1 + mlen m2)---LIQUID join kx x Tip r = insertMin kx x r---LIQUID join kx x l Tip = insertMax kx x l---LIQUID join kx x l@(Bin sizeL ky y ly ry) r@(Bin sizeR kz z lz rz)---LIQUID | delta*sizeL < sizeR = balanceL kz z (join kx x l lz) rz---LIQUID | delta*sizeR < sizeL = balanceR ky y ly (join kx x ry r)---LIQUID | otherwise = bin kx x l r--{-@ joinT :: k:k -> a -> a:OMap {v:k | v < k} a -> b:OMap {v:k| v > k} a -> SumMLen a b -> OMap k a @-}-{-@ decrease joinT 5 @-}-{- LIQUID WITNESS -}-joinT :: k -> a -> Map k a -> Map k a -> Int -> Map k a-joinT kx x Tip r _ = insertMin kx x r-joinT kx x l Tip _ = insertMax kx x l-joinT kx x l@(Bin sizeL ky y ly ry) r@(Bin sizeR kz z lz rz) d- | delta*sizeL < sizeR = balanceL kz z (joinT kx x l lz (d-(mlen rz)-1)) rz- | delta*sizeR < sizeL = balanceR ky y ly (joinT kx x ry r (d-(mlen ly)-1))- | otherwise = bin kx x l r---- insertMin and insertMax don't perform potentially expensive comparisons.-insertMax, insertMin :: k -> a -> Map k a -> Map k a-insertMax kx x t- = case t of- Tip -> singleton kx x- Bin _ ky y l r- -> balanceR ky y l (insertMax kx x r)--insertMin kx x t- = case t of- Tip -> singleton kx x- Bin _ ky y l r- -> balanceL ky y (insertMin kx x l) r--{--------------------------------------------------------------------- [merge l r]: merges two trees.---------------------------------------------------------------------}-{-@ merge :: kcut:k -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-merge :: k -> Map k a -> Map k a -> Map k a-merge k m1 m2 = mergeT k m1 m2 (mlen m1 + mlen m2)---LIQUID merge _ Tip r = r---LIQUID merge _ l Tip = l---LIQUID merge kcut l@(Bin sizeL kx x lx rx) r@(Bin sizeR ky y ly ry)---LIQUID | delta*sizeL < sizeR = balanceL ky y (merge kcut l ly) ry---LIQUID | delta*sizeR < sizeL = balanceR kx x lx (merge kcut rx r)---LIQUID | otherwise = glue kcut l r--{-@ mergeT :: kcut:k -> a:OMap {v:k | v < kcut} a -> b:OMap {v:k| v > kcut} a -> SumMLen a b -> OMap k a @-}-{-@ decrease mergeT 4 @-}-{- LIQUID WITNESS -}-mergeT :: k -> Map k a -> Map k a -> Int -> Map k a-mergeT _ Tip r _ = r-mergeT _ l Tip _ = l-mergeT kcut l@(Bin sizeL kx x lx rx) r@(Bin sizeR ky y ly ry) d- | delta*sizeL < sizeR = balanceL ky y (mergeT kcut l ly (d-(mlen ry)-1)) ry- | delta*sizeR < sizeL = balanceR kx x lx (mergeT kcut rx r (d-(mlen lx)-1))- | otherwise = glue kcut l r--{--------------------------------------------------------------------- [glue l r]: glues two trees together.- Assumes that [l] and [r] are already balanced with respect to each other.---------------------------------------------------------------------}-{-@ glue :: kcut:k -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-glue :: k -> Map k a -> Map k a -> Map k a-glue _ Tip r = r-glue _ l Tip = l-glue kcut l r- | size l > size r = let (km, m, l') = deleteFindMax l in balanceR km m l' r- | otherwise = let (km, m, r') = deleteFindMin r in balanceL km m l r'---- | /O(log n)/. Delete and find the minimal element.------ > deleteFindMin (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((3,"b"), fromList[(5,"a"), (10,"c")])--- > deleteFindMin Error: can not return the minimal element of an empty map--{-@ deleteFindMin :: OMap k a -> (k, a, OMap k a)<{\k a -> true}, \a k -> {v0:Map ({v:k | v > k}) a | true}> @-}-deleteFindMin :: Map k a -> (k, a, Map k a)-deleteFindMin t- = case t of- Bin _ k x Tip r -> (k, x, r)- Bin _ k x l r -> let (km, m, l') = deleteFindMin l in (km, m, balanceR k x l' r)- Tip -> error "Map.deleteFindMin: can not return the minimal element of an empty map"---- | /O(log n)/. Delete and find the maximal element.------ > deleteFindMax (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((10,"c"), fromList [(3,"b"), (5,"a")])--- > deleteFindMax empty Error: can not return the maximal element of an empty map--{-@ deleteFindMax :: OMap k a -> (k, a, OMap k a)<{\k a -> true}, \a k -> {v0:Map ({v:k | v < k}) a | true}> @-}-deleteFindMax :: Map k a -> (k, a, Map k a)-deleteFindMax t- = case t of- Bin _ k x l Tip -> (k, x, l)- Bin _ k x l r -> let (km, m, r') = deleteFindMax r in (km, m, balanceL k x l r')- Tip -> error "Map.deleteFindMax: can not return the maximal element of an empty map"---{--------------------------------------------------------------------- [balance l x r] balances two trees with value x.- The sizes of the trees should balance after decreasing the- size of one of them. (a rotation).-- [delta] is the maximal relative difference between the sizes of- two trees, it corresponds with the [w] in Adams' paper.- [ratio] is the ratio between an outer and inner sibling of the- heavier subtree in an unbalanced setting. It determines- whether a double or single rotation should be performed- to restore balance. It is corresponds with the inverse- of $\alpha$ in Adam's article.-- Note that according to the Adam's paper:- - [delta] should be larger than 4.646 with a [ratio] of 2.- - [delta] should be larger than 3.745 with a [ratio] of 1.534.-- But the Adam's paper is erroneous:- - It can be proved that for delta=2 and delta>=5 there does- not exist any ratio that would work.- - Delta=4.5 and ratio=2 does not work.-- That leaves two reasonable variants, delta=3 and delta=4,- both with ratio=2.-- - A lower [delta] leads to a more 'perfectly' balanced tree.- - A higher [delta] performs less rebalancing.-- In the benchmarks, delta=3 is faster on insert operations,- and delta=4 has slightly better deletes. As the insert speedup- is larger, we currently use delta=3.----------------------------------------------------------------------}-delta,ratio :: Int-delta = 3-ratio = 2---- The balance function is equivalent to the following:------ balance :: k -> a -> Map k a -> Map k a -> Map k a--- balance k x l r--- | sizeL + sizeR <= 1 = Bin sizeX k x l r--- | sizeR > delta*sizeL = rotateL k x l r--- | sizeL > delta*sizeR = rotateR k x l r--- | otherwise = Bin sizeX k x l r--- where--- sizeL = size l--- sizeR = size r--- sizeX = sizeL + sizeR + 1------ rotateL :: a -> b -> Map a b -> Map a b -> Map a b--- rotateL k x l r@(Bin _ _ _ ly ry) | size ly < ratio*size ry = singleL k x l r--- | otherwise = doubleL k x l r------ rotateR :: a -> b -> Map a b -> Map a b -> Map a b--- rotateR k x l@(Bin _ _ _ ly ry) r | size ry < ratio*size ly = singleR k x l r--- | otherwise = doubleR k x l r------ singleL, singleR :: a -> b -> Map a b -> Map a b -> Map a b--- singleL k1 x1 t1 (Bin _ k2 x2 t2 t3) = bin k2 x2 (bin k1 x1 t1 t2) t3--- singleR k1 x1 (Bin _ k2 x2 t1 t2) t3 = bin k2 x2 t1 (bin k1 x1 t2 t3)------ doubleL, doubleR :: a -> b -> Map a b -> Map a b -> Map a b--- doubleL k1 x1 t1 (Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4) = bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)--- doubleR k1 x1 (Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3)) t4 = bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)------ It is only written in such a way that every node is pattern-matched only once.--{-@ balance :: k:k -> a -> OMap {v:k|v<k} a -> OMap {v:k|v>k} a -> OMap k a @-}-balance :: k -> a -> Map k a -> Map k a -> Map k a-balance k x l r = case l of- Tip -> case r of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r- (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr- (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)- (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr- | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)-- (Bin ls lk lx ll lr) -> case r of- Tip -> case (ll, lr) of- (Tip, Tip) -> Bin 2 k x l Tip- (Tip, (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)- ((Bin _ _ _ _ _), Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)- ((Bin lls _ _ _ _), (Bin lrs lrk lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)- | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)- (Bin rs rk rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr- | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)- (_, _) -> error "Failure in Data.Map.balance"- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)- | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)- (_, _) -> error "Failure in Data.Map.balance"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balance #-}---- Functions balanceL and balanceR are specialised versions of balance.--- balanceL only checks whether the left subtree is too big,--- balanceR only checks whether the right subtree is too big.---- balanceL is called when left subtree might have been inserted to or when--- right subtree might have been deleted from.-{-@ balanceL :: kcut:k -> a -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-balanceL :: k -> a -> Map k a -> Map k a -> Map k a-balanceL k x l r = case r of- Tip -> case l of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x l Tip- (Bin _ lk lx Tip (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)- (Bin _ lk lx ll@(Bin _ _ _ _ _) Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)- (Bin ls lk lx ll@(Bin lls _ _ _ _) lr@(Bin lrs lrk lrx lrl lrr))- | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)- | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)-- (Bin rs _ _ _ _) -> case l of- Tip -> Bin (1+rs) k x Tip r-- (Bin ls lk lx ll lr)- | ls > delta*rs -> case (ll, lr) of- (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)- | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)- | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)- (_, _) -> error "Failure in Data.Map.balanceL"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balanceL #-}---- balanceR is called when right subtree might have been inserted to or when--- left subtree might have been deleted from.-{-@ balanceR :: kcut:k -> a -> OMap {v:k | v < kcut} a -> OMap {v:k| v > kcut} a -> OMap k a @-}-balanceR :: k -> a -> Map k a -> Map k a -> Map k a-balanceR k x l r = case l of- Tip -> case r of- Tip -> Bin 1 k x Tip Tip- (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r- (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr- (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)- (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))- | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr- | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)-- (Bin ls _ _ _ _) -> case r of- Tip -> Bin (1+ls) k x l Tip-- (Bin rs rk rx rl rr)- | rs > delta*ls -> case (rl, rr) of- (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)- | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr- | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)- (_, _) -> error "Failure in Data.Map.balanceR"- | otherwise -> Bin (1+ls+rs) k x l r-{-# NOINLINE balanceR #-}---{--------------------------------------------------------------------- The bin constructor maintains the size of the tree---------------------------------------------------------------------}-{-@ bin :: k:k -> a -> OMap {v:k | v < k} a -> OMap {v:k| v > k} a -> OMap k a @-}-bin :: k -> a -> Map k a -> Map k a -> Map k a-bin k x l r- = Bin (size l + size r + 1) k x l r-{-# INLINE bin #-}--{--------------------------------------------------------------------- Eq converts the tree to a list. In a lazy setting, this- actually seems one of the faster methods to compare two trees- and it is certainly the simplest :-)---------------------------------------------------------------------}-instance (Eq k,Eq a) => Eq (Map k a) where- t1 == t2 = (size t1 == size t2) && (toAscList t1 == toAscList t2)--{--------------------------------------------------------------------- Ord---------------------------------------------------------------------}--instance (Ord k, Ord v) => Ord (Map k v) where- compare m1 m2 = compare (toAscList m1) (toAscList m2)--{--------------------------------------------------------------------- Functor---------------------------------------------------------------------}---- LIQUID instance Functor (Map k) where--- LIQUID fmap f m = map f m--- LIQUID--- LIQUID instance Traversable (Map k) where--- LIQUID traverse f = traverseWithKey (\_ -> f)--- LIQUID--- LIQUID instance Foldable.Foldable (Map k) where--- LIQUID fold Tip = mempty--- LIQUID fold (Bin _ _ v l r) = Foldable.fold l `mappend` v `mappend` Foldable.fold r--- LIQUID foldr = foldr--- LIQUID foldl = foldl--- LIQUID foldMap _ Tip = mempty--- LIQUID foldMap f (Bin _ _ v l r) = Foldable.foldMap f l `mappend` f v `mappend` Foldable.foldMap f r--- LIQUID--- LIQUID instance (NFData k, NFData a) => NFData (Map k a) where--- LIQUID rnf Tip = ()--- LIQUID rnf (Bin _ kx x l r) = rnf kx `seq` rnf x `seq` rnf l `seq` rnf r--{--------------------------------------------------------------------- Read---------------------------------------------------------------------}--- LIQUID instance (Ord k, Read k, Read e) => Read (Map k e) where--- LIQUID #ifdef __GLASGOW_HASKELL__--- LIQUID readPrec = parens $ prec 10 $ do--- LIQUID Ident "fromList" <- lexP--- LIQUID xs <- readPrec--- LIQUID return (fromList xs)--- LIQUID--- LIQUID readListPrec = readListPrecDefault--- LIQUID #else--- LIQUID readsPrec p = readParen (p > 10) $ \ r -> do--- LIQUID ("fromList",s) <- lex r--- LIQUID (xs,t) <- reads s--- LIQUID return (fromList xs,t)--- LIQUID #endif--{--------------------------------------------------------------------- Show---------------------------------------------------------------------}--- LIQUID instance (Show k, Show a) => Show (Map k a) where--- LIQUID showsPrec d m = showParen (d > 10) $--- LIQUID showString "fromList " . shows (toList m)---- | /O(n)/. Show the tree that implements the map. The tree is shown--- in a compressed, hanging format. See 'showTreeWith'.-showTree :: (Show k,Show a) => Map k a -> String-showTree m- = showTreeWith showElem True False m- where- showElem k x = show k ++ ":=" ++ show x---{- | /O(n)/. The expression (@'showTreeWith' showelem hang wide map@) shows- the tree that implements the map. Elements are shown using the @showElem@ function. If @hang@ is- 'True', a /hanging/ tree is shown otherwise a rotated tree is shown. If- @wide@ is 'True', an extra wide version is shown.--> Map> let t = fromDistinctAscList [(x,()) | x <- [1..5]]-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) True False t-> (4,())-> +--(2,())-> | +--(1,())-> | +--(3,())-> +--(5,())->-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) True True t-> (4,())-> |-> +--(2,())-> | |-> | +--(1,())-> | |-> | +--(3,())-> |-> +--(5,())->-> Map> putStrLn $ showTreeWith (\k x -> show (k,x)) False True t-> +--(5,())-> |-> (4,())-> |-> | +--(3,())-> | |-> +--(2,())-> |-> +--(1,())---}-showTreeWith :: (k -> a -> String) -> Bool -> Bool -> Map k a -> String-showTreeWith showelem hang wide t- | hang = (showsTreeHang showelem wide [] t) ""- | otherwise = (showsTree showelem wide [] [] t) ""--{-@ decrease showsTree 5 @-}-showsTree :: (k -> a -> String) -> Bool -> [String] -> [String] -> Map k a -> ShowS-showsTree showelem wide lbars rbars t- = case t of- Tip -> showsBars lbars . showString "|\n"- Bin _ kx x Tip Tip- -> showsBars lbars . showString (showelem kx x) . showString "\n"- Bin _ kx x l r- -> showsTree showelem wide (withBar rbars) (withEmpty rbars) r .- showWide wide rbars .- showsBars lbars . showString (showelem kx x) . showString "\n" .- showWide wide lbars .- showsTree showelem wide (withEmpty lbars) (withBar lbars) l--{-@ decrease showsTreeHang 4 @-}-showsTreeHang :: (k -> a -> String) -> Bool -> [String] -> Map k a -> ShowS-showsTreeHang showelem wide bars t- = case t of- Tip -> showsBars bars . showString "|\n"- Bin _ kx x Tip Tip- -> showsBars bars . showString (showelem kx x) . showString "\n"- Bin _ kx x l r- -> showsBars bars . showString (showelem kx x) . showString "\n" .- showWide wide bars .- showsTreeHang showelem wide (withBar bars) l .- showWide wide bars .- showsTreeHang showelem wide (withEmpty bars) r--showWide :: Bool -> [String] -> String -> String-showWide wide bars- | wide = showString (concat (reverse bars)) . showString "|\n"- | otherwise = id--showsBars :: [String] -> ShowS-showsBars bars- = case bars of- [] -> id- _ -> showString (concat (reverse (tail bars))) . showString node--node :: String-node = "+--"--withBar, withEmpty :: [String] -> [String]-withBar bars = "| ":bars-withEmpty bars = " ":bars--{--------------------------------------------------------------------- Typeable---------------------------------------------------------------------}---- LIQUID #include "Typeable.h"--- LIQUID INSTANCE_TYPEABLE2(Map,mapTc,"Map")--{--------------------------------------------------------------------- Assertions---------------------------------------------------------------------}--- | /O(n)/. Test if the internal map structure is valid.------ > valid (fromAscList [(3,"b"), (5,"a")]) == True--- > valid (fromAscList [(5,"a"), (3,"b")]) == False--valid :: Ord k => Map k a -> Bool-valid t- = balanced t && ordered t && validsize t--ordered :: Ord a => Map a b -> Bool-ordered t- = bounded (const True) (const True) t- where- bounded lo hi t'- = case t' of- Tip -> True- Bin _ kx _ l r -> (lo kx) && (hi kx) && bounded lo (<kx) l && bounded (>kx) hi r---- | Exported only for "Debug.QuickCheck"-balanced :: Map k a -> Bool-balanced t- = case t of- Tip -> True- Bin _ _ _ l r -> (size l + size r <= 1 || (size l <= delta*size r && size r <= delta*size l)) &&- balanced l && balanced r--validsize :: Map a b -> Bool-validsize t- = (realsize t == Just (size t))- where- realsize t'- = case t' of- Tip -> Just 0- Bin sz _ _ l r -> case (realsize l,realsize r) of- (Just n,Just m) | n+m+1 == sz -> Just sz- _ -> Nothing--{--------------------------------------------------------------------- Utilities---------------------------------------------------------------------}-foldlStrict :: (a -> b -> a) -> a -> [b] -> a-foldlStrict f = go- where- go z [] = z- go z (x:xs) = let z' = f z x in z' `seq` go z' xs-{-# INLINE foldlStrict #-}
@@ -1,73 +0,0 @@-module LiquidArray where--import Language.Haskell.Liquid.Prelude (liquidAssume)--{-@ set :: forall a <p :: x0: Int -> x1: a -> Bool, r :: x0: Int -> Bool>.- i: Int<r> ->- x: a<p i> ->- a: (j: {v: Int<r> | v != i} -> a<p j>) ->- (k: Int<r> -> a<p k>) @-}-set :: Int -> a -> (Int -> a) -> (Int -> a)-set i x a = \k -> if k == i then x else a k--{-@ get :: forall a <p :: x0: Int -> x1: a -> Bool, r :: x0: Int -> Bool>.- i: Int<r> ->- a: (j: Int<r> -> a<p j>) ->- a<p i> - @-}-get :: Int -> (Int -> a) -> a-get i a = a i-------------------------------------------------------------------------------------------------------------- memoization ------------------------------------------------------------------------------------------------------------------------{-@ measure fib :: Int -> Int @-}--{-@ type FibV = j:Int -> { v : Int | v /= 0 => (v = fib j) } @-}--type FibVV = Int -> Int --{-@ assume axiom_fib :: i:Int -> {v: Bool | v <=> (fib i = (if i <= 1 then 1 else (fib (i-1) + fib (i-2)))) } @-}-axiom_fib :: Int -> Bool-axiom_fib = undefined--{-@ fastFib :: x:Int -> {v:Int | v = fib x} @-}-fastFib :: Int -> Int-fastFib n = case fibMemo (\_ -> 0) n of - (_, res) -> res --{-@ fibMemo :: FibV -> i:Int -> (FibV, {v: Int | v = fib i}) @-}-fibMemo :: FibVV -> Int -> (FibVV, Int) -fibMemo t i - | i <= 1 - = (t, liquidAssume (axiom_fib i) (1 :: Int))- - | otherwise - = case get i t of - 0 -> let (t1, n1) = fibMemo t (i-1)- (t2, n2) = fibMemo t1 (i-2)- n = liquidAssume (axiom_fib i) (n1 + n2)- in (set i n t2, n)- n -> (t, n)---------------------
@@ -1,129 +0,0 @@-{-@ LIQUID "--no-termination" @-}--module GhcSort () where--import Language.Haskell.Liquid.Prelude--{-@ type OList a = [a]<{\fld v -> (v >= fld)}> @-}-{-@ type DList a = [a]<{\fld v -> (fld >= v)}> @-}--------------------------------------------------------------------------------------------------------- Official GHC Sort ----------------------------------------------------------------------------------------------------------{-@ sort1 :: (Ord a) => [a] -> OList a @-}-sort1 :: (Ord a) => [a] -> [a]-sort1 = mergeAll . sequences- where- sequences (a:b:xs)- | a > b = descending b [a] xs- | otherwise = ascending b (a:) xs -- a >= b => (a:) -> - sequences [x] = [[x]]- sequences [] = [[]]- {- descending :: x:a -> OList {v:a | x < v} -> [a] -> [OList a] @-}- descending a as (b:bs)- | a > b = descending b (a:as) bs- descending a as bs = (a:as): sequences bs-- {- ascending :: x:a -> (OList {v:a|v>=x} -> OList a) -> [a] -> [OList a] @-}- ascending a as (b:bs)- | a <= b = ascending b (\ys -> as (a:ys)) bs -- a <= b- ascending a as bs = as [a]: sequences bs-- mergeAll [x] = x- mergeAll xs = mergeAll (mergePairs xs)-- mergePairs (a:b:xs) = merge1 a b: mergePairs xs- mergePairs [x] = [x]- mergePairs [] = []---- merge1 needs to be toplevel,--- to get applied transformRec tx-merge1 (a:as') (b:bs')- | a > b = b:merge1 (a:as') bs'- | otherwise = a:merge1 as' (b:bs')-merge1 [] bs = bs-merge1 as [] = as------------------------------------------------------------------------------------------------- Mergesort ---------------------------------------------------------------------------------------------------------------------------{-@ sort2 :: (Ord a) => [a] -> OList a @-}-sort2 :: (Ord a) => [a] -> [a]-sort2 = mergesort--mergesort :: (Ord a) => [a] -> [a]-mergesort = mergesort' . map wrap--mergesort' :: (Ord a) => [[a]] -> [a]-mergesort' [] = []-mergesort' [xs] = xs-mergesort' xss = mergesort' (merge_pairs xss)--merge_pairs :: (Ord a) => [[a]] -> [[a]]-merge_pairs [] = []-merge_pairs [xs] = [xs]-merge_pairs (xs:ys:xss) = merge xs ys : merge_pairs xss--merge :: (Ord a) => [a] -> [a] -> [a]-merge [] ys = ys-merge xs [] = xs-merge (x:xs) (y:ys)- | x > y = y : merge (x:xs) ys- | otherwise = x : merge xs (y:ys)--wrap :: a -> [a]-wrap x = [x]--------------------------------------------------------------------------------------------- QuickSort ----------------------------------------------------------------------------------------------------------------{-@ sort3 :: (Ord a) => w:a -> [{v:a|v<=w}] -> OList a @-}-sort3 :: (Ord a) => a -> [a] -> [a]-sort3 w ls = qsort w ls []---- qsort is stable and does not concatenate.-qsort :: (Ord a) => a -> [a] -> [a] -> [a]-qsort _ [] r = r-qsort _ [x] r = x:r-qsort w (x:xs) r = qpart w x xs [] [] r---- qpart partitions and sorts the sublists-qpart :: (Ord a) => a -> a -> [a] -> [a] -> [a] -> [a] -> [a]-qpart w x [] rlt rge r =- -- rlt and rge are in reverse order and must be sorted with an- -- anti-stable sorting- rqsort x rlt (x:rqsort w rge r)-qpart w x (y:ys) rlt rge r =- case compare x y of- GT -> qpart w x ys (y:rlt) rge r- _ -> qpart w x ys rlt (y:rge) r---- rqsort is as qsort but anti-stable, i.e. reverses equal elements-rqsort :: (Ord a) => a -> [a] -> [a] -> [a]-rqsort _ [] r = r-rqsort _ [x] r = x:r-rqsort w (x:xs) r = rqpart w x xs [] [] r--rqpart :: (Ord a) => a -> a -> [a] -> [a] -> [a] -> [a] -> [a]-rqpart w x [] rle rgt r =- qsort x rle (x:qsort w rgt r)-rqpart w x (y:ys) rle rgt r =- case compare y x of- GT -> rqpart w x ys rle (y:rgt) r- _ -> rqpart w x ys (y:rle) rgt r-------------
@@ -1,64 +0,0 @@-{-@ LIQUID "--no-termination" @-}--module ListSort (insertSort, insertSort', mergeSort, quickSort) where--{-@ type OList a = [a]<{\fld v -> (v >= fld)}> @-}----------------------------------------------------------------------------------- Insert Sort ------------------------------------------------------------------------------------------------------------------------------------------------{-@ insertSort :: (Ord a) => xs:[a] -> OList a @-}-insertSort :: (Ord a) => [a] -> [a]-insertSort [] = []-insertSort (x:xs) = insert x (insertSort xs) --{-@ insertSort' :: (Ord a) => xs:[a] -> OList a @-}-insertSort' :: (Ord a) => [a] -> [a]-insertSort' xs = foldr insert [] xs--insert y [] = [y]-insert y (x : xs) | y <= x = y : x : xs - | otherwise = x : insert y xs----------------------------------------------------------------------------------- Merge Sort -------------------------------------------------------------------------------------------------------------------------------------------------{-@ mergeSort :: (Ord a) => [a] -> OList a @-}-mergeSort :: Ord a => [a] -> [a]-mergeSort [] = []-mergeSort [x] = [x]-mergeSort xs = merge (mergeSort xs1) (mergeSort xs2) where (xs1, xs2) = split xs--split :: [a] -> ([a], [a])-split (x:(y:zs)) = (x:xs, y:ys) where (xs, ys) = split zs-split xs = (xs, [])--merge :: Ord a => [a] -> [a] -> [a]-merge xs [] = xs-merge [] ys = ys-merge (x:xs) (y:ys)- | x <= y- = x:(merge xs (y:ys))- | otherwise - = y:(merge (x:xs) ys)----------------------------------------------------------------------------------- Quick Sort -------------------------------------------------------------------------------------------------------------------------------------------------{-@ quickSort :: (Ord a) => [a] -> OList a @-}-quickSort [] = []-quickSort (x:xs) = append x lts gts - where lts = quickSort [y | y <- xs, y < x]- gts = quickSort [z | z <- xs, z >= x]--append k [] ys = k : ys-append k (x:xs) ys = x : append k xs ys------
@@ -1,426 +0,0 @@-{-@ LIQUID "--no-totality" @-}-{-|- Purely functional top-down splay sets.-- * D.D. Sleator and R.E. Rarjan,- \"Self-Adjusting Binary Search Tree\",- Journal of the Association for Computing Machinery,- Vol 32, No 3, July 1985, pp 652-686.- <http://www.cs.cmu.edu/~sleator/papers/self-adjusting.pdf>--}--module Data.Set.Splay (- -- * Data structures- Splay(..)- -- * Creating sets- , empty- , singleton- , insert- , fromList- -- * Converting a list- , toList- -- * Membership- , member- -- * Deleting- , delete- , deleteMin- , deleteMax- -- * Checking- , null- -- * Set operations- , union- , intersection- , difference- -- * Helper functions- , split- , minimum- , maximum- , valid- , (===)- , showSet- , printSet- , slen- ) where--import Data.List (foldl')-import Prelude hiding (minimum, maximum, null)-import Language.Haskell.Liquid.Prelude---------------------------------------------------------------------- LIQUID left depends on value, so their order had to be changed-{-@ data Splay [slen] a <l :: root:a -> a -> Bool, r :: root:a -> a -> Bool>- = Node (value :: a) - (left :: Splay <l, r> (a <l value>)) - (right :: Splay <l, r> (a <r value>)) - | Leaf -@-}--{-@ measure slen @-}-slen :: Splay a -> Int-slen (Leaf) = 0-slen (Node v l r) = 1 + (slen l) + (slen r)--{-@ type SumSLen A B = {v:Nat | v = (slen A) + (slen B)} @-}--{-@ invariant {v:Splay a | (slen v) >= 0} @-}--data Splay a = Leaf | Node a (Splay a) (Splay a) deriving Show--{-@ type OSplay a = Splay <{\root v -> v < root}, {\root v -> v > root}> a @-}--{-@ type OSplayLE a S = {v:OSplay a | (slen v) <= (slen S)} @-}--{-@ type MinSPair a = (a, OSplay a) <\fld -> {v : Splay {v:a|v>fld} | 0=0}> @-}-{-@ type MinEqSPair a = (a, OSplay a) <\fld -> {v : Splay {v:a|v>=fld}| 0=0}> @-}--{-@ type MaxSPair a = (a, OSplay a) <\fld -> {v : Splay {v:a|v<fld} | 0=0}> @-}-{-@ type MaxEqSPair a = (a, OSplay a) <\fld -> {v : Splay {v:a|v<=fld}| 0=0}> @-}--instance (Eq a) => Eq (Splay a) where- t1 == t2 = toList t1 == toList t2--{-| Checking if two splay sets are exactly the same shape.--}-(===) :: Eq a => Splay a -> Splay a -> Bool-Leaf === Leaf = True-(Node x1 l1 r1) === (Node x2 l2 r2) = x1 == x2 && l1 === l2 && r1 === r2-_ === _ = False--------------------------------------------------------------------{-| Splitting smaller and bigger with splay.- Since this is a set implementation, members must be unique.--}--{-@ split :: Ord a => x:a -> s:OSplay a- -> (OSplayLE {v:a | v<x} s, Bool, OSplayLE {v:a | v>x} s)- @-}--split :: Ord a => a -> Splay a -> (Splay a, Bool, Splay a)-split _ Leaf = (Leaf,False,Leaf)-split k (Node xk xl xr) = case compare k xk of- EQ -> (xl, True, xr)- GT -> case xr of- Leaf -> (Node xk xl Leaf, False, Leaf)- Node yk yl yr -> case compare k yk of- EQ -> (Node xk xl yl, True, yr) -- R :zig- GT -> let (lt, b, gt) = split k yr -- RR :zig zag- in (Node yk (Node xk xl yl) lt, b, gt)- LT -> let (lt, b, gt) = split k yl- in (Node xk xl lt, b, Node yk gt yr) -- RL :zig zig- LT -> case xl of- Leaf -> (Leaf, False, Node xk Leaf xr)- Node yk yl yr -> case compare k yk of- EQ -> (yl, True, Node xk yr xr) -- L :zig- GT -> let (lt, b, gt) = split k yr -- LR :zig zag- in (Node yk yl lt, b, Node xk gt xr)- LT -> let (lt, b, gt) = split k yl -- LL :zig zig- in (lt, b, Node yk gt (Node xk yr xr))-------------------------------------------------------------------{-| Empty set.--}--{-@ empty :: OSplay a @-}-empty :: Splay a-empty = Leaf--{-|-See if the splay set is empty.-->>> Data.Set.Splay.null empty-True->>> Data.Set.Splay.null (singleton 1)-False--}--null :: Splay a -> Bool-null Leaf = True-null _ = False--{-| Singleton set.--}--{-@ singleton :: a -> OSplay a @-}-singleton :: a -> Splay a-singleton x = Node x Leaf Leaf--------------------------------------------------------------------{-| Insertion.-->>> insert 5 (fromList [5,3]) == fromList [3,5]-True->>> insert 7 (fromList [5,3]) == fromList [3,5,7]-True->>> insert 5 empty == singleton 5-True--}--{-@ insert :: Ord a => a -> OSplay a -> OSplay a @-}-insert :: Ord a => a -> Splay a -> Splay a-insert x t = Node x l r- where- (l,_,r) = split x t--------------------------------------------------------------------{-| Creating a set from a list.-->>> empty == fromList []-True->>> singleton 'a' == fromList ['a']-True->>> fromList [5,3,5] == fromList [5,3]-True--}--{-@ fromList :: Ord a => [a] -> OSplay a @-}-fromList :: Ord a => [a] -> Splay a-fromList = foldl' (flip insert) empty--------------------------------------------------------------------{-| Creating a list from a set.-->>> toList (fromList [5,3])-[3,5]->>> toList empty-[]--}--toList :: Splay a -> [a]-toList t = inorder t []- where- inorder Leaf xs = xs- inorder (Node x l r) xs = inorder l (x : inorder r xs)-------------------------------------------------------------------{-| Checking if this element is a member of a set?-->>> fst $ member 5 (fromList [5,3])-True->>> fst $ member 1 (fromList [5,3])-False--}--{-@ member :: Ord a => a -> OSplay a -> (Bool, OSplay a) @-}-member :: Ord a => a -> Splay a -> (Bool, Splay a)-member x t = case split x t of- (l,True,r) -> (True, Node x l r)- (Leaf,_,r) -> (False, r)- (l,_,Leaf) -> (False, l)- (l,_,r) -> let (m,l') = deleteMax l- in (False, Node m l' r)--------------------------------------------------------------------{-| Finding the minimum element.-->>> fst $ minimum (fromList [3,5,1])-1->>> minimum empty-*** Exception: minimum--}--{-@ minimum :: OSplay a -> MinEqSPair a @-}-minimum :: Splay a -> (a, Splay a)-minimum Leaf = unsafeError "minimum"-minimum t = let (x,mt) = deleteMin t in (x, Node x Leaf mt)--{-| Finding the maximum element.-->>> fst $ maximum (fromList [3,5,1])-5->>> maximum empty-*** Exception: maximum--}--{-@ maximum :: OSplay a -> MaxEqSPair a @-}-maximum :: Splay a -> (a, Splay a)-maximum Leaf = unsafeError "maximum"-maximum t = let (x,mt) = deleteMax t in (x, Node x mt Leaf)--------------------------------------------------------------------{-| Deleting the minimum element.-->>> snd (deleteMin (fromList [5,3,7])) == fromList [5,7]-True->>> deleteMin empty-*** Exception: deleteMin--}--{-@ deleteMin :: OSplay a -> MinSPair a @-}-deleteMin :: Splay a -> (a, Splay a)-deleteMin Leaf = unsafeError "deleteMin"-deleteMin (Node x Leaf r) = (x,r)-deleteMin (Node x (Node lx Leaf lr) r) = (lx, Node x lr r)-deleteMin (Node x (Node lx ll lr) r) = let (k,mt) = deleteMin ll- in (k, Node lx mt (Node x lr r))--{-| Deleting the maximum-->>> snd (deleteMax (fromList [(5,"a"), (3,"b"), (7,"c")])) == fromList [(3,"b"), (5,"a")]-True->>> deleteMax empty-*** Exception: deleteMax--}---{-@ deleteMax :: OSplay a -> MaxSPair a @-}-deleteMax :: Splay a -> (,) a (Splay a)-deleteMax Leaf = unsafeError "deleteMax"-deleteMax (Node x l Leaf) = (x,l)-deleteMax (Node x l (Node rx rl Leaf)) = (rx, Node x l rl)-deleteMax (Node x l (Node rx rl rr)) = let (k,mt) = deleteMax rr- in (k, Node rx (Node x l rl) mt)-------------------------------------------------------------------{-| Deleting this element from a set.-->>> delete 5 (fromList [5,3]) == singleton 3-True->>> delete 7 (fromList [5,3]) == fromList [3,5]-True->>> delete 5 empty == empty-True--}---- Liquid TOPROVE--- delete :: Ord a => x:a -> OSplay a -> OSplay {v:a| v!=x}-{-@ delete :: Ord a => x:a -> OSplay a -> OSplay a @-}-delete :: Ord a => a -> Splay a -> Splay a-delete x t = case split x t of- (l, True, r) -> union l r- _ -> t--------------------------------------------------------------------{-| Creating a union set from two sets.-->>> union (fromList [5,3]) (fromList [5,7]) == fromList [3,5,7]-True--}--{-@ union :: Ord a => OSplay a -> OSplay a -> OSplay a@-}-union :: Ord a => Splay a -> Splay a -> Splay a-union a b = unionT a b (slen a + slen b)---LIQUID union Leaf t = t---LIQUID union (Node x a b) t = Node x (union ta a) (union tb b)---LIQUID where---LIQUID (ta,_,tb) = split x t--{-@ unionT :: Ord a => a:OSplay a -> b:OSplay a -> SumSLen a b -> OSplay a @-}-{-@ decrease unionT 4 @-}-{- LIQUID WITNESS -}-unionT :: Ord a => Splay a -> Splay a -> Int -> Splay a-unionT Leaf t _ = t-unionT (Node x a b) t _ = Node x (unionT ta a (slen ta + slen a))- (unionT tb b (slen tb + slen b))- where- (ta,_,tb) = split x t---{-| Creating a intersection set from sets.-->>> intersection (fromList [5,3]) (fromList [5,7]) == singleton 5-True--}--{-@ intersection :: Ord a => OSplay a -> OSplay a -> OSplay a @-}-intersection :: Ord a => Splay a -> Splay a -> Splay a-intersection a b = intersectionT a b (slen a + slen b)---LIQUID intersection Leaf _ = Leaf---LIQUID intersection _ Leaf = Leaf---LIQUID intersection t1 (Node x l r) = case split x t1 of---LIQUID (l', True, r') -> Node x (intersection l' l) (intersection r' r)---LIQUID (l', False, r') -> union (intersection l' l) (intersection r' r)--{-@ intersectionT :: Ord a => a:OSplay a -> b:OSplay a -> SumSLen a b -> OSplay a @-}-{-@ decrease intersectionT 4 @-}-{- LIQUID WITNESS -}-intersectionT :: Ord a => Splay a -> Splay a -> Int -> Splay a-intersectionT Leaf _ _ = Leaf-intersectionT _ Leaf _ = Leaf-intersectionT t1 (Node x l r) _ = case split x t1 of- (l', True, r') -> Node x (intersectionT l' l (slen l' + slen l))- (intersectionT r' r (slen r' + slen r))- (l', False, r') -> union (intersectionT l' l (slen l' + slen l))- (intersectionT r' r (slen r' + slen r))--{-| Creating a difference set from sets.-->>> difference (fromList [5,3]) (fromList [5,7]) == singleton 3-True--}--{-@ difference :: Ord a => OSplay a -> OSplay a -> OSplay a @-}-difference :: Ord a => Splay a -> Splay a -> Splay a-difference a b = differenceT a b (slen a + slen b)---LIQUID difference Leaf _ = Leaf---LIQUID difference t1 Leaf = t1---LIQUID difference t1 (Node x l r) = union (difference l' l) (difference r' r)---LIQUID where---LIQUID (l',_,r') = split x t1--{-@ differenceT :: Ord a => a:OSplay a -> b:OSplay a -> SumSLen a b -> OSplay a @-}-{-@ decrease differenceT 4 @-}-{- LIQUID WITNESS -}-differenceT :: Ord a => Splay a -> Splay a -> Int -> Splay a-differenceT Leaf _ _ = Leaf-differenceT t1 Leaf _ = t1-differenceT t1 (Node x l r) _ = union (differenceT l' l (slen l' + slen l))- (differenceT r' r (slen r' + slen r))- where- (l',_,r') = split x t1--------------------------------------------------------------------- Basic operations------------------------------------------------------------------{-| Checking validity of a set.--}--valid :: Ord a => Splay a -> Bool-valid t = isOrdered t--isOrdered :: Ord a => Splay a -> Bool-isOrdered t = ordered $ toList t- where- ordered [] = True- ordered [_] = True- ordered (x:y:xys) = x < y && ordered (y:xys)---showSet :: Show a => Splay a -> String-showSet = showSet_go ""----LIQUID FIXME: renamed from `showSet'`, must fix parser!--{-@ decrease showSet_go 3 @-}-showSet_go :: Show a => String -> Splay a -> String-showSet_go _ Leaf = "\n"-showSet_go pref (Node x l r) = show x ++ "\n"- ++ pref ++ "+ " ++ showSet_go pref' l- ++ pref ++ "+ " ++ showSet_go pref' r- where- pref' = " " ++ pref--printSet :: Show a => Splay a -> IO ()-printSet = putStr . showSet--{--Demo: http://www.link.cs.cmu.edu/splay/-Paper: http://www.cs.cmu.edu/~sleator/papers/self-adjusting.pdf-TopDown: http://www.cs.umbc.edu/courses/undergraduate/341/fall02/Lectures/Splay/TopDownSplay.ppt-Blog: http://chasen.org/~daiti-m/diary/?20061223- http://www.geocities.jp/m_hiroi/clisp/clispb07.html--- fromList minimum delMin member-Blanced Tree N log N log N log N log N-Skew Heap N log N 1 log N(???) N/A-Splay Heap N log N or A(N)? log N or A(N)? log N or A(N)?---}
@@ -1,113 +0,0 @@-{-@ LIQUID "--pruneunsorted" @-}--{-@ LIQUID "--no-termination" @-}-{-@ LIQUID "--no-totality" @-}--module Toy (sizeOf) where--import Language.Haskell.Liquid.Prelude (isEven)------------------------------------------------------------------------------ | Parametric Invariants over Base Types ----------------------------------------------------------------------------------------------------------maxInt :: Int -> Int -> Int -maxInt x y = if x <= y then y else x --maximumInt :: [Int] -> Int -maximumInt (x:xs) = foldr maxInt x xs--{-@ maxEvens1 :: [Int] -> {v:Int | v mod 2 = 0 } @-}-maxEvens1 xs = maximumInt (0 : xs') - where xs' = [ x | x <- xs, isEven x]------------------------------------------------------------------------------ | Parametric Invariants over Class-Predicated Tyvars ---------------------------------------------------------------------------------------------maxPoly :: (Ord a) => a -> a -> a -maxPoly x y = if x <= y then y else x--maximumPoly :: (Ord a) => [a] -> a-maximumPoly (x:xs) = foldr maxPoly x xs--{-@ maxEvens2 :: [Int] -> {v:Int | v mod 2 = 0 } @-}-maxEvens2 xs = maximumPoly (0 : xs') - where xs' = [ x | x <- xs, isEven x]------------------------------------------------------------------------------ | Induction over Int Ranges ----------------------------------------------------------------------------------------------------------------------{-@ foldN :: forall a <p :: x0:Int -> x1:a -> Bool>. - (i:Int -> a<p i> -> a<p (i+1)>) - -> n:{v: Int | v >= 0}- -> a <p 0> - -> a <p n>- @-}--foldN :: (Int -> a -> a) -> Int -> a -> a-foldN f n = go 0 - where go i x | i < n = go (i+1) (f i x)- | otherwise = x--{-@ count :: m: {v: Int | v > 0 } -> {v: Int | v = m} @-}-count :: Int -> Int-count m = foldN (\_ n -> n + 1) m 0------------------------------------------------------------------------------ | Induction over Data types ----------------------------------------------------------------------------------------------------------------------data Vec a = Nil | Cons a (Vec a)--{-@ data Vec [sizeOf] @-} -- a = Nil | Cons (x::a) (xs::Vec a) ---- | As a warmup, lets check that a /real/ length function indeed computes--- the length of the list.--{-@ measure sizeOf @-}-{-@ sizeOf :: xs:Vec a -> {v: Int | v = sizeOf xs} @-}-sizeOf :: Vec a -> Int-sizeOf Nil = 0-sizeOf (Cons _ xs) = 1 + sizeOf xs------------------------------------------------------------------------------ | Higher-order fold -------------------------------------------------- ------------------------------------------------------------------------------ | Time to roll up the sleeves. Here's a a higher-order @foldr@ function--- for our `Vec` type. Note that the `op` argument takes an extra /ghost/--- parameter that will let us properly describe the type of `efoldr` --{-@ efoldr :: forall a b <p :: x0:Vec a -> x1:b -> Bool>. - (xs:Vec a -> x:a -> b <p xs> -> b <p (Toy.Cons x xs)>) - -> b <p Toy.Nil> - -> ys: Vec a- -> b <p ys>- @-}-efoldr :: (Vec a -> a -> b -> b) -> b -> Vec a -> b-efoldr op b Nil = b-efoldr op b (Cons x xs) = op xs x (efoldr op b xs) ------------------------------------------------------------------------------ | Clients of `efold` ------------------------------------------------- ------------------------------------------------------------------------------ | Finally, lets write a few /client/ functions that use `efoldr` to --- operate on the `Vec`s. ---- | First: Computing the length using `efoldr`-{-@ size :: xs:Vec a -> {v: Int | v = sizeOf(xs)} @-}-size :: Vec a -> Int-size = efoldr (\_ _ n -> n + 1) 0---- | The above uses a helper that counts up the size. (Pesky hack to avoid writing qualifier v = ~A + 1)-{-@ suc :: x:Int -> {v: Int | v = x + 1} @-}-suc :: Int -> Int-suc x = x + 1 ---- | Second: Appending two lists using `efoldr`-{-@ app :: xs: Vec a -> ys: Vec a -> {v: Vec a | sizeOf(v) = sizeOf(xs) + sizeOf(ys) } @-} -app xs ys = efoldr (\_ z zs -> Cons z zs) ys xs -
@@ -1,35 +0,0 @@-#!/usr/bin/python--# used by count.sh--import re-import sys-import string--fname = sys.argv[1]-str = (open(fname, 'r')).read()--#measures = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ measure', str)) ]-other = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ (type|measure|data|include|predicate)', str)) ]-tyspecs = [(str[a.start():(3+string.find(str,"@-}", a.start()))]) for a in list(re.finditer('{-@ (?!(type|measure|data|include|predicate))', str)) ]--#print measures-#print tyspecs-#print other-#print "Measures :\t\t count = %d \t chars = %d \t lines = %d" %(len(measures), sum(map(lambda x:len(x), measures)), sum(map(lambda x:(1+x.count('\n')), measures)))-print "Type specifications:\t\t count = %d \t lines = %d" %(len(tyspecs), sum(map(lambda x:(1+x.count('\n')), tyspecs)))-print "Other Annotations :\t\t count = %d \t lines = %d" %(len(other), sum(map(lambda x:(1+x.count('\n')), other)))---ftyspec = open('_'.join(["tyspec", fname, ".txt"]), 'w')-fother = open('_'.join(["other", fname, ".txt"]), 'w')--#tmp.write("TYSPECS\n\n")-tyspecsJoined = '\n'.join(tyspecs)-ftyspec.write(tyspecsJoined)--#tmp.write("\n\nOTHER\n\n")-otherJoined = '\n'.join(other)-fother.write(otherJoined)--
@@ -1,10 +0,0 @@-for file in $(ls *.hs); do-content=`cat $file`-echo $file-lines= sloccount $file | grep "Total Physical Source"-echo $lines-python count.py $file $lines-#echo "Time = "-#time liquid $file > /dev/null | tail -n1-echo ""-done
@@ -1,100 +0,0 @@-{-#LH LIQUID "--higherorder" @-}-{-#LH LIQUID "--totality" @-}-{-#LH LIQUID "--exact-data-cons" @-}-{-#LH LIQUID "--higherorderqs" @-}--module Peano where--import Prelude hiding (plus)---- import Proves--import ProofCombinators---- Why do we need these?-zeroR :: Peano -> Proof-zeroL :: Peano -> Proof-plusAssoc :: Peano -> Peano -> Peano -> Proof-plusComm :: Peano -> Peano -> Proof-plusSuccR :: Peano -> Peano -> Proof--infixl 3 ==.--(==.) :: a -> a -> a-x ==. _ = x --data Peano = Z | S Peano--{-#LH data Peano [toInt] = Z | S {prev :: Peano} @-}--{-#LH measure toInt @-}-toInt :: Peano -> Int--{-#LH toInt :: Peano -> Nat @-}-toInt Z = 0-toInt (S n) = 1 + toInt n--{-#LH axiomatize plus @-}-plus :: Peano -> Peano -> Peano-plus Z m = m-plus (S n) m = S (plus n m)--{-#LH zeroL :: n:Peano -> { plus Z n == n } @-}-zeroL n- = plus Z n- ==! n- *** QED--{-#LH zeroR :: n:Peano -> { plus n Z == n } @-}-zeroR Z- = plus Z Z- ==! Z- *** QED--zeroR (S n)- = plus (S n) Z- ==! S (plus n Z)- ==! S n ∵ zeroR n- *** QED--{-#LH plusSuccR :: n:Peano -> m:Peano -> { plus n (S m) = S (plus n m) } @-}-plusSuccR Z m- = plus Z (S m)- ==! S m- ==! S (plus Z m)- *** QED--plusSuccR (S n) m- = plus (S n) (S m)- ==! S (plus n (S m))- ==! S (S (plus n m)) ∵ plusSuccR n m- ==! S (plus (S n) m)- *** QED--{-#LH plusComm :: a:_ -> b:_ -> {plus a b == plus b a} @-}-plusComm Z b- = plus Z b- ==! plus b Z ∵ zeroR b- *** QED--plusComm (S a) b- = plus (S a) b- ==! S (plus a b)- ==! S (plus b a) ∵ plusComm a b- ==! plus b (S a) ∵ plusSuccR b a- *** QED--{-#LH plusAssoc :: a:_ -> b:_ -> c:_ -> {plus (plus a b) c == plus a (plus b c) } @-}-plusAssoc Z b c- = plus (plus Z b) c- ==! plus b c- ==! plus Z (plus b c)- *** QED--plusAssoc (S a) b c- = plus (plus (S a) b) c- ==! plus (S (plus a b)) c- ==! S (plus (plus a b) c)- ==! S (plus a (plus b c)) ∵ plusAssoc a b c- ==! plus (S a) (plus b c)- *** QED
@@ -1,155 +0,0 @@-{-- GSL and LAPACK may require auxiliary libraries which depend on OS,- distribution, and implementation. This script tries to to find out- the correct link command for your system.- Suggestions and contributions are welcome.-- By default we try to link -lgsl -llapack. This works in ubuntu/debian,- both with and without ATLAS.- If this fails we try different sets of additional libraries which are- known to work in some systems.-- The desired libraries can also be explicitly given by the user using cabal- flags (e.g., -fmkl, -faccelerate) or --configure-option=link:lib1,lib2,lib3,...---}--module Config(config) where--import System.Process-import System.Exit-import System.Environment-import System.Directory(createDirectoryIfMissing)-import System.FilePath((</>))-import Data.List(isPrefixOf, intercalate)-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Configure-import Distribution.PackageDescription---- possible additional dependencies for the desired libs (by default gsl lapack)--opts = [ "" -- Ubuntu/Debian- , "blas"- , "blas cblas"- , "cblas"- , "gslcblas"- , "blas gslcblas"- , "f77blas"- , "f77blas cblas atlas gcc_s" -- Arch Linux (older version of atlas-lapack)- , "blas gslcblas gfortran" -- Arch Linux with normal blas and lapack- ]---- location of test program-testProgLoc bInfo = buildDir bInfo </> "dummy.c"-testOutLoc bInfo = buildDir bInfo </> "dummy"---- write test program-writeTestProg bInfo contents = writeFile (testProgLoc bInfo) contents---- compile, discarding error messages-compile cmd = do- let processRecord = (shell $ join cmd) { std_out = CreatePipe- , std_err = CreatePipe }- ( _, _, _, h) <- createProcess processRecord- waitForProcess h---- command to compile the test program-compileCmd bInfo buildInfo = [ "gcc "- , (join $ ccOptions buildInfo) - , (join $ cppOptions buildInfo) - , (join $ map ("-I"++) $ includeDirs buildInfo) - , testProgLoc bInfo- , "-o"- , testOutLoc bInfo - , (join $ map ("-L"++) $ extraLibDirs buildInfo) - ]- --- compile a simple program with symbols from GSL and LAPACK with the given libs-testprog bInfo buildInfo libs fmks = do- writeTestProg bInfo "#include <gsl/gsl_sf_gamma.h>\nint main(){dgemm_(); zgesvd_(); gsl_sf_gamma(5);}"- compile $ compileCmd bInfo - buildInfo - ++ [ (prepend "-l" $ libs)- , (prepend "-framework " fmks) ] --join = intercalate " "-prepend x = unwords . map (x++) . words--check bInfo buildInfo libs fmks = (ExitSuccess ==) `fmap` testprog bInfo buildInfo libs fmks---- simple test for GSL-gsl bInfo buildInfo = do- writeTestProg bInfo "#include <gsl/gsl_sf_gamma.h>\nint main(){gsl_sf_gamma(5);}"- compile $ compileCmd bInfo buildInfo ++ ["-lgsl", "-lgslcblas"]---- test for gsl >= 1.12-gsl112 bInfo buildInfo = do- writeTestProg bInfo "#include <gsl/gsl_sf_exp.h>\nint main(){gsl_sf_exprel_n_CF_e(1,1,0);}"- compile $ compileCmd bInfo buildInfo ++ ["-lgsl", "-lgslcblas"]---- test for odeiv2-gslodeiv2 bInfo buildInfo = do- writeTestProg bInfo "#include <gsl/gsl_odeiv2.h>\nint main(){return 0;}"- compile $ compileCmd bInfo buildInfo ++ ["-lgsl", "-lgslcblas"]--checkCommand c = (ExitSuccess ==) `fmap` c---- test different configurations until the first one works-try _ _ _ _ [] = return Nothing-try l i b f (opt:rest) = do- ok <- check l i (b ++ " " ++ opt) f- if ok then return (Just opt)- else try l i b f rest---- read --configure-option=link:lib1,lib2,lib3,etc-linkop = "--configure-option=link:"-getUserLink = concatMap (g . drop (length linkop)) . filter (isPrefixOf linkop)- where g = map cs- cs ',' = ' '- cs x = x--config :: LocalBuildInfo -> IO HookedBuildInfo- -config bInfo = do- putStr "Checking foreign libraries..."- args <- getArgs-- let Just lib = library . localPkgDescr $ bInfo- buildInfo = libBuildInfo lib- base = unwords . extraLibs $ buildInfo- fwks = unwords . frameworks $ buildInfo- auxpref = getUserLink args-- -- We extract the desired libs from hmatrix.cabal (using a cabal flags)- -- and from a posible --configure-option=link:lib1,lib2,lib3- -- by default the desired libs are gsl lapack.-- let pref = if null (words (base ++ " " ++ auxpref)) then "gsl lapack" else auxpref- fullOpts = map ((pref++" ")++) opts-- -- create the build directory (used for tmp files) if necessary- createDirectoryIfMissing True $ buildDir bInfo- - r <- try bInfo buildInfo base fwks fullOpts-- case r of- Nothing -> do- putStrLn " FAIL"- g <- checkCommand $ gsl bInfo buildInfo- if g- then putStrLn " *** Sorry, I can't link LAPACK."- else putStrLn " *** Sorry, I can't link GSL."- putStrLn " *** Please make sure that the appropriate -dev packages are installed."- putStrLn " *** You can also specify the required libraries using"- putStrLn " *** cabal install hmatrix --configure-option=link:lib1,lib2,lib3,etc." - return (Just emptyBuildInfo { buildable = False }, [])- Just ops -> do- putStrLn $ " OK " ++ ops- g1 <- checkCommand $ gsl112 bInfo buildInfo- let op1 = if g1 then "" else "-DGSL110"- g2 <- checkCommand $ gslodeiv2 bInfo buildInfo- let op2 = if g2 then "" else "-DGSLODE1"- opts = filter (not.null) [op1,op2]- let hbi = emptyBuildInfo { extraLibs = words ops, ccOptions = opts }- return (Just hbi, [])-
@@ -1,2 +0,0 @@-Copyright Alberto Ruiz 2006-2007-GPL license
@@ -1,18 +0,0 @@-#! /usr/bin/env runhaskell--> import Distribution.Simple-> import Distribution.Simple.Setup-> import Distribution.PackageDescription-> import Distribution.Simple.LocalBuildInfo--> import System.Process(system)-> import Config(config)--> main = defaultMainWithHooks simpleUserHooks { confHook = c }--> c x y = do-> binfo <- confHook simpleUserHooks x y-> pbi <- config binfo-> let pkg_descr = localPkgDescr binfo-> return $ binfo { localPkgDescr = updatePackageDescription pbi pkg_descr }-
@@ -1,54 +0,0 @@--- vectorized boolean operations defined in terms of step or cond--import Numeric.LinearAlgebra--infix 4 .==., ./=., .<., .<=., .>=., .>.-infixr 3 .&&.-infixr 2 .||.--a .<. b = step (b-a)-a .<=. b = cond a b 1 1 0-a .==. b = cond a b 0 1 0-a ./=. b = cond a b 1 0 1-a .>=. b = cond a b 0 1 1-a .>. b = step (a-b)--a .&&. b = step (a*b)-a .||. b = step (a+b)-no a = 1-a-xor a b = a ./=. b-equiv a b = a .==. b-imp a b = no a .||. b--taut x = minElement x == 1--minEvery a b = cond a b a a b-maxEvery a b = cond a b b b a---- examples--clip a b x = cond y b y y b where y = cond x a a x x--disp = putStr . dispf 3--eye n = ident n :: Matrix Double-row = asRow . fromList :: [Double] -> Matrix Double-col = asColumn . fromList :: [Double] -> Matrix Double--m = (3><4) [1..] :: Matrix Double--p = row [0,0,1,1]-q = row [0,1,0,1]--main = do- print $ find (>6) m- disp $ assoc (6,8) 7 $ zip (find (/=0) (eye 5)) [10..]- disp $ accum (eye 5) (+) [((0,2),3), ((3,1),7), ((1,1),1)]- disp $ m .>=. 10 .||. m .<. 4- (disp . fromColumns . map flatten) [p, q, p.&&.q, p .||.q, p `xor` q, p `equiv` q, p `imp` q]- print $ taut $ (p `imp` q ) `equiv` (no q `imp` no p)- print $ taut $ (xor p q) `equiv` (p .&&. no q .||. no p .&&. q)- disp $ clip 3 8 m- disp $ col [1..7] .<=. row [1..5]- disp $ cond (col [1..3]) (row [1..4]) m 50 (3*m)-
@@ -1,10 +0,0 @@- 0.9 1.1- 2.1 3.9- 3.1 9.2- 4.0 51.8- 4.9 25.3- 6.1 35.7- 7.0 49.4- 7.9 3.6- 9.1 81.5-10.2 99.5
@@ -1,8 +0,0 @@--- Numerical differentiation--import Numeric.GSL--d :: (Double -> Double) -> (Double -> Double)-d f x = fst $ derivCentral 0.01 f x--main = print $ d (\x-> x * d (\y-> x+y) 1) 1
@@ -1,35 +0,0 @@-/* assuming row order */--typedef struct { double r, i; } doublecomplex;--#define DVEC(A) int A##n, double*A##p-#define CVEC(A) int A##n, doublecomplex*A##p-#define DMAT(A) int A##r, int A##c, double*A##p-#define CMAT(A) int A##r, int A##c, doublecomplex*A##p--#define AT(M,row,col) (M##p[(row)*M##c + (col)])--/*-----------------------------------------------------*/--int c_scale_vector(double s, DVEC(x), DVEC(y)) {- int k;- for (k=0; k<=yn; k++) {- yp[k] = s*xp[k];- }- return 0;-}--/*-----------------------------------------------------*/--int c_diag(DMAT(m),DVEC(y),DMAT(z)) {- int i,j;- for (j=0; j<yn; j++) {- yp[j] = AT(m,j,j);- }- for (i=0; i<mr; i++) {- for (j=0; j<mc; j++) {- AT(z,i,j) = i==j?yp[i]:0;- }- }- return 0;-}
@@ -1,44 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}---- $ ghc -O2 --make wrappers.hs functions.c--import Numeric.LinearAlgebra-import Data.Packed.Development-import Foreign(Ptr,unsafePerformIO)-import Foreign.C.Types(CInt)---------------------------------------------------------main = do- print $ myScale 3.0 (fromList [1..10])- print $ myDiag $ (3><5) [1..]---------------------------------------------------------foreign import ccall unsafe "c_scale_vector"- cScaleVector :: Double -- scale- -> CInt -> Ptr Double -- argument- -> CInt -> Ptr Double -- result- -> IO CInt -- exit code--myScale s x = unsafePerformIO $ do- y <- createVector (dim x)- app2 (cScaleVector s) vec x vec y "cScaleVector"- return y---------------------------------------------------------- forcing row order--foreign import ccall unsafe "c_diag"- cDiag :: CInt -> CInt -> Ptr Double -- argument- -> CInt -> Ptr Double -- result1- -> CInt -> CInt -> Ptr Double -- result2- -> IO CInt -- exit code--myDiag m = unsafePerformIO $ do- y <- createVector (min r c)- z <- createMatrix RowMajor r c- app3 cDiag mat (cmat m) vec y mat z "cDiag"- return (y,z)- where r = rows m- c = cols m
@@ -1,24 +0,0 @@-/* general element order */--typedef struct { double r, i; } doublecomplex;--#define DVEC(A) int A##n, double*A##p-#define CVEC(A) int A##n, doublecomplex*A##p-#define DMAT(A) int A##r, int A##c, double*A##p-#define CMAT(A) int A##r, int A##c, doublecomplex*A##p--#define AT(M,r,c) (M##p[(r)*sr+(c)*sc])--int c_diag(int ro, DMAT(m),DVEC(y),DMAT(z)) {- int i,j,sr,sc;- if (ro==1) { sr = mc; sc = 1;} else { sr = 1; sc = mr;}- for (j=0; j<yn; j++) {- yp[j] = AT(m,j,j);- }- for (i=0; i<mr; i++) {- for (j=0; j<mc; j++) {- AT(z,i,j) = i==j?yp[i]:0;- }- }- return 0;-}
@@ -1,32 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}---- $ ghc -O2 --make wrappers.hs functions.c--import Numeric.LinearAlgebra-import Data.Packed.Development-import Foreign(Ptr,unsafePerformIO)-import Foreign.C.Types(CInt)---------------------------------------------------------main = do- print $ myDiag $ (3><5) [1..]---------------------------------------------------------- arbitrary data order--foreign import ccall unsafe "c_diag"- cDiag :: CInt -- matrix order- -> CInt -> CInt -> Ptr Double -- argument- -> CInt -> Ptr Double -- result1- -> CInt -> CInt -> Ptr Double -- result2- -> IO CInt -- exit code--myDiag m = unsafePerformIO $ do- y <- createVector (min r c)- z <- createMatrix (orderOf m) r c- app3 (cDiag o) mat m vec y mat z "cDiag"- return (y,z)- where r = rows m- c = cols m- o = if orderOf m == RowMajor then 1 else 0
@@ -1,21 +0,0 @@-import Numeric.GSL-import Numeric.GSL.Special-import Numeric.LinearAlgebra-import Prelude hiding (catch)-import Control.Exception--test x = catch- (print x)- (\e -> putStrLn $ "captured ["++ show (e :: SomeException) ++"]")--main = do- setErrorHandlerOff-- test $ log_e (-1)- test $ 5 + (fst.exp_e) 1000- test $ bessel_zero_Jnu_e (-0.3) 2-- test $ (linearSolve 0 4 :: Matrix Double)- test $ (linearSolve 5 (sqrt (-1)) :: Matrix Double)-- putStrLn "Bye"
@@ -1,24 +0,0 @@--- nonlinear least-squares fitting--import Numeric.GSL.Fitting-import Numeric.LinearAlgebra--xs = map return [0 .. 39]-sigma = 0.1-ys = map return $ toList $ fromList (map (head . expModel [5,0.1,1]) xs)- + scalar sigma * (randomVector 0 Gaussian 40)--dat :: [([Double],([Double],Double))]--dat = zip xs (zip ys (repeat sigma))--expModel [a,lambda,b] [t] = [a * exp (-lambda * t) + b]--expModelDer [a,lambda,b] [t] = [[exp (-lambda * t), -t * a * exp(-lambda*t) , 1]]--(sol,path) = fitModelScaled 1E-4 1E-4 20 (expModel, expModelDer) dat [1,0,0]--main = do- print dat- print path- print sol
@@ -1,152 +0,0 @@--- some tests of the interface for pure--- computations with inplace updates--import Numeric.LinearAlgebra-import Data.Packed.ST-import Data.Packed.Convert--import Data.Array.Unboxed-import Data.Array.ST-import Control.Monad.ST-import Control.Monad--main = sequence_[- print test1,- print test2,- print test3,- print test4,- test5,- test6,- print test7,- test8,- test0]---- helper functions-vector l = fromList l :: Vector Double-norm v = pnorm PNorm2 v---- hmatrix vector and matrix-v = vector [1..10]-m = (5><10) [1..50::Double]---------------------------------------------------------------------------- vector creation by in-place updates on a copy of the argument-test1 = fun v--fun :: Element t => Vector t -> Vector t-fun x = runSTVector $ do- a <- thawVector x- mapM_ (flip (modifyVector a) (+57)) [0 .. dim x `div` 2 - 1]- return a---- another example: creation of an antidiagonal matrix from a list-test2 = antiDiag 5 8 [1..] :: Matrix Double--antiDiag :: (Element b) => Int -> Int -> [b] -> Matrix b-antiDiag r c l = runSTMatrix $ do- m <- newMatrix 0 r c- let d = min r c - 1- sequence_ $ zipWith (\i v -> writeMatrix m i (c-1-i) v) [0..d] l- return m---- using vector or matrix functions on mutable objects requires freezing:-test3 = g1 v--g1 x = runST $ do- a <- thawVector x- writeVector a (dim x -1) 0- b <- freezeVector a- return (norm b)---- another possibility:-test4 = g2 v--g2 x = runST $ do- a <- thawVector x- writeVector a (dim x -1) 0- t <- liftSTVector norm a- return t-------------------------------------------------------------------- haskell arrays-hv = listArray (0,9) [1..10::Double]-hm = listArray ((0,0),(4,9)) [1..50::Double]------ conversion from standard Haskell arrays-test5 = do- print $ norm (vectorFromArray hv)- print $ norm v- print $ rcond (matrixFromArray hm)- print $ rcond m----- conversion to mutable ST arrays-test6 = do- let y = clearColumn m 1- print y- print (matrixFromArray y)--clearColumn x c = runSTUArray $ do- a <- mArrayFromMatrix x- forM_ [0..rows x-1] $ \i->- writeArray a (i,c) (0::Double)- return a---- hmatrix functions applied to mutable ST arrays-test7 = unitary (listArray (1,4) [3,5,7,2] :: UArray Int Double)--unitary v = runSTUArray $ do- a <- thaw v- n <- norm `fmap` vectorFromMArray a- b <- mapArray (/n) a- return b------------------------------------------------------- (just to check that they are not affected)-test0 = do- print v- print m- --print hv- --print hm-----------------------------------------------------histogram n ds = runSTVector $ do- h <- newVector (0::Double) n -- number of bins- let inc k = modifyVector h k (+1)- mapM_ inc ds- return h---- check that newVector is really called with a fresh new array-histoCheck ds = runSTVector $ do- h <- newVector (0::Double) 15 -- > constant for this test- let inc k = modifyVector h k (+1)- mapM_ inc ds- return h--hc = fromList [1 .. 15::Double]---- check that thawVector creates a new array-histoCheck2 ds = runSTVector $ do- h <- thawVector hc- let inc k = modifyVector h k (+1)- mapM_ inc ds- return h--test8 = do- let ds = [0..14]- print $ histogram 15 ds- print $ histogram 15 ds- print $ histogram 15 ds- print $ histoCheck ds- print $ histoCheck ds- print $ histoCheck ds- print $ histoCheck2 ds- print $ histoCheck2 ds- print $ histoCheck2 ds- putStrLn "----------------------"
@@ -1,24 +0,0 @@--- Numerical integration-import Numeric.GSL--quad f a b = fst $ integrateQAGS 1E-9 100 f a b ---- A multiple integral can be easily defined using partial application-quad2 f y1 y2 g1 g2 = quad h y1 y2- where- h y = quad (flip f y) (g1 y) (g2 y)--volSphere r = 8 * quad2 (\x y -> sqrt (r*r-x*x-y*y)) - 0 r (const 0) (\x->sqrt (r*r-x*x))---- wikipedia example-exw = quad2 f 7 10 (const 11) (const 14)- where- f x y = x**2 + 4*y--main = do- print $ quad (\x -> 4/(x^2+1)) 0 1- print pi- print $ volSphere 2.5- print $ 4/3*pi*2.5**3- print $ exw
@@ -1,51 +0,0 @@-import Numeric.LinearAlgebra-import Graphics.Plot--vector l = fromList l :: Vector Double-matrix ls = fromLists ls :: Matrix Double-diagl = diag . vector--f = matrix [[1,0,0,0],- [1,1,0,0],- [0,0,1,0],- [0,0,0,1]]--h = matrix [[0,-1,1,0],- [0,-1,0,1]]--q = diagl [1,1,0,0]--r = diagl [2,2]--s0 = State (vector [0, 0, 10, -10]) (diagl [10,0, 100, 100])--data System = System {kF, kH, kQ, kR :: Matrix Double}-data State = State {sX :: Vector Double , sP :: Matrix Double}-type Measurement = Vector Double--kalman :: System -> State -> Measurement -> State-kalman (System f h q r) (State x p) z = State x' p' where- px = f <> x -- prediction- pq = f <> p <> trans f + q -- its covariance- y = z - h <> px -- residue- cy = h <> pq <> trans h + r -- its covariance- k = pq <> trans h <> inv cy -- kalman gain- x' = px + k <> y -- new state- p' = (ident (dim x) - k <> h) <> pq -- its covariance--sys = System f h q r--zs = [vector [15-k,-20-k] | k <- [0..]]--xs = s0 : zipWith (kalman sys) xs zs--des = map (sqrt.takeDiag.sP) xs--evolution n (xs,des) =- vector [1.. fromIntegral n]:(toColumns $ fromRows $ take n (zipWith (-) (map sX xs) des)) ++- (toColumns $ fromRows $ take n (zipWith (+) (map sX xs) des))--main = do- print $ fromRows $ take 10 (map sX xs)- mapM_ (print . sP) $ take 10 xs- mplot (evolution 20 (xs,des))
@@ -1,65 +0,0 @@--- The magic of Lie Algebra--import Numeric.LinearAlgebra--disp = putStrLn . dispf 5--rot1 :: Double -> Matrix Double-rot1 a = (3><3)- [ 1, 0, 0- , 0, c, s- , 0,-s, c ]- where c = cos a- s = sin a--g1,g2,g3 :: Matrix Double--g1 = (3><3) [0, 0,0- ,0, 0,1- ,0,-1,0]--rot2 :: Double -> Matrix Double-rot2 a = (3><3)- [ c, 0, s- , 0, 1, 0- ,-s, 0, c ]- where c = cos a- s = sin a--g2 = (3><3) [ 0,0,1- , 0,0,0- ,-1,0,0]--rot3 :: Double -> Matrix Double-rot3 a = (3><3)- [ c, s, 0- ,-s, c, 0- , 0, 0, 1 ]- where c = cos a- s = sin a--g3 = (3><3) [ 0,1,0- ,-1,0,0- , 0,0,0]--deg=pi/180---- commutator-infix 8 &-a & b = a <> b - b <> a--infixl 6 |+|-a |+| b = a + b + a&b /2 + (a-b)&(a & b) /12--main = do- let a = 45*deg- b = 50*deg- c = -30*deg- exact = rot3 a <> rot1 b <> rot2 c- lie = scalar a * g3 |+| scalar b * g1 |+| scalar c * g2- putStrLn "position in the tangent space:"- disp lie- putStrLn "exponential map back to the group (2 terms):"- disp (expm lie)- putStrLn "exact position:"- disp exact
@@ -1,50 +0,0 @@--- the multidimensional minimization example in the GSL manual-import Numeric.GSL-import Numeric.LinearAlgebra-import Graphics.Plot-import Text.Printf(printf)---- the function to be minimized-f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30---- exact gradient-df [x,y] = [20*(x-1), 40*(y-2)]---- a minimization algorithm which does not require the gradient-minimizeS f xi = minimize NMSimplex2 1E-2 100 (replicate (length xi) 1) f xi---- Numerical estimation of the gradient-gradient f v = [partialDerivative k f v | k <- [0 .. length v -1]]--partialDerivative n f v = fst (derivCentral 0.01 g (v!!n)) where- g x = f (concat [a,x:b])- (a,_:b) = splitAt n v--disp = putStrLn . format " " (printf "%.3f")--allMethods :: (Enum a, Bounded a) => [a]-allMethods = [minBound .. maxBound]--test method = do- print method- let (s,p) = minimize method 1E-2 30 [1,1] f [5,7]- print s- disp p--testD method = do- print method- let (s,p) = minimizeD method 1E-3 30 1E-2 1E-4 f df [5,7]- print s- disp p--testD' method = do- putStrLn $ show method ++ " with estimated gradient"- let (s,p) = minimizeD method 1E-3 30 1E-2 1E-4 f (gradient f) [5,7]- print s- disp p--main = do- mapM_ test [NMSimplex, NMSimplex2]- mapM_ testD allMethods- testD' ConjugateFR- mplot $ drop 3 . toColumns . snd $ minimizeS f [5,7]
@@ -1,118 +0,0 @@--- monadic computations--- (contributed by Vivian McPhail)--import Numeric.LinearAlgebra-import Control.Monad.State.Strict-import Control.Monad.Maybe-import Foreign.Storable(Storable)-import System.Random(randomIO)------------------------------------------------- an instance of MonadIO, a monad transformer-type VectorMonadT = StateT Int IO--test1 :: Vector Int -> IO (Vector Int)-test1 = mapVectorM $ \x -> do- putStr $ (show x) ++ " "- return (x + 1)---- we can have an arbitrary monad AND do IO-addInitialM :: Vector Int -> VectorMonadT ()-addInitialM = mapVectorM_ $ \x -> do- i <- get- liftIO $ putStr $ (show $ x + i) ++ " "- put $ x + i---- sum the values of the even indiced elements-sumEvens :: Vector Int -> Int-sumEvens = foldVectorWithIndex (\x a b -> if x `mod` 2 == 0 then a + b else b) 0---- sum and print running total of evens-sumEvensAndPrint :: Vector Int -> VectorMonadT ()-sumEvensAndPrint = mapVectorWithIndexM_ $ \ i x -> do- when (i `mod` 2 == 0) $ do- v <- get- put $ v + x- v' <- get- liftIO $ putStr $ (show v') ++ " "---indexPlusSum :: Vector Int -> VectorMonadT ()-indexPlusSum v' = do- let f i x = do- s <- get- let inc = x+s- liftIO $ putStr $ show (i,inc) ++ " "- put inc- return inc- v <- mapVectorWithIndexM f v'- liftIO $ do- putStrLn ""- putStrLn $ show v------------------------------------------------- short circuit-monoStep :: Double -> MaybeT (State Double) ()-monoStep d = do- dp <- get- when (d < dp) (fail "negative difference")- put d-{-# INLINE monoStep #-}--isMonotoneIncreasing :: Vector Double -> Bool-isMonotoneIncreasing v =- let res = evalState (runMaybeT $ (mapVectorM_ monoStep v)) (v @> 0)- in case res of- Nothing -> False- Just _ -> True-------------------------------------------------- | apply a test to successive elements of a vector, evaluates to true iff test passes for all pairs-successive_ :: Storable a => (a -> a -> Bool) -> Vector a -> Bool-successive_ t v = maybe False (\_ -> True) $ evalState (runMaybeT (mapVectorM_ step (subVector 1 (dim v - 1) v))) (v @> 0)- where step e = do- ep <- lift $ get- if t e ep- then lift $ put e- else (fail "successive_ test failed")---- | operate on successive elements of a vector and return the resulting vector, whose length 1 less than that of the input-successive :: (Storable a, Storable b) => (a -> a -> b) -> Vector a -> Vector b-successive f v = evalState (mapVectorM step (subVector 1 (dim v - 1) v)) (v @> 0)- where step e = do- ep <- get- put e- return $ f ep e-----------------------------------------------v :: Vector Int-v = 10 |> [0..]--w = fromList ([1..10]++[10,9..1]) :: Vector Double---main = do- v' <- test1 v- putStrLn ""- putStrLn $ show v'- evalStateT (addInitialM v) 0- putStrLn ""- putStrLn $ show (sumEvens v)- evalStateT (sumEvensAndPrint v) 0- putStrLn ""- evalStateT (indexPlusSum v) 0- putStrLn "-----------------------"- mapVectorM_ print v- print =<< (mapVectorM (const randomIO) v :: IO (Vector Double))- print =<< (mapVectorM (\a -> fmap (+a) randomIO) (5|>[0,100..1000]) :: IO (Vector Double))- putStrLn "-----------------------"- print $ isMonotoneIncreasing w- print $ isMonotoneIncreasing (subVector 0 7 w)- print $ successive_ (>) v- print $ successive_ (>) w- print $ successive (+) v
@@ -1,100 +0,0 @@-{-# LANGUAGE UnicodeSyntax- , MultiParamTypeClasses- , FunctionalDependencies- , FlexibleInstances- , FlexibleContexts--- , OverlappingInstances- , UndecidableInstances #-}--import Numeric.LinearAlgebra--class Scaling a b c | a b -> c where- -- ^ 0x22C5 8901 DOT OPERATOR, scaling- infixl 7 ⋅- (⋅) :: a -> b -> c--class Contraction a b c | a b -> c where- -- ^ 0x00D7 215 MULTIPLICATION SIGN ×, contraction- infixl 7 ×- (×) :: a -> b -> c--class Outer a b c | a b -> c where- -- ^ 0x2297 8855 CIRCLED TIMES ⊗, outer product (not associative)- infixl 7 ⊗- (⊗) :: a -> b -> c------------instance (Num t) => Scaling t t t where- (⋅) = (*)--instance Container Vector t => Scaling t (Vector t) (Vector t) where- (⋅) = scale--instance Container Vector t => Scaling (Vector t) t (Vector t) where- (⋅) = flip scale--instance Container Vector t => Scaling t (Matrix t) (Matrix t) where- (⋅) = scale--instance Container Vector t => Scaling (Matrix t) t (Matrix t) where- (⋅) = flip scale---instance Product t => Contraction (Vector t) (Vector t) t where- (×) = dot--instance Product t => Contraction (Matrix t) (Vector t) (Vector t) where- (×) = mXv--instance Product t => Contraction (Vector t) (Matrix t) (Vector t) where- (×) = vXm--instance Product t => Contraction (Matrix t) (Matrix t) (Matrix t) where- (×) = mXm-----instance Scaling a b c => Contraction a b c where--- (×) = (⋅)---------instance Product t => Outer (Vector t) (Vector t) (Matrix t) where- (⊗) = outer--instance Product t => Outer (Vector t) (Matrix t) (Matrix t) where- v ⊗ m = kronecker (asColumn v) m--instance Product t => Outer (Matrix t) (Vector t) (Matrix t) where- m ⊗ v = kronecker m (asRow v)--instance Product t => Outer (Matrix t) (Matrix t) (Matrix t) where- (⊗) = kronecker----------v = 3 |> [1..] :: Vector Double--m = (3 >< 3) [1..] :: Matrix Double--s = 3 :: Double--a = s ⋅ v × m × m × v ⋅ s--b = (v ⊗ m) ⊗ (v ⊗ m)--c = v ⊗ m ⊗ v ⊗ m--d = s ⋅ (3 |> [10,20..] :: Vector Double)--main = do- print $ scale s v <> m <.> v - print $ scale s v <.> (m <> v)- print $ s * (v <> m <.> v)- print $ s ⋅ v × m × v- print a- print (b == c)- print d-
@@ -1,50 +0,0 @@-{-# LANGUAGE ViewPatterns #-}-import Numeric.GSL.ODE-import Numeric.LinearAlgebra-import Graphics.Plot-import Debug.Trace(trace)-debug x = trace (show x) x--vanderpol mu = do- let xdot mu t [x,v] = [v, -x + mu * v * (1-x^2)]- ts = linspace 1000 (0,50)- sol = toColumns $ odeSolve (xdot mu) [1,0] ts- mplot (ts : sol)- mplot sol---harmonic w d = do- let xdot w d t [x,v] = [v, a*x + b*v] where a = -w^2; b = -2*d*w- ts = linspace 100 (0,20)- sol = odeSolve (xdot w d) [1,0] ts- mplot (ts : toColumns sol)---kepler v a = mplot (take 2 $ toColumns sol) where- xdot t [x,y,vx,vy] = [vx,vy,x*k,y*k]- where g=1- k=(-g)*(x*x+y*y)**(-1.5)- ts = linspace 100 (0,30)- sol = odeSolve xdot [4, 0, v * cos (a*degree), v * sin (a*degree)] ts- degree = pi/180---main = do- vanderpol 2- harmonic 1 0- harmonic 1 0.1- kepler 0.3 60- kepler 0.4 70- vanderpol' 2---- example of odeSolveV with jacobian-vanderpol' mu = do- let xdot mu t (toList->[x,v]) = fromList [v, -x + mu * v * (1-x^2)]- jac t (toList->[x,v]) = (2><2) [ 0 , 1- , -1-2*x*v*mu, mu*(1-x**2) ]- ts = linspace 1000 (0,50)- hi = (ts@>1 - ts@>0)/100- sol = toColumns $ odeSolveV (MSBDF jac) hi 1E-8 1E-8 (xdot mu) (fromList [1,0]) ts- mplot sol--
@@ -1,28 +0,0 @@--- $ ghc --make -O -rtsopts -threaded parallel.hs--- $ ./parallel 3000 +RTS -N4 -s -A200M--import System.Environment(getArgs)-import Numeric.LinearAlgebra-import Control.Parallel.Strategies-import System.Time--inParallel = parMap rwhnf id---- matrix product decomposed into p parallel subtasks-parMul p x y = fromBlocks [ inParallel ( map (x <>) ys ) ]- where [ys] = toBlocksEvery (rows y) (cols y `div` p) y--main = do- n <- (read . head) `fmap` getArgs- let m = ident n :: Matrix Double- time $ print $ maxElement $ takeDiag $ m <> m- time $ print $ maxElement $ takeDiag $ parMul 2 m m- time $ print $ maxElement $ takeDiag $ parMul 4 m m- time $ print $ maxElement $ takeDiag $ parMul 8 m m--time act = do- t0 <- getClockTime- act- t1 <- getClockTime- print $ tdSec $ normalizeTimeDiff $ diffClockTimes t1 t0-
@@ -1,46 +0,0 @@--- Principal component analysis--import Numeric.LinearAlgebra-import System.Directory(doesFileExist)-import System.Process(system)-import Control.Monad(when)--type Vec = Vector Double-type Mat = Matrix Double----- Vector with the mean value of the columns of a matrix-mean a = constant (recip . fromIntegral . rows $ a) (rows a) <> a---- covariance matrix of a list of observations stored as rows-cov x = (trans xc <> xc) / fromIntegral (rows x - 1)- where xc = x - asRow (mean x)----- creates the compression and decompression functions from the desired number of components-pca :: Int -> Mat -> (Vec -> Vec , Vec -> Vec)-pca n dataSet = (encode,decode)- where- encode x = vp <> (x - m)- decode x = x <> vp + m- m = mean dataSet- c = cov dataSet- (_,v) = eigSH' c- vp = takeRows n (trans v)--norm = pnorm PNorm2--main = do- ok <- doesFileExist ("mnist.txt")- when (not ok) $ do- putStrLn "\nTrying to download test datafile..."- system("wget -nv http://dis.um.es/~alberto/material/sp/mnist.txt.gz")- system("gunzip mnist.txt.gz")- return ()- m <- loadMatrix "mnist.txt" -- fromFile "mnist.txt" (5000,785)- let xs = takeColumns (cols m -1) m -- the last column is the digit type (class label)- let x = toRows xs !! 4 -- an arbitrary test Vec- let (pe,pd) = pca 10 xs- let y = pe x- print y -- compressed version- print $ norm (x - pd y) / norm x --reconstruction quality
@@ -1,65 +0,0 @@--- Improved PCA, including illustrative graphics--import Numeric.LinearAlgebra-import Graphics.Plot-import System.Directory(doesFileExist)-import System.Process(system)-import Control.Monad(when)--type Vec = Vector Double-type Mat = Matrix Double---- Vector with the mean value of the columns of a matrix-mean a = constant (recip . fromIntegral . rows $ a) (rows a) <> a---- covariance matrix of a list of observations stored as rows-cov x = (trans xc <> xc) / fromIntegral (rows x - 1)- where xc = x - asRow (mean x)---type Stat = (Vec, [Double], Mat)--- 1st and 2nd order statistics of a dataset (mean, eigenvalues and eigenvectors of cov)-stat :: Mat -> Stat-stat x = (m, toList s, trans v) where- m = mean x- (s,v) = eigSH' (cov x)---- creates the compression and decompression functions from the desired reconstruction--- quality and the statistics of a data set-pca :: Double -> Stat -> (Vec -> Vec , Vec -> Vec)-pca prec (m,s,v) = (encode,decode) - where - encode x = vp <> (x - m)- decode x = x <> vp + m- vp = takeRows n v- n = 1 + (length $ fst $ span (< (prec'*sum s)) $ cumSum s)- cumSum = tail . scanl (+) 0.0- prec' = if prec <=0.0 || prec >= 1.0- then error "the precision in pca must be 0<prec<1"- else prec--shdigit :: Vec -> IO ()-shdigit v = imshow (reshape 28 (-v))---- shows the effect of a given reconstruction quality on a test vector-test :: Stat -> Double -> Vec -> IO ()-test st prec x = do- let (pe,pd) = pca prec st- let y = pe x- print $ dim y- shdigit (pd y)--main = do- ok <- doesFileExist ("mnist.txt")- when (not ok) $ do- putStrLn "\nTrying to download test datafile..."- system("wget -nv http://dis.um.es/~alberto/material/sp/mnist.txt.gz")- system("gunzip mnist.txt.gz")- return ()- m <- loadMatrix "mnist.txt"- let xs = takeColumns (cols m -1) m- let x = toRows xs !! 4 -- an arbitrary test vector- shdigit x- let st = stat xs- test st 0.90 x- test st 0.50 x
@@ -1,20 +0,0 @@-import Numeric.LinearAlgebra-import Graphics.Plot-import Text.Printf(printf)--expand :: Int -> Vector Double -> Matrix Double-expand n x = fromColumns $ map (x^) [0 .. n]--polynomialModel :: Vector Double -> Vector Double -> Int- -> (Vector Double -> Vector Double)-polynomialModel x y n = f where- f z = expand n z <> ws- ws = expand n x <\> y--main = do- [x,y] <- (toColumns . readMatrix) `fmap` readFile "data.txt"- let pol = polynomialModel x y- let view = [x, y, pol 1 x, pol 2 x, pol 3 x]- putStrLn $ " x y p 1 p 2 p 3"- putStrLn $ format " " (printf "%.2f") $ fromColumns view- mplot view
@@ -1,20 +0,0 @@-import Numeric.LinearAlgebra-import Graphics.Plot-import Numeric.GSL.Special(erf_Z, erf)--sombrero n = f x y where - (x,y) = meshdom range range- range = linspace n (-2,2)- f x y = exp (-r2) * cos (2*r2) where - r2 = x*x+y*y--f x = sin x + 0.5 * sin (5*x)--gaussianPDF = erf_Z-cumdist x = 0.5 * (1+ erf (x/sqrt 2))--main = do- let x = linspace 1000 (-4,4)- mplot [f x]- mplot [x, mapVector cumdist x, mapVector gaussianPDF x]- mesh (sombrero 40)
@@ -1,31 +0,0 @@--- root finding examples-import Numeric.GSL-import Numeric.LinearAlgebra-import Text.Printf(printf)--rosenbrock a b [x,y] = [ a*(1-x), b*(y-x^2) ]--test method = do- print method- let (s,p) = root method 1E-7 30 (rosenbrock 1 10) [-10,-5]- print s -- solution- disp p -- evolution of the algorithm--jacobian a b [x,y] = [ [-a , 0]- , [-2*b*x, b] ]--testJ method = do- print method- let (s,p) = rootJ method 1E-7 30 (rosenbrock 1 10) (jacobian 1 10) [-10,-5]- print s- disp p--disp = putStrLn . format " " (printf "%.3f")--main = do- test Hybrids- test Hybrid- test DNewton- test Broyden-- mapM_ testJ [HybridsJ .. GNewton]
@@ -1,31 +0,0 @@--- conversion to/from Data.Vector.Storable--- from Roman Leshchinskiy "vector" package------ In the future Data.Packed.Vector will be replaced by Data.Vector.Storable-----------------------------------------------import Numeric.LinearAlgebra as H-import Data.Packed.Development(unsafeFromForeignPtr, unsafeToForeignPtr)-import Foreign.Storable-import qualified Data.Vector.Storable as V--fromVector :: Storable t => V.Vector t -> H.Vector t-fromVector v = unsafeFromForeignPtr p i n where- (p,i,n) = V.unsafeToForeignPtr v--toVector :: Storable t => H.Vector t -> V.Vector t-toVector v = V.unsafeFromForeignPtr p i n where- (p,i,n) = unsafeToForeignPtr v-----------------------------------------------v = V.slice 5 10 (V.fromList [1 .. 10::Double] V.++ V.replicate 10 7)--w = subVector 2 3 (linspace 5 (0,1)) :: Vector Double--main = do- print v- print $ fromVector v- print w- print $ toVector w
@@ -1,207 +0,0 @@-Name: hmatrix-Version: 0.15.0.1-License: GPL-License-file: LICENSE-Author: Alberto Ruiz-Maintainer: Alberto Ruiz <aruiz@um.es>-Stability: provisional-Homepage: https://github.com/albertoruiz/hmatrix-Synopsis: Linear algebra and numerical computation-Description: Purely functional interface to basic linear algebra- and other numerical computations, internally implemented using- GSL, BLAS and LAPACK.- .- The Linear Algebra API is organized as follows:- .- - "Data.Packed": structure manipulation- .- - "Numeric.Container": simple numeric functions- .- - "Numeric.LinearAlgebra.Algorithms": matrix computations- .- - "Numeric.LinearAlgebra": everything + instances of standard Haskell numeric classes-Category: Math-tested-with: GHC ==7.6--cabal-version: >=1.8--build-type: Custom--extra-source-files: Config.hs THANKS.md INSTALL.md CHANGES.md--extra-source-files: examples/deriv.hs- examples/integrate.hs- examples/minimize.hs- examples/root.hs- examples/ode.hs- examples/pca1.hs- examples/pca2.hs- examples/pinv.hs- examples/data.txt- examples/lie.hs- examples/kalman.hs- examples/parallel.hs- examples/plot.hs- examples/inplace.hs- examples/error.hs- examples/fitting.hs- examples/devel/ej1/wrappers.hs- examples/devel/ej1/functions.c- examples/devel/ej2/wrappers.hs- examples/devel/ej2/functions.c- examples/vector.hs- examples/monadic.hs- examples/bool.hs- examples/multiply.hs--extra-source-files: lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.h,- lib/Numeric/GSL/gsl-ode.c--flag dd- description: svd = zgesdd- default: True--flag mkl- description: Link with Intel's MKL optimized libraries.- default: False--flag unsafe- description: Compile the library with bound checking disabled.- default: False--flag finit- description: Force FPU initialization in foreing calls- default: False--flag debugfpu- description: Check FPU stack- default: False--flag debugnan- description: Check NaN- default: False--library-- Build-Depends: base >= 4 && < 5,- array,- storable-complex,- process, random,- vector >= 0.8,- binary,- deepseq-- Extensions: ForeignFunctionInterface,- CPP-- hs-source-dirs: lib- Exposed-modules: Data.Packed,- Data.Packed.Vector,- Data.Packed.Matrix,- Data.Packed.Foreign,- Numeric.GSL.Differentiation,- Numeric.GSL.Integration,- Numeric.GSL.Fourier,- Numeric.GSL.Polynomials,- Numeric.GSL.Minimization,- Numeric.GSL.Root,- Numeric.GSL.Fitting,- Numeric.GSL.ODE,- Numeric.GSL,- Numeric.Container,- Numeric.LinearAlgebra,- Numeric.LinearAlgebra.LAPACK,- Numeric.LinearAlgebra.Algorithms,- Numeric.LinearAlgebra.Util,- Graphics.Plot,- Data.Packed.ST,- Data.Packed.Development- other-modules: Data.Packed.Internal,- Data.Packed.Internal.Common,- Data.Packed.Internal.Signatures,- Data.Packed.Internal.Vector,- Data.Packed.Internal.Matrix,- Data.Packed.Random,- Numeric.GSL.Internal,- Numeric.GSL.Vector,- Numeric.Conversion,- Numeric.ContainerBoot,- Numeric.IO,- Numeric.Chain,- Numeric.Vector,- Numeric.Matrix,- Numeric.LinearAlgebra.Util.Convolution-- C-sources: lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c,- lib/Numeric/GSL/gsl-aux.c-- cpp-options: -DBINARY-- -- ghc-prof-options: -auto-- ghc-options: -Wall -fno-warn-missing-signatures- -fno-warn-orphans- -fno-warn-unused-binds-- if flag(unsafe)- cpp-options: -DUNSAFE-- if !flag(dd)- cpp-options: -DNOZGESDD-- if impl(ghc < 6.10.2)- cpp-options: -DFINIT-- if impl(ghc == 7.0.1)- cpp-options: -DFINIT-- if impl(ghc == 7.0.2)- cpp-options: -DFINIT-- if flag(finit)- cpp-options: -DFINIT-- if flag(debugfpu)- cc-options: -DFPUDEBUG-- if flag(debugnan)- cc-options: -DNANDEBUG-- if impl(ghc == 7.0.1)- cpp-options: -DNONORMVTEST-- if flag(mkl)- if arch(x86_64)- extra-libraries: gsl mkl_lapack mkl_intel_lp64 mkl_sequential mkl_core- else- extra-libraries: gsl mkl_lapack mkl_intel mkl_sequential mkl_core-- if os(OSX)- extra-lib-dirs: /opt/local/lib/- include-dirs: /opt/local/include/- extra-lib-dirs: /usr/local/lib/- include-dirs: /usr/local/include/- extra-libraries: gsl- if arch(i386)- cc-options: -arch i386- frameworks: Accelerate-- if os(windows)- extra-libraries: gsl-0 blas lapack-- if os(linux)- if arch(x86_64)- cc-options: -fPIC---- The extra-libraries required for GSL and LAPACK--- should now be automatically detected by configure(.hs)-- extra-libraries:- extra-lib-dirs:--source-repository head- type: git- location: https://github.com/albertoruiz/hmatrix---- The tests are in package hmatrix-tests-
@@ -1,28 +0,0 @@-------------------------------------------------------------------------------{- |-Module : Data.Packed-Copyright : (c) Alberto Ruiz 2006-2010-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Types for dense 'Vector' and 'Matrix' of 'Storable' elements.---}--------------------------------------------------------------------------------module Data.Packed (- module Data.Packed.Vector,- module Data.Packed.Matrix,--- module Numeric.Conversion,--- module Data.Packed.Random,--- module Data.Complex-) where--import Data.Packed.Vector-import Data.Packed.Matrix---import Data.Packed.Random---import Data.Complex---import Numeric.Conversion
@@ -1,30 +0,0 @@---------------------------------------------------------------------------------- |--- Module : Data.Packed.Development--- Copyright : (c) Alberto Ruiz 2009--- License : GPL------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ The library can be easily extended with additional foreign functions--- using the tools in this module. Illustrative usage examples can be found--- in the @examples\/devel@ folder included in the package.-----------------------------------------------------------------------------------module Data.Packed.Development (- createVector, createMatrix,- vec, mat,- app1, app2, app3, app4,- app5, app6, app7, app8, app9, app10,- MatrixOrder(..), orderOf, cmat, fmat,- unsafeFromForeignPtr,- unsafeToForeignPtr,- check, (//),- at', atM'-) where--import Data.Packed.Internal
@@ -1,99 +0,0 @@-{-# LANGUAGE MagicHash, UnboxedTuples #-}--- | FFI and hmatrix helpers.------ Sample usage, to upload a perspective matrix to a shader.------ @ glUniformMatrix4fv 0 1 (fromIntegral gl_TRUE) \`appMatrix\` perspective 0.01 100 (pi\/2) (4\/3) --- @----module Data.Packed.Foreign - ( app- , appVector, appVectorLen- , appMatrix, appMatrixLen, appMatrixRaw, appMatrixRawLen- , unsafeMatrixToVector, unsafeMatrixToForeignPtr- ) where-import Data.Packed.Internal-import qualified Data.Vector.Storable as S-import Foreign (Ptr, ForeignPtr, Storable)-import Foreign.C.Types (CInt)-import GHC.Base (IO(..), realWorld#)--{-# INLINE unsafeInlinePerformIO #-}--- | If we use unsafePerformIO, it may not get inlined, so in a function that returns IO (which are all safe uses of app* in this module), there would be--- unecessary calls to unsafePerformIO or its internals.-unsafeInlinePerformIO :: IO a -> a-unsafeInlinePerformIO (IO f) = case f realWorld# of- (# _, x #) -> x--{-# INLINE app #-}--- | Only useful since it is left associated with a precedence of 1, unlike 'Prelude.$', which is right associative.--- e.g.------ @--- someFunction--- \`appMatrixLen\` m--- \`appVectorLen\` v--- \`app\` other--- \`app\` arguments--- \`app\` go here--- @------ One could also write:------ @--- (someFunction --- \`appMatrixLen\` m--- \`appVectorLen\` v) --- other --- arguments --- (go here)--- @----app :: (a -> b) -> a -> b-app f = f--{-# INLINE appVector #-}-appVector :: Storable a => (Ptr a -> b) -> Vector a -> b-appVector f x = unsafeInlinePerformIO (S.unsafeWith x (return . f))--{-# INLINE appVectorLen #-}-appVectorLen :: Storable a => (CInt -> Ptr a -> b) -> Vector a -> b-appVectorLen f x = unsafeInlinePerformIO (S.unsafeWith x (return . f (fromIntegral (S.length x))))--{-# INLINE appMatrix #-}-appMatrix :: Element a => (Ptr a -> b) -> Matrix a -> b-appMatrix f x = unsafeInlinePerformIO (S.unsafeWith (flatten x) (return . f))--{-# INLINE appMatrixLen #-}-appMatrixLen :: Element a => (CInt -> CInt -> Ptr a -> b) -> Matrix a -> b-appMatrixLen f x = unsafeInlinePerformIO (S.unsafeWith (flatten x) (return . f r c))- where- r = fromIntegral (rows x)- c = fromIntegral (cols x)--{-# INLINE appMatrixRaw #-}-appMatrixRaw :: Storable a => (Ptr a -> b) -> Matrix a -> b-appMatrixRaw f x = unsafeInlinePerformIO (S.unsafeWith (xdat x) (return . f))--{-# INLINE appMatrixRawLen #-}-appMatrixRawLen :: Element a => (CInt -> CInt -> Ptr a -> b) -> Matrix a -> b-appMatrixRawLen f x = unsafeInlinePerformIO (S.unsafeWith (xdat x) (return . f r c))- where- r = fromIntegral (rows x)- c = fromIntegral (cols x)--infixl 1 `app`-infixl 1 `appVector`-infixl 1 `appMatrix`-infixl 1 `appMatrixRaw`--{-# INLINE unsafeMatrixToVector #-}--- | This will disregard the order of the matrix, and simply return it as-is. --- If the order of the matrix is RowMajor, this function is identical to 'flatten'.-unsafeMatrixToVector :: Matrix a -> Vector a-unsafeMatrixToVector = xdat--{-# INLINE unsafeMatrixToForeignPtr #-}-unsafeMatrixToForeignPtr :: Storable a => Matrix a -> (ForeignPtr a, Int)-unsafeMatrixToForeignPtr m = S.unsafeToForeignPtr0 (xdat m)-
@@ -1,26 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Data.Packed.Internal--- Copyright : (c) Alberto Ruiz 2007--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Reexports all internal modules------------------------------------------------------------------------------------ #hide--module Data.Packed.Internal (- module Data.Packed.Internal.Common,- module Data.Packed.Internal.Signatures,- module Data.Packed.Internal.Vector,- module Data.Packed.Internal.Matrix,-) where--import Data.Packed.Internal.Common-import Data.Packed.Internal.Signatures-import Data.Packed.Internal.Vector-import Data.Packed.Internal.Matrix
@@ -1,184 +0,0 @@-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module : Data.Packed.Internal.Common--- Copyright : (c) Alberto Ruiz 2007--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable (uses FFI)------ Development utilities.------------------------------------------------------------------------------------ #hide--module Data.Packed.Internal.Common(- Adapt,- app1, app2, app3, app4,- app5, app6, app7, app8, app9, app10,- (//), check, mbCatch,- splitEvery, common, compatdim,- fi,- table-) where--import Foreign-import Control.Monad(when)-import Foreign.C.String(peekCString)-import Foreign.C.Types-import Foreign.Storable.Complex()-import Data.List(transpose,intersperse)-import Control.Exception as E--{-@ safeTake :: n:Nat -> {v:[a] | (len v) >= n} -> {v:[a] | (len v) = n})@-}-safeTake 0 _ = []-safeTake n (x:xs) = x : safeTake (n-1) xs--{-@ safeTake :: n:Nat -> xs:{v:[a] | (len v) >= n} -> {v:[a] | (len v) = (len xs) - n} @-}-safeDrop 0 xs = xs-safeDrop n (_:xs) = safeDrop (n-1) xs--{-@ splitEvery :: n:Nat -> {v:[a] | ((length v) mod n) = 0} -> [{v:[a] | (len v) = n}] @-}--- | @splitEvery 3 [1..9] == [[1,2,3],[4,5,6],[7,8,9]]@-splitEvery :: Int -> [a] -> [[a]]-splitEvery _ [] = []-splitEvery k l = safeTake k l : splitEvery k (safeDrop k l)---- | obtains the common value of a property of a list-common :: (Eq a) => (b -> a) -> [b] -> Maybe a-common f = commonval . map f where- commonval :: (Eq a) => [a] -> Maybe a- commonval [] = Nothing- commonval [a] = Just a- commonval (a:b:xs) = if a==b then commonval (b:xs) else Nothing--{-@ predicate Max V X Y = V = if (X >= Y) then X else Y @-}--{-@ measure maxInts :: [Int] -> Int - maxInts [] = {v | v = (0 - 1)} - maxInts (x:xs) = {v | (Max v x (maxInts xs))}- @-}--{-@ compatdim :: dims:[{v:Nat | (v = 1 || v = (maxInts dims))}] -> Maybe {v:Nat | (maxInt dims)} @-}--- | common value with \"adaptable\" 1-compatdim :: [Int] -> Maybe Int-compatdim [] = Nothing-compatdim [a] = Just a-compatdim (a:b:xs) = if a==b || a==1 || b==1 then compatdim (max a b:xs) else Nothing---- | Formatting tool-table :: String -> [[String]] -> String-table sep as = unlines . map unwords' $ transpose mtp where - mt = transpose as- longs = map (maximum . map length) mt- mtp = zipWith (\a b -> map (pad a) b) longs mt- pad n str = replicate (n - length str) ' ' ++ str- unwords' = concat . intersperse sep---- | postfix function application (@flip ($)@)-(//) :: x -> (x -> y) -> y-infixl 0 //-(//) = flip ($)---- | specialized fromIntegral-fi :: Int -> CInt-fi = fromIntegral---- hmm..-ww2 w1 o1 w2 o2 f = w1 o1 $ w2 o2 . f-ww3 w1 o1 w2 o2 w3 o3 f = w1 o1 $ ww2 w2 o2 w3 o3 . f-ww4 w1 o1 w2 o2 w3 o3 w4 o4 f = w1 o1 $ ww3 w2 o2 w3 o3 w4 o4 . f-ww5 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 f = w1 o1 $ ww4 w2 o2 w3 o3 w4 o4 w5 o5 . f-ww6 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 f = w1 o1 $ ww5 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 . f-ww7 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 f = w1 o1 $ ww6 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 . f-ww8 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 f = w1 o1 $ ww7 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 . f-ww9 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 f = w1 o1 $ ww8 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 . f-ww10 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 w10 o10 f = w1 o1 $ ww9 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 w10 o10 . f--type Adapt f t r = t -> ((f -> r) -> IO()) -> IO()--type Adapt1 f t1 = Adapt f t1 (IO CInt) -> t1 -> String -> IO()-type Adapt2 f t1 r1 t2 = Adapt f t1 r1 -> t1 -> Adapt1 r1 t2-type Adapt3 f t1 r1 t2 r2 t3 = Adapt f t1 r1 -> t1 -> Adapt2 r1 t2 r2 t3-type Adapt4 f t1 r1 t2 r2 t3 r3 t4 = Adapt f t1 r1 -> t1 -> Adapt3 r1 t2 r2 t3 r3 t4-type Adapt5 f t1 r1 t2 r2 t3 r3 t4 r4 t5 = Adapt f t1 r1 -> t1 -> Adapt4 r1 t2 r2 t3 r3 t4 r4 t5-type Adapt6 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 = Adapt f t1 r1 -> t1 -> Adapt5 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6-type Adapt7 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 = Adapt f t1 r1 -> t1 -> Adapt6 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7-type Adapt8 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 = Adapt f t1 r1 -> t1 -> Adapt7 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8-type Adapt9 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 r8 t9 = Adapt f t1 r1 -> t1 -> Adapt8 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 r8 t9-type Adapt10 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 r8 t9 r9 t10 = Adapt f t1 r1 -> t1 -> Adapt9 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 r8 t9 r9 t10--app1 :: f -> Adapt1 f t1-app2 :: f -> Adapt2 f t1 r1 t2-app3 :: f -> Adapt3 f t1 r1 t2 r2 t3-app4 :: f -> Adapt4 f t1 r1 t2 r2 t3 r3 t4-app5 :: f -> Adapt5 f t1 r1 t2 r2 t3 r3 t4 r4 t5-app6 :: f -> Adapt6 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6-app7 :: f -> Adapt7 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7-app8 :: f -> Adapt8 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8-app9 :: f -> Adapt9 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 r8 t9-app10 :: f -> Adapt10 f t1 r1 t2 r2 t3 r3 t4 r4 t5 r5 t6 r6 t7 r7 t8 r8 t9 r9 t10--app1 f w1 o1 s = w1 o1 $ \a1 -> f // a1 // check s-app2 f w1 o1 w2 o2 s = ww2 w1 o1 w2 o2 $ \a1 a2 -> f // a1 // a2 // check s-app3 f w1 o1 w2 o2 w3 o3 s = ww3 w1 o1 w2 o2 w3 o3 $- \a1 a2 a3 -> f // a1 // a2 // a3 // check s-app4 f w1 o1 w2 o2 w3 o3 w4 o4 s = ww4 w1 o1 w2 o2 w3 o3 w4 o4 $- \a1 a2 a3 a4 -> f // a1 // a2 // a3 // a4 // check s-app5 f w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 s = ww5 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 $- \a1 a2 a3 a4 a5 -> f // a1 // a2 // a3 // a4 // a5 // check s-app6 f w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 s = ww6 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 $- \a1 a2 a3 a4 a5 a6 -> f // a1 // a2 // a3 // a4 // a5 // a6 // check s-app7 f w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 s = ww7 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 $- \a1 a2 a3 a4 a5 a6 a7 -> f // a1 // a2 // a3 // a4 // a5 // a6 // a7 // check s-app8 f w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 s = ww8 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 $- \a1 a2 a3 a4 a5 a6 a7 a8 -> f // a1 // a2 // a3 // a4 // a5 // a6 // a7 // a8 // check s-app9 f w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 s = ww9 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 $- \a1 a2 a3 a4 a5 a6 a7 a8 a9 -> f // a1 // a2 // a3 // a4 // a5 // a6 // a7 // a8 // a9 // check s-app10 f w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 w10 o10 s = ww10 w1 o1 w2 o2 w3 o3 w4 o4 w5 o5 w6 o6 w7 o7 w8 o8 w9 o9 w10 o10 $- \a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 -> f // a1 // a2 // a3 // a4 // a5 // a6 // a7 // a8 // a9 // a10 // check s------ GSL error codes are <= 1024--- | error codes for the auxiliary functions required by the wrappers-errorCode :: CInt -> String-errorCode 2000 = "bad size"-errorCode 2001 = "bad function code"-errorCode 2002 = "memory problem"-errorCode 2003 = "bad file"-errorCode 2004 = "singular"-errorCode 2005 = "didn't converge"-errorCode 2006 = "the input matrix is not positive definite"-errorCode 2007 = "not yet supported in this OS"-errorCode n = "code "++show n----- | clear the fpu-foreign import ccall unsafe "asm_finit" finit :: IO ()---- | check the error code-check :: String -> IO CInt -> IO ()-check msg f = do-#if FINIT- finit-#endif- err <- f- when (err/=0) $ if err > 1024- then (error (msg++": "++errorCode err)) -- our errors- else do -- GSL errors- ps <- gsl_strerror err- s <- peekCString ps- error (msg++": "++s)- return ()---- | description of GSL error codes-foreign import ccall unsafe "gsl_strerror" gsl_strerror :: CInt -> IO (Ptr CChar)---- | Error capture and conversion to Maybe-mbCatch :: IO x -> IO (Maybe x)-mbCatch act = E.catch (Just `fmap` act) f- where f :: SomeException -> IO (Maybe x)- f _ = return Nothing
@@ -1,470 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE BangPatterns #-}--------------------------------------------------------------------------------- |--- Module : Data.Packed.Internal.Matrix--- Copyright : (c) Alberto Ruiz 2007--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable (uses FFI)------ Internal matrix representation------------------------------------------------------------------------------------ #hide--module Data.Packed.Internal.Matrix(- Matrix(..), rows, cols, cdat, fdat,- MatrixOrder(..), orderOf,- createMatrix, mat,- cmat, fmat,- toLists, flatten, reshape,- Element(..),- trans,- fromRows, toRows, fromColumns, toColumns,- matrixFromVector,- subMatrix,- liftMatrix, liftMatrix2,- (@@>), atM',- saveMatrix,- singleton,- size, shSize, conformVs, conformMs, conformVTo, conformMTo-) where--import Data.Packed.Internal.Common-import Data.Packed.Internal.Signatures-import Data.Packed.Internal.Vector--import Foreign.Marshal.Alloc(alloca, free)-import Foreign.Marshal.Array(newArray)-import Foreign.Ptr(Ptr, castPtr)-import Foreign.Storable(Storable, peekElemOff, pokeElemOff, poke, sizeOf)-import Data.Complex(Complex)-import Foreign.C.Types-import Foreign.C.String(newCString)-import System.IO.Unsafe(unsafePerformIO)-import Control.DeepSeq---------------------------------------------------------------------{- Design considerations for the Matrix Type- -------------------------------------------- we must easily handle both row major and column major order,- for bindings to LAPACK and GSL/C--- we'd like to simplify redundant matrix transposes:- - Some of them arise from the order requirements of some functions- - some functions (matrix product) admit transposed arguments--- maybe we don't really need this kind of simplification:- - more complex code- - some computational overhead- - only appreciable gain in code with a lot of redundant transpositions- and cheap matrix computations--- we could carry both the matrix and its (lazily computed) transpose.- This may save some transpositions, but it is necessary to keep track of the- data which is actually computed to be used by functions like the matrix product- which admit both orders.--- but if we need the transposed data and it is not in the structure, we must make- sure that we touch the same foreignptr that is used in the computation.--- a reasonable solution is using two constructors for a matrix. Transposition just- "flips" the constructor. Actual data transposition is not done if followed by a- matrix product or another transpose.---}--data MatrixOrder = RowMajor | ColumnMajor deriving (Show,Eq)--transOrder RowMajor = ColumnMajor-transOrder ColumnMajor = RowMajor-{- | Matrix representation suitable for GSL and LAPACK computations.--The elements are stored in a continuous memory array.---}--data Matrix t = Matrix { irows :: {-# UNPACK #-} !Int- , icols :: {-# UNPACK #-} !Int- , xdat :: {-# UNPACK #-} !(Vector t)- , order :: !MatrixOrder }--- RowMajor: preferred by C, fdat may require a transposition--- ColumnMajor: preferred by LAPACK, cdat may require a transposition--cdat = xdat-fdat = xdat--rows :: Matrix t -> Int-rows = irows--cols :: Matrix t -> Int-cols = icols--orderOf :: Matrix t -> MatrixOrder-orderOf = order----- | Matrix transpose.-trans :: Matrix t -> Matrix t-trans Matrix {irows = r, icols = c, xdat = d, order = o } = Matrix { irows = c, icols = r, xdat = d, order = transOrder o}--cmat :: (Element t) => Matrix t -> Matrix t-cmat m@Matrix{order = RowMajor} = m-cmat Matrix {irows = r, icols = c, xdat = d, order = ColumnMajor } = Matrix { irows = r, icols = c, xdat = transdata r d c, order = RowMajor}--fmat :: (Element t) => Matrix t -> Matrix t-fmat m@Matrix{order = ColumnMajor} = m-fmat Matrix {irows = r, icols = c, xdat = d, order = RowMajor } = Matrix { irows = r, icols = c, xdat = transdata c d r, order = ColumnMajor}---- C-Haskell matrix adapter--- mat :: Adapt (CInt -> CInt -> Ptr t -> r) (Matrix t) r--mat :: (Storable t) => Matrix t -> (((CInt -> CInt -> Ptr t -> t1) -> t1) -> IO b) -> IO b-mat a f =- unsafeWith (xdat a) $ \p -> do- let m g = do- g (fi (rows a)) (fi (cols a)) p- f m--- | Creates a vector by concatenation of rows. If the matrix is ColumnMajor, this operation requires a transpose.------ @\> flatten ('ident' 3)--- 9 |> [1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0]@-flatten :: Element t => Matrix t -> Vector t-flatten = xdat . cmat--type Mt t s = Int -> Int -> Ptr t -> s--- not yet admitted by my haddock version--- infixr 6 ::>--- type t ::> s = Mt t s---- | the inverse of 'Data.Packed.Matrix.fromLists'-toLists :: (Element t) => Matrix t -> [[t]]-toLists m = splitEvery (cols m) . toList . flatten $ m---- | Create a matrix from a list of vectors.--- All vectors must have the same dimension,--- or dimension 1, which is are automatically expanded.-fromRows :: Element t => [Vector t] -> Matrix t-fromRows vs = case compatdim (map dim vs) of- Nothing -> error "fromRows applied to [] or to vectors with different sizes"- Just c -> reshape c . join . map (adapt c) $ vs- where- adapt c v | dim v == c = v- | otherwise = constantD (v@>0) c---- | extracts the rows of a matrix as a list of vectors-toRows :: Element t => Matrix t -> [Vector t]-toRows m = toRows' 0 where- v = flatten m- r = rows m- c = cols m- toRows' k | k == r*c = []- | otherwise = subVector k c v : toRows' (k+c)---- | Creates a matrix from a list of vectors, as columns-fromColumns :: Element t => [Vector t] -> Matrix t-fromColumns m = trans . fromRows $ m---- | Creates a list of vectors from the columns of a matrix-toColumns :: Element t => Matrix t -> [Vector t]-toColumns m = toRows . trans $ m---- | Reads a matrix position.-(@@>) :: Storable t => Matrix t -> (Int,Int) -> t-infixl 9 @@>-m@Matrix {irows = r, icols = c} @@> (i,j)- | safe = if i<0 || i>=r || j<0 || j>=c- then error "matrix indexing out of range"- else atM' m i j- | otherwise = atM' m i j-{-# INLINE (@@>) #-}---- Unsafe matrix access without range checking-atM' Matrix {icols = c, xdat = v, order = RowMajor} i j = v `at'` (i*c+j)-atM' Matrix {irows = r, xdat = v, order = ColumnMajor} i j = v `at'` (j*r+i)-{-# INLINE atM' #-}----------------------------------------------------------------------matrixFromVector o c v = Matrix { irows = r, icols = c, xdat = v, order = o }- where (d,m) = dim v `quotRem` c- r | m==0 = d- | otherwise = error "matrixFromVector"---- allocates memory for a new matrix-createMatrix :: (Storable a) => MatrixOrder -> Int -> Int -> IO (Matrix a)-createMatrix ord r c = do- p <- createVector (r*c)- return (matrixFromVector ord c p)--{- | Creates a matrix from a vector by grouping the elements in rows with the desired number of columns. (GNU-Octave groups by columns. To do it you can define @reshapeF r = trans . reshape r@-where r is the desired number of rows.)--@\> reshape 4 ('fromList' [1..12])-(3><4)- [ 1.0, 2.0, 3.0, 4.0- , 5.0, 6.0, 7.0, 8.0- , 9.0, 10.0, 11.0, 12.0 ]@---}-reshape :: Storable t => Int -> Vector t -> Matrix t-reshape c v = matrixFromVector RowMajor c v--singleton x = reshape 1 (fromList [x])---- | application of a vector function on the flattened matrix elements-liftMatrix :: (Storable a, Storable b) => (Vector a -> Vector b) -> Matrix a -> Matrix b-liftMatrix f Matrix { icols = c, xdat = d, order = o } = matrixFromVector o c (f d)---- | application of a vector function on the flattened matrices elements-liftMatrix2 :: (Element t, Element a, Element b) => (Vector a -> Vector b -> Vector t) -> Matrix a -> Matrix b -> Matrix t-liftMatrix2 f m1 m2- | not (compat m1 m2) = error "nonconformant matrices in liftMatrix2"- | otherwise = case orderOf m1 of- RowMajor -> matrixFromVector RowMajor (cols m1) (f (xdat m1) (flatten m2))- ColumnMajor -> matrixFromVector ColumnMajor (cols m1) (f (xdat m1) ((xdat.fmat) m2))---compat :: Matrix a -> Matrix b -> Bool-compat m1 m2 = rows m1 == rows m2 && cols m1 == cols m2----------------------------------------------------------------------{- | Supported matrix elements.-- This class provides optimized internal- operations for selected element types.- It provides unoptimised defaults for any 'Storable' type,- so you can create instances simply as:- @instance Element Foo@.--}-class (Storable a) => Element a where- subMatrixD :: (Int,Int) -- ^ (r0,c0) starting position - -> (Int,Int) -- ^ (rt,ct) dimensions of submatrix- -> Matrix a -> Matrix a- subMatrixD = subMatrix'- transdata :: Int -> Vector a -> Int -> Vector a- transdata = transdataP -- transdata'- constantD :: a -> Int -> Vector a- constantD = constantP -- constant'---instance Element Float where- transdata = transdataAux ctransF- constantD = constantAux cconstantF--instance Element Double where- transdata = transdataAux ctransR- constantD = constantAux cconstantR--instance Element (Complex Float) where- transdata = transdataAux ctransQ- constantD = constantAux cconstantQ--instance Element (Complex Double) where- transdata = transdataAux ctransC- constantD = constantAux cconstantC-----------------------------------------------------------------------transdata' :: Storable a => Int -> Vector a -> Int -> Vector a-transdata' c1 v c2 =- if noneed- then v- else unsafePerformIO $ do- w <- createVector (r2*c2)- unsafeWith v $ \p ->- unsafeWith w $ \q -> do- let go (-1) _ = return ()- go !i (-1) = go (i-1) (c1-1)- go !i !j = do x <- peekElemOff p (i*c1+j)- pokeElemOff q (j*c2+i) x- go i (j-1)- go (r1-1) (c1-1)- return w- where r1 = dim v `div` c1- r2 = dim v `div` c2- noneed = r1 == 1 || c1 == 1---- {-# SPECIALIZE transdata' :: Int -> Vector Double -> Int -> Vector Double #-}--- {-# SPECIALIZE transdata' :: Int -> Vector (Complex Double) -> Int -> Vector (Complex Double) #-}---- I don't know how to specialize...--- The above pragmas only seem to work on top level defs--- Fortunately everything seems to work using the above class---- C versions, still a little faster:--transdataAux fun c1 d c2 =- if noneed- then d- else unsafePerformIO $ do- v <- createVector (dim d)- unsafeWith d $ \pd ->- unsafeWith v $ \pv ->- fun (fi r1) (fi c1) pd (fi r2) (fi c2) pv // check "transdataAux"- return v- where r1 = dim d `div` c1- r2 = dim d `div` c2- noneed = r1 == 1 || c1 == 1--transdataP :: Storable a => Int -> Vector a -> Int -> Vector a-transdataP c1 d c2 =- if noneed- then d- else unsafePerformIO $ do- v <- createVector (dim d)- unsafeWith d $ \pd ->- unsafeWith v $ \pv ->- ctransP (fi r1) (fi c1) (castPtr pd) (fi sz) (fi r2) (fi c2) (castPtr pv) (fi sz) // check "transdataP"- return v- where r1 = dim d `div` c1- r2 = dim d `div` c2- sz = sizeOf (d @> 0)- noneed = r1 == 1 || c1 == 1--foreign import ccall unsafe "transF" ctransF :: TFMFM-foreign import ccall unsafe "transR" ctransR :: TMM-foreign import ccall unsafe "transQ" ctransQ :: TQMQM-foreign import ccall unsafe "transC" ctransC :: TCMCM-foreign import ccall unsafe "transP" ctransP :: CInt -> CInt -> Ptr () -> CInt -> CInt -> CInt -> Ptr () -> CInt -> IO CInt--------------------------------------------------------------------------constant' v n = unsafePerformIO $ do- w <- createVector n- unsafeWith w $ \p -> do- let go (-1) = return ()- go !k = pokeElemOff p k v >> go (k-1)- go (n-1)- return w---- C versions--constantAux fun x n = unsafePerformIO $ do- v <- createVector n- px <- newArray [x]- app1 (fun px) vec v "constantAux"- free px- return v--constantF :: Float -> Int -> Vector Float-constantF = constantAux cconstantF-foreign import ccall unsafe "constantF" cconstantF :: Ptr Float -> TF--constantR :: Double -> Int -> Vector Double-constantR = constantAux cconstantR-foreign import ccall unsafe "constantR" cconstantR :: Ptr Double -> TV--constantQ :: Complex Float -> Int -> Vector (Complex Float)-constantQ = constantAux cconstantQ-foreign import ccall unsafe "constantQ" cconstantQ :: Ptr (Complex Float) -> TQV--constantC :: Complex Double -> Int -> Vector (Complex Double)-constantC = constantAux cconstantC-foreign import ccall unsafe "constantC" cconstantC :: Ptr (Complex Double) -> TCV--constantP :: Storable a => a -> Int -> Vector a-constantP a n = unsafePerformIO $ do- let sz = sizeOf a- v <- createVector n- unsafeWith v $ \p -> do- alloca $ \k -> do- poke k a- cconstantP (castPtr k) (fi n) (castPtr p) (fi sz) // check "constantP"- return v-foreign import ccall unsafe "constantP" cconstantP :: Ptr () -> CInt -> Ptr () -> CInt -> IO CInt---------------------------------------------------------------------------- | Extracts a submatrix from a matrix.-subMatrix :: Element a- => (Int,Int) -- ^ (r0,c0) starting position - -> (Int,Int) -- ^ (rt,ct) dimensions of submatrix- -> Matrix a -- ^ input matrix- -> Matrix a -- ^ result-subMatrix (r0,c0) (rt,ct) m- | 0 <= r0 && 0 < rt && r0+rt <= (rows m) &&- 0 <= c0 && 0 < ct && c0+ct <= (cols m) = subMatrixD (r0,c0) (rt,ct) m- | otherwise = error $ "wrong subMatrix "++- show ((r0,c0),(rt,ct))++" of "++show(rows m)++"x"++ show (cols m)--subMatrix'' (r0,c0) (rt,ct) c v = unsafePerformIO $ do- w <- createVector (rt*ct)- unsafeWith v $ \p ->- unsafeWith w $ \q -> do- let go (-1) _ = return ()- go !i (-1) = go (i-1) (ct-1)- go !i !j = do x <- peekElemOff p ((i+r0)*c+j+c0)- pokeElemOff q (i*ct+j) x- go i (j-1)- go (rt-1) (ct-1)- return w--subMatrix' (r0,c0) (rt,ct) (Matrix { icols = c, xdat = v, order = RowMajor}) = Matrix rt ct (subMatrix'' (r0,c0) (rt,ct) c v) RowMajor-subMatrix' (r0,c0) (rt,ct) m = trans $ subMatrix' (c0,r0) (ct,rt) (trans m)-------------------------------------------------------------------------------- | Saves a matrix as 2D ASCII table.-saveMatrix :: FilePath- -> String -- ^ format (%f, %g, %e)- -> Matrix Double- -> IO ()-saveMatrix filename fmt m = do- charname <- newCString filename- charfmt <- newCString fmt- let o = if orderOf m == RowMajor then 1 else 0- app1 (matrix_fprintf charname charfmt o) mat m "matrix_fprintf"- free charname- free charfmt--foreign import ccall unsafe "matrix_fprintf" matrix_fprintf :: Ptr CChar -> Ptr CChar -> CInt -> TM--------------------------------------------------------------------------conformMs ms = map (conformMTo (r,c)) ms- where- r = maximum (map rows ms)- c = maximum (map cols ms)--conformVs vs = map (conformVTo n) vs- where- n = maximum (map dim vs)--conformMTo (r,c) m- | size m == (r,c) = m- | size m == (1,1) = reshape c (constantD (m@@>(0,0)) (r*c))- | size m == (r,1) = repCols c m- | size m == (1,c) = repRows r m- | otherwise = error $ "matrix " ++ shSize m ++ " cannot be expanded to (" ++ show r ++ "><"++ show c ++")"--conformVTo n v- | dim v == n = v- | dim v == 1 = constantD (v@>0) n- | otherwise = error $ "vector of dim=" ++ show (dim v) ++ " cannot be expanded to dim=" ++ show n--repRows n x = fromRows (replicate n (flatten x))-repCols n x = fromColumns (replicate n (flatten x))--size m = (rows m, cols m)--shSize m = "(" ++ show (rows m) ++"><"++ show (cols m)++")"--------------------------------------------------------------------------instance (Storable t, NFData t) => NFData (Matrix t)- where- rnf m | d > 0 = rnf (v @> 0)- | otherwise = ()- where- d = dim v- v = xdat m-
@@ -1,72 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Data.Packed.Internal.Signatures--- Copyright : (c) Alberto Ruiz 2009--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable (uses FFI)------ Signatures of the C functions.-----------------------------------------------------------------------------------module Data.Packed.Internal.Signatures where--import Foreign.Ptr(Ptr)-import Data.Complex(Complex)-import Foreign.C.Types(CInt)--type PF = Ptr Float ---type PD = Ptr Double ---type PQ = Ptr (Complex Float) ---type PC = Ptr (Complex Double) ---type TF = CInt -> PF -> IO CInt ---type TFF = CInt -> PF -> TF ---type TFV = CInt -> PF -> TV ---type TVF = CInt -> PD -> TF ---type TFFF = CInt -> PF -> TFF ---type TV = CInt -> PD -> IO CInt ---type TVV = CInt -> PD -> TV ---type TVVV = CInt -> PD -> TVV ---type TFM = CInt -> CInt -> PF -> IO CInt ---type TFMFM = CInt -> CInt -> PF -> TFM ---type TFMFMFM = CInt -> CInt -> PF -> TFMFM ---type TM = CInt -> CInt -> PD -> IO CInt ---type TMM = CInt -> CInt -> PD -> TM ---type TVMM = CInt -> PD -> TMM ---type TMVMM = CInt -> CInt -> PD -> TVMM ---type TMMM = CInt -> CInt -> PD -> TMM ---type TVM = CInt -> PD -> TM ---type TVVM = CInt -> PD -> TVM ---type TMV = CInt -> CInt -> PD -> TV ---type TMMV = CInt -> CInt -> PD -> TMV ---type TMVM = CInt -> CInt -> PD -> TVM ---type TMMVM = CInt -> CInt -> PD -> TMVM ---type TCM = CInt -> CInt -> PC -> IO CInt ---type TCVCM = CInt -> PC -> TCM ---type TCMCVCM = CInt -> CInt -> PC -> TCVCM ---type TMCMCVCM = CInt -> CInt -> PD -> TCMCVCM ---type TCMCMCVCM = CInt -> CInt -> PC -> TCMCVCM ---type TCMCM = CInt -> CInt -> PC -> TCM ---type TVCM = CInt -> PD -> TCM ---type TCMVCM = CInt -> CInt -> PC -> TVCM ---type TCMCMVCM = CInt -> CInt -> PC -> TCMVCM ---type TCMCMCM = CInt -> CInt -> PC -> TCMCM ---type TCV = CInt -> PC -> IO CInt ---type TCVCV = CInt -> PC -> TCV ---type TCVCVCV = CInt -> PC -> TCVCV ---type TCVV = CInt -> PC -> TV ---type TQV = CInt -> PQ -> IO CInt ---type TQVQV = CInt -> PQ -> TQV ---type TQVQVQV = CInt -> PQ -> TQVQV ---type TQVF = CInt -> PQ -> TF ---type TQM = CInt -> CInt -> PQ -> IO CInt ---type TQMQM = CInt -> CInt -> PQ -> TQM ---type TQMQMQM = CInt -> CInt -> PQ -> TQMQM ---type TCMCV = CInt -> CInt -> PC -> TCV ---type TVCV = CInt -> PD -> TCV ---type TCVM = CInt -> PC -> TM ---type TMCVM = CInt -> CInt -> PD -> TCVM ---type TMMCVM = CInt -> CInt -> PD -> TMCVM --
@@ -1,523 +0,0 @@-{-# LANGUAGE MagicHash, CPP, UnboxedTuples, BangPatterns, FlexibleContexts #-}--------------------------------------------------------------------------------- |--- Module : Data.Packed.Internal.Vector--- Copyright : (c) Alberto Ruiz 2007--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable (uses FFI)------ Vector implementation-----------------------------------------------------------------------------------module Data.Packed.Internal.Vector (- Vector, dim,- fromList, toList, (|>),- join, (@>), safe, at, at', subVector, takesV,- mapVector, mapVectorWithIndex, zipVectorWith, unzipVectorWith,- mapVectorM, mapVectorM_, mapVectorWithIndexM, mapVectorWithIndexM_,- foldVector, foldVectorG, foldLoop, foldVectorWithIndex,- createVector, vec,- asComplex, asReal, float2DoubleV, double2FloatV,- stepF, stepD, condF, condD,- conjugateQ, conjugateC,- fwriteVector, freadVector, fprintfVector, fscanfVector,- cloneVector,- unsafeToForeignPtr,- unsafeFromForeignPtr,- unsafeWith-) where--import Data.Packed.Internal.Common-import Data.Packed.Internal.Signatures-import Foreign.Marshal.Alloc(free)-import Foreign.Marshal.Array(peekArray, pokeArray, copyArray, advancePtr)-import Foreign.ForeignPtr(ForeignPtr, castForeignPtr)-import Foreign.Ptr(Ptr)-import Foreign.Storable(Storable, peekElemOff, pokeElemOff, sizeOf)-import Foreign.C.String-import Foreign.C.Types-import Data.Complex-import Control.Monad(when)-import System.IO.Unsafe(unsafePerformIO)--#if __GLASGOW_HASKELL__ >= 605-import GHC.ForeignPtr (mallocPlainForeignPtrBytes)-#else-import Foreign.ForeignPtr (mallocForeignPtrBytes)-#endif--import GHC.Base-#if __GLASGOW_HASKELL__ < 612-import GHC.IOBase hiding (liftIO)-#endif--import qualified Data.Vector.Storable as Vector-import Data.Vector.Storable(Vector,- unsafeToForeignPtr,- unsafeFromForeignPtr,- unsafeWith)----- | Number of elements-dim :: (Storable t) => Vector t -> Int-dim = Vector.length----- C-Haskell vector adapter--- vec :: Adapt (CInt -> Ptr t -> r) (Vector t) r-vec :: (Storable t) => Vector t -> (((CInt -> Ptr t -> t1) -> t1) -> IO b) -> IO b-vec x f = unsafeWith x $ \p -> do- let v g = do- g (fi $ dim x) p- f v-{-# INLINE vec #-}----- allocates memory for a new vector-createVector :: Storable a => Int -> IO (Vector a)-createVector n = do- when (n <= 0) $ error ("trying to createVector of dim "++show n)- fp <- doMalloc undefined- return $ unsafeFromForeignPtr fp 0 n- where- --- -- Use the much cheaper Haskell heap allocated storage- -- for foreign pointer space we control- --- doMalloc :: Storable b => b -> IO (ForeignPtr b)- doMalloc dummy = do-#if __GLASGOW_HASKELL__ >= 605- mallocPlainForeignPtrBytes (n * sizeOf dummy)-#else- mallocForeignPtrBytes (n * sizeOf dummy)-#endif--{- | creates a Vector from a list:--@> fromList [2,3,5,7]-4 |> [2.0,3.0,5.0,7.0]@---}-fromList :: Storable a => [a] -> Vector a-fromList l = unsafePerformIO $ do- v <- createVector (length l)- unsafeWith v $ \ p -> pokeArray p l- return v--safeRead v = inlinePerformIO . unsafeWith v-{-# INLINE safeRead #-}--inlinePerformIO :: IO a -> a-inlinePerformIO (IO m) = case m realWorld# of (# _, r #) -> r-{-# INLINE inlinePerformIO #-}--{- | extracts the Vector elements to a list--@> toList (linspace 5 (1,10))-[1.0,3.25,5.5,7.75,10.0]@---}-toList :: Storable a => Vector a -> [a]-toList v = safeRead v $ peekArray (dim v)--{- | An alternative to 'fromList' with explicit dimension. The input- list is explicitly truncated if it is too long, so it may safely- be used, for instance, with infinite lists.-- This is the format used in the instances for Show (Vector a).--}-(|>) :: (Storable a) => Int -> [a] -> Vector a-infixl 9 |>-n |> l = if length l' == n- then fromList l'- else error "list too short for |>"- where l' = take n l----- | access to Vector elements without range checking-at' :: Storable a => Vector a -> Int -> a-at' v n = safeRead v $ flip peekElemOff n-{-# INLINE at' #-}------- turn off bounds checking with -funsafe at configure time.--- ghc will optimise away the salways true case at compile time.----#if defined(UNSAFE)-safe :: Bool-safe = False-#else-safe = True-#endif---- | access to Vector elements with range checking.-at :: Storable a => Vector a -> Int -> a-at v n- | safe = if n >= 0 && n < dim v- then at' v n- else error "vector index out of range"- | otherwise = at' v n-{-# INLINE at #-}--{- | takes a number of consecutive elements from a Vector--@> subVector 2 3 (fromList [1..10])-3 |> [3.0,4.0,5.0]@---}-subVector :: Storable t => Int -- ^ index of the starting element- -> Int -- ^ number of elements to extract- -> Vector t -- ^ source- -> Vector t -- ^ result-subVector = Vector.slice---{- | Reads a vector position:--@> fromList [0..9] \@\> 7-7.0@---}-(@>) :: Storable t => Vector t -> Int -> t-infixl 9 @>-(@>) = at---{- | creates a new Vector by joining a list of Vectors--@> join [fromList [1..5], constant 1 3]-8 |> [1.0,2.0,3.0,4.0,5.0,1.0,1.0,1.0]@---}-join :: Storable t => [Vector t] -> Vector t-join [] = error "joining zero vectors"-join [v] = v-join as = unsafePerformIO $ do- let tot = sum (map dim as)- r <- createVector tot- unsafeWith r $ \ptr ->- joiner as tot ptr- return r- where joiner [] _ _ = return ()- joiner (v:cs) _ p = do- let n = dim v- unsafeWith v $ \pb -> copyArray p pb n- joiner cs 0 (advancePtr p n)---{- | Extract consecutive subvectors of the given sizes.--@> takesV [3,4] (linspace 10 (1,10))-[3 |> [1.0,2.0,3.0],4 |> [4.0,5.0,6.0,7.0]]@---}-takesV :: Storable t => [Int] -> Vector t -> [Vector t]-takesV ms w | sum ms > dim w = error $ "takesV " ++ show ms ++ " on dim = " ++ (show $ dim w)- | otherwise = go ms w- where go [] _ = []- go (n:ns) v = subVector 0 n v- : go ns (subVector n (dim v - n) v)--------------------------------------------------------------------- | transforms a complex vector into a real vector with alternating real and imaginary parts -asReal :: (RealFloat a, Storable a) => Vector (Complex a) -> Vector a-asReal v = unsafeFromForeignPtr (castForeignPtr fp) (2*i) (2*n)- where (fp,i,n) = unsafeToForeignPtr v---- | transforms a real vector into a complex vector with alternating real and imaginary parts-asComplex :: (RealFloat a, Storable a) => Vector a -> Vector (Complex a)-asComplex v = unsafeFromForeignPtr (castForeignPtr fp) (i `div` 2) (n `div` 2)- where (fp,i,n) = unsafeToForeignPtr v-------------------------------------------------------------------float2DoubleV :: Vector Float -> Vector Double-float2DoubleV v = unsafePerformIO $ do- r <- createVector (dim v)- app2 c_float2double vec v vec r "float2double"- return r--double2FloatV :: Vector Double -> Vector Float-double2FloatV v = unsafePerformIO $ do- r <- createVector (dim v)- app2 c_double2float vec v vec r "double2float2"- return r---foreign import ccall unsafe "float2double" c_float2double:: TFV-foreign import ccall unsafe "double2float" c_double2float:: TVF-------------------------------------------------------------------stepF :: Vector Float -> Vector Float-stepF v = unsafePerformIO $ do- r <- createVector (dim v)- app2 c_stepF vec v vec r "stepF"- return r--stepD :: Vector Double -> Vector Double-stepD v = unsafePerformIO $ do- r <- createVector (dim v)- app2 c_stepD vec v vec r "stepD"- return r--foreign import ccall unsafe "stepF" c_stepF :: TFF-foreign import ccall unsafe "stepD" c_stepD :: TVV-------------------------------------------------------------------condF :: Vector Float -> Vector Float -> Vector Float -> Vector Float -> Vector Float -> Vector Float-condF x y l e g = unsafePerformIO $ do- r <- createVector (dim x)- app6 c_condF vec x vec y vec l vec e vec g vec r "condF"- return r--condD :: Vector Double -> Vector Double -> Vector Double -> Vector Double -> Vector Double -> Vector Double-condD x y l e g = unsafePerformIO $ do- r <- createVector (dim x)- app6 c_condD vec x vec y vec l vec e vec g vec r "condD"- return r--foreign import ccall unsafe "condF" c_condF :: CInt -> PF -> CInt -> PF -> CInt -> PF -> TFFF-foreign import ccall unsafe "condD" c_condD :: CInt -> PD -> CInt -> PD -> CInt -> PD -> TVVV------------------------------------------------------------------------------------conjugateAux fun x = unsafePerformIO $ do- v <- createVector (dim x)- app2 fun vec x vec v "conjugateAux"- return v--conjugateQ :: Vector (Complex Float) -> Vector (Complex Float)-conjugateQ = conjugateAux c_conjugateQ-foreign import ccall unsafe "conjugateQ" c_conjugateQ :: TQVQV--conjugateC :: Vector (Complex Double) -> Vector (Complex Double)-conjugateC = conjugateAux c_conjugateC-foreign import ccall unsafe "conjugateC" c_conjugateC :: TCVCV------------------------------------------------------------------------------------cloneVector :: Storable t => Vector t -> IO (Vector t)-cloneVector v = do- let n = dim v- r <- createVector n- let f _ s _ d = copyArray d s n >> return 0- app2 f vec v vec r "cloneVector"- return r------------------------------------------------------------------------ | map on Vectors-mapVector :: (Storable a, Storable b) => (a-> b) -> Vector a -> Vector b-mapVector f v = unsafePerformIO $ do- w <- createVector (dim v)- unsafeWith v $ \p ->- unsafeWith w $ \q -> do- let go (-1) = return ()- go !k = do x <- peekElemOff p k- pokeElemOff q k (f x)- go (k-1)- go (dim v -1)- return w-{-# INLINE mapVector #-}---- | zipWith for Vectors-zipVectorWith :: (Storable a, Storable b, Storable c) => (a-> b -> c) -> Vector a -> Vector b -> Vector c-zipVectorWith f u v = unsafePerformIO $ do- let n = min (dim u) (dim v)- w <- createVector n- unsafeWith u $ \pu ->- unsafeWith v $ \pv ->- unsafeWith w $ \pw -> do- let go (-1) = return ()- go !k = do x <- peekElemOff pu k- y <- peekElemOff pv k- pokeElemOff pw k (f x y)- go (k-1)- go (n -1)- return w-{-# INLINE zipVectorWith #-}---- | unzipWith for Vectors-unzipVectorWith :: (Storable (a,b), Storable c, Storable d) - => ((a,b) -> (c,d)) -> Vector (a,b) -> (Vector c,Vector d)-unzipVectorWith f u = unsafePerformIO $ do- let n = dim u- v <- createVector n- w <- createVector n- unsafeWith u $ \pu ->- unsafeWith v $ \pv ->- unsafeWith w $ \pw -> do- let go (-1) = return ()- go !k = do z <- peekElemOff pu k- let (x,y) = f z - pokeElemOff pv k x- pokeElemOff pw k y- go (k-1)- go (n-1)- return (v,w)-{-# INLINE unzipVectorWith #-}--foldVector :: Storable a => (a -> b -> b) -> b -> Vector a -> b-foldVector f x v = unsafePerformIO $- unsafeWith v $ \p -> do- let go (-1) s = return s- go !k !s = do y <- peekElemOff p k- go (k-1::Int) (f y s)- go (dim v -1) x-{-# INLINE foldVector #-}---- the zero-indexed index is passed to the folding function-foldVectorWithIndex :: Storable a => (Int -> a -> b -> b) -> b -> Vector a -> b-foldVectorWithIndex f x v = unsafePerformIO $- unsafeWith v $ \p -> do- let go (-1) s = return s- go !k !s = do y <- peekElemOff p k- go (k-1::Int) (f k y s)- go (dim v -1) x-{-# INLINE foldVectorWithIndex #-}--foldLoop f s0 d = go (d - 1) s0- where- go 0 s = f (0::Int) s- go !j !s = go (j - 1) (f j s)--foldVectorG f s0 v = foldLoop g s0 (dim v)- where g !k !s = f k (at' v) s- {-# INLINE g #-} -- Thanks to Ryan Ingram (http://permalink.gmane.org/gmane.comp.lang.haskell.cafe/46479)-{-# INLINE foldVectorG #-}------------------------------------------------------------------------- | monadic map over Vectors--- the monad @m@ must be strict-mapVectorM :: (Storable a, Storable b, Monad m) => (a -> m b) -> Vector a -> m (Vector b)-mapVectorM f v = do- w <- return $! unsafePerformIO $! createVector (dim v)- mapVectorM' w 0 (dim v -1)- return w- where mapVectorM' w' !k !t- | k == t = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k - y <- f x- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y- | otherwise = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k - y <- f x- _ <- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y- mapVectorM' w' (k+1) t-{-# INLINE mapVectorM #-}---- | monadic map over Vectors-mapVectorM_ :: (Storable a, Monad m) => (a -> m ()) -> Vector a -> m ()-mapVectorM_ f v = do- mapVectorM' 0 (dim v -1)- where mapVectorM' !k !t- | k == t = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k- f x- | otherwise = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k - _ <- f x- mapVectorM' (k+1) t-{-# INLINE mapVectorM_ #-}---- | monadic map over Vectors with the zero-indexed index passed to the mapping function--- the monad @m@ must be strict-mapVectorWithIndexM :: (Storable a, Storable b, Monad m) => (Int -> a -> m b) -> Vector a -> m (Vector b)-mapVectorWithIndexM f v = do- w <- return $! unsafePerformIO $! createVector (dim v)- mapVectorM' w 0 (dim v -1)- return w- where mapVectorM' w' !k !t- | k == t = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k - y <- f k x- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y- | otherwise = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k - y <- f k x- _ <- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y- mapVectorM' w' (k+1) t-{-# INLINE mapVectorWithIndexM #-}---- | monadic map over Vectors with the zero-indexed index passed to the mapping function-mapVectorWithIndexM_ :: (Storable a, Monad m) => (Int -> a -> m ()) -> Vector a -> m ()-mapVectorWithIndexM_ f v = do- mapVectorM' 0 (dim v -1)- where mapVectorM' !k !t- | k == t = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k- f k x- | otherwise = do- x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k - _ <- f k x- mapVectorM' (k+1) t-{-# INLINE mapVectorWithIndexM_ #-}---mapVectorWithIndex :: (Storable a, Storable b) => (Int -> a -> b) -> Vector a -> Vector b---mapVectorWithIndex g = head . mapVectorWithIndexM (\a b -> [g a b])-mapVectorWithIndex f v = unsafePerformIO $ do- w <- createVector (dim v)- unsafeWith v $ \p ->- unsafeWith w $ \q -> do- let go (-1) = return ()- go !k = do x <- peekElemOff p k- pokeElemOff q k (f k x)- go (k-1)- go (dim v -1)- return w-{-# INLINE mapVectorWithIndex #-}-------------------------------------------------------------------------- | Loads a vector from an ASCII file (the number of elements must be known in advance).-fscanfVector :: FilePath -> Int -> IO (Vector Double)-fscanfVector filename n = do- charname <- newCString filename- res <- createVector n- app1 (gsl_vector_fscanf charname) vec res "gsl_vector_fscanf"- free charname- return res--foreign import ccall unsafe "vector_fscanf" gsl_vector_fscanf:: Ptr CChar -> TV---- | Saves the elements of a vector, with a given format (%f, %e, %g), to an ASCII file.-fprintfVector :: FilePath -> String -> Vector Double -> IO ()-fprintfVector filename fmt v = do- charname <- newCString filename- charfmt <- newCString fmt- app1 (gsl_vector_fprintf charname charfmt) vec v "gsl_vector_fprintf"- free charname- free charfmt--foreign import ccall unsafe "vector_fprintf" gsl_vector_fprintf :: Ptr CChar -> Ptr CChar -> TV---- | Loads a vector from a binary file (the number of elements must be known in advance).-freadVector :: FilePath -> Int -> IO (Vector Double)-freadVector filename n = do- charname <- newCString filename- res <- createVector n- app1 (gsl_vector_fread charname) vec res "gsl_vector_fread"- free charname- return res--foreign import ccall unsafe "vector_fread" gsl_vector_fread:: Ptr CChar -> TV---- | Saves the elements of a vector to a binary file.-fwriteVector :: FilePath -> Vector Double -> IO ()-fwriteVector filename v = do- charname <- newCString filename- app1 (gsl_vector_fwrite charname) vec v "gsl_vector_fwrite"- free charname--foreign import ccall unsafe "vector_fwrite" gsl_vector_fwrite :: Ptr CChar -> TV-
@@ -1,420 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Packed.Matrix--- Copyright : (c) Alberto Ruiz 2007-10--- License : GPL------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional------ A Matrix representation suitable for numerical computations using LAPACK and GSL.------ This module provides basic functions for manipulation of structure.---------------------------------------------------------------------------------module Data.Packed.Matrix (- Matrix,- Element,- rows,cols,- (><),- trans,- reshape, flatten,- fromLists, toLists, buildMatrix,- (@@>),- asRow, asColumn,- fromRows, toRows, fromColumns, toColumns,- fromBlocks, diagBlock, toBlocks, toBlocksEvery,- repmat,- flipud, fliprl,- subMatrix, takeRows, dropRows, takeColumns, dropColumns,- extractRows,- diagRect, takeDiag,- mapMatrix, mapMatrixWithIndex, mapMatrixWithIndexM, mapMatrixWithIndexM_,- liftMatrix, liftMatrix2, liftMatrix2Auto,fromArray2D-) where--import Data.Packed.Internal-import qualified Data.Packed.ST as ST-import Data.Array--import Data.List(transpose,intersperse)-import Foreign.Storable(Storable)-import Control.Monad(liftM)-----------------------------------------------------------------------#ifdef BINARY--import Data.Binary-import Control.Monad(replicateM)--instance (Binary a, Element a, Storable a) => Binary (Matrix a) where- put m = do- let r = rows m- let c = cols m- put r- put c- mapM_ (\i -> mapM_ (\j -> put $ m @@> (i,j)) [0..(c-1)]) [0..(r-1)]- get = do- r <- get- c <- get- xs <- replicateM r $ replicateM c get- return $ fromLists xs--#endif-----------------------------------------------------------------------instance (Show a, Element a) => (Show (Matrix a)) where- show m = (sizes++) . dsp . map (map show) . toLists $ m- where sizes = "("++show (rows m)++"><"++show (cols m)++")\n"--dsp as = (++" ]") . (" ["++) . init . drop 2 . unlines . map (" , "++) . map unwords' $ transpose mtp- where- mt = transpose as- longs = map (maximum . map length) mt- mtp = zipWith (\a b -> map (pad a) b) longs mt- pad n str = replicate (n - length str) ' ' ++ str- unwords' = concat . intersperse ", "----------------------------------------------------------------------instance (Element a, Read a) => Read (Matrix a) where- readsPrec _ s = [((rs><cs) . read $ listnums, rest)]- where (thing,rest) = breakAt ']' s- (dims,listnums) = breakAt ')' thing- cs = read . init . fst. breakAt ')' . snd . breakAt '<' $ dims- rs = read . snd . breakAt '(' .init . fst . breakAt '>' $ dims---breakAt c l = (a++[c],tail b) where- (a,b) = break (==c) l------------------------------------------------------------------------ | creates a matrix from a vertical list of matrices-joinVert :: Element t => [Matrix t] -> Matrix t-joinVert ms = case common cols ms of- Nothing -> error "(impossible) joinVert on matrices with different number of columns"- Just c -> reshape c $ join (map flatten ms)---- | creates a matrix from a horizontal list of matrices-joinHoriz :: Element t => [Matrix t] -> Matrix t-joinHoriz ms = trans. joinVert . map trans $ ms--{- | Creates a matrix from blocks given as a list of lists of matrices.--Single row/column components are automatically expanded to match the-corresponding common row and column:--@\> let disp = putStr . dispf 2-\> let vector xs = fromList xs :: Vector Double-\> let diagl = diag . vector-\> let rowm = asRow . vector--\> disp $ fromBlocks [[ident 5, 7, rowm[10,20]], [3, diagl[1,2,3], 0]]--8x10-1 0 0 0 0 7 7 7 10 20-0 1 0 0 0 7 7 7 10 20-0 0 1 0 0 7 7 7 10 20-0 0 0 1 0 7 7 7 10 20-0 0 0 0 1 7 7 7 10 20-3 3 3 3 3 1 0 0 0 0-3 3 3 3 3 0 2 0 0 0-3 3 3 3 3 0 0 3 0 0@--}-fromBlocks :: Element t => [[Matrix t]] -> Matrix t-fromBlocks = fromBlocksRaw . adaptBlocks--fromBlocksRaw mms = joinVert . map joinHoriz $ mms--adaptBlocks ms = ms' where- bc = case common length ms of- Just c -> c- Nothing -> error "fromBlocks requires rectangular [[Matrix]]"- rs = map (compatdim . map rows) ms- cs = map (compatdim . map cols) (transpose ms)- szs = sequence [rs,cs]- ms' = splitEvery bc $ zipWith g szs (concat ms)-- g [Just nr,Just nc] m- | nr == r && nc == c = m- | r == 1 && c == 1 = reshape nc (constantD x (nr*nc))- | r == 1 = fromRows (replicate nr (flatten m))- | otherwise = fromColumns (replicate nc (flatten m))- where- r = rows m- c = cols m- x = m@@>(0,0)- g _ _ = error "inconsistent dimensions in fromBlocks"--------------------------------------------------------------------------------------- | create a block diagonal matrix-diagBlock :: (Element t, Num t) => [Matrix t] -> Matrix t-diagBlock ms = fromBlocks $ zipWith f ms [0..]- where- f m k = take n $ replicate k z ++ m : repeat z- n = length ms- z = (1><1) [0]--------------------------------------------------------------------------------------- | Reverse rows-flipud :: Element t => Matrix t -> Matrix t-flipud m = fromRows . reverse . toRows $ m---- | Reverse columns-fliprl :: Element t => Matrix t -> Matrix t-fliprl m = fromColumns . reverse . toColumns $ m----------------------------------------------------------------{- | creates a rectangular diagonal matrix:--@> diagRect 7 (fromList [10,20,30]) 4 5 :: Matrix Double-(4><5)- [ 10.0, 7.0, 7.0, 7.0, 7.0- , 7.0, 20.0, 7.0, 7.0, 7.0- , 7.0, 7.0, 30.0, 7.0, 7.0- , 7.0, 7.0, 7.0, 7.0, 7.0 ]@--}-diagRect :: (Storable t) => t -> Vector t -> Int -> Int -> Matrix t-diagRect z v r c = ST.runSTMatrix $ do- m <- ST.newMatrix z r c- let d = min r c `min` (dim v)- mapM_ (\k -> ST.writeMatrix m k k (v@>k)) [0..d-1]- return m---- | extracts the diagonal from a rectangular matrix-takeDiag :: (Element t) => Matrix t -> Vector t-takeDiag m = fromList [flatten m `at` (k*cols m+k) | k <- [0 .. min (rows m) (cols m) -1]]----------------------------------------------------------------{- | An easy way to create a matrix:--@\> (2><3)[1..6]-(2><3)- [ 1.0, 2.0, 3.0- , 4.0, 5.0, 6.0 ]@--This is the format produced by the instances of Show (Matrix a), which-can also be used for input.--The input list is explicitly truncated, so that it can-safely be used with lists that are too long (like infinite lists).--Example:--@\> (2><3)[1..]-(2><3)- [ 1.0, 2.0, 3.0- , 4.0, 5.0, 6.0 ]@---}-(><) :: (Storable a) => Int -> Int -> [a] -> Matrix a-r >< c = f where- f l | dim v == r*c = matrixFromVector RowMajor c v- | otherwise = error $ "inconsistent list size = "- ++show (dim v) ++" in ("++show r++"><"++show c++")"- where v = fromList $ take (r*c) l---------------------------------------------------------------------- | Creates a matrix with the first n rows of another matrix-takeRows :: Element t => Int -> Matrix t -> Matrix t-takeRows n mt = subMatrix (0,0) (n, cols mt) mt--- | Creates a copy of a matrix without the first n rows-dropRows :: Element t => Int -> Matrix t -> Matrix t-dropRows n mt = subMatrix (n,0) (rows mt - n, cols mt) mt--- |Creates a matrix with the first n columns of another matrix-takeColumns :: Element t => Int -> Matrix t -> Matrix t-takeColumns n mt = subMatrix (0,0) (rows mt, n) mt--- | Creates a copy of a matrix without the first n columns-dropColumns :: Element t => Int -> Matrix t -> Matrix t-dropColumns n mt = subMatrix (0,n) (rows mt, cols mt - n) mt--------------------------------------------------------------------{- | Creates a 'Matrix' from a list of lists (considered as rows).--@\> fromLists [[1,2],[3,4],[5,6]]-(3><2)- [ 1.0, 2.0- , 3.0, 4.0- , 5.0, 6.0 ]@--}-fromLists :: Element t => [[t]] -> Matrix t-fromLists = fromRows . map fromList---- | creates a 1-row matrix from a vector-asRow :: Storable a => Vector a -> Matrix a-asRow v = reshape (dim v) v---- | creates a 1-column matrix from a vector-asColumn :: Storable a => Vector a -> Matrix a-asColumn v = reshape 1 v----{- | creates a Matrix of the specified size using the supplied function to- to map the row\/column position to the value at that row\/column position.--@> buildMatrix 3 4 (\\(r,c) -> fromIntegral r * fromIntegral c)-(3><4)- [ 0.0, 0.0, 0.0, 0.0, 0.0- , 0.0, 1.0, 2.0, 3.0, 4.0- , 0.0, 2.0, 4.0, 6.0, 8.0]@--Hilbert matrix of order N:--@hilb n = buildMatrix n n (\\(i,j)->1/(fromIntegral i + fromIntegral j +1))@---}-buildMatrix :: Element a => Int -> Int -> ((Int, Int) -> a) -> Matrix a-buildMatrix rc cc f =- fromLists $ map (map f)- $ map (\ ri -> map (\ ci -> (ri, ci)) [0 .. (cc - 1)]) [0 .. (rc - 1)]---------------------------------------------------------fromArray2D :: (Storable e) => Array (Int, Int) e -> Matrix e-fromArray2D m = (r><c) (elems m)- where ((r0,c0),(r1,c1)) = bounds m- r = r1-r0+1- c = c1-c0+1----- | rearranges the rows of a matrix according to the order given in a list of integers.-extractRows :: Element t => [Int] -> Matrix t -> Matrix t-extractRows l m = fromRows $ extract (toRows m) l- where extract l' is = [l'!!i |i<-is]--{- | creates matrix by repetition of a matrix a given number of rows and columns--@> repmat (ident 2) 2 3 :: Matrix Double-(4><6)- [ 1.0, 0.0, 1.0, 0.0, 1.0, 0.0- , 0.0, 1.0, 0.0, 1.0, 0.0, 1.0- , 1.0, 0.0, 1.0, 0.0, 1.0, 0.0- , 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 ]@---}-repmat :: (Element t) => Matrix t -> Int -> Int -> Matrix t-repmat m r c = fromBlocks $ splitEvery c $ replicate (r*c) m---- | A version of 'liftMatrix2' which automatically adapt matrices with a single row or column to match the dimensions of the other matrix.-liftMatrix2Auto :: (Element t, Element a, Element b) => (Vector a -> Vector b -> Vector t) -> Matrix a -> Matrix b -> Matrix t-liftMatrix2Auto f m1 m2- | compat' m1 m2 = lM f m1 m2- | ok = lM f m1' m2'- | otherwise = error $ "nonconformable matrices in liftMatrix2Auto: " ++ shSize m1 ++ ", " ++ shSize m2- where- (r1,c1) = size m1- (r2,c2) = size m2- r = max r1 r2- c = max c1 c2- r0 = min r1 r2- c0 = min c1 c2- ok = r0 == 1 || r1 == r2 && c0 == 1 || c1 == c2- m1' = conformMTo (r,c) m1- m2' = conformMTo (r,c) m2--lM f m1 m2 = reshape (max (cols m1) (cols m2)) (f (flatten m1) (flatten m2))--compat' :: Matrix a -> Matrix b -> Bool-compat' m1 m2 = s1 == (1,1) || s2 == (1,1) || s1 == s2- where- s1 = size m1- s2 = size m2----------------------------------------------------------------toBlockRows [r] m | r == rows m = [m]-toBlockRows rs m = map (reshape (cols m)) (takesV szs (flatten m))- where szs = map (* cols m) rs--toBlockCols [c] m | c == cols m = [m]-toBlockCols cs m = map trans . toBlockRows cs . trans $ m---- | Partition a matrix into blocks with the given numbers of rows and columns.--- The remaining rows and columns are discarded.-toBlocks :: (Element t) => [Int] -> [Int] -> Matrix t -> [[Matrix t]]-toBlocks rs cs m = map (toBlockCols cs) . toBlockRows rs $ m---- | Fully partition a matrix into blocks of the same size. If the dimensions are not--- a multiple of the given size the last blocks will be smaller.-toBlocksEvery :: (Element t) => Int -> Int -> Matrix t -> [[Matrix t]]-toBlocksEvery r c m = toBlocks rs cs m where- (qr,rr) = rows m `divMod` r- (qc,rc) = cols m `divMod` c- rs = replicate qr r ++ if rr > 0 then [rr] else []- cs = replicate qc c ++ if rc > 0 then [rc] else []------------------------------------------------------------------------- Given a column number and a function taking matrix indexes, returns--- a function which takes vector indexes (that can be used on the--- flattened matrix).-mk :: Int -> ((Int, Int) -> t) -> (Int -> t)-mk c g = \k -> g (divMod k c)--{- |--@ghci> mapMatrixWithIndexM_ (\\(i,j) v -> printf \"m[%.0f,%.0f] = %.f\\n\" i j v :: IO()) ((2><3)[1 :: Double ..])-m[0,0] = 1-m[0,1] = 2-m[0,2] = 3-m[1,0] = 4-m[1,1] = 5-m[1,2] = 6@--}-mapMatrixWithIndexM_- :: (Element a, Num a, Monad m) =>- ((Int, Int) -> a -> m ()) -> Matrix a -> m ()-mapMatrixWithIndexM_ g m = mapVectorWithIndexM_ (mk c g) . flatten $ m- where- c = cols m--{- |--@ghci> mapMatrixWithIndexM (\\(i,j) v -> Just $ 100*v + 10*i + j) (ident 3:: Matrix Double)-Just (3><3)- [ 100.0, 1.0, 2.0- , 10.0, 111.0, 12.0- , 20.0, 21.0, 122.0 ]@--}-mapMatrixWithIndexM- :: (Element a, Storable b, Monad m) =>- ((Int, Int) -> a -> m b) -> Matrix a -> m (Matrix b)-mapMatrixWithIndexM g m = liftM (reshape c) . mapVectorWithIndexM (mk c g) . flatten $ m - where- c = cols m--{- |-@ghci> mapMatrixWithIndex (\\(i,j) v -> 100*v + 10*i + j) (ident 3:: Matrix Double)-(3><3)- [ 100.0, 1.0, 2.0- , 10.0, 111.0, 12.0- , 20.0, 21.0, 122.0 ]@- -}-mapMatrixWithIndex- :: (Element a, Storable b) =>- ((Int, Int) -> a -> b) -> Matrix a -> Matrix b-mapMatrixWithIndex g m = reshape c . mapVectorWithIndex (mk c g) . flatten $ m- where- c = cols m--mapMatrix :: (Storable a, Storable b) => (a -> b) -> Matrix a -> Matrix b-mapMatrix f = liftMatrix (mapVector f)
@@ -1,57 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Data.Packed.Vector--- Copyright : (c) Alberto Ruiz 2009--- License : GPL------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional------ Random vectors and matrices.-----------------------------------------------------------------------------------module Data.Packed.Random (- Seed,- RandDist(..),- randomVector,- gaussianSample,- uniformSample-) where--import Numeric.GSL.Vector-import Data.Packed-import Numeric.ContainerBoot-import Numeric.LinearAlgebra.Algorithms---type Seed = Int---- | Obtains a matrix whose rows are pseudorandom samples from a multivariate--- Gaussian distribution.-gaussianSample :: Seed- -> Int -- ^ number of rows- -> Vector Double -- ^ mean vector- -> Matrix Double -- ^ covariance matrix- -> Matrix Double -- ^ result-gaussianSample seed n med cov = m where- c = dim med- meds = konst 1 n `outer` med- rs = reshape c $ randomVector seed Gaussian (c * n)- m = rs `mXm` cholSH cov `add` meds---- | Obtains a matrix whose rows are pseudorandom samples from a multivariate--- uniform distribution.-uniformSample :: Seed- -> Int -- ^ number of rows- -> [(Double,Double)] -- ^ ranges for each column- -> Matrix Double -- ^ result-uniformSample seed n rgs = m where- (as,bs) = unzip rgs- a = fromList as- cs = zipWith subtract as bs- d = dim a- dat = toRows $ reshape n $ randomVector seed Uniform (n*d)- am = konst 1 n `outer` a- m = fromColumns (zipWith scale cs dat) `add` am-
@@ -1,178 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE BangPatterns #-}--------------------------------------------------------------------------------- |--- Module : Data.Packed.ST--- Copyright : (c) Alberto Ruiz 2008--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ In-place manipulation inside the ST monad.--- See examples/inplace.hs in the distribution.-----------------------------------------------------------------------------------module Data.Packed.ST (- -- * Mutable Vectors- STVector, newVector, thawVector, freezeVector, runSTVector,- readVector, writeVector, modifyVector, liftSTVector,- -- * Mutable Matrices- STMatrix, newMatrix, thawMatrix, freezeMatrix, runSTMatrix,- readMatrix, writeMatrix, modifyMatrix, liftSTMatrix,- -- * Unsafe functions- newUndefinedVector,- unsafeReadVector, unsafeWriteVector,- unsafeThawVector, unsafeFreezeVector,- newUndefinedMatrix,- unsafeReadMatrix, unsafeWriteMatrix,- unsafeThawMatrix, unsafeFreezeMatrix-) where--import Data.Packed.Internal--import Control.Monad.ST(ST, runST)-import Foreign.Storable(Storable, peekElemOff, pokeElemOff)--#if MIN_VERSION_base(4,4,0)-import Control.Monad.ST.Unsafe(unsafeIOToST)-#else-import Control.Monad.ST(unsafeIOToST)-#endif--{-# INLINE ioReadV #-}-ioReadV :: Storable t => Vector t -> Int -> IO t-ioReadV v k = unsafeWith v $ \s -> peekElemOff s k--{-# INLINE ioWriteV #-}-ioWriteV :: Storable t => Vector t -> Int -> t -> IO ()-ioWriteV v k x = unsafeWith v $ \s -> pokeElemOff s k x--newtype STVector s t = STVector (Vector t)--thawVector :: Storable t => Vector t -> ST s (STVector s t)-thawVector = unsafeIOToST . fmap STVector . cloneVector--unsafeThawVector :: Storable t => Vector t -> ST s (STVector s t)-unsafeThawVector = unsafeIOToST . return . STVector--runSTVector :: Storable t => (forall s . ST s (STVector s t)) -> Vector t-runSTVector st = runST (st >>= unsafeFreezeVector)--{-# INLINE unsafeReadVector #-}-unsafeReadVector :: Storable t => STVector s t -> Int -> ST s t-unsafeReadVector (STVector x) = unsafeIOToST . ioReadV x--{-# INLINE unsafeWriteVector #-}-unsafeWriteVector :: Storable t => STVector s t -> Int -> t -> ST s ()-unsafeWriteVector (STVector x) k = unsafeIOToST . ioWriteV x k--{-# INLINE modifyVector #-}-modifyVector :: (Storable t) => STVector s t -> Int -> (t -> t) -> ST s ()-modifyVector x k f = readVector x k >>= return . f >>= unsafeWriteVector x k--liftSTVector :: (Storable t) => (Vector t -> a) -> STVector s1 t -> ST s2 a-liftSTVector f (STVector x) = unsafeIOToST . fmap f . cloneVector $ x--freezeVector :: (Storable t) => STVector s1 t -> ST s2 (Vector t)-freezeVector v = liftSTVector id v--unsafeFreezeVector :: (Storable t) => STVector s1 t -> ST s2 (Vector t)-unsafeFreezeVector (STVector x) = unsafeIOToST . return $ x--{-# INLINE safeIndexV #-}-safeIndexV f (STVector v) k- | k < 0 || k>= dim v = error $ "out of range error in vector (dim="- ++show (dim v)++", pos="++show k++")"- | otherwise = f (STVector v) k--{-# INLINE readVector #-}-readVector :: Storable t => STVector s t -> Int -> ST s t-readVector = safeIndexV unsafeReadVector--{-# INLINE writeVector #-}-writeVector :: Storable t => STVector s t -> Int -> t -> ST s ()-writeVector = safeIndexV unsafeWriteVector--newUndefinedVector :: Storable t => Int -> ST s (STVector s t)-newUndefinedVector = unsafeIOToST . fmap STVector . createVector--{-# INLINE newVector #-}-newVector :: Storable t => t -> Int -> ST s (STVector s t)-newVector x n = do- v <- newUndefinedVector n- let go (-1) = return v- go !k = unsafeWriteVector v k x >> go (k-1 :: Int)- go (n-1)-----------------------------------------------------------------------------{-# INLINE ioReadM #-}-ioReadM :: Storable t => Matrix t -> Int -> Int -> IO t-ioReadM (Matrix _ nc cv RowMajor) r c = ioReadV cv (r*nc+c)-ioReadM (Matrix nr _ fv ColumnMajor) r c = ioReadV fv (c*nr+r)--{-# INLINE ioWriteM #-}-ioWriteM :: Storable t => Matrix t -> Int -> Int -> t -> IO ()-ioWriteM (Matrix _ nc cv RowMajor) r c val = ioWriteV cv (r*nc+c) val-ioWriteM (Matrix nr _ fv ColumnMajor) r c val = ioWriteV fv (c*nr+r) val--newtype STMatrix s t = STMatrix (Matrix t)--thawMatrix :: Storable t => Matrix t -> ST s (STMatrix s t)-thawMatrix = unsafeIOToST . fmap STMatrix . cloneMatrix--unsafeThawMatrix :: Storable t => Matrix t -> ST s (STMatrix s t)-unsafeThawMatrix = unsafeIOToST . return . STMatrix--runSTMatrix :: Storable t => (forall s . ST s (STMatrix s t)) -> Matrix t-runSTMatrix st = runST (st >>= unsafeFreezeMatrix)--{-# INLINE unsafeReadMatrix #-}-unsafeReadMatrix :: Storable t => STMatrix s t -> Int -> Int -> ST s t-unsafeReadMatrix (STMatrix x) r = unsafeIOToST . ioReadM x r--{-# INLINE unsafeWriteMatrix #-}-unsafeWriteMatrix :: Storable t => STMatrix s t -> Int -> Int -> t -> ST s ()-unsafeWriteMatrix (STMatrix x) r c = unsafeIOToST . ioWriteM x r c--{-# INLINE modifyMatrix #-}-modifyMatrix :: (Storable t) => STMatrix s t -> Int -> Int -> (t -> t) -> ST s ()-modifyMatrix x r c f = readMatrix x r c >>= return . f >>= unsafeWriteMatrix x r c--liftSTMatrix :: (Storable t) => (Matrix t -> a) -> STMatrix s1 t -> ST s2 a-liftSTMatrix f (STMatrix x) = unsafeIOToST . fmap f . cloneMatrix $ x--unsafeFreezeMatrix :: (Storable t) => STMatrix s1 t -> ST s2 (Matrix t)-unsafeFreezeMatrix (STMatrix x) = unsafeIOToST . return $ x--freezeMatrix :: (Storable t) => STMatrix s1 t -> ST s2 (Matrix t)-freezeMatrix m = liftSTMatrix id m--cloneMatrix (Matrix r c d o) = cloneVector d >>= return . (\d' -> Matrix r c d' o)--{-# INLINE safeIndexM #-}-safeIndexM f (STMatrix m) r c- | r<0 || r>=rows m ||- c<0 || c>=cols m = error $ "out of range error in matrix (size="- ++show (rows m,cols m)++", pos="++show (r,c)++")"- | otherwise = f (STMatrix m) r c--{-# INLINE readMatrix #-}-readMatrix :: Storable t => STMatrix s t -> Int -> Int -> ST s t-readMatrix = safeIndexM unsafeReadMatrix--{-# INLINE writeMatrix #-}-writeMatrix :: Storable t => STMatrix s t -> Int -> Int -> t -> ST s ()-writeMatrix = safeIndexM unsafeWriteMatrix--newUndefinedMatrix :: Storable t => MatrixOrder -> Int -> Int -> ST s (STMatrix s t)-newUndefinedMatrix ord r c = unsafeIOToST $ fmap STMatrix $ createMatrix ord r c--{-# NOINLINE newMatrix #-}-newMatrix :: Storable t => t -> Int -> Int -> ST s (STMatrix s t)-newMatrix v r c = unsafeThawMatrix $ reshape c $ runSTVector $ newVector v (r*c)
@@ -1,90 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module : Data.Packed.Vector--- Copyright : (c) Alberto Ruiz 2007-10--- License : GPL------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional------ 1D arrays suitable for numeric computations using external libraries.------ This module provides basic functions for manipulation of structure.-----------------------------------------------------------------------------------module Data.Packed.Vector (- Vector,- fromList, (|>), toList, buildVector,- dim, (@>),- subVector, takesV, join,- mapVector, mapVectorWithIndex, zipVector, zipVectorWith, unzipVector, unzipVectorWith,- mapVectorM, mapVectorM_, mapVectorWithIndexM, mapVectorWithIndexM_,- foldLoop, foldVector, foldVectorG, foldVectorWithIndex-) where--import Data.Packed.Internal.Vector-import Foreign.Storable-----------------------------------------------------------------------#ifdef BINARY--import Data.Binary-import Control.Monad(replicateM)---- a 64K cache, with a Double taking 13 bytes in Bytestring,--- implies a chunk size of 5041-chunk :: Int-chunk = 5000--chunks :: Int -> [Int]-chunks d = let c = d `div` chunk- m = d `mod` chunk- in if m /= 0 then reverse (m:(replicate c chunk)) else (replicate c chunk) --putVector v = do- let d = dim v- mapM_ (\i -> put $ v @> i) [0..(d-1)]--getVector d = do- xs <- replicateM d get- return $! fromList xs--instance (Binary a, Storable a) => Binary (Vector a) where- put v = do- let d = dim v- put d- mapM_ putVector $! takesV (chunks d) v- get = do- d <- get- vs <- mapM getVector $ chunks d- return $! join vs--#endif-----------------------------------------------------------------------{- | creates a Vector of the specified length using the supplied function to- to map the index to the value at that index.--@> buildVector 4 fromIntegral-4 |> [0.0,1.0,2.0,3.0]@---}-buildVector :: Storable a => Int -> (Int -> a) -> Vector a-buildVector len f =- fromList $ map f [0 .. (len - 1)]----- | zip for Vectors-zipVector :: (Storable a, Storable b, Storable (a,b)) => Vector a -> Vector b -> Vector (a,b)-zipVector = zipVectorWith (,)---- | unzip for Vectors-unzipVector :: (Storable a, Storable b, Storable (a,b)) => Vector (a,b) -> (Vector a,Vector b)-unzipVector = unzipVectorWith id---------------------------------------------------------------------
@@ -1,183 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Graphics.Plot--- Copyright : (c) Alberto Ruiz 2005-8--- License : GPL-style------ Maintainer : Alberto Ruiz (aruiz at um dot es)--- Stability : provisional--- Portability : uses gnuplot and ImageMagick------ This module is deprecated. It can be replaced by improved drawing tools--- available in the plot\\plot-gtk packages by Vivian McPhail or Gnuplot by Henning Thielemann.--------------------------------------------------------------------------------module Graphics.Plot(-- mplot,-- plot, parametricPlot, -- splot, mesh, meshdom,-- matrixToPGM, imshow,-- gnuplotX, gnuplotpdf, gnuplotWin--) where--import Numeric.Container-import Data.List(intersperse)-import System.Process (system)---- | From vectors x and y, it generates a pair of matrices to be used as x and y arguments for matrix functions.-meshdom :: Vector Double -> Vector Double -> (Matrix Double , Matrix Double)-meshdom r1 r2 = (outer r1 (constant 1 (dim r2)), outer (constant 1 (dim r1)) r2)---{- | Draws a 3D surface representation of a real matrix.--> > mesh $ build (10,10) (\\i j -> i + (j-5)^2)--In certain versions you can interactively rotate the graphic using the mouse.---}-mesh :: Matrix Double -> IO ()-mesh m = gnuplotX (command++dat) where- command = "splot "++datafollows++" matrix with lines\n"- dat = prep $ toLists m--{- | Draws the surface represented by the function f in the desired ranges and number of points, internally using 'mesh'.--> > let f x y = cos (x + y) -> > splot f (0,pi) (0,2*pi) 50 ---}-splot :: (Matrix Double->Matrix Double->Matrix Double) -> (Double,Double) -> (Double,Double) -> Int -> IO () -splot f rx ry n = mesh z where- (x,y) = meshdom (linspace n rx) (linspace n ry)- z = f x y--{- | plots several vectors against the first one --> > let t = linspace 100 (-3,3) in mplot [t, sin t, exp (-t^2)]---}-mplot :: [Vector Double] -> IO ()-mplot m = gnuplotX (commands++dats) where- commands = if length m == 1 then command1 else commandmore- command1 = "plot "++datafollows++" with lines\n" ++ dat- commandmore = "plot " ++ plots ++ "\n"- plots = concat $ intersperse ", " (map cmd [2 .. length m])- cmd k = datafollows++" using 1:"++show k++" with lines"- dat = prep $ toLists $ fromColumns m- dats = concat (replicate (length m-1) dat)---{- | Draws a list of functions over a desired range and with a desired number of points --> > plot [sin, cos, sin.(3*)] (0,2*pi) 1000---}-plot :: [Vector Double->Vector Double] -> (Double,Double) -> Int -> IO ()-plot fs rx n = mplot (x: mapf fs x)- where x = linspace n rx- mapf gs y = map ($ y) gs--{- | Draws a parametric curve. For instance, to draw a spiral we can do something like:--> > parametricPlot (\t->(t * sin t, t * cos t)) (0,10*pi) 1000---}-parametricPlot :: (Vector Double->(Vector Double,Vector Double)) -> (Double, Double) -> Int -> IO ()-parametricPlot f rt n = mplot [fx, fy]- where t = linspace n rt- (fx,fy) = f t----- | writes a matrix to pgm image file-matrixToPGM :: Matrix Double -> String-matrixToPGM m = header ++ unlines (map unwords ll) where- c = cols m- r = rows m- header = "P2 "++show c++" "++show r++" "++show (round maxgray :: Int)++"\n"- maxgray = 255.0- maxval = maxElement m- minval = minElement m- scale' = if maxval == minval- then 0.0- else maxgray / (maxval - minval)- f x = show ( round ( scale' *(x - minval) ) :: Int )- ll = map (map f) (toLists m)---- | imshow shows a representation of a matrix as a gray level image using ImageMagick's display.-imshow :: Matrix Double -> IO ()-imshow m = do- _ <- system $ "echo \""++ matrixToPGM m ++"\"| display -antialias -resize 300 - &"- return ()--------------------------------------------------------gnuplotX :: String -> IO ()-gnuplotX command = do { _ <- system cmdstr; return()} where- cmdstr = "echo \""++command++"\" | gnuplot -persist"--datafollows = "\\\"-\\\""--prep = (++"e\n\n") . unlines . map (unwords . map show)---gnuplotpdf :: String -> String -> [([[Double]], String)] -> IO ()-gnuplotpdf title command ds = gnuplot (prelude ++ command ++" "++ draw) >> postproc where- prelude = "set terminal epslatex color; set output '"++title++".tex';"- (dats,defs) = unzip ds- draw = concat (intersperse ", " (map ("\"-\" "++) defs)) ++ "\n" ++- concatMap pr dats- postproc = do- _ <- system $ "epstopdf "++title++".eps"- mklatex- _ <- system $ "pdflatex "++title++"aux.tex > /dev/null"- _ <- system $ "pdfcrop "++title++"aux.pdf > /dev/null"- _ <- system $ "mv "++title++"aux-crop.pdf "++title++".pdf"- _ <- system $ "rm "++title++"aux.* "++title++".eps "++title++".tex"- return ()-- mklatex = writeFile (title++"aux.tex") $- "\\documentclass{article}\n"++- "\\usepackage{graphics}\n"++- "\\usepackage{nopageno}\n"++- "\\usepackage{txfonts}\n"++- "\\renewcommand{\\familydefault}{phv}\n"++- "\\usepackage[usenames]{color}\n"++-- "\\begin{document}\n"++-- "\\begin{center}\n"++- " \\input{./"++title++".tex}\n"++- "\\end{center}\n"++-- "\\end{document}"-- pr = (++"e\n") . unlines . map (unwords . map show)-- gnuplot cmd = do- writeFile "gnuplotcommand" cmd- _ <- system "gnuplot gnuplotcommand"- _ <- system "rm gnuplotcommand"- return ()--gnuplotWin :: String -> String -> [([[Double]], String)] -> IO ()-gnuplotWin title command ds = gnuplot (prelude ++ command ++" "++ draw) where- (dats,defs) = unzip ds- draw = concat (intersperse ", " (map ("\"-\" "++) defs)) ++ "\n" ++- concatMap pr dats-- pr = (++"e\n") . unlines . map (unwords . map show)-- prelude = "set title \""++title++"\";"-- gnuplot cmd = do- writeFile "gnuplotcommand" cmd- _ <- system "gnuplot -persist gnuplotcommand"- _ <- system "rm gnuplotcommand"- return ()
@@ -1,140 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Numeric.Chain--- Copyright : (c) Vivian McPhail 2010--- License : GPL-style------ Maintainer : Vivian McPhail <haskell.vivian.mcphail <at> gmail.com>--- Stability : provisional--- Portability : portable------ optimisation of association order for chains of matrix multiplication-----------------------------------------------------------------------------------module Numeric.Chain (- optimiseMult,- ) where--import Data.Maybe--import Data.Packed.Matrix-import Numeric.ContainerBoot--import qualified Data.Array.IArray as A--------------------------------------------------------------------------------{- | - Provide optimal association order for a chain of matrix multiplications - and apply the multiplications.-- The algorithm is the well-known O(n\^3) dynamic programming algorithm- that builds a pyramid of optimal associations.--> m1, m2, m3, m4 :: Matrix Double-> m1 = (10><15) [1..]-> m2 = (15><20) [1..]-> m3 = (20><5) [1..]-> m4 = (5><10) [1..]--> >>> optimiseMult [m1,m2,m3,m4]--will perform @((m1 `multiply` (m2 `multiply` m3)) `multiply` m4)@--The naive left-to-right multiplication would take @4500@ scalar multiplications-whereas the optimised version performs @2750@ scalar multiplications. The complexity-in this case is 32 (= 4^3/2) * (2 comparisons, 3 scalar multiplications, 3 scalar additions,-5 lookups, 2 updates) + a constant (= three table allocations)--}-optimiseMult :: Product t => [Matrix t] -> Matrix t-optimiseMult = chain---------------------------------------------------------------------------------type Matrices a = A.Array Int (Matrix a)-type Sizes = A.Array Int (Int,Int)-type Cost = A.Array Int (A.Array Int (Maybe Int))-type Indexes = A.Array Int (A.Array Int (Maybe ((Int,Int),(Int,Int))))--update :: A.Array Int (A.Array Int a) -> (Int,Int) -> a -> A.Array Int (A.Array Int a)-update a (r,c) e = a A.// [(r,(a A.! r) A.// [(c,e)])]--newWorkSpaceCost :: Int -> A.Array Int (A.Array Int (Maybe Int))-newWorkSpaceCost n = A.array (1,n) $ map (\i -> (i, subArray i)) [1..n]- where subArray i = A.listArray (1,i) (repeat Nothing)--newWorkSpaceIndexes :: Int -> A.Array Int (A.Array Int (Maybe ((Int,Int),(Int,Int))))-newWorkSpaceIndexes n = A.array (1,n) $ map (\i -> (i, subArray i)) [1..n]- where subArray i = A.listArray (1,i) (repeat Nothing)--matricesToSizes :: [Matrix a] -> Sizes-matricesToSizes ms = A.listArray (1,length ms) $ map (\m -> (rows m,cols m)) ms--chain :: Product a => [Matrix a] -> Matrix a-chain [] = error "chain: zero matrices to multiply"-chain [m] = m-chain [ml,mr] = ml `multiply` mr-chain ms = let ln = length ms- ma = A.listArray (1,ln) ms- mz = matricesToSizes ms- i = chain_cost mz- in chain_paren (ln,ln) i ma--chain_cost :: Sizes -> Indexes-chain_cost mz = let (_,u) = A.bounds mz- cost = newWorkSpaceCost u- ixes = newWorkSpaceIndexes u- (_,_,i) = foldl chain_cost' (mz,cost,ixes) (order u)- in i--chain_cost' :: (Sizes,Cost,Indexes) -> (Int,Int) -> (Sizes,Cost,Indexes)-chain_cost' sci@(mz,cost,ixes) (r,c) - | c == 1 = let cost' = update cost (r,c) (Just 0)- ixes' = update ixes (r,c) (Just ((r,c),(r,c)))- in (mz,cost',ixes')- | otherwise = minimum_cost sci (r,c)--minimum_cost :: (Sizes,Cost,Indexes) -> (Int,Int) -> (Sizes,Cost,Indexes)-minimum_cost sci fu = foldl (smaller_cost fu) sci (fulcrum_order fu)--smaller_cost :: (Int,Int) -> (Sizes,Cost,Indexes) -> ((Int,Int),(Int,Int)) -> (Sizes,Cost,Indexes)-smaller_cost (r,c) (mz,cost,ixes) ix@((lr,lc),(rr,rc)) = let op_cost = fromJust ((cost A.! lr) A.! lc)- + fromJust ((cost A.! rr) A.! rc)- + fst (mz A.! (lr-lc+1))- * snd (mz A.! lc)- * snd (mz A.! rr)- cost' = (cost A.! r) A.! c- in case cost' of- Nothing -> let cost'' = update cost (r,c) (Just op_cost)- ixes'' = update ixes (r,c) (Just ix)- in (mz,cost'',ixes'')- Just ct -> if op_cost < ct then- let cost'' = update cost (r,c) (Just op_cost)- ixes'' = update ixes (r,c) (Just ix)- in (mz,cost'',ixes'')- else (mz,cost,ixes)- --fulcrum_order (r,c) = let fs' = zip (repeat r) [1..(c-1)]- in map (partner (r,c)) fs'--partner (r,c) (a,b) = ((r-b, c-b), (a,b))--order 0 = []-order n = order (n-1) ++ zip (repeat n) [1..n]--chain_paren :: Product a => (Int,Int) -> Indexes -> Matrices a -> Matrix a-chain_paren (r,c) ixes ma = let ((lr,lc),(rr,rc)) = fromJust $ (ixes A.! r) A.! c- in if lr == rr && lc == rc then (ma A.! lr)- else (chain_paren (lr,lc) ixes ma) `multiply` (chain_paren (rr,rc) ixes ma) ------------------------------------------------------------------------------{- TESTS -}---- optimal association is ((m1*(m2*m3))*m4)-m1, m2, m3, m4 :: Matrix Double-m1 = (10><15) [1..]-m2 = (15><20) [1..]-m3 = (20><5) [1..]-m4 = (5><10) [1..]
@@ -1,145 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE UndecidableInstances #-}---------------------------------------------------------------------------------- |--- Module : Numeric.Container--- Copyright : (c) Alberto Ruiz 2010--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Basic numeric operations on 'Vector' and 'Matrix', including conversion routines.------ The 'Container' class is used to define optimized generic functions which work--- on 'Vector' and 'Matrix' with real or complex elements.------ Some of these functions are also available in the instances of the standard--- numeric Haskell classes provided by "Numeric.LinearAlgebra".-----------------------------------------------------------------------------------module Numeric.Container (- -- * Basic functions- module Data.Packed,- constant, linspace,- diag, ident,- ctrans,- -- * Generic operations- Container(..),- -- * Matrix product- Product(..),- optimiseMult,- mXm,mXv,vXm,(<.>),Mul(..),LSDiv(..),- outer, kronecker,- -- * Random numbers- RandDist(..),- randomVector,- gaussianSample,- uniformSample,- meanCov,- -- * Element conversion- Convert(..),- Complexable(),- RealElement(),-- RealOf, ComplexOf, SingleOf, DoubleOf,-- IndexOf,- module Data.Complex,- -- * Input / Output- dispf, disps, dispcf, vecdisp, latexFormat, format,- loadMatrix, saveMatrix, fromFile, fileDimensions,- readMatrix,- fscanfVector, fprintfVector, freadVector, fwriteVector,- -- * Experimental- build', konst'-) where--import Data.Packed-import Data.Packed.Internal(constantD)-import Numeric.ContainerBoot-import Numeric.Chain-import Numeric.IO-import Data.Complex-import Numeric.LinearAlgebra.Algorithms(Field,linearSolveSVD)-import Data.Packed.Random----------------------------------------------------------------------{- | creates a vector with a given number of equal components:--@> constant 2 7-7 |> [2.0,2.0,2.0,2.0,2.0,2.0,2.0]@--}-constant :: Element a => a -> Int -> Vector a--- constant x n = runSTVector (newVector x n)-constant = constantD-- about 2x faster--{- | Creates a real vector containing a range of values:--@\> linspace 5 (-3,7)-5 |> [-3.0,-0.5,2.0,4.5,7.0]@--Logarithmic spacing can be defined as follows:--@logspace n (a,b) = 10 ** linspace n (a,b)@--}-linspace :: (Enum e, Container Vector e) => Int -> (e, e) -> Vector e-linspace n (a,b) = addConstant a $ scale s $ fromList [0 .. fromIntegral n-1]- where s = (b-a)/fromIntegral (n-1)---- | Dot product: @u \<.\> v = dot u v@-(<.>) :: Product t => Vector t -> Vector t -> t-infixl 7 <.>-(<.>) = dot--------------------------------------------------------------class Mul a b c | a b -> c where- infixl 7 <>- -- | Matrix-matrix, matrix-vector, and vector-matrix products.- (<>) :: Product t => a t -> b t -> c t--instance Mul Matrix Matrix Matrix where- (<>) = mXm--instance Mul Matrix Vector Vector where- (<>) m v = flatten $ m <> asColumn v--instance Mul Vector Matrix Vector where- (<>) v m = flatten $ asRow v <> m------------------------------------------------------------class LSDiv b c | b -> c, c->b where- infixl 7 <\>- -- | least squares solution of a linear system, similar to the \\ operator of Matlab\/Octave (based on linearSolveSVD)- (<\>) :: Field t => Matrix t -> b t -> c t--instance LSDiv Vector Vector where- m <\> v = flatten (linearSolveSVD m (reshape 1 v))--instance LSDiv Matrix Matrix where- (<\>) = linearSolveSVD-------------------------------------------------------------- | Compute mean vector and covariance matrix of the rows of a matrix.-meanCov :: Matrix Double -> (Vector Double, Matrix Double)-meanCov x = (med,cov) where- r = rows x- k = 1 / fromIntegral r- med = konst k r `vXm` x- meds = konst 1 r `outer` med- xc = x `sub` meds- cov = scale (recip (fromIntegral (r-1))) (trans xc `mXm` xc)-
@@ -1,603 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}---------------------------------------------------------------------------------- |--- Module : Numeric.ContainerBoot--- Copyright : (c) Alberto Ruiz 2010--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Module to avoid cyclyc dependencies.-----------------------------------------------------------------------------------module Numeric.ContainerBoot (- -- * Basic functions- ident, diag, ctrans,- -- * Generic operations- Container(..),- -- * Matrix product and related functions- Product(..),- mXm,mXv,vXm,- outer, kronecker,- -- * Element conversion- Convert(..),- Complexable(),- RealElement(),-- RealOf, ComplexOf, SingleOf, DoubleOf,-- IndexOf,- module Data.Complex,- -- * Experimental- build', konst'-) where--import Data.Packed-import Data.Packed.ST as ST-import Numeric.Conversion-import Data.Packed.Internal-import Numeric.GSL.Vector-import Data.Complex-import Control.Monad(ap)--import Numeric.LinearAlgebra.LAPACK(multiplyR,multiplyC,multiplyF,multiplyQ)-----------------------------------------------------------------------type family IndexOf (c :: * -> *)--type instance IndexOf Vector = Int-type instance IndexOf Matrix = (Int,Int)--type family ArgOf (c :: * -> *) a--type instance ArgOf Vector a = a -> a-type instance ArgOf Matrix a = a -> a -> a------------------------------------------------------------------------- | Basic element-by-element functions for numeric containers-class (Complexable c, Fractional e, Element e) => Container c e where- -- | create a structure with a single element- scalar :: e -> c e- -- | complex conjugate- conj :: c e -> c e- scale :: e -> c e -> c e- -- | scale the element by element reciprocal of the object:- --- -- @scaleRecip 2 (fromList [5,i]) == 2 |> [0.4 :+ 0.0,0.0 :+ (-2.0)]@- scaleRecip :: e -> c e -> c e- addConstant :: e -> c e -> c e- add :: c e -> c e -> c e- sub :: c e -> c e -> c e- -- | element by element multiplication- mul :: c e -> c e -> c e- -- | element by element division- divide :: c e -> c e -> c e- equal :: c e -> c e -> Bool- --- -- element by element inverse tangent- arctan2 :: c e -> c e -> c e- --- -- | cannot implement instance Functor because of Element class constraint- cmap :: (Element b) => (e -> b) -> c e -> c b- -- | constant structure of given size- konst :: e -> IndexOf c -> c e- -- | create a structure using a function- --- -- Hilbert matrix of order N:- --- -- @hilb n = build (n,n) (\\i j -> 1/(i+j+1))@- build :: IndexOf c -> (ArgOf c e) -> c e- --build :: BoundsOf f -> f -> (ContainerOf f) e- --- -- | indexing function- atIndex :: c e -> IndexOf c -> e- -- | index of min element- minIndex :: c e -> IndexOf c- -- | index of max element- maxIndex :: c e -> IndexOf c- -- | value of min element- minElement :: c e -> e- -- | value of max element- maxElement :: c e -> e- -- the C functions sumX/prodX are twice as fast as using foldVector- -- | the sum of elements (faster than using @fold@)- sumElements :: c e -> e- -- | the product of elements (faster than using @fold@)- prodElements :: c e -> e-- -- | A more efficient implementation of @cmap (\\x -> if x>0 then 1 else 0)@- --- -- @> step $ linspace 5 (-1,1::Double)- -- 5 |> [0.0,0.0,0.0,1.0,1.0]@- - step :: RealElement e => c e -> c e-- -- | Element by element version of @case compare a b of {LT -> l; EQ -> e; GT -> g}@.- --- -- Arguments with any dimension = 1 are automatically expanded: - --- -- @> cond ((1>\<4)[1..]) ((3>\<1)[1..]) 0 100 ((3>\<4)[1..]) :: Matrix Double- -- (3><4)- -- [ 100.0, 2.0, 3.0, 4.0- -- , 0.0, 100.0, 7.0, 8.0- -- , 0.0, 0.0, 100.0, 12.0 ]@- - cond :: RealElement e - => c e -- ^ a- -> c e -- ^ b- -> c e -- ^ l - -> c e -- ^ e- -> c e -- ^ g- -> c e -- ^ result-- -- | Find index of elements which satisfy a predicate- --- -- @> find (>0) (ident 3 :: Matrix Double)- -- [(0,0),(1,1),(2,2)]@-- find :: (e -> Bool) -> c e -> [IndexOf c]-- -- | Create a structure from an association list- --- -- @> assoc 5 0 [(2,7),(1,3)] :: Vector Double- -- 5 |> [0.0,3.0,7.0,0.0,0.0]@- - assoc :: IndexOf c -- ^ size- -> e -- ^ default value- -> [(IndexOf c, e)] -- ^ association list- -> c e -- ^ result-- -- | Modify a structure using an update function- --- -- @> accum (ident 5) (+) [((1,1),5),((0,3),3)] :: Matrix Double- -- (5><5)- -- [ 1.0, 0.0, 0.0, 3.0, 0.0- -- , 0.0, 6.0, 0.0, 0.0, 0.0- -- , 0.0, 0.0, 1.0, 0.0, 0.0- -- , 0.0, 0.0, 0.0, 1.0, 0.0- -- , 0.0, 0.0, 0.0, 0.0, 1.0 ]@- - accum :: c e -- ^ initial structure- -> (e -> e -> e) -- ^ update function- -> [(IndexOf c, e)] -- ^ association list- -> c e -- ^ result------------------------------------------------------------------------------instance Container Vector Float where- scale = vectorMapValF Scale- scaleRecip = vectorMapValF Recip- addConstant = vectorMapValF AddConstant- add = vectorZipF Add- sub = vectorZipF Sub- mul = vectorZipF Mul- divide = vectorZipF Div- equal u v = dim u == dim v && maxElement (vectorMapF Abs (sub u v)) == 0.0- arctan2 = vectorZipF ATan2- scalar x = fromList [x]- konst = constantD- build = buildV- conj = id- cmap = mapVector- atIndex = (@>)- minIndex = round . toScalarF MinIdx- maxIndex = round . toScalarF MaxIdx- minElement = toScalarF Min- maxElement = toScalarF Max- sumElements = sumF- prodElements = prodF- step = stepF- find = findV- assoc = assocV- accum = accumV- cond = condV condF--instance Container Vector Double where- scale = vectorMapValR Scale- scaleRecip = vectorMapValR Recip- addConstant = vectorMapValR AddConstant- add = vectorZipR Add- sub = vectorZipR Sub- mul = vectorZipR Mul- divide = vectorZipR Div- equal u v = dim u == dim v && maxElement (vectorMapR Abs (sub u v)) == 0.0- arctan2 = vectorZipR ATan2- scalar x = fromList [x]- konst = constantD- build = buildV- conj = id- cmap = mapVector- atIndex = (@>)- minIndex = round . toScalarR MinIdx- maxIndex = round . toScalarR MaxIdx- minElement = toScalarR Min- maxElement = toScalarR Max- sumElements = sumR- prodElements = prodR- step = stepD- find = findV- assoc = assocV- accum = accumV- cond = condV condD--instance Container Vector (Complex Double) where- scale = vectorMapValC Scale- scaleRecip = vectorMapValC Recip- addConstant = vectorMapValC AddConstant- add = vectorZipC Add- sub = vectorZipC Sub- mul = vectorZipC Mul- divide = vectorZipC Div- equal u v = dim u == dim v && maxElement (mapVector magnitude (sub u v)) == 0.0- arctan2 = vectorZipC ATan2- scalar x = fromList [x]- konst = constantD- build = buildV- conj = conjugateC- cmap = mapVector- atIndex = (@>)- minIndex = minIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)- maxIndex = maxIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)- minElement = ap (@>) minIndex- maxElement = ap (@>) maxIndex- sumElements = sumC- prodElements = prodC- step = undefined -- cannot match- find = findV- assoc = assocV- accum = accumV- cond = undefined -- cannot match--instance Container Vector (Complex Float) where- scale = vectorMapValQ Scale- scaleRecip = vectorMapValQ Recip- addConstant = vectorMapValQ AddConstant- add = vectorZipQ Add- sub = vectorZipQ Sub- mul = vectorZipQ Mul- divide = vectorZipQ Div- equal u v = dim u == dim v && maxElement (mapVector magnitude (sub u v)) == 0.0- arctan2 = vectorZipQ ATan2- scalar x = fromList [x]- konst = constantD- build = buildV- conj = conjugateQ- cmap = mapVector- atIndex = (@>)- minIndex = minIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)- maxIndex = maxIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)- minElement = ap (@>) minIndex- maxElement = ap (@>) maxIndex- sumElements = sumQ- prodElements = prodQ- step = undefined -- cannot match- find = findV- assoc = assocV- accum = accumV- cond = undefined -- cannot match-------------------------------------------------------------------instance (Container Vector a) => Container Matrix a where- scale x = liftMatrix (scale x)- scaleRecip x = liftMatrix (scaleRecip x)- addConstant x = liftMatrix (addConstant x)- add = liftMatrix2 add- sub = liftMatrix2 sub- mul = liftMatrix2 mul- divide = liftMatrix2 divide- equal a b = cols a == cols b && flatten a `equal` flatten b- arctan2 = liftMatrix2 arctan2- scalar x = (1><1) [x]- konst v (r,c) = reshape c (konst v (r*c))- build = buildM- conj = liftMatrix conj- cmap f = liftMatrix (mapVector f)- atIndex = (@@>)- minIndex m = let (r,c) = (rows m,cols m)- i = (minIndex $ flatten m)- in (i `div` c,i `mod` c)- maxIndex m = let (r,c) = (rows m,cols m)- i = (maxIndex $ flatten m)- in (i `div` c,i `mod` c)- minElement = ap (@@>) minIndex- maxElement = ap (@@>) maxIndex- sumElements = sumElements . flatten- prodElements = prodElements . flatten- step = liftMatrix step- find = findM- assoc = assocM- accum = accumM- cond = condM---------------------------------------------------------- | Matrix product and related functions-class Element e => Product e where- -- | matrix product- multiply :: Matrix e -> Matrix e -> Matrix e- -- | dot (inner) product- dot :: Vector e -> Vector e -> e- -- | sum of absolute value of elements (differs in complex case from @norm1@)- absSum :: Vector e -> RealOf e- -- | sum of absolute value of elements- norm1 :: Vector e -> RealOf e- -- | euclidean norm- norm2 :: Vector e -> RealOf e- -- | element of maximum magnitude- normInf :: Vector e -> RealOf e--instance Product Float where- norm2 = toScalarF Norm2- absSum = toScalarF AbsSum- dot = dotF- norm1 = toScalarF AbsSum- normInf = maxElement . vectorMapF Abs- multiply = multiplyF--instance Product Double where- norm2 = toScalarR Norm2- absSum = toScalarR AbsSum- dot = dotR- norm1 = toScalarR AbsSum- normInf = maxElement . vectorMapR Abs- multiply = multiplyR--instance Product (Complex Float) where- norm2 = toScalarQ Norm2- absSum = toScalarQ AbsSum- dot = dotQ- norm1 = sumElements . fst . fromComplex . vectorMapQ Abs- normInf = maxElement . fst . fromComplex . vectorMapQ Abs- multiply = multiplyQ--instance Product (Complex Double) where- norm2 = toScalarC Norm2- absSum = toScalarC AbsSum- dot = dotC- norm1 = sumElements . fst . fromComplex . vectorMapC Abs- normInf = maxElement . fst . fromComplex . vectorMapC Abs- multiply = multiplyC---------------------------------------------------------------- synonym for matrix product-mXm :: Product t => Matrix t -> Matrix t -> Matrix t-mXm = multiply---- matrix - vector product-mXv :: Product t => Matrix t -> Vector t -> Vector t-mXv m v = flatten $ m `mXm` (asColumn v)---- vector - matrix product-vXm :: Product t => Vector t -> Matrix t -> Vector t-vXm v m = flatten $ (asRow v) `mXm` m--{- | Outer product of two vectors.--@\> 'fromList' [1,2,3] \`outer\` 'fromList' [5,2,3]-(3><3)- [ 5.0, 2.0, 3.0- , 10.0, 4.0, 6.0- , 15.0, 6.0, 9.0 ]@--}-outer :: (Product t) => Vector t -> Vector t -> Matrix t-outer u v = asColumn u `multiply` asRow v--{- | Kronecker product of two matrices.--@m1=(2><3)- [ 1.0, 2.0, 0.0- , 0.0, -1.0, 3.0 ]-m2=(4><3)- [ 1.0, 2.0, 3.0- , 4.0, 5.0, 6.0- , 7.0, 8.0, 9.0- , 10.0, 11.0, 12.0 ]@--@\> kronecker m1 m2-(8><9)- [ 1.0, 2.0, 3.0, 2.0, 4.0, 6.0, 0.0, 0.0, 0.0- , 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 0.0, 0.0, 0.0- , 7.0, 8.0, 9.0, 14.0, 16.0, 18.0, 0.0, 0.0, 0.0- , 10.0, 11.0, 12.0, 20.0, 22.0, 24.0, 0.0, 0.0, 0.0- , 0.0, 0.0, 0.0, -1.0, -2.0, -3.0, 3.0, 6.0, 9.0- , 0.0, 0.0, 0.0, -4.0, -5.0, -6.0, 12.0, 15.0, 18.0- , 0.0, 0.0, 0.0, -7.0, -8.0, -9.0, 21.0, 24.0, 27.0- , 0.0, 0.0, 0.0, -10.0, -11.0, -12.0, 30.0, 33.0, 36.0 ]@--}-kronecker :: (Product t) => Matrix t -> Matrix t -> Matrix t-kronecker a b = fromBlocks- . splitEvery (cols a)- . map (reshape (cols b))- . toRows- $ flatten a `outer` flatten b------------------------------------------------------------------------class Convert t where- real :: Container c t => c (RealOf t) -> c t- complex :: Container c t => c t -> c (ComplexOf t)- single :: Container c t => c t -> c (SingleOf t)- double :: Container c t => c t -> c (DoubleOf t)- toComplex :: (Container c t, RealElement t) => (c t, c t) -> c (Complex t)- fromComplex :: (Container c t, RealElement t) => c (Complex t) -> (c t, c t)---instance Convert Double where- real = id- complex = comp'- single = single'- double = id- toComplex = toComplex'- fromComplex = fromComplex'--instance Convert Float where- real = id- complex = comp'- single = id- double = double'- toComplex = toComplex'- fromComplex = fromComplex'--instance Convert (Complex Double) where- real = comp'- complex = id- single = single'- double = id- toComplex = toComplex'- fromComplex = fromComplex'--instance Convert (Complex Float) where- real = comp'- complex = id- single = id- double = double'- toComplex = toComplex'- fromComplex = fromComplex'-----------------------------------------------------------------------type family RealOf x--type instance RealOf Double = Double-type instance RealOf (Complex Double) = Double--type instance RealOf Float = Float-type instance RealOf (Complex Float) = Float--type family ComplexOf x--type instance ComplexOf Double = Complex Double-type instance ComplexOf (Complex Double) = Complex Double--type instance ComplexOf Float = Complex Float-type instance ComplexOf (Complex Float) = Complex Float--type family SingleOf x--type instance SingleOf Double = Float-type instance SingleOf Float = Float--type instance SingleOf (Complex a) = Complex (SingleOf a)--type family DoubleOf x--type instance DoubleOf Double = Double-type instance DoubleOf Float = Double--type instance DoubleOf (Complex a) = Complex (DoubleOf a)--type family ElementOf c--type instance ElementOf (Vector a) = a-type instance ElementOf (Matrix a) = a----------------------------------------------------------------class Build f where- build' :: BoundsOf f -> f -> ContainerOf f--type family BoundsOf x--type instance BoundsOf (a->a) = Int-type instance BoundsOf (a->a->a) = (Int,Int)--type family ContainerOf x--type instance ContainerOf (a->a) = Vector a-type instance ContainerOf (a->a->a) = Matrix a--instance (Element a, Num a) => Build (a->a) where- build' = buildV--instance (Element a, Num a) => Build (a->a->a) where- build' = buildM--buildM (rc,cc) f = fromLists [ [f r c | c <- cs] | r <- rs ]- where rs = map fromIntegral [0 .. (rc-1)]- cs = map fromIntegral [0 .. (cc-1)]--buildV n f = fromList [f k | k <- ks]- where ks = map fromIntegral [0 .. (n-1)]--------------------------------------------------------- experimental--class Konst s where- konst' :: Element e => e -> s -> ContainerOf' s e--type family ContainerOf' x y--type instance ContainerOf' Int a = Vector a-type instance ContainerOf' (Int,Int) a = Matrix a--instance Konst Int where- konst' = constantD--instance Konst (Int,Int) where- konst' k (r,c) = reshape c $ konst' k (r*c)------------------------------------------------------------- | conjugate transpose-ctrans :: (Container Vector e, Element e) => Matrix e -> Matrix e-ctrans = liftMatrix conj . trans---- | Creates a square matrix with a given diagonal.-diag :: (Num a, Element a) => Vector a -> Matrix a-diag v = diagRect 0 v n n where n = dim v---- | creates the identity matrix of given dimension-ident :: (Num a, Element a) => Int -> Matrix a-ident n = diag (constantD 1 n)------------------------------------------------------------findV p x = foldVectorWithIndex g [] x where- g k z l = if p z then k:l else l--findM p x = map ((`divMod` cols x)) $ findV p (flatten x)--assocV n z xs = ST.runSTVector $ do- v <- ST.newVector z n- mapM_ (\(k,x) -> ST.writeVector v k x) xs- return v--assocM (r,c) z xs = ST.runSTMatrix $ do- m <- ST.newMatrix z r c- mapM_ (\((i,j),x) -> ST.writeMatrix m i j x) xs- return m--accumV v0 f xs = ST.runSTVector $ do- v <- ST.thawVector v0- mapM_ (\(k,x) -> ST.modifyVector v k (f x)) xs- return v--accumM m0 f xs = ST.runSTMatrix $ do- m <- ST.thawMatrix m0- mapM_ (\((i,j),x) -> ST.modifyMatrix m i j (f x)) xs- return m--------------------------------------------------------------------------condM a b l e t = reshape (cols a'') $ cond a' b' l' e' t'- where- args@(a'':_) = conformMs [a,b,l,e,t]- [a', b', l', e', t'] = map flatten args--condV f a b l e t = f a' b' l' e' t'- where- [a', b', l', e', t'] = conformVs [a,b,l,e,t]-
@@ -1,91 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE UndecidableInstances #-}---------------------------------------------------------------------------------- |--- Module : Numeric.Conversion--- Copyright : (c) Alberto Ruiz 2010--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Conversion routines-----------------------------------------------------------------------------------module Numeric.Conversion (- Complexable(..), RealElement,- module Data.Complex-) where--import Data.Packed.Internal.Vector-import Data.Packed.Internal.Matrix-import Data.Complex-import Control.Arrow((***))------------------------------------------------------------------------- | Supported single-double precision type pairs-class (Element s, Element d) => Precision s d | s -> d, d -> s where- double2FloatG :: Vector d -> Vector s- float2DoubleG :: Vector s -> Vector d--instance Precision Float Double where- double2FloatG = double2FloatV- float2DoubleG = float2DoubleV--instance Precision (Complex Float) (Complex Double) where- double2FloatG = asComplex . double2FloatV . asReal- float2DoubleG = asComplex . float2DoubleV . asReal---- | Supported real types-class (Element t, Element (Complex t), RealFloat t--- , RealOf t ~ t, RealOf (Complex t) ~ t- )- => RealElement t--instance RealElement Double-instance RealElement Float----- | Structures that may contain complex numbers-class Complexable c where- toComplex' :: (RealElement e) => (c e, c e) -> c (Complex e)- fromComplex' :: (RealElement e) => c (Complex e) -> (c e, c e)- comp' :: (RealElement e) => c e -> c (Complex e)- single' :: Precision a b => c b -> c a- double' :: Precision a b => c a -> c b---instance Complexable Vector where- toComplex' = toComplexV- fromComplex' = fromComplexV- comp' v = toComplex' (v,constantD 0 (dim v))- single' = double2FloatG- double' = float2DoubleG----- | creates a complex vector from vectors with real and imaginary parts-toComplexV :: (RealElement a) => (Vector a, Vector a) -> Vector (Complex a)-toComplexV (r,i) = asComplex $ flatten $ fromColumns [r,i]---- | the inverse of 'toComplex'-fromComplexV :: (RealElement a) => Vector (Complex a) -> (Vector a, Vector a)-fromComplexV z = (r,i) where- [r,i] = toColumns $ reshape 2 $ asReal z---instance Complexable Matrix where- toComplex' = uncurry $ liftMatrix2 $ curry toComplex'- fromComplex' z = (reshape c *** reshape c) . fromComplex' . flatten $ z- where c = cols z- comp' = liftMatrix comp'- single' = liftMatrix single'- double' = liftMatrix double'-
@@ -1,43 +0,0 @@-{- |--Module : Numeric.GSL-Copyright : (c) Alberto Ruiz 2006-7-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses -fffi and -fglasgow-exts--This module reexports all available GSL functions.--The GSL special functions are in the separate package hmatrix-special.---}--module Numeric.GSL (- module Numeric.GSL.Integration-, module Numeric.GSL.Differentiation-, module Numeric.GSL.Fourier-, module Numeric.GSL.Polynomials-, module Numeric.GSL.Minimization-, module Numeric.GSL.Root-, module Numeric.GSL.ODE-, module Numeric.GSL.Fitting-, module Data.Complex-, setErrorHandlerOff-) where--import Numeric.GSL.Integration-import Numeric.GSL.Differentiation-import Numeric.GSL.Fourier-import Numeric.GSL.Polynomials-import Numeric.GSL.Minimization-import Numeric.GSL.Root-import Numeric.GSL.ODE-import Numeric.GSL.Fitting-import Data.Complex----- | This action removes the GSL default error handler (which aborts the program), so that--- GSL errors can be handled by Haskell (using Control.Exception) and ghci doesn't abort.-foreign import ccall unsafe "GSL/gsl-aux.h no_abort_on_error" setErrorHandlerOff :: IO ()
@@ -1,87 +0,0 @@-{-# OPTIONS #-}-------------------------------------------------------------------------------{- |-Module : Numeric.GSL.Differentiation-Copyright : (c) Alberto Ruiz 2006-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Numerical differentiation.--<http://www.gnu.org/software/gsl/manual/html_node/Numerical-Differentiation.html#Numerical-Differentiation>--From the GSL manual: \"The functions described in this chapter compute numerical derivatives by finite differencing. An adaptive algorithm is used to find the best choice of finite difference and to estimate the error in the derivative.\"--}-------------------------------------------------------------------------------module Numeric.GSL.Differentiation (- derivCentral,- derivForward,- derivBackward-) where--import Foreign.C.Types-import Foreign.Marshal.Alloc(malloc, free)-import Foreign.Ptr(Ptr, FunPtr, freeHaskellFunPtr)-import Foreign.Storable(peek)-import Data.Packed.Internal(check,(//))-import System.IO.Unsafe(unsafePerformIO)--derivGen ::- CInt -- ^ type: 0 central, 1 forward, 2 backward- -> Double -- ^ initial step size- -> (Double -> Double) -- ^ function- -> Double -- ^ point where the derivative is taken- -> (Double, Double) -- ^ result and error-derivGen c h f x = unsafePerformIO $ do- r <- malloc- e <- malloc- fp <- mkfun (\y _ -> f y) - c_deriv c fp x h r e // check "deriv"- vr <- peek r- ve <- peek e- let result = (vr,ve)- free r- free e- freeHaskellFunPtr fp- return result--foreign import ccall safe "gsl-aux.h deriv" - c_deriv :: CInt -> FunPtr (Double -> Ptr () -> Double) -> Double -> Double - -> Ptr Double -> Ptr Double -> IO CInt---{- | Adaptive central difference algorithm, /gsl_deriv_central/. For example:--> > let deriv = derivCentral 0.01 -> > deriv sin (pi/4)->(0.7071067812000676,1.0600063101654055e-10)-> > cos (pi/4)->0.7071067811865476 ---}-derivCentral :: Double -- ^ initial step size- -> (Double -> Double) -- ^ function - -> Double -- ^ point where the derivative is taken- -> (Double, Double) -- ^ result and absolute error-derivCentral = derivGen 0---- | Adaptive forward difference algorithm, /gsl_deriv_forward/. The function is evaluated only at points greater than x, and never at x itself. The derivative is returned in result and an estimate of its absolute error is returned in abserr. This function should be used if f(x) has a discontinuity at x, or is undefined for values less than x. A backward derivative can be obtained using a negative step.-derivForward :: Double -- ^ initial step size- -> (Double -> Double) -- ^ function - -> Double -- ^ point where the derivative is taken- -> (Double, Double) -- ^ result and absolute error-derivForward = derivGen 1---- | Adaptive backward difference algorithm, /gsl_deriv_backward/. -derivBackward ::Double -- ^ initial step size- -> (Double -> Double) -- ^ function - -> Double -- ^ point where the derivative is taken- -> (Double, Double) -- ^ result and absolute error-derivBackward = derivGen 2--{- | conversion of Haskell functions into function pointers that can be used in the C side--}-foreign import ccall safe "wrapper" mkfun:: (Double -> Ptr() -> Double) -> IO( FunPtr (Double -> Ptr() -> Double))
@@ -1,177 +0,0 @@-{- |-Module : Numeric.GSL.Fitting-Copyright : (c) Alberto Ruiz 2010-License : GPL--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Nonlinear Least-Squares Fitting--<http://www.gnu.org/software/gsl/manual/html_node/Nonlinear-Least_002dSquares-Fitting.html>--The example program in the GSL manual (see examples/fitting.hs):--@dat = [- ([0.0],([6.0133918608118675],0.1)),- ([1.0],([5.5153769909966535],0.1)),- ([2.0],([5.261094606015287],0.1)),- ...- ([39.0],([1.0619821710802808],0.1))]--expModel [a,lambda,b] [t] = [a * exp (-lambda * t) + b]--expModelDer [a,lambda,b] [t] = [[exp (-lambda * t), -t * a * exp(-lambda*t) , 1]]--(sol,path) = fitModelScaled 1E-4 1E-4 20 (expModel, expModelDer) dat [1,0,0]--\> path-(6><5)- [ 1.0, 76.45780563978782, 1.6465931240727802, 1.8147715267618197e-2, 0.6465931240727797- , 2.0, 37.683816318260355, 2.858760367632973, 8.092094813253975e-2, 1.4479636296208662- , 3.0, 9.5807893736187, 4.948995119561291, 0.11942927999921617, 1.0945766509238248- , 4.0, 5.630494933603935, 5.021755718065913, 0.10287787128056883, 1.0338835440862608- , 5.0, 5.443976278682909, 5.045204331329302, 0.10405523433131504, 1.019416067207375- , 6.0, 5.4439736648994685, 5.045357818922331, 0.10404905846029407, 1.0192487112786812 ]-\> sol-[(5.045357818922331,6.027976702418132e-2),-(0.10404905846029407,3.157045047172834e-3),-(1.0192487112786812,3.782067731353722e-2)]@---}--------------------------------------------------------------------------------module Numeric.GSL.Fitting (- -- * Levenberg-Marquardt- nlFitting, FittingMethod(..),- -- * Utilities- fitModelScaled, fitModel-) where--import Data.Packed.Internal-import Numeric.LinearAlgebra-import Numeric.GSL.Internal--import Foreign.Ptr(FunPtr, freeHaskellFunPtr)-import Foreign.C.Types-import System.IO.Unsafe(unsafePerformIO)-----------------------------------------------------------------------------data FittingMethod = LevenbergMarquardtScaled -- ^ Interface to gsl_multifit_fdfsolver_lmsder. This is a robust and efficient version of the Levenberg-Marquardt algorithm as implemented in the scaled lmder routine in minpack. Minpack was written by Jorge J. More, Burton S. Garbow and Kenneth E. Hillstrom.- | LevenbergMarquardt -- ^ This is an unscaled version of the lmder algorithm. The elements of the diagonal scaling matrix D are set to 1. This algorithm may be useful in circumstances where the scaled version of lmder converges too slowly, or the function is already scaled appropriately.- deriving (Enum,Eq,Show,Bounded)----- | Nonlinear multidimensional least-squares fitting.-nlFitting :: FittingMethod- -> Double -- ^ absolute tolerance- -> Double -- ^ relative tolerance- -> Int -- ^ maximum number of iterations allowed- -> (Vector Double -> Vector Double) -- ^ function to be minimized- -> (Vector Double -> Matrix Double) -- ^ Jacobian- -> Vector Double -- ^ starting point- -> (Vector Double, Matrix Double) -- ^ solution vector and optimization path--nlFitting method epsabs epsrel maxit fun jac xinit = nlFitGen (fi (fromEnum method)) fun jac xinit epsabs epsrel maxit--nlFitGen m f jac xiv epsabs epsrel maxit = unsafePerformIO $ do- let p = dim xiv- n = dim (f xiv)- fp <- mkVecVecfun (aux_vTov (checkdim1 n p . f))- jp <- mkVecMatfun (aux_vTom (checkdim2 n p . jac))- rawpath <- createMatrix RowMajor maxit (2+p)- app2 (c_nlfit m fp jp epsabs epsrel (fi maxit) (fi n)) vec xiv mat rawpath "c_nlfit"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- [sol] = toRows $ dropRows (it-1) path- freeHaskellFunPtr fp- freeHaskellFunPtr jp- return (subVector 2 p sol, path)--foreign import ccall safe "nlfit"- c_nlfit:: CInt -> FunPtr TVV -> FunPtr TVM -> Double -> Double -> CInt -> CInt -> TVM-----------------------------------------------------------checkdim1 n _p v- | dim v == n = v- | otherwise = error $ "Error: "++ show n- ++ " components expected in the result of the function supplied to nlFitting"--checkdim2 n p m- | rows m == n && cols m == p = m- | otherwise = error $ "Error: "++ show n ++ "x" ++ show p- ++ " Jacobian expected in nlFitting"----------------------------------------------------------------err (model,deriv) dat vsol = zip sol errs where- sol = toList vsol- c = max 1 (chi/sqrt (fromIntegral dof))- dof = length dat - (rows cov)- chi = norm2 (fromList $ cost (resMs model) dat sol)- js = fromLists $ jacobian (resDs deriv) dat sol- cov = inv $ trans js <> js- errs = toList $ scalar c * sqrt (takeDiag cov)------ | Higher level interface to 'nlFitting' 'LevenbergMarquardtScaled'. The optimization function and--- Jacobian are automatically built from a model f vs x = y and its derivatives, and a list of--- instances (x, (y,sigma)) to be fitted.--fitModelScaled- :: Double -- ^ absolute tolerance- -> Double -- ^ relative tolerance- -> Int -- ^ maximum number of iterations allowed- -> ([Double] -> x -> [Double], [Double] -> x -> [[Double]]) -- ^ (model, derivatives)- -> [(x, ([Double], Double))] -- ^ instances- -> [Double] -- ^ starting point- -> ([(Double, Double)], Matrix Double) -- ^ (solution, error) and optimization path-fitModelScaled epsabs epsrel maxit (model,deriv) dt xin = (err (model,deriv) dt sol, path) where- (sol,path) = nlFitting LevenbergMarquardtScaled epsabs epsrel maxit- (fromList . cost (resMs model) dt . toList)- (fromLists . jacobian (resDs deriv) dt . toList)- (fromList xin)------ | Higher level interface to 'nlFitting' 'LevenbergMarquardt'. The optimization function and--- Jacobian are automatically built from a model f vs x = y and its derivatives, and a list of--- instances (x,y) to be fitted.--fitModel :: Double -- ^ absolute tolerance- -> Double -- ^ relative tolerance- -> Int -- ^ maximum number of iterations allowed- -> ([Double] -> x -> [Double], [Double] -> x -> [[Double]]) -- ^ (model, derivatives)- -> [(x, [Double])] -- ^ instances- -> [Double] -- ^ starting point- -> ([Double], Matrix Double) -- ^ solution and optimization path-fitModel epsabs epsrel maxit (model,deriv) dt xin = (toList sol, path) where- (sol,path) = nlFitting LevenbergMarquardt epsabs epsrel maxit- (fromList . cost (resM model) dt . toList)- (fromLists . jacobian (resD deriv) dt . toList)- (fromList xin)--cost model ds vs = concatMap (model vs) ds--jacobian modelDer ds vs = concatMap (modelDer vs) ds---- | Model-to-residual for association pairs with sigma, to be used with 'fitModel'.-resMs :: ([Double] -> x -> [Double]) -> [Double] -> (x, ([Double], Double)) -> [Double]-resMs m v = \(x,(ys,s)) -> zipWith (g s) (m v x) ys where g s a b = (a-b)/s---- | Associated derivative for 'resMs'.-resDs :: ([Double] -> x -> [[Double]]) -> [Double] -> (x, ([Double], Double)) -> [[Double]]-resDs m v = \(x,(_,s)) -> map (map (/s)) (m v x)---- | Model-to-residual for association pairs, to be used with 'fitModel'. It is equivalent--- to 'resMs' with all sigmas = 1.-resM :: ([Double] -> x -> [Double]) -> [Double] -> (x, [Double]) -> [Double]-resM m v = \(x,ys) -> zipWith g (m v x) ys where g a b = a-b---- | Associated derivative for 'resM'.-resD :: ([Double] -> x -> [[Double]]) -> [Double] -> (x, [Double]) -> [[Double]]-resD m v = \(x,_) -> m v x
@@ -1,47 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-------------------------------------------------------------------------------{- |-Module : Numeric.GSL.Fourier-Copyright : (c) Alberto Ruiz 2006-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Fourier Transform.--<http://www.gnu.org/software/gsl/manual/html_node/Fast-Fourier-Transforms.html#Fast-Fourier-Transforms>---}-------------------------------------------------------------------------------module Numeric.GSL.Fourier (- fft,- ifft-) where--import Data.Packed.Internal-import Data.Complex-import Foreign.C.Types-import System.IO.Unsafe (unsafePerformIO)--genfft code v = unsafePerformIO $ do- r <- createVector (dim v)- app2 (c_fft code) vec v vec r "fft"- return r--foreign import ccall unsafe "gsl-aux.h fft" c_fft :: CInt -> TCVCV---{- | Fast 1D Fourier transform of a 'Vector' @(@'Complex' 'Double'@)@ using /gsl_fft_complex_forward/. It uses the same scaling conventions as GNU Octave.--@> fft ('fromList' [1,2,3,4])-vector (4) [10.0 :+ 0.0,(-2.0) :+ 2.0,(-2.0) :+ 0.0,(-2.0) :+ (-2.0)]@---}-fft :: Vector (Complex Double) -> Vector (Complex Double)-fft = genfft 0---- | The inverse of 'fft', using /gsl_fft_complex_inverse/.-ifft :: Vector (Complex Double) -> Vector (Complex Double)-ifft = genfft 1
@@ -1,198 +0,0 @@-{-# OPTIONS #-}-------------------------------------------------------------------------------{- |-Module : Numeric.GSL.Integration-Copyright : (c) Alberto Ruiz 2006-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Numerical integration routines.--<http://www.gnu.org/software/gsl/manual/html_node/Numerical-Integration.html#Numerical-Integration>--}--------------------------------------------------------------------------------module Numeric.GSL.Integration (- integrateQNG,- integrateQAGS,- integrateQAGI,- integrateQAGIU,- integrateQAGIL-) where--import Foreign.C.Types-import Foreign.Marshal.Alloc(malloc, free)-import Foreign.Ptr(Ptr, FunPtr, freeHaskellFunPtr)-import Foreign.Storable(peek)-import Data.Packed.Internal(check,(//))-import System.IO.Unsafe(unsafePerformIO)--{- | conversion of Haskell functions into function pointers that can be used in the C side--}-foreign import ccall safe "wrapper" mkfun:: (Double -> Ptr() -> Double) -> IO( FunPtr (Double -> Ptr() -> Double)) -----------------------------------------------------------------------{- | Numerical integration using /gsl_integration_qags/ (adaptive integration with singularities). For example:--@\> let quad = integrateQAGS 1E-9 1000 -\> let f a x = x**(-0.5) * log (a*x)-\> quad (f 1) 0 1-(-3.999999999999974,4.871658632055187e-13)@- --}--integrateQAGS :: Double -- ^ precision (e.g. 1E-9)- -> Int -- ^ size of auxiliary workspace (e.g. 1000)- -> (Double -> Double) -- ^ function to be integrated on the interval (a,b)- -> Double -- ^ a- -> Double -- ^ b- -> (Double, Double) -- ^ result of the integration and error-integrateQAGS prec n f a b = unsafePerformIO $ do- r <- malloc- e <- malloc- fp <- mkfun (\x _ -> f x) - c_integrate_qags fp a b prec (fromIntegral n) r e // check "integrate_qags"- vr <- peek r- ve <- peek e- let result = (vr,ve)- free r- free e- freeHaskellFunPtr fp- return result--foreign import ccall safe "gsl-aux.h integrate_qags" - c_integrate_qags :: FunPtr (Double-> Ptr() -> Double) -> Double -> Double -> Double -> CInt- -> Ptr Double -> Ptr Double -> IO CInt--------------------------------------------------------------------{- | Numerical integration using /gsl_integration_qng/ (useful for fast integration of smooth functions). For example:--@\> let quad = integrateQNG 1E-6 -\> quad (\\x -> 4\/(1+x*x)) 0 1 -(3.141592653589793,3.487868498008632e-14)@- --}--integrateQNG :: Double -- ^ precision (e.g. 1E-9)- -> (Double -> Double) -- ^ function to be integrated on the interval (a,b)- -> Double -- ^ a- -> Double -- ^ b- -> (Double, Double) -- ^ result of the integration and error-integrateQNG prec f a b = unsafePerformIO $ do- r <- malloc- e <- malloc- fp <- mkfun (\x _ -> f x) - c_integrate_qng fp a b prec r e // check "integrate_qng"- vr <- peek r- ve <- peek e- let result = (vr,ve)- free r- free e- freeHaskellFunPtr fp- return result--foreign import ccall safe "gsl-aux.h integrate_qng" - c_integrate_qng :: FunPtr (Double-> Ptr() -> Double) -> Double -> Double -> Double - -> Ptr Double -> Ptr Double -> IO CInt-----------------------------------------------------------------------{- | Numerical integration using /gsl_integration_qagi/ (integration over the infinite integral -Inf..Inf using QAGS). -For example:--@\> let quad = integrateQAGI 1E-9 1000 -\> let f a x = exp(-a * x^2)-\> quad (f 0.5) -(2.5066282746310002,6.229215880648858e-11)@- --}--integrateQAGI :: Double -- ^ precision (e.g. 1E-9)- -> Int -- ^ size of auxiliary workspace (e.g. 1000)- -> (Double -> Double) -- ^ function to be integrated on the interval (-Inf,Inf)- -> (Double, Double) -- ^ result of the integration and error-integrateQAGI prec n f = unsafePerformIO $ do- r <- malloc- e <- malloc- fp <- mkfun (\x _ -> f x) - c_integrate_qagi fp prec (fromIntegral n) r e // check "integrate_qagi"- vr <- peek r- ve <- peek e- let result = (vr,ve)- free r- free e- freeHaskellFunPtr fp- return result--foreign import ccall safe "gsl-aux.h integrate_qagi" - c_integrate_qagi :: FunPtr (Double-> Ptr() -> Double) -> Double -> CInt- -> Ptr Double -> Ptr Double -> IO CInt-----------------------------------------------------------------------{- | Numerical integration using /gsl_integration_qagiu/ (integration over the semi-infinite integral a..Inf). -For example:--@\> let quad = integrateQAGIU 1E-9 1000 -\> let f a x = exp(-a * x^2)-\> quad (f 0.5) 0-(1.2533141373155001,3.114607940324429e-11)@- --}--integrateQAGIU :: Double -- ^ precision (e.g. 1E-9)- -> Int -- ^ size of auxiliary workspace (e.g. 1000)- -> (Double -> Double) -- ^ function to be integrated on the interval (a,Inf)- -> Double -- ^ a- -> (Double, Double) -- ^ result of the integration and error-integrateQAGIU prec n f a = unsafePerformIO $ do- r <- malloc- e <- malloc- fp <- mkfun (\x _ -> f x) - c_integrate_qagiu fp a prec (fromIntegral n) r e // check "integrate_qagiu"- vr <- peek r- ve <- peek e- let result = (vr,ve)- free r- free e- freeHaskellFunPtr fp- return result--foreign import ccall safe "gsl-aux.h integrate_qagiu" - c_integrate_qagiu :: FunPtr (Double-> Ptr() -> Double) -> Double -> Double -> CInt- -> Ptr Double -> Ptr Double -> IO CInt-----------------------------------------------------------------------{- | Numerical integration using /gsl_integration_qagil/ (integration over the semi-infinite integral -Inf..b). -For example:--@\> let quad = integrateQAGIL 1E-9 1000 -\> let f a x = exp(-a * x^2)-\> quad (f 0.5) 0 -(1.2533141373155001,3.114607940324429e-11)@- --}--integrateQAGIL :: Double -- ^ precision (e.g. 1E-9)- -> Int -- ^ size of auxiliary workspace (e.g. 1000)- -> (Double -> Double) -- ^ function to be integrated on the interval (a,Inf)- -> Double -- ^ b- -> (Double, Double) -- ^ result of the integration and error-integrateQAGIL prec n f b = unsafePerformIO $ do- r <- malloc- e <- malloc- fp <- mkfun (\x _ -> f x) - c_integrate_qagil fp b prec (fromIntegral n) r e // check "integrate_qagil"- vr <- peek r- ve <- peek e- let result = (vr,ve)- free r- free e- freeHaskellFunPtr fp- return result--foreign import ccall safe "gsl-aux.h integrate_qagil" - c_integrate_qagil :: FunPtr (Double-> Ptr() -> Double) -> Double -> Double -> CInt- -> Ptr Double -> Ptr Double -> IO CInt-
@@ -1,76 +0,0 @@--- Module : Numeric.GSL.Internal--- Copyright : (c) Alberto Ruiz 2009--- License : GPL------ Maintainer : Alberto Ruiz (aruiz at um dot es)--- Stability : provisional--- Portability : uses ffi------ Auxiliary functions.------ #hide--module Numeric.GSL.Internal where--import Data.Packed.Internal--import Foreign.Marshal.Array(copyArray)-import Foreign.Ptr(Ptr, FunPtr)-import Foreign.C.Types-import System.IO.Unsafe(unsafePerformIO)--iv :: (Vector Double -> Double) -> (CInt -> Ptr Double -> Double)-iv f n p = f (createV (fromIntegral n) copy "iv") where- copy n' q = do- copyArray q p (fromIntegral n')- return 0---- | conversion of Haskell functions into function pointers that can be used in the C side-foreign import ccall safe "wrapper"- mkVecfun :: (CInt -> Ptr Double -> Double)- -> IO( FunPtr (CInt -> Ptr Double -> Double))--foreign import ccall safe "wrapper"- mkVecVecfun :: TVV -> IO (FunPtr TVV)--foreign import ccall safe "wrapper"- mkDoubleVecVecfun :: (Double -> TVV) -> IO (FunPtr (Double -> TVV))--foreign import ccall safe "wrapper"- mkDoublefun :: (Double -> Double) -> IO (FunPtr (Double -> Double))--aux_vTov :: (Vector Double -> Vector Double) -> TVV-aux_vTov f n p nr r = g where- v = f x- x = createV (fromIntegral n) copy "aux_vTov"- copy n' q = do- copyArray q p (fromIntegral n')- return 0- g = do unsafeWith v $ \p' -> copyArray r p' (fromIntegral nr)- return 0--foreign import ccall safe "wrapper"- mkVecMatfun :: TVM -> IO (FunPtr TVM)--foreign import ccall safe "wrapper"- mkDoubleVecMatfun :: (Double -> TVM) -> IO (FunPtr (Double -> TVM))--aux_vTom :: (Vector Double -> Matrix Double) -> TVM-aux_vTom f n p rr cr r = g where- v = flatten $ f x- x = createV (fromIntegral n) copy "aux_vTov"- copy n' q = do- copyArray q p (fromIntegral n')- return 0- g = do unsafeWith v $ \p' -> copyArray r p' (fromIntegral $ rr*cr)- return 0--createV n fun msg = unsafePerformIO $ do- r <- createVector n- app1 fun vec r msg- return r--createMIO r c fun msg = do- res <- createMatrix RowMajor r c- app1 fun mat res msg- return res
@@ -1,194 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-------------------------------------------------------------------------------{- |-Module : Numeric.GSL.Minimization-Copyright : (c) Alberto Ruiz 2006-9-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Minimization of a multidimensional function using some of the algorithms described in:--<http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html>--The example in the GSL manual:--@--f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30--main = do- let (s,p) = minimize NMSimplex2 1E-2 30 [1,1] f [5,7]- print s- print p--\> main-[0.9920430849306288,1.9969168063253182]- 0.000 512.500 1.130 6.500 5.000- 1.000 290.625 1.409 5.250 4.000- 2.000 290.625 1.409 5.250 4.000- 3.000 252.500 1.409 5.500 1.000- ...-22.000 30.001 0.013 0.992 1.997-23.000 30.001 0.008 0.992 1.997-@--The path to the solution can be graphically shown by means of:--@'Graphics.Plot.mplot' $ drop 3 ('toColumns' p)@--Taken from the GSL manual:--The vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm is a quasi-Newton method which builds up an approximation to the second derivatives of the function f using the difference between successive gradient vectors. By combining the first and second derivatives the algorithm is able to take Newton-type steps towards the function minimum, assuming quadratic behavior in that region.--The bfgs2 version of this minimizer is the most efficient version available, and is a faithful implementation of the line minimization scheme described in Fletcher's Practical Methods of Optimization, Algorithms 2.6.2 and 2.6.4. It supercedes the original bfgs routine and requires substantially fewer function and gradient evaluations. The user-supplied tolerance tol corresponds to the parameter \sigma used by Fletcher. A value of 0.1 is recommended for typical use (larger values correspond to less accurate line searches).--The nmsimplex2 version is a new O(N) implementation of the earlier O(N^2) nmsimplex minimiser. It calculates the size of simplex as the rms distance of each vertex from the center rather than the mean distance, which has the advantage of allowing a linear update.---}--------------------------------------------------------------------------------module Numeric.GSL.Minimization (- minimize, minimizeV, MinimizeMethod(..),- minimizeD, minimizeVD, MinimizeMethodD(..),-- minimizeNMSimplex,- minimizeConjugateGradient,- minimizeVectorBFGS2-) where---import Data.Packed.Internal-import Data.Packed.Matrix-import Numeric.GSL.Internal--import Foreign.Ptr(Ptr, FunPtr, freeHaskellFunPtr)-import Foreign.C.Types-import System.IO.Unsafe(unsafePerformIO)----------------------------------------------------------------------------{-# DEPRECATED minimizeNMSimplex "use minimize NMSimplex2 eps maxit sizes f xi" #-}-minimizeNMSimplex f xi szs eps maxit = minimize NMSimplex eps maxit szs f xi--{-# DEPRECATED minimizeConjugateGradient "use minimizeD ConjugateFR eps maxit step tol f g xi" #-}-minimizeConjugateGradient step tol eps maxit f g xi = minimizeD ConjugateFR eps maxit step tol f g xi--{-# DEPRECATED minimizeVectorBFGS2 "use minimizeD VectorBFGS2 eps maxit step tol f g xi" #-}-minimizeVectorBFGS2 step tol eps maxit f g xi = minimizeD VectorBFGS2 eps maxit step tol f g xi-----------------------------------------------------------------------------data MinimizeMethod = NMSimplex- | NMSimplex2- deriving (Enum,Eq,Show,Bounded)---- | Minimization without derivatives-minimize :: MinimizeMethod- -> Double -- ^ desired precision of the solution (size test)- -> Int -- ^ maximum number of iterations allowed- -> [Double] -- ^ sizes of the initial search box- -> ([Double] -> Double) -- ^ function to minimize- -> [Double] -- ^ starting point- -> ([Double], Matrix Double) -- ^ solution vector and optimization path---- | Minimization without derivatives (vector version)-minimizeV :: MinimizeMethod- -> Double -- ^ desired precision of the solution (size test)- -> Int -- ^ maximum number of iterations allowed- -> Vector Double -- ^ sizes of the initial search box- -> (Vector Double -> Double) -- ^ function to minimize- -> Vector Double -- ^ starting point- -> (Vector Double, Matrix Double) -- ^ solution vector and optimization path--minimize method eps maxit sz f xi = v2l $ minimizeV method eps maxit (fromList sz) (f.toList) (fromList xi)- where v2l (v,m) = (toList v, m)--ww2 w1 o1 w2 o2 f = w1 o1 $ \a1 -> w2 o2 $ \a2 -> f a1 a2--minimizeV method eps maxit szv f xiv = unsafePerformIO $ do- let n = dim xiv- fp <- mkVecfun (iv f)- rawpath <- ww2 vec xiv vec szv $ \xiv' szv' ->- createMIO maxit (n+3)- (c_minimize (fi (fromEnum method)) fp eps (fi maxit) // xiv' // szv')- "minimize"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- sol = cdat $ dropColumns 3 $ dropRows (it-1) path- freeHaskellFunPtr fp- return (sol, path)---foreign import ccall safe "gsl-aux.h minimize"- c_minimize:: CInt -> FunPtr (CInt -> Ptr Double -> Double) -> Double -> CInt -> TVVM---------------------------------------------------------------------------------------data MinimizeMethodD = ConjugateFR- | ConjugatePR- | VectorBFGS- | VectorBFGS2- | SteepestDescent- deriving (Enum,Eq,Show,Bounded)---- | Minimization with derivatives.-minimizeD :: MinimizeMethodD- -> Double -- ^ desired precision of the solution (gradient test)- -> Int -- ^ maximum number of iterations allowed- -> Double -- ^ size of the first trial step- -> Double -- ^ tol (precise meaning depends on method)- -> ([Double] -> Double) -- ^ function to minimize- -> ([Double] -> [Double]) -- ^ gradient- -> [Double] -- ^ starting point- -> ([Double], Matrix Double) -- ^ solution vector and optimization path---- | Minimization with derivatives (vector version)-minimizeVD :: MinimizeMethodD- -> Double -- ^ desired precision of the solution (gradient test)- -> Int -- ^ maximum number of iterations allowed- -> Double -- ^ size of the first trial step- -> Double -- ^ tol (precise meaning depends on method)- -> (Vector Double -> Double) -- ^ function to minimize- -> (Vector Double -> Vector Double) -- ^ gradient- -> Vector Double -- ^ starting point- -> (Vector Double, Matrix Double) -- ^ solution vector and optimization path--minimizeD method eps maxit istep tol f df xi = v2l $ minimizeVD- method eps maxit istep tol (f.toList) (fromList.df.toList) (fromList xi)- where v2l (v,m) = (toList v, m)---minimizeVD method eps maxit istep tol f df xiv = unsafePerformIO $ do- let n = dim xiv- f' = f- df' = (checkdim1 n . df)- fp <- mkVecfun (iv f')- dfp <- mkVecVecfun (aux_vTov df')- rawpath <- vec xiv $ \xiv' ->- createMIO maxit (n+2)- (c_minimizeD (fi (fromEnum method)) fp dfp istep tol eps (fi maxit) // xiv')- "minimizeD"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- sol = cdat $ dropColumns 2 $ dropRows (it-1) path- freeHaskellFunPtr fp- freeHaskellFunPtr dfp- return (sol,path)--foreign import ccall safe "gsl-aux.h minimizeD"- c_minimizeD :: CInt- -> FunPtr (CInt -> Ptr Double -> Double)- -> FunPtr TVV- -> Double -> Double -> Double -> CInt- -> TVM-------------------------------------------------------------------------checkdim1 n v- | dim v == n = v- | otherwise = error $ "Error: "++ show n- ++ " components expected in the result of the gradient supplied to minimizeD"
@@ -1,136 +0,0 @@-{- |-Module : Numeric.GSL.ODE-Copyright : (c) Alberto Ruiz 2010-License : GPL--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Solution of ordinary differential equation (ODE) initial value problems.--<http://www.gnu.org/software/gsl/manual/html_node/Ordinary-Differential-Equations.html>--A simple example:--@import Numeric.GSL-import Numeric.LinearAlgebra-import Graphics.Plot--xdot t [x,v] = [v, -0.95*x - 0.1*v]--ts = linspace 100 (0,20 :: Double)--sol = odeSolve xdot [10,0] ts--main = mplot (ts : toColumns sol)@---}--------------------------------------------------------------------------------module Numeric.GSL.ODE (- odeSolve, odeSolveV, ODEMethod(..), Jacobian-) where--import Data.Packed.Internal-import Numeric.GSL.Internal--import Foreign.Ptr(FunPtr, nullFunPtr, freeHaskellFunPtr)-import Foreign.C.Types-import System.IO.Unsafe(unsafePerformIO)-----------------------------------------------------------------------------type Jacobian = Double -> Vector Double -> Matrix Double---- | Stepping functions-data ODEMethod = RK2 -- ^ Embedded Runge-Kutta (2, 3) method.- | RK4 -- ^ 4th order (classical) Runge-Kutta. The error estimate is obtained by halving the step-size. For more efficient estimate of the error, use the embedded methods.- | RKf45 -- ^ Embedded Runge-Kutta-Fehlberg (4, 5) method. This method is a good general-purpose integrator.- | RKck -- ^ Embedded Runge-Kutta Cash-Karp (4, 5) method.- | RK8pd -- ^ Embedded Runge-Kutta Prince-Dormand (8,9) method.- | RK2imp Jacobian -- ^ Implicit 2nd order Runge-Kutta at Gaussian points.- | RK4imp Jacobian -- ^ Implicit 4th order Runge-Kutta at Gaussian points.- | BSimp Jacobian -- ^ Implicit Bulirsch-Stoer method of Bader and Deuflhard. The method is generally suitable for stiff problems.- | RK1imp Jacobian -- ^ Implicit Gaussian first order Runge-Kutta. Also known as implicit Euler or backward Euler method. Error estimation is carried out by the step doubling method.- | MSAdams -- ^ A variable-coefficient linear multistep Adams method in Nordsieck form. This stepper uses explicit Adams-Bashforth (predictor) and implicit Adams-Moulton (corrector) methods in P(EC)^m functional iteration mode. Method order varies dynamically between 1 and 12. - | MSBDF Jacobian -- ^ A variable-coefficient linear multistep backward differentiation formula (BDF) method in Nordsieck form. This stepper uses the explicit BDF formula as predictor and implicit BDF formula as corrector. A modified Newton iteration method is used to solve the system of non-linear equations. Method order varies dynamically between 1 and 5. The method is generally suitable for stiff problems.----- | A version of 'odeSolveV' with reasonable default parameters and system of equations defined using lists.-odeSolve- :: (Double -> [Double] -> [Double]) -- ^ xdot(t,x)- -> [Double] -- ^ initial conditions- -> Vector Double -- ^ desired solution times- -> Matrix Double -- ^ solution-odeSolve xdot xi ts = odeSolveV RKf45 hi epsAbs epsRel (l2v xdot) (fromList xi) ts- where hi = (ts@>1 - ts@>0)/100- epsAbs = 1.49012e-08- epsRel = 1.49012e-08- l2v f = \t -> fromList . f t . toList---- | Evolution of the system with adaptive step-size control.-odeSolveV- :: ODEMethod- -> Double -- ^ initial step size- -> Double -- ^ absolute tolerance for the state vector- -> Double -- ^ relative tolerance for the state vector- -> (Double -> Vector Double -> Vector Double) -- ^ xdot(t,x)- -> Vector Double -- ^ initial conditions- -> Vector Double -- ^ desired solution times- -> Matrix Double -- ^ solution-odeSolveV RK2 = odeSolveV' 0 Nothing-odeSolveV RK4 = odeSolveV' 1 Nothing-odeSolveV RKf45 = odeSolveV' 2 Nothing-odeSolveV RKck = odeSolveV' 3 Nothing-odeSolveV RK8pd = odeSolveV' 4 Nothing-odeSolveV (RK2imp jac) = odeSolveV' 5 (Just jac)-odeSolveV (RK4imp jac) = odeSolveV' 6 (Just jac)-odeSolveV (BSimp jac) = odeSolveV' 7 (Just jac)-odeSolveV (RK1imp jac) = odeSolveV' 8 (Just jac)-odeSolveV MSAdams = odeSolveV' 9 Nothing-odeSolveV (MSBDF jac) = odeSolveV' 10 (Just jac)---odeSolveV'- :: CInt- -> Maybe (Double -> Vector Double -> Matrix Double) -- ^ optional jacobian- -> Double -- ^ initial step size- -> Double -- ^ absolute tolerance for the state vector- -> Double -- ^ relative tolerance for the state vector- -> (Double -> Vector Double -> Vector Double) -- ^ xdot(t,x)- -> Vector Double -- ^ initial conditions- -> Vector Double -- ^ desired solution times- -> Matrix Double -- ^ solution-odeSolveV' method mbjac h epsAbs epsRel f xiv ts = unsafePerformIO $ do- let n = dim xiv- fp <- mkDoubleVecVecfun (\t -> aux_vTov (checkdim1 n . f t))- jp <- case mbjac of- Just jac -> mkDoubleVecMatfun (\t -> aux_vTom (checkdim2 n . jac t))- Nothing -> return nullFunPtr- sol <- vec xiv $ \xiv' ->- vec (checkTimes ts) $ \ts' ->- createMIO (dim ts) n- (ode_c (method) h epsAbs epsRel fp jp // xiv' // ts' )- "ode"- freeHaskellFunPtr fp- return sol--foreign import ccall safe "ode"- ode_c :: CInt -> Double -> Double -> Double -> FunPtr (Double -> TVV) -> FunPtr (Double -> TVM) -> TVVM-----------------------------------------------------------checkdim1 n v- | dim v == n = v- | otherwise = error $ "Error: "++ show n- ++ " components expected in the result of the function supplied to odeSolve"--checkdim2 n m- | rows m == n && cols m == n = m- | otherwise = error $ "Error: "++ show n ++ "x" ++ show n- ++ " Jacobian expected in odeSolve"--checkTimes ts | dim ts > 1 && all (>0) (zipWith subtract ts' (tail ts')) = ts- | otherwise = error "odeSolve requires increasing times"- where ts' = toList ts
@@ -1,58 +0,0 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}-------------------------------------------------------------------------------{- |-Module : Numeric.GSL.Polynomials-Copyright : (c) Alberto Ruiz 2006-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Polynomials.--<http://www.gnu.org/software/gsl/manual/html_node/General-Polynomial-Equations.html#General-Polynomial-Equations>---}-------------------------------------------------------------------------------module Numeric.GSL.Polynomials (- polySolve-) where--import Data.Packed.Internal-import Data.Complex-import System.IO.Unsafe (unsafePerformIO)--#if __GLASGOW_HASKELL__ >= 704-import Foreign.C.Types (CInt(..))-#endif--{- | Solution of general polynomial equations, using /gsl_poly_complex_solve/. For example,- the three solutions of x^3 + 8 = 0--@\> polySolve [8,0,0,1]-[(-1.9999999999999998) :+ 0.0,- 1.0 :+ 1.732050807568877,- 1.0 :+ (-1.732050807568877)]@--The example in the GSL manual: To find the roots of x^5 -1 = 0:--@\> polySolve [-1, 0, 0, 0, 0, 1]-[(-0.8090169943749475) :+ 0.5877852522924731,-(-0.8090169943749475) :+ (-0.5877852522924731),-0.30901699437494734 :+ 0.9510565162951536,-0.30901699437494734 :+ (-0.9510565162951536),-1.0 :+ 0.0]@---} -polySolve :: [Double] -> [Complex Double]-polySolve = toList . polySolve' . fromList--polySolve' :: Vector Double -> Vector (Complex Double)-polySolve' v | dim v > 1 = unsafePerformIO $ do- r <- createVector (dim v-1)- app2 c_polySolve vec v vec r "polySolve"- return r- | otherwise = error "polySolve on a polynomial of degree zero"--foreign import ccall unsafe "gsl-aux.h polySolve" c_polySolve:: TVCV
@@ -1,209 +0,0 @@-{- |-Module : Numeric.GSL.Root-Copyright : (c) Alberto Ruiz 2009-License : GPL--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--Multidimensional root finding.--<http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Root_002dFinding.html>--The example in the GSL manual:--@import Numeric.GSL-import Numeric.LinearAlgebra(format)-import Text.Printf(printf)--rosenbrock a b [x,y] = [ a*(1-x), b*(y-x^2) ]--disp = putStrLn . format \" \" (printf \"%.3f\")--main = do- let (sol,path) = root Hybrids 1E-7 30 (rosenbrock 1 10) [-10,-5]- print sol- disp path--\> main-[1.0,1.0]- 0.000 -10.000 -5.000 11.000 -1050.000- 1.000 -3.976 24.827 4.976 90.203- 2.000 -3.976 24.827 4.976 90.203- 3.000 -3.976 24.827 4.976 90.203- 4.000 -1.274 -5.680 2.274 -73.018- 5.000 -1.274 -5.680 2.274 -73.018- 6.000 0.249 0.298 0.751 2.359- 7.000 0.249 0.298 0.751 2.359- 8.000 1.000 0.878 -0.000 -1.218- 9.000 1.000 0.989 -0.000 -0.108-10.000 1.000 1.000 0.000 0.000-@---}--------------------------------------------------------------------------------module Numeric.GSL.Root (- uniRoot, UniRootMethod(..),- uniRootJ, UniRootMethodJ(..),- root, RootMethod(..),- rootJ, RootMethodJ(..),-) where--import Data.Packed.Internal-import Data.Packed.Matrix-import Numeric.GSL.Internal-import Foreign.Ptr(FunPtr, freeHaskellFunPtr)-import Foreign.C.Types-import System.IO.Unsafe(unsafePerformIO)-----------------------------------------------------------------------------data UniRootMethod = Bisection- | FalsePos- | Brent- deriving (Enum, Eq, Show, Bounded)--uniRoot :: UniRootMethod- -> Double- -> Int- -> (Double -> Double)- -> Double- -> Double- -> (Double, Matrix Double)-uniRoot method epsrel maxit fun xl xu = uniRootGen (fi (fromEnum method)) fun xl xu epsrel maxit--uniRootGen m f xl xu epsrel maxit = unsafePerformIO $ do- fp <- mkDoublefun f- rawpath <- createMIO maxit 4- (c_root m fp epsrel (fi maxit) xl xu)- "root"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- [sol] = toLists $ dropRows (it-1) path- freeHaskellFunPtr fp- return (sol !! 1, path)--foreign import ccall safe "root"- c_root:: CInt -> FunPtr (Double -> Double) -> Double -> CInt -> Double -> Double -> TM----------------------------------------------------------------------------data UniRootMethodJ = UNewton- | Secant- | Steffenson- deriving (Enum, Eq, Show, Bounded)--uniRootJ :: UniRootMethodJ- -> Double- -> Int- -> (Double -> Double)- -> (Double -> Double)- -> Double- -> (Double, Matrix Double)-uniRootJ method epsrel maxit fun dfun x = uniRootJGen (fi (fromEnum method)) fun- dfun x epsrel maxit--uniRootJGen m f df x epsrel maxit = unsafePerformIO $ do- fp <- mkDoublefun f- dfp <- mkDoublefun df- rawpath <- createMIO maxit 2- (c_rootj m fp dfp epsrel (fi maxit) x)- "rootj"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- [sol] = toLists $ dropRows (it-1) path- freeHaskellFunPtr fp- return (sol !! 1, path)--foreign import ccall safe "rootj"- c_rootj :: CInt -> FunPtr (Double -> Double) -> FunPtr (Double -> Double)- -> Double -> CInt -> Double -> TM-----------------------------------------------------------------------------data RootMethod = Hybrids- | Hybrid- | DNewton- | Broyden- deriving (Enum,Eq,Show,Bounded)---- | Nonlinear multidimensional root finding using algorithms that do not require --- any derivative information to be supplied by the user.--- Any derivatives needed are approximated by finite differences.-root :: RootMethod- -> Double -- ^ maximum residual- -> Int -- ^ maximum number of iterations allowed- -> ([Double] -> [Double]) -- ^ function to minimize- -> [Double] -- ^ starting point- -> ([Double], Matrix Double) -- ^ solution vector and optimization path--root method epsabs maxit fun xinit = rootGen (fi (fromEnum method)) fun xinit epsabs maxit--rootGen m f xi epsabs maxit = unsafePerformIO $ do- let xiv = fromList xi- n = dim xiv- fp <- mkVecVecfun (aux_vTov (checkdim1 n . fromList . f . toList))- rawpath <- vec xiv $ \xiv' ->- createMIO maxit (2*n+1)- (c_multiroot m fp epsabs (fi maxit) // xiv')- "multiroot"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- [sol] = toLists $ dropRows (it-1) path- freeHaskellFunPtr fp- return (take n $ drop 1 sol, path)---foreign import ccall safe "multiroot"- c_multiroot:: CInt -> FunPtr TVV -> Double -> CInt -> TVM-----------------------------------------------------------------------------data RootMethodJ = HybridsJ- | HybridJ- | Newton- | GNewton- deriving (Enum,Eq,Show,Bounded)---- | Nonlinear multidimensional root finding using both the function and its derivatives.-rootJ :: RootMethodJ- -> Double -- ^ maximum residual- -> Int -- ^ maximum number of iterations allowed- -> ([Double] -> [Double]) -- ^ function to minimize- -> ([Double] -> [[Double]]) -- ^ Jacobian- -> [Double] -- ^ starting point- -> ([Double], Matrix Double) -- ^ solution vector and optimization path--rootJ method epsabs maxit fun jac xinit = rootJGen (fi (fromEnum method)) fun jac xinit epsabs maxit--rootJGen m f jac xi epsabs maxit = unsafePerformIO $ do- let xiv = fromList xi- n = dim xiv- fp <- mkVecVecfun (aux_vTov (checkdim1 n . fromList . f . toList))- jp <- mkVecMatfun (aux_vTom (checkdim2 n . fromLists . jac . toList))- rawpath <- vec xiv $ \xiv' ->- createMIO maxit (2*n+1)- (c_multirootj m fp jp epsabs (fi maxit) // xiv')- "multiroot"- let it = round (rawpath @@> (maxit-1,0))- path = takeRows it rawpath- [sol] = toLists $ dropRows (it-1) path- freeHaskellFunPtr fp- freeHaskellFunPtr jp- return (take n $ drop 1 sol, path)--foreign import ccall safe "multirootj"- c_multirootj:: CInt -> FunPtr TVV -> FunPtr TVM -> Double -> CInt -> TVM-----------------------------------------------------------checkdim1 n v- | dim v == n = v- | otherwise = error $ "Error: "++ show n- ++ " components expected in the result of the function supplied to root"--checkdim2 n m- | rows m == n && cols m == n = m- | otherwise = error $ "Error: "++ show n ++ "x" ++ show n- ++ " Jacobian expected in rootJ"
@@ -1,327 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Numeric.GSL.Vector--- Copyright : (c) Alberto Ruiz 2007--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable (uses FFI)------ Low level interface to vector operations.-----------------------------------------------------------------------------------module Numeric.GSL.Vector (- sumF, sumR, sumQ, sumC,- prodF, prodR, prodQ, prodC,- dotF, dotR, dotQ, dotC,- FunCodeS(..), toScalarR, toScalarF, toScalarC, toScalarQ,- FunCodeV(..), vectorMapR, vectorMapC, vectorMapF, vectorMapQ,- FunCodeSV(..), vectorMapValR, vectorMapValC, vectorMapValF, vectorMapValQ,- FunCodeVV(..), vectorZipR, vectorZipC, vectorZipF, vectorZipQ,- RandDist(..), randomVector-) where--import Data.Packed.Internal.Common-import Data.Packed.Internal.Signatures-import Data.Packed.Internal.Vector--import Data.Complex-import Foreign.Marshal.Alloc(free)-import Foreign.Marshal.Array(newArray)-import Foreign.Ptr(Ptr)-import Foreign.C.Types-import System.IO.Unsafe(unsafePerformIO)--fromei x = fromIntegral (fromEnum x) :: CInt--data FunCodeV = Sin- | Cos- | Tan- | Abs- | ASin- | ACos- | ATan- | Sinh- | Cosh- | Tanh- | ASinh- | ACosh- | ATanh- | Exp- | Log- | Sign- | Sqrt- deriving Enum--data FunCodeSV = Scale- | Recip- | AddConstant- | Negate- | PowSV- | PowVS- deriving Enum--data FunCodeVV = Add- | Sub- | Mul- | Div- | Pow- | ATan2- deriving Enum--data FunCodeS = Norm2- | AbsSum- | MaxIdx- | Max- | MinIdx- | Min- deriving Enum------------------------------------------------------------------------ | sum of elements-sumF :: Vector Float -> Float-sumF x = unsafePerformIO $ do- r <- createVector 1- app2 c_sumF vec x vec r "sumF"- return $ r @> 0---- | sum of elements-sumR :: Vector Double -> Double-sumR x = unsafePerformIO $ do- r <- createVector 1- app2 c_sumR vec x vec r "sumR"- return $ r @> 0---- | sum of elements-sumQ :: Vector (Complex Float) -> Complex Float-sumQ x = unsafePerformIO $ do- r <- createVector 1- app2 c_sumQ vec x vec r "sumQ"- return $ r @> 0---- | sum of elements-sumC :: Vector (Complex Double) -> Complex Double-sumC x = unsafePerformIO $ do- r <- createVector 1- app2 c_sumC vec x vec r "sumC"- return $ r @> 0--foreign import ccall unsafe "gsl-aux.h sumF" c_sumF :: TFF-foreign import ccall unsafe "gsl-aux.h sumR" c_sumR :: TVV-foreign import ccall unsafe "gsl-aux.h sumQ" c_sumQ :: TQVQV-foreign import ccall unsafe "gsl-aux.h sumC" c_sumC :: TCVCV---- | product of elements-prodF :: Vector Float -> Float-prodF x = unsafePerformIO $ do- r <- createVector 1- app2 c_prodF vec x vec r "prodF"- return $ r @> 0---- | product of elements-prodR :: Vector Double -> Double-prodR x = unsafePerformIO $ do- r <- createVector 1- app2 c_prodR vec x vec r "prodR"- return $ r @> 0---- | product of elements-prodQ :: Vector (Complex Float) -> Complex Float-prodQ x = unsafePerformIO $ do- r <- createVector 1- app2 c_prodQ vec x vec r "prodQ"- return $ r @> 0---- | product of elements-prodC :: Vector (Complex Double) -> Complex Double-prodC x = unsafePerformIO $ do- r <- createVector 1- app2 c_prodC vec x vec r "prodC"- return $ r @> 0--foreign import ccall unsafe "gsl-aux.h prodF" c_prodF :: TFF-foreign import ccall unsafe "gsl-aux.h prodR" c_prodR :: TVV-foreign import ccall unsafe "gsl-aux.h prodQ" c_prodQ :: TQVQV-foreign import ccall unsafe "gsl-aux.h prodC" c_prodC :: TCVCV---- | dot product-dotF :: Vector Float -> Vector Float -> Float-dotF x y = unsafePerformIO $ do- r <- createVector 1- app3 c_dotF vec x vec y vec r "dotF"- return $ r @> 0---- | dot product-dotR :: Vector Double -> Vector Double -> Double-dotR x y = unsafePerformIO $ do- r <- createVector 1- app3 c_dotR vec x vec y vec r "dotR"- return $ r @> 0---- | dot product-dotQ :: Vector (Complex Float) -> Vector (Complex Float) -> Complex Float-dotQ x y = unsafePerformIO $ do- r <- createVector 1- app3 c_dotQ vec x vec y vec r "dotQ"- return $ r @> 0---- | dot product-dotC :: Vector (Complex Double) -> Vector (Complex Double) -> Complex Double-dotC x y = unsafePerformIO $ do- r <- createVector 1- app3 c_dotC vec x vec y vec r "dotC"- return $ r @> 0--foreign import ccall unsafe "gsl-aux.h dotF" c_dotF :: TFFF-foreign import ccall unsafe "gsl-aux.h dotR" c_dotR :: TVVV-foreign import ccall unsafe "gsl-aux.h dotQ" c_dotQ :: TQVQVQV-foreign import ccall unsafe "gsl-aux.h dotC" c_dotC :: TCVCVCV----------------------------------------------------------------------toScalarAux fun code v = unsafePerformIO $ do- r <- createVector 1- app2 (fun (fromei code)) vec v vec r "toScalarAux"- return (r `at` 0)--vectorMapAux fun code v = unsafePerformIO $ do- r <- createVector (dim v)- app2 (fun (fromei code)) vec v vec r "vectorMapAux"- return r--vectorMapValAux fun code val v = unsafePerformIO $ do- r <- createVector (dim v)- pval <- newArray [val]- app2 (fun (fromei code) pval) vec v vec r "vectorMapValAux"- free pval- return r--vectorZipAux fun code u v = unsafePerformIO $ do- r <- createVector (dim u)- app3 (fun (fromei code)) vec u vec v vec r "vectorZipAux"- return r--------------------------------------------------------------------------- | obtains different functions of a vector: norm1, norm2, max, min, posmax, posmin, etc.-toScalarR :: FunCodeS -> Vector Double -> Double-toScalarR oper = toScalarAux c_toScalarR (fromei oper)--foreign import ccall unsafe "gsl-aux.h toScalarR" c_toScalarR :: CInt -> TVV---- | obtains different functions of a vector: norm1, norm2, max, min, posmax, posmin, etc.-toScalarF :: FunCodeS -> Vector Float -> Float-toScalarF oper = toScalarAux c_toScalarF (fromei oper)--foreign import ccall unsafe "gsl-aux.h toScalarF" c_toScalarF :: CInt -> TFF---- | obtains different functions of a vector: only norm1, norm2-toScalarC :: FunCodeS -> Vector (Complex Double) -> Double-toScalarC oper = toScalarAux c_toScalarC (fromei oper)--foreign import ccall unsafe "gsl-aux.h toScalarC" c_toScalarC :: CInt -> TCVV---- | obtains different functions of a vector: only norm1, norm2-toScalarQ :: FunCodeS -> Vector (Complex Float) -> Float-toScalarQ oper = toScalarAux c_toScalarQ (fromei oper)--foreign import ccall unsafe "gsl-aux.h toScalarQ" c_toScalarQ :: CInt -> TQVF------------------------------------------------------------------------ | map of real vectors with given function-vectorMapR :: FunCodeV -> Vector Double -> Vector Double-vectorMapR = vectorMapAux c_vectorMapR--foreign import ccall unsafe "gsl-aux.h mapR" c_vectorMapR :: CInt -> TVV---- | map of complex vectors with given function-vectorMapC :: FunCodeV -> Vector (Complex Double) -> Vector (Complex Double)-vectorMapC oper = vectorMapAux c_vectorMapC (fromei oper)--foreign import ccall unsafe "gsl-aux.h mapC" c_vectorMapC :: CInt -> TCVCV---- | map of real vectors with given function-vectorMapF :: FunCodeV -> Vector Float -> Vector Float-vectorMapF = vectorMapAux c_vectorMapF--foreign import ccall unsafe "gsl-aux.h mapF" c_vectorMapF :: CInt -> TFF---- | map of real vectors with given function-vectorMapQ :: FunCodeV -> Vector (Complex Float) -> Vector (Complex Float)-vectorMapQ = vectorMapAux c_vectorMapQ--foreign import ccall unsafe "gsl-aux.h mapQ" c_vectorMapQ :: CInt -> TQVQV------------------------------------------------------------------------- | map of real vectors with given function-vectorMapValR :: FunCodeSV -> Double -> Vector Double -> Vector Double-vectorMapValR oper = vectorMapValAux c_vectorMapValR (fromei oper)--foreign import ccall unsafe "gsl-aux.h mapValR" c_vectorMapValR :: CInt -> Ptr Double -> TVV---- | map of complex vectors with given function-vectorMapValC :: FunCodeSV -> Complex Double -> Vector (Complex Double) -> Vector (Complex Double)-vectorMapValC = vectorMapValAux c_vectorMapValC--foreign import ccall unsafe "gsl-aux.h mapValC" c_vectorMapValC :: CInt -> Ptr (Complex Double) -> TCVCV---- | map of real vectors with given function-vectorMapValF :: FunCodeSV -> Float -> Vector Float -> Vector Float-vectorMapValF oper = vectorMapValAux c_vectorMapValF (fromei oper)--foreign import ccall unsafe "gsl-aux.h mapValF" c_vectorMapValF :: CInt -> Ptr Float -> TFF---- | map of complex vectors with given function-vectorMapValQ :: FunCodeSV -> Complex Float -> Vector (Complex Float) -> Vector (Complex Float)-vectorMapValQ oper = vectorMapValAux c_vectorMapValQ (fromei oper)--foreign import ccall unsafe "gsl-aux.h mapValQ" c_vectorMapValQ :: CInt -> Ptr (Complex Float) -> TQVQV------------------------------------------------------------------------- | elementwise operation on real vectors-vectorZipR :: FunCodeVV -> Vector Double -> Vector Double -> Vector Double-vectorZipR = vectorZipAux c_vectorZipR--foreign import ccall unsafe "gsl-aux.h zipR" c_vectorZipR :: CInt -> TVVV---- | elementwise operation on complex vectors-vectorZipC :: FunCodeVV -> Vector (Complex Double) -> Vector (Complex Double) -> Vector (Complex Double)-vectorZipC = vectorZipAux c_vectorZipC--foreign import ccall unsafe "gsl-aux.h zipC" c_vectorZipC :: CInt -> TCVCVCV---- | elementwise operation on real vectors-vectorZipF :: FunCodeVV -> Vector Float -> Vector Float -> Vector Float-vectorZipF = vectorZipAux c_vectorZipF--foreign import ccall unsafe "gsl-aux.h zipF" c_vectorZipF :: CInt -> TFFF---- | elementwise operation on complex vectors-vectorZipQ :: FunCodeVV -> Vector (Complex Float) -> Vector (Complex Float) -> Vector (Complex Float)-vectorZipQ = vectorZipAux c_vectorZipQ--foreign import ccall unsafe "gsl-aux.h zipQ" c_vectorZipQ :: CInt -> TQVQVQV---------------------------------------------------------------------------data RandDist = Uniform -- ^ uniform distribution in [0,1)- | Gaussian -- ^ normal distribution with mean zero and standard deviation one- deriving Enum---- | Obtains a vector of pseudorandom elements from the the mt19937 generator in GSL, with a given seed. Use randomIO to get a random seed.-randomVector :: Int -- ^ seed- -> RandDist -- ^ distribution- -> Int -- ^ vector size- -> Vector Double-randomVector seed dist n = unsafePerformIO $ do- r <- createVector n- app1 (c_random_vector (fi seed) ((fi.fromEnum) dist)) vec r "randomVector"- return r--foreign import ccall unsafe "random_vector" c_random_vector :: CInt -> CInt -> TV
@@ -1,1472 +0,0 @@-#include <gsl/gsl_complex.h>--#define RVEC(A) int A##n, double*A##p-#define RMAT(A) int A##r, int A##c, double* A##p-#define KRVEC(A) int A##n, const double*A##p-#define KRMAT(A) int A##r, int A##c, const double* A##p--#define CVEC(A) int A##n, gsl_complex*A##p-#define CMAT(A) int A##r, int A##c, gsl_complex* A##p-#define KCVEC(A) int A##n, const gsl_complex*A##p-#define KCMAT(A) int A##r, int A##c, const gsl_complex* A##p--#define FVEC(A) int A##n, float*A##p-#define FMAT(A) int A##r, int A##c, float* A##p-#define KFVEC(A) int A##n, const float*A##p-#define KFMAT(A) int A##r, int A##c, const float* A##p--#define QVEC(A) int A##n, gsl_complex_float*A##p-#define QMAT(A) int A##r, int A##c, gsl_complex_float* A##p-#define KQVEC(A) int A##n, const gsl_complex_float*A##p-#define KQMAT(A) int A##r, int A##c, const gsl_complex_float* A##p--#include <gsl/gsl_blas.h>-#include <gsl/gsl_math.h>-#include <gsl/gsl_errno.h>-#include <gsl/gsl_fft_complex.h>-#include <gsl/gsl_integration.h>-#include <gsl/gsl_deriv.h>-#include <gsl/gsl_poly.h>-#include <gsl/gsl_multimin.h>-#include <gsl/gsl_multiroots.h>-#include <gsl/gsl_complex_math.h>-#include <gsl/gsl_rng.h>-#include <gsl/gsl_randist.h>-#include <gsl/gsl_roots.h>-#include <gsl/gsl_multifit_nlin.h>-#include <string.h>-#include <stdio.h>--#define MACRO(B) do {B} while (0)-#define ERROR(CODE) MACRO(return CODE;)-#define REQUIRES(COND, CODE) MACRO(if(!(COND)) {ERROR(CODE);})-#define OK return 0;--#define MIN(A,B) ((A)<(B)?(A):(B))-#define MAX(A,B) ((A)>(B)?(A):(B))--#ifdef DBG-#define DEBUGMSG(M) printf("*** calling aux C function: %s\n",M);-#else-#define DEBUGMSG(M)-#endif--#define CHECK(RES,CODE) MACRO(if(RES) return CODE;)--#ifdef DBG-#define DEBUGMAT(MSG,X) printf(MSG" = \n"); gsl_matrix_fprintf(stdout,X,"%f"); printf("\n");-#else-#define DEBUGMAT(MSG,X)-#endif--#ifdef DBG-#define DEBUGVEC(MSG,X) printf(MSG" = \n"); gsl_vector_fprintf(stdout,X,"%f"); printf("\n");-#else-#define DEBUGVEC(MSG,X)-#endif--#define DVVIEW(A) gsl_vector_view A = gsl_vector_view_array(A##p,A##n)-#define DMVIEW(A) gsl_matrix_view A = gsl_matrix_view_array(A##p,A##r,A##c)-#define CVVIEW(A) gsl_vector_complex_view A = gsl_vector_complex_view_array((double*)A##p,A##n)-#define CMVIEW(A) gsl_matrix_complex_view A = gsl_matrix_complex_view_array((double*)A##p,A##r,A##c)-#define KDVVIEW(A) gsl_vector_const_view A = gsl_vector_const_view_array(A##p,A##n)-#define KDMVIEW(A) gsl_matrix_const_view A = gsl_matrix_const_view_array(A##p,A##r,A##c)-#define KCVVIEW(A) gsl_vector_complex_const_view A = gsl_vector_complex_const_view_array((double*)A##p,A##n)-#define KCMVIEW(A) gsl_matrix_complex_const_view A = gsl_matrix_complex_const_view_array((double*)A##p,A##r,A##c)--#define FVVIEW(A) gsl_vector_float_view A = gsl_vector_float_view_array(A##p,A##n)-#define FMVIEW(A) gsl_matrix_float_view A = gsl_matrix_float_view_array(A##p,A##r,A##c)-#define QVVIEW(A) gsl_vector_complex_float_view A = gsl_vector_float_complex_view_array((float*)A##p,A##n)-#define QMVIEW(A) gsl_matrix_complex_float_view A = gsl_matrix_float_complex_view_array((float*)A##p,A##r,A##c)-#define KFVVIEW(A) gsl_vector_float_const_view A = gsl_vector_float_const_view_array(A##p,A##n)-#define KFMVIEW(A) gsl_matrix_float_const_view A = gsl_matrix_float_const_view_array(A##p,A##r,A##c)-#define KQVVIEW(A) gsl_vector_complex_float_const_view A = gsl_vector_complex_float_const_view_array((float*)A##p,A##n)-#define KQMVIEW(A) gsl_matrix_complex_float_const_view A = gsl_matrix_complex_float_const_view_array((float*)A##p,A##r,A##c)--#define V(a) (&a.vector)-#define M(a) (&a.matrix)--#define GCVEC(A) int A##n, gsl_complex*A##p-#define KGCVEC(A) int A##n, const gsl_complex*A##p--#define GQVEC(A) int A##n, gsl_complex_float*A##p-#define KGQVEC(A) int A##n, const gsl_complex_float*A##p--#define BAD_SIZE 2000-#define BAD_CODE 2001-#define MEM 2002-#define BAD_FILE 2003---void no_abort_on_error() {- gsl_set_error_handler_off();-}---int sumF(KFVEC(x),FVEC(r)) {- DEBUGMSG("sumF");- REQUIRES(rn==1,BAD_SIZE);- int i;- float res = 0;- for (i = 0; i < xn; i++) res += xp[i];- rp[0] = res;- OK-}- -int sumR(KRVEC(x),RVEC(r)) {- DEBUGMSG("sumR");- REQUIRES(rn==1,BAD_SIZE);- int i;- double res = 0;- for (i = 0; i < xn; i++) res += xp[i];- rp[0] = res;- OK-}- -int sumQ(KQVEC(x),QVEC(r)) {- DEBUGMSG("sumQ");- REQUIRES(rn==1,BAD_SIZE);- int i;- gsl_complex_float res;- res.dat[0] = 0;- res.dat[1] = 0;- for (i = 0; i < xn; i++) {- res.dat[0] += xp[i].dat[0];- res.dat[1] += xp[i].dat[1];- }- rp[0] = res;- OK-}- -int sumC(KCVEC(x),CVEC(r)) {- DEBUGMSG("sumC");- REQUIRES(rn==1,BAD_SIZE);- int i;- gsl_complex res;- res.dat[0] = 0;- res.dat[1] = 0;- for (i = 0; i < xn; i++) {- res.dat[0] += xp[i].dat[0];- res.dat[1] += xp[i].dat[1];- }- rp[0] = res;- OK-}--int prodF(KFVEC(x),FVEC(r)) {- DEBUGMSG("prodF");- REQUIRES(rn==1,BAD_SIZE);- int i;- float res = 1;- for (i = 0; i < xn; i++) res *= xp[i];- rp[0] = res;- OK-}- -int prodR(KRVEC(x),RVEC(r)) {- DEBUGMSG("prodR");- REQUIRES(rn==1,BAD_SIZE);- int i;- double res = 1;- for (i = 0; i < xn; i++) res *= xp[i];- rp[0] = res;- OK-}- -int prodQ(KQVEC(x),QVEC(r)) {- DEBUGMSG("prodQ");- REQUIRES(rn==1,BAD_SIZE);- int i;- gsl_complex_float res;- float temp;- res.dat[0] = 1;- res.dat[1] = 0;- for (i = 0; i < xn; i++) {- temp = res.dat[0] * xp[i].dat[0] - res.dat[1] * xp[i].dat[1];- res.dat[1] = res.dat[0] * xp[i].dat[1] + res.dat[1] * xp[i].dat[0];- res.dat[0] = temp;- }- rp[0] = res;- OK-}- -int prodC(KCVEC(x),CVEC(r)) {- DEBUGMSG("prodC");- REQUIRES(rn==1,BAD_SIZE);- int i;- gsl_complex res;- double temp;- res.dat[0] = 1;- res.dat[1] = 0;- for (i = 0; i < xn; i++) {- temp = res.dat[0] * xp[i].dat[0] - res.dat[1] * xp[i].dat[1];- res.dat[1] = res.dat[0] * xp[i].dat[1] + res.dat[1] * xp[i].dat[0];- res.dat[0] = temp;- }- rp[0] = res;- OK-}--int dotF(KFVEC(x), KFVEC(y), FVEC(r)) {- DEBUGMSG("dotF");- REQUIRES(xn==yn,BAD_SIZE); - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("dotF");- KFVVIEW(x);- KFVVIEW(y);- gsl_blas_sdot(V(x),V(y),rp);- OK-}- -int dotR(KRVEC(x), KRVEC(y), RVEC(r)) {- DEBUGMSG("dotR");- REQUIRES(xn==yn,BAD_SIZE); - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("dotR");- KDVVIEW(x);- KDVVIEW(y);- gsl_blas_ddot(V(x),V(y),rp);- OK-}- -int dotQ(KQVEC(x), KQVEC(y), QVEC(r)) {- DEBUGMSG("dotQ");- REQUIRES(xn==yn,BAD_SIZE); - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("dotQ");- KQVVIEW(x);- KQVVIEW(y);- gsl_blas_cdotu(V(x),V(y),rp);- OK-}- -int dotC(KCVEC(x), KCVEC(y), CVEC(r)) {- DEBUGMSG("dotC");- REQUIRES(xn==yn,BAD_SIZE); - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("dotC");- KCVVIEW(x);- KCVVIEW(y);- gsl_blas_zdotu(V(x),V(y),rp);- OK-}- -int toScalarR(int code, KRVEC(x), RVEC(r)) { - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("toScalarR");- KDVVIEW(x);- double res;- switch(code) {- case 0: { res = gsl_blas_dnrm2(V(x)); break; } - case 1: { res = gsl_blas_dasum(V(x)); break; }- case 2: { res = gsl_vector_max_index(V(x)); break; }- case 3: { res = gsl_vector_max(V(x)); break; }- case 4: { res = gsl_vector_min_index(V(x)); break; }- case 5: { res = gsl_vector_min(V(x)); break; }- default: ERROR(BAD_CODE);- }- rp[0] = res;- OK-}--int toScalarF(int code, KFVEC(x), FVEC(r)) { - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("toScalarF");- KFVVIEW(x);- float res;- switch(code) {- case 0: { res = gsl_blas_snrm2(V(x)); break; } - case 1: { res = gsl_blas_sasum(V(x)); break; }- case 2: { res = gsl_vector_float_max_index(V(x)); break; }- case 3: { res = gsl_vector_float_max(V(x)); break; }- case 4: { res = gsl_vector_float_min_index(V(x)); break; }- case 5: { res = gsl_vector_float_min(V(x)); break; }- default: ERROR(BAD_CODE);- }- rp[0] = res;- OK-}---int toScalarC(int code, KCVEC(x), RVEC(r)) { - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("toScalarC");- KCVVIEW(x);- double res;- switch(code) {- case 0: { res = gsl_blas_dznrm2(V(x)); break; } - case 1: { res = gsl_blas_dzasum(V(x)); break; }- default: ERROR(BAD_CODE);- }- rp[0] = res;- OK-}--int toScalarQ(int code, KQVEC(x), FVEC(r)) { - REQUIRES(rn==1,BAD_SIZE);- DEBUGMSG("toScalarQ");- KQVVIEW(x);- float res;- switch(code) {- case 0: { res = gsl_blas_scnrm2(V(x)); break; } - case 1: { res = gsl_blas_scasum(V(x)); break; }- default: ERROR(BAD_CODE);- }- rp[0] = res;- OK-}---inline double sign(double x) {- if(x>0) {- return +1.0;- } else if (x<0) {- return -1.0;- } else {- return 0.0;- }-}--inline float float_sign(float x) {- if(x>0) {- return +1.0;- } else if (x<0) {- return -1.0;- } else {- return 0.0;- }-}--inline gsl_complex complex_abs(gsl_complex z) {- gsl_complex r;- r.dat[0] = gsl_complex_abs(z);- r.dat[1] = 0;- return r;-}--inline gsl_complex complex_signum(gsl_complex z) {- gsl_complex r;- double mag;- if (z.dat[0] == 0 && z.dat[1] == 0) {- r.dat[0] = 0;- r.dat[1] = 0;- } else {- mag = gsl_complex_abs(z);- r.dat[0] = z.dat[0]/mag;- r.dat[1] = z.dat[1]/mag;- }- return r;-}--#define OP(C,F) case C: { for(k=0;k<xn;k++) rp[k] = F(xp[k]); OK }-#define OPV(C,E) case C: { for(k=0;k<xn;k++) rp[k] = E; OK }-int mapR(int code, KRVEC(x), RVEC(r)) {- int k;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapR");- switch (code) {- OP(0,sin)- OP(1,cos)- OP(2,tan)- OP(3,fabs)- OP(4,asin)- OP(5,acos)- OP(6,atan) /* atan2 mediante vectorZip */- OP(7,sinh)- OP(8,cosh)- OP(9,tanh)- OP(10,gsl_asinh)- OP(11,gsl_acosh)- OP(12,gsl_atanh)- OP(13,exp)- OP(14,log)- OP(15,sign)- OP(16,sqrt)- default: ERROR(BAD_CODE);- }-}--int mapF(int code, KFVEC(x), FVEC(r)) {- int k;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapF");- switch (code) {- OP(0,sin)- OP(1,cos)- OP(2,tan)- OP(3,fabs)- OP(4,asin)- OP(5,acos)- OP(6,atan) /* atan2 mediante vectorZip */- OP(7,sinh)- OP(8,cosh)- OP(9,tanh)- OP(10,gsl_asinh)- OP(11,gsl_acosh)- OP(12,gsl_atanh)- OP(13,exp)- OP(14,log)- OP(15,sign)- OP(16,sqrt)- default: ERROR(BAD_CODE);- }-}---int mapCAux(int code, KGCVEC(x), GCVEC(r)) {- int k;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapC");- switch (code) {- OP(0,gsl_complex_sin)- OP(1,gsl_complex_cos)- OP(2,gsl_complex_tan)- OP(3,complex_abs)- OP(4,gsl_complex_arcsin)- OP(5,gsl_complex_arccos)- OP(6,gsl_complex_arctan)- OP(7,gsl_complex_sinh)- OP(8,gsl_complex_cosh)- OP(9,gsl_complex_tanh)- OP(10,gsl_complex_arcsinh)- OP(11,gsl_complex_arccosh)- OP(12,gsl_complex_arctanh)- OP(13,gsl_complex_exp)- OP(14,gsl_complex_log)- OP(15,complex_signum)- OP(16,gsl_complex_sqrt)-- // gsl_complex_arg- // gsl_complex_abs- default: ERROR(BAD_CODE);- }-}--int mapC(int code, KCVEC(x), CVEC(r)) {- return mapCAux(code, xn, (gsl_complex*)xp, rn, (gsl_complex*)rp);-}---gsl_complex_float complex_float_math_fun(gsl_complex (*cf)(gsl_complex), gsl_complex_float a)-{- gsl_complex c;- gsl_complex r;-- gsl_complex_float float_r;-- c.dat[0] = a.dat[0];- c.dat[1] = a.dat[1];-- r = (*cf)(c);-- float_r.dat[0] = r.dat[0];- float_r.dat[1] = r.dat[1];-- return float_r;-}--gsl_complex_float complex_float_math_op(gsl_complex (*cf)(gsl_complex,gsl_complex), - gsl_complex_float a,gsl_complex_float b)-{- gsl_complex c1;- gsl_complex c2;- gsl_complex r;-- gsl_complex_float float_r;-- c1.dat[0] = a.dat[0];- c1.dat[1] = a.dat[1];-- c2.dat[0] = b.dat[0];- c2.dat[1] = b.dat[1];-- r = (*cf)(c1,c2);-- float_r.dat[0] = r.dat[0];- float_r.dat[1] = r.dat[1];-- return float_r;-}--#define OPC(C,F) case C: { for(k=0;k<xn;k++) rp[k] = complex_float_math_fun(&F,xp[k]); OK }-#define OPCA(C,F,A,B) case C: { for(k=0;k<xn;k++) rp[k] = complex_float_math_op(&F,A,B); OK }-int mapQAux(int code, KGQVEC(x), GQVEC(r)) {- int k;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapQ");- switch (code) {- OPC(0,gsl_complex_sin)- OPC(1,gsl_complex_cos)- OPC(2,gsl_complex_tan)- OPC(3,complex_abs)- OPC(4,gsl_complex_arcsin)- OPC(5,gsl_complex_arccos)- OPC(6,gsl_complex_arctan)- OPC(7,gsl_complex_sinh)- OPC(8,gsl_complex_cosh)- OPC(9,gsl_complex_tanh)- OPC(10,gsl_complex_arcsinh)- OPC(11,gsl_complex_arccosh)- OPC(12,gsl_complex_arctanh)- OPC(13,gsl_complex_exp)- OPC(14,gsl_complex_log)- OPC(15,complex_signum)- OPC(16,gsl_complex_sqrt)-- // gsl_complex_arg- // gsl_complex_abs- default: ERROR(BAD_CODE);- }-}--int mapQ(int code, KQVEC(x), QVEC(r)) {- return mapQAux(code, xn, (gsl_complex_float*)xp, rn, (gsl_complex_float*)rp);-}---int mapValR(int code, double* pval, KRVEC(x), RVEC(r)) {- int k;- double val = *pval;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapValR");- switch (code) {- OPV(0,val*xp[k])- OPV(1,val/xp[k])- OPV(2,val+xp[k])- OPV(3,val-xp[k])- OPV(4,pow(val,xp[k]))- OPV(5,pow(xp[k],val))- default: ERROR(BAD_CODE);- }-}--int mapValF(int code, float* pval, KFVEC(x), FVEC(r)) {- int k;- float val = *pval;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapValF");- switch (code) {- OPV(0,val*xp[k])- OPV(1,val/xp[k])- OPV(2,val+xp[k])- OPV(3,val-xp[k])- OPV(4,pow(val,xp[k]))- OPV(5,pow(xp[k],val))- default: ERROR(BAD_CODE);- }-}--int mapValCAux(int code, gsl_complex* pval, KGCVEC(x), GCVEC(r)) {- int k;- gsl_complex val = *pval;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapValC");- switch (code) {- OPV(0,gsl_complex_mul(val,xp[k]))- OPV(1,gsl_complex_div(val,xp[k]))- OPV(2,gsl_complex_add(val,xp[k]))- OPV(3,gsl_complex_sub(val,xp[k]))- OPV(4,gsl_complex_pow(val,xp[k]))- OPV(5,gsl_complex_pow(xp[k],val))- default: ERROR(BAD_CODE);- }-}--int mapValC(int code, gsl_complex* val, KCVEC(x), CVEC(r)) {- return mapValCAux(code, val, xn, (gsl_complex*)xp, rn, (gsl_complex*)rp);-}---int mapValQAux(int code, gsl_complex_float* pval, KQVEC(x), GQVEC(r)) {- int k;- gsl_complex_float val = *pval;- REQUIRES(xn == rn,BAD_SIZE);- DEBUGMSG("mapValQ");- switch (code) {- OPCA(0,gsl_complex_mul,val,xp[k])- OPCA(1,gsl_complex_div,val,xp[k])- OPCA(2,gsl_complex_add,val,xp[k])- OPCA(3,gsl_complex_sub,val,xp[k])- OPCA(4,gsl_complex_pow,val,xp[k])- OPCA(5,gsl_complex_pow,xp[k],val)- default: ERROR(BAD_CODE);- }-}--int mapValQ(int code, gsl_complex_float* val, KQVEC(x), QVEC(r)) {- return mapValQAux(code, val, xn, (gsl_complex_float*)xp, rn, (gsl_complex_float*)rp);-}---#define OPZE(C,msg,E) case C: {DEBUGMSG(msg) for(k=0;k<an;k++) rp[k] = E(ap[k],bp[k]); OK }-#define OPZV(C,msg,E) case C: {DEBUGMSG(msg) res = E(V(r),V(b)); CHECK(res,res); OK }-int zipR(int code, KRVEC(a), KRVEC(b), RVEC(r)) {- REQUIRES(an == bn && an == rn, BAD_SIZE);- int k;- switch(code) {- OPZE(4,"zipR Pow",pow)- OPZE(5,"zipR ATan2",atan2)- }- KDVVIEW(a);- KDVVIEW(b);- DVVIEW(r);- gsl_vector_memcpy(V(r),V(a));- int res;- switch(code) {- OPZV(0,"zipR Add",gsl_vector_add)- OPZV(1,"zipR Sub",gsl_vector_sub)- OPZV(2,"zipR Mul",gsl_vector_mul)- OPZV(3,"zipR Div",gsl_vector_div)- default: ERROR(BAD_CODE);- }-}---int zipF(int code, KFVEC(a), KFVEC(b), FVEC(r)) {- REQUIRES(an == bn && an == rn, BAD_SIZE);- int k;- switch(code) {- OPZE(4,"zipF Pow",pow)- OPZE(5,"zipF ATan2",atan2)- }- KFVVIEW(a);- KFVVIEW(b);- FVVIEW(r);- gsl_vector_float_memcpy(V(r),V(a));- int res;- switch(code) {- OPZV(0,"zipF Add",gsl_vector_float_add)- OPZV(1,"zipF Sub",gsl_vector_float_sub)- OPZV(2,"zipF Mul",gsl_vector_float_mul)- OPZV(3,"zipF Div",gsl_vector_float_div)- default: ERROR(BAD_CODE);- }-}---int zipCAux(int code, KGCVEC(a), KGCVEC(b), GCVEC(r)) {- REQUIRES(an == bn && an == rn, BAD_SIZE);- int k;- switch(code) {- OPZE(0,"zipC Add",gsl_complex_add)- OPZE(1,"zipC Sub",gsl_complex_sub)- OPZE(2,"zipC Mul",gsl_complex_mul)- OPZE(3,"zipC Div",gsl_complex_div)- OPZE(4,"zipC Pow",gsl_complex_pow)- //OPZE(5,"zipR ATan2",atan2)- }- //KCVVIEW(a);- //KCVVIEW(b);- //CVVIEW(r);- //gsl_vector_memcpy(V(r),V(a));- //int res;- switch(code) {- default: ERROR(BAD_CODE);- }-}---int zipC(int code, KCVEC(a), KCVEC(b), CVEC(r)) {- return zipCAux(code, an, (gsl_complex*)ap, bn, (gsl_complex*)bp, rn, (gsl_complex*)rp);-}---#define OPCZE(C,msg,E) case C: {DEBUGMSG(msg) for(k=0;k<an;k++) rp[k] = complex_float_math_op(&E,ap[k],bp[k]); OK }-int zipQAux(int code, KGQVEC(a), KGQVEC(b), GQVEC(r)) {- REQUIRES(an == bn && an == rn, BAD_SIZE);- int k;- switch(code) {- OPCZE(0,"zipQ Add",gsl_complex_add)- OPCZE(1,"zipQ Sub",gsl_complex_sub)- OPCZE(2,"zipQ Mul",gsl_complex_mul)- OPCZE(3,"zipQ Div",gsl_complex_div)- OPCZE(4,"zipQ Pow",gsl_complex_pow)- //OPZE(5,"zipR ATan2",atan2)- }- //KCVVIEW(a);- //KCVVIEW(b);- //CVVIEW(r);- //gsl_vector_memcpy(V(r),V(a));- //int res;- switch(code) {- default: ERROR(BAD_CODE);- }-}---int zipQ(int code, KQVEC(a), KQVEC(b), QVEC(r)) {- return zipQAux(code, an, (gsl_complex_float*)ap, bn, (gsl_complex_float*)bp, rn, (gsl_complex_float*)rp);-}----int fft(int code, KCVEC(X), CVEC(R)) {- REQUIRES(Xn == Rn,BAD_SIZE);- DEBUGMSG("fft");- int s = Xn;- gsl_fft_complex_wavetable * wavetable = gsl_fft_complex_wavetable_alloc (s);- gsl_fft_complex_workspace * workspace = gsl_fft_complex_workspace_alloc (s);- gsl_vector_const_view X = gsl_vector_const_view_array((double*)Xp, 2*Xn);- gsl_vector_view R = gsl_vector_view_array((double*)Rp, 2*Rn);- gsl_blas_dcopy(&X.vector,&R.vector);- if(code==0) {- gsl_fft_complex_forward ((double*)Rp, 1, s, wavetable, workspace);- } else {- gsl_fft_complex_inverse ((double*)Rp, 1, s, wavetable, workspace);- }- gsl_fft_complex_wavetable_free (wavetable);- gsl_fft_complex_workspace_free (workspace);- OK-}---int deriv(int code, double f(double, void*), double x, double h, double * result, double * abserr)-{- gsl_function F;- F.function = f;- F.params = 0;-- if(code==0) return gsl_deriv_central (&F, x, h, result, abserr);-- if(code==1) return gsl_deriv_forward (&F, x, h, result, abserr);-- if(code==2) return gsl_deriv_backward (&F, x, h, result, abserr);-- return 0;-}---int integrate_qng(double f(double, void*), double a, double b, double prec,- double *result, double*error) {- DEBUGMSG("integrate_qng");- gsl_function F;- F.function = f;- F.params = NULL;- size_t neval;- int res = gsl_integration_qng (&F, a,b, 0, prec, result, error, &neval); - CHECK(res,res);- OK-}--int integrate_qags(double f(double,void*), double a, double b, double prec, int w, - double *result, double* error) {- DEBUGMSG("integrate_qags");- gsl_integration_workspace * wk = gsl_integration_workspace_alloc (w);- gsl_function F;- F.function = f;- F.params = NULL;- int res = gsl_integration_qags (&F, a,b, 0, prec, w,wk, result, error); - CHECK(res,res);- gsl_integration_workspace_free (wk); - OK-}--int integrate_qagi(double f(double,void*), double prec, int w, - double *result, double* error) {- DEBUGMSG("integrate_qagi");- gsl_integration_workspace * wk = gsl_integration_workspace_alloc (w);- gsl_function F;- F.function = f;- F.params = NULL;- int res = gsl_integration_qagi (&F, 0, prec, w,wk, result, error); - CHECK(res,res);- gsl_integration_workspace_free (wk); - OK-}---int integrate_qagiu(double f(double,void*), double a, double prec, int w, - double *result, double* error) {- DEBUGMSG("integrate_qagiu");- gsl_integration_workspace * wk = gsl_integration_workspace_alloc (w);- gsl_function F;- F.function = f;- F.params = NULL;- int res = gsl_integration_qagiu (&F, a, 0, prec, w,wk, result, error); - CHECK(res,res);- gsl_integration_workspace_free (wk); - OK-}---int integrate_qagil(double f(double,void*), double b, double prec, int w, - double *result, double* error) {- DEBUGMSG("integrate_qagil");- gsl_integration_workspace * wk = gsl_integration_workspace_alloc (w);- gsl_function F;- F.function = f;- F.params = NULL;- int res = gsl_integration_qagil (&F, b, 0, prec, w,wk, result, error); - CHECK(res,res);- gsl_integration_workspace_free (wk); - OK-}---int polySolve(KRVEC(a), CVEC(z)) {- DEBUGMSG("polySolve");- REQUIRES(an>1,BAD_SIZE);- gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc (an);- int res = gsl_poly_complex_solve ((double*)ap, an, w, (double*)zp);- CHECK(res,res);- gsl_poly_complex_workspace_free (w);- OK;-}--int vector_fscanf(char*filename, RVEC(a)) {- DEBUGMSG("gsl_vector_fscanf");- DVVIEW(a);- FILE * f = fopen(filename,"r");- CHECK(!f,BAD_FILE);- int res = gsl_vector_fscanf(f,V(a));- CHECK(res,res);- fclose (f);- OK-}--int vector_fprintf(char*filename, char*fmt, RVEC(a)) {- DEBUGMSG("gsl_vector_fprintf");- DVVIEW(a);- FILE * f = fopen(filename,"w");- CHECK(!f,BAD_FILE);- int res = gsl_vector_fprintf(f,V(a),fmt);- CHECK(res,res);- fclose (f);- OK-}--int vector_fread(char*filename, RVEC(a)) {- DEBUGMSG("gsl_vector_fread");- DVVIEW(a);- FILE * f = fopen(filename,"r");- CHECK(!f,BAD_FILE);- int res = gsl_vector_fread(f,V(a));- CHECK(res,res);- fclose (f);- OK-}--int vector_fwrite(char*filename, RVEC(a)) {- DEBUGMSG("gsl_vector_fwrite");- DVVIEW(a);- FILE * f = fopen(filename,"w");- CHECK(!f,BAD_FILE);- int res = gsl_vector_fwrite(f,V(a));- CHECK(res,res);- fclose (f);- OK-}--int matrix_fprintf(char*filename, char*fmt, int ro, RMAT(m)) {- DEBUGMSG("matrix_fprintf");- FILE * f = fopen(filename,"w");- CHECK(!f,BAD_FILE);- int i,j,sr,sc;- if (ro==1) { sr = mc; sc = 1;} else { sr = 1; sc = mr;}- #define AT(M,r,c) (M##p[(r)*sr+(c)*sc])- for (i=0; i<mr; i++) {- for (j=0; j<mc-1; j++) {- fprintf(f,fmt,AT(m,i,j));- fprintf(f," ");- }- fprintf(f,fmt,AT(m,i,j));- fprintf(f,"\n");- }- fclose (f);- OK-}--//-----------------------------------------------------------------typedef double Trawfun(int, double*);--double only_f_aux_min(const gsl_vector*x, void *pars) {- Trawfun * f = (Trawfun*) pars; - double* p = (double*)calloc(x->size,sizeof(double));- int k;- for(k=0;k<x->size;k++) {- p[k] = gsl_vector_get(x,k);- } - double res = f(x->size,p);- free(p);- return res;-}--// this version returns info about intermediate steps-int minimize(int method, double f(int, double*), double tolsize, int maxit, - KRVEC(xi), KRVEC(sz), RMAT(sol)) {- REQUIRES(xin==szn && solr == maxit && solc == 3+xin,BAD_SIZE);- DEBUGMSG("minimizeList (nmsimplex)");- gsl_multimin_function my_func;- // extract function from pars- my_func.f = only_f_aux_min;- my_func.n = xin; - my_func.params = f;- size_t iter = 0;- int status;- double size;- const gsl_multimin_fminimizer_type *T;- gsl_multimin_fminimizer *s = NULL;- // Initial vertex size vector - KDVVIEW(sz);- // Starting point- KDVVIEW(xi);- // Minimizer nmsimplex, without derivatives- switch(method) {- case 0 : {T = gsl_multimin_fminimizer_nmsimplex; break; }-#ifdef GSL110- case 1 : {T = gsl_multimin_fminimizer_nmsimplex; break; }-#else- case 1 : {T = gsl_multimin_fminimizer_nmsimplex2; break; }-#endif- default: ERROR(BAD_CODE);- }- s = gsl_multimin_fminimizer_alloc (T, my_func.n);- gsl_multimin_fminimizer_set (s, &my_func, V(xi), V(sz));- do {- status = gsl_multimin_fminimizer_iterate (s);- size = gsl_multimin_fminimizer_size (s);-- solp[iter*solc+0] = iter+1;- solp[iter*solc+1] = s->fval;- solp[iter*solc+2] = size;-- int k;- for(k=0;k<xin;k++) {- solp[iter*solc+k+3] = gsl_vector_get(s->x,k);- }- iter++;- if (status) break;- status = gsl_multimin_test_size (size, tolsize);- } while (status == GSL_CONTINUE && iter < maxit);- int i,j;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- for(j=1;j<solc;j++) {- solp[i*solc+j]=0.;- }- }- gsl_multimin_fminimizer_free(s);- OK-}--// working with the gradient--typedef struct {double (*f)(int, double*); int (*df)(int, double*, int, double*);} Tfdf;--double f_aux_min(const gsl_vector*x, void *pars) {- Tfdf * fdf = ((Tfdf*) pars);- double* p = (double*)calloc(x->size,sizeof(double));- int k;- for(k=0;k<x->size;k++) {- p[k] = gsl_vector_get(x,k);- }- double res = fdf->f(x->size,p);- free(p);- return res;-}---void df_aux_min(const gsl_vector * x, void * pars, gsl_vector * g) {- Tfdf * fdf = ((Tfdf*) pars);- double* p = (double*)calloc(x->size,sizeof(double));- double* q = (double*)calloc(g->size,sizeof(double));- int k;- for(k=0;k<x->size;k++) {- p[k] = gsl_vector_get(x,k);- }-- fdf->df(x->size,p,g->size,q);-- for(k=0;k<x->size;k++) {- gsl_vector_set(g,k,q[k]);- }- free(p);- free(q);-}--void fdf_aux_min(const gsl_vector * x, void * pars, double * f, gsl_vector * g) {- *f = f_aux_min(x,pars);- df_aux_min(x,pars,g);-}---int minimizeD(int method, double f(int, double*), int df(int, double*, int, double*),- double initstep, double minimpar, double tolgrad, int maxit, - KRVEC(xi), RMAT(sol)) {- REQUIRES(solr == maxit && solc == 2+xin,BAD_SIZE);- DEBUGMSG("minimizeWithDeriv (conjugate_fr)");- gsl_multimin_function_fdf my_func;- // extract function from pars- my_func.f = f_aux_min;- my_func.df = df_aux_min;- my_func.fdf = fdf_aux_min;- my_func.n = xin; - Tfdf stfdf;- stfdf.f = f;- stfdf.df = df;- my_func.params = &stfdf;- size_t iter = 0;- int status;- const gsl_multimin_fdfminimizer_type *T;- gsl_multimin_fdfminimizer *s = NULL;- // Starting point- KDVVIEW(xi);- // conjugate gradient fr- switch(method) {- case 0 : {T = gsl_multimin_fdfminimizer_conjugate_fr; break; }- case 1 : {T = gsl_multimin_fdfminimizer_conjugate_pr; break; }- case 2 : {T = gsl_multimin_fdfminimizer_vector_bfgs; break; }- case 3 : {T = gsl_multimin_fdfminimizer_vector_bfgs2; break; }- case 4 : {T = gsl_multimin_fdfminimizer_steepest_descent; break; }- default: ERROR(BAD_CODE);- }- s = gsl_multimin_fdfminimizer_alloc (T, my_func.n);- gsl_multimin_fdfminimizer_set (s, &my_func, V(xi), initstep, minimpar);- do {- status = gsl_multimin_fdfminimizer_iterate (s);- solp[iter*solc+0] = iter+1;- solp[iter*solc+1] = s->f;- int k;- for(k=0;k<xin;k++) {- solp[iter*solc+k+2] = gsl_vector_get(s->x,k);- }- iter++;- if (status) break;- status = gsl_multimin_test_gradient (s->gradient, tolgrad);- } while (status == GSL_CONTINUE && iter < maxit);- int i,j;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- for(j=1;j<solc;j++) {- solp[i*solc+j]=0.;- }- }- gsl_multimin_fdfminimizer_free(s);- OK-}--//-----------------------------------------------------------------double only_f_aux_root(double x, void *pars) {- double (*f)(double) = (double (*)(double)) pars;- return f(x);-}--int root(int method, double f(double),- double epsrel, int maxit,- double xl, double xu, RMAT(sol)) {- REQUIRES(solr == maxit && solc == 4,BAD_SIZE);- DEBUGMSG("root_only_f");- gsl_function my_func;- // extract function from pars- my_func.function = only_f_aux_root;- my_func.params = f;- size_t iter = 0;- int status;- const gsl_root_fsolver_type *T;- gsl_root_fsolver *s;- // Starting point- switch(method) {- case 0 : {T = gsl_root_fsolver_bisection; printf("7\n"); break; }- case 1 : {T = gsl_root_fsolver_falsepos; break; }- case 2 : {T = gsl_root_fsolver_brent; break; }- default: ERROR(BAD_CODE);- }- s = gsl_root_fsolver_alloc (T);- gsl_root_fsolver_set (s, &my_func, xl, xu);- do {- double best, current_lo, current_hi;- status = gsl_root_fsolver_iterate (s);- best = gsl_root_fsolver_root (s);- current_lo = gsl_root_fsolver_x_lower (s);- current_hi = gsl_root_fsolver_x_upper (s);- solp[iter*solc] = iter + 1;- solp[iter*solc+1] = best;- solp[iter*solc+2] = current_lo;- solp[iter*solc+3] = current_hi;- iter++;- if (status) /* check if solver is stuck */- break;-- status =- gsl_root_test_interval (current_lo, current_hi, 0, epsrel);- }- while (status == GSL_CONTINUE && iter < maxit);- int i;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- solp[i*solc+1]=0.;- solp[i*solc+2]=0.;- solp[i*solc+3]=0.;- }- gsl_root_fsolver_free(s);- OK-}--typedef struct {- double (*f)(double);- double (*jf)(double);-} uniTfjf;--double f_aux_uni(double x, void *pars) {- uniTfjf * fjf = ((uniTfjf*) pars);- return (fjf->f)(x);-}--double jf_aux_uni(double x, void * pars) {- uniTfjf * fjf = ((uniTfjf*) pars);- return (fjf->jf)(x);-}--void fjf_aux_uni(double x, void * pars, double * f, double * g) {- *f = f_aux_uni(x,pars);- *g = jf_aux_uni(x,pars);-}--int rootj(int method, double f(double),- double df(double),- double epsrel, int maxit,- double x, RMAT(sol)) {- REQUIRES(solr == maxit && solc == 2,BAD_SIZE);- DEBUGMSG("root_fjf");- gsl_function_fdf my_func;- // extract function from pars- my_func.f = f_aux_uni;- my_func.df = jf_aux_uni;- my_func.fdf = fjf_aux_uni;- uniTfjf stfjf;- stfjf.f = f;- stfjf.jf = df;- my_func.params = &stfjf;- size_t iter = 0;- int status;- const gsl_root_fdfsolver_type *T;- gsl_root_fdfsolver *s;- // Starting point- switch(method) {- case 0 : {T = gsl_root_fdfsolver_newton;; break; }- case 1 : {T = gsl_root_fdfsolver_secant; break; }- case 2 : {T = gsl_root_fdfsolver_steffenson; break; }- default: ERROR(BAD_CODE);- }- s = gsl_root_fdfsolver_alloc (T);-- gsl_root_fdfsolver_set (s, &my_func, x);-- do {- double x0;- status = gsl_root_fdfsolver_iterate (s);- x0 = x;- x = gsl_root_fdfsolver_root(s);- solp[iter*solc+0] = iter+1;- solp[iter*solc+1] = x;-- iter++;- if (status) /* check if solver is stuck */- break;-- status =- gsl_root_test_delta (x, x0, 0, epsrel);- }- while (status == GSL_CONTINUE && iter < maxit);-- int i;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- solp[i*solc+1]=0.;- }- gsl_root_fdfsolver_free(s);- OK-}---//-----------------------------------------------------------------typedef void TrawfunV(int, double*, int, double*);--int only_f_aux_multiroot(const gsl_vector*x, void *pars, gsl_vector*y) {- TrawfunV * f = (TrawfunV*) pars;- double* p = (double*)calloc(x->size,sizeof(double));- double* q = (double*)calloc(y->size,sizeof(double));- int k;- for(k=0;k<x->size;k++) {- p[k] = gsl_vector_get(x,k);- }- f(x->size,p,y->size,q);- for(k=0;k<y->size;k++) {- gsl_vector_set(y,k,q[k]);- }- free(p);- free(q);- return 0; //hmmm-}--int multiroot(int method, void f(int, double*, int, double*),- double epsabs, int maxit,- KRVEC(xi), RMAT(sol)) {- REQUIRES(solr == maxit && solc == 1+2*xin,BAD_SIZE);- DEBUGMSG("root_only_f");- gsl_multiroot_function my_func;- // extract function from pars- my_func.f = only_f_aux_multiroot;- my_func.n = xin;- my_func.params = f;- size_t iter = 0;- int status;- const gsl_multiroot_fsolver_type *T;- gsl_multiroot_fsolver *s;- // Starting point- KDVVIEW(xi);- switch(method) {- case 0 : {T = gsl_multiroot_fsolver_hybrids;; break; }- case 1 : {T = gsl_multiroot_fsolver_hybrid; break; }- case 2 : {T = gsl_multiroot_fsolver_dnewton; break; }- case 3 : {T = gsl_multiroot_fsolver_broyden; break; }- default: ERROR(BAD_CODE);- }- s = gsl_multiroot_fsolver_alloc (T, my_func.n);- gsl_multiroot_fsolver_set (s, &my_func, V(xi));-- do {- status = gsl_multiroot_fsolver_iterate (s);-- solp[iter*solc+0] = iter+1;-- int k;- for(k=0;k<xin;k++) {- solp[iter*solc+k+1] = gsl_vector_get(s->x,k);- }- for(k=xin;k<2*xin;k++) {- solp[iter*solc+k+1] = gsl_vector_get(s->f,k-xin);- }-- iter++;- if (status) /* check if solver is stuck */- break;-- status =- gsl_multiroot_test_residual (s->f, epsabs);- }- while (status == GSL_CONTINUE && iter < maxit);-- int i,j;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- for(j=1;j<solc;j++) {- solp[i*solc+j]=0.;- }- }- gsl_multiroot_fsolver_free(s);- OK-}--// working with the jacobian--typedef struct {int (*f)(int, double*, int, double *);- int (*jf)(int, double*, int, int, double*);} Tfjf;--int f_aux(const gsl_vector*x, void *pars, gsl_vector*y) {- Tfjf * fjf = ((Tfjf*) pars);- double* p = (double*)calloc(x->size,sizeof(double));- double* q = (double*)calloc(y->size,sizeof(double));- int k;- for(k=0;k<x->size;k++) {- p[k] = gsl_vector_get(x,k);- }- (fjf->f)(x->size,p,y->size,q);- for(k=0;k<y->size;k++) {- gsl_vector_set(y,k,q[k]);- }- free(p);- free(q);- return 0;-}--int jf_aux(const gsl_vector * x, void * pars, gsl_matrix * jac) {- Tfjf * fjf = ((Tfjf*) pars);- double* p = (double*)calloc(x->size,sizeof(double));- double* q = (double*)calloc((jac->size1)*(jac->size2),sizeof(double));- int i,j,k;- for(k=0;k<x->size;k++) {- p[k] = gsl_vector_get(x,k);- }-- (fjf->jf)(x->size,p,jac->size1,jac->size2,q);-- k=0;- for(i=0;i<jac->size1;i++) {- for(j=0;j<jac->size2;j++){- gsl_matrix_set(jac,i,j,q[k++]);- }- }- free(p);- free(q);- return 0;-}--int fjf_aux(const gsl_vector * x, void * pars, gsl_vector * f, gsl_matrix * g) {- f_aux(x,pars,f);- jf_aux(x,pars,g);- return 0;-}--int multirootj(int method, int f(int, double*, int, double*),- int jac(int, double*, int, int, double*),- double epsabs, int maxit,- KRVEC(xi), RMAT(sol)) {- REQUIRES(solr == maxit && solc == 1+2*xin,BAD_SIZE);- DEBUGMSG("root_fjf");- gsl_multiroot_function_fdf my_func;- // extract function from pars- my_func.f = f_aux;- my_func.df = jf_aux;- my_func.fdf = fjf_aux;- my_func.n = xin;- Tfjf stfjf;- stfjf.f = f;- stfjf.jf = jac;- my_func.params = &stfjf;- size_t iter = 0;- int status;- const gsl_multiroot_fdfsolver_type *T;- gsl_multiroot_fdfsolver *s;- // Starting point- KDVVIEW(xi);- switch(method) {- case 0 : {T = gsl_multiroot_fdfsolver_hybridsj;; break; }- case 1 : {T = gsl_multiroot_fdfsolver_hybridj; break; }- case 2 : {T = gsl_multiroot_fdfsolver_newton; break; }- case 3 : {T = gsl_multiroot_fdfsolver_gnewton; break; }- default: ERROR(BAD_CODE);- }- s = gsl_multiroot_fdfsolver_alloc (T, my_func.n);-- gsl_multiroot_fdfsolver_set (s, &my_func, V(xi));-- do {- status = gsl_multiroot_fdfsolver_iterate (s);-- solp[iter*solc+0] = iter+1;-- int k;- for(k=0;k<xin;k++) {- solp[iter*solc+k+1] = gsl_vector_get(s->x,k);- }- for(k=xin;k<2*xin;k++) {- solp[iter*solc+k+1] = gsl_vector_get(s->f,k-xin);- }-- iter++;- if (status) /* check if solver is stuck */- break;-- status =- gsl_multiroot_test_residual (s->f, epsabs);- }- while (status == GSL_CONTINUE && iter < maxit);-- int i,j;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- for(j=1;j<solc;j++) {- solp[i*solc+j]=0.;- }- }- gsl_multiroot_fdfsolver_free(s);- OK-}--//-------------- non linear least squares fitting ---------------------int nlfit(int method, int f(int, double*, int, double*),- int jac(int, double*, int, int, double*),- double epsabs, double epsrel, int maxit, int p,- KRVEC(xi), RMAT(sol)) {- REQUIRES(solr == maxit && solc == 2+xin,BAD_SIZE);- DEBUGMSG("nlfit");- const gsl_multifit_fdfsolver_type *T;- gsl_multifit_fdfsolver *s;- gsl_multifit_function_fdf my_f;- // extract function from pars- my_f.f = f_aux;- my_f.df = jf_aux;- my_f.fdf = fjf_aux;- my_f.n = p;- my_f.p = xin; // !!!!- Tfjf stfjf;- stfjf.f = f;- stfjf.jf = jac;- my_f.params = &stfjf;- size_t iter = 0;- int status;-- KDVVIEW(xi);- //DMVIEW(cov);-- switch(method) {- case 0 : { T = gsl_multifit_fdfsolver_lmsder; break; }- case 1 : { T = gsl_multifit_fdfsolver_lmder; break; }- default: ERROR(BAD_CODE);- }-- s = gsl_multifit_fdfsolver_alloc (T, my_f.n, my_f.p);- gsl_multifit_fdfsolver_set (s, &my_f, V(xi));-- do { status = gsl_multifit_fdfsolver_iterate (s);-- solp[iter*solc+0] = iter+1;- solp[iter*solc+1] = gsl_blas_dnrm2 (s->f);-- int k;- for(k=0;k<xin;k++) {- solp[iter*solc+k+2] = gsl_vector_get(s->x,k);- }-- iter++;- if (status) /* check if solver is stuck */- break;-- status = gsl_multifit_test_delta (s->dx, s->x, epsabs, epsrel);- }- while (status == GSL_CONTINUE && iter < maxit);-- int i,j;- for (i=iter; i<solr; i++) {- solp[i*solc+0] = iter;- for(j=1;j<solc;j++) {- solp[i*solc+j]=0.;- }- }-- //gsl_multifit_covar (s->J, 0.0, M(cov));-- gsl_multifit_fdfsolver_free (s);- OK-}---//////////////////////////////////////////////////////---#define RAN(C,F) case C: { for(k=0;k<rn;k++) { rp[k]= F(gen); }; OK }--int random_vector(int seed, int code, RVEC(r)) {- DEBUGMSG("random_vector")- static gsl_rng * gen = NULL;- if (!gen) { gen = gsl_rng_alloc (gsl_rng_mt19937);}- gsl_rng_set (gen, seed);- int k;- switch (code) {- RAN(0,gsl_rng_uniform)- RAN(1,gsl_ran_ugaussian)- default: ERROR(BAD_CODE);- }-}-#undef RAN--//////////////////////////////////////////////////////--#include "gsl-ode.c"--//////////////////////////////////////////////////////
@@ -1,182 +0,0 @@--#ifdef GSLODE1--////////////////////////////// ODE V1 //////////////////////////////////////////--#include <gsl/gsl_odeiv.h>--typedef struct {int n; int (*f)(double,int, const double*, int, double *); int (*j)(double,int, const double*, int, int, double*);} Tode;--int odefunc (double t, const double y[], double f[], void *params) { - Tode * P = (Tode*) params;- (P->f)(t,P->n,y,P->n,f);- return GSL_SUCCESS;-}--int odejac (double t, const double y[], double *dfdy, double dfdt[], void *params) {- Tode * P = ((Tode*) params);- (P->j)(t,P->n,y,P->n,P->n,dfdy);- int j;- for (j=0; j< P->n; j++)- dfdt[j] = 0.0;- return GSL_SUCCESS;-}---int ode(int method, double h, double eps_abs, double eps_rel,- int f(double, int, const double*, int, double*),- int jac(double, int, const double*, int, int, double*),- KRVEC(xi), KRVEC(ts), RMAT(sol)) {-- const gsl_odeiv_step_type * T;-- switch(method) {- case 0 : {T = gsl_odeiv_step_rk2; break; }- case 1 : {T = gsl_odeiv_step_rk4; break; }- case 2 : {T = gsl_odeiv_step_rkf45; break; }- case 3 : {T = gsl_odeiv_step_rkck; break; }- case 4 : {T = gsl_odeiv_step_rk8pd; break; }- case 5 : {T = gsl_odeiv_step_rk2imp; break; }- case 6 : {T = gsl_odeiv_step_rk4imp; break; }- case 7 : {T = gsl_odeiv_step_bsimp; break; }- case 8 : { printf("Sorry: ODE rk1imp not available in this GSL version\n"); exit(0); }- case 9 : { printf("Sorry: ODE msadams not available in this GSL version\n"); exit(0); }- case 10: { printf("Sorry: ODE msbdf not available in this GSL version\n"); exit(0); }- default: ERROR(BAD_CODE);- }-- gsl_odeiv_step * s = gsl_odeiv_step_alloc (T, xin);- gsl_odeiv_control * c = gsl_odeiv_control_y_new (eps_abs, eps_rel);- gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc (xin);-- Tode P;- P.f = f;- P.j = jac;- P.n = xin;-- gsl_odeiv_system sys = {odefunc, odejac, xin, &P};-- double t = tsp[0];-- double* y = (double*)calloc(xin,sizeof(double));- int i,j;- for(i=0; i< xin; i++) {- y[i] = xip[i];- solp[i] = xip[i];- }-- for (i = 1; i < tsn ; i++)- {- double ti = tsp[i];- while (t < ti)- {- gsl_odeiv_evolve_apply (e, c, s,- &sys,- &t, ti, &h,- y);- // if (h < hmin) h = hmin;- }- for(j=0; j<xin; j++) {- solp[i*xin + j] = y[j];- }- }-- free(y);- gsl_odeiv_evolve_free (e);- gsl_odeiv_control_free (c);- gsl_odeiv_step_free (s);- return 0;-}--#else--///////////////////// ODE V2 ///////////////////////////////////////////////////- -#include <gsl/gsl_odeiv2.h>--typedef struct {int n; int (*f)(double,int, const double*, int, double *); int (*j)(double,int, const double*, int, int, double*);} Tode;--int odefunc (double t, const double y[], double f[], void *params) { - Tode * P = (Tode*) params;- (P->f)(t,P->n,y,P->n,f);- return GSL_SUCCESS;-}--int odejac (double t, const double y[], double *dfdy, double dfdt[], void *params) {- Tode * P = ((Tode*) params);- (P->j)(t,P->n,y,P->n,P->n,dfdy);- int j;- for (j=0; j< P->n; j++)- dfdt[j] = 0.0;- return GSL_SUCCESS;-}---int ode(int method, double h, double eps_abs, double eps_rel,- int f(double, int, const double*, int, double*),- int jac(double, int, const double*, int, int, double*),- KRVEC(xi), KRVEC(ts), RMAT(sol)) {-- const gsl_odeiv2_step_type * T;-- switch(method) {- case 0 : {T = gsl_odeiv2_step_rk2; break; }- case 1 : {T = gsl_odeiv2_step_rk4; break; }- case 2 : {T = gsl_odeiv2_step_rkf45; break; }- case 3 : {T = gsl_odeiv2_step_rkck; break; }- case 4 : {T = gsl_odeiv2_step_rk8pd; break; }- case 5 : {T = gsl_odeiv2_step_rk2imp; break; }- case 6 : {T = gsl_odeiv2_step_rk4imp; break; }- case 7 : {T = gsl_odeiv2_step_bsimp; break; }- case 8 : {T = gsl_odeiv2_step_rk1imp; break; }- case 9 : {T = gsl_odeiv2_step_msadams; break; }- case 10: {T = gsl_odeiv2_step_msbdf; break; }- default: ERROR(BAD_CODE);- }-- Tode P;- P.f = f;- P.j = jac;- P.n = xin;-- gsl_odeiv2_system sys = {odefunc, odejac, xin, &P};-- gsl_odeiv2_driver * d =- gsl_odeiv2_driver_alloc_y_new (&sys, T, h, eps_abs, eps_rel);-- double t = tsp[0];-- double* y = (double*)calloc(xin,sizeof(double));- int i,j;- int status;- for(i=0; i< xin; i++) {- y[i] = xip[i];- solp[i] = xip[i];- }-- for (i = 1; i < tsn ; i++)- {- double ti = tsp[i];- - status = gsl_odeiv2_driver_apply (d, &t, ti, y);- - if (status != GSL_SUCCESS) {- printf ("error in ode, return value=%d\n", status);- break;- }--// printf ("%.5e %.5e %.5e\n", t, y[0], y[1]);- - for(j=0; j<xin; j++) {- solp[i*xin + j] = y[j];- }- }-- free(y);- gsl_odeiv2_driver_free (d);- - return status;-}--#endif-
@@ -1,160 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Numeric.IO--- Copyright : (c) Alberto Ruiz 2010--- License : GPL------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Display, formatting and IO functions for numeric 'Vector' and 'Matrix'-----------------------------------------------------------------------------------module Numeric.IO (- dispf, disps, dispcf, vecdisp, latexFormat, format,- loadMatrix, saveMatrix, fromFile, fileDimensions,- readMatrix, fromArray2D,- fscanfVector, fprintfVector, freadVector, fwriteVector-) where--import Data.Packed-import Data.Packed.Internal-import System.Process(readProcess)-import Text.Printf(printf)-import Data.List(intersperse)-import Data.Complex--{- | Creates a string from a matrix given a separator and a function to show each entry. Using-this function the user can easily define any desired display function:--@import Text.Printf(printf)@--@disp = putStr . format \" \" (printf \"%.2f\")@---}-format :: (Element t) => String -> (t -> String) -> Matrix t -> String-format sep f m = table sep . map (map f) . toLists $ m--{- | Show a matrix with \"autoscaling\" and a given number of decimal places.--@disp = putStr . disps 2--\> disp $ 120 * (3><4) [1..]-3x4 E3- 0.12 0.24 0.36 0.48- 0.60 0.72 0.84 0.96- 1.08 1.20 1.32 1.44-@--}-disps :: Int -> Matrix Double -> String-disps d x = sdims x ++ " " ++ formatScaled d x--{- | Show a matrix with a given number of decimal places.--@disp = putStr . dispf 3--\> disp (1/3 + ident 4)-4x4-1.333 0.333 0.333 0.333-0.333 1.333 0.333 0.333-0.333 0.333 1.333 0.333-0.333 0.333 0.333 1.333-@--}-dispf :: Int -> Matrix Double -> String-dispf d x = sdims x ++ "\n" ++ formatFixed (if isInt x then 0 else d) x--sdims x = show (rows x) ++ "x" ++ show (cols x)--formatFixed d x = format " " (printf ("%."++show d++"f")) $ x--isInt = all lookslikeInt . toList . flatten--formatScaled dec t = "E"++show o++"\n" ++ ss- where ss = format " " (printf fmt. g) t- g x | o >= 0 = x/10^(o::Int)- | otherwise = x*10^(-o)- o = floor $ maximum $ map (logBase 10 . abs) $ toList $ flatten t- fmt = '%':show (dec+3) ++ '.':show dec ++"f"--{- | Show a vector using a function for showing matrices.--@disp = putStr . vecdisp ('dispf' 2)--\> disp ('linspace' 10 (0,1))-10 |> 0.00 0.11 0.22 0.33 0.44 0.56 0.67 0.78 0.89 1.00-@--}-vecdisp :: (Element t) => (Matrix t -> String) -> Vector t -> String-vecdisp f v- = ((show (dim v) ++ " |> ") ++) . (++"\n")- . unwords . lines . tail . dropWhile (not . (`elem` " \n"))- . f . trans . reshape 1- $ v---- | Tool to display matrices with latex syntax.-latexFormat :: String -- ^ type of braces: \"matrix\", \"bmatrix\", \"pmatrix\", etc.- -> String -- ^ Formatted matrix, with elements separated by spaces and newlines- -> String-latexFormat del tab = "\\begin{"++del++"}\n" ++ f tab ++ "\\end{"++del++"}"- where f = unlines . intersperse "\\\\" . map unwords . map (intersperse " & " . words) . tail . lines---- | Pretty print a complex number with at most n decimal digits.-showComplex :: Int -> Complex Double -> String-showComplex d (a:+b)- | isZero a && isZero b = "0"- | isZero b = sa- | isZero a && isOne b = s2++"i"- | isZero a = sb++"i"- | isOne b = sa++s3++"i"- | otherwise = sa++s1++sb++"i"- where- sa = shcr d a- sb = shcr d b- s1 = if b<0 then "" else "+"- s2 = if b<0 then "-" else ""- s3 = if b<0 then "-" else "+"--shcr d a | lookslikeInt a = printf "%.0f" a- | otherwise = printf ("%."++show d++"f") a---lookslikeInt x = show (round x :: Int) ++".0" == shx || "-0.0" == shx- where shx = show x--isZero x = show x `elem` ["0.0","-0.0"]-isOne x = show x `elem` ["1.0","-1.0"]---- | Pretty print a complex matrix with at most n decimal digits.-dispcf :: Int -> Matrix (Complex Double) -> String-dispcf d m = sdims m ++ "\n" ++ format " " (showComplex d) m-------------------------------------------------------------------------- | reads a matrix from a string containing a table of numbers.-readMatrix :: String -> Matrix Double-readMatrix = fromLists . map (map read). map words . filter (not.null) . lines--{- | obtains the number of rows and columns in an ASCII data file- (provisionally using unix's wc).--}-fileDimensions :: FilePath -> IO (Int,Int)-fileDimensions fname = do- wcres <- readProcess "wc" ["-w",fname] ""- contents <- readFile fname- let tot = read . head . words $ wcres- c = length . head . dropWhile null . map words . lines $ contents- if tot > 0- then return (tot `div` c, c)- else return (0,0)---- | Loads a matrix from an ASCII file formatted as a 2D table.-loadMatrix :: FilePath -> IO (Matrix Double)-loadMatrix file = fromFile file =<< fileDimensions file---- | Loads a matrix from an ASCII file (the number of rows and columns must be known in advance).-fromFile :: FilePath -> (Int,Int) -> IO (Matrix Double)-fromFile filename (r,c) = reshape c `fmap` fscanfVector filename (r*c)-
@@ -1,28 +0,0 @@-------------------------------------------------------------------------------{- |-Module : Numeric.LinearAlgebra-Copyright : (c) Alberto Ruiz 2006-10-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--This module reexports all normally required functions for Linear Algebra applications.--It also provides instances of standard classes 'Show', 'Read', 'Eq',-'Num', 'Fractional', and 'Floating' for 'Vector' and 'Matrix'.-In arithmetic operations one-component vectors and matrices automatically-expand to match the dimensions of the other operand.---}-------------------------------------------------------------------------------module Numeric.LinearAlgebra (- module Numeric.Container,- module Numeric.LinearAlgebra.Algorithms-) where--import Numeric.Container-import Numeric.LinearAlgebra.Algorithms-import Numeric.Matrix()-import Numeric.Vector()
@@ -1,731 +0,0 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeFamilies #-}--------------------------------------------------------------------------------{- |-Module : Numeric.LinearAlgebra.Algorithms-Copyright : (c) Alberto Ruiz 2006-9-License : GPL-style--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional-Portability : uses ffi--High level generic interface to common matrix computations.--Specific functions for particular base types can also be explicitly-imported from "Numeric.LinearAlgebra.LAPACK".---}--------------------------------------------------------------------------------module Numeric.LinearAlgebra.Algorithms (--- * Supported types- Field(),--- * Linear Systems- linearSolve,- luSolve,- cholSolve,- linearSolveLS,- linearSolveSVD,- inv, pinv,- det, invlndet,- rank, rcond,--- * Matrix factorizations--- ** Singular value decomposition- svd,- fullSVD,- thinSVD,- compactSVD,- singularValues,- leftSV, rightSV,--- ** Eigensystems- eig, eigSH, eigSH',- eigenvalues, eigenvaluesSH, eigenvaluesSH',- geigSH',--- ** QR- qr, rq,--- ** Cholesky- chol, cholSH, mbCholSH,--- ** Hessenberg- hess,--- ** Schur- schur,--- ** LU- lu, luPacked,--- * Matrix functions- expm,- sqrtm,- matFunc,--- * Nullspace- nullspacePrec,- nullVector,- nullspaceSVD,- orth,--- * Norms- Normed(..), NormType(..),- relativeError,--- * Misc- eps, peps, i,--- * Util- haussholder,- unpackQR, unpackHess,- pinvTol,- ranksv-) where---import Data.Packed.Internal hiding ((//))-import Data.Packed.Matrix-import Numeric.LinearAlgebra.LAPACK as LAPACK-import Data.List(foldl1')-import Data.Array-import Numeric.ContainerBoot---{- | Class used to define generic linear algebra computations for both real and complex matrices. Only double precision is supported in this version (we can-transform single precision objects using 'single' and 'double').---}-class (Product t,- Convert t,- Container Vector t,- Container Matrix t,- Normed Matrix t,- Normed Vector t) => Field t where- svd' :: Matrix t -> (Matrix t, Vector Double, Matrix t)- thinSVD' :: Matrix t -> (Matrix t, Vector Double, Matrix t)- sv' :: Matrix t -> Vector Double- luPacked' :: Matrix t -> (Matrix t, [Int])- luSolve' :: (Matrix t, [Int]) -> Matrix t -> Matrix t- linearSolve' :: Matrix t -> Matrix t -> Matrix t- cholSolve' :: Matrix t -> Matrix t -> Matrix t- linearSolveSVD' :: Matrix t -> Matrix t -> Matrix t- linearSolveLS' :: Matrix t -> Matrix t -> Matrix t- eig' :: Matrix t -> (Vector (Complex Double), Matrix (Complex Double))- eigSH'' :: Matrix t -> (Vector Double, Matrix t)- eigOnly :: Matrix t -> Vector (Complex Double)- eigOnlySH :: Matrix t -> Vector Double- cholSH' :: Matrix t -> Matrix t- mbCholSH' :: Matrix t -> Maybe (Matrix t)- qr' :: Matrix t -> (Matrix t, Matrix t)- hess' :: Matrix t -> (Matrix t, Matrix t)- schur' :: Matrix t -> (Matrix t, Matrix t)---instance Field Double where- svd' = svdRd- thinSVD' = thinSVDRd- sv' = svR- luPacked' = luR- luSolve' (l_u,perm) = lusR l_u perm- linearSolve' = linearSolveR -- (luSolve . luPacked) ??- cholSolve' = cholSolveR- linearSolveLS' = linearSolveLSR- linearSolveSVD' = linearSolveSVDR Nothing- eig' = eigR- eigSH'' = eigS- eigOnly = eigOnlyR- eigOnlySH = eigOnlyS- cholSH' = cholS- mbCholSH' = mbCholS- qr' = unpackQR . qrR- hess' = unpackHess hessR- schur' = schurR--instance Field (Complex Double) where-#ifdef NOZGESDD- svd' = svdC- thinSVD' = thinSVDC-#else- svd' = svdCd- thinSVD' = thinSVDCd-#endif- sv' = svC- luPacked' = luC- luSolve' (l_u,perm) = lusC l_u perm- linearSolve' = linearSolveC- cholSolve' = cholSolveC- linearSolveLS' = linearSolveLSC- linearSolveSVD' = linearSolveSVDC Nothing- eig' = eigC- eigOnly = eigOnlyC- eigSH'' = eigH- eigOnlySH = eigOnlyH- cholSH' = cholH- mbCholSH' = mbCholH- qr' = unpackQR . qrC- hess' = unpackHess hessC- schur' = schurC------------------------------------------------------------------square m = rows m == cols m--vertical m = rows m >= cols m--exactHermitian m = m `equal` ctrans m-------------------------------------------------------------------- | Full singular value decomposition.-svd :: Field t => Matrix t -> (Matrix t, Vector Double, Matrix t)-svd = {-# SCC "svd" #-} svd'---- | A version of 'svd' which returns only the @min (rows m) (cols m)@ singular vectors of @m@.------ If @(u,s,v) = thinSVD m@ then @m == u \<> diag s \<> trans v@.-thinSVD :: Field t => Matrix t -> (Matrix t, Vector Double, Matrix t)-thinSVD = {-# SCC "thinSVD" #-} thinSVD'---- | Singular values only.-singularValues :: Field t => Matrix t -> Vector Double-singularValues = {-# SCC "singularValues" #-} sv'---- | A version of 'svd' which returns an appropriate diagonal matrix with the singular values.------ If @(u,d,v) = fullSVD m@ then @m == u \<> d \<> trans v@.-fullSVD :: Field t => Matrix t -> (Matrix t, Matrix Double, Matrix t)-fullSVD m = (u,d,v) where- (u,s,v) = svd m- d = diagRect 0 s r c- r = rows m- c = cols m---- | Similar to 'thinSVD', returning only the nonzero singular values and the corresponding singular vectors.-compactSVD :: Field t => Matrix t -> (Matrix t, Vector Double, Matrix t)-compactSVD m = (u', subVector 0 d s, v') where- (u,s,v) = thinSVD m- d = rankSVD (1*eps) m s `max` 1- u' = takeColumns d u- v' = takeColumns d v----- | Singular values and all right singular vectors.-rightSV :: Field t => Matrix t -> (Vector Double, Matrix t)-rightSV m | vertical m = let (_,s,v) = thinSVD m in (s,v)- | otherwise = let (_,s,v) = svd m in (s,v)---- | Singular values and all left singular vectors.-leftSV :: Field t => Matrix t -> (Matrix t, Vector Double)-leftSV m | vertical m = let (u,s,_) = svd m in (u,s)- | otherwise = let (u,s,_) = thinSVD m in (u,s)--------------------------------------------------------------------- | Obtains the LU decomposition of a matrix in a compact data structure suitable for 'luSolve'.-luPacked :: Field t => Matrix t -> (Matrix t, [Int])-luPacked = {-# SCC "luPacked" #-} luPacked'---- | Solution of a linear system (for several right hand sides) from the precomputed LU factorization obtained by 'luPacked'.-luSolve :: Field t => (Matrix t, [Int]) -> Matrix t -> Matrix t-luSolve = {-# SCC "luSolve" #-} luSolve'---- | Solve a linear system (for square coefficient matrix and several right-hand sides) using the LU decomposition. For underconstrained or overconstrained systems use 'linearSolveLS' or 'linearSolveSVD'.--- It is similar to 'luSolve' . 'luPacked', but @linearSolve@ raises an error if called on a singular system.-linearSolve :: Field t => Matrix t -> Matrix t -> Matrix t-linearSolve = {-# SCC "linearSolve" #-} linearSolve'---- | Solve a symmetric or Hermitian positive definite linear system using a precomputed Cholesky decomposition obtained by 'chol'.-cholSolve :: Field t => Matrix t -> Matrix t -> Matrix t-cholSolve = {-# SCC "cholSolve" #-} cholSolve'---- | Minimum norm solution of a general linear least squares problem Ax=B using the SVD. Admits rank-deficient systems but it is slower than 'linearSolveLS'. The effective rank of A is determined by treating as zero those singular valures which are less than 'eps' times the largest singular value.-linearSolveSVD :: Field t => Matrix t -> Matrix t -> Matrix t-linearSolveSVD = {-# SCC "linearSolveSVD" #-} linearSolveSVD'----- | Least squared error solution of an overconstrained linear system, or the minimum norm solution of an underconstrained system. For rank-deficient systems use 'linearSolveSVD'.-linearSolveLS :: Field t => Matrix t -> Matrix t -> Matrix t-linearSolveLS = {-# SCC "linearSolveLS" #-} linearSolveLS'-------------------------------------------------------------------- | Eigenvalues and eigenvectors of a general square matrix.------ If @(s,v) = eig m@ then @m \<> v == v \<> diag s@-eig :: Field t => Matrix t -> (Vector (Complex Double), Matrix (Complex Double))-eig = {-# SCC "eig" #-} eig'---- | Eigenvalues of a general square matrix.-eigenvalues :: Field t => Matrix t -> Vector (Complex Double)-eigenvalues = {-# SCC "eigenvalues" #-} eigOnly---- | Similar to 'eigSH' without checking that the input matrix is hermitian or symmetric. It works with the upper triangular part.-eigSH' :: Field t => Matrix t -> (Vector Double, Matrix t)-eigSH' = {-# SCC "eigSH'" #-} eigSH''---- | Similar to 'eigenvaluesSH' without checking that the input matrix is hermitian or symmetric. It works with the upper triangular part.-eigenvaluesSH' :: Field t => Matrix t -> Vector Double-eigenvaluesSH' = {-# SCC "eigenvaluesSH'" #-} eigOnlySH---- | Eigenvalues and Eigenvectors of a complex hermitian or real symmetric matrix.------ If @(s,v) = eigSH m@ then @m == v \<> diag s \<> ctrans v@-eigSH :: Field t => Matrix t -> (Vector Double, Matrix t)-eigSH m | exactHermitian m = eigSH' m- | otherwise = error "eigSH requires complex hermitian or real symmetric matrix"---- | Eigenvalues of a complex hermitian or real symmetric matrix.-eigenvaluesSH :: Field t => Matrix t -> Vector Double-eigenvaluesSH m | exactHermitian m = eigenvaluesSH' m- | otherwise = error "eigenvaluesSH requires complex hermitian or real symmetric matrix"-------------------------------------------------------------------- | QR factorization.------ If @(q,r) = qr m@ then @m == q \<> r@, where q is unitary and r is upper triangular.-qr :: Field t => Matrix t -> (Matrix t, Matrix t)-qr = {-# SCC "qr" #-} qr'---- | RQ factorization.------ If @(r,q) = rq m@ then @m == r \<> q@, where q is unitary and r is upper triangular.-rq :: Field t => Matrix t -> (Matrix t, Matrix t)-rq m = {-# SCC "rq" #-} (r,q) where- (q',r') = qr $ trans $ rev1 m- r = rev2 (trans r')- q = rev2 (trans q')- rev1 = flipud . fliprl- rev2 = fliprl . flipud---- | Hessenberg factorization.------ If @(p,h) = hess m@ then @m == p \<> h \<> ctrans p@, where p is unitary--- and h is in upper Hessenberg form (it has zero entries below the first subdiagonal).-hess :: Field t => Matrix t -> (Matrix t, Matrix t)-hess = hess'---- | Schur factorization.------ If @(u,s) = schur m@ then @m == u \<> s \<> ctrans u@, where u is unitary--- and s is a Shur matrix. A complex Schur matrix is upper triangular. A real Schur matrix is--- upper triangular in 2x2 blocks.------ \"Anything that the Jordan decomposition can do, the Schur decomposition--- can do better!\" (Van Loan)-schur :: Field t => Matrix t -> (Matrix t, Matrix t)-schur = schur'----- | Similar to 'cholSH', but instead of an error (e.g., caused by a matrix not positive definite) it returns 'Nothing'.-mbCholSH :: Field t => Matrix t -> Maybe (Matrix t)-mbCholSH = {-# SCC "mbCholSH" #-} mbCholSH'---- | Similar to 'chol', without checking that the input matrix is hermitian or symmetric. It works with the upper triangular part.-cholSH :: Field t => Matrix t -> Matrix t-cholSH = {-# SCC "cholSH" #-} cholSH'---- | Cholesky factorization of a positive definite hermitian or symmetric matrix.------ If @c = chol m@ then @c@ is upper triangular and @m == ctrans c \<> c@.-chol :: Field t => Matrix t -> Matrix t-chol m | exactHermitian m = cholSH m- | otherwise = error "chol requires positive definite complex hermitian or real symmetric matrix"----- | Joint computation of inverse and logarithm of determinant of a square matrix.-invlndet :: (Floating t, Field t)- => Matrix t- -> (Matrix t, (t, t)) -- ^ (inverse, (log abs det, sign or phase of det)) -invlndet m | square m = (im,(ladm,sdm))- | otherwise = error $ "invlndet of nonsquare "++ shSize m ++ " matrix"- where- lp@(lup,perm) = luPacked m- s = signlp (rows m) perm- dg = toList $ takeDiag $ lup- ladm = sum $ map (log.abs) dg- sdm = s* product (map signum dg)- im = luSolve lp (ident (rows m))----- | Determinant of a square matrix. To avoid possible overflow or underflow use 'invlndet'.-det :: Field t => Matrix t -> t-det m | square m = {-# SCC "det" #-} s * (product $ toList $ takeDiag $ lup)- | otherwise = error $ "det of nonsquare "++ shSize m ++ " matrix"- where (lup,perm) = luPacked m- s = signlp (rows m) perm---- | Explicit LU factorization of a general matrix.------ If @(l,u,p,s) = lu m@ then @m == p \<> l \<> u@, where l is lower triangular,--- u is upper triangular, p is a permutation matrix and s is the signature of the permutation.-lu :: Field t => Matrix t -> (Matrix t, Matrix t, Matrix t, t)-lu = luFact . luPacked---- | Inverse of a square matrix. See also 'invlndet'.-inv :: Field t => Matrix t -> Matrix t-inv m | square m = m `linearSolve` ident (rows m)- | otherwise = error $ "inv of nonsquare "++ shSize m ++ " matrix"---- | Pseudoinverse of a general matrix.-pinv :: Field t => Matrix t -> Matrix t-pinv m = linearSolveSVD m (ident (rows m))---- | Numeric rank of a matrix from the SVD decomposition.-rankSVD :: Element t- => Double -- ^ numeric zero (e.g. 1*'eps')- -> Matrix t -- ^ input matrix m- -> Vector Double -- ^ 'sv' of m- -> Int -- ^ rank of m-rankSVD teps m s = ranksv teps (max (rows m) (cols m)) (toList s)---- | Numeric rank of a matrix from its singular values.-ranksv :: Double -- ^ numeric zero (e.g. 1*'eps')- -> Int -- ^ maximum dimension of the matrix- -> [Double] -- ^ singular values- -> Int -- ^ rank of m-ranksv teps maxdim s = k where- g = maximum s- tol = fromIntegral maxdim * g * teps- s' = filter (>tol) s- k = if g > teps then length s' else 0---- | The machine precision of a Double: @eps = 2.22044604925031e-16@ (the value used by GNU-Octave).-eps :: Double-eps = 2.22044604925031e-16----- | 1 + 0.5*peps == 1, 1 + 0.6*peps /= 1-peps :: RealFloat x => x-peps = x where x = 2.0 ** fromIntegral (1 - floatDigits x)----- | The imaginary unit: @i = 0.0 :+ 1.0@-i :: Complex Double-i = 0:+1----------------------------------------------------------------------------- | The nullspace of a matrix from its SVD decomposition.-nullspaceSVD :: Field t- => Either Double Int -- ^ Left \"numeric\" zero (eg. 1*'eps'),- -- or Right \"theoretical\" matrix rank.- -> Matrix t -- ^ input matrix m- -> (Vector Double, Matrix t) -- ^ 'rightSV' of m- -> [Vector t] -- ^ list of unitary vectors spanning the nullspace-nullspaceSVD hint a (s,v) = vs where- tol = case hint of- Left t -> t- _ -> eps- k = case hint of- Right t -> t- _ -> rankSVD tol a s- vs = drop k $ toRows $ ctrans v----- | The nullspace of a matrix. See also 'nullspaceSVD'.-nullspacePrec :: Field t- => Double -- ^ relative tolerance in 'eps' units (e.g., use 3 to get 3*'eps')- -> Matrix t -- ^ input matrix- -> [Vector t] -- ^ list of unitary vectors spanning the nullspace-nullspacePrec t m = nullspaceSVD (Left (t*eps)) m (rightSV m)---- | The nullspace of a matrix, assumed to be one-dimensional, with machine precision.-nullVector :: Field t => Matrix t -> Vector t-nullVector = last . nullspacePrec 1--orth :: Field t => Matrix t -> [Vector t]--- ^ Return an orthonormal basis of the range space of a matrix-orth m = take r $ toColumns u- where- (u,s,_) = compactSVD m- r = ranksv eps (max (rows m) (cols m)) (toList s)----------------------------------------------------------------------------{- Pseudoinverse of a real matrix with the desired tolerance, expressed as a-multiplicative factor of the default tolerance used by GNU-Octave (see 'pinv').--@\> let m = 'fromLists' [[1,0, 0]- ,[0,1, 0]- ,[0,0,1e-10]]-\ ---\> 'pinv' m -1. 0. 0.-0. 1. 0.-0. 0. 10000000000.-\ ---\> pinvTol 1E8 m-1. 0. 0.-0. 1. 0.-0. 0. 1.@---}---pinvTol :: Double -> Matrix Double -> Matrix Double-pinvTol t m = v' `mXm` diag s' `mXm` trans u' where- (u,s,v) = thinSVDRd m- sl@(g:_) = toList s- s' = fromList . map rec $ sl- rec x = if x < g*tol then 1 else 1/x- tol = (fromIntegral (max r c) * g * t * eps)- r = rows m- c = cols m- d = dim s- u' = takeColumns d u- v' = takeColumns d v--------------------------------------------------------------------------- many thanks, quickcheck!--haussholder :: (Field a) => a -> Vector a -> Matrix a-haussholder tau v = ident (dim v) `sub` (tau `scale` (w `mXm` ctrans w))- where w = asColumn v---zh k v = fromList $ replicate (k-1) 0 ++ (1:drop k xs)- where xs = toList v--zt 0 v = v-zt k v = join [subVector 0 (dim v - k) v, konst 0 k]---unpackQR :: (Field t) => (Matrix t, Vector t) -> (Matrix t, Matrix t)-unpackQR (pq, tau) = {-# SCC "unpackQR" #-} (q,r)- where cs = toColumns pq- m = rows pq- n = cols pq- mn = min m n- r = fromColumns $ zipWith zt ([m-1, m-2 .. 1] ++ repeat 0) cs- vs = zipWith zh [1..mn] cs- hs = zipWith haussholder (toList tau) vs- q = foldl1' mXm hs--unpackHess :: (Field t) => (Matrix t -> (Matrix t,Vector t)) -> Matrix t -> (Matrix t, Matrix t)-unpackHess hf m- | rows m == 1 = ((1><1)[1],m)- | otherwise = (uH . hf) m--uH (pq, tau) = (p,h)- where cs = toColumns pq- m = rows pq- n = cols pq- mn = min m n- h = fromColumns $ zipWith zt ([m-2, m-3 .. 1] ++ repeat 0) cs- vs = zipWith zh [2..mn] cs- hs = zipWith haussholder (toList tau) vs- p = foldl1' mXm hs-------------------------------------------------------------------------------- | Reciprocal of the 2-norm condition number of a matrix, computed from the singular values.-rcond :: Field t => Matrix t -> Double-rcond m = last s / head s- where s = toList (singularValues m)---- | Number of linearly independent rows or columns.-rank :: Field t => Matrix t -> Int-rank m = rankSVD eps m (singularValues m)--{--expm' m = case diagonalize (complex m) of- Just (l,v) -> v `mXm` diag (exp l) `mXm` inv v- Nothing -> error "Sorry, expm not yet implemented for non-diagonalizable matrices"- where exp = vectorMapC Exp--}--diagonalize m = if rank v == n- then Just (l,v)- else Nothing- where n = rows m- (l,v) = if exactHermitian m- then let (l',v') = eigSH m in (real l', v')- else eig m---- | Generic matrix functions for diagonalizable matrices. For instance:------ @logm = matFunc log@----matFunc :: (Complex Double -> Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)-matFunc f m = case diagonalize m of- Just (l,v) -> v `mXm` diag (mapVector f l) `mXm` inv v- Nothing -> error "Sorry, matFunc requires a diagonalizable matrix" ------------------------------------------------------------------golubeps :: Integer -> Integer -> Double-golubeps p q = a * fromIntegral b / fromIntegral c where- a = 2^^(3-p-q)- b = fact p * fact q- c = fact (p+q) * fact (p+q+1)- fact n = product [1..n]--epslist = [ (fromIntegral k, golubeps k k) | k <- [1..]]--geps delta = head [ k | (k,g) <- epslist, g<delta]---{- | Matrix exponential. It uses a direct translation of Algorithm 11.3.1 in Golub & Van Loan,- based on a scaled Pade approximation.--}-expm :: Field t => Matrix t -> Matrix t-expm = expGolub--expGolub :: ( Fractional t, Element t, Field t- , Normed Matrix t- , RealFrac (RealOf t)- , Floating (RealOf t)- ) => Matrix t -> Matrix t-expGolub m = iterate msq f !! j- where j = max 0 $ floor $ logBase 2 $ pnorm Infinity m- a = m */ fromIntegral ((2::Int)^j)- q = geps eps -- 7 steps- eye = ident (rows m)- work (k,c,x,n,d) = (k',c',x',n',d')- where k' = k+1- c' = c * fromIntegral (q-k+1) / fromIntegral ((2*q-k+1)*k)- x' = a <> x- n' = n |+| (c' .* x')- d' = d |+| (((-1)^k * c') .* x')- (_,_,_,nf,df) = iterate work (1,1,eye,eye,eye) !! q- f = linearSolve df nf- msq x = x <> x-- (<>) = multiply- v */ x = scale (recip x) v- (.*) = scale- (|+|) = add------------------------------------------------------------------{- | Matrix square root. Currently it uses a simple iterative algorithm described in Wikipedia.-It only works with invertible matrices that have a real solution. For diagonalizable matrices you can try @matFunc sqrt@.--@m = (2><2) [4,9- ,0,4] :: Matrix Double@--@\>sqrtm m-(2><2)- [ 2.0, 2.25- , 0.0, 2.0 ]@--}-sqrtm :: Field t => Matrix t -> Matrix t-sqrtm = sqrtmInv--sqrtmInv x = fst $ fixedPoint $ iterate f (x, ident (rows x))- where fixedPoint (a:b:rest) | pnorm PNorm1 (fst a |-| fst b) < peps = a- | otherwise = fixedPoint (b:rest)- fixedPoint _ = error "fixedpoint with impossible inputs"- f (y,z) = (0.5 .* (y |+| inv z),- 0.5 .* (inv y |+| z))- (.*) = scale- (|+|) = add- (|-|) = sub----------------------------------------------------------------------signlp r vals = foldl f 1 (zip [0..r-1] vals)- where f s (a,b) | a /= b = -s- | otherwise = s--swap (arr,s) (a,b) | a /= b = (arr // [(a, arr!b),(b,arr!a)],-s)- | otherwise = (arr,s)--fixPerm r vals = (fromColumns $ elems res, sign)- where v = [0..r-1]- s = toColumns (ident r)- (res,sign) = foldl swap (listArray (0,r-1) s, 1) (zip v vals)--triang r c h v = (r><c) [el s t | s<-[0..r-1], t<-[0..c-1]]- where el p q = if q-p>=h then v else 1 - v--luFact (l_u,perm) | r <= c = (l ,u ,p, s)- | otherwise = (l',u',p, s)- where- r = rows l_u- c = cols l_u- tu = triang r c 0 1- tl = triang r c 0 0- l = takeColumns r (l_u |*| tl) |+| diagRect 0 (konst 1 r) r r- u = l_u |*| tu- (p,s) = fixPerm r perm- l' = (l_u |*| tl) |+| diagRect 0 (konst 1 c) r c- u' = takeRows c (l_u |*| tu)- (|+|) = add- (|*|) = mul-------------------------------------------------------------------------------data NormType = Infinity | PNorm1 | PNorm2 | Frobenius--class (RealFloat (RealOf t)) => Normed c t where- pnorm :: NormType -> c t -> RealOf t--instance Normed Vector Double where- pnorm PNorm1 = norm1- pnorm PNorm2 = norm2- pnorm Infinity = normInf- pnorm Frobenius = norm2--instance Normed Vector (Complex Double) where- pnorm PNorm1 = norm1- pnorm PNorm2 = norm2- pnorm Infinity = normInf- pnorm Frobenius = pnorm PNorm2--instance Normed Vector Float where- pnorm PNorm1 = norm1- pnorm PNorm2 = norm2- pnorm Infinity = normInf- pnorm Frobenius = pnorm PNorm2--instance Normed Vector (Complex Float) where- pnorm PNorm1 = norm1- pnorm PNorm2 = norm2- pnorm Infinity = normInf- pnorm Frobenius = pnorm PNorm2---instance Normed Matrix Double where- pnorm PNorm1 = maximum . map (pnorm PNorm1) . toColumns- pnorm PNorm2 = (@>0) . singularValues- pnorm Infinity = pnorm PNorm1 . trans- pnorm Frobenius = pnorm PNorm2 . flatten--instance Normed Matrix (Complex Double) where- pnorm PNorm1 = maximum . map (pnorm PNorm1) . toColumns- pnorm PNorm2 = (@>0) . singularValues- pnorm Infinity = pnorm PNorm1 . trans- pnorm Frobenius = pnorm PNorm2 . flatten--instance Normed Matrix Float where- pnorm PNorm1 = maximum . map (pnorm PNorm1) . toColumns- pnorm PNorm2 = realToFrac . (@>0) . singularValues . double- pnorm Infinity = pnorm PNorm1 . trans- pnorm Frobenius = pnorm PNorm2 . flatten--instance Normed Matrix (Complex Float) where- pnorm PNorm1 = maximum . map (pnorm PNorm1) . toColumns- pnorm PNorm2 = realToFrac . (@>0) . singularValues . double- pnorm Infinity = pnorm PNorm1 . trans- pnorm Frobenius = pnorm PNorm2 . flatten---- | Approximate number of common digits in the maximum element.-relativeError :: (Normed c t, Container c t) => c t -> c t -> Int-relativeError x y = dig (norm (x `sub` y) / norm x)- where norm = pnorm Infinity- dig r = round $ -logBase 10 (realToFrac r :: Double)---------------------------------------------------------------------------- | Generalized symmetric positive definite eigensystem Av = lBv,--- for A and B symmetric, B positive definite (conditions not checked).-geigSH' :: Field t- => Matrix t -- ^ A- -> Matrix t -- ^ B- -> (Vector Double, Matrix t)-geigSH' a b = (l,v')- where- u = cholSH b- iu = inv u- c = ctrans iu <> a <> iu- (l,v) = eigSH' c- v' = iu <> v- (<>) = mXm-
@@ -1,536 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Numeric.LinearAlgebra.LAPACK--- Copyright : (c) Alberto Ruiz 2006-7--- License : GPL-style--- --- Maintainer : Alberto Ruiz (aruiz at um dot es)--- Stability : provisional--- Portability : portable (uses FFI)------ Functional interface to selected LAPACK functions (<http://www.netlib.org/lapack>).-----------------------------------------------------------------------------------module Numeric.LinearAlgebra.LAPACK (- -- * Matrix product- multiplyR, multiplyC, multiplyF, multiplyQ,- -- * Linear systems- linearSolveR, linearSolveC,- lusR, lusC,- cholSolveR, cholSolveC,- linearSolveLSR, linearSolveLSC,- linearSolveSVDR, linearSolveSVDC,- -- * SVD- svR, svRd, svC, svCd,- svdR, svdRd, svdC, svdCd,- thinSVDR, thinSVDRd, thinSVDC, thinSVDCd,- rightSVR, rightSVC, leftSVR, leftSVC,- -- * Eigensystems- eigR, eigC, eigS, eigS', eigH, eigH',- eigOnlyR, eigOnlyC, eigOnlyS, eigOnlyH,- -- * LU- luR, luC,- -- * Cholesky- cholS, cholH, mbCholS, mbCholH,- -- * QR- qrR, qrC,- -- * Hessenberg- hessR, hessC,- -- * Schur- schurR, schurC-) where--import Data.Packed.Internal-import Data.Packed.Matrix-import Numeric.Conversion-import Numeric.GSL.Vector(vectorMapValR, FunCodeSV(Scale))--import Foreign.Ptr(nullPtr)-import Foreign.C.Types-import Control.Monad(when)-import System.IO.Unsafe(unsafePerformIO)---------------------------------------------------------------------------------------foreign import ccall unsafe "multiplyR" dgemmc :: CInt -> CInt -> TMMM-foreign import ccall unsafe "multiplyC" zgemmc :: CInt -> CInt -> TCMCMCM-foreign import ccall unsafe "multiplyF" sgemmc :: CInt -> CInt -> TFMFMFM-foreign import ccall unsafe "multiplyQ" cgemmc :: CInt -> CInt -> TQMQMQM--isT Matrix{order = ColumnMajor} = 0-isT Matrix{order = RowMajor} = 1--tt x@Matrix{order = ColumnMajor} = x-tt x@Matrix{order = RowMajor} = trans x--multiplyAux f st a b = unsafePerformIO $ do- when (cols a /= rows b) $ error $ "inconsistent dimensions in matrix product "++- show (rows a,cols a) ++ " x " ++ show (rows b, cols b)- s <- createMatrix ColumnMajor (rows a) (cols b)- app3 (f (isT a) (isT b)) mat (tt a) mat (tt b) mat s st- return s---- | Matrix product based on BLAS's /dgemm/.-multiplyR :: Matrix Double -> Matrix Double -> Matrix Double-multiplyR a b = {-# SCC "multiplyR" #-} multiplyAux dgemmc "dgemmc" a b---- | Matrix product based on BLAS's /zgemm/.-multiplyC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)-multiplyC a b = multiplyAux zgemmc "zgemmc" a b---- | Matrix product based on BLAS's /sgemm/.-multiplyF :: Matrix Float -> Matrix Float -> Matrix Float-multiplyF a b = multiplyAux sgemmc "sgemmc" a b---- | Matrix product based on BLAS's /cgemm/.-multiplyQ :: Matrix (Complex Float) -> Matrix (Complex Float) -> Matrix (Complex Float)-multiplyQ a b = multiplyAux cgemmc "cgemmc" a b--------------------------------------------------------------------------------foreign import ccall unsafe "svd_l_R" dgesvd :: TMMVM-foreign import ccall unsafe "svd_l_C" zgesvd :: TCMCMVCM-foreign import ccall unsafe "svd_l_Rdd" dgesdd :: TMMVM-foreign import ccall unsafe "svd_l_Cdd" zgesdd :: TCMCMVCM---- | Full SVD of a real matrix using LAPACK's /dgesvd/.-svdR :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double)-svdR = svdAux dgesvd "svdR" . fmat---- | Full SVD of a real matrix using LAPACK's /dgesdd/.-svdRd :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double)-svdRd = svdAux dgesdd "svdRdd" . fmat---- | Full SVD of a complex matrix using LAPACK's /zgesvd/.-svdC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector Double, Matrix (Complex Double))-svdC = svdAux zgesvd "svdC" . fmat---- | Full SVD of a complex matrix using LAPACK's /zgesdd/.-svdCd :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector Double, Matrix (Complex Double))-svdCd = svdAux zgesdd "svdCdd" . fmat--svdAux f st x = unsafePerformIO $ do- u <- createMatrix ColumnMajor r r- s <- createVector (min r c)- v <- createMatrix ColumnMajor c c- app4 f mat x mat u vec s mat v st- return (u,s,trans v)- where r = rows x- c = cols x----- | Thin SVD of a real matrix, using LAPACK's /dgesvd/ with jobu == jobvt == \'S\'.-thinSVDR :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double)-thinSVDR = thinSVDAux dgesvd "thinSVDR" . fmat---- | Thin SVD of a complex matrix, using LAPACK's /zgesvd/ with jobu == jobvt == \'S\'.-thinSVDC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector Double, Matrix (Complex Double))-thinSVDC = thinSVDAux zgesvd "thinSVDC" . fmat---- | Thin SVD of a real matrix, using LAPACK's /dgesdd/ with jobz == \'S\'.-thinSVDRd :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double)-thinSVDRd = thinSVDAux dgesdd "thinSVDRdd" . fmat---- | Thin SVD of a complex matrix, using LAPACK's /zgesdd/ with jobz == \'S\'.-thinSVDCd :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector Double, Matrix (Complex Double))-thinSVDCd = thinSVDAux zgesdd "thinSVDCdd" . fmat--thinSVDAux f st x = unsafePerformIO $ do- u <- createMatrix ColumnMajor r q- s <- createVector q- v <- createMatrix ColumnMajor q c- app4 f mat x mat u vec s mat v st- return (u,s,trans v)- where r = rows x- c = cols x- q = min r c----- | Singular values of a real matrix, using LAPACK's /dgesvd/ with jobu == jobvt == \'N\'.-svR :: Matrix Double -> Vector Double-svR = svAux dgesvd "svR" . fmat---- | Singular values of a complex matrix, using LAPACK's /zgesvd/ with jobu == jobvt == \'N\'.-svC :: Matrix (Complex Double) -> Vector Double-svC = svAux zgesvd "svC" . fmat---- | Singular values of a real matrix, using LAPACK's /dgesdd/ with jobz == \'N\'.-svRd :: Matrix Double -> Vector Double-svRd = svAux dgesdd "svRd" . fmat---- | Singular values of a complex matrix, using LAPACK's /zgesdd/ with jobz == \'N\'.-svCd :: Matrix (Complex Double) -> Vector Double-svCd = svAux zgesdd "svCd" . fmat--svAux f st x = unsafePerformIO $ do- s <- createVector q- app2 g mat x vec s st- return s- where r = rows x- c = cols x- q = min r c- g ra ca pa nb pb = f ra ca pa 0 0 nullPtr nb pb 0 0 nullPtr----- | Singular values and all right singular vectors of a real matrix, using LAPACK's /dgesvd/ with jobu == \'N\' and jobvt == \'A\'.-rightSVR :: Matrix Double -> (Vector Double, Matrix Double)-rightSVR = rightSVAux dgesvd "rightSVR" . fmat---- | Singular values and all right singular vectors of a complex matrix, using LAPACK's /zgesvd/ with jobu == \'N\' and jobvt == \'A\'.-rightSVC :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double))-rightSVC = rightSVAux zgesvd "rightSVC" . fmat--rightSVAux f st x = unsafePerformIO $ do- s <- createVector q- v <- createMatrix ColumnMajor c c- app3 g mat x vec s mat v st- return (s,trans v)- where r = rows x- c = cols x- q = min r c- g ra ca pa = f ra ca pa 0 0 nullPtr----- | Singular values and all left singular vectors of a real matrix, using LAPACK's /dgesvd/ with jobu == \'A\' and jobvt == \'N\'.-leftSVR :: Matrix Double -> (Matrix Double, Vector Double)-leftSVR = leftSVAux dgesvd "leftSVR" . fmat---- | Singular values and all left singular vectors of a complex matrix, using LAPACK's /zgesvd/ with jobu == \'A\' and jobvt == \'N\'.-leftSVC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector Double)-leftSVC = leftSVAux zgesvd "leftSVC" . fmat--leftSVAux f st x = unsafePerformIO $ do- u <- createMatrix ColumnMajor r r- s <- createVector q- app3 g mat x mat u vec s st- return (u,s)- where r = rows x- c = cols x- q = min r c- g ra ca pa ru cu pu nb pb = f ra ca pa ru cu pu nb pb 0 0 nullPtr---------------------------------------------------------------------------------foreign import ccall unsafe "eig_l_R" dgeev :: TMMCVM-foreign import ccall unsafe "eig_l_C" zgeev :: TCMCMCVCM-foreign import ccall unsafe "eig_l_S" dsyev :: CInt -> TMVM-foreign import ccall unsafe "eig_l_H" zheev :: CInt -> TCMVCM--eigAux f st m = unsafePerformIO $ do- l <- createVector r- v <- createMatrix ColumnMajor r r- app3 g mat m vec l mat v st- return (l,v)- where r = rows m- g ra ca pa = f ra ca pa 0 0 nullPtr----- | Eigenvalues and right eigenvectors of a general complex matrix, using LAPACK's /zgeev/.--- The eigenvectors are the columns of v. The eigenvalues are not sorted.-eigC :: Matrix (Complex Double) -> (Vector (Complex Double), Matrix (Complex Double))-eigC = eigAux zgeev "eigC" . fmat--eigOnlyAux f st m = unsafePerformIO $ do- l <- createVector r- app2 g mat m vec l st- return l- where r = rows m- g ra ca pa nl pl = f ra ca pa 0 0 nullPtr nl pl 0 0 nullPtr---- | Eigenvalues of a general complex matrix, using LAPACK's /zgeev/ with jobz == \'N\'.--- The eigenvalues are not sorted.-eigOnlyC :: Matrix (Complex Double) -> Vector (Complex Double)-eigOnlyC = eigOnlyAux zgeev "eigOnlyC" . fmat---- | Eigenvalues and right eigenvectors of a general real matrix, using LAPACK's /dgeev/.--- The eigenvectors are the columns of v. The eigenvalues are not sorted.-eigR :: Matrix Double -> (Vector (Complex Double), Matrix (Complex Double))-eigR m = (s', v'')- where (s,v) = eigRaux (fmat m)- s' = fixeig1 s- v' = toRows $ trans v- v'' = fromColumns $ fixeig (toList s') v'--eigRaux :: Matrix Double -> (Vector (Complex Double), Matrix Double)-eigRaux m = unsafePerformIO $ do- l <- createVector r- v <- createMatrix ColumnMajor r r- app3 g mat m vec l mat v "eigR"- return (l,v)- where r = rows m- g ra ca pa = dgeev ra ca pa 0 0 nullPtr--fixeig1 s = toComplex' (subVector 0 r (asReal s), subVector r r (asReal s))- where r = dim s--fixeig [] _ = []-fixeig [_] [v] = [comp' v]-fixeig ((r1:+i1):(r2:+i2):r) (v1:v2:vs)- | r1 == r2 && i1 == (-i2) = toComplex' (v1,v2) : toComplex' (v1,scale (-1) v2) : fixeig r vs- | otherwise = comp' v1 : fixeig ((r2:+i2):r) (v2:vs)- where scale = vectorMapValR Scale-fixeig _ _ = error "fixeig with impossible inputs"----- | Eigenvalues of a general real matrix, using LAPACK's /dgeev/ with jobz == \'N\'.--- The eigenvalues are not sorted.-eigOnlyR :: Matrix Double -> Vector (Complex Double)-eigOnlyR = fixeig1 . eigOnlyAux dgeev "eigOnlyR" . fmat----------------------------------------------------------------------------------eigSHAux f st m = unsafePerformIO $ do- l <- createVector r- v <- createMatrix ColumnMajor r r- app3 f mat m vec l mat v st- return (l,v)- where r = rows m---- | Eigenvalues and right eigenvectors of a symmetric real matrix, using LAPACK's /dsyev/.--- The eigenvectors are the columns of v.--- The eigenvalues are sorted in descending order (use 'eigS'' for ascending order).-eigS :: Matrix Double -> (Vector Double, Matrix Double)-eigS m = (s', fliprl v)- where (s,v) = eigS' (fmat m)- s' = fromList . reverse . toList $ s---- | 'eigS' in ascending order-eigS' :: Matrix Double -> (Vector Double, Matrix Double)-eigS' = eigSHAux (dsyev 1) "eigS'" . fmat---- | Eigenvalues and right eigenvectors of a hermitian complex matrix, using LAPACK's /zheev/.--- The eigenvectors are the columns of v.--- The eigenvalues are sorted in descending order (use 'eigH'' for ascending order).-eigH :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double))-eigH m = (s', fliprl v)- where (s,v) = eigH' (fmat m)- s' = fromList . reverse . toList $ s---- | 'eigH' in ascending order-eigH' :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double))-eigH' = eigSHAux (zheev 1) "eigH'" . fmat----- | Eigenvalues of a symmetric real matrix, using LAPACK's /dsyev/ with jobz == \'N\'.--- The eigenvalues are sorted in descending order.-eigOnlyS :: Matrix Double -> Vector Double-eigOnlyS = vrev . fst. eigSHAux (dsyev 0) "eigS'" . fmat---- | Eigenvalues of a hermitian complex matrix, using LAPACK's /zheev/ with jobz == \'N\'.--- The eigenvalues are sorted in descending order.-eigOnlyH :: Matrix (Complex Double) -> Vector Double-eigOnlyH = vrev . fst. eigSHAux (zheev 1) "eigH'" . fmat--vrev = flatten . flipud . reshape 1--------------------------------------------------------------------------------foreign import ccall unsafe "linearSolveR_l" dgesv :: TMMM-foreign import ccall unsafe "linearSolveC_l" zgesv :: TCMCMCM-foreign import ccall unsafe "cholSolveR_l" dpotrs :: TMMM-foreign import ccall unsafe "cholSolveC_l" zpotrs :: TCMCMCM--linearSolveSQAux f st a b- | n1==n2 && n1==r = unsafePerformIO $ do- s <- createMatrix ColumnMajor r c- app3 f mat a mat b mat s st- return s- | otherwise = error $ st ++ " of nonsquare matrix"- where n1 = rows a- n2 = cols a- r = rows b- c = cols b---- | Solve a real linear system (for square coefficient matrix and several right-hand sides) using the LU decomposition, based on LAPACK's /dgesv/. For underconstrained or overconstrained systems use 'linearSolveLSR' or 'linearSolveSVDR'. See also 'lusR'.-linearSolveR :: Matrix Double -> Matrix Double -> Matrix Double-linearSolveR a b = linearSolveSQAux dgesv "linearSolveR" (fmat a) (fmat b)---- | Solve a complex linear system (for square coefficient matrix and several right-hand sides) using the LU decomposition, based on LAPACK's /zgesv/. For underconstrained or overconstrained systems use 'linearSolveLSC' or 'linearSolveSVDC'. See also 'lusC'.-linearSolveC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)-linearSolveC a b = linearSolveSQAux zgesv "linearSolveC" (fmat a) (fmat b)----- | Solves a symmetric positive definite system of linear equations using a precomputed Cholesky factorization obtained by 'cholS'.-cholSolveR :: Matrix Double -> Matrix Double -> Matrix Double-cholSolveR a b = linearSolveSQAux dpotrs "cholSolveR" (fmat a) (fmat b)---- | Solves a Hermitian positive definite system of linear equations using a precomputed Cholesky factorization obtained by 'cholH'.-cholSolveC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)-cholSolveC a b = linearSolveSQAux zpotrs "cholSolveC" (fmat a) (fmat b)--------------------------------------------------------------------------------------foreign import ccall unsafe "linearSolveLSR_l" dgels :: TMMM-foreign import ccall unsafe "linearSolveLSC_l" zgels :: TCMCMCM-foreign import ccall unsafe "linearSolveSVDR_l" dgelss :: Double -> TMMM-foreign import ccall unsafe "linearSolveSVDC_l" zgelss :: Double -> TCMCMCM--linearSolveAux f st a b = unsafePerformIO $ do- r <- createMatrix ColumnMajor (max m n) nrhs- app3 f mat a mat b mat r st- return r- where m = rows a- n = cols a- nrhs = cols b---- | Least squared error solution of an overconstrained real linear system, or the minimum norm solution of an underconstrained system, using LAPACK's /dgels/. For rank-deficient systems use 'linearSolveSVDR'.-linearSolveLSR :: Matrix Double -> Matrix Double -> Matrix Double-linearSolveLSR a b = subMatrix (0,0) (cols a, cols b) $- linearSolveAux dgels "linearSolverLSR" (fmat a) (fmat b)---- | Least squared error solution of an overconstrained complex linear system, or the minimum norm solution of an underconstrained system, using LAPACK's /zgels/. For rank-deficient systems use 'linearSolveSVDC'.-linearSolveLSC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)-linearSolveLSC a b = subMatrix (0,0) (cols a, cols b) $- linearSolveAux zgels "linearSolveLSC" (fmat a) (fmat b)---- | Minimum norm solution of a general real linear least squares problem Ax=B using the SVD, based on LAPACK's /dgelss/. Admits rank-deficient systems but it is slower than 'linearSolveLSR'. The effective rank of A is determined by treating as zero those singular valures which are less than rcond times the largest singular value. If rcond == Nothing machine precision is used.-linearSolveSVDR :: Maybe Double -- ^ rcond- -> Matrix Double -- ^ coefficient matrix- -> Matrix Double -- ^ right hand sides (as columns)- -> Matrix Double -- ^ solution vectors (as columns)-linearSolveSVDR (Just rcond) a b = subMatrix (0,0) (cols a, cols b) $- linearSolveAux (dgelss rcond) "linearSolveSVDR" (fmat a) (fmat b)-linearSolveSVDR Nothing a b = linearSolveSVDR (Just (-1)) (fmat a) (fmat b)---- | Minimum norm solution of a general complex linear least squares problem Ax=B using the SVD, based on LAPACK's /zgelss/. Admits rank-deficient systems but it is slower than 'linearSolveLSC'. The effective rank of A is determined by treating as zero those singular valures which are less than rcond times the largest singular value. If rcond == Nothing machine precision is used.-linearSolveSVDC :: Maybe Double -- ^ rcond- -> Matrix (Complex Double) -- ^ coefficient matrix- -> Matrix (Complex Double) -- ^ right hand sides (as columns)- -> Matrix (Complex Double) -- ^ solution vectors (as columns)-linearSolveSVDC (Just rcond) a b = subMatrix (0,0) (cols a, cols b) $- linearSolveAux (zgelss rcond) "linearSolveSVDC" (fmat a) (fmat b)-linearSolveSVDC Nothing a b = linearSolveSVDC (Just (-1)) (fmat a) (fmat b)--------------------------------------------------------------------------------------foreign import ccall unsafe "chol_l_H" zpotrf :: TCMCM-foreign import ccall unsafe "chol_l_S" dpotrf :: TMM--cholAux f st a = do- r <- createMatrix ColumnMajor n n- app2 f mat a mat r st- return r- where n = rows a---- | Cholesky factorization of a complex Hermitian positive definite matrix, using LAPACK's /zpotrf/.-cholH :: Matrix (Complex Double) -> Matrix (Complex Double)-cholH = unsafePerformIO . cholAux zpotrf "cholH" . fmat---- | Cholesky factorization of a real symmetric positive definite matrix, using LAPACK's /dpotrf/.-cholS :: Matrix Double -> Matrix Double-cholS = unsafePerformIO . cholAux dpotrf "cholS" . fmat---- | Cholesky factorization of a complex Hermitian positive definite matrix, using LAPACK's /zpotrf/ ('Maybe' version).-mbCholH :: Matrix (Complex Double) -> Maybe (Matrix (Complex Double))-mbCholH = unsafePerformIO . mbCatch . cholAux zpotrf "cholH" . fmat---- | Cholesky factorization of a real symmetric positive definite matrix, using LAPACK's /dpotrf/ ('Maybe' version).-mbCholS :: Matrix Double -> Maybe (Matrix Double)-mbCholS = unsafePerformIO . mbCatch . cholAux dpotrf "cholS" . fmat--------------------------------------------------------------------------------------foreign import ccall unsafe "qr_l_R" dgeqr2 :: TMVM-foreign import ccall unsafe "qr_l_C" zgeqr2 :: TCMCVCM---- | QR factorization of a real matrix, using LAPACK's /dgeqr2/.-qrR :: Matrix Double -> (Matrix Double, Vector Double)-qrR = qrAux dgeqr2 "qrR" . fmat---- | QR factorization of a complex matrix, using LAPACK's /zgeqr2/.-qrC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector (Complex Double))-qrC = qrAux zgeqr2 "qrC" . fmat--qrAux f st a = unsafePerformIO $ do- r <- createMatrix ColumnMajor m n- tau <- createVector mn- app3 f mat a vec tau mat r st- return (r,tau)- where m = rows a- n = cols a- mn = min m n--------------------------------------------------------------------------------------foreign import ccall unsafe "hess_l_R" dgehrd :: TMVM-foreign import ccall unsafe "hess_l_C" zgehrd :: TCMCVCM---- | Hessenberg factorization of a square real matrix, using LAPACK's /dgehrd/.-hessR :: Matrix Double -> (Matrix Double, Vector Double)-hessR = hessAux dgehrd "hessR" . fmat---- | Hessenberg factorization of a square complex matrix, using LAPACK's /zgehrd/.-hessC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector (Complex Double))-hessC = hessAux zgehrd "hessC" . fmat--hessAux f st a = unsafePerformIO $ do- r <- createMatrix ColumnMajor m n- tau <- createVector (mn-1)- app3 f mat a vec tau mat r st- return (r,tau)- where m = rows a- n = cols a- mn = min m n--------------------------------------------------------------------------------------foreign import ccall unsafe "schur_l_R" dgees :: TMMM-foreign import ccall unsafe "schur_l_C" zgees :: TCMCMCM---- | Schur factorization of a square real matrix, using LAPACK's /dgees/.-schurR :: Matrix Double -> (Matrix Double, Matrix Double)-schurR = schurAux dgees "schurR" . fmat---- | Schur factorization of a square complex matrix, using LAPACK's /zgees/.-schurC :: Matrix (Complex Double) -> (Matrix (Complex Double), Matrix (Complex Double))-schurC = schurAux zgees "schurC" . fmat--schurAux f st a = unsafePerformIO $ do- u <- createMatrix ColumnMajor n n- s <- createMatrix ColumnMajor n n- app3 f mat a mat u mat s st- return (u,s)- where n = rows a--------------------------------------------------------------------------------------foreign import ccall unsafe "lu_l_R" dgetrf :: TMVM-foreign import ccall unsafe "lu_l_C" zgetrf :: TCMVCM---- | LU factorization of a general real matrix, using LAPACK's /dgetrf/.-luR :: Matrix Double -> (Matrix Double, [Int])-luR = luAux dgetrf "luR" . fmat---- | LU factorization of a general complex matrix, using LAPACK's /zgetrf/.-luC :: Matrix (Complex Double) -> (Matrix (Complex Double), [Int])-luC = luAux zgetrf "luC" . fmat--luAux f st a = unsafePerformIO $ do- lu <- createMatrix ColumnMajor n m- piv <- createVector (min n m)- app3 f mat a vec piv mat lu st- return (lu, map (pred.round) (toList piv))- where n = rows a- m = cols a--------------------------------------------------------------------------------------type TW a = CInt -> PD -> a-type TQ a = CInt -> CInt -> PC -> a--foreign import ccall unsafe "luS_l_R" dgetrs :: TMVMM-foreign import ccall unsafe "luS_l_C" zgetrs :: TQ (TW (TQ (TQ (IO CInt))))---- | Solve a real linear system from a precomputed LU decomposition ('luR'), using LAPACK's /dgetrs/.-lusR :: Matrix Double -> [Int] -> Matrix Double -> Matrix Double-lusR a piv b = lusAux dgetrs "lusR" (fmat a) piv (fmat b)---- | Solve a real linear system from a precomputed LU decomposition ('luC'), using LAPACK's /zgetrs/.-lusC :: Matrix (Complex Double) -> [Int] -> Matrix (Complex Double) -> Matrix (Complex Double)-lusC a piv b = lusAux zgetrs "lusC" (fmat a) piv (fmat b)--lusAux f st a piv b- | n1==n2 && n2==n =unsafePerformIO $ do- x <- createMatrix ColumnMajor n m- app4 f mat a vec piv' mat b mat x st- return x- | otherwise = error $ st ++ " on LU factorization of nonsquare matrix"- where n1 = rows a- n2 = cols a- n = rows b- m = cols b- piv' = fromList (map (fromIntegral.succ) piv) :: Vector Double-
@@ -1,1448 +0,0 @@-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <math.h>-#include <time.h>-#include "lapack-aux.h"--#define MACRO(B) do {B} while (0)-#define ERROR(CODE) MACRO(return CODE;)-#define REQUIRES(COND, CODE) MACRO(if(!(COND)) {ERROR(CODE);})--#define MIN(A,B) ((A)<(B)?(A):(B))-#define MAX(A,B) ((A)>(B)?(A):(B))--// #define DBGL--#ifdef DBGL-#define DEBUGMSG(M) printf("\nLAPACK "M"\n");-#else-#define DEBUGMSG(M)-#endif--#define OK return 0;--// #ifdef DBGL-// #define DEBUGMSG(M) printf("LAPACK Wrapper "M"\n: "); size_t t0 = time(NULL);-// #define OK MACRO(printf("%ld s\n",time(0)-t0); return 0;);-// #else-// #define DEBUGMSG(M)-// #define OK return 0;-// #endif--#define TRACEMAT(M) {int q; printf(" %d x %d: ",M##r,M##c); \- for(q=0;q<M##r*M##c;q++) printf("%.1f ",M##p[q]); printf("\n");}--#define CHECK(RES,CODE) MACRO(if(RES) return CODE;)--#define BAD_SIZE 2000-#define BAD_CODE 2001-#define MEM 2002-#define BAD_FILE 2003-#define SINGULAR 2004-#define NOCONVER 2005-#define NODEFPOS 2006-#define NOSPRTD 2007--//----------------------------------------void asm_finit() {-#ifdef i386--// asm("finit");-- static unsigned char buf[108];- asm("FSAVE %0":"=m" (buf));-- #if FPUDEBUG- if(buf[8]!=255 || buf[9]!=255) { // print warning in red- printf("%c[;31mWarning: FPU TAG = %x %x\%c[0m\n",0x1B,buf[8],buf[9],0x1B);- }- #endif-- #if NANDEBUG- asm("FRSTOR %0":"=m" (buf));- #endif--#endif-}--//-----------------------------------------#if NANDEBUG--#define CHECKNANR(M,msg) \-{ int k; \-for(k=0; k<(M##r * M##c); k++) { \- if(M##p[k] != M##p[k]) { \- printf(msg); \- TRACEMAT(M) \- /*exit(1);*/ \- } \-} \-}--#define CHECKNANC(M,msg) \-{ int k; \-for(k=0; k<(M##r * M##c); k++) { \- if( M##p[k].r != M##p[k].r \- || M##p[k].i != M##p[k].i) { \- printf(msg); \- /*exit(1);*/ \- } \-} \-}--#else-#define CHECKNANC(M,msg)-#define CHECKNANR(M,msg)-#endif--//-----------------------------------------//////////////////// real svd ////////////////////////////////////--/* Subroutine */ int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n,- doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *- ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,- integer *info);--int svd_l_R(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) {- integer m = ar;- integer n = ac;- integer q = MIN(m,n);- REQUIRES(sn==q,BAD_SIZE);- REQUIRES(up==NULL || ur==m && (uc==m || uc==q),BAD_SIZE);- char* jobu = "A";- if (up==NULL) {- jobu = "N";- } else {- if (uc==q) {- jobu = "S";- }- }- REQUIRES(vp==NULL || vc==n && (vr==n || vr==q),BAD_SIZE);- char* jobvt = "A";- integer ldvt = n;- if (vp==NULL) {- jobvt = "N";- } else {- if (vr==q) {- jobvt = "S";- ldvt = q;- }- }- DEBUGMSG("svd_l_R");- double *B = (double*)malloc(m*n*sizeof(double));- CHECK(!B,MEM);- memcpy(B,ap,m*n*sizeof(double));- integer lwork = -1;- integer res;- // ask for optimal lwork- double ans;- dgesvd_ (jobu,jobvt,- &m,&n,B,&m,- sp,- up,&m,- vp,&ldvt,- &ans, &lwork,- &res);- lwork = ceil(ans);- double * work = (double*)malloc(lwork*sizeof(double));- CHECK(!work,MEM);- dgesvd_ (jobu,jobvt,- &m,&n,B,&m,- sp,- up,&m,- vp,&ldvt,- work, &lwork,- &res);- CHECK(res,res);- free(work);- free(B);- OK-}--// (alternative version)--/* Subroutine */ int dgesdd_(char *jobz, integer *m, integer *n, doublereal *- a, integer *lda, doublereal *s, doublereal *u, integer *ldu,- doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,- integer *iwork, integer *info);--int svd_l_Rdd(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) {- integer m = ar;- integer n = ac;- integer q = MIN(m,n);- REQUIRES(sn==q,BAD_SIZE);- REQUIRES(up == NULL && vp == NULL- || ur==m && vc==n- && (uc == q && vr == q- || uc == m && vc==n),BAD_SIZE);- char* jobz = "A";- integer ldvt = n;- if (up==NULL) {- jobz = "N";- } else {- if (uc==q && vr == q) {- jobz = "S";- ldvt = q;- }- }- DEBUGMSG("svd_l_Rdd");- double *B = (double*)malloc(m*n*sizeof(double));- CHECK(!B,MEM);- memcpy(B,ap,m*n*sizeof(double));- integer* iwk = (integer*) malloc(8*q*sizeof(integer));- CHECK(!iwk,MEM);- integer lwk = -1;- integer res;- // ask for optimal lwk- double ans;- dgesdd_ (jobz,&m,&n,B,&m,sp,up,&m,vp,&ldvt,&ans,&lwk,iwk,&res);- lwk = ans;- double * workv = (double*)malloc(lwk*sizeof(double));- CHECK(!workv,MEM);- dgesdd_ (jobz,&m,&n,B,&m,sp,up,&m,vp,&ldvt,workv,&lwk,iwk,&res);- CHECK(res,res);- free(iwk);- free(workv);- free(B);- OK-}--//////////////////// complex svd ////////////////////////////////////--// not in clapack.h--int zgesvd_(char *jobu, char *jobvt, integer *m, integer *n,- doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u,- integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work,- integer *lwork, doublereal *rwork, integer *info);--int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) {- integer m = ar;- integer n = ac;- integer q = MIN(m,n);- REQUIRES(sn==q,BAD_SIZE);- REQUIRES(up==NULL || ur==m && (uc==m || uc==q),BAD_SIZE);- char* jobu = "A";- if (up==NULL) {- jobu = "N";- } else {- if (uc==q) {- jobu = "S";- }- }- REQUIRES(vp==NULL || vc==n && (vr==n || vr==q),BAD_SIZE);- char* jobvt = "A";- integer ldvt = n;- if (vp==NULL) {- jobvt = "N";- } else {- if (vr==q) {- jobvt = "S";- ldvt = q;- }- }DEBUGMSG("svd_l_C");- doublecomplex *B = (doublecomplex*)malloc(m*n*sizeof(doublecomplex));- CHECK(!B,MEM);- memcpy(B,ap,m*n*sizeof(doublecomplex));-- double *rwork = (double*) malloc(5*q*sizeof(double));- CHECK(!rwork,MEM);- integer lwork = -1;- integer res;- // ask for optimal lwork- doublecomplex ans;- zgesvd_ (jobu,jobvt,- &m,&n,B,&m,- sp,- up,&m,- vp,&ldvt,- &ans, &lwork,- rwork,- &res);- lwork = ceil(ans.r);- doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- CHECK(!work,MEM);- zgesvd_ (jobu,jobvt,- &m,&n,B,&m,- sp,- up,&m,- vp,&ldvt,- work, &lwork,- rwork,- &res);- CHECK(res,res);- free(work);- free(rwork);- free(B);- OK-}--int zgesdd_ (char *jobz, integer *m, integer *n,- doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u,- integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work,- integer *lwork, doublereal *rwork, integer* iwork, integer *info);--int svd_l_Cdd(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) {- //printf("entro\n");- integer m = ar;- integer n = ac;- integer q = MIN(m,n);- REQUIRES(sn==q,BAD_SIZE);- REQUIRES(up == NULL && vp == NULL- || ur==m && vc==n- && (uc == q && vr == q- || uc == m && vc==n),BAD_SIZE);- char* jobz = "A";- integer ldvt = n;- if (up==NULL) {- jobz = "N";- } else {- if (uc==q && vr == q) {- jobz = "S";- ldvt = q;- }- }- DEBUGMSG("svd_l_Cdd");- doublecomplex *B = (doublecomplex*)malloc(m*n*sizeof(doublecomplex));- CHECK(!B,MEM);- memcpy(B,ap,m*n*sizeof(doublecomplex));- integer* iwk = (integer*) malloc(8*q*sizeof(integer));- CHECK(!iwk,MEM);- int lrwk;- if (0 && *jobz == 'N') {- lrwk = 5*q; // does not work, crash at free below- } else {- lrwk = 5*q*q + 7*q;- }- double *rwk = (double*)malloc(lrwk*sizeof(double));;- CHECK(!rwk,MEM);- //printf("%s %ld %d\n",jobz,q,lrwk);- integer lwk = -1;- integer res;- // ask for optimal lwk- doublecomplex ans;- zgesdd_ (jobz,&m,&n,B,&m,sp,up,&m,vp,&ldvt,&ans,&lwk,rwk,iwk,&res);- lwk = ans.r;- //printf("lwk = %ld\n",lwk);- doublecomplex * workv = (doublecomplex*)malloc(lwk*sizeof(doublecomplex));- CHECK(!workv,MEM);- zgesdd_ (jobz,&m,&n,B,&m,sp,up,&m,vp,&ldvt,workv,&lwk,rwk,iwk,&res);- //printf("res = %ld\n",res);- CHECK(res,res);- free(workv); // printf("freed workv\n");- free(rwk); // printf("freed rwk\n");- free(iwk); // printf("freed iwk\n");- free(B); // printf("freed B, salgo\n");- OK-}--//////////////////// general complex eigensystem ////////////--/* Subroutine */ int zgeev_(char *jobvl, char *jobvr, integer *n,- doublecomplex *a, integer *lda, doublecomplex *w, doublecomplex *vl,- integer *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work,- integer *lwork, doublereal *rwork, integer *info);--int eig_l_C(KCMAT(a), CMAT(u), CVEC(s),CMAT(v)) {- integer n = ar;- REQUIRES(ac==n && sn==n, BAD_SIZE);- REQUIRES(up==NULL || ur==n && uc==n, BAD_SIZE);- char jobvl = up==NULL?'N':'V';- REQUIRES(vp==NULL || vr==n && vc==n, BAD_SIZE);- char jobvr = vp==NULL?'N':'V';- DEBUGMSG("eig_l_C");- doublecomplex *B = (doublecomplex*)malloc(n*n*sizeof(doublecomplex));- CHECK(!B,MEM);- memcpy(B,ap,n*n*sizeof(doublecomplex));- double *rwork = (double*) malloc(2*n*sizeof(double));- CHECK(!rwork,MEM);- integer lwork = -1;- integer res;- // ask for optimal lwork- doublecomplex ans;- //printf("ask zgeev\n");- zgeev_ (&jobvl,&jobvr,- &n,B,&n,- sp,- up,&n,- vp,&n,- &ans, &lwork,- rwork,- &res);- lwork = ceil(ans.r);- //printf("ans = %d\n",lwork);- doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- CHECK(!work,MEM);- //printf("zgeev\n");- zgeev_ (&jobvl,&jobvr,- &n,B,&n,- sp,- up,&n,- vp,&n,- work, &lwork,- rwork,- &res);- CHECK(res,res);- free(work);- free(rwork);- free(B);- OK-}----//////////////////// general real eigensystem ////////////--/* Subroutine */ int dgeev_(char *jobvl, char *jobvr, integer *n, doublereal *- a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl,- integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work,- integer *lwork, integer *info);--int eig_l_R(KDMAT(a),DMAT(u), CVEC(s),DMAT(v)) {- integer n = ar;- REQUIRES(ac==n && sn==n, BAD_SIZE);- REQUIRES(up==NULL || ur==n && uc==n, BAD_SIZE);- char jobvl = up==NULL?'N':'V';- REQUIRES(vp==NULL || vr==n && vc==n, BAD_SIZE);- char jobvr = vp==NULL?'N':'V';- DEBUGMSG("eig_l_R");- double *B = (double*)malloc(n*n*sizeof(double));- CHECK(!B,MEM);- memcpy(B,ap,n*n*sizeof(double));- integer lwork = -1;- integer res;- // ask for optimal lwork- double ans;- //printf("ask dgeev\n");- dgeev_ (&jobvl,&jobvr,- &n,B,&n,- (double*)sp, (double*)sp+n,- up,&n,- vp,&n,- &ans, &lwork,- &res);- lwork = ceil(ans);- //printf("ans = %d\n",lwork);- double * work = (double*)malloc(lwork*sizeof(double));- CHECK(!work,MEM);- //printf("dgeev\n");- dgeev_ (&jobvl,&jobvr,- &n,B,&n,- (double*)sp, (double*)sp+n,- up,&n,- vp,&n,- work, &lwork,- &res);- CHECK(res,res);- free(work);- free(B);- OK-}---//////////////////// symmetric real eigensystem ////////////--/* Subroutine */ int dsyev_(char *jobz, char *uplo, integer *n, doublereal *a,- integer *lda, doublereal *w, doublereal *work, integer *lwork,- integer *info);--int eig_l_S(int wantV,KDMAT(a),DVEC(s),DMAT(v)) {- integer n = ar;- REQUIRES(ac==n && sn==n, BAD_SIZE);- REQUIRES(vr==n && vc==n, BAD_SIZE);- char jobz = wantV?'V':'N';- DEBUGMSG("eig_l_S");- memcpy(vp,ap,n*n*sizeof(double));- integer lwork = -1;- char uplo = 'U';- integer res;- // ask for optimal lwork- double ans;- //printf("ask dsyev\n");- dsyev_ (&jobz,&uplo,- &n,vp,&n,- sp,- &ans, &lwork,- &res);- lwork = ceil(ans);- //printf("ans = %d\n",lwork);- double * work = (double*)malloc(lwork*sizeof(double));- CHECK(!work,MEM);- dsyev_ (&jobz,&uplo,- &n,vp,&n,- sp,- work, &lwork,- &res);- CHECK(res,res);- free(work);- OK-}--//////////////////// hermitian complex eigensystem ////////////--/* Subroutine */ int zheev_(char *jobz, char *uplo, integer *n, doublecomplex- *a, integer *lda, doublereal *w, doublecomplex *work, integer *lwork,- doublereal *rwork, integer *info);--int eig_l_H(int wantV,KCMAT(a),DVEC(s),CMAT(v)) {- integer n = ar;- REQUIRES(ac==n && sn==n, BAD_SIZE);- REQUIRES(vr==n && vc==n, BAD_SIZE);- char jobz = wantV?'V':'N';- DEBUGMSG("eig_l_H");- memcpy(vp,ap,2*n*n*sizeof(double));- double *rwork = (double*) malloc((3*n-2)*sizeof(double));- CHECK(!rwork,MEM);- integer lwork = -1;- char uplo = 'U';- integer res;- // ask for optimal lwork- doublecomplex ans;- //printf("ask zheev\n");- zheev_ (&jobz,&uplo,- &n,vp,&n,- sp,- &ans, &lwork,- rwork,- &res);- lwork = ceil(ans.r);- //printf("ans = %d\n",lwork);- doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- CHECK(!work,MEM);- zheev_ (&jobz,&uplo,- &n,vp,&n,- sp,- work, &lwork,- rwork,- &res);- CHECK(res,res);- free(work);- free(rwork);- OK-}--//////////////////// general real linear system ////////////--/* Subroutine */ int dgesv_(integer *n, integer *nrhs, doublereal *a, integer- *lda, integer *ipiv, doublereal *b, integer *ldb, integer *info);--int linearSolveR_l(KDMAT(a),KDMAT(b),DMAT(x)) {- integer n = ar;- integer nhrs = bc;- REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE);- DEBUGMSG("linearSolveR_l");- double*AC = (double*)malloc(n*n*sizeof(double));- memcpy(AC,ap,n*n*sizeof(double));- memcpy(xp,bp,n*nhrs*sizeof(double));- integer * ipiv = (integer*)malloc(n*sizeof(integer));- integer res;- dgesv_ (&n,&nhrs,- AC, &n,- ipiv,- xp, &n,- &res);- if(res>0) {- return SINGULAR;- }- CHECK(res,res);- free(ipiv);- free(AC);- OK-}--//////////////////// general complex linear system ////////////--/* Subroutine */ int zgesv_(integer *n, integer *nrhs, doublecomplex *a,- integer *lda, integer *ipiv, doublecomplex *b, integer *ldb, integer *- info);--int linearSolveC_l(KCMAT(a),KCMAT(b),CMAT(x)) {- integer n = ar;- integer nhrs = bc;- REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE);- DEBUGMSG("linearSolveC_l");- doublecomplex*AC = (doublecomplex*)malloc(n*n*sizeof(doublecomplex));- memcpy(AC,ap,n*n*sizeof(doublecomplex));- memcpy(xp,bp,n*nhrs*sizeof(doublecomplex));- integer * ipiv = (integer*)malloc(n*sizeof(integer));- integer res;- zgesv_ (&n,&nhrs,- AC, &n,- ipiv,- xp, &n,- &res);- if(res>0) {- return SINGULAR;- }- CHECK(res,res);- free(ipiv);- free(AC);- OK-}--//////// symmetric positive definite real linear system using Cholesky ////////////--/* Subroutine */ int dpotrs_(char *uplo, integer *n, integer *nrhs,- doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *- info);--int cholSolveR_l(KDMAT(a),KDMAT(b),DMAT(x)) {- integer n = ar;- integer nhrs = bc;- REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE);- DEBUGMSG("cholSolveR_l");- memcpy(xp,bp,n*nhrs*sizeof(double));- integer res;- dpotrs_ ("U",- &n,&nhrs,- (double*)ap, &n,- xp, &n,- &res);- CHECK(res,res);- OK-}--//////// Hermitian positive definite real linear system using Cholesky ////////////--/* Subroutine */ int zpotrs_(char *uplo, integer *n, integer *nrhs,- doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,- integer *info);--int cholSolveC_l(KCMAT(a),KCMAT(b),CMAT(x)) {- integer n = ar;- integer nhrs = bc;- REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE);- DEBUGMSG("cholSolveC_l");- memcpy(xp,bp,n*nhrs*sizeof(doublecomplex));- integer res;- zpotrs_ ("U",- &n,&nhrs,- (doublecomplex*)ap, &n,- xp, &n,- &res);- CHECK(res,res);- OK-}--//////////////////// least squares real linear system ////////////--/* Subroutine */ int dgels_(char *trans, integer *m, integer *n, integer *- nrhs, doublereal *a, integer *lda, doublereal *b, integer *ldb,- doublereal *work, integer *lwork, integer *info);--int linearSolveLSR_l(KDMAT(a),KDMAT(b),DMAT(x)) {- integer m = ar;- integer n = ac;- integer nrhs = bc;- integer ldb = xr;- REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);- DEBUGMSG("linearSolveLSR_l");- double*AC = (double*)malloc(m*n*sizeof(double));- memcpy(AC,ap,m*n*sizeof(double));- if (m>=n) {- memcpy(xp,bp,m*nrhs*sizeof(double));- } else {- int k;- for(k = 0; k<nrhs; k++) {- memcpy(xp+ldb*k,bp+m*k,m*sizeof(double));- }- }- integer res;- integer lwork = -1;- double ans;- dgels_ ("N",&m,&n,&nrhs,- AC,&m,- xp,&ldb,- &ans,&lwork,- &res);- lwork = ceil(ans);- //printf("ans = %d\n",lwork);- double * work = (double*)malloc(lwork*sizeof(double));- dgels_ ("N",&m,&n,&nrhs,- AC,&m,- xp,&ldb,- work,&lwork,- &res);- if(res>0) {- return SINGULAR;- }- CHECK(res,res);- free(work);- free(AC);- OK-}--//////////////////// least squares complex linear system ////////////--/* Subroutine */ int zgels_(char *trans, integer *m, integer *n, integer *- nrhs, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,- doublecomplex *work, integer *lwork, integer *info);--int linearSolveLSC_l(KCMAT(a),KCMAT(b),CMAT(x)) {- integer m = ar;- integer n = ac;- integer nrhs = bc;- integer ldb = xr;- REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);- DEBUGMSG("linearSolveLSC_l");- doublecomplex*AC = (doublecomplex*)malloc(m*n*sizeof(doublecomplex));- memcpy(AC,ap,m*n*sizeof(doublecomplex));- if (m>=n) {- memcpy(xp,bp,m*nrhs*sizeof(doublecomplex));- } else {- int k;- for(k = 0; k<nrhs; k++) {- memcpy(xp+ldb*k,bp+m*k,m*sizeof(doublecomplex));- }- }- integer res;- integer lwork = -1;- doublecomplex ans;- zgels_ ("N",&m,&n,&nrhs,- AC,&m,- xp,&ldb,- &ans,&lwork,- &res);- lwork = ceil(ans.r);- //printf("ans = %d\n",lwork);- doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- zgels_ ("N",&m,&n,&nrhs,- AC,&m,- xp,&ldb,- work,&lwork,- &res);- if(res>0) {- return SINGULAR;- }- CHECK(res,res);- free(work);- free(AC);- OK-}--//////////////////// least squares real linear system using SVD ////////////--/* Subroutine */ int dgelss_(integer *m, integer *n, integer *nrhs,- doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *- s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork,- integer *info);--int linearSolveSVDR_l(double rcond,KDMAT(a),KDMAT(b),DMAT(x)) {- integer m = ar;- integer n = ac;- integer nrhs = bc;- integer ldb = xr;- REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);- DEBUGMSG("linearSolveSVDR_l");- double*AC = (double*)malloc(m*n*sizeof(double));- double*S = (double*)malloc(MIN(m,n)*sizeof(double));- memcpy(AC,ap,m*n*sizeof(double));- if (m>=n) {- memcpy(xp,bp,m*nrhs*sizeof(double));- } else {- int k;- for(k = 0; k<nrhs; k++) {- memcpy(xp+ldb*k,bp+m*k,m*sizeof(double));- }- }- integer res;- integer lwork = -1;- integer rank;- double ans;- dgelss_ (&m,&n,&nrhs,- AC,&m,- xp,&ldb,- S,- &rcond,&rank,- &ans,&lwork,- &res);- lwork = ceil(ans);- //printf("ans = %d\n",lwork);- double * work = (double*)malloc(lwork*sizeof(double));- dgelss_ (&m,&n,&nrhs,- AC,&m,- xp,&ldb,- S,- &rcond,&rank,- work,&lwork,- &res);- if(res>0) {- return NOCONVER;- }- CHECK(res,res);- free(work);- free(S);- free(AC);- OK-}--//////////////////// least squares complex linear system using SVD ////////////--// not in clapack.h--int zgelss_(integer *m, integer *n, integer *nhrs,- doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, doublereal *s,- doublereal *rcond, integer* rank,- doublecomplex *work, integer* lwork, doublereal* rwork,- integer *info);--int linearSolveSVDC_l(double rcond, KCMAT(a),KCMAT(b),CMAT(x)) {- integer m = ar;- integer n = ac;- integer nrhs = bc;- integer ldb = xr;- REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);- DEBUGMSG("linearSolveSVDC_l");- doublecomplex*AC = (doublecomplex*)malloc(m*n*sizeof(doublecomplex));- double*S = (double*)malloc(MIN(m,n)*sizeof(double));- double*RWORK = (double*)malloc(5*MIN(m,n)*sizeof(double));- memcpy(AC,ap,m*n*sizeof(doublecomplex));- if (m>=n) {- memcpy(xp,bp,m*nrhs*sizeof(doublecomplex));- } else {- int k;- for(k = 0; k<nrhs; k++) {- memcpy(xp+ldb*k,bp+m*k,m*sizeof(doublecomplex));- }- }- integer res;- integer lwork = -1;- integer rank;- doublecomplex ans;- zgelss_ (&m,&n,&nrhs,- AC,&m,- xp,&ldb,- S,- &rcond,&rank,- &ans,&lwork,- RWORK,- &res);- lwork = ceil(ans.r);- //printf("ans = %d\n",lwork);- doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- zgelss_ (&m,&n,&nrhs,- AC,&m,- xp,&ldb,- S,- &rcond,&rank,- work,&lwork,- RWORK,- &res);- if(res>0) {- return NOCONVER;- }- CHECK(res,res);- free(work);- free(RWORK);- free(S);- free(AC);- OK-}--//////////////////// Cholesky factorization /////////////////////////--/* Subroutine */ int zpotrf_(char *uplo, integer *n, doublecomplex *a,- integer *lda, integer *info);--int chol_l_H(KCMAT(a),CMAT(l)) {- integer n = ar;- REQUIRES(n>=1 && ac == n && lr==n && lc==n,BAD_SIZE);- DEBUGMSG("chol_l_H");- memcpy(lp,ap,n*n*sizeof(doublecomplex));- char uplo = 'U';- integer res;- zpotrf_ (&uplo,&n,lp,&n,&res);- CHECK(res>0,NODEFPOS);- CHECK(res,res);- doublecomplex zero = {0.,0.};- int r,c;- for (r=0; r<lr-1; r++) {- for(c=r+1; c<lc; c++) {- lp[r*lc+c] = zero;- }- }- OK-}---/* Subroutine */ int dpotrf_(char *uplo, integer *n, doublereal *a, integer *- lda, integer *info);--int chol_l_S(KDMAT(a),DMAT(l)) {- integer n = ar;- REQUIRES(n>=1 && ac == n && lr==n && lc==n,BAD_SIZE);- DEBUGMSG("chol_l_S");- memcpy(lp,ap,n*n*sizeof(double));- char uplo = 'U';- integer res;- dpotrf_ (&uplo,&n,lp,&n,&res);- CHECK(res>0,NODEFPOS);- CHECK(res,res);- int r,c;- for (r=0; r<lr-1; r++) {- for(c=r+1; c<lc; c++) {- lp[r*lc+c] = 0.;- }- }- OK-}--//////////////////// QR factorization /////////////////////////--/* Subroutine */ int dgeqr2_(integer *m, integer *n, doublereal *a, integer *- lda, doublereal *tau, doublereal *work, integer *info);--int qr_l_R(KDMAT(a), DVEC(tau), DMAT(r)) {- integer m = ar;- integer n = ac;- integer mn = MIN(m,n);- REQUIRES(m>=1 && n >=1 && rr== m && rc == n && taun == mn, BAD_SIZE);- DEBUGMSG("qr_l_R");- double *WORK = (double*)malloc(n*sizeof(double));- CHECK(!WORK,MEM);- memcpy(rp,ap,m*n*sizeof(double));- integer res;- dgeqr2_ (&m,&n,rp,&m,taup,WORK,&res);- CHECK(res,res);- free(WORK);- OK-}--/* Subroutine */ int zgeqr2_(integer *m, integer *n, doublecomplex *a,- integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);--int qr_l_C(KCMAT(a), CVEC(tau), CMAT(r)) {- integer m = ar;- integer n = ac;- integer mn = MIN(m,n);- REQUIRES(m>=1 && n >=1 && rr== m && rc == n && taun == mn, BAD_SIZE);- DEBUGMSG("qr_l_C");- doublecomplex *WORK = (doublecomplex*)malloc(n*sizeof(doublecomplex));- CHECK(!WORK,MEM);- memcpy(rp,ap,m*n*sizeof(doublecomplex));- integer res;- zgeqr2_ (&m,&n,rp,&m,taup,WORK,&res);- CHECK(res,res);- free(WORK);- OK-}--//////////////////// Hessenberg factorization /////////////////////////--/* Subroutine */ int dgehrd_(integer *n, integer *ilo, integer *ihi,- doublereal *a, integer *lda, doublereal *tau, doublereal *work,- integer *lwork, integer *info);--int hess_l_R(KDMAT(a), DVEC(tau), DMAT(r)) {- integer m = ar;- integer n = ac;- integer mn = MIN(m,n);- REQUIRES(m>=1 && n == m && rr== m && rc == n && taun == mn-1, BAD_SIZE);- DEBUGMSG("hess_l_R");- integer lwork = 5*n; // fixme- double *WORK = (double*)malloc(lwork*sizeof(double));- CHECK(!WORK,MEM);- memcpy(rp,ap,m*n*sizeof(double));- integer res;- integer one = 1;- dgehrd_ (&n,&one,&n,rp,&n,taup,WORK,&lwork,&res);- CHECK(res,res);- free(WORK);- OK-}---/* Subroutine */ int zgehrd_(integer *n, integer *ilo, integer *ihi,- doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *- work, integer *lwork, integer *info);--int hess_l_C(KCMAT(a), CVEC(tau), CMAT(r)) {- integer m = ar;- integer n = ac;- integer mn = MIN(m,n);- REQUIRES(m>=1 && n == m && rr== m && rc == n && taun == mn-1, BAD_SIZE);- DEBUGMSG("hess_l_C");- integer lwork = 5*n; // fixme- doublecomplex *WORK = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- CHECK(!WORK,MEM);- memcpy(rp,ap,m*n*sizeof(doublecomplex));- integer res;- integer one = 1;- zgehrd_ (&n,&one,&n,rp,&n,taup,WORK,&lwork,&res);- CHECK(res,res);- free(WORK);- OK-}--//////////////////// Schur factorization /////////////////////////--/* Subroutine */ int dgees_(char *jobvs, char *sort, L_fp select, integer *n,- doublereal *a, integer *lda, integer *sdim, doublereal *wr,- doublereal *wi, doublereal *vs, integer *ldvs, doublereal *work,- integer *lwork, logical *bwork, integer *info);--int schur_l_R(KDMAT(a), DMAT(u), DMAT(s)) {- integer m = ar;- integer n = ac;- REQUIRES(m>=1 && n==m && ur==n && uc==n && sr==n && sc==n, BAD_SIZE);- DEBUGMSG("schur_l_R");- int k;- //printf("---------------------------\n");- //printf("%p: ",ap); for(k=0;k<n*n;k++) printf("%f ",ap[k]); printf("\n");- //printf("%p: ",up); for(k=0;k<n*n;k++) printf("%f ",up[k]); printf("\n");- //printf("%p: ",sp); for(k=0;k<n*n;k++) printf("%f ",sp[k]); printf("\n");- memcpy(sp,ap,n*n*sizeof(double));- integer lwork = 6*n; // fixme- double *WORK = (double*)malloc(lwork*sizeof(double));- double *WR = (double*)malloc(n*sizeof(double));- double *WI = (double*)malloc(n*sizeof(double));- // WR and WI not really required in this call- logical *BWORK = (logical*)malloc(n*sizeof(logical));- integer res;- integer sdim;- dgees_ ("V","N",NULL,&n,sp,&n,&sdim,WR,WI,up,&n,WORK,&lwork,BWORK,&res);- //printf("%p: ",ap); for(k=0;k<n*n;k++) printf("%f ",ap[k]); printf("\n");- //printf("%p: ",up); for(k=0;k<n*n;k++) printf("%f ",up[k]); printf("\n");- //printf("%p: ",sp); for(k=0;k<n*n;k++) printf("%f ",sp[k]); printf("\n");- if(res>0) {- return NOCONVER;- }- CHECK(res,res);- free(WR);- free(WI);- free(BWORK);- free(WORK);- OK-}---/* Subroutine */ int zgees_(char *jobvs, char *sort, L_fp select, integer *n,- doublecomplex *a, integer *lda, integer *sdim, doublecomplex *w,- doublecomplex *vs, integer *ldvs, doublecomplex *work, integer *lwork,- doublereal *rwork, logical *bwork, integer *info);--int schur_l_C(KCMAT(a), CMAT(u), CMAT(s)) {- integer m = ar;- integer n = ac;- REQUIRES(m>=1 && n==m && ur==n && uc==n && sr==n && sc==n, BAD_SIZE);- DEBUGMSG("schur_l_C");- memcpy(sp,ap,n*n*sizeof(doublecomplex));- integer lwork = 6*n; // fixme- doublecomplex *WORK = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));- doublecomplex *W = (doublecomplex*)malloc(n*sizeof(doublecomplex));- // W not really required in this call- logical *BWORK = (logical*)malloc(n*sizeof(logical));- double *RWORK = (double*)malloc(n*sizeof(double));- integer res;- integer sdim;- zgees_ ("V","N",NULL,&n,sp,&n,&sdim,W,- up,&n,- WORK,&lwork,RWORK,BWORK,&res);- if(res>0) {- return NOCONVER;- }- CHECK(res,res);- free(W);- free(BWORK);- free(WORK);- OK-}--//////////////////// LU factorization /////////////////////////--/* Subroutine */ int dgetrf_(integer *m, integer *n, doublereal *a, integer *- lda, integer *ipiv, integer *info);--int lu_l_R(KDMAT(a), DVEC(ipiv), DMAT(r)) {- integer m = ar;- integer n = ac;- integer mn = MIN(m,n);- REQUIRES(m>=1 && n >=1 && ipivn == mn, BAD_SIZE);- DEBUGMSG("lu_l_R");- integer* auxipiv = (integer*)malloc(mn*sizeof(integer));- memcpy(rp,ap,m*n*sizeof(double));- integer res;- dgetrf_ (&m,&n,rp,&m,auxipiv,&res);- if(res>0) {- res = 0; // fixme- }- CHECK(res,res);- int k;- for (k=0; k<mn; k++) {- ipivp[k] = auxipiv[k];- }- free(auxipiv);- OK-}---/* Subroutine */ int zgetrf_(integer *m, integer *n, doublecomplex *a,- integer *lda, integer *ipiv, integer *info);--int lu_l_C(KCMAT(a), DVEC(ipiv), CMAT(r)) {- integer m = ar;- integer n = ac;- integer mn = MIN(m,n);- REQUIRES(m>=1 && n >=1 && ipivn == mn, BAD_SIZE);- DEBUGMSG("lu_l_C");- integer* auxipiv = (integer*)malloc(mn*sizeof(integer));- memcpy(rp,ap,m*n*sizeof(doublecomplex));- integer res;- zgetrf_ (&m,&n,rp,&m,auxipiv,&res);- if(res>0) {- res = 0; // fixme- }- CHECK(res,res);- int k;- for (k=0; k<mn; k++) {- ipivp[k] = auxipiv[k];- }- free(auxipiv);- OK-}---//////////////////// LU substitution /////////////////////////--/* Subroutine */ int dgetrs_(char *trans, integer *n, integer *nrhs,- doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *- ldb, integer *info);--int luS_l_R(KDMAT(a), KDVEC(ipiv), KDMAT(b), DMAT(x)) {- integer m = ar;- integer n = ac;- integer mrhs = br;- integer nrhs = bc;-- REQUIRES(m==n && m==mrhs && m==ipivn,BAD_SIZE);- integer* auxipiv = (integer*)malloc(n*sizeof(integer));- int k;- for (k=0; k<n; k++) {- auxipiv[k] = (integer)ipivp[k];- }- integer res;- memcpy(xp,bp,mrhs*nrhs*sizeof(double));- dgetrs_ ("N",&n,&nrhs,(/*no const (!?)*/ double*)ap,&m,auxipiv,xp,&mrhs,&res);- CHECK(res,res);- free(auxipiv);- OK-}---/* Subroutine */ int zgetrs_(char *trans, integer *n, integer *nrhs,- doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b,- integer *ldb, integer *info);--int luS_l_C(KCMAT(a), KDVEC(ipiv), KCMAT(b), CMAT(x)) {- integer m = ar;- integer n = ac;- integer mrhs = br;- integer nrhs = bc;-- REQUIRES(m==n && m==mrhs && m==ipivn,BAD_SIZE);- integer* auxipiv = (integer*)malloc(n*sizeof(integer));- int k;- for (k=0; k<n; k++) {- auxipiv[k] = (integer)ipivp[k];- }- integer res;- memcpy(xp,bp,mrhs*nrhs*sizeof(doublecomplex));- zgetrs_ ("N",&n,&nrhs,(doublecomplex*)ap,&m,auxipiv,xp,&mrhs,&res);- CHECK(res,res);- free(auxipiv);- OK-}--//////////////////// Matrix Product /////////////////////////--void dgemm_(char *, char *, integer *, integer *, integer *,- double *, const double *, integer *, const double *,- integer *, double *, double *, integer *);--int multiplyR(int ta, int tb, KDMAT(a),KDMAT(b),DMAT(r)) {- //REQUIRES(ac==br && ar==rr && bc==rc,BAD_SIZE);- DEBUGMSG("dgemm_");- CHECKNANR(a,"NaN multR Input\n")- CHECKNANR(b,"NaN multR Input\n")- integer m = ta?ac:ar;- integer n = tb?br:bc;- integer k = ta?ar:ac;- integer lda = ar;- integer ldb = br;- integer ldc = rr;- double alpha = 1;- double beta = 0;- dgemm_(ta?"T":"N",tb?"T":"N",&m,&n,&k,&alpha,ap,&lda,bp,&ldb,&beta,rp,&ldc);- CHECKNANR(r,"NaN multR Output\n")- OK-}--void zgemm_(char *, char *, integer *, integer *, integer *,- doublecomplex *, const doublecomplex *, integer *, const doublecomplex *,- integer *, doublecomplex *, doublecomplex *, integer *);--int multiplyC(int ta, int tb, KCMAT(a),KCMAT(b),CMAT(r)) {- //REQUIRES(ac==br && ar==rr && bc==rc,BAD_SIZE);- DEBUGMSG("zgemm_");- CHECKNANC(a,"NaN multC Input\n")- CHECKNANC(b,"NaN multC Input\n")- integer m = ta?ac:ar;- integer n = tb?br:bc;- integer k = ta?ar:ac;- integer lda = ar;- integer ldb = br;- integer ldc = rr;- doublecomplex alpha = {1,0};- doublecomplex beta = {0,0};- zgemm_(ta?"T":"N",tb?"T":"N",&m,&n,&k,&alpha,- ap,&lda,- bp,&ldb,&beta,- rp,&ldc);- CHECKNANC(r,"NaN multC Output\n")- OK-}--void sgemm_(char *, char *, integer *, integer *, integer *,- float *, const float *, integer *, const float *,- integer *, float *, float *, integer *);--int multiplyF(int ta, int tb, KFMAT(a),KFMAT(b),FMAT(r)) {- //REQUIRES(ac==br && ar==rr && bc==rc,BAD_SIZE);- DEBUGMSG("sgemm_");- integer m = ta?ac:ar;- integer n = tb?br:bc;- integer k = ta?ar:ac;- integer lda = ar;- integer ldb = br;- integer ldc = rr;- float alpha = 1;- float beta = 0;- sgemm_(ta?"T":"N",tb?"T":"N",&m,&n,&k,&alpha,ap,&lda,bp,&ldb,&beta,rp,&ldc);- OK-}--void cgemm_(char *, char *, integer *, integer *, integer *,- complex *, const complex *, integer *, const complex *,- integer *, complex *, complex *, integer *);--int multiplyQ(int ta, int tb, KQMAT(a),KQMAT(b),QMAT(r)) {- //REQUIRES(ac==br && ar==rr && bc==rc,BAD_SIZE);- DEBUGMSG("cgemm_");- integer m = ta?ac:ar;- integer n = tb?br:bc;- integer k = ta?ar:ac;- integer lda = ar;- integer ldb = br;- integer ldc = rr;- complex alpha = {1,0};- complex beta = {0,0};- cgemm_(ta?"T":"N",tb?"T":"N",&m,&n,&k,&alpha,- ap,&lda,- bp,&ldb,&beta,- rp,&ldc);- OK-}--//////////////////// transpose /////////////////////////--int transF(KFMAT(x),FMAT(t)) {- REQUIRES(xr==tc && xc==tr,BAD_SIZE);- DEBUGMSG("transF");- int i,j;- for (i=0; i<tr; i++) {- for (j=0; j<tc; j++) {- tp[i*tc+j] = xp[j*xc+i];- }- }- OK-}--int transR(KDMAT(x),DMAT(t)) {- REQUIRES(xr==tc && xc==tr,BAD_SIZE);- DEBUGMSG("transR");- int i,j;- for (i=0; i<tr; i++) {- for (j=0; j<tc; j++) {- tp[i*tc+j] = xp[j*xc+i];- }- }- OK-}--int transQ(KQMAT(x),QMAT(t)) {- REQUIRES(xr==tc && xc==tr,BAD_SIZE);- DEBUGMSG("transQ");- int i,j;- for (i=0; i<tr; i++) {- for (j=0; j<tc; j++) {- tp[i*tc+j] = xp[j*xc+i];- }- }- OK-}--int transC(KCMAT(x),CMAT(t)) {- REQUIRES(xr==tc && xc==tr,BAD_SIZE);- DEBUGMSG("transC");- int i,j;- for (i=0; i<tr; i++) {- for (j=0; j<tc; j++) {- tp[i*tc+j] = xp[j*xc+i];- }- }- OK-}--int transP(KPMAT(x), PMAT(t)) {- REQUIRES(xr==tc && xc==tr,BAD_SIZE);- REQUIRES(xs==ts,NOCONVER);- DEBUGMSG("transP");- int i,j;- for (i=0; i<tr; i++) {- for (j=0; j<tc; j++) {- memcpy(tp+(i*tc+j)*xs,xp +(j*xc+i)*xs,xs);- }- }- OK-}--//////////////////// constant /////////////////////////--int constantF(float * pval, FVEC(r)) {- DEBUGMSG("constantF")- int k;- double val = *pval;- for(k=0;k<rn;k++) {- rp[k]=val;- }- OK-}--int constantR(double * pval, DVEC(r)) {- DEBUGMSG("constantR")- int k;- double val = *pval;- for(k=0;k<rn;k++) {- rp[k]=val;- }- OK-}--int constantQ(complex* pval, QVEC(r)) {- DEBUGMSG("constantQ")- int k;- complex val = *pval;- for(k=0;k<rn;k++) {- rp[k]=val;- }- OK-}--int constantC(doublecomplex* pval, CVEC(r)) {- DEBUGMSG("constantC")- int k;- doublecomplex val = *pval;- for(k=0;k<rn;k++) {- rp[k]=val;- }- OK-}--int constantP(void* pval, PVEC(r)) {- DEBUGMSG("constantP")- int k;- for(k=0;k<rn;k++) {- memcpy(rp+k*rs,pval,rs);- }- OK-}--//////////////////// float-double conversion /////////////////////////--int float2double(FVEC(x),DVEC(y)) {- DEBUGMSG("float2double")- int k;- for(k=0;k<xn;k++) {- yp[k]=xp[k];- }- OK-}--int double2float(DVEC(x),FVEC(y)) {- DEBUGMSG("double2float")- int k;- for(k=0;k<xn;k++) {- yp[k]=xp[k];- }- OK-}--//////////////////// conjugate /////////////////////////--int conjugateQ(KQVEC(x),QVEC(t)) {- REQUIRES(xn==tn,BAD_SIZE);- DEBUGMSG("conjugateQ");- int k;- for(k=0;k<xn;k++) {- tp[k].r = xp[k].r;- tp[k].i = -xp[k].i;- }- OK-}--int conjugateC(KCVEC(x),CVEC(t)) {- REQUIRES(xn==tn,BAD_SIZE);- DEBUGMSG("conjugateC");- int k;- for(k=0;k<xn;k++) {- tp[k].r = xp[k].r;- tp[k].i = -xp[k].i;- }- OK-}--//////////////////// step /////////////////////////--int stepF(FVEC(x),FVEC(y)) {- DEBUGMSG("stepF")- int k;- for(k=0;k<xn;k++) {- yp[k]=xp[k]>0;- }- OK-}--int stepD(DVEC(x),DVEC(y)) {- DEBUGMSG("stepD")- int k;- for(k=0;k<xn;k++) {- yp[k]=xp[k]>0;- }- OK-}--//////////////////// cond /////////////////////////--int condF(FVEC(x),FVEC(y),FVEC(lt),FVEC(eq),FVEC(gt),FVEC(r)) {- REQUIRES(xn==yn && xn==ltn && xn==eqn && xn==gtn && xn==rn ,BAD_SIZE);- DEBUGMSG("condF")- int k;- for(k=0;k<xn;k++) {- rp[k] = xp[k]<yp[k]?ltp[k]:(xp[k]>yp[k]?gtp[k]:eqp[k]);- }- OK-}--int condD(DVEC(x),DVEC(y),DVEC(lt),DVEC(eq),DVEC(gt),DVEC(r)) {- REQUIRES(xn==yn && xn==ltn && xn==eqn && xn==gtn && xn==rn ,BAD_SIZE);- DEBUGMSG("condD")- int k;- for(k=0;k<xn;k++) {- rp[k] = xp[k]<yp[k]?ltp[k]:(xp[k]>yp[k]?gtp[k]:eqp[k]);- }- OK-}-
@@ -1,60 +0,0 @@-/*- * We have copied the definitions in f2c.h required- * to compile clapack.h, modified to support both- * 32 and 64 bit-- http://opengrok.creo.hu/dragonfly/xref/src/contrib/gcc-3.4/libf2c/readme.netlib- http://www.ibm.com/developerworks/library/l-port64.html- */--#ifdef _LP64-typedef int integer;-typedef unsigned int uinteger;-typedef int logical;-typedef long longint; /* system-dependent */-typedef unsigned long ulongint; /* system-dependent */-#else-typedef long int integer;-typedef unsigned long int uinteger;-typedef long int logical;-typedef long long longint; /* system-dependent */-typedef unsigned long long ulongint; /* system-dependent */-#endif--typedef char *address;-typedef short int shortint;-typedef float real;-typedef double doublereal;-typedef struct { real r, i; } complex;-typedef struct { doublereal r, i; } doublecomplex;-typedef short int shortlogical;-typedef char logical1;-typedef char integer1;--typedef logical (*L_fp)();-typedef short ftnlen;--/********************************************************/--#define FVEC(A) int A##n, float*A##p-#define DVEC(A) int A##n, double*A##p-#define QVEC(A) int A##n, complex*A##p-#define CVEC(A) int A##n, doublecomplex*A##p-#define PVEC(A) int A##n, void* A##p, int A##s-#define FMAT(A) int A##r, int A##c, float* A##p-#define DMAT(A) int A##r, int A##c, double* A##p-#define QMAT(A) int A##r, int A##c, complex* A##p-#define CMAT(A) int A##r, int A##c, doublecomplex* A##p-#define PMAT(A) int A##r, int A##c, void* A##p, int A##s--#define KFVEC(A) int A##n, const float*A##p-#define KDVEC(A) int A##n, const double*A##p-#define KQVEC(A) int A##n, const complex*A##p-#define KCVEC(A) int A##n, const doublecomplex*A##p-#define KPVEC(A) int A##n, const void* A##p, int A##s-#define KFMAT(A) int A##r, int A##c, const float* A##p-#define KDMAT(A) int A##r, int A##c, const double* A##p-#define KQMAT(A) int A##r, int A##c, const complex* A##p-#define KCMAT(A) int A##r, int A##c, const doublecomplex* A##p-#define KPMAT(A) int A##r, int A##c, const void* A##p, int A##s-
@@ -1,233 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-------------------------------------------------------------------------------{- |-Module : Numeric.LinearAlgebra.Util-Copyright : (c) Alberto Ruiz 2013-License : GPL--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional---}--------------------------------------------------------------------------------module Numeric.LinearAlgebra.Util(- - -- * Convenience functions- size, disp,- zeros, ones,- diagl,- row,- col,- (&),(!), (¦), (#),- (?),(¿),- rand, randn,- cross,- norm,- unitary,- mt,- pairwiseD2,- rowOuters,- null1,- null1sym,- -- * Convolution- -- ** 1D- corr, conv, corrMin,- -- ** 2D- corr2, conv2, separable,- -- * Tools for the Kronecker product- --- -- | (see A. Fusiello, A matter of notation: Several uses of the Kronecker product in- -- 3d computer vision, Pattern Recognition Letters 28 (15) (2007) 2127-2132)-- --- -- | @`vec` (a \<> x \<> b) == ('trans' b ` 'kronecker' ` a) \<> 'vec' x@- vec,- vech,- dup,- vtrans-) where--import Numeric.Container-import Numeric.LinearAlgebra.Algorithms hiding (i)-import Numeric.Matrix()-import Numeric.Vector()--import System.Random(randomIO)-import Numeric.LinearAlgebra.Util.Convolution---disp :: Int -> Matrix Double -> IO ()--- ^ show a matrix with given number of digits after the decimal point-disp n = putStrLn . dispf n---- | pseudorandom matrix with uniform elements between 0 and 1-randm :: RandDist- -> Int -- ^ rows- -> Int -- ^ columns- -> IO (Matrix Double)-randm d r c = do- seed <- randomIO- return (reshape c $ randomVector seed d (r*c))---- | pseudorandom matrix with uniform elements between 0 and 1-rand :: Int -> Int -> IO (Matrix Double)-rand = randm Uniform---- | pseudorandom matrix with normal elements-randn :: Int -> Int -> IO (Matrix Double)-randn = randm Gaussian---- | create a real diagonal matrix from a list-diagl :: [Double] -> Matrix Double-diagl = diag . fromList---- | a real matrix of zeros-zeros :: Int -- ^ rows- -> Int -- ^ columns- -> Matrix Double-zeros r c = konst 0 (r,c)---- | a real matrix of ones-ones :: Int -- ^ rows- -> Int -- ^ columns- -> Matrix Double-ones r c = konst 1 (r,c)---- | concatenation of real vectors-infixl 3 &-(&) :: Vector Double -> Vector Double -> Vector Double-a & b = join [a,b]---- | horizontal concatenation of real matrices-infixl 3 !-(!) :: Matrix Double -> Matrix Double -> Matrix Double-a ! b = fromBlocks [[a,b]]---- | (00A6) horizontal concatenation of real matrices-infixl 3 ¦-(¦) :: Matrix Double -> Matrix Double -> Matrix Double-a ¦ b = fromBlocks [[a,b]]---- | vertical concatenation of real matrices-(#) :: Matrix Double -> Matrix Double -> Matrix Double-infixl 2 #-a # b = fromBlocks [[a],[b]]---- | create a single row real matrix from a list-row :: [Double] -> Matrix Double-row = asRow . fromList---- | create a single column real matrix from a list-col :: [Double] -> Matrix Double-col = asColumn . fromList---- | extract selected rows-infixl 9 ?-(?) :: Element t => Matrix t -> [Int] -> Matrix t-(?) = flip extractRows---- | (00BF) extract selected columns-infixl 9 ¿-(¿) :: Element t => Matrix t -> [Int] -> Matrix t-m ¿ ks = trans . extractRows ks . trans $ m---cross :: Vector Double -> Vector Double -> Vector Double--- ^ cross product (for three-element real vectors)-cross x y | dim x == 3 && dim y == 3 = fromList [z1,z2,z3]- | otherwise = error $ "cross ("++show x++") ("++show y++")"- where- [x1,x2,x3] = toList x- [y1,y2,y3] = toList y- z1 = x2*y3-x3*y2- z2 = x3*y1-x1*y3- z3 = x1*y2-x2*y1--norm :: Vector Double -> Double--- ^ 2-norm of real vector-norm = pnorm PNorm2----- | Obtains a vector in the same direction with 2-norm=1-unitary :: Vector Double -> Vector Double-unitary v = v / scalar (norm v)---- | (rows &&& cols)-size :: Matrix t -> (Int, Int)-size m = (rows m, cols m)---- | trans . inv-mt :: Matrix Double -> Matrix Double-mt = trans . inv---------------------------------------------------------------------------- | Matrix of pairwise squared distances of row vectors--- (using the matrix product trick in blog.smola.org)-pairwiseD2 :: Matrix Double -> Matrix Double -> Matrix Double-pairwiseD2 x y | ok = x2 `outer` oy + ox `outer` y2 - 2* x <> trans y- | otherwise = error $ "pairwiseD2 with different number of columns: "- ++ show (size x) ++ ", " ++ show (size y)- where- ox = one (rows x)- oy = one (rows y)- oc = one (cols x)- one k = constant 1 k- x2 = x * x <> oc- y2 = y * y <> oc- ok = cols x == cols y-------------------------------------------------------------------------------------- | outer products of rows-rowOuters :: Matrix Double -> Matrix Double -> Matrix Double-rowOuters a b = a' * b'- where- a' = kronecker a (ones 1 (cols b))- b' = kronecker (ones 1 (cols a)) b-------------------------------------------------------------------------------------- | solution of overconstrained homogeneous linear system-null1 :: Matrix Double -> Vector Double-null1 = last . toColumns . snd . rightSV---- | solution of overconstrained homogeneous symmetric linear system-null1sym :: Matrix Double -> Vector Double-null1sym = last . toColumns . snd . eigSH'------------------------------------------------------------------------------------vec :: Element t => Matrix t -> Vector t--- ^ stacking of columns-vec = flatten . trans---vech :: Element t => Matrix t -> Vector t--- ^ half-vectorization (of the lower triangular part)-vech m = join . zipWith f [0..] . toColumns $ m- where- f k v = subVector k (dim v - k) v---dup :: (Num t, Num (Vector t), Element t) => Int -> Matrix t--- ^ duplication matrix (@'dup' k \<> 'vech' m == 'vec' m@, for symmetric m of 'dim' k)-dup k = trans $ fromRows $ map f es- where- rs = zip [0..] (toRows (ident (k^(2::Int))))- es = [(i,j) | j <- [0..k-1], i <- [0..k-1], i>=j ]- f (i,j) | i == j = g (k*j + i)- | otherwise = g (k*j + i) + g (k*i + j)- g j = v- where- Just v = lookup j rs---vtrans :: Element t => Int -> Matrix t -> Matrix t--- ^ generalized \"vector\" transposition: @'vtrans' 1 == 'trans'@, and @'vtrans' ('rows' m) m == 'asColumn' ('vec' m)@-vtrans p m | r == 0 = fromBlocks . map (map asColumn . takesV (replicate q p)) . toColumns $ m- | otherwise = error $ "vtrans " ++ show p ++ " of matrix with " ++ show (rows m) ++ " rows"- where- (q,r) = divMod (rows m) p-
@@ -1,114 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-------------------------------------------------------------------------------{- |-Module : Numeric.LinearAlgebra.Util.Convolution-Copyright : (c) Alberto Ruiz 2012-License : GPL--Maintainer : Alberto Ruiz (aruiz at um dot es)-Stability : provisional---}--------------------------------------------------------------------------------module Numeric.LinearAlgebra.Util.Convolution(- corr, conv, corrMin,- corr2, conv2, separable-) where--import Numeric.LinearAlgebra---vectSS :: Element t => Int -> Vector t -> Matrix t-vectSS n v = fromRows [ subVector k n v | k <- [0 .. dim v - n] ]---corr :: Product t => Vector t -- ^ kernel- -> Vector t -- ^ source- -> Vector t-{- ^ correlation-->>> corr (fromList[1,2,3]) (fromList [1..10])-fromList [14.0,20.0,26.0,32.0,38.0,44.0,50.0,56.0]---}-corr ker v | dim ker <= dim v = vectSS (dim ker) v <> ker- | otherwise = error $ "corr: dim kernel ("++show (dim ker)++") > dim vector ("++show (dim v)++")"---conv :: (Product t, Num t) => Vector t -> Vector t -> Vector t-{- ^ convolution ('corr' with reversed kernel and padded input, equivalent to polynomial product)-->>> conv (fromList[1,1]) (fromList [-1,1])-fromList [-1.0,0.0,1.0]---}-conv ker v = corr ker' v'- where- ker' = (flatten.fliprl.asRow) ker- v' | dim ker > 1 = join [z,v,z]- | otherwise = v- z = constant 0 (dim ker -1)--corrMin :: (Container Vector t, RealElement t, Product t)- => Vector t- -> Vector t- -> Vector t--- ^ similar to 'corr', using 'min' instead of (*)-corrMin ker v = minEvery ss (asRow ker) <> ones- where- minEvery a b = cond a b a a b- ss = vectSS (dim ker) v- ones = konst' 1 (dim ker)----matSS :: Element t => Int -> Matrix t -> [Matrix t]-matSS dr m = map (reshape c) [ subVector (k*c) n v | k <- [0 .. r - dr] ]- where- v = flatten m- c = cols m- r = rows m- n = dr*c---corr2 :: Product a => Matrix a -> Matrix a -> Matrix a--- ^ 2D correlation-corr2 ker mat = dims- . concatMap (map ((<.> ker') . flatten) . matSS c . trans)- . matSS r $ mat- where- r = rows ker- c = cols ker- ker' = flatten (trans ker)- rr = rows mat - r + 1- rc = cols mat - c + 1- dims | rr > 0 && rc > 0 = (rr >< rc)- | otherwise = error $ "corr2: dim kernel ("++sz ker++") > dim matrix ("++sz mat++")"- sz m = show (rows m)++"x"++show (cols m)--conv2 :: (Num a, Product a) => Matrix a -> Matrix a -> Matrix a--- ^ 2D convolution-conv2 k m = corr2 (fliprl . flipud $ k) pm- where- pm | r == 0 && c == 0 = m- | r == 0 = fromBlocks [[z3,m,z3]]- | c == 0 = fromBlocks [[z2],[m],[z2]]- | otherwise = fromBlocks [[z1,z2,z1]- ,[z3, m,z3]- ,[z1,z2,z1]]- r = rows k - 1- c = cols k - 1- h = rows m- w = cols m- z1 = konst' 0 (r,c)- z2 = konst' 0 (r,w)- z3 = konst' 0 (h,c)---- TODO: could be simplified using future empty arrays---separable :: Element t => (Vector t -> Vector t) -> Matrix t -> Matrix t--- ^ matrix computation implemented as separated vector operations by rows and columns.-separable f = fromColumns . map f . toColumns . fromRows . map f . toRows-
@@ -1,71 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}---------------------------------------------------------------------------------- |--- Module : Numeric.Matrix--- Copyright : (c) Alberto Ruiz 2010--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Provides instances of standard classes 'Show', 'Read', 'Eq',--- 'Num', 'Fractional', and 'Floating' for 'Matrix'.------ In arithmetic operations one-component--- vectors and matrices automatically expand to match the dimensions of the other operand.---------------------------------------------------------------------------------module Numeric.Matrix (- ) where-----------------------------------------------------------------------import Numeric.Container-----------------------------------------------------------------------instance Container Matrix a => Eq (Matrix a) where- (==) = equal--instance (Container Matrix a, Num (Vector a)) => Num (Matrix a) where- (+) = liftMatrix2Auto (+)- (-) = liftMatrix2Auto (-)- negate = liftMatrix negate- (*) = liftMatrix2Auto (*)- signum = liftMatrix signum- abs = liftMatrix abs- fromInteger = (1><1) . return . fromInteger-------------------------------------------------------instance (Container Vector a, Fractional (Vector a), Num (Matrix a)) => Fractional (Matrix a) where- fromRational n = (1><1) [fromRational n]- (/) = liftMatrix2Auto (/)-------------------------------------------------------------instance (Floating a, Container Vector a, Floating (Vector a), Fractional (Matrix a)) => Floating (Matrix a) where- sin = liftMatrix sin- cos = liftMatrix cos- tan = liftMatrix tan- asin = liftMatrix asin- acos = liftMatrix acos- atan = liftMatrix atan- sinh = liftMatrix sinh- cosh = liftMatrix cosh- tanh = liftMatrix tanh- asinh = liftMatrix asinh- acosh = liftMatrix acosh- atanh = liftMatrix atanh- exp = liftMatrix exp- log = liftMatrix log- (**) = liftMatrix2Auto (**)- sqrt = liftMatrix sqrt- pi = (1><1) [pi]
@@ -1,158 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Numeric.Vector--- Copyright : (c) Alberto Ruiz 2011--- License : GPL-style------ Maintainer : Alberto Ruiz <aruiz@um.es>--- Stability : provisional--- Portability : portable------ Provides instances of standard classes 'Show', 'Read', 'Eq',--- 'Num', 'Fractional', and 'Floating' for 'Vector'.--- --------------------------------------------------------------------------------module Numeric.Vector () where--import Numeric.GSL.Vector-import Numeric.Container-----------------------------------------------------------------------adaptScalar f1 f2 f3 x y- | dim x == 1 = f1 (x@>0) y- | dim y == 1 = f3 x (y@>0)- | otherwise = f2 x y----------------------------------------------------------------------instance Num (Vector Float) where- (+) = adaptScalar addConstant add (flip addConstant)- negate = scale (-1)- (*) = adaptScalar scale mul (flip scale)- signum = vectorMapF Sign- abs = vectorMapF Abs- fromInteger = fromList . return . fromInteger--instance Num (Vector Double) where- (+) = adaptScalar addConstant add (flip addConstant)- negate = scale (-1)- (*) = adaptScalar scale mul (flip scale)- signum = vectorMapR Sign- abs = vectorMapR Abs- fromInteger = fromList . return . fromInteger--instance Num (Vector (Complex Double)) where- (+) = adaptScalar addConstant add (flip addConstant)- negate = scale (-1)- (*) = adaptScalar scale mul (flip scale)- signum = vectorMapC Sign- abs = vectorMapC Abs- fromInteger = fromList . return . fromInteger--instance Num (Vector (Complex Float)) where- (+) = adaptScalar addConstant add (flip addConstant)- negate = scale (-1)- (*) = adaptScalar scale mul (flip scale)- signum = vectorMapQ Sign- abs = vectorMapQ Abs- fromInteger = fromList . return . fromInteger-------------------------------------------------------instance (Container Vector a, Num (Vector a)) => Fractional (Vector a) where- fromRational n = fromList [fromRational n]- (/) = adaptScalar f divide g where- r `f` v = scaleRecip r v- v `g` r = scale (recip r) v-----------------------------------------------------------instance Floating (Vector Float) where- sin = vectorMapF Sin- cos = vectorMapF Cos- tan = vectorMapF Tan- asin = vectorMapF ASin- acos = vectorMapF ACos- atan = vectorMapF ATan- sinh = vectorMapF Sinh- cosh = vectorMapF Cosh- tanh = vectorMapF Tanh- asinh = vectorMapF ASinh- acosh = vectorMapF ACosh- atanh = vectorMapF ATanh- exp = vectorMapF Exp- log = vectorMapF Log- sqrt = vectorMapF Sqrt- (**) = adaptScalar (vectorMapValF PowSV) (vectorZipF Pow) (flip (vectorMapValF PowVS))- pi = fromList [pi]-----------------------------------------------------------------instance Floating (Vector Double) where- sin = vectorMapR Sin- cos = vectorMapR Cos- tan = vectorMapR Tan- asin = vectorMapR ASin- acos = vectorMapR ACos- atan = vectorMapR ATan- sinh = vectorMapR Sinh- cosh = vectorMapR Cosh- tanh = vectorMapR Tanh- asinh = vectorMapR ASinh- acosh = vectorMapR ACosh- atanh = vectorMapR ATanh- exp = vectorMapR Exp- log = vectorMapR Log- sqrt = vectorMapR Sqrt- (**) = adaptScalar (vectorMapValR PowSV) (vectorZipR Pow) (flip (vectorMapValR PowVS))- pi = fromList [pi]-----------------------------------------------------------------instance Floating (Vector (Complex Double)) where- sin = vectorMapC Sin- cos = vectorMapC Cos- tan = vectorMapC Tan- asin = vectorMapC ASin- acos = vectorMapC ACos- atan = vectorMapC ATan- sinh = vectorMapC Sinh- cosh = vectorMapC Cosh- tanh = vectorMapC Tanh- asinh = vectorMapC ASinh- acosh = vectorMapC ACosh- atanh = vectorMapC ATanh- exp = vectorMapC Exp- log = vectorMapC Log- sqrt = vectorMapC Sqrt- (**) = adaptScalar (vectorMapValC PowSV) (vectorZipC Pow) (flip (vectorMapValC PowVS))- pi = fromList [pi]---------------------------------------------------------------instance Floating (Vector (Complex Float)) where- sin = vectorMapQ Sin- cos = vectorMapQ Cos- tan = vectorMapQ Tan- asin = vectorMapQ ASin- acos = vectorMapQ ACos- atan = vectorMapQ ATan- sinh = vectorMapQ Sinh- cosh = vectorMapQ Cosh- tanh = vectorMapQ Tanh- asinh = vectorMapQ ASinh- acosh = vectorMapQ ACosh- atanh = vectorMapQ ATanh- exp = vectorMapQ Exp- log = vectorMapQ Log- sqrt = vectorMapQ Sqrt- (**) = adaptScalar (vectorMapValQ PowSV) (vectorZipQ Pow) (flip (vectorMapValQ PowVS))- pi = fromList [pi]-
@@ -1,95 +0,0 @@-module MiniPosix where- -import Data.Set-import System.Posix.Types-import System.Posix.Files-import System.Posix.IO hiding (openFd, fdRead, fdWrite, createFile)-import System.FilePath ((</>))---data World = W-{-@ data FIO a <pre :: World -> Prop, post :: World -> a -> World -> Prop> - = FIO (rs :: (x:World<pre> -> (a, World)<\y -> {v:World<post x y> | true}>)) @-}-{-@ runState :: forall <pre :: World -> Prop, post :: World -> a -> World -> Prop>. - FIO <pre, post> a -> x:World<pre> -> (a, World)<\w -> {v:World<post x w> | true}> @-}-data FIO a = FIO {runState :: World -> (a, World)}--data Capability = C CapabilityT Privilege-data CapabilityT = File | Directory-data Privilege = Read | Write | Lookup | Create | CreateRestr [Privilege]- -{-@ measure sel :: World -> Fd -> Set Capability @-}-{-@ measure upd :: World -> Fd -> Set Capability -> World @-}-{-@ measure fd :: FilePath -> Fd @-}-{-@ measure parent :: Fd -> Fd @-}--{-@ predicate HasPriv W T P F = Set_mem (C T P) (sel W F) @-}-{-@ predicate Rd W F = HasPriv W File Read (fd F) @-}-{-@ predicate Cr W F = HasPriv W Directory Create (fd F) @-}-{-@ predicate RdFD W F = HasPriv W File Read F @-}-{-@ predicate CrFD W F = HasPriv W Directory Create F @-}-{-@ predicate Wr W F = HasPriv W File Write (fd F) @-}-{-@ predicate Lst W F = HasPriv W File Lookup (fd F) @-}--{- ******************** API **************************** -}-instance Monad FIO where-{-@ instance Monad FIO where- >>= :: forall < pre :: World -> Prop - , pre2 :: World -> Prop - , p :: a -> Prop- , post1 :: World -> a -> World -> Prop- , post2 :: World -> b -> World -> Prop- , post :: World -> b -> World -> Prop>.- {w:World<pre> -> x:a -> World<post1 w x> -> World<pre2>} - {w:World<pre> -> y:a -> w2:World<post1 w y> -> x:b -> World<post2 w2 x> -> World<post w x>} - {w:World -> x:a -> w2:World<post1 w x> -> {v:a | v = x} -> a<p>}- FIO <pre, post1> a- -> (a<p> -> FIO <pre2, post2> b)- -> FIO <pre, post> b ;- >> :: forall < pre :: World -> Prop - , pre2 :: World -> Prop - , p :: a -> Prop- , post1 :: World -> a -> World -> Prop- , post2 :: World -> b -> World -> Prop- , post :: World -> b -> World -> Prop>.- {w:World<pre> -> x:a -> World<post1 w x> -> World<pre2>} - {w:World<pre> -> y:a -> w2:World<post1 w y> -> x:b -> World<post2 w2 x> -> World<post w x>} - FIO <pre, post1> a- -> FIO <pre2, post2> b- -> FIO <pre, post> b ;- return :: forall <p :: World -> Prop>.- x:a -> FIO <p, \w0 y -> {w1:World<p> | w0 == w1 && y == x }> a- @-} - (FIO g) >>= f = FIO $ \x -> case g x of {(y, s) -> (runState (f y)) s} - (FIO g) >> f = FIO $ \x -> case g x of {(y, s) -> (runState f ) s} - return w = FIO $ \x -> (w, x)- -{-@ openFd :: f:FilePath -> _ -> _ -> _ ->- FIO <{\w -> HasPriv w File Read (fd f)},{\w1 x w2 -> (w1 == w2)}> {v:Fd | v = fd f} @-}-openFd :: FilePath -> OpenMode -> Maybe FileMode -> OpenFileFlags -> FIO Fd-openFd = undefined- -{-@ fdRead :: f:Fd -> _ -> - FIO<{\w -> HasPriv w File Read f},{\w1 x w2 -> (w1 == w2)}> (String, ByteCount) @-}-fdRead :: Fd -> ByteCount -> FIO (String, ByteCount)-fdRead = undefined--{-@ fdWrite :: f:Fd -> _ -> - FIO<{\w -> HasPriv w File Write f},{\w1 x w2 -> (w1 == w2)}> ByteCount @-}-fdWrite :: Fd -> String -> FIO ByteCount-fdWrite = undefined- -{-@ createFile :: f:FilePath -> _ ->- FIO<{\w -> CrFD w (parent (fd f))},- {\w1 x w2 -> (x = fd f) && (w2 = upd w1 x (sel w1 (parent (fd f))))}> {v:Fd | v = fd f } @-}-createFile :: FilePath -> FileMode -> FIO Fd-createFile = undefined- -{-@ assume (</>) :: p:{v:FilePath | true } -> c:FilePath -> {v:FilePath | parent (fd v) = (fd p)} @-}-{- ***************************************************** -}--{-@ createTest :: p:FilePath ->- FIO<{\w -> RdFD w (parent (fd p)) && CrFD w (parent (fd p)) },- \w x -> {v:World | RdFD v x }> Fd @-}-createTest :: FilePath -> FIO Fd-createTest p = createFile p ownerWriteMode
@@ -1,63 +0,0 @@-module Compose where--{-@-cmp :: forall < p :: b -> c -> Bool- , q :: a -> b -> Bool- , r :: a -> c -> Bool- >.- {x::a, w::b<q x> |- c<p w> <: c<r x>}- f:(y:b -> c<p y>)- -> g:(z:a -> b<q z>)- -> x:a -> c<r x>-@-}--cmp :: (b -> c)- -> (a -> b)- -> a -> c--cmp f g x = f (g x)----{-@ incr :: x:Nat -> {v:Nat | v == x + 1} @-}-incr :: Int -> Int-incr x = x + 1---{-@ incr2 :: x:Nat -> {v:Nat | v = x + 2} @-}-incr2 :: Int -> Int-incr2 = incr `cmp` incr--{-@ incr2' :: x:Nat -> {v:Nat | v = x + 2} @-}-incr2' :: Int -> Int-incr2' = incr `cmp` incr--{-@ plusminus :: n:Nat -> m:Nat -> x:{Nat | x <= m} -> {v:Nat | v < (m - x) + n} @-}-plusminus :: Int -> Int -> Int -> Int-plusminus n m = (n+) `cmp` (m-)---{-@ plus :: n:a -> x:a -> {v:a | v = (x + n)} @-}-plus :: Num a => a -> a -> a-plus = undefined-minus :: Num a => a -> a -> a-{-@ minus :: n:a -> x:a -> {v:a | v = x - n} @-}-minus _ _ = undefined--{-@ plus1 :: x:Nat -> {v:Nat | v == x + 20} @-}-plus1 :: Int -> Int-plus1 x = x + 20--{-@ plus2 :: x:{v:Nat | v > 10} -> {v:Nat | v == x + 2} @-}-plus2 :: Int -> Int-plus2 x = x + 2--{-@ plus42 :: x:Nat -> {v:Nat | v == x + 42} @-}-plus42 :: Int -> Int-plus42 = cmp plus2 plus1----{-@ qualif PLUSMINUS(v:int, x:int, y:int, z:int): (v = (x - y) + z) @-}-{-@ qualif PLUS (v:int, x:int, y:int) : (v = x + y) @-}-{-@ qualif MINUS (v:int, x:int, y:int) : (v = x - y) @-}
@@ -1,159 +0,0 @@-{-@ LIQUID "--pruneunsorted" @-}--module MovieClient where--import DataBase-import GHC.CString -- This import interprets Strings as constants!-import Data.Maybe (catMaybes)-import Prelude hiding (product, elem)-import Control.Applicative ((<$>))-import qualified Data.Set as S--type Tag = String--data Value = I Int | S Name- deriving (Show, Eq)--data Name = ChickenPlums | TalkToHer | Persepolis | FunnyGames- | Paronnaud | Almadovar | Haneke- deriving (Show, Eq)--{-@ type Movies = [MovieScheme] @-}-{-@ type MovieScheme = {v:Dict <{\t val -> MovieRange t val}> Tag Value | ValidMovieScheme v} @-}-{-@ type Directors = [DirectorScheme] @-}-{-@ type DirectorScheme = {v:Dict <{\t val -> DirectorRange t val}> Tag Value | ValidDirectorScheme v} @-}-{-@ type Stars = [StarScheme] @-}-{-@ type StarScheme = {v:Dict <{\t val -> StarRange t val}> Tag Value | ValidStarScheme v} @-}-{-@ type Titles = [TitleScheme] @-}-{-@ type TitleScheme = {v:Dict <{\t val -> TitleRange t val}> Tag Value | ValidTitleScheme v} @-}-{-@ type DirStars = [DirStarScheme] @-}-{-@ type DirStarScheme = {v:Dict <{\t val -> DirStarRange t val}> Tag Value | ValidDirStarScheme v} @-}---{-@ predicate ValidMovieScheme V =- ((listElts (ddom V) ~~ Set_cup (Set_sng "year")- (Set_cup (Set_sng "star")- (Set_cup (Set_sng "director")- (Set_sng "title"))))) @-}--{-@ predicate MovieRange T V = (T ~~ "year" => ValidYear V)- && (T ~~ "star" => ValidStar V)- && (T ~~ "director" => ValidDirector V)- && (T ~~ "title" => ValidTitle V) @-}--{-@ predicate ValidDirectorScheme V = (listElts (ddom V) ~~ (Set_sng "director")) @-}-{-@ predicate DirectorRange T V = (T ~~ "director" => ValidDirector V) @-}--{-@ predicate ValidStarScheme V = (listElts (ddom V) ~~ (Set_sng "star")) @-}-{-@ predicate StarRange T V = (T ~~ "star" => ValidStar V) @-}--{-@ predicate ValidTitleScheme V = (listElts (ddom V) ~~ (Set_sng "title")) @-}-{-@ predicate TitleDomain T = (T ~~ "title") @-}-{-@ predicate TitleRange T V = (T ~~ "title" => ValidTitle V) @-}--{-@ predicate ValidDirStarScheme V = (listElts (ddom V) ~~ Set_cup (Set_sng "director") (Set_sng "star")) @-}-{-@ predicate DirStarDomain T = (T ~~ "director" || T ~~ "star") @-}-{-@ predicate DirStarRange T V = (T ~~ "director" => ValidDirector V) && (T ~~ "star" => ValidStar V) @-}---{-@ predicate ValidYear V = isInt V && 1889 <= toInt V @-}-{-@ predicate ValidStar V = isInt V && 0 <= toInt V && toInt V <= 10 @-}-{-@ predicate ValidDirector V = isString V @-}-{-@ predicate ValidTitle V = isString V @-}-----type Movies = Table Tag Value-type Titles = Table Tag Value-type Directors = Table Tag Value-type Stars = Table Tag Value-type DirStars = Table Tag Value--type MovieScheme = Dict Tag Value--movies :: Movies-{-@ movies :: Movies @-}-movies = fromList [movie1, movie2, movie3, movie4]--movie1, movie2, movie3, movie4 :: MovieScheme-{-@ movie1, movie2, movie3, movie4 :: MovieScheme @-}-movie1 = mkMovie (S TalkToHer) (S Almadovar) (I 8) (I 2002)-movie2 = mkMovie (S ChickenPlums) (S Paronnaud) (I 7) (I 2011)-movie3 = mkMovie (S Persepolis) (S Paronnaud) (I 8) (I 2007)-movie4 = mkMovie (S FunnyGames) (S Haneke) (I 7) (I 2007)--mkMovie :: Value -> Value -> Value -> Value -> MovieScheme-{-@ mkMovie :: {t:Value | ValidTitle t}- -> {d:Value | ValidDirector d}- -> {s:Value | ValidStar s}- -> {y:Value | ValidYear y}- -> MovieScheme- @-}-mkMovie t d s y = ("title" := t) += ("star" := s) += ("director" := d) += ("year" := y) += empty--seen :: Titles-{-@ seen :: Titles @-}-seen = [t1, t2]- where- t1 = ("title" := S ChickenPlums) += empty- t2 = ("title" := S FunnyGames) += empty--not_seen :: Movies-not_seen = select isSeen movies- where- isSeen = undefined--- isSeen t v | t == "title" = not $ v `elem` (values "title" seen)--- isSeen _ _ = True--to_see = select isGoodMovie not_seen- where- isGoodMovie = undefined--- isGoodMovie t (I s) | t == "star" = s >= 8--- isGoodMovie t d | t == "director" = d `elem` (values "director" good_directors)--- isGoodMovie _ _ = True--directors, good_directors :: Directors-{-@ directors, good_directors :: Directors @-}-directors = project ["director"] movies---good_stars :: Stars-{-@ good_stars :: Stars @-}--- good_directors = directors `diff` project ["director"] not_good_directors--- This _IS_ unsafe!-good_directors = directors `diff` not_good_directors--not_good_directors :: DirStars-{-@ not_good_directors :: DirStars @-}--- not_good_directors = project ["director", "star"] movies `diff` product directors good_stars----- This _IS_ unsafe!-not_good_directors = project ["director", "star"] movies `diff` product directors movies--good_stars = mk_star_table (I 8) `union` mk_star_table (I 9) `union` mk_star_table (I 10)--mk_star_table :: Value -> Stars-{-@ mk_star_table :: {s:Value | ValidStar s} -> Stars @-}-mk_star_table s = [("star" := s) += empty]-------------------------------------------------------------------------------------------------- Some measures ------------------------------------------------------------------------------------------------------------------------------------{-@ measure toInt :: Value -> Int- toInt (I n) = n- @-}--{-@ measure isInt @-}-isInt :: Value -> Bool-isInt (I _) = True-isInt _ = False--{-@ measure isString @-}-isString :: Value -> Bool-isString (S _) = True-isString _ = False
@@ -1,250 +0,0 @@-{-@ LIQUID "--no-termination" @-}-{-@ LIQUID "totality" @-}--module DataBase (-- Table, Dict(..), (+=), P(..), values, empty,-- emptyTable, singleton, fromList, elem,-- union, diff, product, project, select, productD-- ) where--import qualified Data.Set as Set-import Prelude hiding (product, union, filter, elem)---- THE REST OF THIS FILE IS SAFE; just adding this to trigger an error to appease the "neg" gods.-{-@ silly_buggy_incr :: Nat -> Nat @-}-silly_buggy_incr :: Int -> Int -silly_buggy_incr x = x - 1---type Table t v = [Dict t v]--data Dict key val = D {ddom :: [key], dfun :: key -> val}--{-@ ddom :: forall <range :: key -> val -> Bool>.- x:Dict <range> key val -> {v:[key] | v = ddom x}- @-}--{-@ dfun :: forall <range :: key -> val -> Bool>.- x:Dict <range> key val- -> i:{v:key | Set_mem v (listElts (ddom x))} -> val<range i>- @-}--{-@ data Dict key val <range :: key -> val -> Bool>- = D { ddom :: [key]- , dfun :: i:{v:key | Set_mem v (listElts ddom)} -> val<range i> }- @-}---instance (Show t, Show v, Eq t) => Show (Dict t v) where- show (D ks f) = let f k = show k ++ "\t:=\t" ++ show (f k) ++ "\n"- in concatMap f ks----- LIQUID : This discards the refinement of the Dict--- for example the ddom--{-@ fromList :: forall <range :: key -> val -> Bool, p :: Dict key val -> Bool>.- x:[Dict <range> key val <<p>>] -> {v:[Dict <range> key val <<p>>] | x = v}- @-}-fromList :: [Dict key val] -> Table key val-fromList xs = xs--{-@ singleton :: forall <range :: key -> val -> Bool, p :: Dict key val -> Bool>.- Dict <range> key val <<p>> -> [Dict <range> key val <<p>>]- @-}-singleton :: Dict key val -> Table key val-singleton d = [d]---{-@ emptyTable :: forall <range :: key -> val -> Bool>.- [Dict <range> key val]- @-}-emptyTable :: Table t v-emptyTable = []--{-@ union :: forall <range :: key -> val -> Bool, p :: Dict key val -> Bool>.- x:[Dict <range> key val <<p>>]- -> y:[Dict <range> key val <<p>>]- -> {v:[Dict <range> key val <<p>>] | listElts v = Set_cup (listElts x) (listElts y)}- @-}-{-@ diff :: forall <range :: key -> val -> Bool, p :: Dict key val -> Bool>.- x:[Dict <range> key val <<p>>]- -> y:[Dict <range> key val <<p>>]- -> {v:[Dict <range> key val <<p>>] | listElts v = Set_dif (listElts x) (listElts y)}- @-}-union, diff :: (Eq key, Eq val) => Table key val -> Table key val -> Table key val-union xs ys = xs ++ ys-diff xs ys = xs \\ ys--{-@ predicate Append XS YS V =- ((listElts (ddom V)) = Set_cup (listElts (ddom YS)) (listElts (ddom XS)) )- @-}---{-@ product :: forall <range1 :: key -> val -> Bool,- range2 :: key -> val -> Bool,- range :: key -> val -> Bool,- p :: Dict key val -> Bool,- q :: Dict key val -> Bool,- r :: Dict key val -> Bool>.- {x::Dict key val <<p>>, y :: Dict key val <<q>> |- {v:Set.Set key | v = Set_cap (listElts (ddom x)) (listElts (ddom y))} <: {v:Set.Set key | Set_emp v }}- {x::Dict key val <<p>>, y :: Dict key val <<q>> |- {v:Dict key val | Append x y v} <: Dict key val <<r>>}- {x::Dict key val <<p>>, k::{v:key | Set_mem v (listElts (ddom x))} |- val<range1 k> <: val<range k> }- {x::Dict key val <<q>>, k::{v:key | Set_mem v (listElts (ddom x))} |- val<range2 k> <: val<range k> }- xs:[Dict <range1> key val <<p>>]- -> ys:[Dict <range2> key val <<q>>]- -> [Dict <range > key val <<r>>]- @-}--product :: (Eq key, Eq val) => Table key val -> Table key val -> Table key val-product xs ys = go xs ys- where- go [] _ = []- go (x:xs) [] = go xs ys- go (x:xs) (y:ys) = productD x y : go (x:xs) ys--product (x:xs) (y:ys) = [ productD x y] -- | x <- xs, y <- ys]--- product (x:xs) (y:ys) = [productD x y] -- [ productD x y | x <- xs, y <- ys]---instance (Eq key, Eq val) => Eq (Dict key val) where- (D ks1 f1) == (D ks2 f2) = all (\k -> k `elem` ks2 && f1 k == f2 k) ks1--{-@ productD :: forall <range1 :: key -> val -> Bool,- range2 :: key -> val -> Bool,- range :: key -> val -> Bool,- p :: Dict key val -> Bool,- q :: Dict key val -> Bool>.- {x::Dict key val <<p>>, y :: Dict key val <<q>> |- {v:Set.Set key | v = Set_cap (listElts (ddom x)) (listElts (ddom y))} <: {v:Set.Set key | Set_emp v }}- {x::Dict key val <<p>>, k::{v:key | Set_mem v (listElts (ddom x))} |- val<range1 k> <: val<range k> }- {x::Dict key val <<q>>, k::{v:key | Set_mem v (listElts (ddom x))}|- val<range2 k> <: val<range k> }- x:Dict <range1> key val <<p>>- -> y:Dict <range2> key val <<q>>- -> {v:Dict <range> key val | (listElts (ddom v)) = Set_cup (listElts (ddom x)) (listElts (ddom y))}- @-}--productD :: Eq key => Dict key val -> Dict key val -> Dict key val-productD (D ks1 f1) (D ks2 f2)- = let ks = ks1 ++ ks2 in- -- ORDERING IN LETS IS IMPORTANT: ks should be in scope for f- let f i = if i `elem` ks1 then f1 (ensuredomain ks1 i) else f2 (ensuredomain ks2 i) in- D ks f--{-@ project :: forall <range :: key -> val -> Bool>.- keys:[key]- -> [{v:Dict <range> key val | (Set_sub (listElts keys) (listElts (ddom v)))}]- -> [{v:Dict <range> key val | (listElts (ddom v)) = listElts keys}]- @-}-project :: Eq t => [t] -> Table t v -> Table t v-project ks [] = []-project ks (x:xs) = projectD ks x : project ks xs---{-@ projectD :: forall <range :: key -> val -> Bool>.- keys:[key]- -> {v:Dict <range> key val | (Set_sub (listElts keys) (listElts (ddom v)))}- -> {v:Dict <range> key val | (listElts (ddom v)) = listElts keys}- @-}-projectD ks (D _ f) = D ks f--{-@ select :: forall <range :: key -> val -> Bool>.- (Dict <range> key val -> Bool)- -> x:[Dict <range> key val]- -> {v:[Dict <range> key val] | Set_sub (listElts v) (listElts x)}- @-}-select :: (Dict key val -> Bool) -> Table key val -> Table key val-select _ [] = []-select p (x:xs) | p x = x : select p xs- | otherwise = select p xs--{-@ values :: forall <range :: key -> val -> Bool>.- k:key -> [{v:Dict <range> key val | Set_mem k (listElts (ddom v))}] -> [val<range k>] @-}-values :: key -> [Dict key val] -> [val]-values k = map go- where- go (D _ f) = f k---{-@ empty :: {v:Dict <{\k v -> false}> key val | Set_emp (listElts (ddom v))} @-}-empty :: Dict key val-empty = D [] (\x -> error "call empty") -- TODO: replace error with liquidError?---extend :: Eq key => key -> val -> Dict key val -> Dict key val-{-@ extend :: forall <range :: key -> val -> Bool>.- k:key-> val<range k>- -> x:Dict <range> key val- -> {v:Dict <range> key val | (listElts (ddom v)) = (Set_cup (listElts (ddom x)) (Set_sng k))} @-}-extend k v (D ks f) = D (k:ks) (\i -> if i == k then v else f i)----data P k v = (:=) { kkey :: k, kval :: v }-{-@ data P k v <range :: k -> v -> Bool> = (:=) { kkey :: k, kval :: v<range kkey> }- @-}-infixr 3 +=--{-@ += :: forall <range :: key -> val -> Bool>.- pp:P <range> key val- -> x:Dict <range> key val- -> {v:Dict <range> key val | (listElts (ddom v)) = (Set_cup (listElts (ddom x)) (Set_sng (kkey pp)))} @-}-(+=) :: Eq key => P key val -> Dict key val -> Dict key val--(t := v) += c = extend t v c-------------------------------------------------------------------------------------------------------------- HELPERS --------------------------------------------------------------------------------------------------------------------------{-@ ensuredomain :: forall <p ::a -> Bool>. Eq a => xs:[a<p>] -> x:{v:a | Set_mem v (listElts xs)} -> {v:a<p> | Set_mem v (listElts xs) && v = x} @-}-ensuredomain :: Eq a => [a] -> a -> a-ensuredomain (y:ys) x | x == y = y- | otherwise = ensuredomain ys x-ensuredomain _ _ = liquidError "ensuredomain on empty list"----- | List functions--{-@ (\\) :: forall<p :: a -> Bool>. xs:[a<p>] -> ys:[a] -> {v:[a<p>] | (listElts v) = (Set_dif (listElts xs) (listElts ys))} @-}-(\\) :: Eq a => [a] -> [a] -> [a]-[] \\ _ = []-(x:xs) \\ ys = if x `elem` ys then xs \\ ys else x:(xs \\ ys)---{-@ assume (++) :: xs:[a] -> ys:[a] -> {v:[a] | listElts v = Set_cup (listElts xs) (listElts ys)} @-}--{-@ assume elem :: x:a -> xs:[a] -> {v:Bool | v <=> Set_mem x (listElts xs)} @-}-elem :: a -> [a] -> Bool-elem = undefined--{-@ filter :: xs:[a] -> ({v:a | Set_mem v (listElts xs)} -> Bool) -> {v:[a] | Set_sub (listElts v) (listElts xs)} @-}-filter :: [a] -> (a -> Bool) -> [a]-filter [] _ = []-filter (x:xs) f- | f x = x : filter xs f- | otherwise = filter xs f---liquidError :: String -> a-{-@ liquidError :: {v:String | false} -> a @-}-liquidError = error---{-@ qual :: xs:[a] -> {v: a | Set_mem v (listElts xs)} @-}-qual :: [a] -> a-qual = undefined--{-@ qual' :: forall <range :: key -> val -> Bool>. k:key -> val<range k> @-}-qual' :: key -> val-qual' = undefined--{-@ qual1 :: ks:[key] -> {v:Dict key val | (listElts (ddom v)) = listElts ks} @-}-qual1 :: [key] -> Dict key val-qual1 = undefined
@@ -1,88 +0,0 @@-module IfM where--{-@ LIQUID "--no-pattern-inline" @-}-{-@ LIQUID "--no-termination" @-}-{-@ LIQUID "--short-names" @-}--import RIO--{-@-ifM :: forall < p :: World -> Bool- , qc :: World -> Bool -> World -> Bool- , p1 :: World -> Bool- , p2 :: World -> Bool- , qe :: World -> a -> World -> Bool- , q :: World -> a -> World -> Bool>.- {b :: {v:Bool | v}, w :: World<p> |- World<qc w b> <: World<p1> }- {b :: {v:Bool | not (v)}, w :: World<p> |- World<qc w b> <: World<p2> }- {w1::World<p>, w2::World, y::a |- World<qe w2 y> <: World<q w1 y>}- RIO <p , qc> Bool- -> RIO <p1, qe> a- -> RIO <p2, qe> a- -> RIO <p , q > a-@-}-ifM :: RIO Bool -> RIO a -> RIO a -> RIO a-ifM (RIO cond) e1 e2- = RIO $ \x -> case cond x of {(y, s) -> runState (if y then e1 else e2) s}--{-@ measure counter :: World -> Int @-}------------------------------------------------------------------------------------------------------------------ ifM client ----------------------------------------------------------------------------------------------------------------------{-@-myif :: forall < p :: World -> Bool- , q :: World -> a -> World -> Bool>.- b:Bool- -> RIO <{v:World<p> | b }, q> a- -> RIO <{v:World<p> | not (b)}, q> a- -> RIO <p , q > a-@-}-myif :: Bool -> RIO a -> RIO a -> RIO a-myif b e1 e2- = if b then e1 else e2------------------------------------------------------------------------------------------------------------------ ifM client ----------------------------------------------------------------------------------------------------------------------ifTestUnsafe0 :: RIO Int-{-@ ifTestUnsafe0 :: RIO Int @-}-ifTestUnsafe0 = ifM checkZero (return 10) divX- where- checkZero = get >>= return . (/= 0)- divX = get >>= return . (42 `div`)--ifTestUnsafe1 :: RIO Int-{-@ ifTestUnsafe1 :: RIO Int @-}-ifTestUnsafe1 = ifM (checkNZeroX) divX (return 10)- where- checkNZeroX = do {x <- get; return $ x == 0 }- divX = do {x <- get; return $ 100 `div` x}---get :: RIO Int-{-@ get :: forall <p :: World -> Bool >.- RIO <p,\w x -> {v:World<p> | x = counter v && v == w}> Int @-}-get = undefined----{-@ qual1 :: n:Int -> RIO <{v:World | counter v = n}, \w1 b -> {v:World | (b <=> n /= 0) && (b <=> counter v /= 0)}> {v:Bool | v <=> n /= 0} @-}-qual1 :: Int -> RIO Bool-qual1 = \x -> return (x /= 0)--{-@ qual2 :: RIO <{\x -> true}, {\w1 b w2 -> b <=> counter w2 /= 0}> Bool @-}-qual2 :: RIO Bool-qual2 = undefined--{-@ qual3 :: n:Int -> RIO <{v:World | counter v = n}, \w1 b -> {v:World | (b <=> n == 0) && (b <=> counter v == 0)}> {v:Bool | v <=> n == 0} @-}-qual3 :: Int -> RIO Bool-qual3 = \x -> return (x == 0)--{-@ qual4 :: RIO <{\x -> true}, {\w1 b w2 -> b <=> counter w2 == 0}> Bool @-}-qual4 :: RIO Bool-qual4 = undefined
@@ -1,71 +0,0 @@-{-# LANGUAGE CPP #-}-module RIO where--#if __GLASGOW_HASKELL__ < 710-import Control.Applicative-#endif----- THE REST OF THIS FILE IS SAFE; just adding this to trigger an error to appease the "neg" gods.-{-@ silly_buggy_incr :: Nat -> Nat @-}-silly_buggy_incr :: Int -> Int -silly_buggy_incr x = x - 1---{-@ data RIO a <p :: World -> Bool, q :: World -> a -> World -> Bool>- = RIO (rs :: (xxx:World<p> -> (a, World)<\w -> {v:World<q xxx w> | true}>))- @-}-data RIO a = RIO {runState :: World -> (a, World)}--{-@ runState :: forall <p :: World -> Bool, q :: World -> a -> World -> Bool>.- RIO <p, q> a -> xyy:World<p> -> (a, World)<\w -> {v:World<q xyy w> | true}> @-}--data World = W---- | RJ: Putting these in to get GHC 7.10 to not fuss-instance Functor RIO where- fmap = undefined---- | RJ: Putting these in to get GHC 7.10 to not fuss-instance Applicative RIO where- pure = undefined- (<*>) = undefined--instance Monad RIO where-{-@ instance Monad RIO where- >>= :: forall < p :: World -> Bool- , p2 :: a -> World -> Bool- , r :: a -> Bool- , q1 :: World -> a -> World -> Bool- , q2 :: a -> World -> b -> World -> Bool- , q :: World -> b -> World -> Bool>.- {x::a<r>, w::World<p>|- World<q1 w x> <: World<p2 x>}- {y::a, w::World<p>, w2::World<p2 y>, x::b, y::a<r> |- World<q2 y w2 x> <: World<q w x>}- {x::a, w::World, w2::World<q1 w x>|- {v:a | v = x} <: a<r>}- RIO <p, q1> a- -> (x:a<r> -> RIO <{v:World<p2 x> | true}, \w1 y -> {v:World<q2 x w1 y> | true}> b)- -> RIO <p, q> b ;- >> :: forall < p :: World -> Bool- , p2 :: World -> Bool- , q1 :: World -> a -> World -> Bool- , q2 :: World -> b -> World -> Bool- , q :: World -> b -> World -> Bool>.- {x::a, w::World<p>|- World<q1 w x> <: World<p2>}- {w::World<p>, w2::World<p2>, x::b, y::a |- World<q2 w2 x> <: World<q w x>}- RIO <p, q1> a- -> RIO <p2, q2> b- -> RIO <p, q> b ;- return :: forall <p :: World -> Bool>.- x:a -> RIO <p, \w0 y -> {w1:World | w0 == w1 && y == x}> a- @-}- (RIO g) >>= f = RIO $ \x -> case g x of {(y, s) -> (runState (f y)) s}- (RIO g) >> f = RIO $ \x -> case g x of {(y, s) -> (runState f ) s}- return w = RIO $ \x -> (w, x)--{-@ qualif Papp4(v:a, x:b, y:c, z:d, p:Pred a b c d) : papp4(p, v, x, y, z) @-}---- Test Cases:--- * TestM (Basic)--- * TwiceM--- * IfM--- * WhileM
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff