1(*
2    Title:      Standard Basis Library: PACK_WORD signature and structures
3    Author:     David Matthews
4    Copyright   David Matthews 2000, 2005
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    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10    
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15    
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19*)
20
21(* G&R 2004 status: updated, the structure names have changed. *)
22
23signature PACK_WORD =
24sig
25    val bytesPerElem : int
26    val isBigEndian : bool
27    val subVec  : Word8Vector.vector * int -> LargeWord.word
28    val subVecX : Word8Vector.vector * int -> LargeWord.word
29    val subArr  : Word8Array.array * int -> LargeWord.word
30    val subArrX : Word8Array.array * int -> LargeWord.word
31    val update : Word8Array.array * int * LargeWord.word -> unit
32end;
33
34(* I'm not sure what use Pack8Big and Pack8Little are since
35   they don't do any packing. *)
36structure PackWord8Big : PACK_WORD =
37struct
38    val bytesPerElem = 1
39    val isBigEndian = true
40    val subVec = Word8.toLargeWord o Word8Vector.sub
41    val subVecX = Word8.toLargeWordX o Word8Vector.sub
42    val subArr = Word8.toLargeWord o Word8Array.sub
43    val subArrX = Word8.toLargeWordX o Word8Array.sub
44    fun update(a, i, v) = Word8Array.update(a, i, Word8.fromLargeWord v)
45end;
46
47structure PackWord8Little : PACK_WORD =
48struct
49(* Exactly the same as Pack8Big except for the value of isBigEndian *)
50    open PackWord8Big
51    val isBigEndian = false
52end;
53
54local
55    infix << >>
56    infix andb
57    infix orb
58    val op orb = LargeWord.orb
59    and op << = LargeWord.<<
60    and op >> = LargeWord.>>
61
62    fun twoBytesToWord(hi: Word8.word, lo: Word8.word) =
63        (Word8.toLargeWord hi << 0w8) orb Word8.toLargeWord lo
64
65    fun twoBytesToWordX(hi: Word8.word, lo: Word8.word) =
66        (Word8.toLargeWordX hi << 0w8) orb Word8.toLargeWord lo
67
68    fun fourBytesToWord(highest, higher, lower, low) =
69        (Word8.toLargeWord highest << 0w24) orb 
70        (Word8.toLargeWord higher << 0w16) orb
71        (Word8.toLargeWord lower << 0w8) orb 
72        Word8.toLargeWord low
73
74    fun fourBytesToWordX(highest, higher, lower, low) =
75        (Word8.toLargeWordX highest << 0w24) orb 
76        (Word8.toLargeWord higher << 0w16) orb
77        (Word8.toLargeWord lower << 0w8) orb 
78        Word8.toLargeWord low
79
80in
81    structure PackWord16Big : PACK_WORD =
82    struct
83        val bytesPerElem = 2
84        val isBigEndian = true
85
86        fun subVec(a, i) =
87            twoBytesToWord(
88                Word8Vector.sub(a, i*2), Word8Vector.sub(a, i*2+1))
89
90        fun subVecX(a, i) =
91            twoBytesToWordX(
92                Word8Vector.sub(a, i*2), Word8Vector.sub(a, i*2+1))
93
94        fun subArr(a, i) =
95            twoBytesToWord(
96                Word8Array.sub(a, i*2), Word8Array.sub(a, i*2+1))
97
98        fun subArrX(a, i) =
99            twoBytesToWordX(
100                Word8Array.sub(a, i*2), Word8Array.sub(a, i*2+1))
101
102        fun update(a, i, v) =
103            (* Check the index before doing any update. *)
104            if i < 0 orelse i*2+1 >= Word8Array.length a
105            then raise Subscript
106            else
107            (Word8Array.update(a, i*2+1, Word8.fromLargeWord v);
108             Word8Array.update(a, i*2, Word8.fromLargeWord(v >> 0w8))
109            )
110    end;
111
112    structure PackWord16Little : PACK_WORD =
113    struct
114        val bytesPerElem = 2
115        val isBigEndian = false
116
117        fun subVec(a, i) =
118            twoBytesToWord(
119                Word8Vector.sub(a, i*2+1), Word8Vector.sub(a, i*2))
120
121        fun subVecX(a, i) =
122            twoBytesToWordX(
123                Word8Vector.sub(a, i*2+1), Word8Vector.sub(a, i*2))
124
125        fun subArr(a, i) =
126            twoBytesToWord(
127                Word8Array.sub(a, i*2+1), Word8Array.sub(a, i*2))
128
129        fun subArrX(a, i) =
130            twoBytesToWordX(
131                Word8Array.sub(a, i*2+1), Word8Array.sub(a, i*2))
132
133        fun update(a, i, v) =
134            (* Check the index before doing any update. *)
135            if i < 0 orelse i*2+1 >= Word8Array.length a
136            then raise Subscript
137            else
138            (Word8Array.update(a, i*2, Word8.fromLargeWord v);
139             Word8Array.update(a, i*2+1, Word8.fromLargeWord(v >> 0w8))
140            )
141    end;
142
143    structure PackWord32Big : PACK_WORD =
144    struct
145        val bytesPerElem = 4
146        val isBigEndian = true
147
148        fun subVec(a, i) =
149            fourBytesToWord(
150                Word8Vector.sub(a, i*4), Word8Vector.sub(a, i*4+1),
151                Word8Vector.sub(a, i*4+2), Word8Vector.sub(a, i*4+3))
152
153        fun subVecX(a, i) =
154            fourBytesToWordX(
155                Word8Vector.sub(a, i*4), Word8Vector.sub(a, i*4+1),
156                Word8Vector.sub(a, i*4+2), Word8Vector.sub(a, i*4+3))
157
158        fun subArr(a, i) =
159            fourBytesToWord(
160                Word8Array.sub(a, i*4), Word8Array.sub(a, i*4+1),
161                Word8Array.sub(a, i*4+2), Word8Array.sub(a, i*4+3))
162
163        fun subArrX(a, i) =
164            fourBytesToWordX(
165                Word8Array.sub(a, i*4), Word8Array.sub(a, i*4+1),
166                Word8Array.sub(a, i*4+2), Word8Array.sub(a, i*4+3))
167
168        fun update(a, i, v) =
169            (* Check the index before doing any update. *)
170            if i < 0 orelse i*4+3 >= Word8Array.length a
171            then raise Subscript
172            else
173            (Word8Array.update(a, i*4+3, Word8.fromLargeWord v);
174             Word8Array.update(a, i*4+2, Word8.fromLargeWord(v >> 0w8));
175             Word8Array.update(a, i*4+1, Word8.fromLargeWord(v >> 0w16));
176             Word8Array.update(a, i*4, Word8.fromLargeWord(v >> 0w24))
177            )
178    end;
179
180    structure PackWord32Little : PACK_WORD =
181    struct
182        val bytesPerElem = 4
183        val isBigEndian = false
184
185        fun subVec(a, i) =
186            fourBytesToWord(
187                Word8Vector.sub(a, i*4+3), Word8Vector.sub(a, i*4+2),
188                Word8Vector.sub(a, i*4+1), Word8Vector.sub(a, i*4))
189
190        fun subVecX(a, i) =
191            fourBytesToWordX(
192                Word8Vector.sub(a, i*4+3), Word8Vector.sub(a, i*4+2),
193                Word8Vector.sub(a, i*4+1), Word8Vector.sub(a, i*4))
194
195        fun subArr(a, i) =
196            fourBytesToWord(
197                Word8Array.sub(a, i*4+3), Word8Array.sub(a, i*4+2),
198                Word8Array.sub(a, i*4+1), Word8Array.sub(a, i*4))
199
200        fun subArrX(a, i) =
201            fourBytesToWordX(
202                Word8Array.sub(a, i*4+3), Word8Array.sub(a, i*4+2),
203                Word8Array.sub(a, i*4+1), Word8Array.sub(a, i*4))
204
205        fun update(a, i, v) =
206            (* Check the index before doing any update. *)
207            if i < 0 orelse i*4+3 >= Word8Array.length a
208            then raise Subscript
209            else
210            (Word8Array.update(a, i*4, Word8.fromLargeWord v);
211             Word8Array.update(a, i*4+1, Word8.fromLargeWord(v >> 0w8));
212             Word8Array.update(a, i*4+2, Word8.fromLargeWord(v >> 0w16));
213             Word8Array.update(a, i*4+3, Word8.fromLargeWord(v >> 0w24))
214            )
215    end
216
217end;
218
219