ICP  1
vms_convert.cpp
Go to the documentation of this file.
1 /*
2  * Module: vms_convert
3  * Author: Freddie Akeroyd, ISIS
4  * Purpose: Routines to convert from VAX to local integer representations
5  *
6  * $Id: vms_convert.cpp 859 2010-10-29 12:18:36Z FreddieAkeroyd $
7  */
8 #include "stdafx.h"
9 #include "vms_convert.h"
10 
11 /*
12  * Byte swaps for int and short
13  */
14 
15 
16 #if 0
17 inline unsigned swap_int(unsigned a)
18 {
19  union { unsigned u; unsigned char c[4]; } temp;
20  unsigned char ctemp;
21  temp.u = a;
22  ctemp = temp.c[0]; temp.c[0] = temp.c[3]; temp.c[3] = ctemp;
23  ctemp = temp.c[1]; temp.c[1] = temp.c[2]; temp.c[2] = ctemp;
24  return temp.u;
25 }
26 #endif
27 
28 #define swap_int(a) ( ((a) << 24) | \
29  (((a) << 8) & 0x00ff0000) | \
30  (((a) >> 8) & 0x0000ff00) | \
31  ((unsigned long)(a) >>24) )
32 
33 #define swap_short(a) ( ((a & 0xff) << 8) | ((unsigned short)(a) >> 8) )
34 
35 /* VAXes are little endian */
36 
37 unsigned short local_to_vax_short(const unsigned short* s)
38 {
39 #if defined(WORDS_BIGENDIAN)
40  return swap_short(*s);
41 #else
42  return *s;
43 #endif /* WORDS_BIGENDIAN */
44 }
45 
46 unsigned short vax_to_local_short(const unsigned short* s)
47 {
48 #if defined(WORDS_BIGENDIAN)
49  return swap_short(*s);
50 #else
51  return *s;
52 #endif /* WORDS_BIGENDIAN */
53 }
54 
55 unsigned local_to_vax_int(const fort_int* i)
56 {
57 #if defined(WORDS_BIGENDIAN)
58  return swap_int(*(unsigned*)i);
59 #else
60  return *i;
61 #endif /* WORDS_BIGENDIAN */
62 }
63 
64 unsigned vax_to_local_int(const fort_int* i)
65 {
66 #if defined(WORDS_BIGENDIAN)
67  return swap_int(*(unsigned*)i);
68 #else
69  return *i;
70 #endif /* WORDS_BIGENDIAN */
71 }
72 
73 void local_to_vax_shorts(unsigned short* sa, const int* n)
74 {
75 #if defined(WORDS_BIGENDIAN)
76  int i;
77  for(i=0; i<*n; i++)
78  {
79  sa[i] = swap_short(sa[i]);
80  }
81 #endif /* WORDS_BIGENDIAN */
82  return;
83 }
84 
85 void vax_to_local_shorts(unsigned short* sa, const int* n)
86 {
87 #if defined(WORDS_BIGENDIAN)
88  int i;
89  for(i=0; i<*n; i++)
90  {
91  sa[i] = swap_short(sa[i]);
92  }
93 #endif /* WORDS_BIGENDIAN */
94  return;
95 }
96 
97 void local_to_vax_ints(fort_int* ia, const fort_int* n)
98 {
99 #if defined(WORDS_BIGENDIAN)
100  int i;
101  unsigned *uia = (unsigned*)ia;
102  for(i=0; i<*n; i++)
103  {
104  uia[i] = swap_int(uia[i]);
105  }
106 #endif /* WORDS_BIGENDIAN */
107  return;
108 }
109 
111 {
112 #if defined(WORDS_BIGENDIAN)
113  int i;
114  unsigned *uia = (unsigned*)ia;
115  for(i=0; i<*n; i++)
116  {
117  uia[i] = swap_int(uia[i]);
118  }
119 #endif /* WORDS_BIGENDIAN */
120  return;
121 }
122 
123 
124 /*
125  * determine a few things we need to know to write machine independent data
126  */
127 
128 #ifndef __VMS
129 #define IEEEFP 1
130 #endif /* __VMS */
131 
132 #ifdef __VMS
133 /* set up codes for use of CVT$CONVERT_FLOAT */
134 # if __IEEE_FLOAT
135 # define IEEEFP 1
136 # define VMS_FLOAT_NATIVE CVT$K_IEEE_S
137 # define VMS_DOUBLE_NATIVE CVT$K_IEEE_T
138 # elif __D_FLOAT
139 # define VAXFP 1
140 # define VMS_FLOAT_NATIVE CVT$K_VAX_F
141 # define VMS_DOUBLE_NATIVE CVT$K_VAX_D
142 # elif __G_FLOAT
143 # define VAXFP 1
144 # define VMS_FLOAT_NATIVE CVT$K_VAX_F
145 # define VMS_DOUBLE_NATIVE CVT$K_VAX_G
146 # else
147 # error Cannot determine VMS floating point format
148 # endif
149 #endif /* __VMS */
150 
151 #if WORDS_BIGENDIAN
152 
153 /* What IEEE single precision floating point looks like on local machine */
154 struct ieee_single {
155  unsigned int sign : 1;
156  unsigned int exp : 8;
157  unsigned int mantissa: 23;
158 };
159 
160 /* Vax single precision floating point */
161 struct vax_single {
162  unsigned int mantissa2 : 16;
163  unsigned int sign : 1;
164  unsigned int exp : 8;
165  unsigned int mantissa1 : 7;
166 };
167 
168 #else
169 
170 /* What IEEE single precision floating point looks like on local machine */
171 struct ieee_single {
172  unsigned int mantissa: 23;
173  unsigned int exp : 8;
174  unsigned int sign : 1;
175 };
176 
177 /* Vax single precision floating point */
178 struct vax_single {
179  unsigned int mantissa1 : 7;
180  unsigned int exp : 8;
181  unsigned int sign : 1;
182  unsigned int mantissa2 : 16;
183 };
184 
185 #endif /* WORDS_BIGENDIAN */
186 
187 #define VAX_SNG_BIAS 0x81
188 #define IEEE_SNG_BIAS 0x7f
189 
190 static const struct sgl_limits_struct {
191  struct vax_single s;
193 } sgl_limits[2] = {
194  {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
195  { 0x0, 0xff, 0x0 }}, /* Max IEEE */
196  {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
197  { 0x0, 0x0, 0x0 }} /* Min IEEE */
198 };
199 
200 #define mmax sgl_limits[0]
201 #define mmin sgl_limits[1]
202 
203 #if WORDS_BIGENDIAN
204 
205 /* What IEEE double precision floating point looks like */
206 struct ieee_double {
207  unsigned int mantissa2 : 32;
208  unsigned int sign : 1;
209  unsigned int exp : 11;
210  unsigned int mantissa1 : 20;
211 };
212 
213 /* Vax double precision floating point */
214 struct vax_double {
215  unsigned int mantissa4 : 16;
216  unsigned int mantissa3 : 16;
217  unsigned int mantissa2 : 16;
218  unsigned int sign : 1;
219  unsigned int exp : 8;
220  unsigned int mantissa1 : 7;
221 };
222 
223 #else
224 
225 /* What IEEE double precision floating point looks like */
226 struct ieee_double {
227  unsigned int mantissa1 : 20;
228  unsigned int exp : 11;
229  unsigned int sign : 1;
230  unsigned int mantissa2 : 32;
231 };
232 
233 /* Vax double precision floating point */
234 struct vax_double {
235  unsigned int mantissa1 : 7;
236  unsigned int exp : 8;
237  unsigned int sign : 1;
238  unsigned int mantissa2 : 16;
239  unsigned int mantissa3 : 16;
240  unsigned int mantissa4 : 16;
241 };
242 
243 #endif /* WORDS_BIGENDIAN */
244 
245 
246 #define VAX_DBL_BIAS 0x81
247 #define IEEE_DBL_BIAS 0x3ff
248 #define MASK(nbits) ((1 << nbits) - 1)
249 
250 static struct dbl_limits {
251  struct vax_double d;
253 } dbl_limits[2] = {
254  {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
255  { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
256  {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
257  { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
258 };
259 
260 /* VAX is little endian, so we may need to flip */
261 #if WORDS_BIGENDIAN
262  static int maybe_flip_bytes(void* p, size_t n)
263  {
264  unsigned i;
265  unsigned char c_tmp, *c_p = (unsigned char*)p;
266  for(i=0; i<n/2; i++)
267  {
268  c_tmp = c_p[i];
269  c_p[i] = c_p[n-i-1];
270  c_p[n-i-1] = c_tmp;
271  }
272  return 0;
273  }
274 #else
275 # define maybe_flip_bytes(__p,__n)
276 #endif /* WORDS_BIGENDIAN */
277 
278 /* convert VAX F FLOAT into a local IEEE single float */
279 static int vax_to_ieee_float(float* fp)
280 {
281  struct ieee_single is;
282  struct vax_single vs;
283  struct sgl_limits_struct;
284  maybe_flip_bytes(fp, sizeof(float));
285  vs = *((struct vax_single *)fp);
286  switch(vs.exp){
287  case 0 :
288  /* all vax float with zero exponent map to zero */
289  is = mmin.ieee ;
290  break ;
291  case 2 :
292  case 1 :
293  /* These will map to subnormals */
294  is.exp = 0 ;
295  is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
296  /* lose some precision */
297  is.mantissa >>= 3 - vs.exp ;
298  is.mantissa += (1 << (20 + vs.exp)) ;
299  break ;
300  case 0xff : /* mmax.s.exp */
301  if( vs.mantissa2 == mmax.s.mantissa2
302  && vs.mantissa1 == mmax.s.mantissa1)
303  {
304  /* map largest vax float to ieee infinity */
305  is = mmax.ieee ;
306  break ;
307  } /* else, fall thru */
308  default :
309  is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
310  is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
311  }
312 
313  is.sign = vs.sign;
314  *fp = *((float*)&is);
315  return 0;
316 }
317 
318 /* convert a local IEEE single float to little endian VAX F FLOAT format */
319 static int ieee_to_vax_float(float* fp)
320 {
321  struct ieee_single is;
322  struct vax_single vs;
323  struct sgl_limits_struct;
324  is = *((struct ieee_single*)fp);
325  switch(is.exp) {
326  case 0 :
327  if(is.mantissa == mmin.ieee.mantissa)
328  {
329  vs = mmin.s ;
330  } else {
331  unsigned tmp = is.mantissa >> 20 ;
332  if(tmp >= 4) {
333  vs.exp = 2 ;
334  } else if (tmp >= 2) {
335  vs.exp = 1 ;
336  } else {
337  vs = mmin.s ;
338  break ;
339  } /* else */
340  tmp = is.mantissa - (1 << (20 + vs.exp )) ;
341  tmp <<= 3 - vs.exp ;
342  vs.mantissa2 = tmp ;
343  vs.mantissa1 = (tmp >> 16);
344  }
345  break ;
346  case 0xfe :
347  case 0xff :
348  vs = mmax.s ;
349  break ;
350  default :
351  vs.exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
352  vs.mantissa2 = is.mantissa;
353  vs.mantissa1 = (is.mantissa >> 16);
354  }
355 
356  vs.sign = is.sign;
357  *fp = *((float*)&vs);
358  maybe_flip_bytes(fp, sizeof(float)); /* Make little endian */
359  return 0;
360 }
361 
362 void vaxf_to_local(float *val, const int *n, int *errcode)
363 {
364 #if defined(VAXFP)
365 #include <cvtdef>
366 #include <cvt$routines>
367 #endif
368  int i;
369  *errcode=0;
370 #if defined(VAXFP)
371  /* Do a null conversion to replace invalid values (prevents floating exceptions later on) */
372  for(i=0; i<*n; i++)
373  {
374  if ( cvt$ftof(val+i, CVT$K_VAX_F, val+i, CVT$K_VAX_F, CVT$M_REPORT_ALL) != CVT$K_NORMAL )
375  {
376  val[i] = 0.0; /* Fix with a safe value when status shows an invalid real is being converted */
377  }
378  }
379 #elif defined(IEEEFP)
380  for(i=0; i<*n; i++)
381  {
382  if (vax_to_ieee_float(i+val) != 0)
383  {
384  *errcode=1;
385  }
386  }
387 #else
388 #error Unknown floating point format
389 #endif
390  return;
391 }
392 
393 void local_to_vaxf(float *val, const int *n, int *errcode)
394 {
395  int i;
396  *errcode=0;
397 #if defined(VAXFP)
398  /* nothing required */
399 #elif defined(IEEEFP)
400  for(i=0; i<*n; i++)
401  {
402  if (ieee_to_vax_float(i+val) != 0)
403  {
404  *errcode=1;
405  }
406  }
407 #else
408 #error Unknown floating point format
409 #endif
410  return;
411 }
412 
413 void ieee_float_to_local(float *val, const int *n, int *errcode)
414 {
415 #if defined(IEEEFP)
416  *errcode=0;
417 #elif defined(VAXFP)
418  int i;
419  *errcode=0;
420  for(i=0; i<*n; i++)
421  {
422 // if (ieee_to_vax_float(i+val) != 0)
423  if ( cvt$ftof(val+i, CVT$K_IEEE_S, val+i, VMS_FLOAT_NATIVE, 0) != CVT$K_NORMAL )
424  {
425  *errcode=1;
426  val[i] = 0.0;
427  }
428  }
429 #else
430 #error Unknown floating point format
431 #endif
432  return;
433 }
434 
435 void ieee_double_to_local(double *val, const int *n, int *errcode)
436 {
437 #if defined(IEEEFP)
438  *errcode=0;
439 #elif defined(VAXFP)
440 #include <cvtdef>
441 #include <cvt$routines>
442  int i;
443  *errcode=0;
444  for(i=0; i<*n; i++)
445  {
446  if ( cvt$ftof(val+i, CVT$K_IEEE_T, val+i, VMS_DOUBLE_NATIVE, CVT$M_REPORT_ALL) != CVT$K_NORMAL )
447  {
448  val[i] = 0.0;
449  *errcode=1;
450  }
451  }
452 #else
453 #error Unknown floating point format
454 #endif
455  return;
456 }
457 
458 void local_to_ieee_float(float *val, const int *n, int *errcode)
459 {
460 #if defined(IEEEFP)
461  *errcode=0;
462 #elif defined(VAXFP)
463 #include <cvtdef>
464 #include <cvt$routines>
465  int i;
466  *errcode=0;
467  for(i=0; i<*n; i++)
468  {
469  if ( cvt$ftof(val+i, VMS_FLOAT_NATIVE, val+i, CVT$K_IEEE_S, CVT$M_REPORT_ALL) != CVT$K_NORMAL )
470  {
471  val[i] = 0.0;
472  *errcode=1;
473  }
474  }
475 #else
476 #error Unknown floating point format
477 #endif
478  return;
479 }
480 
481 void local_to_ieee_double(double *val, const int *n, int *errcode)
482 {
483 #if defined(IEEEFP)
484  *errcode=0;
485 #elif defined(VAXFP)
486  int i;
487  *errcode=0;
488  for(i=0; i<*n; i++)
489  {
490  if ( cvt$ftof(val+i, VMS_DOUBLE_NATIVE, val+i, CVT$K_IEEE_T, CVT$M_REPORT_ALL) != CVT$K_NORMAL )
491  {
492  val[i] = 0.0;
493  *errcode=1;
494  }
495  }
496 #else
497 #error Unknown floating point format
498 #endif
499  return;
500 }
501 
502 #if 0
503 static unsigned char flip_bits(unsigned char cc)
504 {
505  static int init = 0;
506  static unsigned char ct[256];
507  if (!init)
508  {
509  unsigned _i,_j;
510  for(_i=0; _i<256; _i++)
511  {
512  ct[_i] = 0;
513  for(_j=0; _j<8; _j++)
514  {
515  if (_i & (1<<_j)) { ct[_i] |= (128 >> _j); }
516  }
517  }
518  init = 1;
519  }
520  return ct[cc];
521 }
522 #endif
unsigned int sign
unsigned int exp
unsigned short vax_to_local_short(const unsigned short *s)
Definition: vms_convert.cpp:46
void ieee_float_to_local(float *val, const int *n, int *errcode)
void vax_to_local_shorts(unsigned short *sa, const int *n)
Definition: vms_convert.cpp:85
#define swap_int(a)
Definition: vms_convert.cpp:28
void local_to_ieee_float(float *val, const int *n, int *errcode)
#define mmax
unsigned int mantissa4
unsigned int mantissa
unsigned local_to_vax_int(const fort_int *i)
Definition: vms_convert.cpp:55
#define mmin
void local_to_vaxf(float *val, const int *n, int *errcode)
unsigned int sign
unsigned int exp
void local_to_vax_ints(fort_int *ia, const fort_int *n)
Definition: vms_convert.cpp:97
unsigned int mantissa1
unsigned int mantissa1
void vax_to_local_ints(fort_int *ia, const fort_int *n)
#define IEEE_SNG_BIAS
static int vax_to_ieee_float(float *fp)
unsigned vax_to_local_int(const fort_int *i)
Definition: vms_convert.cpp:64
unsigned int sign
static struct sgl_limits_struct sgl_limits[2]
#define maybe_flip_bytes(__p, __n)
void local_to_ieee_double(double *val, const int *n, int *errcode)
unsigned int exp
unsigned int mantissa2
static int ieee_to_vax_float(float *fp)
unsigned int mantissa2
struct vax_double d
void ieee_double_to_local(double *val, const int *n, int *errcode)
unsigned int sign
unsigned int mantissa1
void local_to_vax_shorts(unsigned short *sa, const int *n)
Definition: vms_convert.cpp:73
struct ieee_double ieee
struct ieee_single ieee
unsigned int mantissa2
unsigned int exp
#define swap_short(a)
Definition: vms_convert.cpp:33
unsigned int mantissa3
int fort_int
Definition: vms_convert.h:4
void vaxf_to_local(float *val, const int *n, int *errcode)
unsigned short local_to_vax_short(const unsigned short *s)
Definition: vms_convert.cpp:37
#define VAX_SNG_BIAS
struct vax_single s