PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/wrfv2_fire/external/io_grib1/MEL_grib1/pack_spatial.c

http://github.com/jbeezley/wrf-fire
C | 652 lines | 257 code | 56 blank | 339 comment | 52 complexity | 25355c1a41c79f4e2f25f1c4a3f7ad45 MD5 | raw file
Possible License(s): AGPL-1.0
  1. /* 20jun97/atn: always scaling data up whether dsf is -/+;
  2. */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #ifdef XT3_Catamount
  8. #include <features.h>
  9. #undef htonl
  10. #define htonl(x) swap_byte4(x)
  11. #elif defined(_WIN32)
  12. #include <Winsock2.h>
  13. #else
  14. #include <netinet/in.h>
  15. #endif
  16. #include "dprints.h" /* for dprints */
  17. #include "gribfuncs.h" /* prototypes */
  18. #include "isdb.h" /* WORD_BIT_CNT defn */
  19. /*
  20. ****************************************************************
  21. * A. FUNCTION: pack_spatial
  22. * pack gridded data values into a bitstream
  23. *
  24. * INTERFACE:
  25. * int pack_spatial (pt_cnt, bit_cnt, pack_null, fbuff, ppbitstream,
  26. * dec_scl_fctr, BDSlength, errmsg)
  27. *
  28. * ARGUMENTS (I=input, O=output, I&O=input and output):
  29. * (I) long *pt_cnt; count of points in grid
  30. * (I) long *bit_cnt; count of bits to pack value in.
  31. * will be calculated if set to zero
  32. * (I) float *pack_null; parameter value for null (huge number)
  33. * (I&O) float *fbuff; array containing grid values to pack
  34. * returned scaled up by Decimal Scale Factor
  35. * (O) unsigned long **ppbitstream; Null upon entry;
  36. * returned pointing to new Storage
  37. * holding packed bitstream;
  38. * (I) short dec_scl_fctr; decimal scale factor to apply to data
  39. * (O) long *BDSlength; updated with #bytes in packed bitstream
  40. * (O) char *errmsg returned filled if error occurred
  41. *
  42. * RETURN CODE:
  43. * 0> success, ppbitstream contains packed values
  44. * else> error: errmsg holds msg;
  45. ****************************************************************
  46. */
  47. #if PROTOTYPE_NEEDED
  48. int pack_spatial ( long *pt_cnt,
  49. unsigned short *bit_cnt,
  50. float *pack_null,
  51. float *fbuff,
  52. unsigned long **ppbitstream,
  53. short dec_scl_fctr,
  54. long *BDSlength,
  55. char *errmsg)
  56. #else
  57. int pack_spatial ( pt_cnt, bit_cnt, pack_null, fbuff, ppbitstream,
  58. dec_scl_fctr, BDSlength, errmsg)
  59. long *pt_cnt;
  60. unsigned short *bit_cnt;
  61. float *pack_null;
  62. float *fbuff;
  63. unsigned long **ppbitstream;
  64. short dec_scl_fctr;
  65. long *BDSlength;
  66. char *errmsg;
  67. #endif
  68. {
  69. char *func="pack_spatial";
  70. long ipt; /* index over points */
  71. int null_flag; /* flag indicating presence of null values */
  72. int bit1; /* starting bit in current word */
  73. int empty; /* number of empty bits in word */
  74. int diff; /* difference of empty - bit1 */
  75. long max_value; /* max value storable in bit_cnt bits */
  76. unsigned long itemp; /* temporary unsigned integer */
  77. unsigned long *bstr; /* pointer running across bitstream */
  78. int pack_bit_cnt; /* count of bits to pack parameter values */
  79. int unused_bit_cnt; /* count of unused bits for i2 words */
  80. /*long byte4_cnt; /- count of bytes using i4 words */
  81. long byte2_cnt; /* count of bytes using i2 words */
  82. short scl_fctr; /* scaling factor for grid values */
  83. double pow_scl; /* 2 ** (-scl_fctr) */
  84. double pwr10toD; /* 10 ** (D) */
  85. float reference; /* reference = minimum value in grid */
  86. float max_grid; /* maximum value in grid */
  87. float ftemp; /* temporary float containing grid value */
  88. unsigned long *pBitstream;
  89. unsigned long grib_local_ibm();
  90. int wordnum;
  91. int zero_cnt;
  92. int prec_too_high = 0;
  93. unsigned char bdshdr[14]; /* Character array to temporarily hold bds
  94. * header */
  95. int hdrwords;
  96. DPRINT1 ( "Entering %s....\n", func );
  97. /*
  98. *
  99. * A.1 IF (no data in grid) THEN
  100. * PRINT message
  101. * RETURN Stat= -1
  102. * ENDIF
  103. */
  104. if (*pt_cnt <= 0) {
  105. DPRINT2 ("%s; invalid pt_cnt = %d\n", func,*pt_cnt);
  106. sprintf(errmsg, "%s; invalid pt_cnt = %d\n", func,*pt_cnt);
  107. return (-1);
  108. }
  109. /*
  110. *
  111. * A.2 IF (number of bits to pack into is greater than 30) THEN
  112. * PRINT message
  113. * RETURN Stat= -1
  114. * ENDIF
  115. * SET pack_bit_cnt for local use
  116. */
  117. if ( *bit_cnt > 30 ) {
  118. DPRINT2 ("%s; invalid bit_cnt = %d\n", func,*bit_cnt);
  119. sprintf(errmsg, "%s; invalid bit_cnt = %d\n", func,*bit_cnt);
  120. return (-1);
  121. }
  122. pack_bit_cnt = (int) *bit_cnt;
  123. DPRINT1 (" use Pack_bit_cnt= %d\n", pack_bit_cnt);
  124. /*
  125. *
  126. * A.3 FOR (each data point) DO
  127. * SCALE all values of data array !multiply by 10**DSF
  128. * ENDDO
  129. */
  130. pwr10toD= pow ( 10., (double) dec_scl_fctr );
  131. for (ipt=0; ipt < *pt_cnt; ipt++) fbuff[ipt] *= pwr10toD;
  132. DPRINT2 (" Decimal Scale Fctr= %d, scale data by 10**dsf "\
  133. "(Fbuff *= %lf)\n", dec_scl_fctr, pwr10toD);
  134. /*
  135. *
  136. * A.4 INIT reference, max_grid, null_flag
  137. */
  138. reference = 1.e30;
  139. max_grid = -1.e30;
  140. null_flag = 0;
  141. /*
  142. *
  143. * A.5 FOR (each data point) DO
  144. * IF (value < reference) THEN
  145. * SET reference to this value !smallest value
  146. * ENDIF
  147. * IF (value > max_grid AND not a missing value ) THEN
  148. * SET max_grid to this value !largest value
  149. * ENDIF
  150. * IF (value >= missing value ) THEN
  151. * SET null_flag to 1 !grid contains nulls
  152. * ENDIF
  153. * ENDDO
  154. Find reference (minimum) and maximum values of the grid points
  155. */
  156. for (ipt = 0; ipt < *pt_cnt; ipt++) {
  157. ftemp = *(fbuff+ipt);
  158. if (ftemp < reference) reference = ftemp; /* REF is SCALED UP */
  159. if (ftemp > max_grid && ftemp < *pack_null) max_grid = ftemp;
  160. if (ftemp >= *pack_null) null_flag = 1;
  161. }
  162. DPRINT2 (" Max before taking out Ref =%.4lf\n Null flag=%d\n",
  163. max_grid, null_flag);
  164. /* Compute maximum range of grid (max_grid - reference) */
  165. /*
  166. *
  167. * A.6 IF (max value is same as smallest value AND
  168. * null_flag is zero) THEN
  169. * CLEAR pack_bit_cnt !constant values, no nulls
  170. * CLEAR max_grid !set grid range to 0
  171. */
  172. if (((max_grid - reference) < 1.0) && null_flag == 0) {
  173. pack_bit_cnt = 0;
  174. max_grid = 0;
  175. /*
  176. * A.6.a ELSE IF (max value is same as smallest value AND
  177. * null_flag is set) THEN
  178. * SET max_grid to 1 !const values, some nulls
  179. */
  180. } else if (((max_grid - reference) < 1.0) && null_flag == 1) {
  181. max_grid = 1.;
  182. /*
  183. * A.6.b ELSE IF (max value <= -1.e29 AND null_flag is set) THEN
  184. * PRINT message
  185. * RETURN Stat= -1
  186. */
  187. } else if (max_grid <= -1.e29 && null_flag == 1) {
  188. DPRINT1 ("%s; Grid contains all NULLS\n",func);
  189. sprintf(errmsg, "%s; Grid contains all NULLS\n",func);
  190. return (-1);
  191. /*
  192. * A.6.c ELSE IF (max value not equal to reference) THEN
  193. * SET max_grid (max_grid-reference) !non-constant values w/wo nulls
  194. */
  195. } else if (max_grid != reference) {
  196. max_grid -= reference;
  197. /*
  198. * A.6 ENDIF
  199. */
  200. }
  201. /*
  202. *
  203. * A.7 DEBUG print grid range and reference value
  204. */
  205. DPRINT2 ( " Reference = %f\n Max_grid (range) = %f\n",
  206. reference, max_grid);
  207. /* Find minimum number of bits to pack data */
  208. /*
  209. *
  210. * A.8.a IF (grid range is not zero) THEN
  211. */
  212. if ( max_grid != 0 )
  213. {
  214. /*
  215. *
  216. * A.8.a.1 DEBUG print input bit width
  217. * IF (input bit_num is zero) THEN
  218. * CALCULATE number of bits needed to store grid range
  219. * DEBUG print calculated bit count
  220. * ENDIF
  221. */
  222. DPRINT1 ( " Input bit cnt = %d\n", pack_bit_cnt );
  223. if ( pack_bit_cnt == 0 )
  224. {
  225. pack_bit_cnt = (int)(floor(log10((double)max_grid) / log10(2.)) +1);
  226. DPRINT1 ( " Calculated bit cnt = %d\n", pack_bit_cnt );
  227. }
  228. if ( (pack_bit_cnt < 0) || (pack_bit_cnt > 30) )
  229. {
  230. DPRINT1 ("%s: Calculated bit count OUT OF RANGE [0 - 30] !!\n", func);
  231. sprintf (errmsg, "%s: Calculated bit count OUT OF RANGE!! bit_cnt: %d max: %f\n", func,pack_bit_cnt,max_grid);
  232. return (-1);
  233. }
  234. /*
  235. *
  236. * A.8.a.2 CALCULATE various byte counters
  237. * !itemp: #bits required for header + grid
  238. * !Byte2_cnt: #bytes rounded up to next 2-byte bdry
  239. * !Byte4_cnt: #bytes rounded up to next 4-byte bdry
  240. * !Unused_bit_cnt: #unused bits at end using byte2_cnt
  241. * DEBUG print expected length and unused bits
  242. */
  243. itemp = *pt_cnt * pack_bit_cnt + 11 * BYTE_BIT_CNT;
  244. byte2_cnt = (long) ceil(((double) itemp / BYTE_BIT_CNT) / 2.) * 2;
  245. /*byte4_cnt = (long) ceil(((double) itemp / BYTE_BIT_CNT) / 4.) * 4;*/
  246. unused_bit_cnt = byte2_cnt * BYTE_BIT_CNT - itemp;
  247. DPRINT1 ( " Calculated length = %ld bytes (Rnd2)\n", byte2_cnt);
  248. DPRINT1 ( " Bitstream padding = %ld bits\n",unused_bit_cnt);
  249. /*
  250. *
  251. * A.8.a.3 CALCULATE maximum storable value
  252. * CALCULATE scl_fctr required to fit grid range
  253. * into available bit width
  254. */
  255. max_value = (long) pow(2., (double) pack_bit_cnt) - 1;
  256. if (max_value < 2) max_value = 2;
  257. scl_fctr = -(short) floor(log10((double) (max_value-1) /
  258. (double) max_grid) / log10(2.));
  259. pow_scl = pow(2., (double) -scl_fctr);
  260. DPRINT1 ( " Calculated Binary scale = %d\n",scl_fctr);
  261. }
  262. /*
  263. *
  264. * A.8.b ELSE !max_grid = 0, all zero data or constant values
  265. * SET number of bits to pack to zero
  266. * SET lengths to 12 bytes
  267. * SET unused bits to 8 (1 byte of padding)
  268. * SET scl_fctr to 0
  269. * DEBUG print constant grid
  270. * ENDIF
  271. */
  272. else
  273. {
  274. pack_bit_cnt = 0;
  275. byte2_cnt = 12;
  276. /*byte4_cnt = 12;*/
  277. unused_bit_cnt = 8;
  278. scl_fctr = 0;
  279. DPRINT0 ( " Constant grid. Using bit cnt = 0\n");
  280. }
  281. /*
  282. *
  283. * A.9 MALLOC space for bitstream (Rnd2_cnt)
  284. * IF (failed) THEN
  285. * PRINT error mesg
  286. * RETURN Stat= 999;
  287. * ENDIF
  288. */
  289. pBitstream = ( unsigned long * ) malloc ( sizeof( unsigned long ) *
  290. byte2_cnt );
  291. if ( !pBitstream )
  292. {
  293. DPRINT1 ("%s: MAlloc failed pBitstream\n", func );
  294. sprintf(errmsg, "%s: MAlloc failed pBitstream\n", func );
  295. return (999);
  296. }
  297. /*
  298. *
  299. * A.10 SET ptr to bitstream
  300. * UPDATE bit_cnt for input structure
  301. */
  302. *bit_cnt = (unsigned short) pack_bit_cnt;
  303. DPRINT1 (" Updated input bit cnt to %d\n", *bit_cnt);
  304. bstr = pBitstream;
  305. /*
  306. *
  307. * A.11 ZERO out entire bitstream
  308. */
  309. zero_cnt = ceil(byte2_cnt / (float)sizeof(long)) * sizeof(long);
  310. memset ((void *)pBitstream, '\0', zero_cnt);
  311. /*
  312. *
  313. * A.12 PUT packing info into first 11 bytes:
  314. * NOTE: The Table 11 Flag stored in the first
  315. * 4 bits of Octet 4 is HARDCODED to 0000.
  316. * This implies Simple packing of float
  317. * grid point data with no additional flags.
  318. * Octet 1-3 = Byte2_cnt
  319. * Octet 4 = Table 11 Flag & unused_bit_cnt
  320. * Octet 5-6 = Scl_fctr
  321. * Octet 7-10 = Reference truncated to DSF precision
  322. * Octet 11 = Pack_bit_cnt
  323. * Octet 12 = Bitstream starts (bit 25 of word 3)
  324. */
  325. set_bytes_u(byte2_cnt, 3, bdshdr);
  326. itemp = unused_bit_cnt;
  327. set_bytes_u(itemp, 1, bdshdr+3);
  328. set_bytes_u(scl_fctr, 2, bdshdr+4);
  329. DPRINT1 (" Reference (%f) ", reference);
  330. reference = floor((double) reference + .5);
  331. DPRINT1 ("truncated to DSF precision= %lf\n", reference);
  332. itemp = grib_local_ibm(reference);
  333. DPRINT1 (" Reference converted to local IBM format= 0x%x\n", itemp);
  334. set_bytes_u(itemp, 4, bdshdr+6);
  335. set_bytes_u(pack_bit_cnt, 1, bdshdr+10);
  336. bit1 = 25;
  337. memcpy(bstr,bdshdr,11);
  338. /*
  339. * For non-internet byte order machines (i.e., linux),
  340. * We reverse the order of the last byte in the bds header, since
  341. * it will be reversed once again below.
  342. */
  343. hdrwords = 11/(WORD_BIT_CNT/BYTE_BIT_CNT);
  344. set_bytes_u(bstr[hdrwords], WORD_BIT_CNT/BYTE_BIT_CNT,
  345. (char *)(bstr+hdrwords) );
  346. bstr += hdrwords;
  347. /*
  348. itemp = unused_bit_cnt;
  349. *bstr = (byte2_cnt << 8) | itemp;
  350. bstr++;
  351. *bstr = scl_fctr;
  352. DPRINT1 (" Reference (%f) ", reference);
  353. reference = floor((double) reference + .5);
  354. DPRINT1 ("truncated to DSF precision= %lf\n", reference);
  355. itemp = grib_local_ibm(reference);
  356. DPRINT1 (" Reference converted to local IBM format= 0x%x\n", itemp);
  357. *bstr = (*bstr << 16) | (itemp >> 16);
  358. bstr++;
  359. *bstr = (itemp << 16) | (pack_bit_cnt << 8);
  360. bit1 = 25; */ /* starting bit within current bstr word */
  361. /*
  362. *
  363. * A.13 IF (grid values are not constant) THEN
  364. */
  365. if (pack_bit_cnt > 0) {
  366. /*
  367. * A.13.1 SET empty value
  368. */
  369. empty = WORD_BIT_CNT - pack_bit_cnt + 1;
  370. for (ipt=0; ipt < 5; ipt++) DPRINT4 (
  371. " ITEMP= (*(fbuff+ipt) - reference) * pow_scl + .5=\n"\
  372. " (%lf -%lf) * %lf + .5 = %lf\n",
  373. *(fbuff+ipt), reference, pow_scl,
  374. (*(fbuff+ipt) - reference) * pow_scl + .5);
  375. /*
  376. * A.13.2 FOR (each point in bitstream) DO
  377. */
  378. for (ipt = 0; ipt < *pt_cnt; ipt++) {
  379. /*
  380. * A.13.2.1 IF ( data value < pack_null) THEN
  381. * SET itemp to (value - reference) * pow_scl + .5;
  382. * ELSE
  383. * SET itemp to max value;
  384. * ENDIF
  385. */
  386. if (*(fbuff+ipt) < *pack_null) {
  387. itemp = (*(fbuff+ipt) - reference) * pow_scl + .5;
  388. } else {
  389. itemp = max_value;
  390. DPRINT1 ("%s: Setting to max_value: Precision may be too high !!\n", func);
  391. sprintf (errmsg, "%s: Setting grid point to max value, precision may be too high", func);
  392. /* return (-1); */
  393. }
  394. /*
  395. * A.13.2.2 COMPUTE if data point can fit in current word
  396. */
  397. diff = empty - bit1;
  398. /*
  399. * A.13.2.3.a IF (data point falls within word ) THEN
  400. * SHIFT value to the correct bit position
  401. * COMBINE it with data in current word of bitstream
  402. * CALCULATE starting bit in curr word for next time
  403. */
  404. if (diff > 0)
  405. {
  406. *bstr |= itemp << diff;
  407. bit1 += pack_bit_cnt;
  408. }
  409. /*
  410. * A.13.2.3.b ELSE IF (data point ends at word boundary) THEN
  411. * COMBINE value with data in current word of bitstream
  412. * SET starting bit to 1
  413. * BUMP word counter in bitstream up by 1 word
  414. */
  415. else if (diff == 0)
  416. {
  417. *bstr |= itemp;
  418. bit1 = 1;
  419. bstr++;
  420. }
  421. /*
  422. * A.13.2.3.c ELSE !point crosses word boundary
  423. * STORE "diff" bits of value in current word of bitstream
  424. * BUMP word counter in bitstream up by 1 word
  425. * STORE remaining bits of value in next word
  426. * CALCULATE starting bit in curr word for next time
  427. * ENDIF !word location check
  428. */
  429. else /* pixel crosses word boundary */
  430. {
  431. *bstr |= itemp >> -diff;
  432. bstr++;
  433. *bstr |= itemp << (WORD_BIT_CNT + diff);
  434. bit1 = -diff + 1;
  435. }
  436. /*
  437. * A.13.2 ENDFOR loop over grid points
  438. */
  439. }
  440. /*
  441. * A.13 ENDIF (pack_bit_cnt > 0)
  442. */
  443. }
  444. /* For little endian machines, swap the bytes in the bstr pointer */
  445. /* for (wordnum = 0; */
  446. for (wordnum = hdrwords;
  447. wordnum < ceil(byte2_cnt/(float)(WORD_BIT_CNT/BYTE_BIT_CNT));
  448. wordnum++) {
  449. set_bytes_u(pBitstream[wordnum], WORD_BIT_CNT/BYTE_BIT_CNT,
  450. (char *)(pBitstream+wordnum) );
  451. }
  452. /*
  453. *
  454. * A.14 ASSIGN bitstream block to ppbitstream pointer
  455. * SET BDSlength (size rnded to next 2 byte boundary)
  456. * RETURN Status 0 ! success
  457. */
  458. *ppbitstream = pBitstream;
  459. *BDSlength = (long) byte2_cnt;
  460. DPRINT1 ("Exiting pack_spatial, BDS len=%ld, Status=0\n" , *BDSlength);
  461. if (prec_too_high) {
  462. fprintf(stderr,"pack_spatial: Warning: Precision for a parameter may be too high in gribmap.txt\n");
  463. }
  464. return (0);
  465. /*
  466. * END OF FUNCTION
  467. *
  468. */
  469. }
  470. /*
  471. *
  472. **************************************************************
  473. * B. FUNCTION grib_local_ibm
  474. * convert local_float from local floating point to
  475. * IBM floating point stored in a 4-byte integer.
  476. *
  477. * INTERFACE:
  478. * unsigned long grib_local_ibm (local_float)
  479. *
  480. * ARGUMENTS (I=input, O=output, I&O=input and output):
  481. * (I) double local_float float value in local format
  482. *
  483. * RETURNS:
  484. * the actual IBM floating point value
  485. **************************************************************
  486. *
  487. */
  488. #if PROTOTYPE_NEEDED
  489. unsigned long grib_local_ibm (double local_float)
  490. #else
  491. unsigned long grib_local_ibm (local_float)
  492. double local_float;
  493. #endif
  494. {
  495. long a, b;
  496. unsigned long ibm_float;
  497. /*
  498. *
  499. * B.1.a IF (local float value is zero) THEN
  500. * SET the ibm float to zero too
  501. */
  502. if (local_float == 0.) {
  503. ibm_float = 0;
  504. } else {
  505. /*
  506. * B.1.b ELSE
  507. * CONVERT to IBM floating point
  508. * ! IBM floating point is stored in 4 bytes as:
  509. * ! saaaaaaa bbbbbbbb bbbbbbbb bbbbbbbb
  510. * ! where s is sign bit, 0 -> positive, 1 -> negative
  511. * ! a is 7-bit characteristic
  512. * ! b is 24-bit fraction
  513. * ! s, a and b are obtained from local_float (local 32-bit float) as
  514. * ! s = sign(local_float)
  515. * ! a = ceil(log10(local_float) / log10(16.)) + 64
  516. * ! b = local_float / 16**(a-64) * 2**24
  517. * B.1.b ENDIF
  518. */
  519. a = ceil(log10(fabs(local_float)) / log10(16.)) + 64;
  520. /* Added by Todd Hutchinson, 8/13/99 */
  521. /* This fixes a problem when local_float == 256, etc. */
  522. if ( fmod((log10(fabs(local_float))/log10(16.)),1.) == 0) {
  523. a++;
  524. }
  525. /* Local_float == +/-1. is a special case because of log function */
  526. if ( (local_float == 1.) || (local_float == -1.)) a = 65;
  527. b = (long) (fabs(local_float) * pow(16.,(double) (70 - a)) +.5)
  528. & 0x00ffffff;
  529. ibm_float = (((local_float > 0.) ? 0 : 1) << 31) | (a << 24) | b;
  530. }
  531. /*
  532. *
  533. * B.2 RETURN the ibm float value
  534. */
  535. return ibm_float;
  536. /*
  537. *
  538. * END OF FUNCTION
  539. *
  540. */ }
  541. /*
  542. *
  543. **************************************************************
  544. * C. FUNCTION: grib_ibm_local
  545. * convert local_float from IBM floating point to
  546. * local floating point.
  547. *
  548. * INTERFACE:
  549. * float grib_ibm_local(ibm_float)
  550. *
  551. * ARGUMENTS (I=input, O=output, I&O=input and output):
  552. * (I) double local_float float value in local format
  553. *
  554. * RETURNS:
  555. * the actual local floating point
  556. **************************************************************
  557. */
  558. #if PROTOTYPE_NEEDED
  559. float grib_ibm_local( unsigned long ibm_float)
  560. #else
  561. float grib_ibm_local( ibm_float)
  562. unsigned long ibm_float;
  563. #endif
  564. {
  565. /*
  566. Convert ibm_float from IBM floating point stored in a 4-byte integer
  567. to local floating point.
  568. *
  569. * C.1 DETERMINE local floating point
  570. * ! IBM floating point is stored in 4 bytes as:
  571. * ! saaaaaaa bbbbbbbb bbbbbbbb bbbbbbbb
  572. * ! where s is sign bit, 0 -> positive, 1 -> negative
  573. * ! a is 7-bit characteristic
  574. * ! b is 24-bit fraction
  575. * ! local_float (local 32-bit float) is recovered from
  576. * ! s, a and b as
  577. * ! local_float = (-1)**s * 2**(-24) * b * 16**(a-64)
  578. */
  579. long a, b;
  580. float local_float;
  581. a = (ibm_float >> 24) & 0x0000007f;
  582. b = ibm_float & 0x00ffffff;
  583. local_float = (float) b * pow(16., (double) (a - 70));
  584. if (ibm_float >> 31) local_float = -local_float;
  585. /*
  586. *
  587. * C.2 RETURN floating point
  588. */
  589. return local_float;
  590. /*
  591. * END OF FUNCTION
  592. *
  593. */
  594. }