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 1597 : 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 1597 : src = (unsigned char *) dbl;
58 1597 : dest = (unsigned char *) &dt;
59 : #ifdef CPL_LSB
60 1597 : dest[2] = src[0];
61 1597 : dest[3] = src[1];
62 1597 : dest[0] = src[2];
63 1597 : dest[1] = src[3];
64 1597 : dest[6] = src[4];
65 1597 : dest[7] = src[5];
66 1597 : dest[4] = src[6];
67 1597 : 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 1597 : sign = dt.hi & 0x80000000;
83 :
84 : /* -------------------------------------------------------------------- */
85 : /* Adjust the exponent so that we may work with it */
86 : /* -------------------------------------------------------------------- */
87 1597 : exponent = dt.hi >> 23;
88 1597 : exponent = exponent & 0x000000ff;
89 :
90 1597 : if (exponent)
91 318 : exponent = exponent -129 + 1023;
92 :
93 : /* -------------------------------------------------------------------- */
94 : /* Save the bits that we are discarding so we can round properly */
95 : /* -------------------------------------------------------------------- */
96 1597 : rndbits = dt.lo & 0x00000007;
97 :
98 1597 : dt.lo = dt.lo >> 3;
99 1597 : dt.lo = (dt.lo & 0x1fffffff) | (dt.hi << 29);
100 :
101 1597 : 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 1597 : dt.hi = dt.hi >> 3;
108 1597 : dt.hi = dt.hi & 0x000fffff;
109 1597 : 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 1597 : src = (unsigned char *) &dt;
118 1597 : dest = (unsigned char *) dbl;
119 :
120 1597 : dest[0] = src[4];
121 1597 : dest[1] = src[5];
122 1597 : dest[2] = src[6];
123 1597 : dest[3] = src[7];
124 1597 : dest[4] = src[0];
125 1597 : dest[5] = src[1];
126 1597 : dest[6] = src[2];
127 1597 : dest[7] = src[3];
128 : #else
129 : memcpy( dbl, &dt, 8 );
130 : #endif
131 1597 : }
132 :
133 : /************************************************************************/
134 : /* IEEE2DGNDouble() */
135 : /************************************************************************/
136 :
137 3 : 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 3 : src = (GByte *) dbl;
147 3 : dest = (GByte *) &dt;
148 :
149 3 : dest[0] = src[4];
150 3 : dest[1] = src[5];
151 3 : dest[2] = src[6];
152 3 : dest[3] = src[7];
153 3 : dest[4] = src[0];
154 3 : dest[5] = src[1];
155 3 : dest[6] = src[2];
156 3 : dest[7] = src[3];
157 : #else
158 : memcpy( &dt, dbl, 8 );
159 : #endif
160 :
161 3 : sign = dt.hi & 0x80000000;
162 3 : exponent = dt.hi >> 20;
163 3 : exponent = exponent & 0x000007ff;
164 :
165 : /* -------------------------------------------------------------------- */
166 : /* An exponent of zero means a zero value. */
167 : /* -------------------------------------------------------------------- */
168 3 : if (exponent)
169 2 : exponent = exponent -1023+129;
170 :
171 : /* -------------------------------------------------------------------- */
172 : /* In the case of overflow, return the largest number we can */
173 : /* -------------------------------------------------------------------- */
174 3 : 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 3 : else if ((exponent < 0 ) ||
198 : (exponent == 0 && sign == 0))
199 : {
200 1 : dest = (GByte *) dbl;
201 :
202 1 : dest[0] = 0x00;
203 1 : dest[1] = 0x00;
204 1 : dest[2] = 0x00;
205 1 : dest[3] = 0x00;
206 1 : dest[4] = 0x00;
207 1 : dest[5] = 0x00;
208 1 : dest[6] = 0x00;
209 1 : dest[7] = 0x00;
210 :
211 1 : return;
212 : }
213 : else
214 : {
215 : /* -------------------------------------------------------------------- */
216 : /* Shift the fraction 3 bits left and set the exponent and sign*/
217 : /* -------------------------------------------------------------------- */
218 2 : dt.hi = dt.hi << 3;
219 2 : dt.hi = dt.hi | (dt.lo >> 29);
220 2 : dt.hi = dt.hi & 0x007fffff;
221 2 : dt.hi = dt.hi | (exponent << 23) | sign;
222 :
223 2 : dt.lo = dt.lo << 3;
224 : }
225 :
226 : /* -------------------------------------------------------------------- */
227 : /* Convert the double back to VAX format */
228 : /* -------------------------------------------------------------------- */
229 2 : src = (GByte *) &dt;
230 2 : dest = (GByte *) dbl;
231 :
232 : #ifdef CPL_LSB
233 2 : dest[2] = src[0];
234 2 : dest[3] = src[1];
235 2 : dest[0] = src[2];
236 2 : dest[1] = src[3];
237 2 : dest[6] = src[4];
238 2 : dest[7] = src[5];
239 2 : dest[4] = src[6];
240 2 : 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 : }
|