1
2
3
4
5
6
7
8
9
10
11 package com.legstar.coxb.convert.simple;
12
13 import com.legstar.coxb.CobolContext;
14 import com.legstar.coxb.ICobolArrayDoubleBinding;
15 import com.legstar.coxb.ICobolDoubleBinding;
16 import com.legstar.coxb.convert.ICobolDoubleConverter;
17 import com.legstar.coxb.convert.CobolConversionException;
18 import com.legstar.coxb.host.HostData;
19 import com.legstar.coxb.host.HostDouble;
20 import com.legstar.coxb.host.HostException;
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25
26
27
28
29
30
31
32 public class CobolDoubleSimpleConverter extends CobolSimpleConverter
33 implements ICobolDoubleConverter {
34
35
36
37
38 public CobolDoubleSimpleConverter(final CobolContext cobolContext) {
39 super(cobolContext);
40 }
41
42
43 public int toHost(
44 final ICobolDoubleBinding ce,
45 final byte[] hostTarget,
46 final int offset)
47 throws HostException {
48 int newOffset = 0;
49 try {
50 newOffset = toHostSingle(ce.getDoubleValue(),
51 hostTarget,
52 offset);
53 } catch (CobolConversionException e) {
54 throwHostException(ce, e);
55 }
56 return newOffset;
57 }
58
59
60 public int toHost(
61 final ICobolArrayDoubleBinding ce,
62 final byte[] hostTarget,
63 final int offset,
64 final int currentOccurs)
65 throws HostException {
66 int newOffset = offset;
67 try {
68 for (Double javaSource : ce.getDoubleList()) {
69 newOffset = toHostSingle(javaSource,
70 hostTarget,
71 newOffset);
72 }
73
74 for (int i = ce.getDoubleList().size(); i < currentOccurs; i++) {
75 newOffset = toHostSingle(Double.valueOf(0),
76 hostTarget,
77 newOffset);
78 }
79 } catch (CobolConversionException e) {
80 throwHostException(ce, e);
81 }
82 return newOffset;
83 }
84
85
86 public int fromHost(
87 final ICobolDoubleBinding ce,
88 final byte[] hostSource,
89 final int offset)
90 throws HostException {
91 int newOffset = offset;
92 try {
93 Double javaDouble = fromHostSingle(ce.getByteLength(),
94 hostSource,
95 newOffset);
96 ce.setDoubleValue(javaDouble);
97 newOffset += ce.getByteLength();
98 } catch (CobolConversionException e) {
99 throwHostException(ce, e);
100 }
101 return newOffset;
102 }
103
104
105 public int fromHost(
106 final ICobolArrayDoubleBinding ce,
107 final byte[] hostSource,
108 final int offset,
109 final int currentOccurs)
110 throws HostException {
111 List < Double > lArray = new ArrayList < Double >();
112 int newOffset = offset;
113 try {
114 for (int i = 0; i < currentOccurs; i++) {
115 Double javaDouble = fromHostSingle(ce.getItemByteLength(),
116 hostSource,
117 newOffset);
118 lArray.add(javaDouble);
119 newOffset += ce.getItemByteLength();
120 }
121 ce.setDoubleList(lArray);
122 } catch (CobolConversionException e) {
123 throwHostException(ce, e);
124 }
125 return newOffset;
126 }
127
128
129
130
131
132
133
134
135
136
137 public static final int toHostSingle(
138 final Double javaDouble,
139 final byte[] hostTarget,
140 final int offset)
141 throws CobolConversionException {
142
143
144 int cobolByteLength = 8;
145
146
147 int lastOffset = offset + cobolByteLength;
148 if (lastOffset > hostTarget.length) {
149 throw (new CobolConversionException(
150 "Attempt to write past end of host source buffer",
151 new HostData(hostTarget), offset));
152 }
153
154
155 Double localDouble = javaDouble;
156 if (localDouble == null) {
157 localDouble = 0d;
158 }
159
160
161 if (localDouble.isInfinite()) {
162 throw (new CobolConversionException(
163 "Infinite doubles are not supported",
164 new HostData(hostTarget), offset));
165 }
166 if (localDouble.isNaN()) {
167 throw (new CobolConversionException(
168 "NaN doubles are not supported",
169 new HostData(hostTarget), offset));
170 }
171
172
173
174
175
176 if ((localDouble.doubleValue() == 0.0f)
177 ||
178 (localDouble.doubleValue() == -0.0f)) {
179 for (int i = 0; i < 8; i++) {
180 hostTarget[offset + i] = 0;
181 }
182 return offset + cobolByteLength;
183 }
184
185
186 HostDouble jF = parseJavaDouble(localDouble);
187
188
189 HostDouble hF = new HostDouble();
190 hF.setSign(jF.getSign());
191
192
193
194
195
196
197
198 int r = jF.getExponent() % 4;
199 int mantissaShift = 0;
200 if (r <= 0) {
201 mantissaShift = -1 * r;
202 } else {
203 mantissaShift = 4 - r;
204 }
205
206 hF.setExponent((jF.getExponent() + mantissaShift) / 4);
207 hF.setMantissa(jF.getMantissa() >> mantissaShift);
208
209
210
211
212
213
214
215 hF.setMantissa(hF.getMantissa() << 3);
216
217
218 long hostLongBits = createHostDouble(hF);
219
220
221 for (int i = 0; i < 8; i++) {
222 hostTarget[offset + i] =
223 (byte) ((hostLongBits >>> (56 - i * 8)) & 0xff);
224 }
225
226 return offset + cobolByteLength;
227 }
228
229
230
231
232
233
234
235
236
237
238 public static final Double fromHostSingle(
239 final int cobolByteLength,
240 final byte[] hostSource,
241 final int offset)
242 throws CobolConversionException {
243
244 int lastOffset = offset + cobolByteLength;
245
246
247
248
249
250
251 if (lastOffset > hostSource.length) {
252 return Double.valueOf(0d);
253 }
254
255
256 long hostLongBits = 0;
257 for (int i = 0; i < 8; i++) {
258 hostLongBits = hostLongBits
259 | ((long) (hostSource[offset + (7 - i)] & 0xff) << (i * 8));
260 }
261 HostDouble hF = parseHostDouble(hostLongBits);
262
263
264 HostDouble jF = new HostDouble();
265 jF.setSign(hF.getSign());
266
267
268
269
270
271
272 if (hF.getMantissa() != 0) {
273 jF.setExponent((4 * hF.getExponent()) - 1);
274 }
275
276
277
278
279
280 jF.setMantissa(hF.getMantissa() >>> 3);
281
282
283 while ((jF.getMantissa() > 0L)
284 &&
285 (jF.getMantissa() & 0x0010000000000000L) == 0) {
286 jF.setMantissa(jF.getMantissa() << 1);
287 jF.setExponent(jF.getExponent() - 1);
288 }
289
290 return createJavaDouble(jF);
291 }
292
293
294
295
296
297
298
299 public static final HostDouble parseJavaDouble(final double f) {
300
301 HostDouble jF = new HostDouble();
302
303
304 if (f == 0.0f) {
305 return jF;
306 }
307
308 long javaLongBits = Double.doubleToLongBits(f);
309
310
311 jF.setSign((int) ((javaLongBits & 0x8000000000000000L) >>> 63));
312
313
314
315
316
317
318
319
320 int excess = (int) ((javaLongBits >> 52) & 0x7ffL);
321 jF.setExponent(excess - 1023 + 1);
322
323
324
325
326
327
328
329 long orMask = 1L << 52;
330 jF.setMantissa(javaLongBits & 0x000fffffffffffffL | orMask);
331
332 return jF;
333 }
334
335
336
337
338
339
340
341
342 public static final double createJavaDouble(final HostDouble jF) {
343
344
345 if (jF.getExponent() == 0 && jF.getMantissa() == 0) {
346 return 0d;
347 }
348
349
350 long javaLongBits = jF.getMantissa() & 0x000fffffffffffffL;
351 javaLongBits = javaLongBits | ((long) (jF.getExponent() + 1023) << 52);
352 javaLongBits = javaLongBits | ((long) jF.getSign() << 63);
353 return Double.longBitsToDouble(javaLongBits);
354 }
355
356
357
358
359
360
361
362 public static final HostDouble parseHostDouble(final long hostLongBits) {
363 HostDouble hF = new HostDouble();
364
365
366 hF.setSign((int) ((hostLongBits & 0x8000000000000000L) >>> 63));
367
368
369
370
371
372
373 int excess = (int) ((hostLongBits & 0x7f00000000000000L) >>> 56);
374 if (excess != 0) {
375 hF.setExponent((excess - 64));
376 }
377
378
379 hF.setMantissa(hostLongBits & 0x00ffffffffffffffL);
380
381 return hF;
382 }
383
384
385
386
387
388
389
390
391 public static final long createHostDouble(final HostDouble hF) {
392
393
394 if (hF.getExponent() == 0 && hF.getMantissa() == 0) {
395 return 0L;
396 }
397
398 long hostLongBits = hF.getMantissa();
399 hostLongBits = hostLongBits | ((long) (hF.getExponent() + 64) << 56);
400 hostLongBits = hostLongBits | ((long) hF.getSign() << 63);
401 return hostLongBits;
402 }
403 }