Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
sml-util/libs/pack-real.sml
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
58 lines (48 sloc)
2.08 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* SML has optional structures in the basis called PackRealLittle and | |
* PackRealBig (implementing the PACK_REAL signature) for marshalling and | |
* unmarshalling real data. While mlton provides these, SML/NJ does not. | |
* This is an implementation of PACK_REAL for SML/NJ built on top of | |
* unsafe casting and subscripting. *) | |
local | |
functor PackRealFn(val isBigEndian : bool) : PACK_REAL = | |
struct | |
type real = real | |
val bytesPerElem = 8 | |
val isBigEndian = isBigEndian | |
structure UR = Unsafe.Real64Array | |
structure UB = Unsafe.Word8Array | |
structure A = Word8Array | |
structure AS = Word8ArraySlice | |
structure V = Word8Vector | |
structure VS = Word8VectorSlice | |
(* | |
fun rawToBytes x = | |
let val a : UR.array = Unsafe.cast (RealArray.array (1, x)) | |
in V.tabulate (bytesPerElem, fn i => UB.sub (a, i)) end | |
fun rawFromBytes (v : V.vector) = UR.sub (Unsafe.cast v, 0) | |
*) | |
fun rawToBytes x = | |
let val a = Real64Array.array (8, x) (* LOOOOOL. *) | |
in V.tabulate (bytesPerElem, fn i => A.sub (a, i)) end | |
fun rawFromBytes (v : V.vector) = | |
let val a = A.tabulate (V.length v, fn i => V.sub (v, i)) | |
in Real64Array.sub (a, 0) end | |
(* Compare against a known result to determine the system's endianness | |
* and swap around byte orders if it differs from our intended endianness. *) | |
val isSystemBigEndian = V.sub (rawToBytes 3.14159265358979323, 0) <> 0wx18 | |
val swizzle = if isBigEndian = isSystemBigEndian then (fn v => v) else | |
(fn v => V.tabulate (bytesPerElem, fn i => V.sub (v, bytesPerElem-i-1))) | |
val toBytes = swizzle o rawToBytes | |
val fromBytes = rawFromBytes o swizzle | |
fun subVec (v, i) = | |
fromBytes (VS.vector (VS.slice (v, bytesPerElem*i, SOME bytesPerElem))) | |
fun subArr (v, i) = | |
fromBytes (AS.vector (AS.slice (v, bytesPerElem*i, SOME bytesPerElem))) | |
fun update (v, i, x) = A.copyVec { src = toBytes x, dst = v, di = i*bytesPerElem } | |
end | |
in | |
structure PackRealLittle = PackRealFn(val isBigEndian = false) | |
structure PackReal64Little = PackRealLittle | |
structure PackRealBig = PackRealFn(val isBigEndian = true) | |
structure PackReal64Big = PackRealBig | |
end |