1(*
2    Title:      Standard Basis Library: Pack Real32 structures for 64-bit platforms
3    Author:     David Matthews
4    Copyright   David Matthews 2021
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    Licence version 2.1 as published by the Free Software Foundation.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public Licence for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18*)
19
20(* On 64-bit platforms Real32.real values are held as tagged values
21   with the floating point value in the high-order 32-bits. *)
22
23local
24    val r32AsWord: Real32.real -> word = RunCall.unsafeCast
25    and wordAsR32: word -> Real32.real = RunCall.unsafeCast
26
27    infix << >>
28    infix orb
29    val op orb = Word.orb
30    and op << = Word.<<
31    and op >> = Word.>>
32
33    val wordToW8 = Word8.fromLarge o Word.toLarge
34    and w8ToWord = Word.fromLarge o Word8.toLarge
35
36    (* Word values are already shifted by one bit so the
37       actual shifts are 31, 39, 47 and 55 bits. *)
38    val shift0 = Word.fromInt Word.wordSize - 0w32
39    and shift1 = Word.fromInt Word.wordSize - 0w24
40    and shift2 = Word.fromInt Word.wordSize - 0w16
41    and shift3 = Word.fromInt Word.wordSize - 0w08
42in
43
44    structure PackReal32Little: PACK_REAL =
45    struct
46        type real = Real32.real
47        val bytesPerElem = 4
48        val isBigEndian = false
49
50        fun toBytes r =
51        let
52            val w: word = r32AsWord r
53        in
54            Word8Vector.fromList[wordToW8(w >> shift0), wordToW8(w >> shift1),
55                    wordToW8(w >> shift2), wordToW8(w >> shift3)]
56        end
57
58        fun subVec(v, i) =
59        let
60            val iW = i * bytesPerElem
61        in
62            wordAsR32((w8ToWord(Word8Vector.sub(v, iW)) << shift0) orb
63                (w8ToWord(Word8Vector.sub(v, iW+1)) << shift1) orb
64                (w8ToWord(Word8Vector.sub(v, iW+2)) << shift2) orb
65                (w8ToWord(Word8Vector.sub(v, iW+3)) << shift3))
66        end
67
68        fun fromBytes v = subVec(v, 0)
69
70        fun subArr(v, i) =
71        let
72            val iW = i * bytesPerElem
73        in
74            wordAsR32((w8ToWord(Word8Array.sub(v, iW)) << shift0) orb
75                (w8ToWord(Word8Array.sub(v, iW+1)) << shift1) orb
76                (w8ToWord(Word8Array.sub(v, iW+2)) << shift2) orb
77                (w8ToWord(Word8Array.sub(v, iW+3)) << shift3))
78        end
79
80        fun update(v, i, r) =
81        let
82            val w: word = r32AsWord r
83            open Word8Array
84            val iW = i * bytesPerElem
85        in
86            Word8Array.update(v, iW, wordToW8(w >> shift0));
87            Word8Array.update(v, iW+1, wordToW8(w >> shift1));
88            Word8Array.update(v, iW+2, wordToW8(w >> shift2));
89            Word8Array.update(v, iW+3, wordToW8(w >> shift3))
90        end
91    end
92
93    structure PackReal32Big: PACK_REAL =
94    struct
95        type real = Real32.real
96        val bytesPerElem = 4
97        val isBigEndian = false
98
99        fun toBytes r =
100        let
101            val w: word = r32AsWord r
102        in
103            Word8Vector.fromList[wordToW8(w >> shift3), wordToW8(w >> shift2),
104                wordToW8(w >> shift1), wordToW8(w >> shift0)]
105        end
106
107        fun subVec(v, i) =
108        let
109            val iW = i * bytesPerElem
110        in
111            wordAsR32((w8ToWord(Word8Vector.sub(v, iW)) << shift3) orb
112                (w8ToWord(Word8Vector.sub(v, iW+1)) << shift2) orb
113                (w8ToWord(Word8Vector.sub(v, iW+2)) << shift1) orb
114                (w8ToWord(Word8Vector.sub(v, iW+3)) << shift0))
115        end
116
117        fun fromBytes v = subVec(v, 0)
118
119        fun subArr(v, i) =
120        let
121            val iW = i * bytesPerElem
122        in
123            wordAsR32((w8ToWord(Word8Array.sub(v, iW)) << shift3) orb
124                (w8ToWord(Word8Array.sub(v, iW+1)) << shift2) orb
125                (w8ToWord(Word8Array.sub(v, iW+2)) << shift1) orb
126                (w8ToWord(Word8Array.sub(v, iW+3)) << shift0))
127        end
128
129        fun update(v, i, r) =
130        let
131            val w: word = r32AsWord r
132            open Word8Array
133            val iW = i * bytesPerElem
134        in
135            Word8Array.update(v, iW, wordToW8(w >> shift3));
136            Word8Array.update(v, iW+1, wordToW8(w >> shift2));
137            Word8Array.update(v, iW+2, wordToW8(w >> shift1));
138            Word8Array.update(v, iW+3, wordToW8(w >> shift0))
139        end
140    end
141
142end;
143