1 : /******************************************************************************
2 : * $Id: dgnfloat.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: Microstation DGN Access Library
5 : * Purpose: Functions for translating DGN floats into IEEE floats.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, Avenza Systems Inc, http://www.avenza.com/
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "dgnlibp.h"
31 :
32 : CPL_CVSID("$Id: dgnfloat.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
33 :
34 : typedef struct dbl {
35 : GUInt32 hi;
36 : GUInt32 lo;
37 : } double64_t;
38 :
39 : /************************************************************************/
40 : /* DGN2IEEEDouble() */
41 : /************************************************************************/
42 :
43 3194 : void DGN2IEEEDouble(void * dbl)
44 :
45 : {
46 : double64_t dt;
47 : GUInt32 sign;
48 : GUInt32 exponent;
49 : GUInt32 rndbits;
50 : unsigned char *src;
51 : unsigned char *dest;
52 :
53 : /* -------------------------------------------------------------------- */
54 : /* Arrange the VAX double so that it may be accessed by a */
55 : /* double64_t structure, (two GUInt32s). */
56 : /* -------------------------------------------------------------------- */
57 3194 : src = (unsigned char *) dbl;
58 3194 : dest = (unsigned char *) &dt;
59 : #ifdef CPL_LSB
60 3194 : dest[2] = src[0];
61 3194 : dest[3] = src[1];
62 3194 : dest[0] = src[2];
63 3194 : dest[1] = src[3];
64 3194 : dest[6] = src[4];
65 3194 : dest[7] = src[5];
66 3194 : dest[4] = src[6];
67 3194 : dest[5] = src[7];
68 : #else
69 : dest[1] = src[0];
70 : dest[0] = src[1];
71 : dest[3] = src[2];
72 : dest[2] = src[3];
73 : dest[5] = src[4];
74 : dest[4] = src[5];
75 : dest[7] = src[6];
76 : dest[6] = src[7];
77 : #endif
78 :
79 : /* -------------------------------------------------------------------- */
80 : /* Save the sign of the double */
81 : /* -------------------------------------------------------------------- */
82 3194 : sign = dt.hi & 0x80000000;
83 :
84 : /* -------------------------------------------------------------------- */
85 : /* Adjust the exponent so that we may work with it */
86 : /* -------------------------------------------------------------------- */
87 3194 : exponent = dt.hi >> 23;
88 3194 : exponent = exponent & 0x000000ff;
89 :
90 3194 : if (exponent)
91 636 : exponent = exponent -129 + 1023;
92 :
93 : /* -------------------------------------------------------------------- */
94 : /* Save the bits that we are discarding so we can round properly */
95 : /* -------------------------------------------------------------------- */
96 3194 : rndbits = dt.lo & 0x00000007;
97 :
98 3194 : dt.lo = dt.lo >> 3;
99 3194 : dt.lo = (dt.lo & 0x1fffffff) | (dt.hi << 29);
100 :
101 3194 : if (rndbits)
102 0 : dt.lo = dt.lo | 0x00000001;
103 :
104 : /* -------------------------------------------------------------------- */
105 : /* Shift the hi-order int over 3 and insert the exponent and sign */
106 : /* -------------------------------------------------------------------- */
107 3194 : dt.hi = dt.hi >> 3;
108 3194 : dt.hi = dt.hi & 0x000fffff;
109 3194 : dt.hi = dt.hi | (exponent << 20) | sign;
110 :
111 :
112 :
113 : #ifdef CPL_LSB
114 : /* -------------------------------------------------------------------- */
115 : /* Change the number to a byte swapped format */
116 : /* -------------------------------------------------------------------- */
117 3194 : src = (unsigned char *) &dt;
118 3194 : dest = (unsigned char *) dbl;
119 :
120 3194 : dest[0] = src[4];
121 3194 : dest[1] = src[5];
122 3194 : dest[2] = src[6];
123 3194 : dest[3] = src[7];
124 3194 : dest[4] = src[0];
125 3194 : dest[5] = src[1];
126 3194 : dest[6] = src[2];
127 3194 : dest[7] = src[3];
128 : #else
129 : memcpy( dbl, &dt, 8 );
130 : #endif
131 3194 : }
132 :
133 : /************************************************************************/
134 : /* IEEE2DGNDouble() */
135 : /************************************************************************/
136 :
137 6 : void IEEE2DGNDouble(void * dbl)
138 :
139 : {
140 : double64_t dt;
141 : GInt32 exponent;
142 : GInt32 sign;
143 : GByte *src,*dest;
144 :
145 : #ifdef CPL_LSB
146 6 : src = (GByte *) dbl;
147 6 : dest = (GByte *) &dt;
148 :
149 6 : dest[0] = src[4];
150 6 : dest[1] = src[5];
151 6 : dest[2] = src[6];
152 6 : dest[3] = src[7];
153 6 : dest[4] = src[0];
154 6 : dest[5] = src[1];
155 6 : dest[6] = src[2];
156 6 : dest[7] = src[3];
157 : #else
158 : memcpy( &dt, dbl, 8 );
159 : #endif
160 :
161 6 : sign = dt.hi & 0x80000000;
162 6 : exponent = dt.hi >> 20;
163 6 : exponent = exponent & 0x000007ff;
164 :
165 : /* -------------------------------------------------------------------- */
166 : /* An exponent of zero means a zero value. */
167 : /* -------------------------------------------------------------------- */
168 6 : if (exponent)
169 4 : exponent = exponent -1023+129;
170 :
171 : /* -------------------------------------------------------------------- */
172 : /* In the case of overflow, return the largest number we can */
173 : /* -------------------------------------------------------------------- */
174 6 : if (exponent > 255)
175 : {
176 0 : dest = (GByte *) dbl;
177 :
178 0 : if (sign)
179 0 : dest[1] = 0xff;
180 : else
181 0 : dest[1] = 0x7f;
182 :
183 0 : dest[0] = 0xff;
184 0 : dest[2] = 0xff;
185 0 : dest[3] = 0xff;
186 0 : dest[4] = 0xff;
187 0 : dest[5] = 0xff;
188 0 : dest[6] = 0xff;
189 0 : dest[7] = 0xff;
190 :
191 0 : return;
192 : }
193 :
194 : /* -------------------------------------------------------------------- */
195 : /* In the case of of underflow return zero */
196 : /* -------------------------------------------------------------------- */
197 6 : else if ((exponent < 0 ) ||
198 : (exponent == 0 && sign == 0))
199 : {
200 2 : dest = (GByte *) dbl;
201 :
202 2 : dest[0] = 0x00;
203 2 : dest[1] = 0x00;
204 2 : dest[2] = 0x00;
205 2 : dest[3] = 0x00;
206 2 : dest[4] = 0x00;
207 2 : dest[5] = 0x00;
208 2 : dest[6] = 0x00;
209 2 : dest[7] = 0x00;
210 :
211 2 : return;
212 : }
213 : else
214 : {
215 : /* -------------------------------------------------------------------- */
216 : /* Shift the fraction 3 bits left and set the exponent and sign*/
217 : /* -------------------------------------------------------------------- */
218 4 : dt.hi = dt.hi << 3;
219 4 : dt.hi = dt.hi | (dt.lo >> 29);
220 4 : dt.hi = dt.hi & 0x007fffff;
221 4 : dt.hi = dt.hi | (exponent << 23) | sign;
222 :
223 4 : dt.lo = dt.lo << 3;
224 : }
225 :
226 : /* -------------------------------------------------------------------- */
227 : /* Convert the double back to VAX format */
228 : /* -------------------------------------------------------------------- */
229 4 : src = (GByte *) &dt;
230 4 : dest = (GByte *) dbl;
231 :
232 : #ifdef CPL_LSB
233 4 : dest[2] = src[0];
234 4 : dest[3] = src[1];
235 4 : dest[0] = src[2];
236 4 : dest[1] = src[3];
237 4 : dest[6] = src[4];
238 4 : dest[7] = src[5];
239 4 : dest[4] = src[6];
240 4 : dest[5] = src[7];
241 : #else
242 : dest[1] = src[0];
243 : dest[0] = src[1];
244 : dest[3] = src[2];
245 : dest[2] = src[3];
246 : dest[5] = src[4];
247 : dest[4] = src[5];
248 : dest[7] = src[6];
249 : dest[6] = src[7];
250 : #endif
251 : }
|